From: Hashir Mohammed Date: Fri, 10 Feb 2017 19:10:47 +0000 (-0500) Subject: TOSCA to YANG Translator Initial commit X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FSO.git;a=commitdiff_plain;h=bc183dcd09255cbe61afe64f8543824f2270634c TOSCA to YANG Translator Initial commit Signed-off-by: Hashir Mohammed --- diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py index 2b244d7a..7bc0bf3b 100755 --- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py @@ -39,7 +39,13 @@ class ToscaCompute(ManoResource): 'cloud-init-file',] IGNORE_PROPS = [] - toscatype = 'tosca.nodes.Compute' + toscatype = 'tosca.nodes.nfv.VDU' + + VALUE_TYPE_CONVERSION_MAP = { + 'integer': 'INT', + 'string':'STRING', + 'float':'DECIMAL' + } def __init__(self, log, nodetemplate, metadata=None): super(ToscaCompute, self).__init__(log, @@ -54,6 +60,8 @@ class ToscaCompute(ManoResource): self._vnf = None self._yang = None self._id = self.name + self._monitor_param = [] + self._mgmt_interface = {} @property def image(self): @@ -104,6 +112,39 @@ class ToscaCompute(ManoResource): def handle_capabilities(self): + def get_mgmt_interface(specs): + mgmt_intfce = {} + mgmt_intfce['vdu-id'] = self.id + if 'dashboard_params' in specs: + mgmt_intfce['dashboard-params'] = {'path':specs['dashboard_params']['path'], 'port':specs['dashboard_params']['port']} + if 'port' in specs: + mgmt_intfce['port'] = specs['port'] + return mgmt_intfce; + + def get_monitor_param(specs, monitor_id): + monitor_param = {} + monitor_param['id'] = monitor_id + if 'name' in specs: + monitor_param['name'] = specs['name'] + if 'json_query_method' in specs: + monitor_param['json_query_method'] = specs['json_query_method'].upper() + if 'description' in specs: + monitor_param['description'] = specs['description'] + if 'url_path' in specs: + monitor_param['http-endpoint-ref'] = specs['url_path'] + if 'ui_data' in specs: + if 'widget_type' in specs['ui_data']: + monitor_param['widget-type'] = specs['ui_data']['widget_type'].upper() + if 'units' in specs['ui_data']: + monitor_param['units'] = specs['ui_data']['units'] + if 'group_tag' in specs['ui_data']: + monitor_param['group_tag'] = specs['ui_data']['group_tag'] + if 'constraints' in specs: + if 'value_type' in specs['constraints']: + monitor_param['value-type'] = ToscaCompute.VALUE_TYPE_CONVERSION_MAP[specs['constraints']['value_type']] + + return monitor_param + def get_vm_flavor(specs): vm_flavor = {} if 'num_cpus' in specs: @@ -125,14 +166,108 @@ class ToscaCompute(ManoResource): return vm_flavor + def get_host_epa(specs): + host_epa = {} + if 'cpu_model' in specs: + host_epa["cpu-model"] = specs['cpu_model'].upper() + if 'cpu_arch' in specs: + host_epa["cpu-arch"] = specs['cpu_arch'].upper() + if 'cpu_vendor' in specs: + host_epa["cpu-vendor"] = specs['cpu_vendor'].upper() + if 'cpu_socket_count' in specs: + host_epa["cpu-socket-count"] = specs['cpu_socket_count'] + if 'cpu_core_count' in specs: + host_epa["cpu-core-count"] = specs['cpu_core_count'] + if 'cpu_core_thread_count' in specs: + host_epa["cpu-core-thread-count"] = specs['cpu_core_thread_count'] + if 'om_cpu_model_string' in specs: + host_epa["om-cpu-model-string"] = specs['om_cpu_model_string'] + if 'cpu_feature' in specs: + cpu_feature_prop = [] + for spec in specs['cpu_feature']: + cpu_feature_prop.append({'feature':spec.upper()}) + host_epa['cpu-feature'] = cpu_feature_prop + if 'om_cpu_feature' in specs: + cpu_feature_prop = [] + for spec in specs['om_cpu_feature']: + cpu_feature_prop.append({'feature':spec}) + host_epa['om-cpu-feature'] = cpu_feature_prop + return host_epa; + + def get_vswitch_epa(specs): + vswitch_epa = {} + if 'ovs_acceleration' in specs: + vswitch_epa['ovs-acceleration'] = specs['ovs_acceleration'].upper() + if 'ovs_offload' in specs: + vswitch_epa['ovs-offload'] = specs['ovs_offload'].upper() + return vswitch_epa + + def get_hypervisor_epa(specs): + hypervisor_epa = {} + if 'type' in specs: + hypervisor_epa['type'] = specs['type'].upper() + if 'version' in specs: + hypervisor_epa['version'] = specs['version'] + + return hypervisor_epa + + def get_guest_epa(specs): + guest_epa = {} + guest_epa['numa-node-policy'] = {} + guest_epa['numa-node-policy']['node'] = [] + if 'mem_policy' in specs: + guest_epa['numa-node-policy']['mem-policy'] = specs['mem_policy'].upper() + if 'node_cnt' in specs: + guest_epa['numa-node-policy']['node-cnt'] = specs['node_cnt'] + if 'node' in specs: + for node in specs['node']: + node_prop = {} + if 'id' in node: + node_prop['id'] = node['id'] + if 'mem_size' in node: + if 'MiB' in node['mem_size'] or 'MB' in node['mem_size']: + node_prop['memory-mb'] = int(node['mem_size'].replace('MB','')) + else: + err_msg = "Specify mem_size of NUMA extension should be in MB" + raise ValidationError(message=err_msg) + if 'om_numa_type' in node: + numa_type = node['om_numa_type'] + if 'paired-threads' == numa_type: + node_prop['paired_threads'] = {} + node_prop['paired_threads']['num_paired_threads'] = node['paired_threads']['num_paired_threads'] + elif 'threads' == numa_type: + if 'num_threads' in node: + node_prop['num_threads'] = node['num_threads'] + elif 'cores' == numa_type: + if 'num_cores' in node: + node_prop['num_cores'] = node['num_cores'] + else: + err_msg = "om_numa_type should be among cores, paired-threads or threads" + raise ValidationError(message=err_msg) + guest_epa['numa-node-policy']['node'].append(node_prop) + return guest_epa + tosca_caps = self.get_tosca_caps() self.log.debug(_("VDU {0} tosca capabilites: {1}"). format(self.name, tosca_caps)) - - if 'host' in tosca_caps: - self.properties['vm-flavor'] = get_vm_flavor(tosca_caps['host']) + if 'nfv_compute' in tosca_caps: + self.properties['vm-flavor'] = get_vm_flavor(tosca_caps['nfv_compute']) self.log.debug(_("VDU {0} properties: {1}"). format(self.name, self.properties)) + if 'host_epa' in tosca_caps: + self.properties['host-epa'] = get_host_epa(tosca_caps['host_epa']) + if 'hypervisor_epa' in tosca_caps: + self.properties['hypervisor-epa'] = get_hypervisor_epa(tosca_caps['hypervisor_epa']) + if 'vswitch_epa' in tosca_caps: + self.properties['vswitch-epa'] = get_vswitch_epa(tosca_caps['vswitch_epa']) + if 'numa_extension' in tosca_caps: + self.properties['guest-epa'] = get_guest_epa(tosca_caps['numa_extension']) + if 'monitoring_param' in tosca_caps: + self._monitor_param.append(get_monitor_param(tosca_caps['monitoring_param'], '1')) + if 'monitoring_param_1' in tosca_caps: + self._monitor_param.append(get_monitor_param(tosca_caps['monitoring_param_1'], '2')) + if 'mgmt_interface' in tosca_caps: + self._mgmt_interface = get_mgmt_interface(tosca_caps['mgmt_interface']) def handle_artifacts(self): if self.artifacts is None: @@ -145,20 +280,18 @@ class ToscaCompute(ManoResource): if isinstance(props, dict): details = {} for name, value in props.items(): - if name == 'type': + if name == 'type' and value == 'tosca.artifacts.Deployment.Image.riftio.QCOW2': prefix, type_ = value.rsplit('.', 1) if type_ == 'QCOW2': details['type'] = 'qcow2' - else: - err_msg = _("VDU {0}, Currently only QCOW2 images " - "are supported in artifacts ({1}:{2})"). \ - format(self.name, key, value) - self.log.error(err_msg) - raise ValidationError(message=err_msg) + self.properties['image'] = os.path.basename(props['file']) + elif name == 'type' and value == 'tosca.artifacts.Deployment.riftio.cloud_init_file': + details['cloud_init_file'] = os.path.basename(props['file']) + self.properties['cloud_init_file'] = os.path.basename(props['file']) elif name == 'file': details['file'] = value elif name == 'image_checksum': - details['image_checksum'] = value + self.properties['image_checksum'] = value else: self.log.warn(_("VDU {0}, unsuported attribute {1}"). format(self.name, name)) @@ -249,7 +382,13 @@ class ToscaCompute(ManoResource): return None self._update_properties_for_model() props = convert_keys_to_python(self.properties) + + for monitor_param in self._monitor_param: + monitor_props = convert_keys_to_python(monitor_param) + vnfd.monitoring_param.add().from_dict(monitor_props) try: + if len(self._mgmt_interface) > 0: + vnfd.mgmt_interface.from_dict(convert_keys_to_python(self._mgmt_interface)) vnfd.vdu.add().from_dict(props) except Exception as e: err_msg = _("{0} Exception vdu from dict {1}: {2}"). \ diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py new file mode 100644 index 00000000..715ddc33 --- /dev/null +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py @@ -0,0 +1,62 @@ +from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource +from toscaparser.functions import GetInput + +TARGET_CLASS_NAME = 'ToscaForwardingGraph' +class ToscaForwardingGraph(ManoResource): + '''Translate TOSCA node type tosca.nodes.nfv.FP''' + toscatype = 'tosca.groups.nfv.VNFFG' + + def __init__(self, log, group, metadata=None): + #super(ToscaForwardingGraph, self).__init__(log, nodetemplate, type_='forwardgraph', metadata=metadata) + super(ToscaForwardingGraph, self).__init__(log, + group, + type_="vnfgd", + metadata=metadata) + self.name = group.name + self.type_ = 'vnffg' + self.metadata = metadata + self.group = group + self.properties = {} + self.classifiers = [] + self.rsp = [] + self.log = log + + def get_tosca_group_props(self): + tosca_props = {} + for prop in self.group.get_properties_objects(): + if isinstance(prop.value, GetInput): + tosca_props[prop.name] = {'get_param': prop.value.input_name} + else: + tosca_props[prop.name] = prop.value + return tosca_props + + def handle_properties(self, nodes, groups): + self.properties['name'] = self.name + self.properties['vendor'] = self.metadata['vendor'] + self.properties['id'] = self.id + self.properties['classifier'] = [] + self.properties['rsp'] = [] + + tosca_props = self.get_tosca_group_props() + forwarding_paths = [] + for member in self.group.members: + forwarding_paths.append(member) + + for forwarding_path in forwarding_paths: + node = self.get_node_with_name(forwarding_path, nodes) + if node.classifier is not None: + self.properties['classifier'].append(node.classifier) + if node.rsp is not None: + self.properties['rsp'].append(node.rsp) + + def generate_yang_model_gi(self, nsd, vnfds): + try: + nsd.vnffgd.add().from_dict(self.properties) + except Exception as e: + err_msg = "Error updating VNNFG to nsd" + self.log.error(err_msg) + raise e + + def generate_yang_model(self, nsd, vnfds, use_gi=False): + if use_gi: + return self.generate_yang_model_gi(nsd, vnfds) \ No newline at end of file diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py new file mode 100644 index 00000000..4e392363 --- /dev/null +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py @@ -0,0 +1,86 @@ +from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource +import uuid + + +TARGET_CLASS_NAME = 'ToscaForwardingPath' +class ToscaForwardingPath(ManoResource): + '''Translate TOSCA node type tosca.nodes.nfv.FP''' + + toscatype = 'tosca.nodes.nfv.FP' + + + def __init__(self, log, node, metadata=None): + super(ToscaForwardingPath, self).__init__(log, node, type_='forwarding_path', metadata=metadata) + self.metadata = metadata + self.classifier = None + self.rsp = None + self.cp = None + self.properties = {} + + def handle_forwarding_path_dependencies(self, nodes, vnf_type_to_capability_substitution_mapping): + def get_classifier(specs): + classifier_prop = {} + classifier_prop['name'] = 'VNFFG -' + str(self.name) + classifier_prop['id'] = self.id + if 'policy' in specs: + classifier_prop['match_attributes'] = [] + policy = specs['policy'] + if 'criteria' in policy: + match_prop = {} + match_prop['id'] = str(uuid.uuid1()) + for criteria in policy['criteria']: + if 'ip_dst_prefix' in criteria: + match_prop['destination_ip_address'] = criteria['ip_dst_prefix'] + if 'ip_proto' in criteria: + match_prop['ip_proto'] = criteria['ip_proto'] + if 'source_port_range' in criteria: + match_prop['source_port'] = int(criteria['source_port_range']) + if 'destination_port_range' in criteria: + match_prop['destination_port'] = int(criteria['destination_port_range']) + classifier_prop['match_attributes'].append(match_prop) + if 'cp' in specs: + cp_node_name = specs['cp']['capability'] + cp_node = self.get_node_with_name(cp_node_name, nodes) + if cp_node: + classifier_prop['vnfd_connection_point_ref'] = cp_node.cp_name + if 'cp' in specs: + vnf_node_name = specs['cp']['forwarder'] + vnf_node = self.get_node_with_name(vnf_node_name, nodes) + if vnf_node: + classifier_prop['vnfd_id_ref'] = vnf_node.id + classifier_prop['member_vnf_index_ref'] = vnf_node.get_member_vnf_index() + return classifier_prop + + def get_rsp(specs): + rsp = {} + rsp['id'] = str(uuid.uuid1()) + rsp['name'] = 'VNFFG-RSP-' + str(self.name) + rsp['vnfd_connection_point_ref'] = [] + if 'path' in specs: + fp_connection_point = [] + vnf_index = 1 + order_index = 1 + for rsp_item in specs['path']: + vnf_node_name = rsp_item['forwarder'] + conn_forwarder = rsp_item['capability'] + vnf_node = self.get_node_with_name(vnf_node_name, nodes) + for subs_mapping in vnf_type_to_capability_substitution_mapping[vnf_node.vnf_type]: + prop = {} + if conn_forwarder in subs_mapping: + fp_connection_point.append(subs_mapping[conn_forwarder]) + cp_node_name = subs_mapping[conn_forwarder] + cp_node = self.get_node_with_name(cp_node_name, nodes) + prop['vnfd_connection_point_ref'] = cp_node.cp_name + prop['vnfd_id_ref'] = vnf_node.id + prop['member_vnf_index_ref'] = vnf_index + prop['order'] = order_index + rsp['vnfd_connection_point_ref'].append(prop) + vnf_index = vnf_index + 1 + order_index = order_index + 1 + return rsp + + tosca_props = self.get_tosca_props() + self.classifier = get_classifier(tosca_props) + self.rsp = get_rsp(tosca_props) + if self.classifier and self.rsp: + self.classifier['rsp_id_ref'] = self.rsp['id'] diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py index 7c03d564..9b7cd039 100644 --- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py @@ -18,6 +18,7 @@ from rift.mano.tosca_translator.common.utils import _ from rift.mano.tosca_translator.common.utils import convert_keys_to_python from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource +from toscaparser.functions import GetInput from toscaparser.common.exception import ValidationError @@ -29,18 +30,16 @@ TARGET_CLASS_NAME = 'ToscaInitialConfig' class ToscaInitialConfig(ManoResource): '''Translate TOSCA node type tosca.policies.InitialConfigPrimitive.''' - toscatype = 'tosca.policies.riftio.InitialConfigPrimitive' + toscatype = 'tosca.policies.nfv.riftio.initial_config_primitive' IGNORE_PROPS = [] - def __init__(self, log, primitive, metadata=None): + def __init__(self, log, policy, metadata=None): # TODO(Philip):Not inheriting for ManoResource, as there is no # instance from parser self.log = log - for name, details in primitive.items(): - self.name = name - self.details = details - break + self.name = policy.name + self.policy = policy self.type_ = 'initial-cfg' self.metadata = metadata self.properties = {} @@ -50,7 +49,7 @@ class ToscaInitialConfig(ManoResource): return "%s(%s)" % (self.name, self.type) def handle_properties(self, nodes, groups): - tosca_props = self.details + tosca_props = self.get_policy_props() self.log.debug(_("{0} with tosca properties: {1}"). format(self, tosca_props)) self.properties['name'] = tosca_props['name'] @@ -71,6 +70,14 @@ class ToscaInitialConfig(ManoResource): self.log.debug(_("{0} properties: {1}").format(self, self.properties)) + def get_policy_props(self): + tosca_props = {} + for prop in self.policy.get_properties_objects(): + if isinstance(prop.value, GetInput): + tosca_props[prop.name] = {'get_param': prop.value.input_name} + else: + tosca_props[prop.name] = prop.value + return tosca_props def get_yang_model_gi(self, nsd, vnfds): props = convert_keys_to_python(self.properties) try: diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py index b446e512..a2dd92ba 100644 --- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py @@ -39,48 +39,65 @@ class ToscaNetwork(ManoResource): nodetemplate, type_='vld', metadata=metadata) - - def handle_properties(self): + self._vld = {} + self._ip_profile = {} + + def handle_vld_properties(self, nodes, vnf_type_substitution_mapping): + def get_vld_props(specs): + vld_prop = {} + vld_prop['id'] = self.id + vld_prop['name'] = self.name + vld_prop['short-name'] = self.name + vld_prop['type'] = self.get_type() + if 'description' in specs: + vld_prop['description'] = specs['description'] + if 'vendor' in specs: + vld_prop['vendor'] = specs['vendor'] + + index_count = 1 + vld_connection_point_list = [] + for node in nodes: + if node.type == "vnfd": + substitution_mapping_list = vnf_type_substitution_mapping[node.vnf_type]; + for req_key, req_value in node._reqs.items(): + for mapping in substitution_mapping_list: + if req_key in mapping: + # link the VLD to the connection point + node = self.get_node_with_name(mapping[req_key][0], nodes) + if node: + #print() + prop = {} + prop['member-vnf-index-ref'] = index_count + prop['vnfd-connection-point-ref'] = node.cp_name + prop['vnfd-id-ref'] = node.vnf._id + vld_connection_point_list.append(prop) + index_count += 1 + if len(vld_connection_point_list) > 1: + vld_prop['vnfd-connection-point-ref'] = vld_connection_point_list + return vld_prop + + def get_ip_profile_props(specs): + ip_profile_prop = {} + ip_profile_param = {} + if 'name' in specs: + ip_profile_prop['name'] = specs['name'] + elif 'description' in specs: + ip_profile_prop['name'] = specs['description'] + + if 'description' in specs: + ip_profile_prop['description'] = specs['description'] + if 'gateway_ip' in specs: + ip_profile_param['gateway-address'] = specs['gateway_ip'] + if 'ip_version' in specs: + ip_profile_param['ip-version'] = 'ipv' + str(specs['ip_version']) + if 'ip_version' in specs: + ip_profile_param['subnet-address'] = specs['cidr'] + + ip_profile_prop['ip-profile-params'] = ip_profile_param + return ip_profile_prop tosca_props = self.get_tosca_props() - - if 'cidr' in tosca_props.keys(): - self.log.warn(_("Support for subnet not yet " - "available. Ignoring it")) - net_props = {} - for key, value in tosca_props.items(): - if key in self.NETWORK_PROPS: - if key == 'network_name': - net_props['name'] = value - elif key == 'network_id': - net_props['id'] = value - else: - net_props[key] = value - - net_props['type'] = self.get_type() - - if 'name' not in net_props: - # Use the node name as network name - net_props['name'] = self.name - - if 'short_name' not in net_props: - # Use the node name as network name - net_props['short-name'] = self.name - - if 'id' not in net_props: - net_props['id'] = self.id - - if 'description' not in net_props: - net_props['description'] = self.description - - if 'vendor' not in net_props: - net_props['vendor'] = self.vendor - - if 'version' not in net_props: - net_props['version'] = self.version - - self.log.debug(_("Network {0} properties: {1}"). - format(self.name, net_props)) - self.properties = net_props + self._vld = get_vld_props(tosca_props) + self._ip_profile = get_ip_profile_props(tosca_props) def get_type(self): """Get the network type based on propery or type derived from""" @@ -107,9 +124,12 @@ class ToscaNetwork(ManoResource): return "ELAN" def generate_yang_model_gi(self, nsd, vnfds): - props = convert_keys_to_python(self.properties) + props = convert_keys_to_python(self.properties) + vld_props = convert_keys_to_python(self._vld) + ip_profile_props = convert_keys_to_python(self._ip_profile) try: - nsd.vld.add().from_dict(props) + nsd.vld.add().from_dict(vld_props) + nsd.ip_profiles.add().from_dict(ip_profile_props) except Exception as e: err_msg = _("{0} Exception vld from dict {1}: {2}"). \ format(self, props, e) diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py index 04e3a592..3574355e 100644 --- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py @@ -40,6 +40,8 @@ class ToscaNetworkPort(ManoResource): metadata=metadata) # Default order self.order = 0 + self.vnf = None + self.cp_name = None pass def handle_properties(self): @@ -68,28 +70,32 @@ class ToscaNetworkPort(ManoResource): self.log.warn(err_msg) raise ValidationError(message=err_msg) + self.cp_name = port_props['name'] self.properties = port_props def handle_requirements(self, nodes): tosca_reqs = self.get_tosca_reqs() + tosca_caps = self.get_tosca_caps() self.log.debug("VNF {0} requirements: {1}". format(self.name, tosca_reqs)) vnf = None # Need vnf ref to generate cp refs in vld vld = None + ''' if len(tosca_reqs) != 2: err_msg = _("Invalid configuration as incorrect number of " "requirements for CP {0} are specified"). \ format(self) self.log.error(err_msg) raise ValidationError(message=err_msg) - + ''' for req in tosca_reqs: if 'virtualBinding' in req: target = req['virtualBinding']['target'] node = self.get_node_with_name(target, nodes) if node: vnf = node.vnf + self.vnf = node._vnf if not vnf: err_msg = _("No vnfs linked to a VDU {0}"). \ format(node) @@ -129,17 +135,20 @@ class ToscaNetworkPort(ManoResource): self.log.error(err_msg) raise ValidationError(message=err_msg) - if vnf and vld: + if 'sfc' in tosca_caps and vnf: + if 'sfc_type' in tosca_caps['sfc']: + vnf.properties['service-function-chain'] = tosca_caps['sfc']['sfc_type'].upper() + if 'sf_type' in tosca_caps['sfc']: + vnf.properties['service-function-type'] = tosca_caps['sfc']['sf_type'] + + if vnf: cp_ref = {} cp_ref['vnfd-connection-point-ref'] = self.properties['name'] cp_ref['vnfd-id-ref'] = vnf.properties['id'] cp_ref['member-vnf-index-ref'] = \ vnf._const_vnfd['member-vnf-index'] - if 'vnfd-connection-point-ref' not in vld.properties: - vld.properties['vnfd-connection-point-ref'] = [] - vld.properties['vnfd-connection-point-ref'].append(cp_ref) else: - err_msg = _("CP {0}, VNF {1} or VL {2} not found"). \ + err_msg = _("CP {0}, VNF {1} not found"). \ format(self, vnf, vld) self.log.error(err_msg) raise ValidationError(message=err_msg) diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py index 3e529671..e4e045e3 100644 --- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py @@ -18,6 +18,7 @@ from rift.mano.tosca_translator.common.utils import _ from rift.mano.tosca_translator.common.utils import convert_keys_to_python from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource +from toscaparser.functions import GetInput from toscaparser.common.exception import ValidationError @@ -45,7 +46,7 @@ class ToscaNfvVnf(ManoResource): 'mgmt-interface'] OPTIONAL_PROPS = ['version', 'vendor', 'http-endpoint', 'monitoring-param', 'connection-point'] - IGNORE_PROPS = ['port'] + IGNORE_PROPS = ['port', 'monitoring_param'] TOSCA_CAPS = ['mgmt_interface', 'http_endpoint', 'monitoring_param_0', 'monitoring_param_1', 'connection_point'] @@ -57,6 +58,10 @@ class ToscaNfvVnf(ManoResource): self._const_vnfd = {} self._vnf_config = {} self._vdus = [] + self._policies = [] + self._cps = [] + self.vnf_type = nodetemplate.type + self._reqs = {} def map_tosca_name_to_mano(self, name): new_name = super().map_tosca_name_to_mano(name) @@ -138,6 +143,8 @@ class ToscaNfvVnf(ManoResource): if 'start_by_default' in vnf_props: self._const_vnfd['start-by-default'] = \ vnf_props.pop('start_by_default') + if 'logo' in self.metadata: + vnf_props['logo'] = self.metadata['logo'] self.log.debug(_("VNF {0} with constituent vnf: {1}"). format(self.name, self._const_vnfd)) @@ -186,45 +193,44 @@ class ToscaNfvVnf(ManoResource): self.log.debug(_("VDU {0} properties: {1}"). format(self.name, self.properties)) - def handle_requirements(self, nodes): + def handle_requirements(self, nodes, policies, vnf_type_to_vdus_map): tosca_reqs = self.get_tosca_reqs() - self.log.debug("VNF {0} requirements: {1}". - format(self.name, tosca_reqs)) - - try: - for req in tosca_reqs: - if 'vdus' in req: - target = req['vdus']['target'] - node = self.get_node_with_name(target, nodes) - if node: - self._vdus.append(node) - node._vnf = self - # Add the VDU id to mgmt-intf - if 'mgmt-interface' in self.properties: - self.properties['mgmt-interface']['vdu-id'] = \ - node.id - if 'vdu' in self.properties['mgmt-interface']: - # Older yang - self.properties['mgmt-interface'].pop('vdu') - else: - err_msg = _("VNF {0}, VDU {1} specified not found"). \ - format(self.name, target) - self.log.error(err_msg) - raise ValidationError(message=err_msg) - - except Exception as e: - err_msg = _("Exception getting VDUs for VNF {0}: {1}"). \ - format(self.name, e) - self.log.error(err_msg) - raise e - - self.log.debug(_("VNF {0} properties: {1}"). - format(self.name, self.properties)) + for req in tosca_reqs: + for key, value in req.items(): + if 'target' in value: + self._reqs[key] = value['target'] + + for policy in policies: + if hasattr(policy, '_vnf_name') and policy._vnf_name == self.name: + self._policies.append(policy) + + + if self.vnf_type in vnf_type_to_vdus_map: + for vdu_node_name in vnf_type_to_vdus_map[self.vnf_type]: + node = self.get_node_with_name(vdu_node_name, nodes) + if node: + self._vdus.append(node) + node._vnf = self + # Add the VDU id to mgmt-intf + if 'mgmt-interface' in self.properties: + self.properties['mgmt-interface']['vdu-id'] = \ + node.id + if 'vdu' in self.properties['mgmt-interface']: + # Older yang + self.properties['mgmt-interface'].pop('vdu') + else: + err_msg = _("VNF {0}, VDU {1} specified not found"). \ + format(self.name, target) + self.log.error(err_msg) + raise ValidationError(message=err_msg) def generate_yang_model_gi(self, nsd, vnfds): vnfd_cat = RwVnfdYang.YangData_Vnfd_VnfdCatalog() vnfd = vnfd_cat.vnfd.add() props = convert_keys_to_python(self.properties) + for key in ToscaNfvVnf.IGNORE_PROPS: + if key in props: + props.pop(key) try: vnfd.from_dict(props) except Exception as e: @@ -237,6 +243,8 @@ class ToscaNfvVnf(ManoResource): # Update the VDU properties for vdu in self._vdus: vdu.generate_yang_submodel_gi(vnfd) + for policy in self._policies: + policy.generate_yang_submodel_gi(vnfd) # Update constituent vnfd in nsd try: diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py new file mode 100644 index 00000000..8b8771b9 --- /dev/null +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py @@ -0,0 +1,114 @@ +# +# Copyright 2016 RIFT.io Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +from rift.mano.tosca_translator.common.utils import _ +from rift.mano.tosca_translator.common.utils import convert_keys_to_python +from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource +from toscaparser.functions import GetInput +from rift.mano.tosca_translator.common.utils import convert_keys_to_python + +from toscaparser.common.exception import ValidationError + + +# Name used to dynamically load appropriate map class. +TARGET_CLASS_NAME = 'ToscaPlacementGroup' + + +class ToscaPlacementGroup(ManoResource): + '''Translate TOSCA node type tosca.policies.Scaling.''' + + toscatype = 'tosca.policies.nfv.riftio.placement' + + IGNORE_PROPS = [] + + def __init__(self, log, policy, metadata=None, vnf_name=None): + self.log = log + self.name = policy.name + self.type_ = 'place-grp' + self.metadata = metadata + self.policy = policy + self.properties = {} + self._vnf_name = vnf_name + + def __str__(self): + return "%s(%s)" % (self.name, self.type) + + def handle_properties(self, nodes, groups): + tosca_props = self.get_policy_props() + self.properties['name'] = tosca_props['name'] + self.properties['strategy'] = tosca_props['strategy'] + self.properties['requirement'] = tosca_props['requirement'] + if self._vnf_name is None: + self.properties['member-vnfd'] = [] + index_count = 1 + for node in self.policy.get_targets_list(): + vnf_node = self.get_node_with_name(node.name, nodes) + prop = {} + prop['member-vnf-index-ref'] = index_count + prop['vnfd-id-ref'] = vnf_node.id + self.properties['member-vnfd'].append(prop) + index_count = index_count + 1 + else: + self.properties['member-vdus'] = [] + for node in self.policy.get_targets_list(): + vdu_node = self.get_node_with_name(node.name, nodes) + prop = {} + prop['member-vdu-ref'] = vdu_node.name + self.properties['member-vdus'].append(prop) + + def get_yang_model_gi(self, nsd, vnfds): + props = convert_keys_to_python(self.properties) + try: + if self._vnf_name is None: + nsd.placement_groups.add().from_dict(props) + except Exception as e: + err_msg = _("{0} Exception nsd placement-groups from dict {1}: {2}"). \ + format(self, props, e) + self.log.error(err_msg) + raise e + + def generate_yang_model(self, nsd, vnfds, use_gi=False): + if use_gi: + return self.get_yang_model_gi(nsd, vnfds) + if 'placement-groups' not in nsd: + nsd['placement-groups'] = [] + + for key, value in self.properties.items(): + prim[key] = value + nsd['placement-groups'].append(prim) + + def generate_yang_submodel_gi(self, vnfd): + if vnfd is None: + return None + try: + props = convert_keys_to_python(self.properties) + vnfd.placement_groups.add().from_dict(props) + except Exception as e: + err_msg = _("{0} Exception policy from dict {1}: {2}"). \ + format(self, props, e) + self.log.error(err_msg) + raise e + + def get_policy_props(self): + tosca_props = {} + + for prop in self.policy.get_properties_objects(): + if isinstance(prop.value, GetInput): + tosca_props[prop.name] = {'get_param': prop.value.input_name} + else: + tosca_props[prop.name] = prop.value + return tosca_props diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py index 25246af0..7f427f34 100644 --- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py @@ -18,6 +18,7 @@ from rift.mano.tosca_translator.common.utils import _ from rift.mano.tosca_translator.common.utils import convert_keys_to_python from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource +from toscaparser.functions import GetInput from toscaparser.common.exception import ValidationError @@ -29,54 +30,62 @@ TARGET_CLASS_NAME = 'ToscaScalingGroup' class ToscaScalingGroup(ManoResource): '''Translate TOSCA node type tosca.policies.Scaling.''' - toscatype = 'tosca.policies.riftio.ScalingGroup' + toscatype = 'tosca.groups.nfv.riftio.scaling' IGNORE_PROPS = [] - def __init__(self, log, policy, metadata=None): + def __init__(self, log, group, metadata=None): # TODO(Philip):Not inheriting for ManoResource, as there is no # instance from parser self.log = log - for name, details in policy.items(): - self.name = name - self.details = details - break + self.name = group.name + #self.details = details + self.group = group self.type_ = 'scale-grp' self.metadata = metadata self.properties = {} def __str__(self): return "%s(%s)" % (self.name, self.type) + def get_tosca_group_props(self): + tosca_props = {} + for prop in self.group.get_properties_objects(): + if isinstance(prop.value, GetInput): + tosca_props[prop.name] = {'get_param': prop.value.input_name} + else: + tosca_props[prop.name] = prop.value + return tosca_props def handle_properties(self, nodes, groups): - tosca_props = self.details + tosca_props = self.get_tosca_group_props() self.log.debug(_("{0} with tosca properties: {1}"). format(self, tosca_props)) - self.properties['name'] = tosca_props['name'] - self.properties['max-instance-count'] = \ - tosca_props['max_instance_count'] - self.properties['min-instance-count'] = \ - tosca_props['min_instance_count'] + if 'name ' in tosca_props: + self.properties['name'] = tosca_props['name'] + if 'max_instance_count' in tosca_props: + self.properties['max-instance-count'] = tosca_props['max_instance_count'] + if 'min_instance_count' in tosca_props: + self.properties['min-instance-count'] = tosca_props['min_instance_count'] self.properties['vnfd-member'] = [] def _get_node(name): for node in nodes: if node.name == name: return node - - for member, count in tosca_props['vnfd_members'].items(): - node = _get_node(member) - if node: - memb = {} - memb['member-vnf-index-ref'] = node.get_member_vnf_index() - memb['count'] = count - self.properties['vnfd-member'].append(memb) - else: - err_msg = _("{0}: Did not find the member node {1} in " - "resources list"). \ - format(self, member) - self.log.error(err_msg) - raise ValidationError(message=err_msg) + if 'vnfd_members' in tosca_props: + for member, count in tosca_props['vnfd_members'].items(): + node = _get_node(member) + if node: + memb = {} + memb['member-vnf-index-ref'] = node.get_member_vnf_index() + memb['count'] = count + self.properties['vnfd-member'].append(memb) + else: + err_msg = _("{0}: Did not find the member node {1} in " + "resources list"). \ + format(self, member) + self.log.error(err_msg) + raise ValidationError(message=err_msg) def _validate_action(action): for group in groups: @@ -85,25 +94,27 @@ class ToscaScalingGroup(ManoResource): return False self.properties['scaling-config-action'] = [] - for action, value in tosca_props['config_actions'].items(): - conf = {} - if _validate_action(value): - conf['trigger'] = action - conf['ns-config-primitive-name-ref'] = value - self.properties['scaling-config-action'].append(conf) - else: - err_msg = _("{0}: Did not find the action {1} in " - "config primitives"). \ - format(self, action) - self.log.error(err_msg) - raise ValidationError(message=err_msg) + if 'config_actions' in tosca_props: + for action, value in tosca_props['config_actions'].items(): + conf = {} + if _validate_action(value): + conf['trigger'] = action + conf['ns-config-primitive-name-ref'] = value + self.properties['scaling-config-action'].append(conf) + else: + err_msg = _("{0}: Did not find the action {1} in " + "config primitives"). \ + format(self, action) + self.log.error(err_msg) + raise ValidationError(message=err_msg) self.log.debug(_("{0} properties: {1}").format(self, self.properties)) def get_yang_model_gi(self, nsd, vnfds): props = convert_keys_to_python(self.properties) try: - nsd.scaling_group_descriptor.add().from_dict(props) + if len(self.properties['vnfd-member']) > 0: + nsd.scaling_group_descriptor.add().from_dict(props) except Exception as e: err_msg = _("{0} Exception nsd scaling group from dict {1}: {2}"). \ format(self, props, e) diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py new file mode 100644 index 00000000..0a54bcc0 --- /dev/null +++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py @@ -0,0 +1,89 @@ +# +# Copyright 2016 RIFT.io Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +from rift.mano.tosca_translator.common.utils import _ +from rift.mano.tosca_translator.common.utils import convert_keys_to_python +from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource +from toscaparser.functions import GetInput +from rift.mano.tosca_translator.common.utils import convert_keys_to_python + +from toscaparser.common.exception import ValidationError + + +# Name used to dynamically load appropriate map class. +TARGET_CLASS_NAME = 'ToscaVnfConfiguration' + + +class ToscaVnfConfiguration(ManoResource): + '''Translate TOSCA node type tosca.policies.Scaling.''' + + toscatype = 'tosca.policies.nfv.riftio.vnf_configuration' + + IGNORE_PROPS = [] + + def __init__(self, log, policy, metadata=None, vnf_name = None): + self.log = log + self.name = policy.name + self.type_ = 'place-grp' + self.metadata = metadata + self.policy = policy + self.properties = {} + self.linked_to_vnf = True + self._vnf_name = vnf_name + + def __str__(self): + return "%s(%s)" % (self.name, self.type) + + def handle_properties(self, nodes, groups): + tosca_props = self.get_policy_props() + self.properties["vnf-configuration"] = {} + prop = {} + prop["config-attributes"] = {} + prop["script"] = {} + if 'config' in tosca_props: + if 'config_delay' in tosca_props['config']: + prop["config-attributes"]['config-delay'] = tosca_props['config']['config_delay'] + if 'config_priority' in tosca_props['config']: + prop["config-attributes"]['config-priority'] = tosca_props['config']['config_priority'] + if 'config_template' in tosca_props['config']: + prop["config-template"] = tosca_props['config']['config_template'] + if 'config_details' in tosca_props['config']: + if 'script_type' in tosca_props['config']['config_details']: + prop["script"]["script-type"] = tosca_props['config']['config_details']['script_type'] + self.properties = prop + + def generate_yang_submodel_gi(self, vnfd): + if vnfd is None: + return None + try: + props = convert_keys_to_python(self.properties) + vnfd.vnf_configuration.from_dict(props) + except Exception as e: + err_msg = _("{0} Exception vdu from dict {1}: {2}"). \ + format(self, props, e) + self.log.error(err_msg) + raise e + + def get_policy_props(self): + tosca_props = {} + + for prop in self.policy.get_properties_objects(): + if isinstance(prop.value, GetInput): + tosca_props[prop.name] = {'get_param': prop.value.input_name} + else: + tosca_props[prop.name] = prop.value + return tosca_props \ No newline at end of file diff --git a/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py b/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py index dbfaa62a..3f74336c 100644 --- a/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py +++ b/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py @@ -161,6 +161,8 @@ class TranslateNodeTemplates(object): for key in FIELDS_MAP: if key in tosca_meta.keys(): metadata[FIELDS_MAP[key]] = str(tosca_meta[key]) + if 'logo' in tosca_meta: + metadata['logo'] = os.path.basename(tosca_meta['logo']) self.log.debug(_("Metadata {0}").format(metadata)) self.metadata = metadata @@ -188,8 +190,48 @@ class TranslateNodeTemplates(object): self.log.debug(_('Translating the node templates.')) # Copy the TOSCA graph: nodetemplate + all_node_templates = [] + node_to_artifact_map = {} + vnf_type_to_vnf_node = {} + vnf_type_to_vdus_map = {} + vnf_type_substitution_mapping = {} + vnf_type_to_capability_substitution_mapping = {} tpl = self.tosca.tpl['topology_template']['node_templates'] + for node in self.nodetemplates: + all_node_templates.append(node) + if node.parent_type.type == 'tosca.nodes.nfv.riftio.VNF1': + vnf_type_to_vnf_node[node.type] = node.name + for node_key in tpl: + if 'artifacts' in tpl[node_key]: + node_to_artifact_map[node_key] = tpl[node_key]['artifacts'] + for template in self.tosca.nested_tosca_templates_with_topology: + tpl_node = template.tpl['node_templates'] + vnf_type = template.substitution_mappings.node_type + + vnf_type_to_vdus_map[vnf_type] = [] + vnf_type_substitution_mapping[vnf_type] = [] + vnf_type_to_capability_substitution_mapping[vnf_type] = [] + vnf_type_to_capability_substitution_mapping[vnf_type] = [] + policies = [] + for node in template.nodetemplates: + all_node_templates.append(node) + for node_key in tpl_node: + if 'artifacts' in tpl_node[node_key]: + node_to_artifact_map[node_key] = tpl_node[node_key]['artifacts'] + for node in template.nodetemplates: + if 'VDU' in node.type: + vnf_type_to_vdus_map[vnf_type].append(node.name) + for policy in template.policies: + policies.append(policy.name) + for req in template.substitution_mappings.requirements: + vnf_type_substitution_mapping[template.substitution_mappings.node_type].append(req) + for capability in template.substitution_mappings.capabilities: + sub_list = template.substitution_mappings.capabilities[capability] + if len(sub_list) > 0: + vnf_type_to_capability_substitution_mapping[vnf_type].append({capability: sub_list[0]}) + + for node in all_node_templates: base_type = ManoResource.get_base_type(node.type_definition) self.log.debug(_("Translate node %(name)s of type %(type)s with " "base %(base)s") % @@ -203,46 +245,48 @@ class TranslateNodeTemplates(object): metadata=self.metadata) # Currently tosca-parser does not add the artifacts # to the node - if mano_node.name in tpl: - tpl_node = tpl[mano_node.name] - self.log.debug("Check artifacts for {}".format(tpl_node)) - if 'artifacts' in tpl_node: - mano_node.artifacts = tpl_node['artifacts'] + if mano_node.name in node_to_artifact_map: + mano_node.artifacts = node_to_artifact_map[mano_node.name] self.mano_resources.append(mano_node) self.mano_lookup[node] = mano_node # The parser currently do not generate the objects for groups - if 'groups' in self.tosca.tpl['topology_template']: - tpl = self.tosca.tpl['topology_template']['groups'] - self.log.debug("Groups: {}".format(tpl)) - for group, details in tpl.items(): - self.log.debug(_("Translate group {}: {}"). - format(group, details)) - group_type = details['type'] - if group_type: - group_node = TranslateNodeTemplates. \ - TOSCA_TO_MANO_TYPE[group_type]( - self.log, - group, - details, - metadata=self.metadata) - self.mano_groups.append(group_node) + for group in self.tosca.topology_template.groups: + group_type = group.type + if group_type: + group_node = TranslateNodeTemplates. \ + TOSCA_TO_MANO_TYPE[group_type]( + self.log, + group, + metadata=self.metadata) + self.mano_groups.append(group_node) # The parser currently do not generate the objects for policies - if 'policies' in self.tosca.tpl['topology_template']: - tpl = self.tosca.tpl['topology_template']['policies'] - # for policy in self.policies: - for policy in tpl: - self.log.debug(_("Translate policy {}"). - format(policy)) - policy_type = self._get_policy_type(policy) - if policy_type: - policy_node = TranslateNodeTemplates. \ - TOSCA_TO_MANO_TYPE[policy_type]( - self.log, - policy, - metadata=self.metadata) - self.mano_policies.append(policy_node) + + for policy in self.tosca.topology_template.policies: + policy_type = policy.type + if policy_type: + policy_node = TranslateNodeTemplates. \ + TOSCA_TO_MANO_TYPE[policy_type]( + self.log, + policy, + metadata=self.metadata) + self.mano_policies.append(policy_node) + for template in self.tosca.nested_tosca_templates_with_topology: + vnf_type = template.substitution_mappings.node_type + if vnf_type in vnf_type_to_vnf_node: + vnf_node = vnf_type_to_vnf_node[vnf_type] + + for policy in template.policies: + policy_type = policy.type + if policy_type: + policy_node = TranslateNodeTemplates. \ + TOSCA_TO_MANO_TYPE[policy_type]( + self.log, + policy, + metadata=self.metadata, + vnf_name=vnf_node) + self.mano_policies.append(policy_node) for node in self.mano_resources: self.log.debug(_("Handle properties for {0} of type {1}"). @@ -272,7 +316,8 @@ class TranslateNodeTemplates(object): self.log.debug(_("Handle requirements for {0} of " "type {1}"). format(node.name, node.type_)) - node.handle_requirements(self.mano_resources) + node.handle_requirements(self.mano_resources, self.mano_policies, vnf_type_to_vdus_map) + except Exception as e: self.log.error(_("Exception for {0} in requirements {1}"). format(node.name, node.type_)) @@ -290,11 +335,17 @@ class TranslateNodeTemplates(object): format(node.name, node.type_)) self.log.exception(e) + for node in self.mano_resources: + if node.type == "vld": + node.handle_vld_properties(self.mano_resources, vnf_type_substitution_mapping) + elif node.type == 'forwarding_path': + node.handle_forwarding_path_dependencies(self.mano_resources, vnf_type_to_capability_substitution_mapping) + return self.mano_resources def translate_groups(self): for group in self.mano_groups: - group.handle_properties(self.mano_resources) + group.handle_properties(self.mano_resources, self.mano_groups) return self.mano_groups def translate_policies(self): diff --git a/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py b/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py index 7449c5a1..9ff53e2f 100644 --- a/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py +++ b/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py @@ -117,7 +117,8 @@ class YangVnfd(ToscaResource): http_ep = {'protocol': 'http'} # Required for TOSCA http_ep[self.PATH] = ep.pop(self.PATH) http_ep[self.PORT] = ep.pop(self.PORT) - http_ep[self.POLL_INTVL] = ep.pop(self.POLL_INTVL_SECS) + if self.POLL_INTVL in http_ep: + http_ep[self.POLL_INTVL] = ep.pop(self.POLL_INTVL_SECS) if len(ep): self.log.warn(_("{0}, Did not process the following for " "http ep {1}").format(self, ep)) diff --git a/models/plugins/yang/mano-types.yang b/models/plugins/yang/mano-types.yang index 10135955..aad89724 100644 --- a/models/plugins/yang/mano-types.yang +++ b/models/plugins/yang/mano-types.yang @@ -1072,7 +1072,7 @@ module mano-types type string; } - leaf polling_interval_secs { + leaf polling-interval-secs { description "The HTTP polling interval in seconds"; type uint8; default 2;