diff --git a/controllerconfig/controllerconfig/controllerconfig/configassistant.py b/controllerconfig/controllerconfig/controllerconfig/configassistant.py index 1a224ba90c..e9b9762af1 100644 --- a/controllerconfig/controllerconfig/controllerconfig/configassistant.py +++ b/controllerconfig/controllerconfig/controllerconfig/configassistant.py @@ -461,6 +461,11 @@ class ConfigAssistant(): self.cluster_pod_subnet = IPNetwork("172.16.0.0/16") self.cluster_service_subnet = IPNetwork("10.96.0.0/12") + # Docker Proxy config + self.docker_http_proxy = "" + self.docker_https_proxy = "" + self.docker_no_proxy = "" + # SDN config self.enable_sdn = False # HTTPS @@ -2666,6 +2671,86 @@ class ConfigAssistant(): """ Cluster host interface configuration complete""" self.cluster_host_interface_configured = True + def input_docker_proxy_config(self): + """Allow user to input docker proxy config.""" + + print("\nDocker Proxy:") + print("-------------------------\n") + print(textwrap.fill( + "Docker proxy is needed if host network is behind a proxy.", 80)) + print('') + while True: + user_input = input( + "Configure docker proxy [y/N]: ") + if user_input.lower() == 'q': + raise UserQuit + elif user_input.lower() == 'y': + while True: + user_input = input( + "HTTP proxy (http://example.proxy:port): ") + if user_input.lower() == 'q': + raise UserQuit + self.docker_http_proxy = user_input + break + + while True: + user_input = input( + "HTTPS proxy (https://example.proxy:port): ") + if user_input.lower() == 'q': + raise UserQuit + self.docker_https_proxy = user_input + break + + if not self.docker_http_proxy and not self.docker_https_proxy: + print("At least one proxy required") + continue + + while True: + # TODO: Current Docker version 18.03.1-ce utilizes go-lang + # net library for proxy setting. The go-lang net lib + # doesn't support CIDR notation until this commit: + # + # https://github.com/golang/net/commit/ + # c21de06aaf072cea07f3a65d6970e5c7d8b6cd6d + # + # After docker upgrades to a version that CIDR notation + # supported pre_set_no_proxy will be simplified to subnets + if self.system_mode == \ + sysinv_constants.SYSTEM_MODE_SIMPLEX: + pre_set_no_proxy = "localhost,127.0.0.1," + \ + str(self.controller_floating_address) + "," + \ + str(self.controller_address_0) + "," + \ + str(self.controller_address_1) + "," + \ + str(self.external_oam_address_0) + else: + pre_set_no_proxy = "localhost,127.0.0.1," + \ + str(self.controller_floating_address) + "," + \ + str(self.controller_address_0) + "," + \ + str(self.controller_address_1) + "," + \ + str(self.external_oam_floating_address) + "," + \ + str(self.external_oam_address_0) + "," + \ + str(self.external_oam_address_1) + + user_input = input( + "Additional NO proxy besides '" + + pre_set_no_proxy + + "'\n(Comma-separated addresses, " + + "wildcard/subnet not allowed)\n:") + if user_input.lower() == 'q': + raise UserQuit + if user_input == "": + self.docker_no_proxy = pre_set_no_proxy + else: + self.docker_no_proxy = pre_set_no_proxy + \ + "," + user_input + break + break + elif user_input.lower() in ('n', ''): + break + else: + print("Invalid choice") + continue + def input_authentication_config(self): """Allow user to input authentication config and perform validation. """ @@ -2747,6 +2832,9 @@ class ConfigAssistant(): if self.kubernetes: self.input_cluster_host_config() self.input_external_oam_config() + if self.kubernetes: + # Docker proxy is only used in kubernetes config + self.input_docker_proxy_config() self.input_authentication_config() def is_valid_management_multicast_subnet(self, ip_subnet): @@ -3343,6 +3431,18 @@ class ConfigAssistant(): raise ConfigFail("The option TIME_TO_LIVE is " "no longer supported") + # Kubernetes Configuration + if self.kubernetes: + if config.has_option('cDOCKER_PROXY', 'DOCKER_HTTP_PROXY'): + self.docker_http_proxy = config.get( + 'cDOCKER_PROXY', 'DOCKER_HTTP_PROXY') + if config.has_option('cDOCKER_PROXY', 'DOCKER_HTTPS_PROXY'): + self.docker_https_proxy = config.get( + 'cDOCKER_PROXY', 'DOCKER_HTTPS_PROXY') + if config.has_option('cDOCKER_PROXY', 'DOCKER_NO_PROXY'): + self.docker_no_proxy = config.get( + 'cDOCKER_PROXY', 'DOCKER_NO_PROXY') + except Exception: print("Error parsing answer file") raise @@ -3569,6 +3669,17 @@ class ConfigAssistant(): print("System controller floating ip: " + str(self.system_controller_floating_ip)) + if self.kubernetes: + if self.docker_http_proxy or self.docker_https_proxy: + print("\nKubernetes Configuraton") + print("----------------------") + if self.docker_http_proxy: + print("Docker HTTP proxy: " + self.docker_http_proxy) + if self.docker_https_proxy: + print("Docker HTTPS proxy: " + self.docker_https_proxy) + if self.docker_no_proxy: + print("Docker NO proxy: " + self.docker_no_proxy) + def write_config_file(self): """Write configuration to a text file for later reference.""" try: @@ -3964,6 +4075,20 @@ class ConfigAssistant(): f.write("SYSTEM_CONTROLLER_FLOATING_ADDRESS=%s\n" % str(self.system_controller_floating_ip)) + # Docker proxy configuration + if self.kubernetes: + f.write("\n[cDOCKER_PROXY]") + f.write("\n# Docker Proxy Configuration\n") + f.write( + "DOCKER_HTTP_PROXY=" + + str(self.docker_http_proxy) + "\n") + f.write( + "DOCKER_HTTPS_PROXY=" + + str(self.docker_https_proxy) + "\n") + f.write( + "DOCKER_NO_PROXY=" + + str(self.docker_no_proxy) + "\n") + except IOError: LOG.error("Failed to open file: %s", constants.CGCS_CONFIG_FILE) raise ConfigFail("Failed to write configuration file") @@ -5188,6 +5313,20 @@ class ConfigAssistant(): "required_patches": "N/A"} client.sysinv.load.create(**patch) + def _populate_docker_config(self, client): + parameter = { + 'http_proxy': self.docker_http_proxy, + 'https_proxy': self.docker_https_proxy, + 'no_proxy': self.docker_no_proxy, + } + client.sysinv.service_parameter.create( + sysinv_constants.SERVICE_TYPE_DOCKER, + sysinv_constants.SERVICE_PARAM_SECTION_DOCKER_PROXY, + None, + None, + parameter + ) + def populate_initial_config(self): """Populate initial system inventory configuration""" try: @@ -5199,6 +5338,9 @@ class ConfigAssistant(): # ceph_mon config requires controller host to be created self._inventory_config_complete_wait(client, controller) self._populate_interface_config(client, controller) + if self.kubernetes: + # Docker proxy is only used in kubernetes config + self._populate_docker_config(client) except (KeystoneFail, SysInvFail) as e: LOG.exception(e) diff --git a/puppet-manifests/src/modules/platform/manifests/docker.pp b/puppet-manifests/src/modules/platform/manifests/docker.pp index ababce3d56..cfc1e6fc80 100644 --- a/puppet-manifests/src/modules/platform/manifests/docker.pp +++ b/puppet-manifests/src/modules/platform/manifests/docker.pp @@ -1,5 +1,8 @@ class platform::docker::params ( $package_name = 'docker-ce', + $http_proxy = undef, + $https_proxy = undef, + $no_proxy = undef, ) { } class platform::docker::config @@ -9,6 +12,22 @@ class platform::docker::config if $::platform::kubernetes::params::enabled { + if $http_proxy or $https_proxy { + file { '/etc/systemd/system/docker.service.d': + ensure => 'directory', + owner => 'root', + group => 'root', + mode => '0755', + } + -> file { '/etc/systemd/system/docker.service.d/http-proxy.conf': + ensure => present, + owner => 'root', + group => 'root', + mode => '0644', + content => template('platform/dockerproxy.conf.erb'), + } + } + Class['::platform::filesystem::docker'] ~> Class[$name] service { 'docker': diff --git a/puppet-manifests/src/modules/platform/templates/dockerproxy.conf.erb b/puppet-manifests/src/modules/platform/templates/dockerproxy.conf.erb new file mode 100644 index 0000000000..629f68b556 --- /dev/null +++ b/puppet-manifests/src/modules/platform/templates/dockerproxy.conf.erb @@ -0,0 +1,8 @@ +[Service] +<%- if @http_proxy -%> + Environment="HTTP_PROXY=<%= @http_proxy %>" +<%- end -%> +<%- if @https_proxy -%> + Environment="HTTPS_PROXY=<%= @https_proxy %>" +<%- end -%> +Environment="NO_PROXY=<%= @no_proxy %>" diff --git a/sysinv/sysinv/sysinv/sysinv/common/constants.py b/sysinv/sysinv/sysinv/sysinv/common/constants.py index 87e072f82f..00d740c5c9 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/constants.py +++ b/sysinv/sysinv/sysinv/sysinv/common/constants.py @@ -874,6 +874,7 @@ SERVICE_TYPE_PANKO = 'panko' SERVICE_TYPE_AODH = 'aodh' SERVICE_TYPE_GLANCE = 'glance' SERVICE_TYPE_BARBICAN = 'barbican' +SERVICE_TYPE_DOCKER = 'docker' SERVICE_PARAM_SECTION_MURANO_RABBITMQ = 'rabbitmq' SERVICE_PARAM_SECTION_MURANO_ENGINE = 'engine' @@ -1064,6 +1065,13 @@ SERVICE_PARAM_AODH_DATABASE_ALARM_HISTORY_TIME_TO_LIVE_DEFAULT = PM_TTL_DEFAULT SERVICE_PARAM_SECTION_SWIFT_CONFIG = 'config' SERVICE_PARAM_NAME_SWIFT_SERVICE_ENABLED = 'service_enabled' SERVICE_PARAM_NAME_SWIFT_FS_SIZE_MB = 'fs_size_mb' + +# docker parameters +SERVICE_PARAM_SECTION_DOCKER_PROXY = 'proxy' +SERVICE_PARAM_NAME_DOCKER_HTTP_PROXY = 'http_proxy' +SERVICE_PARAM_NAME_DOCKER_HTTPS_PROXY = 'https_proxy' +SERVICE_PARAM_NAME_DOCKER_NO_PROXY = 'no_proxy' + # default filesystem size to 25 MB SERVICE_PARAM_SWIFT_FS_SIZE_MB_DEFAULT = 25 diff --git a/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py b/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py index ff440ce666..52d9e650e1 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py +++ b/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py @@ -1476,6 +1476,21 @@ SWIFT_CONFIG_PARAMETER_DATA_FORMAT = { constants.SERVICE_PARAM_NAME_SWIFT_SERVICE_ENABLED: SERVICE_PARAMETER_DATA_FORMAT_BOOLEAN, } +DOCKER_PROXY_PARAMETER_OPTIONAL = [ + constants.SERVICE_PARAM_NAME_DOCKER_HTTP_PROXY, + constants.SERVICE_PARAM_NAME_DOCKER_HTTPS_PROXY, + constants.SERVICE_PARAM_NAME_DOCKER_NO_PROXY, +] + +DOCKER_PROXY_PARAMETER_RESOURCE = { + constants.SERVICE_PARAM_NAME_DOCKER_HTTP_PROXY: + 'platform::docker::params::http_proxy', + constants.SERVICE_PARAM_NAME_DOCKER_HTTPS_PROXY: + 'platform::docker::params::https_proxy', + constants.SERVICE_PARAM_NAME_DOCKER_NO_PROXY: + 'platform::docker::params::no_proxy', +} + # Service Parameter Schema SERVICE_PARAM_MANDATORY = 'mandatory' SERVICE_PARAM_OPTIONAL = 'optional' @@ -1652,6 +1667,12 @@ SERVICE_PARAMETER_SCHEMA = { SERVICE_PARAM_DATA_FORMAT: SWIFT_CONFIG_PARAMETER_DATA_FORMAT, }, }, + constants.SERVICE_TYPE_DOCKER: { + constants.SERVICE_PARAM_SECTION_DOCKER_PROXY: { + SERVICE_PARAM_OPTIONAL: DOCKER_PROXY_PARAMETER_OPTIONAL, + SERVICE_PARAM_RESOURCE: DOCKER_PROXY_PARAMETER_RESOURCE, + }, + }, } SERVICE_PARAMETER_MAX_LENGTH = 255