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()
Exemple #2
0
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
Exemple #4
0
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
Exemple #6
0
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, 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 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])
Exemple #12
0
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
Exemple #14
0
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()
Exemple #15
0
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()
Exemple #16
0
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
Exemple #17
0
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()
Exemple #18
0
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
Exemple #19
0
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
Exemple #20
0
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()
Exemple #21
0
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()