Esempio n. 1
0
    def run(self, context):
        # get the stack. Error if doesn't exist
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heatexceptions.HTTPNotFound:
            msg = "Error retrieving stack: %s" % self.container
            LOG.exception(msg)
            return actions.Result(error=msg)

        swift = self.get_object_client(context)

        # Get output and check if DeployStep are None
        removals = ['OS::TripleO::DeploymentSteps']
        for output in stack.to_dict().get('outputs', {}):
            if output['output_key'] == 'RoleData':
                for role in output['output_value']:
                    removals.append("OS::TripleO::Tasks::%sPreConfig" % role)
                    removals.append("OS::TripleO::Tasks::%sPostConfig" % role)

        plan_env = plan_utils.get_env(swift, self.container)
        self.remove_noops_from_env(removals, plan_env)
        plan_utils.put_env(swift, plan_env)

        user_env = plan_utils.get_user_env(swift, self.container)
        self.remove_noops_from_env(removals, user_env)
        plan_utils.put_user_env(swift, self.container, user_env)
Esempio n. 2
0
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        parameter_defaults = env.get('parameter_defaults', {})
        passwords = self._get_overriden_passwords(env.get('passwords', {}),
                                                  parameter_defaults)

        next_index = self.get_next_index(passwords['KeystoneFernetKeys'])
        keys_map = self.rotate_keys(passwords['KeystoneFernetKeys'],
                                    next_index)
        max_keys = self.get_max_keys_value(parameter_defaults)
        keys_map = self.purge_excess_keys(max_keys, keys_map)

        env['passwords']['KeystoneFernetKeys'] = keys_map

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.cache_delete(context, self.container, "tripleo.parameters.get")

        return keys_map
Esempio n. 3
0
    def test_update_in_env(self):
        env = plan_utils.get_env(self.swift, self.container)

        updated_env = plan_utils.update_in_env(self.swift, env, 'template',
                                               'updated-overcloud.yaml')
        self.assertEqual(updated_env['template'], 'updated-overcloud.yaml')

        updated_env = plan_utils.update_in_env(
            self.swift, env, 'parameter_defaults',
            {'another-key': 'another-value'})
        self.assertEqual(
            updated_env['parameter_defaults'], {
                'BlockStorageCount': 42,
                'OvercloudControlFlavor': 'yummy',
                'another-key': 'another-value'
            })

        updated_env = plan_utils.update_in_env(self.swift,
                                               env,
                                               'parameter_defaults',
                                               delete_key=True)
        self.assertNotIn('parameter_defaults', updated_env)

        self.swift.get_object.assert_called()
        self.swift.put_object.assert_called()
Esempio n. 4
0
    def run(self, context):
        swift = self.get_object_client(context)
        mistral = self.get_workflow_client(context)
        from_mistral = False

        try:
            env = plan_utils.get_env(swift, self.plan)
        except swiftexceptions.ClientException:
            # The plan has not been migrated yet. Check if there is a
            # Mistral environment.
            try:
                env = mistral.environments.get(self.plan).variables
                from_mistral = True
            except (mistralclient_base.APIException,
                    keystoneauth_exc.http.NotFound):
                # No Mistral env and no template: likely deploying old
                # templates aka previous version of OpenStack.
                env = {'version': 1.0,
                       'name': self.plan,
                       'description': '',
                       'template': 'overcloud.yaml',
                       'environments': [
                           {'path': 'overcloud-resource-registry-puppet.yaml'}
                       ]}

            # Store the environment info into Swift
            plan_utils.put_env(swift, env)
            if from_mistral:
                mistral.environments.delete(self.plan)
Esempio n. 5
0
    def run(self, context):
        # get the stack. Error if doesn't exist
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heatexceptions.HTTPNotFound:
            msg = "Error retrieving stack: %s" % self.container
            LOG.exception(msg)
            return actions.Result(error=msg)

        swift = self.get_object_client(context)

        # Get output and check if DeployStep are None
        removals = ['OS::TripleO::DeploymentSteps']
        for output in stack.to_dict().get('outputs', {}):
            if output['output_key'] == 'RoleData':
                for role in output['output_value']:
                    removals.append("OS::TripleO::Tasks::%sPreConfig" % role)
                    removals.append("OS::TripleO::Tasks::%sPostConfig" % role)

        plan_env = plan_utils.get_env(swift, self.container)
        self.remove_noops_from_env(removals, plan_env)
        plan_utils.put_env(swift, plan_env)

        user_env = plan_utils.get_user_env(swift, self.container)
        self.remove_noops_from_env(removals, user_env)
        plan_utils.put_user_env(swift, self.container, user_env)
Esempio n. 6
0
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        parameter_defaults = env.get('parameter_defaults', {})
        passwords = self._get_overriden_passwords(env.get('passwords', {}),
                                                  parameter_defaults)

        next_index = self.get_next_index(passwords['KeystoneFernetKeys'])
        keys_map = self.rotate_keys(passwords['KeystoneFernetKeys'],
                                    next_index)
        max_keys = self.get_max_keys_value(parameter_defaults)
        keys_map = self.purge_excess_keys(max_keys, keys_map)

        env['passwords']['KeystoneFernetKeys'] = keys_map

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.cache_delete(context,
                          self.container,
                          "tripleo.parameters.get")

        return keys_map
Esempio n. 7
0
    def run(self, context):
        try:
            swift = self.get_object_client(context)
            plan_env = plan_utils.get_env(swift, self.container)

            if self.env_key not in plan_env:
                msg = "The environment key doesn't exist: %s" % self.env_key
                return actions.Result(error=msg)

            if self.delete:
                if not self.parameter:
                    raise ValueError("delete must specify a parameter")
                plan_env[self.env_key].pop(self.parameter, None)
            elif self.parameter:
                plan_env[self.env_key][self.parameter] = self.value
            elif self.value is not None:
                plan_env[self.env_key] = self.value
            else:
                # Nothing to modify
                return

            plan_utils.update_in_env(swift, plan_env,
                                     self.env_key,
                                     value=plan_env[self.env_key])
        except swiftexceptions.ClientException as err:
            msg = "Error attempting an operation on container: %s" % err
            return actions.Result(error=msg)
        except Exception as err:
            msg = "Error while updating plan: %s" % err
            return actions.Result(error=msg)
