def run_operation(operation, nodes_type_update, operation_kwargs, **kwargs): graph = ctx.graph_mode() send_event_starting_tasks = {} send_event_done_tasks = {} for node_type_update in nodes_type_update: for node in ctx.nodes: if node.type == node_type_update: for instance in node.instances: send_event_starting_tasks[instance.id] = instance.send_event('Starting to run operation') send_event_done_tasks[instance.id] = instance.send_event('Done running operation') for node_type_update in nodes_type_update: previous_task = None for node in ctx.nodes: if node.type == node_type_update: for instance in node.instances: sequence = graph.sequence() #operation_task = instance.execute_operation(operation, kwargs=operation_kwargs) forkjoin_tasks_unlink = [] for relationship in instance.relationships: if relationship.relationship.target_id == 'bind': operation_unlink = 'cloudify.interfaces.relationship_lifecycle.unlink' forkjoin_tasks_unlink.append(relationship.execute_source_operation(operation_unlink)) forkjoin_tasks_unlink.append(relationship.execute_target_operation(operation_unlink)) operation_task_unlink = forkjoin(*forkjoin_tasks_unlink) forkjoin_tasks_link = [] for relationship in instance.relationships: if relationship.relationship.target_id == 'bind': operation_link = 'cloudify.interfaces.relationship_lifecycle.establish' forkjoin_tasks_link.append(relationship.execute_source_operation(operation_link)) forkjoin_tasks_link.append(relationship.execute_target_operation(operation_link)) operation_task_link = forkjoin(*forkjoin_tasks_link) sequence.add( send_event_starting_tasks[instance.id], operation_task_unlink, instance.execute_operation('cloudify.interfaces.lifecycle.update', kwargs=operation_kwargs), operation_task_link, send_event_done_tasks[instance.id]) if previous_task: graph.add_dependency(send_event_starting_tasks.get(instance.id), send_event_done_tasks.get(previous_task)) with open("/file_out.txt", "w") as f: pprint.pprint(previous_task, f) previous_task = instance.id return graph.execute()
def install_node_instance_subgraph(instance, graph, **kwargs): """This function is used to create a tasks sequence installing one node instance. Considering the order of tasks executions, it enforces the proper dependencies only in context of this particular node instance. :param instance: node instance to generate the installation tasks for """ subgraph = graph.subgraph('install_{0}'.format(instance.id)) sequence = subgraph.sequence() sequence.add( instance.set_state('initializing'), forkjoin(instance.send_event('Creating node'), instance.set_state('creating')), instance.execute_operation('cloudify.interfaces.lifecycle.create'), instance.set_state('created'), _relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.preconfigure' ), forkjoin(instance.set_state('configuring'), instance.send_event('Configuring node')), instance.execute_operation('cloudify.interfaces.lifecycle.configure'), instance.set_state('configured'), _relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.postconfigure' ), forkjoin(instance.set_state('starting'), instance.send_event('Starting node')), instance.execute_operation('cloudify.interfaces.lifecycle.start')) # If this is a host node, we need to add specific host start # tasks such as waiting for it to start and installing the agent # worker (if necessary) if is_host_node(instance): sequence.add(*_host_post_start(instance)) sequence.add( instance.execute_operation('cloudify.interfaces.monitoring.start'), _relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.establish' ), instance.set_state('started')) subgraph.on_failure = get_subgraph_on_failure_handler(instance) return subgraph
def install_node_instance_subgraph(instance, graph): """This function is used to create a tasks sequence installing one node instance. Considering the order of tasks executions, it enforces the proper dependencies only in context of this particular node instance. :param instance: node instance to generate the installation tasks for """ subgraph = graph.subgraph('install_{0}'.format(instance.id)) sequence = subgraph.sequence() sequence.add( instance.set_state('initializing'), forkjoin(instance.send_event('Creating node'), instance.set_state('creating')), instance.execute_operation('cloudify.interfaces.lifecycle.create'), instance.set_state('created'), _relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.preconfigure' ), forkjoin(instance.set_state('configuring'), instance.send_event('Configuring node')), instance.execute_operation('cloudify.interfaces.lifecycle.configure'), instance.set_state('configured'), _relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.postconfigure' ), forkjoin(instance.set_state('starting'), instance.send_event('Starting node')), instance.execute_operation('cloudify.interfaces.lifecycle.start')) # If this is a host node, we need to add specific host start # tasks such as waiting for it to start and installing the agent # worker (if necessary) if is_host_node(instance): sequence.add(*_host_post_start(instance)) sequence.add( instance.execute_operation('cloudify.interfaces.monitoring.start'), _relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.establish' ), instance.set_state('started')) subgraph.on_failure = get_install_subgraph_on_failure_handler(instance) return subgraph
def uninstall_node_instance_subgraph(instance, graph): subgraph = graph.subgraph(instance.id) sequence = subgraph.sequence() sequence.add( instance.set_state('stopping'), instance.send_event('Stopping node'), instance.execute_operation('cloudify.interfaces.monitoring.stop') ) if is_host_node(instance): sequence.add(*_host_pre_stop(instance)) sequence.add( instance.execute_operation('cloudify.interfaces.lifecycle.stop'), instance.set_state('stopped'), forkjoin(*_relationships_operations( instance, 'cloudify.interfaces.relationship_lifecycle.unlink')), instance.set_state('deleting'), instance.send_event('Deleting node'), instance.execute_operation('cloudify.interfaces.lifecycle.delete'), instance.set_state('deleted') ) for task in subgraph.tasks.itervalues(): set_send_node_event_on_error_handler(task, instance) return subgraph
def uninstall_node_instance_subgraph(instance, graph): subgraph = graph.subgraph(instance.id) sequence = subgraph.sequence() sequence.add( instance.set_state('stopping'), instance.send_event('Stopping node'), instance.execute_operation('cloudify.interfaces.monitoring.stop') ) if _is_host_node(instance): sequence.add(*_host_pre_stop(instance)) sequence.add( instance.execute_operation('cloudify.interfaces.lifecycle.stop'), instance.set_state('stopped'), forkjoin(*_relationships_operations( instance, 'cloudify.interfaces.relationship_lifecycle.unlink')), instance.set_state('deleting'), instance.send_event('Deleting node'), instance.execute_operation('cloudify.interfaces.lifecycle.delete'), instance.set_state('deleted') ) for task in subgraph.tasks.itervalues(): set_send_node_event_on_error_handler(task, instance) return subgraph
def _relationships_operations(graph, node_instance, operation, reverse=False, modified_relationship_ids=None): relationships_groups = itertools.groupby( node_instance.relationships, key=lambda r: r.relationship.target_id) tasks = [] for _, relationship_group in relationships_groups: group_tasks = [] for relationship in relationship_group: # either the relationship ids aren't specified, or all the # relationship should be added source_id = relationship.node_instance.node.id target_id = relationship.target_node_instance.node.id if (not modified_relationship_ids or (source_id in modified_relationship_ids and target_id in modified_relationship_ids[source_id])): group_tasks += [ op for op in _relationship_operations(relationship, operation) if not op.is_nop() ] if group_tasks: tasks.append(forkjoin(*group_tasks)) if not tasks: return if reverse: tasks = reversed(tasks) result = graph.subgraph('{0}_subgraph'.format(operation)) result.on_failure = _relationship_subgraph_on_failure sequence = result.sequence() sequence.add(*tasks) return result
def _execute_one_operation(instance, operation, is_node_operation, operation_kwargs): if is_node_operation: operation_task = instance.execute_operation(operation, kwargs=operation_kwargs) else: forkjoin_tasks = [] for relationship in instance.relationships: forkjoin_tasks.append(relationship.execute_source_operation(operation)) forkjoin_tasks.append(relationship.execute_target_operation(operation)) operation_task = forkjoin(*forkjoin_tasks) return operation_task
def create(self, instance, graph, uninstallation_tasks): unlink_tasks_with_target_ids = _relationship_operations_with_targets( instance, 'cloudify.interfaces.relationship_lifecycle.unlink') sequence = graph.sequence() sequence.add( uninstallation_tasks.set_state_stopping[instance.id], instance.send_event('Stopping node') ) if _is_host_node(instance): sequence.add(*_host_pre_stop(instance)) sequence.add( uninstallation_tasks.stop_node[instance.id], instance.set_state('stopped'), forkjoin(*[task for task, _ in unlink_tasks_with_target_ids]), instance.set_state('deleting'), instance.send_event('Deleting node'), uninstallation_tasks.delete_node[instance.id], uninstallation_tasks.set_state_deleted[instance.id] ) # adding the stop monitor task not as a part of the sequence, # as it can happen in parallel with any other task, and is only # dependent on the set node state 'stopping' task graph.add_task(uninstallation_tasks.stop_monitor[instance.id]) graph.add_dependency( uninstallation_tasks.stop_monitor[instance.id], uninstallation_tasks.set_state_stopping[instance.id] ) # augmenting the stop node, stop monitor and delete node tasks with # error handlers _set_send_node_event_on_error_handler( uninstallation_tasks.stop_node[instance.id], instance, "Error occurred while stopping node - ignoring...") _set_send_node_event_on_error_handler( uninstallation_tasks.stop_monitor[instance.id], instance, "Error occurred while stopping monitor - ignoring...") _set_send_node_event_on_error_handler( uninstallation_tasks.delete_node[instance.id], instance, "Error occurred while deleting node - ignoring...") _set_send_node_evt_on_failed_unlink_handlers( instance, unlink_tasks_with_target_ids)
def create(self, instance, graph, installation_tasks): """ :param installation_tasks: instance of InstallationTasksReferences :param instance: node instance to generate the installation tasks for """ sequence = graph.sequence() sequence.add( instance.set_state('initializing'), forkjoin( installation_tasks.set_state_creating[instance.id], installation_tasks.send_event_creating[instance.id] ), instance.execute_operation('cloudify.interfaces.lifecycle.create'), instance.set_state('created'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.preconfigure' )), forkjoin( instance.set_state('configuring'), instance.send_event('Configuring node') ), instance.execute_operation( 'cloudify.interfaces.lifecycle.configure'), instance.set_state('configured'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.postconfigure' )), forkjoin( instance.set_state('starting'), instance.send_event('Starting node') ), instance.execute_operation('cloudify.interfaces.lifecycle.start')) # If this is a host node, we need to add specific host start # tasks such as waiting for it to start and installing the agent # worker (if necessary) if _is_host_node(instance): sequence.add(*_host_post_start(instance)) sequence.add( forkjoin( instance.execute_operation( 'cloudify.interfaces.monitoring.start'), *_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.establish' )), installation_tasks.set_state_started[instance.id])
def _relationships_operations(graph, node_instance, operation, reverse=False, modified_relationship_ids=None): def on_failure(subgraph): for task in subgraph.tasks.values(): subgraph.remove_task(task) handler_result = workflow_tasks.HandlerResult.ignore() subgraph.containing_subgraph.failed_task = subgraph.failed_task subgraph.containing_subgraph.set_state(workflow_tasks.TASK_FAILED) return handler_result relationships_groups = itertools.groupby( node_instance.relationships, key=lambda r: r.relationship.target_id) tasks = [] for _, relationship_group in relationships_groups: group_tasks = [] for relationship in relationship_group: # either the relationship ids aren't specified, or all the # relationship should be added source_id = relationship.node_instance.node.id target_id = relationship.target_node_instance.node.id if (not modified_relationship_ids or (source_id in modified_relationship_ids and target_id in modified_relationship_ids[source_id])): group_tasks += [ op for op in _relationship_operations(relationship, operation) if not op.is_nop() ] if group_tasks: tasks.append(forkjoin(*group_tasks)) if not tasks: return if reverse: tasks = reversed(tasks) result = graph.subgraph('{0}_subgraph'.format(operation)) result.on_failure = on_failure sequence = result.sequence() sequence.add(*tasks) return result
def _relationships_operations(graph, node_instance, operation, reverse=False, modified_relationship_ids=None): def on_failure(subgraph): for task in subgraph.tasks.itervalues(): subgraph.remove_task(task) handler_result = workflow_tasks.HandlerResult.ignore() subgraph.containing_subgraph.failed_task = subgraph.failed_task subgraph.containing_subgraph.set_state(workflow_tasks.TASK_FAILED) return handler_result result = graph.subgraph('{0}_subgraph'.format(operation)) result.on_failure = on_failure sequence = result.sequence() relationships_groups = itertools.groupby( node_instance.relationships, key=lambda r: r.relationship.target_id) tasks = [] for _, relationship_group in relationships_groups: group_tasks = [] for relationship in relationship_group: # either the relationship ids aren't specified, or all the # relationship should be added source_id = relationship.node_instance.node.id target_id = relationship.target_node_instance.node.id if (not modified_relationship_ids or (source_id in modified_relationship_ids and target_id in modified_relationship_ids[source_id])): group_tasks += _relationship_operations(relationship, operation) tasks.append(forkjoin(*group_tasks)) if reverse: tasks = reversed(tasks) sequence.add(*tasks) return result
def install(ctx, **kwargs): """Default install workflow""" # switch to graph mode (operations on the context return tasks instead of # result instances) graph = ctx.graph_mode() # We need reference to the create event/state tasks and the started # task so we can later create a proper dependency between nodes and # their relationships. We use the below tasks as part of a single node # workflow, and to create the dependency (at the bottom) send_event_creating_tasks = {} set_state_creating_tasks = {} set_state_started_tasks = {} for node in ctx.nodes: for instance in node.instances: send_event_creating_tasks[instance.id] = instance.send_event( 'Creating node') set_state_creating_tasks[instance.id] = instance.set_state( 'creating') set_state_started_tasks[instance.id] = instance.set_state( 'started') # Create node linear task sequences # For each node, we create a "task sequence" in which all tasks # added to it will be executed in a sequential manner for node in ctx.nodes: for instance in node.instances: sequence = graph.sequence() sequence.add( instance.set_state('initializing'), forkjoin( set_state_creating_tasks[instance.id], send_event_creating_tasks[instance.id] ), instance.execute_operation( 'cloudify.interfaces.lifecycle.create'), instance.set_state('created'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.preconfigure' )), forkjoin( instance.set_state('configuring'), instance.send_event('Configuring node')), instance.execute_operation( 'cloudify.interfaces.lifecycle.configure'), instance.set_state('configured'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.postconfigure' )), forkjoin( instance.set_state('starting'), instance.send_event('Starting node')), instance.execute_operation( 'cloudify.interfaces.lifecycle.start')) # If this is a host node, we need to add specific host start # tasks such as waiting for it to start and installing the agent # worker (if necessary) if _is_host_node(instance): sequence.add(*_host_post_start(instance)) sequence.add( set_state_started_tasks[instance.id], forkjoin( instance.execute_operation( 'cloudify.interfaces.monitor_lifecycle.start'), *_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.establish' ))) # Create task dependencies based on node relationships # for each node, make a dependency between the create tasks (event, state) # and the started state task of the target for node in ctx.nodes: for instance in node.instances: for rel in instance.relationships: node_set_creating = set_state_creating_tasks[instance.id] node_event_creating = send_event_creating_tasks[instance.id] target_set_started = set_state_started_tasks[rel.target_id] graph.add_dependency(node_set_creating, target_set_started) graph.add_dependency(node_event_creating, target_set_started) return graph.execute()
def uninstall(ctx, **kwargs): """Default uninstall workflow""" # switch to graph mode (operations on the context return tasks instead of # result instances) graph = ctx.graph_mode() set_state_stopping_tasks = {} set_state_deleted_tasks = {} stop_node_tasks = {} stop_monitor_tasks = {} delete_node_tasks = {} for node in ctx.nodes: for instance in node.instances: # We need reference to the set deleted state tasks and the set # stopping state tasks so we can later create a proper dependency # between nodes and their relationships. We use the below tasks as # part of a single node workflow, and to create the dependency # (at the bottom) set_state_stopping_tasks[instance.id] = instance.set_state( 'stopping') set_state_deleted_tasks[instance.id] = instance.set_state( 'deleted') # We need reference to the stop node tasks, stop monitor tasks and # delete node tasks as we augment them with on_failure error # handlers # later on stop_node_tasks[instance.id] = instance.execute_operation( 'cloudify.interfaces.lifecycle.stop') stop_monitor_tasks[instance.id] = instance.execute_operation( 'cloudify.interfaces.monitor_lifecycle.stop') delete_node_tasks[instance.id] = instance.execute_operation( 'cloudify.interfaces.lifecycle.delete') # Create node linear task sequences # For each node, we create a "task sequence" in which all tasks # added to it will be executed in a sequential manner for node in ctx.nodes: for instance in node.instances: sequence = graph.sequence() sequence.add(set_state_stopping_tasks[instance.id], instance.send_event('Stopping node')) if _is_host_node(instance): sequence.add(*_host_pre_stop(instance)) sequence.add(stop_node_tasks[instance.id], instance.set_state('stopped'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle' '.unlink')), instance.set_state('deleting'), instance.send_event('Deleting node'), delete_node_tasks[instance.id], set_state_deleted_tasks[instance.id]) # adding the stop monitor task not as a part of the sequence, # as it can happen in parallel with any other task, and is only # dependent on the set node state 'stopping' task graph.add_task(stop_monitor_tasks[instance.id]) graph.add_dependency(stop_monitor_tasks[instance.id], set_state_stopping_tasks[instance.id]) # augmenting the stop node, stop monitor and delete node tasks with # error handlers _set_send_node_event_on_error_handler( stop_node_tasks[instance.id], instance, "Error occurred while stopping node - ignoring...") _set_send_node_event_on_error_handler( stop_monitor_tasks[instance.id], instance, "Error occurred while stopping monitor - ignoring...") _set_send_node_event_on_error_handler( delete_node_tasks[instance.id], instance, "Error occurred while deleting node - ignoring...") # Create task dependencies based on node relationships # for each node, make a dependency between the target's stopping task # and the deleted state task of the current node for node in ctx.nodes: for instance in node.instances: for rel in instance.relationships: target_set_stopping = set_state_stopping_tasks[rel.target_id] node_set_deleted = set_state_deleted_tasks[instance.id] graph.add_dependency(target_set_stopping, node_set_deleted) return graph.execute()
def install_node_instance_subgraph(ctx,instance, graph, hist=None): """This function is used to create a tasks sequence installing one node instance. Considering the order of tasks executions, it enforces the proper dependencies only in context of this particular node instance. :param instance: node instance to generate the installation tasks for """ subgraph = graph.subgraph('install_{0}'.format(instance.id)) ct=None if hist: #get completed tasks for instance ct=_completed_tasks(ctx,hist,instance.id) sequence = subgraph.sequence() #CREATE run=True if(hist and 'create' in ct): run=False ctx.logger.info("run={} CREATE {}".format(str(run),instance.id)) if(run): ctx.logger.info(" hist={} ct={}".format(str(hist),str(ct))) if(run): sequence.add( instance.set_state('initializing'), forkjoin(instance.send_event('Creating node'), instance.set_state('creating')), _add_es_log(ctx,instance,'create',instance.execute_operation('cloudify.interfaces.lifecycle.create')), instance.set_state('created'), forkjoin(*_relationships_operations( instance, 'cloudify.interfaces.relationship_lifecycle.preconfigure' ))) #CONFIGURE run=True if(hist and 'configure' in ct): run=False ctx.logger.info("run={} CONFIGURE {}".format(str(run),instance.id)) if(run): sequence.add( forkjoin(instance.set_state('configuring'), instance.send_event('Configuring node')), _add_es_log(ctx,instance,'configure',instance.execute_operation('cloudify.interfaces.lifecycle.configure')), instance.set_state('configured'), forkjoin(*_relationships_operations( instance, 'cloudify.interfaces.relationship_lifecycle.postconfigure' ))) # STARTING run=True if(hist and 'start' in ct): run=False ctx.logger.info("run={} START {}".format(str(run),instance.id)) if(run): sequence.add( forkjoin(instance.set_state('starting'), instance.send_event('Starting node')), instance.execute_operation('cloudify.interfaces.lifecycle.start')) # If this is a host node, we need to add specific host start # tasks such as waiting for it to start and installing the agent # worker (if necessary) if run and is_host_node(instance): sequence.add(*_host_post_start(instance)) sequence.add( forkjoin( _add_es_log(ctx,instance,'start',instance.execute_operation('cloudify.interfaces.monitoring.start')), *_relationships_operations( instance, 'cloudify.interfaces.relationship_lifecycle.establish' )), instance.set_state('started')) subgraph.on_failure = get_install_subgraph_on_failure_handler(ctx,instance) return subgraph
def uninstall(ctx, **kwargs): """Default uninstall workflow""" # switch to graph mode (operations on the context return tasks instead of # result instances) graph = ctx.graph_mode() set_state_stopping_tasks = {} set_state_deleted_tasks = {} stop_node_tasks = {} stop_monitor_tasks = {} delete_node_tasks = {} for node in ctx.nodes: for instance in node.instances: # We need reference to the set deleted state tasks and the set # stopping state tasks so we can later create a proper dependency # between nodes and their relationships. We use the below tasks as # part of a single node workflow, and to create the dependency # (at the bottom) set_state_stopping_tasks[instance.id] = instance.set_state( 'stopping') set_state_deleted_tasks[instance.id] = instance.set_state( 'deleted') # We need reference to the stop node tasks, stop monitor tasks and # delete node tasks as we augment them with on_failure error # handlers # later on stop_node_tasks[instance.id] = instance.execute_operation( 'cloudify.interfaces.lifecycle.stop') stop_monitor_tasks[instance.id] = instance.execute_operation( 'cloudify.interfaces.monitor_lifecycle.stop') delete_node_tasks[instance.id] = instance.execute_operation( 'cloudify.interfaces.lifecycle.delete') # Create node linear task sequences # For each node, we create a "task sequence" in which all tasks # added to it will be executed in a sequential manner for node in ctx.nodes: for instance in node.instances: sequence = graph.sequence() sequence.add(set_state_stopping_tasks[instance.id], instance.send_event('Stopping node')) if _is_host_node(instance): sequence.add(*_host_pre_stop(instance)) sequence.add( stop_node_tasks[instance.id], instance.set_state('stopped'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle' '.unlink')), instance.set_state('deleting'), instance.send_event('Deleting node'), delete_node_tasks[instance.id], set_state_deleted_tasks[instance.id]) # adding the stop monitor task not as a part of the sequence, # as it can happen in parallel with any other task, and is only # dependent on the set node state 'stopping' task graph.add_task(stop_monitor_tasks[instance.id]) graph.add_dependency(stop_monitor_tasks[instance.id], set_state_stopping_tasks[instance.id]) # augmenting the stop node, stop monitor and delete node tasks with # error handlers _set_send_node_event_on_error_handler( stop_node_tasks[instance.id], instance, "Error occurred while stopping node - ignoring...") _set_send_node_event_on_error_handler( stop_monitor_tasks[instance.id], instance, "Error occurred while stopping monitor - ignoring...") _set_send_node_event_on_error_handler( delete_node_tasks[instance.id], instance, "Error occurred while deleting node - ignoring...") # Create task dependencies based on node relationships # for each node, make a dependency between the target's stopping task # and the deleted state task of the current node for node in ctx.nodes: for instance in node.instances: for rel in instance.relationships: target_set_stopping = set_state_stopping_tasks[rel.target_id] node_set_deleted = set_state_deleted_tasks[instance.id] graph.add_dependency(target_set_stopping, node_set_deleted) return graph.execute()
def uninstall_node_instance_subgraph(instance, graph, ignore_failure=False): subgraph = graph.subgraph(instance.id) sequence = subgraph.sequence() def set_ignore_handlers(_subgraph): for task in _subgraph.tasks.values(): if task.is_subgraph: set_ignore_handlers(task) else: set_send_node_event_on_error_handler(task, instance) # Remove unneeded operations instance_state = instance.state if instance_state in ['stopped', 'deleting', 'deleted', 'uninitialized']: stop_message = [] monitoring_stop = [] host_pre_stop = [] prestop = [] deletion_validation = [] stop = [ instance.send_event( 'Stop: instance already {0}'.format(instance_state)) ] else: stop_message = [ forkjoin(instance.set_state('stopping'), instance.send_event('Stopping node instance')) ] monitoring_stop = _skip_nop_operations( instance.execute_operation('cloudify.interfaces.monitoring.stop')) # Only exists in >= 5.0. if 'cloudify.interfaces.validation.delete' in instance.node.operations: deletion_validation = _skip_nop_operations( pre=instance.send_event( 'Validating node instance before deletion'), task=instance.execute_operation( 'cloudify.interfaces.validation.delete'), post=instance.send_event( 'Node instance validated before deletion')) else: deletion_validation = [] # Only exists in >= 5.0. if 'cloudify.interfaces.lifecycle.prestop' in instance.node.operations: prestop = _skip_nop_operations( pre=instance.send_event('Prestopping node instance'), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.prestop'), post=instance.send_event('Node instance prestopped')) else: prestop = [] if is_host_node(instance): host_pre_stop = _host_pre_stop(instance) else: host_pre_stop = [] stop = _skip_nop_operations( task=instance.execute_operation( 'cloudify.interfaces.lifecycle.stop'), post=instance.send_event('Stopped node instance')) if instance_state in ['stopped', 'deleting', 'deleted']: stopped_set_state = [] else: stopped_set_state = [instance.set_state('stopped')] if instance_state in ['deleted', 'uninitialized']: unlink = [] postdelete = [] delete = [ instance.send_event( 'Delete: instance already {0}'.format(instance_state)) ] else: unlink = _skip_nop_operations( pre=instance.send_event('Unlinking relationships'), task=_relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.unlink', reverse=True), post=instance.send_event('Relationships unlinked')) delete = _skip_nop_operations( pre=forkjoin(instance.set_state('deleting'), instance.send_event('Deleting node instance')), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.delete')) # Only exists in >= 5.0. if 'cloudify.interfaces.lifecycle.postdelete'\ in instance.node.operations: postdelete = _skip_nop_operations( pre=instance.send_event('Postdeleting node instance'), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.postdelete'), post=instance.send_event('Node instance postdeleted')) else: postdelete = [] if instance_state in ['deleted']: finish_message = [] else: finish_message = [ forkjoin(instance.set_state('deleted'), instance.send_event('Deleted node instance')) ] tasks = ( stop_message + (deletion_validation or [ instance.send_event('Validating node instance after deletion: ' 'nothing to do') ]) + monitoring_stop + prestop + host_pre_stop + (stop or [instance.send_event('Stopped node instance: nothing to do')]) + stopped_set_state + unlink + (delete or [instance.send_event('Deleting node instance: nothing to do')]) + postdelete + finish_message) sequence.add(*tasks) if ignore_failure: set_ignore_handlers(subgraph) else: subgraph.on_failure = get_subgraph_on_failure_handler( instance, uninstall_node_instance_subgraph) return subgraph
def install_node_instance_subgraph(instance, graph, **kwargs): """This function is used to create a tasks sequence installing one node instance. Considering the order of tasks executions, it enforces the proper dependencies only in context of this particular node instance. :param instance: node instance to generate the installation tasks for """ subgraph = graph.subgraph('install_{0}'.format(instance.id)) sequence = subgraph.sequence() instance_state = instance.state if instance_state in [ 'started', 'starting', 'created', 'creating', 'configured', 'configuring' ]: creation_validation = [] precreate = [] else: # Only exists in >= 5.0. if 'cloudify.interfaces.validation.create' in instance.node.operations: creation_validation = _skip_nop_operations( pre=instance.send_event( 'Validating node instance before creation'), task=instance.execute_operation( 'cloudify.interfaces.validation.create'), post=instance.send_event( 'Node instance validated before creation')) else: creation_validation = [] # Only exists in >= 5.0. if 'cloudify.interfaces.lifecycle.precreate' \ in instance.node.operations: precreate = _skip_nop_operations( pre=instance.send_event('Precreating node instance'), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.precreate'), post=instance.send_event('Node instance precreated')) else: precreate = [] if instance_state in [ 'started', 'starting', 'created', 'configuring', 'configured' ]: create = [] else: create = _skip_nop_operations( pre=forkjoin(instance.send_event('Creating node instance'), instance.set_state('creating')), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.create'), post=forkjoin(instance.send_event('Node instance created'), instance.set_state('created'))) if instance_state in ['started', 'starting', 'configured']: preconf = [] configure = [] else: preconf = _skip_nop_operations( pre=instance.send_event('Pre-configuring relationships'), task=_relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.preconfigure'), post=instance.send_event('Relationships pre-configured')) configure = _skip_nop_operations( pre=forkjoin(instance.set_state('configuring'), instance.send_event('Configuring node instance')), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.configure'), post=forkjoin(instance.set_state('configured'), instance.send_event('Node instance configured'))) if instance_state == 'started': postconf = [] host_post_start = [] poststart = [] monitoring_start = [] establish = [] start = [] else: postconf = _skip_nop_operations( pre=instance.send_event('Post-configuring relationships'), task=_relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.postconfigure'), post=instance.send_event('Relationships post-configured')) start = _skip_nop_operations( pre=forkjoin(instance.set_state('starting'), instance.send_event('Starting node instance')), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.start')) # If this is a host node, we need to add specific host start # tasks such as waiting for it to start and installing the agent # worker (if necessary) if is_host_node(instance): host_post_start = _host_post_start(instance) else: host_post_start = [] # Only exists in >= 5.0. if 'cloudify.interfaces.lifecycle.poststart' \ in instance.node.operations: poststart = _skip_nop_operations( pre=instance.send_event('Poststarting node instance'), task=instance.execute_operation( 'cloudify.interfaces.lifecycle.poststart'), post=instance.send_event('Node instance poststarted')) else: poststart = [] monitoring_start = _skip_nop_operations( instance.execute_operation('cloudify.interfaces.monitoring.start')) establish = _skip_nop_operations( pre=instance.send_event('Establishing relationships'), task=_relationships_operations( subgraph, instance, 'cloudify.interfaces.relationship_lifecycle.establish'), post=instance.send_event('Relationships established')) if any([ creation_validation, precreate, create, preconf, configure, postconf, start, host_post_start, poststart, monitoring_start, establish ]): tasks = ([ instance.set_state('initializing') ] + (creation_validation or [ instance.send_event('Validating node instance before creation: ' 'nothing to do') ]) + (precreate or [ instance.send_event('Precreating node instance: nothing to do') ]) + (create or [ instance.send_event('Creating node instance: nothing to do') ]) + preconf + (configure or [ instance.send_event('Configuring node instance: nothing to do') ]) + postconf + (start or [ instance.send_event('Starting node instance: nothing to do') ]) + host_post_start + (poststart or [ instance.send_event('Poststarting node instance: nothing to do') ]) + monitoring_start + establish + [ forkjoin(instance.set_state('started'), instance.send_event('Node instance started')) ]) else: tasks = [ forkjoin( instance.set_state('started'), instance.send_event('Node instance started (nothing to do)')) ] sequence.add(*tasks) subgraph.on_failure = get_subgraph_on_failure_handler(instance) return subgraph
def run_operation(operation, nodes_types_list, nodes_types_dependency, relations_unlink, operation_kwargs, **kwargs): graph = ctx.graph_mode() send_event_starting_tasks = {} send_event_done_tasks = {} for node_type_update in nodes_types_list: for node in ctx.nodes: if node.type == node_type_update: for instance in node.instances: send_event_starting_tasks[ instance.id] = instance.send_event( 'Starting to run operation') send_event_done_tasks[instance.id] = instance.send_event( 'Done running operation') previous_task = None for node_type_update in nodes_types_list: if not nodes_types_dependency: previous_task = None for node in ctx.nodes: if node.type == node_type_update: for instance in node.instances: sequence = graph.sequence() #operation_task = instance.execute_operation(operation, kwargs=operation_kwargs) forkjoin_tasks_unlink = [] for relationship in instance.relationships: ctx.logger.info(relationship.relationship.target_id) if relationship.relationship.target_id in relations_unlink: operation_unlink = 'cloudify.interfaces.relationship_lifecycle.unlink' forkjoin_tasks_unlink.append( relationship.execute_source_operation( operation_unlink)) forkjoin_tasks_unlink.append( relationship.execute_target_operation( operation_unlink)) operation_task_unlink = forkjoin(*forkjoin_tasks_unlink) forkjoin_tasks_link = [] for relationship in instance.relationships: if relationship.relationship.target_id in relations_unlink: ctx.logger.info('rel op') operation_link = 'cloudify.interfaces.relationship_lifecycle.establish' forkjoin_tasks_link.append( relationship.execute_source_operation( operation_link)) forkjoin_tasks_link.append( relationship.execute_target_operation( operation_link)) operation_task_link = forkjoin(*forkjoin_tasks_link) sequence.add( send_event_starting_tasks[instance.id], operation_task_unlink, instance.execute_operation( 'cloudify.interfaces.lifecycle.stop', kwargs=operation_kwargs), instance.execute_operation( 'cloudify.interfaces.lifecycle.upgrade', kwargs=operation_kwargs), instance.execute_operation( 'cloudify.interfaces.lifecycle.start', kwargs=operation_kwargs), operation_task_link, send_event_done_tasks[instance.id]) if previous_task: graph.add_dependency( send_event_starting_tasks.get(instance.id), send_event_done_tasks.get(previous_task)) with open("/etc/cloudify/file_out.txt", "w") as f: pprint.pprint(previous_task, f) previous_task = instance.id return graph.execute()
def install(ctx, **kwargs): """Default install workflow""" # switch to graph mode (operations on the context return tasks instead of # result instances) graph = ctx.graph_mode() # We need reference to the create event/state tasks and the started # task so we can later create a proper dependency between nodes and # their relationships. We use the below tasks as part of a single node # workflow, and to create the dependency (at the bottom) send_event_creating_tasks = {} set_state_creating_tasks = {} set_state_started_tasks = {} for node in ctx.nodes: for instance in node.instances: send_event_creating_tasks[instance.id] = instance.send_event( 'Creating node') set_state_creating_tasks[instance.id] = instance.set_state( 'creating') set_state_started_tasks[instance.id] = instance.set_state( 'started') # Create node linear task sequences # For each node, we create a "task sequence" in which all tasks # added to it will be executed in a sequential manner for node in ctx.nodes: for instance in node.instances: sequence = graph.sequence() sequence.add( instance.set_state('initializing'), forkjoin(set_state_creating_tasks[instance.id], send_event_creating_tasks[instance.id]), instance.execute_operation( 'cloudify.interfaces.lifecycle.create'), instance.set_state('created'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.preconfigure') ), forkjoin(instance.set_state('configuring'), instance.send_event('Configuring node')), instance.execute_operation( 'cloudify.interfaces.lifecycle.configure'), instance.set_state('configured'), forkjoin(*_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.postconfigure') ), forkjoin(instance.set_state('starting'), instance.send_event('Starting node')), instance.execute_operation( 'cloudify.interfaces.lifecycle.start')) # If this is a host node, we need to add specific host start # tasks such as waiting for it to start and installing the agent # worker (if necessary) if _is_host_node(instance): sequence.add(*_host_post_start(instance)) sequence.add( set_state_started_tasks[instance.id], forkjoin( instance.execute_operation( 'cloudify.interfaces.monitor_lifecycle.start'), *_relationship_operations( instance, 'cloudify.interfaces.relationship_lifecycle.establish') )) # Create task dependencies based on node relationships # for each node, make a dependency between the create tasks (event, state) # and the started state task of the target for node in ctx.nodes: for instance in node.instances: for rel in instance.relationships: node_set_creating = set_state_creating_tasks[instance.id] node_event_creating = send_event_creating_tasks[instance.id] target_set_started = set_state_started_tasks[rel.target_id] graph.add_dependency(node_set_creating, target_set_started) graph.add_dependency(node_event_creating, target_set_started) return graph.execute()