def minion_check(verbose_level, upgrade=False):
    utils.load_config(CONF, constants.MINION_CONF_PATH)
    utils.configure_logging(LOG, verbose_level, CONF['minion_log_file'])

    try:
        _checking_status('Hostname')
        utils.check_hostname()
        _checking_status('Sysctl')
        _check_sysctl()
        _checking_status('Network interfaces')
        _validate_interface_exists('minion_local_interface')
        _checking_status('Password file')
        _validate_passwords_file()
        # Heat templates validations
        if CONF.get('custom_env_files'):
            _checking_status('Custom env file')
            _validate_env_files_paths()
    except KeyError as e:
        LOG.error(_('Key error in configuration: {error}\n'
                    'Value is missing in configuration.').format(error=e))
        sys.exit(1)
    except FailedValidation as e:
        LOG.error(_('An error occurred during configuration '
                    'validation, please check your host '
                    'configuration and try again.\nError '
                    'message: {error}').format(error=e))
        sys.exit(1)
    except RuntimeError as e:
        LOG.error(_('An error occurred during configuration '
                    'validation, please check your host '
                    'configuration and try again. Error '
                    'message: {error}').format(error=e))
        sys.exit(1)
Пример #2
0
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.MINION_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['minion_log_file'])
        self.log.debug("take action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()
        cmd = minion_config.\
            prepare_minion_deploy(
                upgrade=True,
                yes=parsed_args.yes,
                no_validations=parsed_args.
                no_validations,
                verbose_level=self.app_args.verbose_level,
                force_stack_update=parsed_args.force_stack_update)
        self.log.warning("Running: %s" % ' '.join(cmd))
        if not parsed_args.dry_run:
            try:
                subprocess.check_call(cmd)
                self.log.warning(MINION_UPGRADE_COMPLETION_MESSAGE)
            except Exception as e:
                self.log.error(MINION_FAILURE_MESSAGE)
                self.log.error(e)
                raise exceptions.DeploymentError(e)
Пример #3
0
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take action(%s)" % parsed_args)

        if (not parsed_args.yes and not utils.prompt_user_for_confirmation(
                constants.UPGRADE_PROMPT, self.log)):
            raise exceptions.UndercloudUpgradeNotConfirmed(
                constants.UPGRADE_NO)

        utils.ensure_run_as_normal_user()

        if not parsed_args.skip_package_updates:
            if ('python3' in sys.executable):
                pyver = '3'
            else:
                pyver = '2'
            client_pkgs = [
                "python{}-tripleoclient".format(pyver),
            ]
            pkgs = client_pkgs + constants.UNDERCLOUD_EXTRA_PACKAGES
            self._update_extra_packages(pkgs, parsed_args.dry_run)
            self._invoke_self(parsed_args)
        else:
            self._run_upgrade(parsed_args)
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()

        self._update_extra_packages(constants.UNDERCLOUD_EXTRA_PACKAGES,
                                    parsed_args.dry_run)

        cmd = undercloud_config.\
            prepare_undercloud_deploy(
                upgrade=True,
                yes=parsed_args.yes,
                no_validations=parsed_args.
                no_validations,
                verbose_level=self.app_args.verbose_level,
                force_stack_update=parsed_args.force_stack_update)
        self.log.warning("Running: %s" % ' '.join(cmd))

        if not parsed_args.dry_run:
            try:
                subprocess.check_call(cmd)
                self.log.warning(
                    UNDERCLOUD_UPGRADE_COMPLETION_MESSAGE.format(
                        os.path.join(constants.UNDERCLOUD_OUTPUT_DIR,
                                     'undercloud-passwords.conf'),
                        '~/stackrc'))
            except Exception as e:
                self.log.error(UNDERCLOUD_FAILURE_MESSAGE)
                self.log.error(e)
                raise exceptions.DeploymentError(e)
Пример #5
0
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take_action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()
        no_validations = parsed_args.dry_run or parsed_args.no_validations
        inflight = not parsed_args.dry_run and parsed_args.inflight

        cmd = undercloud_config.prepare_undercloud_deploy(
            no_validations=no_validations,
            verbose_level=self.app_args.verbose_level,
            force_stack_update=parsed_args.force_stack_update,
            dry_run=parsed_args.dry_run,
            inflight=inflight)

        self.log.warning("Running: %s" % ' '.join(cmd))
        if not parsed_args.dry_run:
            try:
                subprocess.check_call(cmd)
                self.log.warning(
                    UNDERCLOUD_COMPLETION_MESSAGE.format(
                        '~/undercloud-passwords.conf', '~/stackrc'))
            except Exception as e:
                self.log.error(UNDERCLOUD_FAILURE_MESSAGE)
                self.log.error(e)
                raise exceptions.DeploymentError(e)
Пример #6
0
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take_action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()
        if parsed_args.use_heat:
            no_validations = parsed_args.dry_run or parsed_args.no_validations
            cmd = undercloud_config.\
                prepare_undercloud_deploy(
                    no_validations=no_validations,
                    verbose_level=self.app_args.verbose_level,
                    force_stack_update=parsed_args.force_stack_update,
                    dry_run=parsed_args.dry_run)
        else:
            self.log.warning(
                _('Non-containerized undercloud deployment is '
                  'deprecated in Rocky cycle.'))
            cmd = ["instack-install-undercloud"]

        self.log.warning("Running: %s" % ' '.join(cmd))
        if not parsed_args.dry_run:
            subprocess.check_call(cmd)
Пример #7
0
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()
        if parsed_args.use_heat:
            cmd = undercloud_config.\
                prepare_undercloud_deploy(
                    upgrade=True,
                    yes=parsed_args.yes,
                    no_validations=parsed_args.
                    no_validations,
                    verbose_level=self.app_args.verbose_level,
                    force_stack_update=parsed_args.force_stack_update)
            self.log.warning("Running: %s" % ' '.join(cmd))
            subprocess.check_call(cmd)
        else:
            self.log.warning(
                _('Non-containerized undercloud deployment is '
                  'deprecated in Rocky cycle.'))
            subprocess.check_call(
                ['sudo', 'yum', 'update', '-y', 'instack-undercloud'])
            subprocess.check_call("instack-pre-upgrade-undercloud")
            subprocess.check_call("instack-upgrade-undercloud")
            # restart nova-api
            # https://bugzilla.redhat.com/show_bug.cgi?id=1315467
            subprocess.check_call(
                ['sudo', 'systemctl', 'restart', 'openstack-nova-api'])
Пример #8
0
def check(verbose_level):
    # Fetch configuration and use its log file param to add logging to a file
    utils.load_config(CONF, constants.UNDERCLOUD_CONF_PATH)
    utils.configure_logging(LOG, verbose_level, CONF['undercloud_log_file'])

    # data = {opt.name: CONF[opt.name] for opt in _opts}
    try:
        # Other validations
        _check_hostname()
        _check_memory()
        _check_sysctl()
        _validate_passwords_file()
        # Heat templates validations
        if CONF.get('custom_env_files'):
            _validate_env_files_paths()
        # Networking validations
        _validate_value_formats()
        for subnet in CONF.subnets:
            s = CONF.get(subnet)
            _validate_in_cidr(s, subnet)
            _validate_dhcp_range(s)
            _validate_inspection_range(s)
            _validate_no_overlap(s)
        _validate_ips()
        _validate_interface_exists()
        _validate_no_ip_change()
    except KeyError as e:
        LOG.error(
            _('Key error in configuration: {error}\n'
              'Value is missing in configuration.').format(error=e))
        sys.exit(1)
    except FailedValidation as e:
        LOG.error(
            _('An error occurred during configuration '
              'validation, please check your host '
              'configuration and try again.\nError '
              'message: {error}').format(error=e))
        sys.exit(1)
    except RuntimeError as e:
        LOG.error(
            _('An error occurred during configuration '
              'validation, please check your host '
              'configuration and try again. Error '
              'message: {error}').format(error=e))
        sys.exit(1)
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()
        if parsed_args.use_heat is not None:
            self.log.warning('--use-heat is deprecated in Rocky')
        if parsed_args.use_heat is not None and \
                parsed_args.use_heat.lower() == "false":
            self.log.warning(
                _('Non-containerized undercloud deployment is '
                  'deprecated in Rocky cycle.'))
            subprocess.check_call(
                ['sudo', 'yum', 'update', '-y', 'instack-undercloud'])
            subprocess.check_call("instack-pre-upgrade-undercloud")
            subprocess.check_call("instack-upgrade-undercloud")
            # restart nova-api
            # https://bugzilla.redhat.com/show_bug.cgi?id=1315467
            subprocess.check_call(
                ['sudo', 'systemctl', 'restart', 'openstack-nova-api'])
        else:
            cmd = undercloud_config.\
                prepare_undercloud_deploy(
                    upgrade=True,
                    yes=parsed_args.yes,
                    no_validations=parsed_args.
                    no_validations,
                    verbose_level=self.app_args.verbose_level,
                    force_stack_update=parsed_args.force_stack_update)
            self.log.warning("Running: %s" % ' '.join(cmd))
            try:
                subprocess.check_call(cmd)
                self.log.warning(
                    UNDERCLOUD_UPGRADE_COMPLETION_MESSAGE.format(
                        '~/undercloud-passwords.conf', '~/stackrc'))
            except Exception as e:
                self.log.error(
                    UNDERCLOUD_FAILURE_MESSAGE.format(
                        self.heat_launch.install_tmp))
                self.log.error(e)
                raise exceptions.DeploymentError(e)
Пример #10
0
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take_action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()
        if parsed_args.use_heat is not None:
            self.log.warning('--use-heat is deprecated in Rocky')
        if parsed_args.use_heat is not None and \
                parsed_args.use_heat.lower() == "false":
            self.log.warning(
                _('Non-containerized undercloud deployment is '
                  'deprecated in Rocky cycle.'))
            cmd = ["instack-install-undercloud"]
        else:
            no_validations = parsed_args.dry_run or parsed_args.no_validations
            cmd = undercloud_config.\
                prepare_undercloud_deploy(
                    no_validations=no_validations,
                    verbose_level=self.app_args.verbose_level,
                    force_stack_update=parsed_args.force_stack_update,
                    dry_run=parsed_args.dry_run)

        self.log.warning("Running: %s" % ' '.join(cmd))
        if not parsed_args.dry_run:
            try:
                subprocess.check_call(cmd)
                self.log.warning(
                    UNDERCLOUD_COMPLETION_MESSAGE.format(
                        '~/undercloud-passwords.conf', '~/stackrc'))
            except Exception as e:
                self.log.error(
                    UNDERCLOUD_FAILURE_MESSAGE.format(
                        self.heat_launch.install_tmp))
                self.log.error(e)
                raise exceptions.DeploymentError(e)
Пример #11
0
    def take_action(self, parsed_args):
        # Fetch configuration used to add logging to a file
        utils.load_config(self.osloconfig, constants.UNDERCLOUD_CONF_PATH)
        utils.configure_logging(self.log, self.app_args.verbose_level,
                                self.osloconfig['undercloud_log_file'])
        self.log.debug("take action(%s)" % parsed_args)

        utils.ensure_run_as_normal_user()

        if not parsed_args.skip_package_updates:
            print("executable is {}".format(sys.executable))
            if ('python3' in sys.executable):
                pyver = '3'
            else:
                pyver = '2'
            client_pkgs = [
                "python{}-tripleoclient".format(pyver),
            ]
            pkgs = client_pkgs + constants.UNDERCLOUD_EXTRA_PACKAGES
            self._update_extra_packages(pkgs, parsed_args.dry_run)
            self._invoke_self(parsed_args)
        else:
            self._run_upgrade(parsed_args)
def prepare_undercloud_deploy(upgrade=False,
                              no_validations=True,
                              verbose_level=1,
                              yes=False,
                              force_stack_update=False,
                              dry_run=False,
                              inflight=False):
    """Prepare Undercloud deploy command based on undercloud.conf"""

    if CONF.get('undercloud_hostname'):
        utils.set_hostname(CONF.get('undercloud_hostname'))

    env_data = {}
    registry_overwrites = {}
    deploy_args = []
    # Fetch configuration and use its log file param to add logging to a file
    utils.load_config(CONF, constants.UNDERCLOUD_CONF_PATH)
    utils.configure_logging(LOG, verbose_level, CONF['undercloud_log_file'])
    _load_subnets_config_groups()

    # NOTE(bogdando): the generated env files are stored another path then
    # picked up later.
    # NOTE(aschultz): We copy this into the tht root that we save because
    # we move any user provided environment files into this root later.
    tempdir = os.path.join(os.path.abspath(CONF['output_dir']),
                           'tripleo-config-generated-env-files')
    utils.makedirs(tempdir)

    # Set the undercloud home dir parameter so that stackrc is produced in
    # the users home directory.
    env_data['UndercloudHomeDir'] = USER_HOME

    env_data['PythonInterpreter'] = sys.executable

    env_data['ContainerImagePrepareDebug'] = CONF['undercloud_debug']

    for param_key, param_value in PARAMETER_MAPPING.items():
        if param_key in CONF.keys():
            env_data[param_value] = CONF[param_key]

    # Some undercloud config options need to tweak multiple template parameters
    for undercloud_key in MULTI_PARAMETER_MAPPING:
        for env_value in MULTI_PARAMETER_MAPPING[undercloud_key]:
            if undercloud_key in CONF.keys():
                env_data[env_value] = CONF[undercloud_key]

    # Set up parameters for undercloud networking
    _process_network_args(env_data)

    # Setup parameter for Chrony ACL rules
    _process_chrony_acls(env_data)

    # Parse the undercloud.conf options to include necessary args and
    # yaml files for undercloud deploy command

    if CONF.get('undercloud_enable_selinux'):
        env_data['SELinuxMode'] = 'enforcing'
    else:
        env_data['SELinuxMode'] = 'permissive'

    if CONF.get('undercloud_enable_paunch'):
        env_data['EnablePaunch'] = True
    else:
        env_data['EnablePaunch'] = False

    if CONF.get('undercloud_ntp_servers', None):
        env_data['NtpServer'] = CONF['undercloud_ntp_servers']

    if CONF.get('undercloud_timezone', None):
        env_data['TimeZone'] = CONF['undercloud_timezone']
    else:
        env_data['TimeZone'] = utils.get_local_timezone()

    if CONF.get('enable_validations', False):
        env_data['UndercloudConfigFilePath'] = constants.UNDERCLOUD_CONF_PATH
        if not no_validations:
            env_data['EnableValidations'] = CONF['enable_validations']

    if CONF.get('overcloud_domain_name', None):
        env_data['NeutronDnsDomain'] = CONF['overcloud_domain_name']
        deploy_args.append('--local-domain=%s' % CONF['overcloud_domain_name'])

    local_registry_name = '.'.join([
        utils.get_short_hostname(), 'ctlplane', CONF['overcloud_domain_name']
    ])
    if CONF.get('container_cli', 'podman') == 'podman':
        env_data['DockerInsecureRegistryAddress'] = [local_registry_name]
        env_data['DockerInsecureRegistryAddress'].append(
            CONF['local_ip'].split('/')[0])
        env_data['DockerInsecureRegistryAddress'].append(
            CONF['undercloud_admin_host'])
    else:
        env_data['DockerInsecureRegistryAddress'] = [
            '%s:8787' % local_registry_name
        ]
        env_data['DockerInsecureRegistryAddress'].append(
            '%s:8787' % CONF['local_ip'].split('/')[0])
        env_data['DockerInsecureRegistryAddress'].append(
            '%s:8787' % CONF['undercloud_admin_host'])
    env_data['DockerInsecureRegistryAddress'].extend(
        CONF['container_insecure_registries'])

    env_data['ContainerCli'] = CONF['container_cli']

    # NOTE(aschultz): deprecated in Stein
    if CONF.get('docker_bip', None):
        env_data['DockerNetworkOptions'] = CONF['docker_bip']

    if CONF.get('container_registry_mirror', None):
        env_data['DockerRegistryMirror'] = CONF['container_registry_mirror']

    # This parameter the IP address used to bind the local container registry
    env_data['LocalContainerRegistry'] = local_registry_name

    if CONF['additional_architectures']:
        # In queens (instack-undercloud) we used this to setup additional
        # architectures.  For rocky+ we want to pass a list and be smarter in
        # THT.  We can remove this in 'T' when we get there.
        for arch in CONF['additional_architectures']:
            env_data['EnableArchitecture%s' % arch.upper()] = True
        env_data['AdditionalArchitectures'] = \
            ','.join(CONF['additional_architectures'])

    if CONF.get('local_ip', None):
        deploy_args.append('--local-ip=%s' % CONF['local_ip'])

    if CONF.get('templates', None):
        tht_templates = CONF['templates']
        deploy_args.append('--templates=%s' % tht_templates)
    else:
        tht_templates = THT_HOME
        deploy_args.append('--templates=%s' % THT_HOME)

    if CONF.get('roles_file', constants.UNDERCLOUD_ROLES_FILE):
        deploy_args.append('--roles-file=%s' % CONF['roles_file'])

    if CONF.get('networks_file'):
        deploy_args.append('--networks-file=%s' % CONF['networks_file'])
    else:
        deploy_args.append('--networks-file=%s' %
                           constants.UNDERCLOUD_NETWORKS_FILE)

    if yes:
        deploy_args += ['-y']

    if upgrade:
        deploy_args += [
            '--upgrade', '-e',
            os.path.join(
                tht_templates,
                "environments/lifecycle/undercloud-upgrade-prepare.yaml")
        ]

    if not CONF.get('heat_native', False):
        deploy_args.append('--heat-native=False')
    else:
        deploy_args.append('--heat-native')

    if CONF.get('heat_container_image'):
        deploy_args.append('--heat-container-image=%s' %
                           CONF['heat_container_image'])

    # These should be loaded first so we can override all the bits later
    deploy_args += [
        "-e",
        os.path.join(tht_templates, "environments/undercloud.yaml"), '-e',
        os.path.join(tht_templates, 'environments/use-dns-for-vips.yaml')
    ]

    # we want to load this environment after undercloud.yaml for precedence.
    if CONF.get('container_cli', 'podman') == 'podman':
        deploy_args += [
            '-e',
            os.path.join(tht_templates, 'environments/podman.yaml')
        ]

    # If a container images file is used, copy it into the tempdir to make it
    # later into other deployment artifacts and user-provided files.
    _container_images_config(CONF, deploy_args, env_data, tempdir)

    if env_data['MasqueradeNetworks']:
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/masquerade-networks.yaml")
        ]

    if CONF.get('enable_ironic'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/ironic.yaml")
        ]

        # ironic-inspector can only work if ironic is enabled
        if CONF.get('enable_ironic_inspector'):
            deploy_args += [
                '-e',
                os.path.join(tht_templates,
                             "environments/services/ironic-inspector.yaml")
            ]

        _process_drivers_and_hardware_types(CONF, env_data)
        _process_ipa_args(CONF, env_data)

    if not CONF.get('enable_nova', True):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         'environments/undercloud-disable-nova.yaml')
        ]

    if CONF.get('enable_mistral'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/mistral.yaml")
        ]

    if CONF.get('enable_novajoin'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/novajoin.yaml")
        ]
        env_data['NovajoinIpaOtp'] = CONF['ipa_otp']

    if CONF.get('enable_zaqar'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/zaqar-swift-backend.yaml")
        ]

    if CONF.get('enable_telemetry'):
        for env_file in TELEMETRY_DOCKER_ENV_YAML:
            deploy_args += ['-e', os.path.join(tht_templates, env_file)]
    else:
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/disable-telemetry.yaml")
        ]

    if CONF.get('enable_cinder'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/undercloud-cinder.yaml")
        ]

    if CONF.get('enable_tempest'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/tempest.yaml")
        ]

    if CONF.get('enable_swift_encryption'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/barbican.yaml"),
            '-e',
            os.path.join(tht_templates,
                         "environments/barbican-backend-simple-crypto.yaml")
        ]
        env_data['BarbicanSimpleCryptoGlobalDefault'] = True
        env_data['SwiftEncryptionEnabled'] = True

    if CONF.get('undercloud_service_certificate'):
        # We assume that the certificate is trusted
        env_data['InternalTLSCAFile'] = ''
        env_data.update(
            _get_public_tls_parameters(
                CONF.get('undercloud_service_certificate')))
    elif CONF.get('generate_service_certificate'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/public-tls-undercloud.yaml")
        ]
    else:
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/ssl/no-tls-endpoints-public-ip.yaml")
        ]

    if (CONF.get('generate_service_certificate')
            or CONF.get('undercloud_service_certificate')):
        endpoint_environment = _get_tls_endpoint_environment(
            CONF.get('undercloud_public_host'), tht_templates)

        public_host = utils.get_single_ip(CONF.get('undercloud_public_host'))
        public_ip = netaddr.IPAddress(public_host)
        deploy_args += ['--public-virtual-ip', public_host]

        # To make sure the resolved host is set to the right IP in /etc/hosts
        if not utils.is_valid_ip(CONF.get('undercloud_public_host')):
            extra_host = public_host + ' ' + CONF.get('undercloud_public_host')
            env_data['ExtraHostFileEntries'] = extra_host

        admin_host = utils.get_single_ip(CONF.get('undercloud_admin_host'))
        admin_ip = netaddr.IPAddress(admin_host)
        deploy_args += ['--control-virtual-ip', admin_host]

        local_net = netaddr.IPNetwork(CONF.get('local_ip'))
        if CONF.get('net_config_override', None):
            if (admin_ip not in local_net.cidr):
                LOG.warning('You may need to specify a custom '
                            'ControlVirtualInterface in a custom env file to '
                            'correctly assign the ip address to an interface '
                            'for undercloud_admin_host. By default it will be '
                            'set to br-ctlplane.')
            if (public_ip not in local_net.cidr):
                LOG.warning('You may need to specify a custom '
                            'PublicVirtualInterface in a custom env file to '
                            'correctly assign the ip address to an interface '
                            'for undercloud_public_host. By default it will be'
                            ' set to br-ctlplane.')
        else:
            if (admin_ip not in local_net.cidr
                    or public_ip not in local_net.cidr):
                LOG.warning('undercloud_admin_host or undercloud_public_host '
                            'is not in the same cidr as local_ip.')

        # Define the *VirtualInterfaces for keepalived. These are used when
        # configuring the undercloud_*_host addresses. If these adddesses are
        # not in the default cidr for the ctlplane, it will not be defined
        # and leads to general sadness during the deployment. Our default
        # net_config uses br-ctlplane. See rhbz#1737150
        env_data['ControlVirtualInterface'] = 'br-ctlplane'
        env_data['PublicVirtualInterface'] = 'br-ctlplane'

        deploy_args += [
            '-e', endpoint_environment, '-e',
            os.path.join(tht_templates,
                         'environments/services/undercloud-haproxy.yaml'),
            '-e',
            os.path.join(tht_templates,
                         'environments/services/undercloud-keepalived.yaml')
        ]

    u = CONF.get('deployment_user') or utils.get_deployment_user()
    env_data['DeploymentUser'] = u
    # TODO(cjeanner) drop that once using oslo.privsep
    deploy_args += ['--deployment-user', u]

    deploy_args += ['--output-dir=%s' % CONF['output_dir']]
    utils.makedirs(CONF['output_dir'])

    if CONF.get('cleanup'):
        deploy_args.append('--cleanup')

    if CONF.get('net_config_override', None):
        data_file = CONF['net_config_override']
        if os.path.abspath(data_file) != data_file:
            data_file = os.path.join(USER_HOME, data_file)

        if not os.path.exists(data_file):
            msg = _("Could not find net_config_override file '%s'") % data_file
            LOG.error(msg)
            raise RuntimeError(msg)

        # NOTE(bogdando): Process templated net config override data:
        # * get a list of used instack_env j2 tags (j2 vars, like {{foo}}),
        # * fetch values for the tags from the known mappins,
        # * raise, if there is unmatched tags left
        # * render the template into a JSON dict
        net_config_env, template_source = _get_jinja_env_source(data_file)
        unknown_tags = _get_unknown_instack_tags(net_config_env,
                                                 template_source)
        if unknown_tags:
            msg = (_('Can not render net_config_override file {0} contains '
                     'unknown instack_env j2 tags: {1}').format(
                         data_file, unknown_tags))
            LOG.error(msg)
            raise exceptions.DeploymentError(msg)

        # Create rendering context from the known to be present mappings for
        # identified instack_env tags to generated in env_data undercloud heat
        # params. Fall back to config opts, when env_data misses a param.
        context = {}
        for tag in INSTACK_NETCONF_MAPPING.keys():
            mapped_value = INSTACK_NETCONF_MAPPING[tag]
            if mapped_value in env_data.keys() or mapped_value in CONF.keys():
                try:
                    context[tag] = CONF[mapped_value]
                except cfg.NoSuchOptError:
                    context[tag] = env_data.get(mapped_value, None)

        # this returns a unicode string, convert it in into json
        net_config_str = net_config_env.get_template(
            os.path.split(data_file)[-1]).render(context).replace(
                "'", '"').replace('"', '"')
        try:
            net_config_json = json.loads(net_config_str)
        except ValueError:
            net_config_json = json.loads("{%s}" % net_config_str)

        if 'network_config' not in net_config_json:
            msg = ('Unsupported data format in net_config_override '
                   'file %s: %s' % (data_file, net_config_str))
            LOG.error(msg)
            raise exceptions.DeploymentError(msg)

        env_data['UndercloudNetConfigOverride'] = net_config_json

    params_file = os.path.join(tempdir, 'undercloud_parameters.yaml')
    utils.write_env_file(env_data, params_file, registry_overwrites)
    deploy_args += ['-e', params_file]

    if CONF.get('hieradata_override', None):
        data_file = CONF['hieradata_override']
        if os.path.abspath(data_file) != data_file:
            data_file = os.path.join(USER_HOME, data_file)

        if not os.path.exists(data_file):
            msg = _("Could not find hieradata_override file '%s'") % data_file
            LOG.error(msg)
            raise RuntimeError(msg)

        deploy_args += ['--hieradata-override=%s' % data_file]

    if CONF.get('enable_validations') and not no_validations:
        undercloud_preflight.check(verbose_level, upgrade)
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/tripleo-validations.yaml")
        ]

    if inflight:
        deploy_args.append('--inflight-validations')

    if CONF.get('custom_env_files'):
        for custom_file in CONF['custom_env_files']:
            deploy_args += ['-e', custom_file]

    if verbose_level > 1:
        deploy_args.append('--debug')

    deploy_args.append('--log-file=%s' % CONF['undercloud_log_file'])

    # Always add a drop-in for the ephemeral undercloud heat stack
    # virtual state tracking (the actual file will be created later)
    stack_vstate_dropin = os.path.join(tht_templates,
                                       'undercloud-stack-vstate-dropin.yaml')
    deploy_args += ["-e", stack_vstate_dropin]
    if force_stack_update:
        deploy_args += ["--force-stack-update"]

    cmd = [
        "sudo", "--preserve-env", "openstack", "tripleo", "deploy",
        "--standalone", "--standalone-role", "Undercloud", "--stack",
        "undercloud"
    ]
    cmd += deploy_args[:]

    # In dry-run, also report the expected heat stack virtual state/action
    if dry_run:
        stack_update_mark = os.path.join(
            constants.STANDALONE_EPHEMERAL_STACK_VSTATE,
            'update_mark_undercloud')
        if os.path.isfile(stack_update_mark) or force_stack_update:
            LOG.warning(
                _('The heat stack undercloud virtual state/action '
                  ' would be UPDATE'))

    return cmd