Esempio n. 8
0
    def test_update_in_env(self):
        env = plan_utils.get_env(self.swift, self.container)

        updated_env = plan_utils.update_in_env(
            self.swift,
            env,
            'template',
            'updated-overcloud.yaml'
        )
        self.assertEqual(updated_env['template'], 'updated-overcloud.yaml')

        updated_env = plan_utils.update_in_env(
            self.swift,
            env,
            'parameter_defaults',
            {'another-key': 'another-value'}
        )
        self.assertEqual(updated_env['parameter_defaults'], {
            'BlockStorageCount': 42,
            'OvercloudControlFlavor': 'yummy',
            'another-key': 'another-value'
        })

        updated_env = plan_utils.update_in_env(
            self.swift,
            env,
            'parameter_defaults',
            delete_key=True
        )
        self.assertNotIn('parameter_defaults', updated_env)

        self.swift.get_object.assert_called()
        self.swift.put_object.assert_called()
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        for k, v in self.environments.items():
            found = False
            if {'path': k} in env['environments']:
                found = True
            if v:
                if not found:
                    env['environments'].append({'path': k})
            else:
                if found:
                    env['environments'].remove({'path': k})

        if self.purge_missing:
            for e in env['environments']:
                if e.get('path') not in self.environments:
                    env['environments'].remove(e)

        self.cache_delete(context, self.container, "tripleo.parameters.get")

        if self.sort_environments:
            # get the capabilities-map content to perform the environment
            # ordering
            try:
                swift = self.get_object_client(context)
                map_file = swiftutils.get_object_string(
                    swift,
                    self.container,
                    'capabilities-map.yaml')
                capabilities = yaml.safe_load(map_file)
            except swiftexceptions.ClientException as err:
                err_msg = ("Error retrieving capabilities-map.yaml for "
                           "plan %s: %s" % (self.container, err))
                LOG.exception(err_msg)
                return actions.Result(error=err_msg)

            ordered_env = plan_utils.apply_environments_order(
                capabilities, env.get('environments', []))

            env['environments'] = ordered_env

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        return env
Esempio n. 10
0
    def run(self, context):
        self.context = context
        swift = self.get_object_client(context)

        try:
            plan_env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            env_paths, temp_env_paths = plan_utils.build_env_paths(
                swift, self.container, plan_env)
            env_files, env = plan_utils.process_environments_and_files(
                swift, env_paths)

            # ensure every image parameter has a default value, even if prepare
            # didn't return it
            params = default_image_params()

            role_data = self._get_role_data(swift)
            image_params = kolla_builder.container_images_prepare_multi(
                env, role_data, dry_run=True)
            if image_params:
                params.update(image_params)

        except Exception as err:
            LOG.exception("Error occurred while processing plan files.")
            return actions.Result(error=six.text_type(err))
        finally:
            # cleanup any local temp files
            for f in temp_env_paths:
                os.remove(f)

        try:
            swiftutils.put_object_string(
                swift,
                self.container,
                constants.CONTAINER_DEFAULTS_ENVIRONMENT,
                yaml.safe_dump(
                    {'parameter_defaults': params},
                    default_flow_style=False
                )
            )
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating %s for plan %s: %s" % (
                constants.CONTAINER_DEFAULTS_ENVIRONMENT, self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        environments = {constants.CONTAINER_DEFAULTS_ENVIRONMENT: True}

        update_action = heat_capabilities.UpdateCapabilitiesAction(
            environments, container=self.container)
        return update_action.run(context)
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        for k, v in self.environments.items():
            found = False
            if {'path': k} in env['environments']:
                found = True
            if v:
                if not found:
                    env['environments'].append({'path': k})
            else:
                if found:
                    env['environments'].remove({'path': k})

        if self.purge_missing:
            for e in env['environments']:
                if e.get('path') not in self.environments:
                    env['environments'].remove(e)

        self.cache_delete(context, self.container, "tripleo.parameters.get")

        if self.sort_environments:
            # get the capabilities-map content to perform the environment
            # ordering
            try:
                swift = self.get_object_client(context)
                map_file = swiftutils.get_object_string(
                    swift, self.container, 'capabilities-map.yaml')
                capabilities = yaml.safe_load(map_file)
            except swiftexceptions.ClientException as err:
                err_msg = ("Error retrieving capabilities-map.yaml for "
                           "plan %s: %s" % (self.container, err))
                LOG.exception(err_msg)
                return actions.Result(error=err_msg)

            ordered_env = plan_utils.apply_environments_order(
                capabilities, env.get('environments', []))

            env['environments'] = ordered_env

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        return env
    def run(self, context):
        self.context = context
        swift = self.get_object_client(context)

        try:
            plan_env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            env_paths, temp_env_paths = plan_utils.build_env_paths(
                swift, self.container, plan_env)
            env_files, env = plan_utils.process_environments_and_files(
                swift, env_paths)

            # ensure every image parameter has a default value, even if prepare
            # didn't return it
            params = default_image_params()

            role_data = self._get_role_data(swift)
            image_params = kolla_builder.container_images_prepare_multi(
                env, role_data, dry_run=True)
            if image_params:
                params.update(image_params)

        except Exception as err:
            LOG.exception("Error occurred while processing plan files.")
            return actions.Result(error=six.text_type(err))
        finally:
            # cleanup any local temp files
            for f in temp_env_paths:
                os.remove(f)

        try:
            swiftutils.put_object_string(
                swift, self.container,
                constants.CONTAINER_DEFAULTS_ENVIRONMENT,
                yaml.safe_dump({'parameter_defaults': params},
                               default_flow_style=False))
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating %s for plan %s: %s" %
                       (constants.CONTAINER_DEFAULTS_ENVIRONMENT,
                        self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        environments = {constants.CONTAINER_DEFAULTS_ENVIRONMENT: True}

        update_action = heat_capabilities.UpdateCapabilitiesAction(
            environments, container=self.container)
        return update_action.run(context)
Esempio n. 13
0
    def run(self, context):
        # get the stack. Error if doesn't exist
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            msg = "Error retrieving stack: %s" % self.container
            LOG.exception(msg)
            return actions.Result(error=msg)

        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        update_env = {}

        noop_env = {
            'resource_registry': {
                'OS::TripleO::DeploymentSteps': 'OS::Heat::None',
            },
        }

        for output in stack.to_dict().get('outputs', {}):
            if output['output_key'] == 'RoleData':
                for role in output['output_value']:
                    role_env = {
                        "OS::TripleO::Tasks::%sPreConfig" % role:
                        'OS::Heat::None',
                        "OS::TripleO::Tasks::%sPostConfig" % role:
                        'OS::Heat::None',
                    }
                    noop_env['resource_registry'].update(role_env)
        update_env.update(noop_env)
        template_utils.deep_update(env, update_env)

        # process all plan files and create or update a stack
        processed_data = super(UpdateStackAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        stack_args = processed_data.copy()

        LOG.info("Performing Heat stack update")
        LOG.info('updating stack: %s', stack.stack_name)
        return heat.stacks.update(stack.id, **stack_args)
Esempio n. 14
0
    def run(self, context):
        heat = self.get_orchestration_client(context)
        swift = self.get_object_client(context)
        mistral = self.get_workflow_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            stack_env = heat.stacks.environment(
                stack_id=self.container)

            # legacy heat resource names from overcloud.yaml
            # We don't modify these to avoid changing defaults
            for pw_res in constants.LEGACY_HEAT_PASSWORD_RESOURCE_NAMES:
                try:
                    res = heat.resources.get(self.container, pw_res)
                    param_defaults = stack_env.get('parameter_defaults', {})
                    param_defaults[pw_res] = res.attributes['value']
                except heat_exc.HTTPNotFound:
                    LOG.debug('Heat resouce not found: %s' % pw_res)
                    pass

        except heat_exc.HTTPNotFound:
            stack_env = None

        passwords = password_utils.generate_passwords(mistral, stack_env)

        # if passwords don't yet exist in plan environment
        if 'passwords' not in env:
            env['passwords'] = {}

        # ensure all generated passwords are present in plan env,
        # but respect any values previously generated and stored
        for name, password in passwords.items():
            if name not in env['passwords']:
                env['passwords'][name] = password

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.cache_delete(context,
                          self.container,
                          "tripleo.parameters.get")
        return env['passwords']
Esempio n. 15
0
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        parameter_defaults = env.get('parameter_defaults', {})
        passwords = env.get('passwords', {})

        return self._get_overriden_passwords(passwords, parameter_defaults)
Esempio n. 16
0
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        parameter_defaults = env.get('parameter_defaults', {})
        passwords = env.get('passwords', {})

        return self._get_overriden_passwords(passwords, parameter_defaults)
Esempio n. 17
0
    def run(self, context):

        cached = self.cache_get(context,
                                self.container,
                                "tripleo.parameters.get")

        if cached is not None:
            return cached

        processed_data = super(GetParametersAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        processed_data['show_nested'] = True

        # respect previously user set param values
        swift = self.get_object_client(context)
        heat = self.get_orchestration_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        params = env.get('parameter_defaults')

        fields = {
            'template': processed_data['template'],
            'files': processed_data['files'],
            'environment': processed_data['environment'],
            'show_nested': True
        }

        result = {
            'heat_resource_tree': heat.stacks.validate(**fields),
            'environment_parameters': params,
        }
        self.cache_set(context,
                       self.container,
                       "tripleo.parameters.get",
                       result)
        return result
Esempio n. 18
0
    def run(self, context):

        cached = self.cache_get(context,
                                self.container,
                                "tripleo.parameters.get")

        if cached is not None:
            return cached

        processed_data = super(GetParametersAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        processed_data['show_nested'] = True

        # respect previously user set param values
        swift = self.get_object_client(context)
        heat = self.get_orchestration_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        params = env.get('parameter_defaults')

        fields = {
            'template': processed_data['template'],
            'files': processed_data['files'],
            'environment': processed_data['environment'],
            'show_nested': True
        }

        result = {
            'heat_resource_tree': heat.stacks.validate(**fields),
            'environment_parameters': params,
        }
        self.cache_set(context,
                       self.container,
                       "tripleo.parameters.get",
                       result)
        return result
Esempio n. 19
0
    def run(self, context):
        heat = self.get_orchestration_client(context)
        swift = self.get_object_client(context)
        mistral = self.get_workflow_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            stack_env = heat.stacks.environment(
                stack_id=self.container)
        except heat_exc.HTTPNotFound:
            stack_env = None

        passwords = password_utils.generate_passwords(mistral, stack_env)

        # if passwords don't yet exist in plan environment
        if 'passwords' not in env:
            env['passwords'] = {}

        # ensure all generated passwords are present in plan env,
        # but respect any values previously generated and stored
        for name, password in passwords.items():
            if name not in env['passwords']:
                env['passwords'][name] = password

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.cache_delete(context,
                          self.container,
                          "tripleo.parameters.get")
        return env['passwords']
Esempio n. 20
0
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            plan_utils.update_in_env(swift, env, self.key, delete_key=True)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.cache_delete(context, self.container, "tripleo.parameters.get")
        return env
Esempio n. 21
0
 def run(self, context):
     try:
         swift = self.get_object_client(context)
         plan_env = plan_utils.get_env(swift, self.container)
         if self.env_key in plan_env.keys():
             if self.delete:
                 try:
                     plan_env[self.env_key].pop(self.parameter)
                 except KeyError:
                     pass
             else:
                 plan_env[self.env_key].update({self.parameter: self.value})
         else:
             msg = "The environment key doesn't exist: %s" % self.env_key
             return actions.Result(error=msg)
     except swiftexceptions.ClientException as err:
         msg = "Error attempting an operation on container: %s" % err
         return actions.Result(error=msg)
     except Exception as err:
         msg = "Error while updating plan: %s" % err
         return actions.Result(error=msg)
Esempio n. 22
0
    def run(self, context):
        orchestration_client = self.get_orchestration_client(context)
        swift = self.get_object_client(context)

        try:
            stack = orchestration_client.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            error = (
                "The Heat stack {} could not be found. Make sure you have "
                "deployed before calling this action.").format(self.container)
            return actions.Result(error=error)

        # We need to check parameter_defaults first for a user provided
        # password. If that doesn't exist, we then should look in the
        # automatically generated passwords.
        # TODO(d0ugal): Abstract this operation somewhere. We shouldn't need to
        # know about the structure of the environment to get a password.
        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.error(err_msg)
            return actions.Result(error=err_msg)

        try:
            parameter_defaults = env['parameter_defaults']
            passwords = env['passwords']
            admin_pass = parameter_defaults.get('AdminPassword')
            if admin_pass is None:
                admin_pass = passwords['AdminPassword']
        except KeyError:
            error = ("Unable to find the AdminPassword in the plan "
                     "environment.")
            return actions.Result(error=error)

        region_name = parameter_defaults.get('KeystoneRegion')
        return overcloudrc.create_overcloudrc(stack, self.no_proxy, admin_pass,
                                              region_name)
Esempio n. 23
0
    def run(self, context):
        heat = self.get_orchestration_client(context)
        swift = self.get_object_client(context)
        mistral = self.get_workflow_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            stack_env = heat.stacks.environment(stack_id=self.container)
        except heat_exc.HTTPNotFound:
            stack_env = None

        passwords = password_utils.generate_passwords(mistral, stack_env)

        # if passwords don't yet exist in plan environment
        if 'passwords' not in env:
            env['passwords'] = {}

        # ensure all generated passwords are present in plan env,
        # but respect any values previously generated and stored
        for name, password in passwords.items():
            if name not in env['passwords']:
                env['passwords'][name] = password

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.cache_delete(context, self.container, "tripleo.parameters.get")
        return env['passwords']
Esempio n. 24
0
    def run(self, context):
        orchestration_client = self.get_orchestration_client(context)
        swift = self.get_object_client(context)

        try:
            stack = orchestration_client.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            error = (
                "The Heat stack {} could not be found. Make sure you have "
                "deployed before calling this action.").format(self.container)
            return actions.Result(error=error)

        # We need to check parameter_defaults first for a user provided
        # password. If that doesn't exist, we then should look in the
        # automatically generated passwords.
        # TODO(d0ugal): Abstract this operation somewhere. We shouldn't need to
        # know about the structure of the environment to get a password.
        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.error(err_msg)
            return actions.Result(error=err_msg)

        try:
            parameter_defaults = env['parameter_defaults']
            passwords = env['passwords']
            admin_pass = parameter_defaults.get('AdminPassword')
            if admin_pass is None:
                admin_pass = passwords['AdminPassword']
        except KeyError:
            error = ("Unable to find the AdminPassword in the plan "
                     "environment.")
            return actions.Result(error=error)

        region_name = parameter_defaults.get('KeystoneRegion')
        return overcloudrc.create_overcloudrc(stack, self.no_proxy, admin_pass,
                                              region_name)
Esempio n. 25
0
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        for k, v in self.environments.items():
            found = False
            if {'path': k} in env['environments']:
                found = True
            if v:
                if not found:
                    env['environments'].append({'path': k})
            else:
                if found:
                    env['environments'].remove({'path': k})

        if self.purge_missing:
            for e in env['environments']:
                if e.get('path') not in self.environments:
                    env['environments'].remove(e)

        self.cache_delete(context, self.container, "tripleo.parameters.get")

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        return env
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        for k, v in self.environments.items():
            found = False
            if {'path': k} in env['environments']:
                found = True
            if v:
                if not found:
                    env['environments'].append({'path': k})
            else:
                if found:
                    env['environments'].remove({'path': k})

        if self.purge_missing:
            for e in env['environments']:
                if e.get('path') not in self.environments:
                    env['environments'].remove(e)

        self.cache_delete(context, self.container, "tripleo.parameters.get")

        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = "Error uploading to container: %s" % err
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        return env
Esempio n. 27
0
    def run(self, context):
        swift = self.get_object_client(context)
        mistral = self.get_workflow_client(context)
        from_mistral = False

        try:
            env = plan_utils.get_env(swift, self.plan)
        except swiftexceptions.ClientException:
            # The plan has not been migrated yet. Check if there is a
            # Mistral environment.
            try:
                env = mistral.environments.get(self.plan).variables
                from_mistral = True
            except (mistralclient_base.APIException,
                    keystoneauth_exc.http.NotFound):
                # No Mistral env and no template: likely deploying old
                # templates aka previous version of OpenStack.
                env = {
                    'version':
                    1.0,
                    'name':
                    self.plan,
                    'description':
                    '',
                    'template':
                    'overcloud.yaml',
                    'environments': [{
                        'path':
                        'overcloud-resource-registry-puppet.yaml'
                    }]
                }

            # Store the environment info into Swift
            plan_utils.put_env(swift, env)
            if from_mistral:
                mistral.environments.delete(self.plan)
Esempio n. 28
0
    def run(self, context):
        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            plan_utils.update_in_env(swift, env, self.key,
                                     delete_key=True)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.cache_delete(context,
                          self.container,
                          "tripleo.parameters.get")
        return env
    def run(self, context):
        try:
            swift = self.get_object_client(context)
            map_file = swiftutils.get_object_string(swift,
                                                    self.container,
                                                    'capabilities-map.yaml')
            capabilities = yaml.safe_load(map_file)
        except Exception:
            err_msg = (
                "Error parsing capabilities-map.yaml.")
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)
        try:
            container_files = swift.get_container(self.container)
            container_file_list = [entry['name'] for entry
                                   in container_files[1]]
        except Exception as swift_err:
            err_msg = ("Error retrieving plan files: %s" % swift_err)
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        selected_envs = [item['path'] for item in env['environments']
                         if 'path' in item]

        # extract environment files
        plan_environments = []
        for env_group in capabilities['topics']:
            for envs in env_group['environment_groups']:
                for files in envs['environments']:
                    file = files.get('file')
                    if file:
                        plan_environments.append(file)

        # parse plan for environment files
        env_files = fnmatch.filter(
            container_file_list, '*environments/*.yaml')
        env_user_files = fnmatch.filter(
            container_file_list, '*user-environment.yaml')

        outstanding_envs = list(set(env_files).union(
            env_user_files) - set(plan_environments))

        # change capabilities format
        data_to_return = {}

        for topic in capabilities['topics']:
            title = topic.get('title', '_title_holder')
            data_to_return[title] = topic
            for eg in topic['environment_groups']:
                for env in eg['environments']:
                    if selected_envs and env.get('file') in selected_envs:
                        env['enabled'] = True
                    else:
                        env['enabled'] = False

        # add custom environment files
        other_environments = []
        for env in outstanding_envs:
            flag = selected_envs and env in selected_envs
            new_env = {
                "description": "Enable %s environment" % env,
                "enabled": flag,
                "file": env,
                "title": env,
            }
            other_environments.append(new_env)
        other_environments.sort(key=lambda x: x['file'])

        other_environment_groups = []
        for group in other_environments:
            new_group = {
                "description": None,
                "environments": [group],
                "title": group['file'],
            }
            other_environment_groups.append(new_group)

        other_environments_topic_dict = {
            "description": None,
            "title": "Other",
            "environment_groups": other_environment_groups
        }

        other_environments_topic = {
            "Other": other_environments_topic_dict
        }
        data_to_return.update(other_environments_topic)

        return data_to_return
Esempio n. 30
0
    def run(self, context):
        error_text = None
        self.context = context
        swift = self.get_object_client(context)

        try:
            plan_env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=error_text)

        try:
            # if the jinja overcloud template exists, process it and write it
            # back to the swift container before continuing processing.  The
            # method called below should handle the case where the files are
            # not found in swift, but if they are found and an exception
            # occurs during processing, that exception will cause the
            # ProcessTemplatesAction to return an error result.
            self._process_custom_roles(context)
        except Exception as err:
            LOG.exception("Error occurred while processing custom roles.")
            return actions.Result(error=six.text_type(err))

        template_name = plan_env.get('template', "")

        template_object = os.path.join(swift.url, self.container,
                                       template_name)
        LOG.debug('Template: %s' % template_name)
        try:
            template_files, template = plan_utils.get_template_contents(
                swift, template_object)
        except Exception as err:
            error_text = six.text_type(err)
            LOG.exception("Error occurred while fetching %s" % template_object)

        temp_env_paths = []
        try:
            env_paths, temp_env_paths = plan_utils.build_env_paths(
                swift, self.container, plan_env)
            env_files, env = plan_utils.process_environments_and_files(
                swift, env_paths)
            parameters.convert_docker_params(env)
        except Exception as err:
            error_text = six.text_type(err)
            LOG.exception("Error occurred while processing plan files.")
        finally:
            # cleanup any local temp files
            for f in temp_env_paths:
                os.remove(f)

        if error_text:
            return actions.Result(error=error_text)

        files = dict(list(template_files.items()) + list(env_files.items()))

        return {
            'stack_name': self.container,
            'template': template,
            'environment': env,
            'files': files
        }
Esempio n. 31
0
    def run(self, context):
        # get the stack. Error if doesn't exist
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            msg = "Error retrieving stack: %s" % self.container
            LOG.exception(msg)
            return actions.Result(error=msg)

        parameters = dict()
        timestamp = int(time.time())
        parameters['DeployIdentifier'] = timestamp
        parameters['UpdateIdentifier'] = timestamp
        parameters['StackAction'] = 'UPDATE'

        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            plan_utils.update_in_env(swift, env, 'parameter_defaults',
                                     parameters)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        # process all plan files and create or update a stack
        processed_data = super(UpdateStackAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        stack_args = processed_data.copy()

        env = stack_args.get('environment', {})
        template_utils.deep_update(
            env, {
                'resource_registry': {
                    'resources': {
                        '*': {
                            '*': {
                                constants.UPDATE_RESOURCE_NAME: {
                                    'hooks': 'pre-update'
                                }
                            }
                        }
                    }
                }
            })
        stack_args['environment'] = env

        stack_args['timeout_mins'] = self.timeout_mins
        stack_args['existing'] = 'true'

        LOG.info("Performing Heat stack update")
        LOG.info('updating stack: %s', stack.stack_name)
        return heat.stacks.update(stack.id, **stack_args)
Esempio n. 32
0
    def test_get_env(self):
        env = plan_utils.get_env(self.swift, self.container)

        self.swift.get_object.assert_called()
        self.assertEqual(env['template'], 'overcloud.yaml')
    def run(self, context):
        try:
            swift = self.get_object_client(context)
            map_file = swiftutils.get_object_string(swift, self.container,
                                                    'capabilities-map.yaml')
            capabilities = yaml.safe_load(map_file)
        except Exception:
            err_msg = ("Error parsing capabilities-map.yaml.")
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)
        try:
            container_files = swift.get_container(self.container)
            container_file_list = [
                entry['name'] for entry in container_files[1]
            ]
        except Exception as swift_err:
            err_msg = ("Error retrieving plan files: %s" % swift_err)
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        selected_envs = [
            item['path'] for item in env['environments'] if 'path' in item
        ]

        # extract environment files
        plan_environments = []
        for env_group in capabilities['topics']:
            for envs in env_group['environment_groups']:
                for files in envs['environments']:
                    file = files.get('file')
                    if file:
                        plan_environments.append(file)

        # parse plan for environment files
        env_files = fnmatch.filter(container_file_list, '*environments/*.yaml')
        env_user_files = fnmatch.filter(container_file_list,
                                        '*user-environment.yaml')

        outstanding_envs = list(
            set(env_files).union(env_user_files) - set(plan_environments))

        # change capabilities format
        data_to_return = {}

        for topic in capabilities['topics']:
            title = topic.get('title', '_title_holder')
            data_to_return[title] = topic
            for eg in topic['environment_groups']:
                for env in eg['environments']:
                    if selected_envs and env.get('file') in selected_envs:
                        env['enabled'] = True
                    else:
                        env['enabled'] = False

        # add custom environment files
        other_environments = []
        for env in outstanding_envs:
            flag = selected_envs and env in selected_envs
            new_env = {
                "description": "Enable %s environment" % env,
                "enabled": flag,
                "file": env,
                "title": env,
            }
            other_environments.append(new_env)
        other_environments.sort(key=lambda x: x['file'])

        other_environment_groups = []
        for group in other_environments:
            new_group = {
                "description": None,
                "environments": [group],
                "title": group['file'],
            }
            other_environment_groups.append(new_group)

        other_environments_topic_dict = {
            "description": None,
            "title": "Other",
            "environment_groups": other_environment_groups
        }

        other_environments_topic = {"Other": other_environments_topic_dict}
        data_to_return.update(other_environments_topic)

        return data_to_return
Esempio n. 34
0
    def run(self, context):
        # check to see if the stack exists
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container, resolve_outputs=False)
        except heat_exc.HTTPNotFound:
            stack = None

        stack_is_new = stack is None

        # update StackAction, DeployIdentifier and UpdateIdentifier
        swift = self.get_object_client(context)

        parameters = dict()
        if not self.skip_deploy_identifier:
            parameters['DeployIdentifier'] = int(time.time())
        parameters['UpdateIdentifier'] = ''
        parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE'

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        self.set_tls_parameters(parameters, env)
        try:
            plan_utils.update_in_env(swift, env, 'parameter_defaults',
                                     parameters)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        if not stack_is_new:
            try:
                LOG.debug('Checking for compatible neutron mechanism drivers')
                msg = update.check_neutron_mechanism_drivers(
                    env, stack, swift, self.container)
                if msg:
                    return actions.Result(error=msg)
            except swiftexceptions.ClientException as err:
                err_msg = ("Error getting template %s: %s" %
                           (self.container, err))
                LOG.exception(err_msg)
                return actions.Result(error=err_msg)

        # process all plan files and create or update a stack
        process_templates_action = templates.ProcessTemplatesAction(
            container=self.container)
        processed_data = process_templates_action.run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        stack_args = processed_data.copy()
        stack_args['timeout_mins'] = self.timeout_mins

        if stack_is_new:
            try:
                swift.copy_object(
                    "%s-swift-rings" % self.container, "swift-rings.tar.gz",
                    "%s-swift-rings/%s-%d" %
                    (self.container, "swift-rings.tar.gz", time.time()))
                swift.delete_object("%s-swift-rings" % self.container,
                                    "swift-rings.tar.gz")
            except swiftexceptions.ClientException:
                pass
            LOG.info("Perfoming Heat stack create")
            try:
                return heat.stacks.create(**stack_args)
            except heat_exc.HTTPException as err:
                err_msg = "Error during stack creation: %s" % (err, )
                LOG.exception(err_msg)
                return actions.Result(error=err_msg)

        LOG.info("Performing Heat stack update")
        stack_args['existing'] = 'true'
        try:
            return heat.stacks.update(stack.id, **stack_args)
        except heat_exc.HTTPException as err:
            err_msg = "Error during stack update: %s" % (err, )
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)
Esempio n. 35
0
    def run(self, context):
        # check to see if the stack exists
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            stack = None

        stack_is_new = stack is None

        # update StackAction, DeployIdentifier and UpdateIdentifier
        swift = self.get_object_client(context)

        parameters = dict()
        if not self.skip_deploy_identifier:
            parameters['DeployIdentifier'] = int(time.time())
        parameters['UpdateIdentifier'] = ''
        parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE'

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            plan_utils.update_in_env(swift, env, 'parameter_defaults',
                                     parameters)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        # process all plan files and create or update a stack
        processed_data = super(DeployStackAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        stack_args = processed_data.copy()
        stack_args['timeout_mins'] = self.timeout_mins

        if stack_is_new:
            try:
                swift.copy_object(
                    "%s-swift-rings" % self.container, "swift-rings.tar.gz",
                    "%s-swift-rings/%s-%d" % (
                        self.container, "swift-rings.tar.gz", time.time()))
                swift.delete_object(
                    "%s-swift-rings" % self.container, "swift-rings.tar.gz")
            except swiftexceptions.ClientException:
                pass
            LOG.info("Perfoming Heat stack create")
            return heat.stacks.create(**stack_args)

        LOG.info("Performing Heat stack update")
        stack_args['existing'] = 'true'
        return heat.stacks.update(stack.id, **stack_args)
Esempio n. 36
0
    def run(self, context):
        error_text = None
        self.context = context
        swift = self.get_object_client(context)

        try:
            plan_env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=error_text)

        try:
            # if the jinja overcloud template exists, process it and write it
            # back to the swift container before continuing processing.  The
            # method called below should handle the case where the files are
            # not found in swift, but if they are found and an exception
            # occurs during processing, that exception will cause the
            # ProcessTemplatesAction to return an error result.
            self._process_custom_roles(context)
        except Exception as err:
            LOG.exception("Error occurred while processing custom roles.")
            return actions.Result(error=six.text_type(err))

        template_name = plan_env.get('template', "")

        template_object = os.path.join(swift.url, self.container,
                                       template_name)
        LOG.debug('Template: %s' % template_name)
        try:
            template_files, template = plan_utils.get_template_contents(
                swift, template_object)
        except Exception as err:
            error_text = six.text_type(err)
            LOG.exception("Error occurred while fetching %s" % template_object)

        temp_env_paths = []
        try:
            env_paths, temp_env_paths = plan_utils.build_env_paths(
                swift, self.container, plan_env)
            env_files, env = plan_utils.process_environments_and_files(
                swift, env_paths)
            parameters.convert_docker_params(env)
        except Exception as err:
            error_text = six.text_type(err)
            LOG.exception("Error occurred while processing plan files.")
        finally:
            # cleanup any local temp files
            for f in temp_env_paths:
                os.remove(f)

        if error_text:
            return actions.Result(error=error_text)

        files = dict(list(template_files.items()) + list(env_files.items()))

        return {
            'stack_name': self.container,
            'template': template,
            'environment': env,
            'files': files
        }
    def run(self, context):
        # get the stack. Error if doesn't exist
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            msg = "Error retrieving stack: %s" % self.container
            LOG.exception(msg)
            return actions.Result(error=msg)

        parameters = dict()
        timestamp = int(time.time())
        parameters['DeployIdentifier'] = timestamp
        parameters['UpdateIdentifier'] = timestamp
        parameters['StackAction'] = 'UPDATE'

        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            plan_utils.update_in_env(swift, env, 'parameter_defaults',
                                     parameters)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        # process all plan files and create or update a stack
        processed_data = super(UpdateStackAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        stack_args = processed_data.copy()

        env = stack_args.get('environment', {})
        template_utils.deep_update(env, {
            'resource_registry': {
                'resources': {
                    '*': {
                        '*': {
                            constants.UPDATE_RESOURCE_NAME: {
                                'hooks': 'pre-update'}
                        }
                    }
                }
            }
        })
        stack_args['environment'] = env

        stack_args['timeout_mins'] = self.timeout_mins
        stack_args['existing'] = 'true'

        LOG.info("Performing Heat stack update")
        LOG.info('updating stack: %s', stack.stack_name)
        return heat.stacks.update(stack.id, **stack_args)
Esempio n. 38
0
    def run(self, context):
        error_text = None
        self.context = context
        swift = self.get_object_client(context)

        try:
            plan_env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=error_text)

        try:
            # if the jinja overcloud template exists, process it and write it
            # back to the swift container before continuing processing.  The
            # method called below should handle the case where the files are
            # not found in swift, but if they are found and an exception
            # occurs during processing, that exception will cause the
            # ProcessTemplatesAction to return an error result.
            self._process_custom_roles(context)
        except Exception as err:
            LOG.exception("Error occurred while processing custom roles.")
            return actions.Result(error=six.text_type(err))

        template_name = plan_env.get('template')
        environments = plan_env.get('environments')
        env_paths = []
        temp_files = []

        template_object = os.path.join(swift.url, self.container,
                                       template_name)

        LOG.debug('Template: %s' % template_name)
        LOG.debug('Environments: %s' % environments)
        try:
            for env in environments:
                if env.get('path'):
                    env_paths.append(os.path.join(swift.url, self.container,
                                                  env['path']))
                elif env.get('data'):
                    env_temp_file = _create_temp_file(env['data'])
                    temp_files.append(env_temp_file)
                    env_paths.append(env_temp_file)

            # create a dict to hold all user set params and merge
            # them in the appropriate order
            merged_params = {}
            # merge generated passwords into params first
            passwords = plan_env.get('passwords', {})
            merged_params.update(passwords)
            # handle user set parameter values next in case a user has set
            # a new value for a password parameter
            params = plan_env.get('parameter_defaults', {})
            merged_params.update(params)
            if merged_params:
                env_temp_file = _create_temp_file(
                    {'parameter_defaults': merged_params})
                temp_files.append(env_temp_file)
                env_paths.append(env_temp_file)

            def _env_path_is_object(env_path):
                retval = env_path.startswith(swift.url)
                LOG.debug('_env_path_is_object %s: %s' % (env_path, retval))
                return retval

            def _object_request(method, url, token=context.auth_token):
                return requests.request(
                    method, url, headers={'X-Auth-Token': token}).content

            template_files, template = template_utils.get_template_contents(
                template_object=template_object,
                object_request=_object_request)

            env_files, env = (
                template_utils.process_multiple_environments_and_files(
                    env_paths=env_paths,
                    env_path_is_object=_env_path_is_object,
                    object_request=_object_request))

        except Exception as err:
            error_text = six.text_type(err)
            LOG.exception("Error occurred while processing plan files.")
        finally:
            # cleanup any local temp files
            for f in temp_files:
                os.remove(f)

        if error_text:
            return actions.Result(error=error_text)

        files = dict(list(template_files.items()) + list(env_files.items()))

        return {
            'stack_name': self.container,
            'template': template,
            'environment': env,
            'files': files
        }
