def __init__(self, \ topology_template, \ node_template_name, \ node_template, \ node_template_type, \ requirement_name, \ requirement, \ relationship_id): # store parameters #TBR self.topology_template = topology_template self.source_node_template_name = node_template_name #TBR self.source_node_template = node_template self.source_node_template_type = node_template_type self.source_requirement_name = requirement_name #TBR self.source_requirement = requirement self.id = relationship_id # get target node template name self.target_node_template_name = \ syntax.get_requirement_node_template(requirement) assert self.target_node_template_name is not None # compute the relationship type name and interfaces node_type_requirements = syntax.get_requirements_dict( node_template_type) requirement_def = node_type_requirements.get(requirement_name, {}) relationship_def = syntax.get_requirement_relationship(requirement_def) relationship_type_name = \ syntax.get_relationship_type(relationship_def) self.interfaces = \ syntax.get_relationship_interfaces(relationship_def) or {} # TODO: merge interfaces defined in the relationship type interfaces = None relationship = syntax.get_requirement_relationship(requirement) if isinstance(relationship, str): # short grammar relationship_template = \ topology_template \ .get(syntax.RELATIONSHIP_TEMPLATES, {}) \ .get(relationship) if relationship_template != None: relationship_type_name = relationship_template['type'] interfaces = relationship_template.get('interfaces') else: relationship_type_name = relationship elif isinstance(relationship, dict): # extended grammar tmp = relationship.get('type') if tmp != None: relationship_type_name = tmp interfaces = relationship.get('interfaces') self.relationship_type_name = relationship_type_name if interfaces != None: self.interfaces = utils.merge_dict(self.interfaces, interfaces)
def generation(self): self.info("TOSCA diagram generation") topology_template = syntax.get_topology_template( self.tosca_service_template.get_yaml()) # Generate only for TOSCA topology template. if topology_template is None: return # Generate the TOSCA diagram. self.open_file(".dot") self.generate("graph ToscaDiagram {") self.generate(' rankdir="LR"') target_capability_ids = { } # map<requirement_assignment_id,capability_id> connected_capabilities = set() # set<node_name.capability_name> connected_requirements = set() # set<node_name.requirement_name> substitution_mappings = syntax.get_substitution_mappings( topology_template) if substitution_mappings is not None: for capability_name, capability_yaml in syntax.get_capabilities( substitution_mappings).items(): if capability_yaml: if not isinstance(capability_yaml, list): continue # TODO something when capability_yaml is not a list capability_name_id = "topology_template_substitution_mappings_capability_" + normalize_name( capability_name) self.generate( " ", capability_name_id, '[label="', capability_name, '" shape=cds style=filled fillcolor=orange]', sep="", ) self.generate( " ", capability_name_id, " -- ", normalize_name(capability_yaml[0]), "_capability_", normalize_name(capability_yaml[1]), "[style=dotted]", sep="", ) connected_capabilities.add(capability_yaml[0] + "." + capability_yaml[1]) for ( requirement_name, requirement_yaml, ) in syntax.get_substitution_mappings_requirements( substitution_mappings).items(): if requirement_yaml: connected_requirements.add(requirement_yaml[0] + "." + requirement_yaml[1]) substitution_mappings_node_type = syntax.get_node_type( substitution_mappings) self.generate(" subgraph clusterSubstitutionMappings {") self.generate(' label="', substitution_mappings_node_type, '"', sep="") node_templates = syntax.get_node_templates(topology_template) for node_name, node_yaml in node_templates.items(): node_type_requirements = syntax.get_requirements_dict( self.type_system.merge_type(syntax.get_type(node_yaml))) for requirement in syntax.get_requirements_list(node_yaml): for requirement_name, requirement_yaml in requirement.items(): # ACK for Alien4Cloud requirement_name = syntax.get_type_requirement( requirement_yaml, requirement_name) if requirement_yaml: requirement_capability = syntax.get_requirement_capability( node_type_requirements.get(requirement_name)) if requirement_capability is None: self.error( requirement_name + ": capability undefined", requirement_name, ) continue requirement_node = syntax.get_requirement_node_template( requirement_yaml) if requirement_node is None: continue capability_found = False requirement_node_template = node_templates.get( requirement_node) if requirement_node_template is None: self.error( requirement_node + " node template undefined", requirement_node, ) continue for capability_name, capability_yaml in syntax.get_capabilities( self.type_system.merge_node_type( syntax.get_type( requirement_node_template))).items(): if self.type_system.is_derived_from( syntax.get_capability_type( capability_yaml), requirement_capability, ): capability_found = True break if capability_found: target_capability_ids[id(requirement)] = ( self.get_node_name_id(requirement_node) + "_capability_" + normalize_name(capability_name)) connected_capabilities.add(requirement_node + "." + capability_name) connected_requirements.add(node_name + "." + requirement_name) else: self.error( ' capability of type "' + requirement_capability + '" not found', requirement_node_template, ) for node_name, node_yaml in node_templates.items(): node_name_id = self.get_node_name_id(node_name) node_type = syntax.get_type(node_yaml) merged_node_type = self.type_system.merge_type(node_type) self.generate(" subgraph cluster", node_name_id, " {", sep="") self.generate(" color=white") self.generate(' label=""') self.generate( " ", node_name_id, '[label="', node_name, ": ", short_type_name(node_type), '|\l\l\l\l" shape=record style=rounded]', sep="", ) for capability_name, capability_yaml in syntax.get_capabilities( merged_node_type).items(): if (node_name + "." + capability_name in connected_capabilities or node_yaml.get("capabilities", {}).get(capability_name) is not None): self.generate( " ", node_name_id, "_capability_", normalize_name(capability_name), '[label="', capability_name, '" shape=cds style=filled fillcolor=orange]', sep="", ) self.generate( " ", node_name_id, "_capability_", normalize_name(capability_name), " -- ", node_name_id, sep="", ) for requirement_name, requirement_yaml in syntax.get_requirements_dict( merged_node_type).items(): if (node_name + "." + requirement_name in connected_requirements or requirement_yaml.get("occurrences", [1, 1])[0] > 0): self.generate( " ", node_name_id, "_requirement_", normalize_name(requirement_name), '[label="', requirement_name, '" shape=cds style=filled fillcolor=turquoise]', sep="", ) self.generate( " ", node_name_id, " -- ", node_name_id, "_requirement_", normalize_name(requirement_name), sep="", ) self.generate(" }") for node_name, node_yaml in node_templates.items(): node_name_id = self.get_node_name_id(node_name) for requirement in syntax.get_requirements_list(node_yaml): for requirement_name, requirement_yaml in requirement.items(): # ACK for Alien4Cloud requirement_name = syntax.get_type_requirement( requirement_yaml, requirement_name) capability_id = target_capability_ids.get(id(requirement)) if capability_id is not None: self.generate( " ", node_name_id, "_requirement_", normalize_name(requirement_name), " -- ", capability_id, "[style=dotted]", sep="", ) if substitution_mappings is not None: self.generate(" }") for ( requirement_name, requirement_yaml, ) in syntax.get_substitution_mappings_requirements( substitution_mappings).items(): if requirement_yaml: requirement_name_id = "topology_template_substitution_mappings_requirement_" + normalize_name( requirement_name) self.generate( " ", requirement_name_id, '[label="', requirement_name, '" shape=cds style=filled fillcolor=turquoise]', sep="", ) self.generate( " ", normalize_name(requirement_yaml[0]), "_requirement_", normalize_name(requirement_yaml[1]), " -- ", requirement_name_id, "[style=dotted]", sep="", ) self.generate("}") self.close_file()
def generate_network_diagram(self, topology_template): # network ports # dict<port node name, array of bindable node templates> ports = {} def add_port_binding(port_name, node_name): port_bindings = ports.get(port_name) if port_bindings is None: port_bindings = [] ports[port_name] = port_bindings port_bindings.append(node_name) # Networks # dict<network name, Network> networks = {} def get_network(network_name): network = networks.get(network_name) if network is None: network = Network() networks[network_name] = network return network # iterates over all the requirements of the substitution mapping # in order to create external networks substitution_mapping = topology_template.get( syntax.SUBSTITUTION_MAPPINGS) if substitution_mapping is not None: substitution_mapping_node_type = syntax.get_node_type( substitution_mapping) if substitution_mapping_node_type is not None: node_type = self.type_system.merge_type( substitution_mapping_node_type) node_type_requirements = syntax.get_requirements_dict( node_type) for ( requirement_name, requirement_value, ) in syntax.get_substitution_mappings_requirements( substitution_mapping).items(): requirement_definition = node_type_requirements.get( requirement_name) capability = syntax.get_requirement_capability( requirement_definition) if capability in self.configuration.get( NWDIAG, "linkable_capability_types"): # is a requirement with capability in linkable # capability types # create the Network associated to this external # network requirement network = get_network(requirement_name) # the requirement node is in the external node network.nodes[ requirement_value[0]] = requirement_value[0] # iterates over all the node templates node_templates = topology_template.get(syntax.NODE_TEMPLATES, {}) for node_name, node_yaml in node_templates.items(): # get the node type node_type = node_yaml.get(syntax.TYPE) node_type_type = self.type_system.merge_type(node_type) # Deal with Forwarding nodes which are both a port and a network if node_type in self.configuration.get(NWDIAG, "forwarding_node_types"): # a Forwarding node is a node of its associated Forwarding # network get_network(node_name).nodes[node_name] = node_name # iterate over all the node capabilities # in order to identify node templates which are networks for cap_name, cap_def in node_type_type.get( syntax.CAPABILITIES, {}).items(): cap_def_type = (cap_def.get(syntax.TYPE) if isinstance( cap_def, dict) else cap_def) if cap_def_type in self.configuration.get( NWDIAG, "linkable_capability_types"): # this node template is a network node, # i.e. a node template with a linkable capability get_network(node_name).network_node = node_yaml # iterate over all the requirements of the current node node_type_requirements = syntax.get_requirements_dict( node_type_type) for requirement in syntax.get_requirements_list(node_yaml): for requirement_name, requirement_yaml in requirement.items(): requirement_definition = node_type_requirements.get( requirement_name) capability = syntax.get_requirement_capability( requirement_definition) if capability in self.configuration.get( NWDIAG, "linkable_capability_types"): network_node = syntax.get_requirement_node_template( requirement_yaml) # current node template is a node of the network node get_network(network_node).nodes[node_name] = node_name elif capability in self.configuration.get( NWDIAG, "bindable_capability_types"): binding_node = syntax.get_requirement_node_template( requirement_yaml) add_port_binding(node_name, binding_node) # network diagram generation if len(networks) == 0: # no network node template found self.info("No network diagram generated.") else: self.info("Network diagram generation ...") # network node templates found then # generate the network diagram file self.open_file(".nwdiag") self.generate("{") # iterate over all found networks for network_name, network in networks.items(): self.generate(' network "%s" {' % network_name) network_node = network.network_node if network_node is None: # this is an external network associated to a network # requirement of the substitution mapping network_repr = {} # use default graphical attributes network_label = network_name network_address = "" # no network address else: # this a network node template network_repr = self.get_representation(network_node) network_label = self.resolve_attribute( network_node, network_repr, "label", "\n") network_label = (network_label if network_label != "" else network_name) network_address = self.resolve_attribute( network_node, network_repr, "address", "\n") # '', ') # generate the graphical attributes of the network # TODO: add other graphical attributes font, etc. self.generate(' label = "%s"' % network_label) self.generate(' address = "%s"' % network_address) self.generate(' color = "%s"' % network_repr.get("color", "lightblue")) self.generate(' textcolor = "%s"' % network_repr.get( "textcolor", "black", )) # generate all the ports connected to the network if len(network.nodes) == 0: # no node found # nwdiag tool requires that a network has nodes else an # error is produced! # so generate a graphical note self.generate( ' empty_network_%s[label="This network\nis empty!", shape=note];' % network_name) else: # iterates over of the nodes of the network for port_name, node_name in network.nodes.items(): port_node = node_templates.get(port_name) port_repr = self.get_representation(port_node) port_address = self.resolve_attribute( port_node, port_repr, "address", ", ") bindings = ports.get(node_name, [node_name]) for binding in bindings: bindings = ports.get(binding, [binding]) for binding in bindings: binding_node = node_templates.get(binding) binding_repr = self.get_representation( binding_node) binding_label = self.resolve_attribute( binding_node, binding_repr, "label", "\n") binding_label = (binding_label if binding_label != "" else binding) # generate the graphical node # TODO: add other graphical attributes font, # etc. self.generate( ' "%s"[label="%s", address="%s", shape="%s", color="%s", textcolor="%s", style="%s"%s];' % ( binding, binding_label, port_address, binding_repr.get("shape", "box"), binding_repr.get("color", "white"), binding_repr.get("textcolor", "black"), binding_repr.get("style", "solid"), self.get_icon_attribute( binding_node, binding_repr), )) self.generate(" }") self.generate("}") self.close_file()