Esempio n. 1
0
def _start_workflow(blueprint_id, deployment_id, execution_id, op_name, sm):
    workflow_id = 'hosts_software_' + op_name

    new_execution = models.Execution(id=execution_id,
                                     status=models.Execution.PENDING,
                                     created_at=str(datetime.now()),
                                     blueprint_id=blueprint_id,
                                     workflow_id=workflow_id,
                                     deployment_id=deployment_id,
                                     error='',
                                     parameters=[],
                                     is_system_workflow=False)

    sm.put_execution(new_execution.id, new_execution)

    workflow = {
        'operation': 'software_replacement_workflow.replace_host_software'
    }

    workflow_client().execute_workflow(
        workflow_id,
        workflow,
        blueprint_id=blueprint_id,
        deployment_id=deployment_id,
        execution_id=execution_id,
        execution_parameters={'op_name': op_name})
    def execute_workflow(self,
                         deployment_id,
                         workflow_id,
                         parameters=None,
                         allow_custom_parameters=False,
                         force=False):
        deployment = self.get_deployment(deployment_id)

        if workflow_id not in deployment.workflows:
            raise manager_exceptions.NonexistentWorkflowError(
                'Workflow {0} does not exist in deployment {1}'.format(
                    workflow_id, deployment_id))
        workflow = deployment.workflows[workflow_id]

        self._verify_deployment_environment_created_successfully(deployment_id)

        # validate no execution is currently in progress
        if not force:
            executions = get_storage_manager().executions_list(
                deployment_id=deployment_id)
            running = [
                e.id for e in executions
                if get_storage_manager().get_execution(e.id).status not in
                models.Execution.END_STATES
            ]
            if len(running) > 0:
                raise manager_exceptions.ExistingRunningExecutionError(
                    'The following executions are currently running for this '
                    'deployment: {0}. To execute this workflow anyway, pass '
                    '"force=true" as a query parameter to this request'.format(
                        running))

        execution_parameters = \
            BlueprintsManager._merge_and_validate_execution_parameters(
                workflow, workflow_id, parameters, allow_custom_parameters)

        execution_id = str(uuid.uuid4())

        new_execution = models.Execution(
            id=execution_id,
            status=models.Execution.PENDING,
            created_at=str(datetime.now()),
            blueprint_id=deployment.blueprint_id,
            workflow_id=workflow_id,
            deployment_id=deployment_id,
            error='',
            parameters=self._get_only_user_execution_parameters(
                execution_parameters))

        get_storage_manager().put_execution(new_execution.id, new_execution)

        workflow_client().execute_workflow(
            workflow_id,
            workflow,
            blueprint_id=deployment.blueprint_id,
            deployment_id=deployment_id,
            execution_id=execution_id,
            execution_parameters=execution_parameters)

        return new_execution
Esempio n. 3
0
    def execute_workflow(self,
                         deployment_id,
                         workflow_id,
                         parameters=None,
                         allow_custom_parameters=False,
                         force=False):
        """Executes the specified workflow

        :param deployment_id:
        :param workflow_id:
        :param parameters:
        :param allow_custom_parameters:
        :param force:
        :return:
        """
        deployment = self.sm.get_deployment(deployment_id)
        blueprint = self.sm.get_blueprint(deployment.blueprint_id)

        if workflow_id not in deployment.workflows:
            raise manager_rest.manager_exceptions.NonexistentWorkflowError(
                'Workflow {0} does not exist in deployment {1}'.format(
                    workflow_id, deployment_id))
        workflow = deployment.workflows[workflow_id]

        execution_parameters = \
            BlueprintsManager._merge_and_validate_execution_parameters(
                workflow, workflow_id, parameters, allow_custom_parameters)

        execution_id = str(uuid.uuid4())

        new_execution = models.Execution(
            id=execution_id,
            status=models.Execution.PENDING,
            created_at=str(datetime.now()),
            blueprint_id=deployment.blueprint_id,
            workflow_id=workflow_id,
            deployment_id=deployment_id,
            error='',
            parameters=BlueprintsManager._get_only_user_execution_parameters(
                execution_parameters),
            is_system_workflow=False)

        self.sm.put_execution(new_execution.id, new_execution)

        # executing the user workflow
        workflow_plugins = blueprint.plan[
            constants.WORKFLOW_PLUGINS_TO_INSTALL]
        self.workflow_client.execute_workflow(
            workflow_id,
            workflow,
            workflow_plugins=workflow_plugins,
            blueprint_id=deployment.blueprint_id,
            deployment_id=deployment_id,
            execution_id=execution_id,
            execution_parameters=execution_parameters)

        return new_execution
    def execute_workflow(self, deployment_id, workflow_id,
                         parameters=None,
                         allow_custom_parameters=False, force=False):
        deployment = self.get_deployment(deployment_id)
        blueprint = self.get_blueprint(deployment.blueprint_id)

        if workflow_id not in deployment.workflows:
            raise manager_exceptions.NonexistentWorkflowError(
                'Workflow {0} does not exist in deployment {1}'.format(
                    workflow_id, deployment_id))
        workflow = deployment.workflows[workflow_id]

        self._verify_deployment_environment_created_successfully(deployment_id)

        self._check_for_active_system_wide_execution()
        self._check_for_active_executions(deployment_id, force)

        execution_parameters = \
            BlueprintsManager._merge_and_validate_execution_parameters(
                workflow, workflow_id, parameters, allow_custom_parameters)

        execution_id = str(uuid.uuid4())

        new_execution = models.Execution(
            id=execution_id,
            status=models.Execution.PENDING,
            created_at=str(datetime.now()),
            blueprint_id=deployment.blueprint_id,
            workflow_id=workflow_id,
            deployment_id=deployment_id,
            error='',
            parameters=self._get_only_user_execution_parameters(
                execution_parameters),
            is_system_workflow=False)

        self.sm.put_execution(new_execution.id, new_execution)

        # executing the user workflow
        workflow_plugins = blueprint.plan[
            constants.WORKFLOW_PLUGINS_TO_INSTALL]
        self.workflow_client.execute_workflow(
            workflow_id,
            workflow,
            workflow_plugins=workflow_plugins,
            blueprint_id=deployment.blueprint_id,
            deployment_id=deployment_id,
            execution_id=execution_id,
            execution_parameters=execution_parameters)

        return new_execution
