Skip to content
This repository has been archived by the owner on Oct 5, 2020. It is now read-only.

Commit

Permalink
Merge pull request #115 from cloudify-cosmo/CFY-2788-relationship-op-fix
Browse files Browse the repository at this point in the history
CFY-2788 only run operation matching target
  • Loading branch information
dankilman committed May 25, 2015
2 parents 755a224 + 541d8af commit 0a46b3a
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 15 deletions.
32 changes: 17 additions & 15 deletions cloudify/plugins/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,10 @@ def finish_creation(self):
for rel in instance.relationships:
if rel.target_node_instance in self.node_instances:
trg_started = self.tasks.set_state_started[rel.target_id]
establish_operations = _relationship_operations(
instance,
'cloudify.interfaces.relationship_lifecycle.establish'
)
for establish_op in establish_operations:
establish_ops = _relationship_operations_with_target(
rel,
'cloudify.interfaces.relationship_lifecycle.establish')
for establish_op, _ in establish_ops:
self.graph.add_task(establish_op)
self.graph.add_dependency(establish_op, trg_started)

Expand Down Expand Up @@ -272,10 +271,9 @@ def finish_creation(self):
for rel in instance.relationships:
if rel.target_node_instance in self.node_instances:
target_stopped = self.tasks.stop_node[rel.target_id]
unlink_tasks = _relationship_operations_with_targets(
instance,
'cloudify.interfaces.relationship_lifecycle.unlink'
)
unlink_tasks = _relationship_operations_with_target(
rel,
'cloudify.interfaces.relationship_lifecycle.unlink')
for unlink_task, _ in unlink_tasks:
self.graph.add_task(unlink_task)
self.graph.add_dependency(unlink_task, target_stopped)
Expand Down Expand Up @@ -354,15 +352,19 @@ def _relationship_operations(node_instance, operation):
def _relationship_operations_with_targets(node_instance, operation):
tasks = []
for relationship in node_instance.relationships:
tasks.append(
(relationship.execute_source_operation(operation),
relationship.target_id))
tasks.append(
(relationship.execute_target_operation(operation),
relationship.target_id))
tasks += _relationship_operations_with_target(relationship, operation)
return tasks


def _relationship_operations_with_target(relationship, operation):
return [
(relationship.execute_source_operation(operation),
relationship.target_id),
(relationship.execute_target_operation(operation),
relationship.target_id)
]


def _is_host_node(node_instance):
return 'cloudify.nodes.Compute' in node_instance.node.type_hierarchy

Expand Down
49 changes: 49 additions & 0 deletions cloudify/tests/resources/blueprints/test-subgraph-blueprint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
tosca_definitions_version: cloudify_dsl_1_0

imports:
- http://www.getcloudify.org/spec/cloudify/3.2/types.yaml

plugins:
p:
executor: central_deployment_agent
install: false

node_types:
type:
derived_from: cloudify.nodes.Root

node_templates:
node1:
type: type
relationships:
- type: cloudify.relationships.connected_to
target: node2
target_interfaces:
cloudify.interfaces.relationship_lifecycle:
establish: p.cloudify.tests.test_builtin_workflows.target_operation
unlink: p.cloudify.tests.test_builtin_workflows.target_operation
source_interfaces:
cloudify.interfaces.relationship_lifecycle:
establish: p.cloudify.tests.test_builtin_workflows.source_operation
unlink: p.cloudify.tests.test_builtin_workflows.source_operation
- type: cloudify.relationships.connected_to
target: node3
target_interfaces:
cloudify.interfaces.relationship_lifecycle:
establish: p.cloudify.tests.test_builtin_workflows.target_operation
unlink: p.cloudify.tests.test_builtin_workflows.target_operation
source_interfaces:
cloudify.interfaces.relationship_lifecycle:
establish: p.cloudify.tests.test_builtin_workflows.source_operation
unlink: p.cloudify.tests.test_builtin_workflows.source_operation
node2_host:
type: cloudify.nodes.Compute
properties:
install_agent: false
node2:
type: type
relationships:
- type: cloudify.relationships.contained_in
target: node2_host
node3:
type: type
75 changes: 75 additions & 0 deletions cloudify/tests/test_builtin_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
from cloudify.decorators import operation


IGNORED_LOCAL_WORKFLOW_MODULES = (
'worker_installer.tasks',
'plugin_installer.tasks',
'windows_agent_installer.tasks',
'windows_plugin_installer.tasks'
)


class TestExecuteOperationWorkflow(testtools.TestCase):

def setUp(self):
Expand Down Expand Up @@ -260,6 +268,54 @@ def test_illegal_delta(self):
'delta': -1})


class TestSubgraphWorkflowLogic(testtools.TestCase):

def setUp(self):
super(TestSubgraphWorkflowLogic, self).setUp()
blueprint_path = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"resources/blueprints/test-subgraph-blueprint.yaml")
self.env = local.init_env(
blueprint_path,
ignored_modules=IGNORED_LOCAL_WORKFLOW_MODULES)

def test_heal_connected_to_relationship_operations_on_on_affected(self):
# Tests CFY-2788 fix
# We run heal on node2 instance. node1 is connected to node2 and node3
# we expect that the establish/unlink operations will only be called
# for node1->node2
node2_instance_id = [i for i in self.env.storage.get_node_instances()
if i.node_id == 'node2'][0].id
self.env.execute('heal', parameters={
'node_instance_id': node2_instance_id})
node1_instance = [i for i in self.env.storage.get_node_instances()
if i.node_id == 'node1'][0]
invocations = node1_instance.runtime_properties['invocations']
self.assertEqual(4, len(invocations))
expected_unlink = invocations[:2]
expected_establish = invocations[2:]

def assertion(actual_invocations, expected_op):
has_source_op = False
has_target_op = False
for invocation in actual_invocations:
if invocation['runs_on'] == 'source':
has_source_op = True
elif invocation['runs_on'] == 'target':
has_target_op = True
else:
self.fail('Unhandled runs_on: {0}'.format(
invocation['runs_on']))
self.assertEqual(invocation['target_node'], 'node2')
self.assertEqual(invocation['operation'], expected_op)
self.assertTrue(all([has_source_op, has_target_op]))

assertion(expected_unlink,
'cloudify.interfaces.relationship_lifecycle.unlink')
assertion(expected_establish,
'cloudify.interfaces.relationship_lifecycle.establish')


@nottest
@operation
def exec_op_test_operation(ctx, **kwargs):
Expand All @@ -273,3 +329,22 @@ def exec_op_test_operation(ctx, **kwargs):
def exec_op_dependency_order_test_operation(ctx, **kwargs):
ctx.instance.runtime_properties['visit_time'] = time.time()
time.sleep(1)


@operation
def source_operation(ctx, **_):
_write_operation(ctx, runs_on='source')


@operation
def target_operation(ctx, **_):
_write_operation(ctx, runs_on='target')


def _write_operation(ctx, runs_on):
invocations = ctx.source.instance.runtime_properties.get('invocations', [])
invocations.append({
'operation': ctx.operation.name,
'target_node': ctx.target.node.name,
'runs_on': runs_on})
ctx.source.instance.runtime_properties['invocations'] = invocations

0 comments on commit 0a46b3a

Please sign in to comment.