Пример #13
0
def check(verbose_level, upgrade=False):
    # Fetch configuration and use its log file param to add logging to a file
    utils.load_config(CONF, constants.UNDERCLOUD_CONF_PATH)
    utils.configure_logging(LOG, verbose_level, CONF['undercloud_log_file'])

    # data = {opt.name: CONF[opt.name] for opt in _opts}
    try:
        # Other validations
        _checking_status('Hostname')
        utils.check_hostname()
        _checking_status('Memory')
        _check_memory()
        _checking_status('Disk space')
        _check_diskspace(upgrade, verbose_level)
        _checking_status('Sysctl')
        _check_sysctl()
        _checking_status('Password file')
        _validate_passwords_file()
        _checking_status('Deprecated now invalid options')
        _validate_deprecetad_now_invalid_parameters()
        # Heat templates validations
        if CONF.get('custom_env_files'):
            _checking_status('Custom env file')
            _validate_env_files_paths()
        # Networking validations
        _checking_status('Networking values')
        _validate_value_formats()
        _check_routed_networks_enabled_if_multiple_subnets_defined()
        _check_all_or_no_subnets_use_dns_nameservers()
        for subnet in CONF.subnets:
            s = CONF.get(subnet)
            _checking_status('Subnet "%s" is in CIDR' % subnet)
            _validate_in_cidr(s, subnet)
            _checking_status('DHCP range is in subnet "%s"' % subnet)
            _validate_dhcp_range(s, subnet)
            _checking_status('Inspection range for subnet "%s"' % subnet)
            _validate_inspection_range(s)
            _validate_dnsnameservers(s)
        _checking_status('IP addresses')
        _validate_ips()
        _checking_status('Network interfaces')
        _validate_interface_exists()
        _checking_status('Provisionning IP change')
        _validate_no_ip_change()
        _checking_status('Architecture')
        _validate_architecure_options()
    except KeyError as e:
        LOG.error(
            _('Key error in configuration: {error}\n'
              'Value is missing in configuration.').format(error=e))
        sys.exit(1)
    except FailedValidation as e:
        LOG.error(
            _('An error occurred during configuration '
              'validation, please check your host '
              'configuration and try again.\nError '
              'message: {error}').format(error=e))
        sys.exit(1)
    except RuntimeError as e:
        LOG.error(
            _('An error occurred during configuration '
              'validation, please check your host '
              'configuration and try again. Error '
              'message: {error}').format(error=e))
        sys.exit(1)