Esempio n. 5
0
    def test_list_system_executions(self):
        (blueprint_id, deployment_id, blueprint_response,
         deployment_response) = self.put_deployment(self.DEPLOYMENT_ID)

        # manually pushing a system workflow execution to the storage
        system_wf_execution_id = 'mock_execution_id'
        system_wf_id = 'mock_system_workflow_id'
        system_wf_execution = models.Execution(
            id=system_wf_execution_id,
            status=models.Execution.TERMINATED,
            deployment_id=deployment_id,
            workflow_id=system_wf_id,
            blueprint_id=blueprint_id,
            created_at=str(datetime.now()),
            error='',
            parameters=dict(),
            is_system_workflow=True)
        storage_manager._get_instance().put_execution(
            system_wf_execution_id, system_wf_execution)

        # listing only non-system workflow executions
        executions = self.client.executions.list(deployment_id=deployment_id)

        # expecting 1 execution (create_deployment_environment)
        self.assertEquals(1, len(executions))
        self.assertEquals('create_deployment_environment',
                          executions[0]['workflow_id'])

        # listing all executions
        executions = self.client.executions.list(deployment_id=deployment_id,
                                                 include_system_workflows=True)
        executions.sort(key=lambda e: e.created_at)

        # expecting 2 executions
        self.assertEquals(2, len(executions))
        self.assertEquals('create_deployment_environment',
                          executions[0]['workflow_id'])
        self.assertEquals(system_wf_id, executions[1]['workflow_id'])

        return deployment_id, system_wf_id
    def _delete_deployment_environment(self, deployment_id):
        deployment = get_storage_manager().get_deployment(deployment_id)

        deployment_env_deletion_task_id = str(uuid.uuid4())
        wf_id = 'delete_deployment_environment'
        deployment_env_deletion_task_name = \
            'system_workflows.deployment_environment.delete'

        context = self._build_context_from_deployment(
            deployment, deployment_env_deletion_task_id, wf_id,
            deployment_env_deletion_task_name)
        kwargs = {'__cloudify_context': context}

        new_execution = models.Execution(
            id=deployment_env_deletion_task_id,
            status=models.Execution.PENDING,
            created_at=str(datetime.now()),
            blueprint_id=deployment.blueprint_id,
            workflow_id=wf_id,
            deployment_id=deployment_id,
            error='',
            parameters=self._get_only_user_execution_parameters(kwargs))
        get_storage_manager().put_execution(new_execution.id, new_execution)

        deployment_env_deletion_task_async_result = \
            celery_client().execute_task(
                deployment_env_deletion_task_name,
                'cloudify.management',
                deployment_env_deletion_task_id,
                kwargs=kwargs)

        # wait for deployment environment deletion to complete
        deployment_env_deletion_task_async_result.get(timeout=300,
                                                      propagate=True)
        # verify deployment environment deletion completed successfully
        execution = get_storage_manager().get_execution(
            deployment_env_deletion_task_id)
        if execution.status != models.Execution.TERMINATED:
            raise RuntimeError('Failed to delete environment for deployment '
                               '{0}'.format(deployment_id))
    def _create_deployment_environment(self, deployment, deployment_plan, now):
        deployment_env_creation_task_id = str(uuid.uuid4())
        wf_id = 'create_deployment_environment'
        deployment_env_creation_task_name = \
            'system_workflows.deployment_environment.create'

        context = self._build_context_from_deployment(
            deployment, deployment_env_creation_task_id, wf_id,
            deployment_env_creation_task_name)
        kwargs = {
            'management_plugins_to_install':
            deployment_plan['management_plugins_to_install'],
            'workflow_plugins_to_install':
            deployment_plan['workflow_plugins_to_install'],
            'policy_configuration': {
                'policy_types': deployment_plan['policy_types'],
                'policy_triggers': deployment_plan['policy_triggers'],
                'groups': deployment_plan['groups'],
            },
            '__cloudify_context':
            context
        }

        new_execution = models.Execution(
            id=deployment_env_creation_task_id,
            status=models.Execution.PENDING,
            created_at=now,
            blueprint_id=deployment.blueprint_id,
            workflow_id=wf_id,
            deployment_id=deployment.id,
            error='',
            parameters=self._get_only_user_execution_parameters(kwargs))
        get_storage_manager().put_execution(new_execution.id, new_execution)

        celery_client().execute_task(deployment_env_creation_task_name,
                                     'cloudify.management',
                                     deployment_env_creation_task_id,
                                     kwargs=kwargs)
    def _execute_system_workflow(self, wf_id, task_mapping, deployment=None,
                                 execution_parameters=None, timeout=0,
                                 created_at=None,
                                 verify_no_executions=True):
        """
        :param deployment: deployment for workflow execution
        :param wf_id: workflow id
        :param task_mapping: mapping to the system workflow
        :param execution_parameters: parameters for the system workflow
        :param timeout: 0 will return immediately; any positive value will
         cause this method to wait for the given timeout for the task to
         complete, and verify it finished successfully before returning
        :param created_at: creation time for the workflow execution object.
         if omitted, a value will be generated by this method.
        :return: (async task object, execution object)
        """
        execution_id = str(uuid.uuid4())  # will also serve as the task id
        execution_parameters = execution_parameters or {}

        # currently, deployment env creation/deletion are not set as
        # system workflows
        is_system_workflow = wf_id not in (
            'create_deployment_environment', 'delete_deployment_environment')

        # It means that a system-wide workflow is about to be launched
        if deployment is None and verify_no_executions:
            self._check_for_any_active_executions()

        execution = models.Execution(
            id=execution_id,
            status=models.Execution.PENDING,
            created_at=created_at or str(datetime.now()),
            blueprint_id=deployment.blueprint_id if deployment else None,
            workflow_id=wf_id,
            deployment_id=deployment.id if deployment else None,
            error='',
            parameters=self._get_only_user_execution_parameters(
                execution_parameters),
            is_system_workflow=is_system_workflow)

        self.sm.put_execution(execution.id, execution)

        async_task = self.workflow_client.execute_system_workflow(
            wf_id=wf_id,
            task_id=execution_id,
            task_mapping=task_mapping,
            deployment=deployment,
            execution_parameters=execution_parameters)

        if timeout > 0:
            try:
                # wait for the workflow execution to complete
                async_task.get(timeout=timeout, propagate=True)
            except Exception as e:
                # error message for the user
                if deployment:
                    add_info = ' for deployment {0}'.format(deployment.id)
                else:
                    add_info = ''
                error_msg = 'Error occurred while executing the {0} ' \
                            'system workflow{1}: {2} - {3}'.format(
                                wf_id, add_info, type(e).__name__, e)
                # adding traceback to the log error message
                tb = StringIO()
                traceback.print_exc(file=tb)
                log_error_msg = '{0}; traceback: {1}'.format(
                    error_msg, tb.getvalue())
                current_app.logger.error(log_error_msg)
                raise RuntimeError(error_msg)

            # verify the execution completed successfully
            execution = self.sm.get_execution(async_task.id)
            if execution.status != models.Execution.TERMINATED:
                raise RuntimeError(
                    'Failed executing the {0} system workflow: '
                    'Execution did not complete successfully before '
                    'timeout ({1} seconds)'.format(wf_id, timeout))

        return async_task, execution
    def execute_workflow(self,
                         deployment_id,
                         workflow_id,
                         parameters=None,
                         allow_custom_parameters=False,
                         force=False):
        deployment = self.get_deployment(deployment_id)

        if workflow_id not in deployment.workflows:
            raise manager_exceptions.NonexistentWorkflowError(
                'Workflow {0} does not exist in deployment {1}'.format(
                    workflow_id, deployment_id))
        workflow = deployment.workflows[workflow_id]

        self._verify_deployment_environment_created_successfully(deployment_id)

        transient_workers_config =\
            self._get_transient_deployment_workers_mode_config()
        is_transient_workers_enabled = transient_workers_config['enabled']

        self._check_for_active_system_wide_execution()
        self._check_for_active_executions(deployment_id, force,
                                          transient_workers_config)

        execution_parameters = \
            BlueprintsManager._merge_and_validate_execution_parameters(
                workflow, workflow_id, parameters, allow_custom_parameters)

        if is_transient_workers_enabled:
            # in this mode, we push the user execution object to storage
            # before executing the "_start_deployment_environment" system
            # workflow, to prevent from other executions to start running in
            # between the system workflow and the user workflow execution.
            # to keep correct chronological order, the system workflow's
            # "created_at" field is generated here.
            start_deployment_env_created_at_time = str(datetime.now())

        execution_id = str(uuid.uuid4())

        new_execution = models.Execution(
            id=execution_id,
            status=models.Execution.PENDING,
            created_at=str(datetime.now()),
            blueprint_id=deployment.blueprint_id,
            workflow_id=workflow_id,
            deployment_id=deployment_id,
            error='',
            parameters=self._get_only_user_execution_parameters(
                execution_parameters),
            is_system_workflow=False)

        self.sm.put_execution(new_execution.id, new_execution)

        if is_transient_workers_enabled:
            # initiating a workflow to start deployment workers
            wf_id = '_start_deployment_environment'
            deployment_env_start_task_name = \
                'cloudify_system_workflows.deployment_environment.start'

            self._execute_system_workflow(
                wf_id=wf_id,
                task_mapping=deployment_env_start_task_name,
                deployment=deployment,
                timeout=300,
                created_at=start_deployment_env_created_at_time)

        # executing the user workflow
        self.workflow_client.execute_workflow(
            workflow_id,
            workflow,
            blueprint_id=deployment.blueprint_id,
            deployment_id=deployment_id,
            execution_id=execution_id,
            execution_parameters=execution_parameters)

        return new_execution