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
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
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