def prepare_minion_deploy(upgrade=False,
                          no_validations=False,
                          verbose_level=1,
                          yes=False,
                          force_stack_update=False,
                          dry_run=False):
    """Prepare Minion deploy command based on minion.conf"""

    env_data = {}
    registry_overwrites = {}
    deploy_args = []
    # Fetch configuration and use its log file param to add logging to a file
    utils.load_config(CONF, constants.MINION_CONF_PATH)
    utils.configure_logging(LOG, verbose_level, CONF['minion_log_file'])

    # NOTE(bogdando): the generated env files are stored another path then
    # picked up later.
    # NOTE(aschultz): We copy this into the tht root that we save because
    # we move any user provided environment files into this root later.
    tempdir = os.path.join(os.path.abspath(CONF['output_dir']),
                           'tripleo-config-generated-env-files')
    if not os.path.isdir(tempdir):
        os.mkdir(tempdir)

    env_data['PythonInterpreter'] = sys.executable

    env_data['ContainerImagePrepareDebug'] = CONF['minion_debug']

    for param_key, param_value in PARAMETER_MAPPING.items():
        if param_key in CONF.keys():
            env_data[param_value] = CONF[param_key]

    # Parse the minion.conf options to include necessary args and
    # yaml files for minion deploy command

    if CONF.get('minion_enable_selinux'):
        env_data['SELinuxMode'] = 'enforcing'
    else:
        env_data['SELinuxMode'] = 'permissive'

    if CONF.get('minion_ntp_servers', None):
        env_data['NtpServer'] = CONF['minion_ntp_servers']

    if CONF.get('minion_timezone', None):
        env_data['TimeZone'] = CONF['minion_timezone']
    else:
        env_data['TimeZone'] = utils.get_local_timezone()

    # TODO(aschultz): fix this logic, look it up out of undercloud-outputs.yaml
    env_data['DockerInsecureRegistryAddress'] = [
        '%s:8787' % CONF['minion_local_ip'].split('/')[0]
    ]
    env_data['DockerInsecureRegistryAddress'].extend(
        CONF['container_insecure_registries'])

    env_data['ContainerCli'] = CONF['container_cli']

    if CONF.get('container_registry_mirror', None):
        env_data['DockerRegistryMirror'] = CONF['container_registry_mirror']

    # This parameter the IP address used to bind the local container registry
    env_data['LocalContainerRegistry'] = CONF['minion_local_ip'].split('/')[0]

    if CONF.get('minion_local_ip', None):
        deploy_args.append('--local-ip=%s' % CONF['minion_local_ip'])

    if CONF.get('templates', None):
        tht_templates = CONF['templates']
        deploy_args.append('--templates=%s' % tht_templates)
    else:
        tht_templates = THT_HOME
        deploy_args.append('--templates=%s' % THT_HOME)

    if CONF.get('roles_file', constants.MINION_ROLES_FILE):
        deploy_args.append('--roles-file=%s' % CONF['roles_file'])

    if CONF.get('networks_file'):
        deploy_args.append('--networks-file=%s' % CONF['networks_file'])
    else:
        deploy_args.append('--networks-file=%s' %
                           constants.UNDERCLOUD_NETWORKS_FILE)

    if yes:
        deploy_args += ['-y']

    # copy the undercloud output file into our working dir and include it
    output_file = _process_undercloud_output(
        tempdir, CONF['minion_undercloud_output_file'])
    deploy_args += ['-e', output_file]

    if upgrade:
        # TODO(aschultz): validate minion upgrade, should be the same as the
        # undercloud one.
        deploy_args += [
            '--upgrade', '-e',
            os.path.join(
                tht_templates,
                "environments/lifecycle/undercloud-upgrade-prepare.yaml")
        ]

    if not CONF.get('heat_native', False):
        deploy_args.append('--heat-native=False')
    else:
        deploy_args.append('--heat-native')

    if CONF.get('heat_container_image'):
        deploy_args.append('--heat-container-image=%s' %
                           CONF['heat_container_image'])

    # These should be loaded first so we can override all the bits later
    deploy_args += [
        "-e",
        os.path.join(tht_templates,
                     'environments/undercloud/undercloud-minion.yaml'), '-e',
        os.path.join(tht_templates, 'environments/use-dns-for-vips.yaml')
    ]

    # TODO(aschultz): remove when podman is actual default
    deploy_args += [
        '-e', os.path.join(tht_templates, 'environments/podman.yaml')
    ]

    # If a container images file is used, copy it into the tempdir to make it
    # later into other deployment artifacts and user-provided files.
    _container_images_config(CONF, deploy_args, env_data, tempdir)

    if CONF.get('enable_heat_engine'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/heat-engine.yaml")
        ]
    if CONF.get('enable_ironic_conductor'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/ironic-conductor.yaml")
        ]

    if CONF.get('minion_service_certificate'):
        # We assume that the certificate is trusted
        env_data['InternalTLSCAFile'] = ''
        env_data.update(
            _get_public_tls_parameters(CONF.get('minion_service_certificate')))

    u = CONF.get('deployment_user') or utils.get_deployment_user()
    env_data['DeploymentUser'] = u
    # TODO(cjeanner) drop that once using oslo.privsep
    deploy_args += ['--deployment-user', u]

    deploy_args += ['--output-dir=%s' % CONF['output_dir']]
    if not os.path.isdir(CONF['output_dir']):
        os.mkdir(CONF['output_dir'])

    # TODO(aschultz): move this to a central class
    if CONF.get('net_config_override', None):
        data_file = CONF['net_config_override']
        if os.path.abspath(data_file) != data_file:
            data_file = os.path.join(USER_HOME, data_file)

        if not os.path.exists(data_file):
            msg = _("Could not find net_config_override file '%s'") % data_file
            LOG.error(msg)
            raise RuntimeError(msg)

        # NOTE(bogdando): Process templated net config override data:
        # * get a list of used instack_env j2 tags (j2 vars, like {{foo}}),
        # * fetch values for the tags from the known mappins,
        # * raise, if there is unmatched tags left
        # * render the template into a JSON dict
        net_config_env, template_source = _get_jinja_env_source(data_file)

        # Create rendering context from the known to be present mappings for
        # identified instack_env tags to generated in env_data minion heat
        # params. Fall back to config opts, when env_data misses a param.
        context = {}
        for tag in INSTACK_NETCONF_MAPPING.keys():
            mapped_value = INSTACK_NETCONF_MAPPING[tag]
            if mapped_value in env_data.keys() or mapped_value in CONF.keys():
                try:
                    context[tag] = CONF[mapped_value]
                except cfg.NoSuchOptError:
                    context[tag] = env_data.get(mapped_value, None)

        # this returns a unicode string, convert it in into json
        net_config_str = net_config_env.get_template(
            os.path.split(data_file)[-1]).render(context).replace(
                "'", '"').replace('"', '"')
        try:
            net_config_json = json.loads(net_config_str)
        except ValueError:
            net_config_json = json.loads("{%s}" % net_config_str)

        if 'network_config' not in net_config_json:
            msg = ('Unsupported data format in net_config_override '
                   'file %s: %s' % (data_file, net_config_str))
            LOG.error(msg)
            raise exceptions.DeploymentError(msg)

        env_data['UndercloudNetConfigOverride'] = net_config_json

    params_file = os.path.join(tempdir, 'minion_parameters.yaml')
    utils.write_env_file(env_data, params_file, registry_overwrites)
    deploy_args += ['-e', params_file]

    if CONF.get('hieradata_override', None):
        data_file = CONF['hieradata_override']
        if os.path.abspath(data_file) != data_file:
            data_file = os.path.join(USER_HOME, data_file)

        if not os.path.exists(data_file):
            msg = _("Could not find hieradata_override file '%s'") % data_file
            LOG.error(msg)
            raise RuntimeError(msg)

        deploy_args += ['--hieradata-override=%s' % data_file]

    if CONF.get('minion_hostname'):
        utils.set_hostname(CONF.get('minion_hostname'))

    if CONF.get('minion_enable_validations') and not no_validations:
        utils.ansible_symlink()
        undercloud_preflight.minion_check(verbose_level, upgrade)

    if CONF.get('custom_env_files'):
        for custom_file in CONF['custom_env_files']:
            deploy_args += ['-e', custom_file]

    if verbose_level > 1:
        deploy_args.append('--debug')

    deploy_args.append('--log-file=%s' % CONF['minion_log_file'])

    # Always add a drop-in for the ephemeral minion heat stack
    # virtual state tracking (the actual file will be created later)
    stack_vstate_dropin = os.path.join(tht_templates,
                                       'minion-stack-vstate-dropin.yaml')
    deploy_args += ["-e", stack_vstate_dropin]
    if force_stack_update:
        deploy_args += ["--force-stack-update"]

    roles_file = os.path.join(tht_templates, constants.MINION_ROLES_FILE)
    cmd = [
        "sudo", "--preserve-env", "openstack", "tripleo", "deploy",
        "--standalone", "--standalone-role", "UndercloudMinion", "--stack",
        "minion", "-r", roles_file
    ]
    cmd += deploy_args[:]

    # In dry-run, also report the expected heat stack virtual state/action
    if dry_run:
        stack_update_mark = os.path.join(
            constants.STANDALONE_EPHEMERAL_STACK_VSTATE, 'update_mark_minion')
        if os.path.isfile(stack_update_mark) or force_stack_update:
            LOG.warning(
                _('The heat stack minion virtual state/action '
                  ' would be UPDATE'))

    return cmd
