Commit 11370fde authored by Spiros Koulouzis's avatar Spiros Koulouzis

fix bug where a node has 2 requirements. Now we map 1 requirement with one matching node

parent af7e56ea
...@@ -14,30 +14,30 @@ logger = logging.getLogger(__name__) ...@@ -14,30 +14,30 @@ logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
def add_requirements(node, missing_requirements, capable_node_name): def add_requirement(node, missing_requirement, capable_node_name):
"""Add the requirements to the node """ """Add the requirement to the node """
for req in missing_requirements: first_key = next(iter(missing_requirement))
req[next(iter(req))]['node'] = capable_node_name missing_requirement[first_key]['node'] = capable_node_name
if isinstance(node, NodeTemplate): if isinstance(node, NodeTemplate):
contains_requirement = False contains_requirement = False
for node_requirement in node.requirements: for node_requirement in node.requirements:
if node_requirement == req: if node_requirement == missing_requirement:
contains_requirement = True contains_requirement = True
break break
if not contains_requirement: if not contains_requirement:
node.requirements.append(req) node.requirements.append(missing_requirement)
elif isinstance(node, dict): elif isinstance(node, dict):
type_name = next(iter(node)) type_name = next(iter(node))
if 'requirements' not in node[type_name]: if 'requirements' not in node[type_name]:
node[type_name]['requirements'] = [] node[type_name]['requirements'] = []
node_requirements = node[type_name]['requirements'] node_requirements = node[type_name]['requirements']
contains_requirement = False contains_requirement = False
for node_requirement in node_requirements: for node_requirement in node_requirements:
if node_requirement == req: if node_requirement == missing_requirement:
contains_requirement = True contains_requirement = True
break break
if not contains_requirement: if not contains_requirement:
node[type_name]['requirements'].append(req) node[type_name]['requirements'].append(missing_requirement)
return node return node
...@@ -173,19 +173,25 @@ class Planner: ...@@ -173,19 +173,25 @@ class Planner:
if not all_requirements: if not all_requirements:
logger.debug('Node: ' + tosca_helper.get_node_type_name(node) + ' has no requirements') logger.debug('Node: ' + tosca_helper.get_node_type_name(node) + ' has no requirements')
return return
matching_node = self.find_best_node_for_requirements(all_requirements) matching_nodes_dict = self.find_best_node_for_requirements(all_requirements)
for capability in matching_nodes_dict:
# Only add node that is not in node_templates # Only add node that is not in node_templates
matching_node_type_name = next(iter(matching_node)) matching_node = matching_nodes_dict[capability]
matching_node_template = tosca_helper.node_type_2_node_template(matching_node, self.all_custom_def) matching_node_type_name = next(iter(matching_node))
# Add the requirements to the node we analyzed. e.g. docker needed host now we added the type and name of host matching_node_template = tosca_helper.node_type_2_node_template(matching_node, self.all_custom_def)
node = add_requirements(node, all_requirements, matching_node_template.name) for req in all_requirements:
if not tosca_helper.contains_node_type(self.required_nodes, matching_node_type_name) and \ req_name = next(iter(req))
requirement_capability = req[req_name]['capability']
if capability == requirement_capability:
# Add the requirements to the node we analyzed. e.g. docker needed host now we added the type and name of host
node = add_requirement(node, req, matching_node_template.name)
break
if not tosca_helper.contains_node_type(self.required_nodes, matching_node_type_name) and \
not tosca_helper.contains_node_type(self.tosca_template.nodetemplates, matching_node_type_name): not tosca_helper.contains_node_type(self.tosca_template.nodetemplates, matching_node_type_name):
logger.info(' Adding: ' + str(matching_node_template.name)) logger.info(' Adding: ' + str(matching_node_template.name))
self.required_nodes.append(matching_node) self.required_nodes.append(matching_node)
# Find matching nodes for the new node's requirements # Find matching nodes for the new node's requirements
self.add_required_nodes(matching_node) self.add_required_nodes(matching_node)
def get_all_requirements(self, node): def get_all_requirements(self, node):
"""Returns all requirements for an input node including all parents requirements""" """Returns all requirements for an input node including all parents requirements"""
...@@ -255,6 +261,7 @@ class Planner: ...@@ -255,6 +261,7 @@ class Planner:
can cover and return the one which covers the most """ can cover and return the one which covers the most """
matching_nodes = {} matching_nodes = {}
number_of_matching_requirement = {} number_of_matching_requirement = {}
met_requirements = {}
# Loop requirements to find nodes per requirement # Loop requirements to find nodes per requirement
for req in all_requirements: for req in all_requirements:
key = next(iter(req)) key = next(iter(req))
...@@ -265,34 +272,27 @@ class Planner: ...@@ -265,34 +272,27 @@ class Planner:
# Find all nodes in the definitions that have the capability: capability # Find all nodes in the definitions that have the capability: capability
logger.info(' Looking for nodes in node types with capability: ' + capability) logger.info(' Looking for nodes in node types with capability: ' + capability)
capable_nodes = self.get_node_types_by_capability(capability) capable_nodes = self.get_node_types_by_capability(capability)
if capable_nodes and len(capable_nodes) == 1: if not capable_nodes:
return capable_nodes
if capable_nodes:
# Add number of matching capabilities for each node.
# Try to score matching_nodes to return one. The more requirements a node meets the better
for node_type in capable_nodes:
matching_requirement_count = 1
if node_type not in number_of_matching_requirement:
number_of_matching_requirement[node_type] = matching_requirement_count
else:
matching_requirement_count = number_of_matching_requirement[node_type]
matching_requirement_count += 1
number_of_matching_requirement[node_type] = matching_requirement_count
logger.info(' Found: ' + str(node_type))
matching_nodes.update(capable_nodes)
else:
logger.error('Did not find any node with required capability: ' + str(capability)) logger.error('Did not find any node with required capability: ' + str(capability))
raise Exception('Did not find any node with required capability: ' + str(capability)) raise Exception('Did not find any node with required capability: ' + str(capability))
matching_nodes[capability] = capable_nodes
# if we only found 1 return it # if we only found 1 return it
if len(matching_nodes) == 1: if len(matching_nodes) == 1:
return matching_nodes return matching_nodes
sorted_number_of_matching_requirement = sorted(number_of_matching_requirement.items(), returning_nodes = {}
key=operator.itemgetter(1)) for capability in matching_nodes:
index = len(sorted_number_of_matching_requirement) - 1 nodes = matching_nodes[capability]
winner_type = next(iter(sorted_number_of_matching_requirement[index])) key = next(iter(nodes))
return {winner_type: matching_nodes[winner_type]} returning_nodes[capability] = {key:nodes[key]}
return returning_nodes
# sorted_number_of_matching_requirement = sorted(number_of_matching_requirement.items(),
# key=operator.itemgetter(1))
# index = len(sorted_number_of_matching_requirement) - 1
# winner_type = next(iter(sorted_number_of_matching_requirement[index]))
# return {winner_type: matching_nodes[winner_type]}
def get_child_nodes(self, parent_node_type_name): def get_child_nodes(self, parent_node_type_name):
child_nodes = {} child_nodes = {}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment