TOSCA to YANG Translator Initial commit 30/1330/1
authorHashir Mohammed <hashir.mohammed@riftio.com>
Fri, 10 Feb 2017 19:10:47 +0000 (14:10 -0500)
committerHashir Mohammed <hashir.mohammed@riftio.com>
Mon, 20 Mar 2017 07:11:46 +0000 (03:11 -0400)
Signed-off-by: Hashir Mohammed <hashir.mohammed@riftio.com>
13 files changed:
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py [new file with mode: 0644]
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py [new file with mode: 0644]
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py [new file with mode: 0644]
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py [new file with mode: 0644]
common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py
common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py
models/plugins/yang/mano-types.yang

index 2b244d7..7bc0bf3 100755 (executable)
@@ -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 (file)
index 0000000..715ddc3
--- /dev/null
@@ -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 (file)
index 0000000..4e39236
--- /dev/null
@@ -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']
index 7c03d56..9b7cd03 100644 (file)
@@ -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:
index b446e51..a2dd92b 100644 (file)
@@ -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)
index 04e3a59..3574355 100644 (file)
@@ -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)
index 3e52967..e4e045e 100644 (file)
@@ -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 (file)
index 0000000..8b8771b
--- /dev/null
@@ -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
index 25246af..7f427f3 100644 (file)
@@ -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 (file)
index 0000000..0a54bcc
--- /dev/null
@@ -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
index dbfaa62..3f74336 100644 (file)
@@ -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):
index 7449c5a..9ff53e2 100644 (file)
@@ -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))
index 1013595..aad8972 100644 (file)
@@ -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;