Пример #15
0
def prepare_undercloud_deploy(upgrade=False,
                              no_validations=False,
                              verbose_level=1,
                              yes=False,
                              force_stack_update=False,
                              dry_run=False):
    """Prepare Undercloud deploy command based on undercloud.conf"""

    env_data = {}
    registry_overwrites = {}
    deploy_args = []
    # Fetch configuration and use its log file param to add logging to a file
    utils.load_config(CONF, constants.UNDERCLOUD_CONF_PATH)
    utils.configure_logging(LOG, verbose_level, CONF['undercloud_log_file'])
    _load_subnets_config_groups()

    # NOTE(bogdando): the generated env files are stored another path then
    # picked up later.
    # NOTE(aschultz): We copy this into the tht root that we save because
    # we move any user provided environment files into this root later.
    tempdir = os.path.join(os.path.abspath(CONF['output_dir']),
                           'tripleo-config-generated-env-files')
    if not os.path.isdir(tempdir):
        os.mkdir(tempdir)

    # Set the undercloud home dir parameter so that stackrc is produced in
    # the users home directory.
    env_data['UndercloudHomeDir'] = USER_HOME

    for param_key, param_value in PARAMETER_MAPPING.items():
        if param_key in CONF.keys():
            env_data[param_value] = CONF[param_key]

    # Set up parameters for undercloud networking
    env_data['IronicInspectorSubnets'] = _generate_inspection_subnets()
    env_data['ControlPlaneStaticRoutes'] = _generate_subnets_static_routes()
    env_data['UndercloudCtlplaneSubnets'] = {}
    for subnet in CONF.subnets:
        s = CONF.get(subnet)
        env_data['UndercloudCtlplaneSubnets'][subnet] = {}
        for param_key, param_value in SUBNET_PARAMETER_MAPPING.items():
            env_data['UndercloudCtlplaneSubnets'][subnet].update(
                {param_value: s[param_key]})
    env_data['MasqueradeNetworks'] = _generate_masquerade_networks()
    env_data['DnsServers'] = ','.join(CONF['undercloud_nameservers'])

    # Parse the undercloud.conf options to include necessary args and
    # yaml files for undercloud deploy command

    if CONF.get('undercloud_enable_selinux'):
        env_data['SELinuxMode'] = 'enforcing'
    else:
        env_data['SELinuxMode'] = 'permissive'

    if CONF.get('undercloud_ntp_servers', None):
        env_data['NtpServer'] = CONF['undercloud_ntp_servers'][0]

    if CONF.get('enable_validations', False) and not no_validations:
        env_data['EnableValidations'] = CONF['enable_validations']

    if CONF.get('overcloud_domain_name', None):
        env_data['NeutronDnsDomain'] = CONF['overcloud_domain_name']
        deploy_args.append('--local-domain=%s' % CONF['overcloud_domain_name'])

    env_data['DockerInsecureRegistryAddress'] = [
        '%s:8787' % CONF['local_ip'].split('/')[0]
    ]
    env_data['DockerInsecureRegistryAddress'].append(
        '%s:8787' % CONF['undercloud_admin_host'])
    env_data['DockerInsecureRegistryAddress'].extend(
        CONF['docker_insecure_registries'])

    if CONF.get('docker_registry_mirror', None):
        env_data['DockerRegistryMirror'] = CONF['docker_registry_mirror']

    # This parameter the IP address used to bind the local container registry
    env_data['LocalContainerRegistry'] = CONF['local_ip'].split('/')[0]

    if CONF.get('local_ip', None):
        deploy_args.append('--local-ip=%s' % CONF['local_ip'])

    if CONF.get('templates', None):
        tht_templates = CONF['templates']
        deploy_args.append('--templates=%s' % tht_templates)
    else:
        tht_templates = THT_HOME
        deploy_args.append('--templates=%s' % THT_HOME)

    if CONF.get('roles_file', constants.UNDERCLOUD_ROLES_FILE):
        deploy_args.append('--roles-file=%s' % CONF['roles_file'])

    if yes:
        deploy_args += ['-y']

    if upgrade:
        deploy_args += [
            '--upgrade', '-e',
            os.path.join(
                tht_templates,
                "environments/lifecycle/undercloud-upgrade-prepare.yaml")
        ]

    if CONF.get('heat_native', None):
        deploy_args.append('--heat-native')

    if CONF.get('heat_container_image'):
        deploy_args.append('--heat-container-image=%s' %
                           CONF['heat_container_image'])

    # These should be loaded first so we can override all the bits later
    deploy_args += [
        "-e",
        os.path.join(tht_templates, "environments/docker.yaml"), "-e",
        os.path.join(tht_templates, "environments/undercloud.yaml")
    ]

    # If a container images file is used, copy it into the tempdir to make it
    # later into other deployment artifacts and user-provided files.
    _container_images_config(CONF, deploy_args, env_data, tempdir)

    if env_data['MasqueradeNetworks']:
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/masquerade-networks.yaml")
        ]

    if CONF.get('enable_ironic'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/ironic.yaml")
        ]

        # ironic-inspector can only work if ironic is enabled
        if CONF.get('enable_ironic_inspector'):
            deploy_args += [
                '-e',
                os.path.join(tht_templates,
                             "environments/services/ironic-inspector.yaml")
            ]

        _process_drivers_and_hardware_types(CONF, env_data)
        _process_ipa_args(CONF, env_data)

    if CONF.get('enable_mistral'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/mistral.yaml")
        ]

    if CONF.get('enable_novajoin'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/novajoin.yaml")
        ]
        env_data['NovajoinIpaOtp'] = CONF['ipa_otp']

    if CONF.get('enable_zaqar'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/zaqar.yaml")
        ]

    if CONF.get('enable_telemetry'):
        for env_file in TELEMETRY_DOCKER_ENV_YAML:
            deploy_args += ['-e', os.path.join(tht_templates, env_file)]

    if CONF.get('enable_ui'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/tripleo-ui.yaml")
        ]

    if CONF.get('enable_cinder'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/services/undercloud-cinder.yaml")
        ]

    if CONF.get('enable_tempest'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/tempest.yaml")
        ]

    if CONF.get('enable_swift_encryption'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates, "environments/services/barbican.yaml"),
            '-e',
            os.path.join(tht_templates,
                         "environments/barbican-backend-simple-crypto.yaml")
        ]
        env_data['BarbicanSimpleCryptoGlobalDefault'] = True
        env_data['SwiftEncryptionEnabled'] = True

    if CONF.get('generate_service_certificate'):
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/public-tls-undercloud.yaml")
        ]
    elif CONF.get('undercloud_service_certificate'):
        enable_tls_yaml_path = os.path.join(
            tht_templates, "environments/ssl/enable-tls.yaml")
        env_data.update(
            _get_public_tls_parameters(
                CONF.get('undercloud_service_certificate')))
        registry_overwrites.update(
            _get_public_tls_resource_registry_overwrites(enable_tls_yaml_path))
        deploy_args += [
            '-e',
            os.path.join(tht_templates, 'environments/services/'
                         'undercloud-haproxy.yaml'), '-e',
            os.path.join(tht_templates, 'environments/services/'
                         'undercloud-keepalived.yaml')
        ]
    else:
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/no-tls-endpoints-public-ip.yaml")
        ]

    if (CONF.get('generate_service_certificate')
            or CONF.get('undercloud_service_certificate')):
        endpoint_environment = _get_tls_endpoint_environment(
            CONF.get('undercloud_public_host'), tht_templates)
        try:
            public_host = CONF.get('undercloud_public_host')
            netaddr.IPAddress(public_host)
            deploy_args += ['--public-virtual-ip', public_host]

            admin_host = CONF.get('undercloud_admin_host')
            netaddr.IPAddress(admin_host)
            deploy_args += ['--control-virtual-ip', admin_host]
        except netaddr.core.AddrFormatError:
            # TODO(jaosorior): We could do a reverse lookup for the hostnames
            # if the *_host variables are DNS names and not IPs.
            pass

        deploy_args += [
            '-e', endpoint_environment, '-e',
            os.path.join(tht_templates,
                         'environments/use-dns-for-vips.yaml'), '-e',
            os.path.join(tht_templates,
                         'environments/services/undercloud-haproxy.yaml'),
            '-e',
            os.path.join(tht_templates,
                         'environments/services/undercloud-keepalived.yaml')
        ]

    u = CONF.get('deployment_user') or utils.get_deployment_user()
    env_data['DeploymentUser'] = u

    deploy_args += ['--output-dir=%s' % CONF['output_dir']]
    if not os.path.isdir(CONF['output_dir']):
        os.mkdir(CONF['output_dir'])

    if CONF.get('cleanup'):
        deploy_args.append('--cleanup')

    if CONF.get('net_config_override', None):
        data_file = CONF['net_config_override']
        if os.path.abspath(data_file) != data_file:
            data_file = os.path.join(USER_HOME, data_file)

        if not os.path.exists(data_file):
            msg = _("Could not find net_config_override file '%s'") % data_file
            LOG.error(msg)
            raise RuntimeError(msg)

        # NOTE(bogdando): Process templated net config override data:
        # * get a list of used instack_env j2 tags (j2 vars, like {{foo}}),
        # * fetch values for the tags from the known mappins,
        # * raise, if there is unmatched tags left
        # * render the template into a JSON dict
        net_config_env, template_source = _get_jinja_env_source(data_file)
        unknown_tags = _get_unknown_instack_tags(net_config_env,
                                                 template_source)
        if unknown_tags:
            msg = (_('Can not render net_config_override file {0} contains '
                     'unknown instack_env j2 tags: {1}').format(
                         data_file, unknown_tags))
            LOG.error(msg)
            raise exceptions.DeploymentError(msg)

        # Create rendering context from the known to be present mappings for
        # identified instack_env tags to generated in env_data undercloud heat
        # params. Fall back to config opts, when env_data misses a param.
        context = {}
        for tag in INSTACK_NETCONF_MAPPING.keys():
            mapped_value = INSTACK_NETCONF_MAPPING[tag]
            if mapped_value in env_data.keys() or mapped_value in CONF.keys():
                try:
                    context[tag] = CONF[mapped_value]
                except cfg.NoSuchOptError:
                    context[tag] = env_data.get(mapped_value, None)

        # this returns a unicode string, convert it in into json
        net_config_str = net_config_env.get_template(
            os.path.split(data_file)[-1]).render(context).replace(
                "'", '"').replace('"', '"')
        try:
            net_config_json = json.loads(net_config_str)
        except ValueError:
            net_config_json = json.loads("{%s}" % net_config_str)

        if 'network_config' not in net_config_json:
            msg = ('Unsupported data format in net_config_override '
                   'file %s: %s' % (data_file, net_config_str))
            LOG.error(msg)
            raise exceptions.DeploymentError(msg)

        env_data['UndercloudNetConfigOverride'] = net_config_json

    params_file = os.path.join(tempdir, 'undercloud_parameters.yaml')
    utils.write_env_file(env_data, params_file, registry_overwrites)
    deploy_args += ['-e', params_file]

    if CONF.get('hieradata_override', None):
        data_file = CONF['hieradata_override']
        if os.path.abspath(data_file) != data_file:
            data_file = os.path.join(USER_HOME, data_file)

        if not os.path.exists(data_file):
            msg = _("Could not find hieradata_override file '%s'") % data_file
            LOG.error(msg)
            raise RuntimeError(msg)

        deploy_args += ['--hieradata-override=%s' % data_file]

    if CONF.get('enable_validations') and not no_validations:
        undercloud_preflight.check(verbose_level)
        deploy_args += [
            '-e',
            os.path.join(tht_templates,
                         "environments/tripleo-validations.yaml")
        ]

    if CONF.get('custom_env_files'):
        for custom_file in CONF['custom_env_files']:
            deploy_args += ['-e', custom_file]

    if verbose_level > 1:
        deploy_args.append('--debug')

    deploy_args.append('--log-file=%s' % CONF['undercloud_log_file'])

    # Always add a drop-in for the ephemeral undercloud heat stack
    # virtual state tracking (the actual file will be created later)
    stack_vstate_dropin = os.path.join(
        CONF.get('templates') or constants.TRIPLEO_HEAT_TEMPLATES,
        'undercloud-stack-vstate-dropin.yaml')
    deploy_args += ["-e", stack_vstate_dropin]
    if force_stack_update:
        deploy_args += ["--force-stack-update"]

    cmd = [
        "sudo", "openstack", "tripleo", "deploy", "--standalone",
        "--standalone-role", "Undercloud", "--stack", "undercloud"
    ]
    cmd += deploy_args[:]

    # In dry-run, also report the expected heat stack virtual state/action
    if dry_run:
        stack_update_mark = os.path.join(
            constants.STANDALONE_EPHEMERAL_STACK_VSTATE,
            'update_mark_undercloud')
        if os.path.isfile(stack_update_mark) or force_stack_update:
            LOG.warning(
                _('The heat stack undercloud virtual state/action '
                  ' would be UPDATE'))

    return cmd