Esempio n. 39
0
    def run(self, context):
        # get the stack. Error if doesn't exist
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            msg = "Error retrieving stack: %s" % self.container
            LOG.exception(msg)
            return actions.Result(error=msg)

        swift = self.get_object_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        update_env = {
            'parameter_defaults': {
                'DeployIdentifier': int(time.time()),
            },
        }

        noop_env = {
            'resource_registry': {
                'OS::TripleO::DeploymentSteps': 'OS::Heat::None',
            },
        }

        for output in stack.to_dict().get('outputs', {}):
            if output['output_key'] == 'RoleData':
                for role in output['output_value']:
                    role_env = {
                        "OS::TripleO::Tasks::%sPreConfig" % role:
                        'OS::Heat::None',
                        "OS::TripleO::Tasks::%sPostConfig" % role:
                        'OS::Heat::None',
                    }
                    noop_env['resource_registry'].update(role_env)
        update_env.update(noop_env)
        template_utils.deep_update(env, update_env)
        try:
            plan_utils.put_env(swift, env)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        # process all plan files and create or update a stack
        processed_data = super(UpdateStackAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        stack_args = processed_data.copy()

        LOG.info("Performing Heat stack update")
        LOG.info('updating stack: %s', stack.stack_name)
        return heat.stacks.update(stack.id, **stack_args)
Esempio n. 40
0
    def test_get_env(self):
        env = plan_utils.get_env(self.swift, self.container)

        self.swift.get_object.assert_called()
        self.assertEqual(env['template'], 'overcloud.yaml')
Esempio n. 41
0
    def run(self, context):
        # check to see if the stack exists
        heat = self.get_orchestration_client(context)
        try:
            stack = heat.stacks.get(self.container)
        except heat_exc.HTTPNotFound:
            stack = None

        stack_is_new = stack is None

        # update StackAction, DeployIdentifier and UpdateIdentifier
        swift = self.get_object_client(context)

        parameters = dict()
        if not self.skip_deploy_identifier:
            parameters['DeployIdentifier'] = int(time.time())
        parameters['UpdateIdentifier'] = ''
        parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE'

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        try:
            plan_utils.update_in_env(swift, env, 'parameter_defaults',
                                     parameters)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        # process all plan files and create or update a stack
        processed_data = super(DeployStackAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        stack_args = processed_data.copy()
        stack_args['timeout_mins'] = self.timeout_mins

        if stack_is_new:
            try:
                swift.copy_object(
                    "%s-swift-rings" % self.container, "swift-rings.tar.gz",
                    "%s-swift-rings/%s-%d" %
                    (self.container, "swift-rings.tar.gz", time.time()))
                swift.delete_object("%s-swift-rings" % self.container,
                                    "swift-rings.tar.gz")
            except swiftexceptions.ClientException:
                pass
            LOG.info("Perfoming Heat stack create")
            return heat.stacks.create(**stack_args)

        LOG.info("Performing Heat stack update")
        stack_args['existing'] = 'true'
        return heat.stacks.update(stack.id, **stack_args)
Esempio n. 42
0
    def run(self, context):
        error_text = None
        self.context = context
        swift = self.get_object_client(context)

        try:
            plan_env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" % (
                self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=error_text)

        try:
            # if the jinja overcloud template exists, process it and write it
            # back to the swift container before continuing processing.  The
            # method called below should handle the case where the files are
            # not found in swift, but if they are found and an exception
            # occurs during processing, that exception will cause the
            # ProcessTemplatesAction to return an error result.
            self._process_custom_roles(context)
        except Exception as err:
            LOG.exception("Error occurred while processing custom roles.")
            return actions.Result(error=six.text_type(err))

        template_name = plan_env.get('template')
        environments = plan_env.get('environments')
        env_paths = []
        temp_files = []

        template_object = os.path.join(swift.url, self.container,
                                       template_name)

        LOG.debug('Template: %s' % template_name)
        LOG.debug('Environments: %s' % environments)
        try:
            for env in environments:
                if env.get('path'):
                    env_paths.append(os.path.join(swift.url, self.container,
                                                  env['path']))
                elif env.get('data'):
                    env_temp_file = _create_temp_file(env['data'])
                    temp_files.append(env_temp_file)
                    env_paths.append(env_temp_file)

            # create a dict to hold all user set params and merge
            # them in the appropriate order
            merged_params = {}
            # merge generated passwords into params first
            passwords = plan_env.get('passwords', {})
            merged_params.update(passwords)

            # derived parameters are merged before 'parameter defaults'
            # so that user-specified values can override the derived values.
            derived_params = plan_env.get('derived_parameters', {})
            merged_params.update(derived_params)

            # handle user set parameter values next in case a user has set
            # a new value for a password parameter
            params = plan_env.get('parameter_defaults', {})
            merged_params = template_utils.deep_update(merged_params, params)

            if merged_params:
                env_temp_file = _create_temp_file(
                    {'parameter_defaults': merged_params})
                temp_files.append(env_temp_file)
                env_paths.append(env_temp_file)

            def _env_path_is_object(env_path):
                retval = env_path.startswith(swift.url)
                LOG.debug('_env_path_is_object %s: %s' % (env_path, retval))
                return retval

            def _object_request(method, url, token=context.auth_token):
                return requests.request(
                    method, url, headers={'X-Auth-Token': token}).content

            template_files, template = template_utils.get_template_contents(
                template_object=template_object,
                object_request=_object_request)

            env_files, env = (
                template_utils.process_multiple_environments_and_files(
                    env_paths=env_paths,
                    env_path_is_object=_env_path_is_object,
                    object_request=_object_request))

        except Exception as err:
            error_text = six.text_type(err)
            LOG.exception("Error occurred while processing plan files.")
        finally:
            # cleanup any local temp files
            for f in temp_files:
                os.remove(f)

        if error_text:
            return actions.Result(error=error_text)

        files = dict(list(template_files.items()) + list(env_files.items()))

        return {
            'stack_name': self.container,
            'template': template,
            'environment': env,
            'files': files
        }
Esempio n. 43
0
    def run(self, context):
        swift = self.get_object_client(context)
        heat = self.get_orchestration_client(context)

        try:
            env = plan_utils.get_env(swift, self.container)
        except swiftexceptions.ClientException as err:
            err_msg = ("Error retrieving environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        saved_env = copy.deepcopy(env)
        try:

            plan_utils.update_in_env(swift, env, self.key, self.parameters)

        except swiftexceptions.ClientException as err:
            err_msg = ("Error updating environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        processed_data = super(UpdateParametersAction, self).run(context)

        # If we receive a 'Result' instance it is because the parent action
        # had an error.
        if isinstance(processed_data, actions.Result):
            return processed_data

        env = plan_utils.get_env(swift, self.container)
        if not self.validate:
            return env

        params = env.get('parameter_defaults')
        fields = {
            'template': processed_data['template'],
            'files': processed_data['files'],
            'environment': processed_data['environment'],
            'show_nested': True
        }

        try:
            result = {
                'heat_resource_tree': heat.stacks.validate(**fields),
                'environment_parameters': params,
            }

            # Validation passes so the old cache gets replaced.
            self.cache_set(context, self.container, "tripleo.parameters.get",
                           result)

            if result['heat_resource_tree']:
                flattened = {'resources': {}, 'parameters': {}}
                _flat_it(flattened, 'Root', result['heat_resource_tree'])
                result['heat_resource_tree'] = flattened

        except heat_exc.HTTPException as err:
            LOG.debug("Validation failed rebuilding saved env")

            # There has been an error validating we must reprocess the
            # templates with the saved working env
            plan_utils.put_env(swift, saved_env)
            self._process_custom_roles(context)

            err_msg = ("Error validating environment for plan %s: %s" %
                       (self.container, err))
            LOG.exception(err_msg)
            return actions.Result(error=err_msg)

        LOG.debug("Validation worked new env is saved")

        return result