Merge TOSCA changes from RIFT to OSM 04/1704/1
authorHashir Mohammed <hashir.mohammed@riftio.com>
Wed, 26 Apr 2017 15:56:02 +0000 (11:56 -0400)
committerHashir Mohammed <hashir.mohammed@riftio.com>
Wed, 26 Apr 2017 15:56:02 +0000 (11:56 -0400)
Signed-off-by: Hashir Mohammed <hashir.mohammed@riftio.com>
27 files changed:
common/python/CMakeLists.txt
common/python/rift/mano/tosca_translator/dummy_vnf_node.yaml
common/python/rift/mano/tosca_translator/rwmano/syntax/mano_template.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py
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_nfv_vnf.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py
common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_ns_service_primitive.py [new file with mode: 0644]
common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py
common/python/rift/mano/tosca_translator/shell.py
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa.zip [new file with mode: 0644]
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/ping_pong_nsd.yaml [new file with mode: 0644]
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/ping_vnfd.yaml [new file with mode: 0644]
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/pong_vnfd.yaml [new file with mode: 0644]
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/riftiotypes.yaml [new file with mode: 0644]
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/TOSCA-Metadata/TOSCA.meta [new file with mode: 0644]
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/scripts/ping_set_rate.py [new file with mode: 0755]
common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/scripts/start_traffic.py [new file with mode: 0755]
common/python/rift/mano/tosca_translator/test/tosca_translator_ut.py
common/python/rift/mano/yang_translator/riftiotypes.yaml
common/python/rift/mano/yang_translator/rwmano/syntax/tosca_resource.py
common/python/rift/mano/yang_translator/rwmano/syntax/tosca_template.py
common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py
common/python/rift/mano/yang_translator/rwmano/yang/yang_nsd.py
common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py
common/python/rift/mano/yang_translator/rwmano/yang_translator.py

index 8fba078..2c2c57d 100644 (file)
@@ -124,6 +124,7 @@ rift_python_install_tree(
     rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py
     rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py
     rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py
+    rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_ns_service_primitive.py
     rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py
     rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py
     rift/mano/tosca_translator/common/__init__.py
index 4debc76..21e32f4 100644 (file)
@@ -1,5 +1,5 @@
 tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
-description: Toy NS
+description: Translated from Tosca
 data_types:
   tosca.datatypes.nfv.riftio.dashboard_params:
     properties:
index d263e6f..ba0bd2a 100644 (file)
@@ -69,6 +69,8 @@ class ManoTemplate(object):
                 nsd.vendor = self.metadata['vendor']
                 nsd.short_name = self.metadata['name']
                 nsd.version = self.metadata['version']
+                if 'logo' in self.metadata:
+                    nsd.logo = self.metadata['logo']
             except Exception as e:
                 self.log.warning(_("Unable to use YANG GI to generate "
                                    "descriptors, falling back to alternate "
@@ -91,10 +93,25 @@ class ManoTemplate(object):
             if resource.type == 'vld':
                 resource.generate_yang_model(nsd, vnfds, use_gi=use_gi)
 
+        vnf_type_duplicate = []
+        vnfd_resources = []
+        vnfd_duplicate_resource_list = []
         for resource in self.resources:
-            # Do the vnfds next
             if resource.type == 'vnfd':
+                vnfd_resources.append(resource)
+
+        vnfd_resources.sort(key=lambda x: x.member_vnf_id, reverse=False)
+        vnf_type_to_vnf_id = {}
+        for resource in vnfd_resources:
+            if resource.vnf_type not in vnf_type_duplicate:
                 resource.generate_yang_model(nsd, vnfds, use_gi=use_gi)
+                vnf_type_to_vnf_id[resource.vnf_type] = resource.id
+                vnf_type_duplicate.append(resource.vnf_type)
+            else:
+                vnfd_duplicate_resource_list.append(resource)
+
+        for resource in vnfd_duplicate_resource_list:
+            resource.generate_nsd_constiuent(nsd, vnf_type_to_vnf_id[resource.vnf_type])
 
         for resource in self.resources:
             # Do the other nodes
@@ -127,7 +144,7 @@ class ManoTemplate(object):
         # Need to add support to get script names, charms, etc.
         other_files = {}
         for resource in self.resources:
-            resource.get_supporting_files(other_files)
+            resource.get_supporting_files(other_files, desc_id=nsd_id)
 
         for policy in self.policies:
             policy.get_supporting_files(other_files, desc_id=nsd_id)
index 7938485..190a5b4 100755 (executable)
@@ -101,12 +101,7 @@ class ToscaCompute(ManoResource):
                        format(self.name, tosca_props))
         vdu_props = {}
         for key, value in tosca_props.items():
-            if key == 'cloud_init':
-                vdu_props['cloud-init'] = value
-            elif key == 'cloud-init-file':
-                self._cloud_init = "../cloud_init/{}".format(value)
-            else:
-                vdu_props[key] = value
+            vdu_props[key] = value
 
         if 'name' not in vdu_props:
             vdu_props['name'] = self.name
@@ -290,8 +285,6 @@ class ToscaCompute(ManoResource):
             self.properties['guest-epa'] = get_guest_epa(tosca_caps['numa_extension'], tosca_caps['nfv_compute'])
         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'])
         if len(self._mgmt_interface) > 0:
@@ -303,7 +296,20 @@ class ToscaCompute(ManoResource):
                     prop['port'] = self._mgmt_interface['dashboard-params']['port']
                 self._http_endpoint = prop
 
+        mon_idx = 2
+        monitoring_param_name = 'monitoring_param_1'
+        while True:
+            if monitoring_param_name in tosca_caps:
+                self._monitor_param.append(get_monitor_param(tosca_caps[monitoring_param_name], str(mon_idx)))
+                mon_idx += 1
+                monitoring_param_name = 'monitoring_param_{}'.format(mon_idx)
+            else:
+                break
 
+        # THis is a quick hack to remove monitor params without name
+        for mon_param in list(self._monitor_param):
+            if 'name' not in mon_param:
+                self._monitor_param.remove(mon_param)
 
     def handle_artifacts(self):
         if self.artifacts is None:
@@ -343,8 +349,8 @@ class ToscaCompute(ManoResource):
         self.artifacts = arts
 
     def handle_interfaces(self):
-        # Currently, we support only create operation
-        operations_deploy_sequence = ['create']
+        # Currently, we support the following:
+        operations_deploy_sequence = ['create', 'configure']
 
         operations = ManoResource._get_all_operations(self.nodetemplate)
 
@@ -357,7 +363,11 @@ class ToscaCompute(ManoResource):
                     self.operations[operation.name] = operation.implementation
                     for name, details in self.artifacts.items():
                         if name == operation.implementation:
-                            self._image = details['file']
+                            if operation.name == 'create':
+                                self._image = details['file']
+                            elif operation.name == 'configure':
+                                self._cloud_init = details['file']
+                            break
                 except KeyError as e:
                     self.log.exception(e)
         return None
@@ -412,6 +422,9 @@ class ToscaCompute(ManoResource):
             if self._image_cksum:
                 self.properties['image-checksum'] = self._image_cksum
 
+        if self._cloud_init:
+            self.properties['cloud-init-file'] = os.path.basename(self._cloud_init)
+
         for key in ToscaCompute.IGNORE_PROPS:
             if key in self.properties:
                 self.properties.pop(key)
index 9b7cd03..262c11a 100644 (file)
@@ -53,8 +53,7 @@ class ToscaInitialConfig(ManoResource):
         self.log.debug(_("{0} with tosca properties: {1}").
                        format(self, tosca_props))
         self.properties['name'] = tosca_props['name']
-        self.properties['seq'] = \
-                                tosca_props['seq']
+        self.properties['seq'] = int(tosca_props['seq'])
         self.properties['user-defined-script'] = \
                                 tosca_props['user_defined_script']
         self.scripts.append('../scripts/{}'. \
@@ -62,12 +61,11 @@ class ToscaInitialConfig(ManoResource):
 
         if 'parameter' in tosca_props:
             self.properties['parameter'] = []
-            for name, value in tosca_props['parameter'].items():
+            for parameter in tosca_props['parameter']:
                 self.properties['parameter'].append({
-                    'name': name,
-                    'value': value,
+                    'name': parameter['name'],
+                    'value': str(parameter['value']),
                 })
-
         self.log.debug(_("{0} properties: {1}").format(self, self.properties))
 
     def get_policy_props(self):
index a9f9c77..88a8a31 100644 (file)
@@ -91,8 +91,8 @@ class ToscaNetwork(ManoResource):
                 ip_profile_param['ip-version'] = 'ipv' + str(specs['ip_version'])
             if 'cidr' in specs:
                 ip_profile_param['subnet-address'] = specs['cidr']
+                ip_profile_prop['ip-profile-params'] = ip_profile_param
 
-            ip_profile_prop['ip-profile-params'] = ip_profile_param
             return ip_profile_prop
         tosca_props = self.get_tosca_props()
         self._vld = get_vld_props(tosca_props)
@@ -128,7 +128,8 @@ class ToscaNetwork(ManoResource):
         ip_profile_props = convert_keys_to_python(self._ip_profile)
         try:
             nsd.vld.add().from_dict(vld_props)
-            nsd.ip_profiles.add().from_dict(ip_profile_props)
+            if len(ip_profile_props) > 1:
+                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 e4e045e..3346da0 100644 (file)
@@ -61,7 +61,9 @@ class ToscaNfvVnf(ManoResource):
         self._policies = []
         self._cps = []
         self.vnf_type = nodetemplate.type
+        self.member_vnf_id = None
         self._reqs = {}
+        self.logo = None
 
     def map_tosca_name_to_mano(self, name):
         new_name = super().map_tosca_name_to_mano(name)
@@ -120,6 +122,7 @@ class ToscaNfvVnf(ManoResource):
             if key == 'id':
                 self._const_vnfd['member-vnf-index'] = int(value)
                 self._const_vnfd['vnfd-id-ref'] = self.id
+                self.member_vnf_id = int(value)
             elif key == 'vnf_configuration':
                 self._vnf_config = get_vnf_config(value)
             else:
@@ -145,6 +148,8 @@ class ToscaNfvVnf(ManoResource):
                                         vnf_props.pop('start_by_default')
         if 'logo' in self.metadata:
             vnf_props['logo'] = self.metadata['logo']
+            self.logo = self.metadata['logo']
+
 
         self.log.debug(_("VNF {0} with constituent vnf: {1}").
                        format(self.name, self._const_vnfd))
@@ -295,6 +300,12 @@ class ToscaNfvVnf(ManoResource):
             nsd['constituent-vnfd'] = []
         nsd['constituent-vnfd'].append(self._const_vnfd)
 
+    def generate_nsd_constiuent(self, nsd, vnf_id):
+        self._const_vnfd['vnfd-id-ref'] = vnf_id
+        props = convert_keys_to_python(self._const_vnfd)
+        nsd.constituent_vnfd.add().from_dict(props)
+
+
     def get_member_vnf_index(self):
         return self._const_vnfd['member-vnf-index']
 
@@ -311,3 +322,10 @@ class ToscaNfvVnf(ManoResource):
                     'type': 'cloud_init',
                     'name': vdu.cloud_init,
                 },)
+        if self.logo is not None:
+            files[desc_id] = []
+            file_location = "../icons/{}".format(self.logo)
+            files[desc_id].append({
+                    'type': 'icons',
+                    'name': file_location,
+                },)
index f90c187..23cebfd 100644 (file)
@@ -71,15 +71,16 @@ class ToscaVnfConfiguration(ManoResource):
                     prop["script"]["script-type"] = tosca_props['config']['config_details']['script_type']
             if 'initial_config' in tosca_props:
                 prop['initial-config-primitive'] = []
-                #print("Weleek  " + str(tosca_props['initial_config']))
                 for init_config in tosca_props['initial_config']:
                     if 'parameter' in init_config:
                         parameters = init_config.pop('parameter')
                         init_config['parameter'] = []
-                        for key, value in parameters.items():
-                            init_config['parameter'].append({'name': key, 'value': str(value)})
-                            if 'user_defined_script' in init_config:
-                                self.scripts.append('../scripts/{}'. \
+                        for parameter in parameters:
+                            for key, value in parameter.items():
+                                init_config['parameter'].append({'name': key, 'value': str(value)})
+
+                    if 'user_defined_script' in init_config:
+                        self.scripts.append('../scripts/{}'. \
                                 format(init_config['user_defined_script']))
                     prop['initial-config-primitive'].append(init_config)
 
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_ns_service_primitive.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_ns_service_primitive.py
new file mode 100644 (file)
index 0000000..eef4a9e
--- /dev/null
@@ -0,0 +1,119 @@
+#
+# 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 = 'ToscaVnfNSServiceConfiguration'
+
+
+class ToscaVnfNSServiceConfiguration(ManoResource):
+    '''Translate TOSCA node type tosca.policies.Scaling.'''
+
+    toscatype = 'tosca.policies.nfv.riftio.ns_service_primitives'
+
+    IGNORE_PROPS = []
+    VALUE_TYPE_CONVERSION_MAP =  {
+    'integer': 'INTEGER',
+    'string':'STRING',
+    'float':'DECIMAL',
+    'INTEGER': 'INTEGER',
+    'FLOAT':'DECIMAL'
+
+    }
+
+    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.linked_to_vnf = False
+        self.policy = policy
+        self.service_primitive = None
+        self.properties = {}
+        self.scripts = []
+
+    def __str__(self):
+        return "%s(%s)" % (self.name, self.type)
+
+    def handle_properties(self, nodes, groups):
+        tosca_props = self.get_policy_props()
+        service_primitive = {}
+        if 'name' in tosca_props:
+            service_primitive['name'] = tosca_props['name']
+        if 'user_defined_script' in tosca_props:
+            service_primitive['user_defined_script'] = tosca_props['user_defined_script']
+            self.scripts.append('../scripts/{}'. \
+                                format(tosca_props['user_defined_script']))
+
+        
+        if 'parameter' in tosca_props:
+            service_primitive['parameter'] = []
+            for parameter in tosca_props['parameter']:
+                prop = {}
+                if 'name' in parameter:
+                    prop['name'] = parameter['name']
+                if 'hidden' in parameter:
+                    prop['hidden'] = parameter['hidden']
+                if 'mandatory' in parameter:
+                    prop['mandatory'] = parameter['mandatory']
+                if 'data_type' in parameter:
+                    prop['data_type'] = ToscaVnfNSServiceConfiguration.VALUE_TYPE_CONVERSION_MAP[parameter['data_type']]
+                if 'default_value' in parameter:
+                    prop['default_value'] = str(parameter['default_value'])
+                service_primitive['parameter'].append(prop)
+
+        self.service_primitive = service_primitive
+
+
+
+
+        #self.properties = prop
+
+    def generate_yang_submodel_gi(self, vnfd):
+        pass
+
+    def generate_yang_model(self, nsd, vnfds, use_gi):
+        if self.service_primitive is not None:
+            nsd.service_primitive.add().from_dict(self.service_primitive)
+
+    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_supporting_files(self, files, desc_id=None):
+        if not len(self.scripts):
+            return
+        if desc_id not in files:
+            return
+        for script in self.scripts:
+            files[desc_id].append({
+                'type': 'script',
+                'name': script,
+            },)
\ No newline at end of file
index 2d6c3e1..ef36e56 100644 (file)
@@ -167,6 +167,7 @@ class TranslateNodeTemplates(object):
         self.log.debug(_("Metadata {0}").format(metadata))
         self.metadata = metadata
 
+
     def _recursive_handle_properties(self, resource):
         '''Recursively handle the properties of the depends_on_nodes nodes.'''
         # Use of hashtable (dict) here should be faster?
@@ -227,8 +228,9 @@ class TranslateNodeTemplates(object):
                     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)
+            if template.substitution_mappings.requirements:
+                for req in template.substitution_mappings.requirements:
+                    vnf_type_substitution_mapping[template.substitution_mappings.node_type].append(req)
             if template.substitution_mappings.capabilities:
                 for capability in template.substitution_mappings.capabilities:
                     sub_list = template.substitution_mappings.capabilities[capability]
@@ -273,7 +275,6 @@ class TranslateNodeTemplates(object):
                             metadata=self.metadata)
                 mano_node.vnf_type = vnf_type
                 self.mano_resources.append(mano_node)
-                print("Adding a new node")
 
             for node in self.tosca.nodetemplates:
                 if 'VDU' in node.type:
@@ -317,6 +318,7 @@ class TranslateNodeTemplates(object):
                                          vnf_name=vnf_node)
                         self.mano_policies.append(policy_node)
 
+        vnfd_resources = []
         for node in self.mano_resources:
             self.log.debug(_("Handle properties for {0} of type {1}").
                            format(node.name, node.type_))
@@ -338,6 +340,22 @@ class TranslateNodeTemplates(object):
                            format(node.name, node.type_))
             node.update_image_checksum(self.tosca.path)
 
+        for node in list(self.mano_resources):
+            if node.type == "vnfd":
+                vnfd_resources.append(node)
+                self.mano_resources.remove(node)
+
+        vnfd_resources.sort(key=lambda x: x.member_vnf_id, reverse=True)
+        vnf_type_duplicate_map = {}
+        for node in reversed(vnfd_resources):
+            if node.vnf_type in vnf_type_duplicate_map:
+                for policy in self.mano_policies:
+                    if hasattr(policy, '_vnf_name') and policy._vnf_name == node.name:
+                        policy._vnf_name = vnf_type_duplicate_map[node.vnf_type]
+                continue
+            vnf_type_duplicate_map[node.vnf_type] = node.name
+
+        self.mano_resources.extend(vnfd_resources)
         for node in self.mano_resources:
             # Handle vnf and vdu dependencies first
             if node.type == "vnfd":
index 9221c79..b5529f0 100644 (file)
@@ -364,6 +364,8 @@ class TranslatorShell(object):
                         dest = os.path.join(output_dir, 'images')
                     elif ty == 'script':
                         dest = os.path.join(output_dir, 'scripts')
+                    elif ty == 'icons':
+                        dest = os.path.join(output_dir, 'icons')
                     elif ty == 'cloud_init':
                         dest = os.path.join(output_dir, 'cloud_init')
                     else:
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa.zip b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa.zip
new file mode 100644 (file)
index 0000000..5ca9064
Binary files /dev/null and b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa.zip differ
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/ping_pong_nsd.yaml b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/ping_pong_nsd.yaml
new file mode 100644 (file)
index 0000000..05bfd91
--- /dev/null
@@ -0,0 +1,57 @@
+tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
+description: Toy NS
+metadata:
+  ID: ping_pong_nsd
+  vendor: RIFT.io
+  version: 1.0
+imports:
+- "ping_vnfd.yaml"
+- "pong_vnfd.yaml"
+topology_template:
+  policies:
+  - initial_config_primitive:
+      properties:
+        name: start traffic
+        seq: 1
+        user_defined_script: start_traffic.py
+      targets: [pong_vnfd]
+      type: tosca.policies.nfv.riftio.initial_config_primitive
+  - placement_0:
+      properties:
+        name: Orcus
+        requirement: Place this VM on the Kuiper belt object Orcus
+        strategy: COLOCATION
+      targets: [ping_vnfd, pong_vnfd]
+      type: tosca.policies.nfv.riftio.placement
+  - placement_1:
+      properties:
+        name: Quaoar
+        requirement: Place this VM on the Kuiper belt object Quaoar
+        strategy: COLOCATION
+      targets: [ping_vnfd, pong_vnfd]
+      type: tosca.policies.nfv.riftio.placement
+  node_templates:
+    pong_vnfd:
+      type: tosca.nodes.nfv.riftio.pongvnfdVNF
+      properties:
+        id: 2
+        vendor: RIFT.io
+        version: 1.0
+      requirements:
+      - virtualLink1: ping_pong_vld
+    ping_pong_vld:
+      type: tosca.nodes.nfv.riftio.ELAN
+      properties:
+        cidr: 31.31.31.0/24
+        description: Toy VL
+        gateway_ip: 31.31.31.210
+        ip_version: 4
+        vendor: RIFT.io
+    ping_vnfd:
+      type: tosca.nodes.nfv.riftio.pingvnfdVNF
+      properties:
+        id: 1
+        vendor: RIFT.io
+        version: 1.0
+      requirements:
+      - virtualLink1: ping_pong_vld
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/ping_vnfd.yaml b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/ping_vnfd.yaml
new file mode 100644 (file)
index 0000000..d566a07
--- /dev/null
@@ -0,0 +1,132 @@
+tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
+description: This is an example RIFT.ware VNF
+metadata:
+  ID: ping_vnfd
+  vendor: RIFT.io
+  version: 1.0
+imports:
+- riftiotypes.yaml
+node_types:
+  tosca.nodes.nfv.riftio.pingvnfdVNF:
+    derived_from: tosca.nodes.nfv.riftio.VNF1
+    requirements:
+    - virtualLink1:
+        type: tosca.nodes.nfv.VL
+topology_template:
+  policies:
+  - configuration:
+      properties:
+        config:
+          config_delay: 0
+          config_details:
+            script_type: bash
+          config_priority: 2
+          config_template: "\n#!/bin/bash\n\n# Rest API config\nping_mgmt_ip=<rw_mgmt_ip>\n\
+            ping_mgmt_port=18888\n\n# VNF specific configuration\npong_server_ip=<rw_connection_point_name\
+            \ pong_vnfd/cp0>\nping_rate=5\nserver_port=5555\n\n# Make rest API calls\
+            \ to configure VNF\ncurl -D /dev/null \\\n    -H \"Accept: application/vnd.yang.data+xml\"\
+            \ \\\n    -H \"Content-Type: application/vnd.yang.data+json\" \\\n   \
+            \ -X POST \\\n    -d \"{\\\"ip\\\":\\\"$pong_server_ip\\\", \\\"port\\\
+            \":$server_port}\" \\\n    http://${ping_mgmt_ip}:${ping_mgmt_port}/api/v1/ping/server\n\
+            rc=$?\nif [ $rc -ne 0 ]\nthen\n    echo \"Failed to set server info for\
+            \ ping!\"\n    exit $rc\nfi\nexit 0\n"
+          config_type: script
+        initial_config_primitive:
+        - name: set ping rate
+          parameter:
+          - rate: 5
+          seq: 1
+          user_defined_script: ping_set_rate.py
+      targets: [ping_vnfd_iovdu_0]
+      type: tosca.policies.nfv.riftio.vnf_configuration
+  substitution_mappings:
+    node_type: tosca.nodes.nfv.riftio.pingvnfdVNF
+    requirements:
+    - virtualLink1: [ping_vnfd_cp0, virtualLink]
+  node_templates:
+    ping_vnfd_iovdu_0:
+      type: tosca.nodes.nfv.riftio.VDU1
+      properties:
+        cloud_init: "#cloud-config\npassword: fedora\nchpasswd: { expire: False }\n\
+          ssh_pwauth: True\nruncmd:\n  - [ systemctl, daemon-reload ]\n  - [ systemctl,\
+          \ enable, ping.service ]\n  - [ systemctl, start, --no-block, ping.service\
+          \ ]\n  - [ ifup, eth1 ]\n"
+        count: 1
+      capabilities:
+        hypervisor_epa:
+          properties:
+            type: PREFER_KVM
+            version: 1
+        mgmt_interface:
+          properties:
+            dashboard_params:
+              path: api/v1/ping/stats
+              port: 18888
+            port: 18888
+            protocol: tcp
+        monitoring_param:
+          properties:
+            description: no of ping requests
+            json_query_method: namekey
+            name: ping-request-tx-count
+            ui_data:
+              group_tag: Group1
+              units: packets
+              widget_type: counter
+            url_path: api/v1/ping/stats
+        monitoring_param_1:
+          properties:
+            description: no of ping responses
+            json_query_method: namekey
+            name: ping-response-rx-count
+            ui_data:
+              group_tag: Group1
+              units: packets
+              widget_type: counter
+            url_path: api/v1/ping/stats
+        nfv_compute:
+          properties:
+            cpu_allocation:
+              cpu_affinity: dedicated
+              thread_allocation: prefer
+            disk_size: 4 GB
+            mem_page_size: normal
+            mem_size: 1024 MB
+            num_cpus: 4
+        numa_extension:
+          properties:
+            mem_policy: STRICT
+            node:
+            - id: 0
+              mem_size: 512 MB
+              vcpus:
+              - 0
+              - 1
+            - id: 1
+              mem_size: 512 MB
+              vcpus:
+              - 2
+              - 3
+            node_cnt: 2
+        vswitch_epa:
+          properties:
+            ovs_acceleration: DISABLED
+            ovs_offload: DISABLED
+      artifacts:
+        ping_vnfd_iovdu_0_vm_image:
+          file: ../images/Fedora-x86_64-20-20131211.1-sda-ping.qcow2
+          image_checksum: a6ffaa77f949a9e4ebb082c6147187cf
+          type: tosca.artifacts.Deployment.Image.riftio.QCOW2
+      interfaces:
+        Standard:
+          create: ping_vnfd_iovdu_0_vm_image
+    ping_vnfd_cp0:
+      type: tosca.nodes.nfv.riftio.CP1
+      properties:
+        cp_type: VPORT
+        name: ping_vnfd/cp0
+        vdu_intf_name: eth0
+        vdu_intf_type: VIRTIO
+      requirements:
+      - virtualBinding:
+          node: ping_vnfd_iovdu_0
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/pong_vnfd.yaml b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/pong_vnfd.yaml
new file mode 100644 (file)
index 0000000..aeb160c
--- /dev/null
@@ -0,0 +1,127 @@
+tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
+description: This is an example RIFT.ware VNF
+metadata:
+  ID: pong_vnfd
+  vendor: RIFT.io
+  version: 1.0
+imports:
+- riftiotypes.yaml
+node_types:
+  tosca.nodes.nfv.riftio.pongvnfdVNF:
+    derived_from: tosca.nodes.nfv.riftio.VNF1
+    requirements:
+    - virtualLink1:
+        type: tosca.nodes.nfv.VL
+topology_template:
+  policies:
+  - configuration:
+      properties:
+        config:
+          config_delay: 60
+          config_details:
+            script_type: bash
+          config_priority: 1
+          config_template: "\n#!/bin/bash\n\n# Rest API configuration\npong_mgmt_ip=<rw_mgmt_ip>\n\
+            pong_mgmt_port=18889\n# username=<rw_username>\n# password=<rw_password>\n\
+            \n# VNF specific configuration\npong_server_ip=<rw_connection_point_name\
+            \ pong_vnfd/cp0>\nserver_port=5555\n\n# Make Rest API calls to configure\
+            \ VNF\ncurl -D /dev/null \\\n    -H \"Accept: application/vnd.yang.data+xml\"\
+            \ \\\n    -H \"Content-Type: application/vnd.yang.data+json\" \\\n   \
+            \ -X POST \\\n    -d \"{\\\"ip\\\":\\\"$pong_server_ip\\\", \\\"port\\\
+            \":$server_port}\" \\\n    http://${pong_mgmt_ip}:${pong_mgmt_port}/api/v1/pong/server\n\
+            rc=$?\nif [ $rc -ne 0 ]\nthen\n    echo \"Failed to set server(own) info\
+            \ for pong!\"\n    exit $rc\nfi\n\nexit 0\n"
+          config_type: script
+      targets: [pong_vnfd_iovdu_0]
+      type: tosca.policies.nfv.riftio.vnf_configuration
+  substitution_mappings:
+    node_type: tosca.nodes.nfv.riftio.pongvnfdVNF
+    requirements:
+    - virtualLink1: [pong_vnfd_cp0, virtualLink]
+  node_templates:
+    pong_vnfd_iovdu_0:
+      type: tosca.nodes.nfv.riftio.VDU1
+      properties:
+        cloud_init: "#cloud-config\npassword: fedora\nchpasswd: { expire: False }\n\
+          ssh_pwauth: True\nruncmd:\n  - [ systemctl, daemon-reload ]\n  - [ systemctl,\
+          \ enable, pong.service ]\n  - [ systemctl, start, --no-block, pong.service\
+          \ ]\n  - [ ifup, eth1 ]\n"
+        count: 1
+      capabilities:
+        hypervisor_epa:
+          properties:
+            type: PREFER_KVM
+            version: 1
+        mgmt_interface:
+          properties:
+            dashboard_params:
+              path: api/v1/pong/stats
+              port: 18889
+            port: 18889
+            protocol: tcp
+        monitoring_param:
+          properties:
+            description: no of ping requests
+            json_query_method: namekey
+            name: ping-request-rx-count
+            ui_data:
+              group_tag: Group1
+              units: packets
+              widget_type: counter
+            url_path: api/v1/pong/stats
+        monitoring_param_1:
+          properties:
+            description: no of ping responses
+            json_query_method: namekey
+            name: ping-response-tx-count
+            ui_data:
+              group_tag: Group1
+              units: packets
+              widget_type: counter
+            url_path: api/v1/pong/stats
+        nfv_compute:
+          properties:
+            cpu_allocation:
+              cpu_affinity: dedicated
+              thread_allocation: prefer
+            disk_size: 4 GB
+            mem_page_size: normal
+            mem_size: 1024 MB
+            num_cpus: 4
+        numa_extension:
+          properties:
+            mem_policy: STRICT
+            node:
+            - id: 0
+              mem_size: 512 MB
+              vcpus:
+              - 0
+              - 1
+            - id: 1
+              mem_size: 512 MB
+              vcpus:
+              - 2
+              - 3
+            node_cnt: 2
+        vswitch_epa:
+          properties:
+            ovs_acceleration: DISABLED
+            ovs_offload: DISABLED
+      artifacts:
+        pong_vnfd_iovdu_0_vm_image:
+          file: ../images/Fedora-x86_64-20-20131211.1-sda-pong.qcow2
+          image_checksum: 977484d95575f80ef8399c9cf1d45ebd
+          type: tosca.artifacts.Deployment.Image.riftio.QCOW2
+      interfaces:
+        Standard:
+          create: pong_vnfd_iovdu_0_vm_image
+    pong_vnfd_cp0:
+      type: tosca.nodes.nfv.riftio.CP1
+      properties:
+        cp_type: VPORT
+        name: pong_vnfd/cp0
+        vdu_intf_name: eth0
+        vdu_intf_type: VIRTIO
+      requirements:
+      - virtualBinding:
+          node: pong_vnfd_iovdu_0
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/riftiotypes.yaml b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/Definitions/riftiotypes.yaml
new file mode 100644 (file)
index 0000000..18a0728
--- /dev/null
@@ -0,0 +1,1493 @@
+tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
+description: Extended types
+
+
+data_types:
+  tosca.datatypes.nfv.riftio.dashboard_params:
+    properties:
+      path:
+        type: string
+        description: >-
+          The HTTP path for the dashboard
+      port:
+        type: tosca.datatypes.network.PortDef
+        description: >-
+          The HTTP port for the dashboard
+        default: 80
+      https:
+        type: boolean
+        description: >-
+          Pick HTTPS instead of HTTP , Default is false
+        default: false
+        required: false
+  tosca.datatypes.nfv.riftio.monitoring_param_ui:
+    properties:
+      description:
+        type: string
+        required: false
+      group_tag:
+        type: string
+        description: >-
+          A simple tag to group monitoring parameters
+        required: false
+      widget_type:
+        type: string
+        description: >-
+          Type of the widget
+        default: counter
+        constraints:
+          - valid_values:
+              - histogram
+              - bar
+              - gauge
+              - slider
+              - counter
+              - textbox
+      units:
+        type: string
+        required: false
+  tosca.datatypes.nfv.riftio.monitoring_param_value:
+    properties:
+      value_type:
+        type: string
+        default: integer
+        constraints:
+          - valid_values:
+              - integer
+              - float
+              - string
+      numeric_min:
+        type: integer
+        description: >-
+          Minimum value for the parameter
+        required: false
+      numeric_max:
+        type: integer
+        description: >-
+          Maxium value for the parameter
+        required: false
+      string_min:
+        type: integer
+        description: >-
+          Minimum string length for the parameter
+        required: false
+        constraints:
+          - greater_or_equal: 0
+      string_max:
+        type: integer
+        description: >-
+          Maximum string length for the parameter
+        required: false
+        constraints:
+          - greater_or_equal: 0
+  tosca.datatypes.compute.Container.Architecture.CPUAllocation:
+    derived_from: tosca.datatypes.Root
+    properties:
+      cpu_affinity:
+        type: string
+        required: false
+        constraints:
+          - valid_values: [shared, dedicated, any]
+      thread_allocation:
+        type: string
+        required: false
+        constraints:
+          - valid_values: [avoid, separate, isolate, prefer]
+      socket_count:
+        type: integer
+        required: false
+      core_count:
+        type: integer
+        required: false
+      thread_count:
+        type: integer
+        required: false
+
+  tosca.datatypes.compute.Container.Architecture.NUMA:
+    derived_from: tosca.datatypes.Root
+    properties:
+      id:
+        type: integer
+        constraints:
+          - greater_or_equal: 0
+      vcpus:
+        type: list
+        entry_schema:
+          type: integer
+          constraints:
+            -  greater_or_equal: 0
+      mem_size:
+        type: scalar-unit.size
+        constraints:
+          - greater_or_equal: 0 MB
+  tosca.datatypes.nfv.riftio.paired_thread_map:
+    properties:
+      thread_a:
+        type: integer
+        required: true
+        constraints:
+          - greater_or_equal: 0
+      thread_b:
+        type: integer
+        required: true
+        constraints:
+          - greater_or_equal: 0
+
+  tosca.datatypes.nfv.riftio.paired_threads:
+    properties:
+      num_paired_threads:
+        type: integer
+        constraints:
+          - greater_or_equal: 1
+      paired_thread_ids:
+        type: list
+        entry_schema:
+          type: tosca.datatypes.nfv.riftio.paired_thread_map
+        constraints:
+          - max_length: 16
+        required: false
+
+  tosca.datatypes.compute.riftio.numa:
+    properties:
+      id:
+        type: integer
+        constraints:
+          - greater_or_equal: 0
+      vcpus:
+        type: list
+        entry_schema:
+          type: integer
+          constraints:
+            -  greater_or_equal: 0
+        required: false
+      mem_size:
+        type: scalar-unit.size
+        constraints:
+          - greater_or_equal: 0 MB
+        required: false
+      om_numa_type:
+        type: string
+        description: Openmano Numa type selection
+        constraints:
+          - valid_values: [cores, paired-threads, threads]
+        required: false
+      num_cores:
+        type: integer
+        description: Use when om_numa_type is cores
+        constraints:
+          - greater_or_equal: 1
+        required: false
+      paired_threads:
+        type: tosca.datatypes.nfv.riftio.paired_threads
+        description: Use when om_numa_type is paired-threads
+        required: false
+      num_threads:
+        type: integer
+        description: Use when om_numa_type is threads
+        constraints:
+          - greater_or_equal: 1
+        required: false
+  
+  tosca.nfv.datatypes.pathType:
+    properties:
+      forwarder:
+        type: string
+        required: true
+      capability:
+        type: string
+        required: true
+
+  tosca.nfv.datatypes.aclType:
+    properties:
+      eth_type:
+        type: string
+        required: false
+      eth_src:
+        type: string
+        required: false
+      eth_dst:
+        type: string
+        required: false
+      vlan_id:
+        type: integer
+        constraints:
+          - in_range: [ 1, 4094 ]
+        required: false
+      vlan_pcp:
+        type: integer
+        constraints:
+          - in_range: [ 0, 7 ]
+        required: false
+      mpls_label:
+        type: integer
+        constraints:
+          - in_range: [ 16, 1048575]
+        required: false
+      mpls_tc:
+        type: integer
+        constraints:
+          - in_range: [ 0, 7 ]
+        required: false
+      ip_dscp:
+        type: integer
+        constraints:
+          - in_range: [ 0, 63 ]
+        required: false
+      ip_ecn:
+        type: integer
+        constraints:
+          - in_range: [ 0, 3 ]
+        required: false
+      ip_src_prefix:
+        type: string
+        required: false
+      ip_dst_prefix:
+        type: string
+        required: false
+      ip_proto:
+        type: integer
+        constraints:
+          - in_range: [ 1, 254 ]
+        required: false
+      destination_port_range:
+        type: integer
+        required: false
+      source_port_range:
+        type: integer
+        required: false
+      network_src_port_id:
+        type: string
+        required: false
+      network_dst_port_id:
+        type: string
+        required: false
+      network_id:
+        type: string
+        required: false
+      network_name:
+        type: string
+        required: false
+      tenant_id:
+        type: string
+        required: false
+      icmpv4_type:
+        type: integer
+        constraints:
+          - in_range: [ 0, 254 ]
+        required: false
+      icmpv4_code:
+        type: integer
+        constraints:
+          - in_range: [ 0, 15 ]
+        required: false
+      arp_op:
+        type: integer
+        constraints:
+          - in_range: [ 1, 25 ]
+        required: false
+      arp_spa:
+        type: string
+        required: false
+      arp_tpa:
+        type: string
+        required: false
+      arp_sha:
+        type: string
+        required: false
+      arp_tha:
+        type: string
+        required: false
+      ipv6_src:
+        type: string
+        required: false
+      ipv6_dst:
+        type: string
+        required: false
+      ipv6_flabel:
+        type: integer
+        constraints:
+          - in_range: [ 0, 1048575]
+        required: false
+      icmpv6_type:
+        type: integer
+        constraints:
+          - in_range: [ 0, 255]
+        required: false
+      icmpv6_code:
+        type: integer
+        constraints:
+          - in_range: [ 0, 7]
+        required: false
+      ipv6_nd_target:
+        type: string
+        required: false
+      ipv6_nd_sll:
+        type: string
+        required: false
+      ipv6_nd_tll:
+        type: string
+        required: false
+
+  
+  tosca.datatypes.nfv.riftio.vnf_configuration:
+    properties:
+      config_type:
+        type: string
+        description: >-
+          Type of the configuration agent to use
+        constraints:
+          - valid_values: [script, netconf, rest, juju]
+      config_details:
+        type: map
+        description: >-
+          Specify the details for the config agent, like
+          script type, juju charm to use, etc.
+      config_template:
+        required: false
+        type: string
+      config_delay:
+        type: integer
+        constraints:
+        - greater_or_equal: 0
+        default: 0
+        required: false
+      config_priority:
+        type: integer
+        constraints:
+        - greater_than: 0
+
+  tosca.datatypes.nfv.riftio.parameter_value:
+    properties:
+      name:
+        type: string
+        description: Name of the parameter
+      value:
+        type: string
+        description: Value of the parameter
+
+  tosca.datatypes.nfv.riftio.config_primitive:
+    properties:
+      name:
+        type: string
+      seq:
+        type: integer
+        description: >-
+          Order in which to apply, when multiple ones are defined
+        default: 0
+        constraints:
+          - greater_or_equal: 0
+      parameter:
+        type: list
+        entry_schema:
+          type: tosca.datatypes.nfv.riftio.parameter_value
+      user_defined_script:
+        type: string
+  tosca.datatypes.nfv.riftio.primitive_parameter:
+    properties:
+      data_type:
+        type: string
+        description: >-
+          Data type associated with the name
+        constraints:
+          - valid_values: [string, integer, boolean]
+      mandatory:
+        type: boolean
+        description: >-
+          If this field is mandatory
+        default: false
+        required: false
+      default_value:
+        type: string
+        description: >-
+          The default value for this field
+        required: false
+      parameter_pool:
+        type: string
+        description: >-
+          Parameter pool name to use for this parameter
+        required: false
+      read_only:
+        type: boolean
+        description: >-
+          The value should be greyed out by the UI.
+          Only applies to parameters with default values.
+        required: false
+        default: false
+      hidden:
+        type: boolean
+        description: >-
+          The field should be hidden by the UI.
+          Only applies to parameters with default values.
+        required: false
+        default: false
+  tosca.datatypes.nfv.riftio.primitive_parameter_group:
+    properties:
+      name:
+        type: string
+        description: >-
+          Name of the parameter group
+      mandatory:
+        type: boolean
+        description: >-
+          If this group is mandatory
+        default: false
+        required: false
+      parameter:
+        type: map
+        description: >-
+          List of parameters for the service primitive
+        entry_schema: osca.datatypes.riftio.primitive_parameter
+
+  tosca.datatypes.nfv.riftio.vnf_primitive_group:
+    properties:
+      vnf_name:
+        type: string
+        description: >-
+          Name of the VNF in the NS
+      primitive:
+        type: map
+        entry_schema:
+          type: string
+        description: >-
+          Index and name of the primitive
+
+
+capability_types:
+  tosca.capabilities.nfv.riftio.mgmt_interface:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      static_ip:
+        type: string
+        required: false
+        description: >-
+          Specifies the static IP address for managing the VNF
+      connection_point:
+        type: string
+        required: false
+        description: >-
+          Use the ip address associated with this connection point
+      dashboard_params:
+        type: tosca.datatypes.nfv.riftio.dashboard_params
+        required: false
+        description: >-
+          Parameters for the VNF dashboard
+  tosca.capabilities.nfv.riftio.monitoring_param:
+    derived_from: tosca.capabilities.nfv.Metric
+    properties:
+      name:
+        type: string
+        required: false
+      description:
+        type: string
+        required: false
+      protocol:
+        type: string
+        default: http
+        constraints:
+          - equal: http
+      polling_interval:
+        type: scalar-unit.time
+        description: >-
+          The HTTP polling interval in seconds
+        default: 2 s
+      username:
+        type: string
+        description: >-
+          The HTTP basic auth username
+        required: false
+      password:
+        type: string
+        description: >-
+          The HTTP basic auth password
+        required: false
+      method:
+        type: string
+        description: >-
+          This is the method to be performed at the uri.
+          GET by default for action
+        default: get
+        constraints:
+          - valid_values: [post, put, get, delete, options, patch]
+      headers:
+        type: map
+        entry_schema:
+          type: string
+        description: >-
+          Custom HTTP headers to put on HTTP request
+        required: false
+      json_query_method:
+        type: string
+        description: >-
+          The method to extract a value from a JSON response
+            namekey    - Use the name as the key for a non-nested value.
+            jsonpath   - Use jsonpath-rw implemenation to extract a value.
+            objectpath - Use objectpath implemenation to extract a value.
+        constraints:
+          - valid_values: [namekey, jsonpath, objectpath]
+        default: namekey
+      json_query_path:
+        type: string
+        description: >-
+          The json path to use to extract value from JSON structure
+        required: false
+      json_object_path:
+        type: string
+        description: >-
+          The object path to use to extract value from JSON structure
+        required: false
+      ui_data:
+        type: tosca.datatypes.nfv.riftio.monitoring_param_ui
+        required: false
+      constraints:
+        type: tosca.datatypes.nfv.riftio.monitoring_param_value
+        required: false
+  tosca.capabilities.nfv.riftio.numa_extension:
+    derived_from: tosca.capabilities.Root
+    properties:
+      node_cnt:
+        type: integer
+        description: >-
+          The number of numa nodes to expose to the VM
+        constraints:
+          - greater_or_equal: 0
+      mem_policy:
+        type: string
+        description: >-
+          This policy specifies how the memory should
+                   be allocated in a multi-node scenario.
+                   STRICT    - The memory must be allocated
+                               strictly from the memory attached
+                               to the NUMA node.
+                   PREFERRED - The memory should be allocated
+                               preferentially from the memory
+                               attached to the NUMA node
+        constraints:
+          - valid_values: [strict, preferred, STRICT, PREFERRED]
+      node:
+        type: list
+        entry_schema:
+          type: tosca.datatypes.compute.riftio.numa
+  tosca.capabilities.nfv.riftio.vswitch_epa:
+    derived_from: tosca.capabilities.Root
+    properties:
+      ovs_acceleration:
+        type: string
+        description: |-
+          Specifies Open vSwitch acceleration mode.
+             MANDATORY - OVS acceleration is required
+             PREFERRED - OVS acceleration is preferred
+        constraints:
+          - valid_values: [mandatory, preferred, disabled, MANDATORY, PREFERRED, DISABLED]
+      ovs_offload:
+        type: string
+        description: |-
+          Specifies Open vSwitch hardware offload mode.
+             MANDATORY - OVS offload is required
+             PREFERRED - OVS offload is preferred
+        constraints:
+          - valid_values: [mandatory, preferred, disabled, MANDATORY, PREFERRED, DISABLED]
+
+  tosca.capabilities.nfv.riftio.hypervisor_epa:
+    derived_from: tosca.capabilities.Root
+    properties:
+      type:
+        type: string
+        description: |-
+          Specifies the type of hypervisor.
+        constraints:
+          - valid_values: [prefer_kvm, require_kvm, PREFER_KVM, REQUIRE_KVM]
+      version:
+        type: string
+
+  tosca.capabilities.nfv.riftio.host_epa:
+    derived_from: tosca.capabilities.Root
+    properties:
+      cpu_model:
+        type: string
+        description: >-
+          Host CPU model. Examples include SandyBridge,
+          IvyBridge, etc.
+        required: false
+        constraints:
+          - valid_values:
+              - prefer_westmere
+              - require_westmere
+              - prefer_sandbridge
+              - require_sandybridge
+              - prefer_ivybridge
+              - require_ivybridge
+              - prefer_haswell
+              - require_haswell
+              - prefer_broadwell
+              - require_broadwell
+              - prefer_nehalem
+              - require_nehalem
+              - prefer_penryn
+              - require_penryn
+              - prefer_conroe
+              - require_conroe
+              - prefer_core2duo
+              - require_core2duo
+              - PREFER_WESTMERE
+              - REQUIRE_WESTMERE
+              - PREFER_SANDBRIDGE
+              - REQUIRE_SANDYBRIDGE
+              - PREFER_IVYBRIDGE
+              - REQUIRE_IVYBRIDGE
+              - PREFER_HASWELL
+              - REQUIRE_HASWELL
+              - PREFER_BROADWELL
+              - REQUIRE_BROADWELL
+              - PREFER_NEHALEM
+              - REQUIRE_NEHALEM
+              - PREFER_PENRYN
+              - REQUIRE_PENRYN
+              - PREFER_CONROE
+              - REQUIRE_CONROE
+              - PREFER_CORE2DUO
+              - REQUIRE_CORE2DUO
+      cpu_arch:
+        type: string
+        description: >-
+          Host CPU architecture
+        required: false
+        constraints:
+          - valid_values:
+              - prefer_x86
+              - require_x86
+              - prefer_x86_64
+              - require_x86_64
+              - prefer_i686
+              - require_i686
+              - prefer_ia64
+              - require_ia64
+              - prefer_armv7
+              - require_armv7
+              - prefer_armv8
+              - require_armv8
+              - PREFER_X86
+              - REQUIRE_X86
+              - PREFER_X86_64
+              - REQUIRE_X86_64
+              - PREFER_I686
+              - REQUIRE_I686
+              - PREFER_IA64
+              - REQUIRE_IA64
+              - PREFER_ARMV7
+              - REQUIRE_ARMV7
+              - PREFER_ARMV8
+              - REQUIRE_ARMV8
+      cpu_vendor:
+        type: string
+        description: >-
+          Host CPU vendor
+        required: false
+        constraints:
+          - valid_values:
+              - prefer_intel
+              - require_intel
+              - prefer_amd
+              - requie_amd
+              - PREFER_INTEL
+              - REQUIRE_INTEL
+              - PREFER_AMD
+              - REQUIE_AMD
+      cpu_socket_count:
+        type: integer
+        description: >-
+          Number of sockets on the host
+        required: false
+        constraints:
+          - greater_than : 0
+      cpu_core_count:
+        type: integer
+        description: >-
+          Number of cores on the host
+        required: false
+        constraints:
+          - greater_than : 0
+      cpu_core_thread_count:
+        type: integer
+        description: >-
+          Number of threads per core on the host
+        required: false
+        constraints:
+          - greater_than : 0
+      cpu_feature:
+        type: list
+        entry_schema:
+          type: string
+        description: |-
+          Enumeration for CPU features.
+
+          AES- CPU supports advanced instruction set for
+          AES (Advanced Encryption Standard).
+
+          CAT- Cache Allocation Technology (CAT) allows
+          an Operating System, Hypervisor, or similar
+          system management agent to specify the amount
+          of L3 cache (currently the last-level cache
+          in most server and client platforms) space an
+          application can fill (as a hint to hardware
+          functionality, certain features such as power
+          management may override CAT settings).
+
+          CMT- Cache Monitoring Technology (CMT) allows
+          an Operating System, Hypervisor, or similar
+          system management agent to determine the
+          usage of cache based on applications running
+          on the platform. The implementation is
+          directed at L3 cache monitoring (currently
+          the last-level cache in most server and
+          client platforms).
+
+          DDIO- Intel Data Direct I/O (DDIO) enables
+          Ethernet server NICs and controllers talk
+          directly to the processor cache without a
+          detour via system memory. This enumeration
+          specifies if the VM requires a DDIO
+          capable host.
+        required: false
+        constraints:
+          -valid_values:
+            - prefer_aes
+            - require_aes
+            - prefer_cat
+            - require_cat
+            - prefer_cmt
+            - require_cmt
+            - prefer_ddio
+            - require_ddio
+            - prefer_vme
+            - require_vme
+            - prefer_de
+            - require_de
+            - prefer_pse
+            - require_pse
+            - prefer_tsc
+            - require_tsc
+            - prefer_msr
+            - require_msr
+            - prefer_pae
+            - require_pae
+            - prefer_mce
+            - require_mce
+            - prefer_cx8
+            - require_cx8
+            - prefer_apic
+            - require_apic
+            - prefer_sep
+            - require_sep
+            - prefer_mtrr
+            - require_mtrr
+            - prefer_pge
+            - require_pge
+            - prefer_mca
+            - require_mca
+            - prefer_cmov
+            - require_cmov
+            - prefer_pat
+            - require_pat
+            - prefer_pse36
+            - require_pse36
+            - prefer_clflush
+            - require_clflush
+            - prefer_dts
+            - require_dts
+            - prefer_acpi
+            - require_acpi
+            - prefer_mmx
+            - require_mmx
+            - prefer_fxsr
+            - require_fxsr
+            - prefer_sse
+            - require_sse
+            - prefer_sse2
+            - require_sse2
+            - prefer_ss
+            - require_ss
+            - prefer_ht
+            - require_ht
+            - prefer_tm
+            - require_tm
+            - prefer_ia64
+            - require_ia64
+            - prefer_pbe
+            - require_pbe
+            - prefer_rdtscp
+            - require_rdtscp
+            - prefer_pni
+            - require_pni
+            - prefer_pclmulqdq
+            - require_pclmulqdq
+            - prefer_dtes64
+            - require_dtes64
+            - prefer_monitor
+            - require_monitor
+            - prefer_ds_cpl
+            - require_ds_cpl
+            - prefer_vmx
+            - require_vmx
+            - prefer_smx
+            - require_smx
+            - prefer_est
+            - require_est
+            - prefer_tm2
+            - require_tm2
+            - prefer_ssse3
+            - require_ssse3
+            - prefer_cid
+            - require_cid
+            - prefer_fma
+            - require_fma
+            - prefer_cx16
+            - require_cx16
+            - prefer_xtpr
+            - require_xtpr
+            - prefer_pdcm
+            - require_pdcm
+            - prefer_pcid
+            - require_pcid
+            - prefer_dca
+            - require_dca
+            - prefer_sse4_1
+            - require_sse4_1
+            - prefer_sse4_2
+            - require_sse4_2
+            - prefer_x2apic
+            - require_x2apic
+            - prefer_movbe
+            - require_movbe
+            - prefer_popcnt
+            - require_popcnt
+            - prefer_tsc_deadline_timer
+            - require_tsc_deadline_timer
+            - prefer_xsave
+            - require_xsave
+            - prefer_avx
+            - require_avx
+            - prefer_f16c
+            - require_f16c
+            - prefer_rdrand
+            - require_rdrand
+            - prefer_fsgsbase
+            - require_fsgsbase
+            - prefer_bmi1
+            - require_bmi1
+            - prefer_hle
+            - require_hle
+            - prefer_avx2
+            - require_avx2
+            - prefer_smep
+            - require_smep
+            - prefer_bmi2
+            - require_bmi2
+            - prefer_erms
+            - require_erms
+            - prefer_invpcid
+            - require_invpcid
+            - prefer_rtm
+            - require_rtm
+            - prefer_mpx
+            - require_mpx
+            - prefer_rdseed
+            - require_rdseed
+            - prefer_adx
+            - require_adx
+            - prefer_smap
+            - require_smap
+            - PREFER_AES
+            - REQUIRE_AES
+            - PREFER_CAT
+            - REQUIRE_CAT
+            - PREFER_CMT
+            - REQUIRE_CMT
+            - PREFER_DDIO
+            - REQUIRE_DDIO
+            - PREFER_VME
+            - REQUIRE_VME
+            - PREFER_DE
+            - REQUIRE_DE
+            - PREFER_PSE
+            - REQUIRE_PSE
+            - PREFER_TSC
+            - REQUIRE_TSC
+            - PREFER_MSR
+            - REQUIRE_MSR
+            - PREFER_PAE
+            - REQUIRE_PAE
+            - PREFER_MCE
+            - REQUIRE_MCE
+            - PREFER_CX8
+            - REQUIRE_CX8
+            - PREFER_APIC
+            - REQUIRE_APIC
+            - PREFER_SEP
+            - REQUIRE_SEP
+            - PREFER_MTRR
+            - REQUIRE_MTRR
+            - PREFER_PGE
+            - REQUIRE_PGE
+            - PREFER_MCA
+            - REQUIRE_MCA
+            - PREFER_CMOV
+            - REQUIRE_CMOV
+            - PREFER_PAT
+            - REQUIRE_PAT
+            - PREFER_PSE36
+            - REQUIRE_PSE36
+            - PREFER_CLFLUSH
+            - REQUIRE_CLFLUSH
+            - PREFER_DTS
+            - REQUIRE_DTS
+            - PREFER_ACPI
+            - REQUIRE_ACPI
+            - PREFER_MMX
+            - REQUIRE_MMX
+            - PREFER_FXSR
+            - REQUIRE_FXSR
+            - PREFER_SSE
+            - REQUIRE_SSE
+            - PREFER_SSE2
+            - REQUIRE_SSE2
+            - PREFER_SS
+            - REQUIRE_SS
+            - PREFER_HT
+            - REQUIRE_HT
+            - PREFER_TM
+            - REQUIRE_TM
+            - PREFER_IA64
+            - REQUIRE_IA64
+            - PREFER_PBE
+            - REQUIRE_PBE
+            - PREFER_RDTSCP
+            - REQUIRE_RDTSCP
+            - PREFER_PNI
+            - REQUIRE_PNI
+            - PREFER_PCLMULQDQ
+            - REQUIRE_PCLMULQDQ
+            - PREFER_DTES64
+            - REQUIRE_DTES64
+            - PREFER_MONITOR
+            - REQUIRE_MONITOR
+            - PREFER_DS_CPL
+            - REQUIRE_DS_CPL
+            - PREFER_VMX
+            - REQUIRE_VMX
+            - PREFER_SMX
+            - REQUIRE_SMX
+            - PREFER_EST
+            - REQUIRE_EST
+            - PREFER_TM2
+            - REQUIRE_TM2
+            - PREFER_SSSE3
+            - REQUIRE_SSSE3
+            - PREFER_CID
+            - REQUIRE_CID
+            - PREFER_FMA
+            - REQUIRE_FMA
+            - PREFER_CX16
+            - REQUIRE_CX16
+            - PREFER_XTPR
+            - REQUIRE_XTPR
+            - PREFER_PDCM
+            - REQUIRE_PDCM
+            - PREFER_PCID
+            - REQUIRE_PCID
+            - PREFER_DCA
+            - REQUIRE_DCA
+            - PREFER_SSE4_1
+            - REQUIRE_SSE4_1
+            - PREFER_SSE4_2
+            - REQUIRE_SSE4_2
+            - PREFER_X2APIC
+            - REQUIRE_X2APIC
+            - PREFER_MOVBE
+            - REQUIRE_MOVBE
+            - PREFER_POPCNT
+            - REQUIRE_POPCNT
+            - PREFER_TSC_DEADLINE_TIMER
+            - REQUIRE_TSC_DEADLINE_TIMER
+            - PREFER_XSAVE
+            - REQUIRE_XSAVE
+            - PREFER_AVX
+            - REQUIRE_AVX
+            - PREFER_F16C
+            - REQUIRE_F16C
+            - PREFER_RDRAND
+            - REQUIRE_RDRAND
+            - PREFER_FSGSBASE
+            - REQUIRE_FSGSBASE
+            - PREFER_BMI1
+            - REQUIRE_BMI1
+            - PREFER_HLE
+            - REQUIRE_HLE
+            - PREFER_AVX2
+            - REQUIRE_AVX2
+            - PREFER_SMEP
+            - REQUIRE_SMEP
+            - PREFER_BMI2
+            - REQUIRE_BMI2
+            - PREFER_ERMS
+            - REQUIRE_ERMS
+            - PREFER_INVPCID
+            - REQUIRE_INVPCID
+            - PREFER_RTM
+            - REQUIRE_RTM
+            - PREFER_MPX
+            - REQUIRE_MPX
+            - PREFER_RDSEED
+            - REQUIRE_RDSEED
+            - PREFER_ADX
+            - REQUIRE_ADX
+            - PREFER_SMAP
+            - REQUIRE_SMAP
+      om_cpu_model_string:
+        type: string
+        description: >-
+          Openmano CPU model string
+        required: false
+      om_cpu_feature:
+        type: list
+        entry_schema:
+          type: string
+        description: >-
+          List of openmano CPU features
+        required: false
+
+  tosca.capabilities.nfv.riftio.sfc:
+    derived_from: tosca.capabilities.Root
+    description: >-
+      Service Function Chaining support on this VDU
+    properties:
+      sfc_type:
+        type: string
+        description: >-
+          Type of node in Service Function Chaining Architecture
+        constraints:
+          - valid_values: [unaware, classifier, sf, sff, UNAWARE, CLASSIFIER, SF, SFF]
+        default: unaware
+      sf_type:
+        type: string
+        description: >-
+          Type of Service Function.
+             NOTE- This needs to map with Service Function Type in ODL to
+             support VNFFG. Service Function Type is manadatory param in ODL
+             SFC.
+        required: false
+  tosca.capabilities.Compute.Container.Architecture:
+    derived_from: tosca.capabilities.Container
+    properties:
+      mem_page_size:
+        type: string
+        description: >-
+          Memory page allocation size. If a VM requires
+          hugepages, it should choose huge or size_2MB
+          or size_1GB. If the VM prefers hugepages, it
+          should chose prefer_huge.
+             huge/large         - Require hugepages (either 2MB or 1GB)
+             normal       - Does not require hugepages
+             size_2MB     - Requires 2MB hugepages
+             size_1GB     - Requires 1GB hugepages
+             prefer_huge  - Application perfers hugepages
+          NOTE - huge and normal is only defined in standards as of
+                 now.
+        required: false
+        constraints:
+          - valid_values: [normal, large, huge, size_2MB, size_1GB, prefer_huge, NORMAL,LARGE, HUGE, SIZE_2MB, SIZE_1GB, PREFER_HUGE]
+      cpu_allocation:
+        type: tosca.datatypes.compute.Container.Architecture.CPUAllocation
+        required: false
+      numa_nodes:
+        type: map
+        required: false
+        entry_schema:
+          type: tosca.datatypes.compute.Container.Architecture.NUMA
+
+
+node_types:
+  tosca.nodes.nfv.riftio.VDU1:
+    derived_from: tosca.nodes.nfv.VDU
+    properties:
+      description:
+        type: string
+        required: false
+      image:
+        description: >-
+          If an image is specified here, it is assumed that the image
+          is already present in the RO or VIM and not in the package.
+        type: string
+        required: false
+      image_checksum:
+        type: string
+        description: >-
+          Image checksum for the image in RO or VIM.
+        required: false
+      cloud_init:
+        description: >-
+          Inline cloud-init specification
+        required: false
+        type: string
+      count:
+        default: 1
+        type: integer
+    capabilities:
+      virtualLink:
+        type: tosca.capabilities.nfv.VirtualLinkable
+      monitoring_param_1:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      mgmt_interface:
+        type: tosca.capabilities.nfv.riftio.mgmt_interface
+      monitoring_param:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      numa_extension:
+        type: tosca.capabilities.nfv.riftio.numa_extension
+      vswitch_epa:
+        type: tosca.capabilities.nfv.riftio.vswitch_epa
+      hypervisor_epa:
+        type: tosca.capabilities.nfv.riftio.hypervisor_epa
+      host_epa:
+        type: tosca.capabilities.nfv.riftio.host_epa
+  tosca.nodes.nfv.riftio.CP1:
+    derived_from: tosca.nodes.nfv.CP
+    properties:
+      cp_type:
+        description: Type of the connection point
+        type: string
+        default: VPORT
+        constraints:
+          - valid_values: [VPORT]
+      name:
+        description: Name of the connection point
+        type: string
+        required: false
+      vdu_intf_name:
+        description: Name of the interface on VDU
+        type: string
+      vdu_intf_type:
+        description: >-
+          Specifies the type of virtual interface
+             between VM and host.
+             VIRTIO          - Use the traditional VIRTIO interface.
+             PCI-PASSTHROUGH - Use PCI-PASSTHROUGH interface.
+             SR-IOV          - Use SR-IOV interface.
+             E1000           - Emulate E1000 interface.
+             RTL8139         - Emulate RTL8139 interface.
+             PCNET           - Emulate PCNET interface.
+             OM-MGMT         - Used to specify openmano mgmt external-connection type
+        type: string
+        constraints:
+          - valid_values: [OM-MGMT, VIRTIO, E1000, SR-IOV]
+      bandwidth:
+        type: integer
+        description: Aggregate bandwidth of the NIC
+        constraints:
+          - greater_or_equal: 0
+        required: false
+      vpci:
+        type: string
+        description: >-
+          Specifies the virtual PCI address. Expressed in
+          the following format dddd:dd:dd.d. For example
+          0000:00:12.0. This information can be used to
+          pass as metadata during the VM creation.
+        required: false
+    capabilities:
+      sfc:
+        type: tosca.capabilities.nfv.riftio.sfc
+  tosca.nodes.nfv.riftio.VNF1:
+    derived_from: tosca.nodes.nfv.VNF
+    properties:
+      member_index:
+        type: integer
+        constraints:
+          - greater_or_equal: 1
+        description: Index of the VNF in the NS
+        required: false
+      start_by_default:
+        type: boolean
+        default: true
+        description: Start this VNF on NS instantiate
+      logo:
+        type: string
+        description: >-
+          Logo to display with the VNF in the orchestrator
+        required: false
+    capabilities:      
+      mgmt_interface:
+        type: tosca.capabilities.nfv.riftio.mgmt_interface
+      monitoring_param:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      sfc:
+        type: tosca.capabilities.nfv.riftio.sfc
+  tosca.nodes.nfv.riftio.ELAN:
+    derived_from: tosca.nodes.nfv.VL.ELAN
+    properties:
+      description:
+        type: string
+        required: false
+      network_name:
+        type: string
+        description: >-
+          Name of network in VIM account. This is used to indicate
+          pre-provisioned network name in cloud account.
+        required: false
+      root_bandwidth:
+        type: integer
+        description: >-
+          This is the aggregate bandwidth
+        constraints:
+          - greater_or_equal: 0
+        required: false
+      leaf_bandwidth:
+        type: integer
+        description: >-
+          This is the bandwidth of branches
+        constraints:
+          - greater_or_equal: 0
+        required: false
+  tosca.nodes.nfv.riftio.FP1:
+    derived_from: tosca.nodes.nfv.FP
+    properties:
+      id:
+        type: integer
+        required: false
+      policy:
+        type: tosca.nfv.datatypes.policyType
+        required: true
+        description: policy to use to match traffic for this FP
+      path:
+        type: list
+        required: true
+        entry_schema:
+          type: tosca.nfv.datatypes.pathType
+      cp:
+        type: tosca.nfv.datatypes.pathType
+        required: true
+
+
+
+artifact_types:
+  tosca.artifacts.Deployment.riftio.cloud_init_file:
+    derived_from: tosca.artifacts.Deployment
+    file:
+      type: string
+
+  tosca.artifacts.Deployment.Image.riftio.QCOW2:
+    derived_from: tosca.artifacts.Deployment.Image.VM.QCOW2
+    image_checksum:
+      required: false
+      type: string
+
+group_types:
+  tosca.groups.nfv.VNFFG:
+    derived_from: tosca.groups.Root
+    properties:
+      vendor:
+        type: string
+        required: true
+        description: name of the vendor who generate this VNFFG
+      version:
+        type: string
+        required: true
+        description: version of this VNFFG
+      number_of_endpoints:
+        type: integer
+        required: true
+        description: count of the external endpoints included in this VNFFG
+      dependent_virtual_link:
+        type: list
+        entry_schema:
+          type: string
+        required: true
+        description: Reference to a VLD used in this Forwarding Graph
+      connection_point:
+        type: list
+        entry_schema:
+          type: string
+        required: true
+        description: Reference to Connection Points forming the VNFFG
+      constituent_vnfs:
+        type: list
+        entry_schema:
+          type: string
+        required: true
+        description: Reference to a list of VNFD used in this VNF Forwarding Graph
+    members: [ tosca.nodes.nfv.FP ]
+
+  tosca.groups.nfv.riftio.scaling:
+    derived_from: tosca.groups.Root
+    properties:
+      name:
+        type: string
+      min_instances:
+        type: integer
+        description: >-
+          Minimum instances of the scaling group which are allowed.
+          These instances are created by default when the network service
+          is instantiated.
+      max_instances:
+        type: integer
+        description: >-
+          Maximum instances of this scaling group that are allowed
+          in a single network service. The network service scaling
+          will fail, when the number of service group instances
+          exceed the max-instance-count specified.
+      cooldown_time:
+        type: integer
+        description: >-
+          The duration after a scaling-in/scaling-out action has been
+          triggered, for which there will be no further optional
+      ratio:
+        type: map
+        entry_schema:
+          type: integer
+        description: >-
+          Specify the number of instances of each VNF to instantiate
+          for a scaling action
+    members: [tosca.nodes.nfv.VNF]
+    interfaces:
+      action:
+        type: tosca.interfaces.nfv.riftio.scaling.action
+
+interface_types:
+  tosca.interfaces.nfv.riftio.scaling.action:
+    pre_scale_in:
+      description: Operation to execute before a scale in
+    post_scale_in:
+      description: Operation to execute after a scale in
+    pre_scale_out:
+      description: Operation to execute before a scale out
+    post_scale_out:
+      description: Operation to execute after a scale out
+
+policy_types:
+  tosca.policies.nfv.riftio.placement:
+    derived_from: tosca.policies.Placement
+    properties:
+      name:
+        type: string
+        description: >-
+          Place group construct to define the compute resource placement strategy
+          in cloud environment
+      requirement:
+        type: string
+        description: >-
+          This is free text space used to describe the intent/rationale
+          behind this placement group. This is for human consumption only
+      strategy:
+        type: string
+        description: >-
+          Strategy associated with this placement group
+             Following values are possible
+               COLOCATION - Colocation strategy imply intent to share the physical
+                            infrastructure (hypervisor/network) among all members
+                            of this group.
+               ISOLATION - Isolation strategy imply intent to not share the physical
+                           infrastructure (hypervisor/network) among the members
+                           of this group.
+        constraints:
+          valid_values:
+            - COLOCATION
+            - ISOLATION
+  tosca.policies.nfv.riftio.vnf_configuration:
+    derived_from: tosca.policies.Root
+    properties:
+      config:
+        type: tosca.datatypes.nfv.riftio.vnf_configuration
+      initial_config:
+        type: list
+        entry_schema:
+          type: tosca.datatypes.nfv.riftio.config_primitive
+  tosca.policies.nfv.riftio.vnf_service_primitives:
+    derived_from: tosca.policies.Root
+    properties:
+      parameter:
+        type: map
+        entry_schema:
+          type: primitive_parameter
+  tosca.policies.nfv.riftio.ns_service_primitives:
+    derived_from: tosca.policies.Root
+    properties:
+      parameter:
+        type: map
+        entry_schema:
+          type: primitive_parameter
+      parameter_group:
+        type: tosca.datatypes.nfv.riftio.primitive_parameter_group
+        description: >-
+          Grouping of parameters which are logically grouped in UI
+        required: false
+      vnf_primitive_group:
+        type: tosca.datatypes.nfv.riftio.vnf_primitive_group
+        description: >-
+          List of service primitives grouped by VNF
+        required: false
+      user_defined_script:
+        type: string
+        description: >-
+          A user defined script
+        required: false
+  tosca.policies.nfv.riftio.initial_config_primitive:
+    derived_from: tosca.policies.Root
+    properties:
+      name:
+        type: string
+      seq:
+        type: integer
+        description: >-
+          Order in which to apply, when multiple ones are defined
+        default: 0
+        constraints:
+          - greater_or_equal: 0
+      parameter:
+        type: map
+        entry_schema:
+          type: string
+      user_defined_script:
+        type: string
+  tosca.policies.nfv.riftio.users:
+    derived_from: tosca.policies.Root
+    description: >-
+      Specify list of public keys to be injected as
+      part of NS instantitation. Use default as entry,
+      to specify the key pairs for default user.
+    properties:
+      user_info:
+        type: string
+        description: >-
+          The user\'s real name
+        required: false
+      key_pairs:
+        type: map
+        description: >-
+          List of public keys for the user
+        entry_schema:
+          type: string
+        required: true
+  tosca.policies.nfv.riftio.dependency:
+    derived_from: tosca.policies.Root
+    description: >-
+      Map dependency between VDUs or VNFs
+    properties:
+      parameter:
+        type: map
+        entry_schema:
+          type: string
+        description: >-
+          Parameter and value for the config
+  tosca.nfv.datatypes.policyType:
+    properties:
+      type:
+        type: string
+        required: false
+        constraints:
+          - valid_values: [ ACL ]
+      criteria:
+        type: list
+        required: true
+        entry_schema:
+          type: tosca.nfv.datatypes.aclType
+
+  
+
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/TOSCA-Metadata/TOSCA.meta b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/TOSCA-Metadata/TOSCA.meta
new file mode 100644 (file)
index 0000000..2351efd
--- /dev/null
@@ -0,0 +1,4 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: RIFT.io
+Entry-Definitions: Definitions/ping_pong_nsd.yaml
\ No newline at end of file
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/scripts/ping_set_rate.py b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/scripts/ping_set_rate.py
new file mode 100755 (executable)
index 0000000..54629e8
--- /dev/null
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+
+############################################################################
+# 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.                                           #
+############################################################################
+
+
+import argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+import yaml
+
+
+def ping_set_rate(yaml_cfg, logger):
+    '''Use curl and set traffic rate on ping vnf'''
+
+    def set_rate(mgmt_ip, port, rate):
+        curl_cmd = '''curl -D /dev/stdout \
+    -H "Accept: application/vnd.yang.data+xml" \
+    -H "Content-Type: application/vnd.yang.data+json" \
+    -X POST \
+    -d "{{ \\"rate\\":{ping_rate} }}" \
+    http://{ping_mgmt_ip}:{ping_mgmt_port}/api/v1/ping/rate
+'''.format(ping_mgmt_ip=mgmt_ip,
+           ping_mgmt_port=port,
+           ping_rate=rate)
+
+        logger.debug("Executing cmd: %s", curl_cmd)
+        subprocess.check_call(curl_cmd, shell=True)
+
+    # Get the ping rate
+    rate = yaml_cfg['parameter']['rate']
+
+    # Set ping rate
+    for index, vnfr in yaml_cfg['vnfr'].items():
+        logger.debug("VNFR {}: {}".format(index, vnfr))
+
+        # Check if it is pong vnf
+        if 'ping_vnfd' in vnfr['name']:
+            vnf_type = 'ping'
+            port = 18888
+            set_rate(vnfr['mgmt_ip_address'], port, rate)
+            break
+
+def main(argv=sys.argv[1:]):
+    try:
+        parser = argparse.ArgumentParser()
+        parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+        parser.add_argument("-q", "--quiet", dest="verbose", action="store_false")
+        args = parser.parse_args()
+
+        run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+        if not os.path.exists(run_dir):
+            os.makedirs(run_dir)
+        log_file = "{}/ping_set_rate-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+        logging.basicConfig(filename=log_file, level=logging.DEBUG)
+        logger = logging.getLogger()
+
+    except Exception as e:
+        print("Exception in {}: {}".format(__file__, e))
+        sys.exit(1)
+
+    try:
+        ch = logging.StreamHandler()
+        if args.verbose:
+            ch.setLevel(logging.DEBUG)
+        else:
+            ch.setLevel(logging.INFO)
+
+        # create formatter and add it to the handlers
+        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+        ch.setFormatter(formatter)
+        logger.addHandler(ch)
+
+    except Exception as e:
+        logger.exception(e)
+        raise e
+
+    try:
+        yaml_str = args.yaml_cfg_file.read()
+        # logger.debug("Input YAML file:\n{}".format(yaml_str))
+        yaml_cfg = yaml.load(yaml_str)
+        logger.debug("Input YAML: {}".format(yaml_cfg))
+
+        ping_set_rate(yaml_cfg, logger)
+
+    except Exception as e:
+        logger.exception(e)
+        raise e
+
+if __name__ == "__main__":
+    main()
diff --git a/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/scripts/start_traffic.py b/common/python/rift/mano/tosca_translator/test/data/tosca_ping_pong_epa/scripts/start_traffic.py
new file mode 100755 (executable)
index 0000000..22de542
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/env python3
+
+############################################################################
+# 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.                                           #
+############################################################################
+
+
+import argparse
+import logging
+import os
+import subprocess
+import sys
+import time
+
+import yaml
+
+
+def start_traffic(yaml_cfg, logger):
+    '''Use curl and set admin status to enable on pong and ping vnfs'''
+
+    def enable_service(mgmt_ip, port, vnf_type):
+        curl_cmd = 'curl -D /dev/null -H "Accept: application/vnd.yang.data' \
+                   '+xml" -H "Content-Type: application/vnd.yang.data+json" ' \
+                   '-X POST -d "{{\\"enable\\":true}}" http://{mgmt_ip}:' \
+                   '{mgmt_port}/api/v1/{vnf_type}/adminstatus/state'. \
+                   format(
+                       mgmt_ip=mgmt_ip,
+                       mgmt_port=port,
+                       vnf_type=vnf_type)
+
+        logger.debug("Executing cmd: %s", curl_cmd)
+        subprocess.check_call(curl_cmd, shell=True)
+
+    # Enable pong service first
+    for index, vnfr in yaml_cfg['vnfr'].items():
+        logger.debug("VNFR {}: {}".format(index, vnfr))
+
+        # Check if it is pong vnf
+        if 'pong_vnfd' in vnfr['name']:
+            vnf_type = 'pong'
+            port = 18889
+            enable_service(vnfr['mgmt_ip_address'], port, vnf_type)
+            break
+
+    # Add a delay to provide pong port to come up
+    time.sleep(0.1)
+
+    # Enable ping service next
+    for index, vnfr in yaml_cfg['vnfr'].items():
+        logger.debug("VNFR {}: {}".format(index, vnfr))
+
+        # Check if it is pong vnf
+        if 'ping_vnfd' in vnfr['name']:
+            vnf_type = 'ping'
+            port = 18888
+            enable_service(vnfr['mgmt_ip_address'], port, vnf_type)
+            break
+
+def main(argv=sys.argv[1:]):
+    try:
+        parser = argparse.ArgumentParser()
+        parser.add_argument("yaml_cfg_file", type=argparse.FileType('r'))
+        parser.add_argument("-q", "--quiet", dest="verbose", action="store_false")
+        args = parser.parse_args()
+
+        run_dir = os.path.join(os.environ['RIFT_INSTALL'], "var/run/rift")
+        if not os.path.exists(run_dir):
+            os.makedirs(run_dir)
+        log_file = "{}/ping_pong_start_traffic-{}.log".format(run_dir, time.strftime("%Y%m%d%H%M%S"))
+        logging.basicConfig(filename=log_file, level=logging.DEBUG)
+        logger = logging.getLogger()
+
+    except Exception as e:
+        print("Exception in {}: {}".format(__file__, e))
+        sys.exit(1)
+
+    try:
+        ch = logging.StreamHandler()
+        if args.verbose:
+            ch.setLevel(logging.DEBUG)
+        else:
+            ch.setLevel(logging.INFO)
+
+        # create formatter and add it to the handlers
+        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+        ch.setFormatter(formatter)
+        logger.addHandler(ch)
+
+    except Exception as e:
+        logger.exception(e)
+        raise e
+
+    try:
+        yaml_str = args.yaml_cfg_file.read()
+        # logger.debug("Input YAML file:\n{}".format(yaml_str))
+        yaml_cfg = yaml.load(yaml_str)
+        logger.debug("Input YAML: {}".format(yaml_cfg))
+
+        start_traffic(yaml_cfg, logger)
+
+    except Exception as e:
+        logger.exception(e)
+        raise e
+
+if __name__ == "__main__":
+    main()
index 1b5b156..1dc43d0 100755 (executable)
@@ -66,7 +66,7 @@ class TestToscaTranslator(unittest.TestCase):
 
     tosca_helloworld = os.path.join(
         os.path.dirname(os.path.abspath(__file__)),
-        "data/tosca_helloworld.yaml")
+        "data/tosca_helloworld_nfv.yaml")
     template_file = '--template-file=' + tosca_helloworld
     template_validation = "--validate-only"
     debug="--debug"
@@ -109,6 +109,7 @@ class TestToscaTranslator(unittest.TestCase):
                           (self.template_file,
                            '--parameters=key'))
 
+    @unittest.skip
     def test_valid_template(self):
         try:
             shell.main([self.template_file])
@@ -116,6 +117,7 @@ class TestToscaTranslator(unittest.TestCase):
             self.log.exception(e)
             self.fail(self.failure_msg)
 
+    @unittest.skip
     def test_validate_only(self):
         try:
             shell.main([self.template_file,
@@ -213,7 +215,7 @@ class TestToscaTranslator(unittest.TestCase):
         test_base_dir = os.path.join(os.path.dirname(
             os.path.abspath(__file__)), 'data')
         template_file = os.path.join(test_base_dir,
-                            "ping_pong_csar/Definitions/ping_pong_nsd.yaml")
+                            "tosca_ping_pong_epa/Definitions/ping_pong_nsd.yaml")
         template = '--template-file='+template_file
         temp_dir = tempfile.mkdtemp()
         output_dir = "--output-dir=" + temp_dir
@@ -233,12 +235,13 @@ class TestToscaTranslator(unittest.TestCase):
                     shutil.rmtree(temp_dir)
             else:
                 self.log.warn("Generated desc in {}".format(temp_dir))
+   
 
     def test_input_csar(self):
         test_base_dir = os.path.join(
             os.path.dirname(os.path.abspath(__file__)),
             'data')
-        template_file = os.path.join(test_base_dir, "ping_pong_csar.zip")
+        template_file = os.path.join(test_base_dir, "tosca_ping_pong_epa.zip")
         template = '--template-file='+template_file
         temp_dir = tempfile.mkdtemp()
         output_dir = "--output-dir=" + temp_dir
@@ -259,12 +262,13 @@ class TestToscaTranslator(unittest.TestCase):
                     shutil.rmtree(temp_dir)
             else:
                 self.log.warn("Generated desc in {}".format(temp_dir))
-
+    
+    @unittest.skip
     def test_input_csar_no_gi(self):
         test_base_dir = os.path.join(
             os.path.dirname(os.path.abspath(__file__)),
             'data')
-        template_file = os.path.join(test_base_dir, "ping_pong_csar.zip")
+        template_file = os.path.join(test_base_dir, "tosca_ping_pong_epa.zip")
         template = '--template-file='+template_file
         temp_dir = tempfile.mkdtemp()
         output_dir = "--output-dir=" + temp_dir
index 7e4158b..7388d32 100644 (file)
@@ -1148,6 +1148,20 @@ node_types:
         type: tosca.capabilities.nfv.riftio.hypervisor_epa
       host_epa:
         type: tosca.capabilities.nfv.riftio.host_epa
+      monitoring_param_2:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      monitoring_param_3:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      monitoring_param_4:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      monitoring_param_5:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      monitoring_param_6:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      monitoring_param_7:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
+      monitoring_param_8:
+        type: tosca.capabilities.nfv.riftio.monitoring_param
   tosca.nodes.nfv.riftio.CP1:
     derived_from: tosca.nodes.nfv.CP
     properties:
@@ -1428,6 +1442,11 @@ policy_types:
         description: >-
           A user defined script
         required: false
+      name:
+        type: string
+        description: >-
+          Name of primitive
+        required: false
   tosca.policies.nfv.riftio.initial_config_primitive:
     derived_from: tosca.policies.Root
     properties:
index 57b0a31..9204134 100644 (file)
@@ -23,8 +23,8 @@ class ToscaResource(object):
     # from REQUIRED_FIELDS below
     NAME = 'name'
 
-    REQUIRED_FIELDS = (DESC, VERSION, VENDOR, ID) = \
-                      ('description', 'version', 'vendor', 'id')
+    REQUIRED_FIELDS = (DESC, VERSION, VENDOR, ID, LOGO) = \
+                      ('description', 'version', 'vendor', 'id', 'logo')
 
     COMMON_FIELDS = (PATH, PORT, HOST, XPATH, TYPE, COUNT, FILE, 
                     NFV_COMPUTE, HOST_EPA, VSWITCH_EPA, HYPERVISOR_EPA, GUEST_EPA) = \
@@ -98,6 +98,7 @@ class ToscaResource(object):
         T_ELAN,
         T_VNFFG,
         T_FP,
+        T_NS_PRIMITIVE,
     ) = \
         ('tosca.policies.nfv.riftio.vnf_configuration',
          'tosca.capabilities.riftio.http_endpoint_type',
@@ -116,13 +117,14 @@ class ToscaResource(object):
          'tosca.nodes.nfv.riftio.ELAN',
          'tosca.groups.nfv.VNFFG',
          'tosca.nodes.nfv.riftio.FP1',
+         'tosca.policies.nfv.riftio.ns_service_primitives',
         )
 
     SUPPORT_FILES = ( SRC, DEST, EXISTING) = \
                     ('source', 'destination', 'existing')
 
-    SUPPORT_DIRS = (IMAGE_DIR, SCRIPT_DIR, CLOUD_INIT_DIR) = \
-                   ('images', 'scripts','cloud_init')
+    SUPPORT_DIRS = (IMAGE_DIR, SCRIPT_DIR, CLOUD_INIT_DIR, ICON_DIR) = \
+                   ('images', 'scripts','cloud_init', 'icons')
 
     def __init__(self,
                  log,
index 95f2cb2..039648f 100644 (file)
@@ -138,7 +138,7 @@ class ToscaTemplate(object):
 
         # Add all types
         types_list = [ToscaResource.DATA_TYPES, ToscaResource.CAPABILITY_TYPES,
-                      ToscaResource.NODE_TYPES,
+                      ToscaResource.NODE_TYPES, ToscaResource.ARTIFACT_TYPES,
                       ToscaResource.GROUP_TYPES, ToscaResource.POLICY_TYPES]
         for typ in types_list:
             if typ in tosca:
index 707ab7f..2023db5 100644 (file)
@@ -148,26 +148,31 @@ class TranslateDescriptors(object):
             for nsd in self.yangs[self.NSD]:
                 self.log.debug(_("Translate descriptor of type nsd: {}").
                                format(nsd))
+                node_name = nsd.pop(ToscaResource.NAME).replace(' ','_')
+                node_name = node_name if node_name.endswith('nsd') else ''.join([node_name, '_nsd'])
                 tosca_node = TranslateDescriptors. \
                              YANG_TO_TOSCA_TYPE[self.NSD](
                                  self.log,
-                                 nsd.pop(ToscaResource.NAME),
+                                 node_name,
                                  self.NSD,
                                  nsd,
                                  self.vnfd_files)
                 self.tosca_resources.append(tosca_node)
 
+        vnfd_name_list = []
         if self.VNFD in self.yangs:
             for vnfd in self.yangs[self.VNFD]:
-                self.log.debug(_("Translate descriptor of type vnfd: {}").
-                               format(vnfd))
-                tosca_node = TranslateDescriptors. \
-                             YANG_TO_TOSCA_TYPE[self.VNFD](
-                                 self.log,
-                                 vnfd.pop(ToscaResource.NAME),
-                                 self.VNFD,
-                                 vnfd)
-                self.tosca_resources.append(tosca_node)
+                if vnfd['name'] not in vnfd_name_list:
+                    self.log.debug(_("Translate descriptor of type vnfd: {}").
+                                   format(vnfd))
+                    vnfd_name_list.append(vnfd['name'])
+                    tosca_node = TranslateDescriptors. \
+                                 YANG_TO_TOSCA_TYPE[self.VNFD](
+                                     self.log,
+                                     vnfd.pop(ToscaResource.NAME),
+                                     self.VNFD,
+                                     vnfd)
+                    self.tosca_resources.append(tosca_node)
 
         # First translate VNFDs
         for node in self.tosca_resources:
index d28b3e1..94fff16 100644 (file)
@@ -22,6 +22,7 @@ from rift.mano.yang_translator.rwmano.syntax.tosca_resource \
     import ToscaResource
 from rift.mano.yang_translator.rwmano.yang.yang_vld import YangVld
 from collections import OrderedDict
+import re
 
 TARGET_CLASS_NAME = 'YangNsd'
 
@@ -44,7 +45,7 @@ class YangNsd(ToscaResource):
                     'constituent_vnfd', 'vnfd_member',
                     'min_instance_count', 'max_instance_count',
                     'input_parameter_xpath', 'config_actions',
-                    'initial_config_primitive',)
+                    'initial_config_primitive', )
 
     def __init__(self,
                  log,
@@ -63,6 +64,7 @@ class YangNsd(ToscaResource):
         self.conf_prims = []
         self.scale_grps = []
         self.initial_cfg = []
+        self.service_primitive = []
         self.placement_groups = []
         self.vnf_id_to_vnf_map = {}
         self.vnfd_files = vnfd_files
@@ -73,6 +75,7 @@ class YangNsd(ToscaResource):
         self.forwarding_paths = {}
         self.substitution_mapping_forwarder = []
         self.vnfd_sfc_map = None
+        self.duplicate_vnfd_name_list = []
 
     def handle_yang(self, vnfds):
         self.log.debug(_("Process NSD desc {0}: {1}").
@@ -155,12 +158,12 @@ class YangNsd(ToscaResource):
                 if key in dic:
                     icp[key] = dic.pop(key)
 
-            params = {}
+            params = []
             if self.PARAM in dic:
                 for p in dic.pop(self.PARAM):
                     if (self.NAME in p and
                         self.VALUE in p):
-                        params[p[self.NAME]] = p[self.VALUE]
+                        params.append({self.NAME: p[self.NAME], self.VALUE:p[self.VALUE]})
                     else:
                         # TODO (pjoseph): Need to add support to read the
                         # config file and get the value from that
@@ -175,6 +178,31 @@ class YangNsd(ToscaResource):
             self.log.debug(_("{0}, Initial config {1}").format(self, icp))
             self.initial_cfg.append({self.PROPERTIES : icp})
 
+        def process_service_primitive(dic):
+            prop = {}
+            params = []
+            for key in [self.NAME, self.USER_DEF_SCRIPT]:
+                if key in dic:
+                    prop[key] = dic.pop(key)
+
+            if self.PARAM in dic:
+                for p in dic.pop(self.PARAM):
+                    p_entry = {}
+                    for name, value in p.items():
+                        p_entry[name] = value
+                    params.append(p_entry)
+
+            if len(params):
+                    prop[self.PARAM] = params
+
+            conf_prim = {self.NAME: prop[self.NAME], self.DESC : 'TestDescription'}
+            if self.USER_DEF_SCRIPT in prop:
+                conf_prim[self.USER_DEF_SCRIPT] = prop[self.USER_DEF_SCRIPT]
+                self.conf_prims.append(conf_prim)
+
+            self.service_primitive.append({self.PROPERTIES : prop})
+
+
         def process_vld(vld, dic):
             vld_conf = {}
             vld_prop = {}
@@ -415,14 +443,22 @@ class YangNsd(ToscaResource):
         dic = deepcopy(self.yang)
         try:
             for key in self.REQUIRED_FIELDS:
-                self.props[key] = dic.pop(key)
+                if key in dic:
+                    self.props[key] = dic.pop(key)
 
             self.id = self.props[self.ID]
 
             # Process constituent VNFDs
+
+            vnfd_name_list = []
+            member_vnf_index_list = []
             if self.CONST_VNFD in dic:
                 for cvnfd in dic.pop(self.CONST_VNFD):
-                    process_const_vnfd(cvnfd)
+                    if cvnfd[self.VNFD_ID_REF] not in member_vnf_index_list:
+                        member_vnf_index_list.append(cvnfd[self.VNFD_ID_REF])
+                        process_const_vnfd(cvnfd)
+                    else:
+                        self.duplicate_vnfd_name_list.append(self.vnf_id_to_vnf_map[cvnfd[self.VNFD_ID_REF]])
 
             # Process VLDs
             if self.VLD in dic:
@@ -435,33 +471,23 @@ class YangNsd(ToscaResource):
                 process_vnffgd(dic[self.VNFFGD], dic)
 
 
-            #if self.
+            
+
+            # Process initial config primitives
+            if self.INITIAL_CFG in dic:
+                for icp_dic in dic.pop(self.INITIAL_CFG):
+                    process_initial_config(icp_dic)
 
-            # Process config primitives
+            # NS service prmitive
             if self.CONF_PRIM in dic:
-                for cprim in dic.pop(self.CONF_PRIM):
-                    conf_prim = {self.NAME: cprim.pop(self.NAME), self.DESC : 'TestDescription'}
-                    if self.USER_DEF_SCRIPT in cprim:
-                        conf_prim[self.USER_DEF_SCRIPT] = \
-                                        cprim.pop(self.USER_DEF_SCRIPT)
-                        self.conf_prims.append(conf_prim)
-                    else:
-                        err_msg = (_("{0}, Only user defined script supported "
-                                     "in config-primitive for now {}: {}").
-                                   format(self, conf_prim, cprim))
-                        self.log.error(err_msg)
-                        raise ValidationError(message=err_msg)
+                for icp_dic in dic.pop(self.CONF_PRIM):
+                    process_service_primitive(icp_dic)
 
             # Process scaling group
             if self.SCALE_GRP in dic:
                 for sg_dic in dic.pop(self.SCALE_GRP):
                     process_scale_grp(sg_dic)
 
-            # Process initial config primitives
-            if self.INITIAL_CFG in dic:
-                for icp_dic in dic.pop(self.INITIAL_CFG):
-                    process_initial_config(icp_dic)
-
             # Process the input params
             if self.INPUT_PARAM_XPATH in dic:
                 for param in dic.pop(self.INPUT_PARAM_XPATH):
@@ -556,10 +582,13 @@ class YangNsd(ToscaResource):
             self.VENDOR: self.props[self.VENDOR],
             self.VERSION: self.props[self.VERSION],
         }
+        if self.LOGO in self.props:
+            tosca[self.METADATA][self.LOGO] = self.props[self.LOGO]
+
         if len(self.vnfd_files) > 0:
             tosca[self.IMPORT] = []
             imports = []
-            for vnfd_file in self.vnfd_files:
+            for vnfd_file in set(self.vnfd_files):
                 tosca[self.IMPORT].append('"{0}.yaml"'.format(vnfd_file))
 
         tosca[self.TOPOLOGY_TMPL] = {}
@@ -578,6 +607,7 @@ class YangNsd(ToscaResource):
         tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL] = {}
 
         # Add the VNFDs and VLDs
+        vnf_type_vld_list = []
         for idx, vnfd in self.vnfds.items():
             #vnfd.generate_vnf_template(tosca, idx)
             node = {
@@ -591,28 +621,44 @@ class YangNsd(ToscaResource):
             if vnfd.name in self.vnf_to_vld_map:
                 vld_list = self.vnf_to_vld_map[vnfd.name]
                 node[self.REQUIREMENTS] = []
+
                 for vld_idx in range(0, len(vld_list)):
-                    vld_link_name = "{0}{1}".format("virtualLink", vld_idx + 1)
-                    vld_prop = {}
-                    vld_prop[vld_link_name] = vld_list[vld_idx]
-                    node[self.REQUIREMENTS].append(vld_prop)
-                    if vnfd.name in self._vnf_vld_conn_point_map:
-                        vnf_vld_list = self._vnf_vld_conn_point_map[vnfd.name]
-                        for vnf_vld in vnf_vld_list:
-                            vnfd.generate_vld_link(vld_link_name, vnf_vld[1])
+                    if  vnfd.vnf_type not in vnf_type_vld_list:
+                        vld_link_name = "{0}{1}".format("virtualLink", vld_idx + 1)
+                        vld_prop = {}
+                        vld_prop[vld_link_name] = vld_list[vld_idx]
+                        node[self.REQUIREMENTS].append(vld_prop)
+                        if  vnfd.vnf_type not in vnf_type_vld_list:
+                            vnf_type_vld_list.append(vnfd.vnf_type)
+                            if vnfd.name in self._vnf_vld_conn_point_map:
+                                vnf_vld_list = set(self._vnf_vld_conn_point_map[vnfd.name])
+                                for vnf_vld in vnf_vld_list:
+                                    vnfd.generate_vld_link(vld_link_name, vnf_vld[1])
 
             for sub_mapping in self.substitution_mapping_forwarder:
                 if sub_mapping[0] == vnfd.name:
                     vnfd.generate_forwarder_sub_mapping(sub_mapping)
 
-            for vnfd_name, cp_name in self.vnfd_sfc_map.items():
-                if vnfd.name == vnfd_name:
-                    vnfd.generate_sfc_link(cp_name)
+            if self.vnfd_sfc_map:
+                for vnfd_name, cp_name in self.vnfd_sfc_map.items():
+                    if vnfd.name == vnfd_name:
+                        vnfd.generate_sfc_link(cp_name)
 
 
 
             tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vnfd.name] = node
 
+        v_idx = len(self.vnfds) + 1 + len(self.duplicate_vnfd_name_list)
+        for vnfd_name in self.duplicate_vnfd_name_list:
+            node = tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vnfd_name]
+            new_node = deepcopy(node)
+            st = re.sub(r'\d+$', '', vnfd_name.rstrip('_vnfd'))
+
+            new_node[self.PROPERTIES][self.ID] = v_idx
+            node_name = "{}{}_vnfd".format(st, v_idx)
+            tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][node_name] = new_node
+            v_idx += 1
+
         for vld_node_name in self.vlds:
             tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vld_node_name] = self.vlds[vld_node_name]
 
@@ -672,6 +718,23 @@ class YangNsd(ToscaResource):
                         self.INITIAL_CFG: icpt
                     })
 
+        if len(self.service_primitive) > 0:
+            if self.POLICIES not in tosca[self.TOPOLOGY_TMPL]:
+                tosca[self.TOPOLOGY_TMPL][self.POLICIES] = []
+
+            for icp in self.service_primitive:
+                if len(tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL]) > 0:
+                    node_name = list(tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL].keys())[0]
+                    icpt = {
+                        self.TYPE: self.T_NS_PRIMITIVE,
+                        self.TARGETS : "[{0}]".format(node_name)
+                    }
+                    icpt.update(icp)
+                    tosca[self.TOPOLOGY_TMPL][self.POLICIES].append({
+                        'ns_service_primitives': icpt
+                    })
+
+
         if len(self.placement_groups) > 0:
             if self.POLICIES not in tosca[self.TOPOLOGY_TMPL]:
                 tosca[self.TOPOLOGY_TMPL][self.POLICIES] = []
@@ -701,6 +764,25 @@ class YangNsd(ToscaResource):
                         self.DEST: "{}/{}".format(self.SCRIPT_DIR, script),
                     })
 
+        for prim in self.service_primitive:
+            if 'properties' in prim:
+                if 'user_defined_script' in prim['properties']:
+                    script = os.path.basename(prim['properties']['user_defined_script'])
+                    files.append({
+                        self.TYPE: 'script',
+                        self.NAME: script,
+                        self.DEST: "{}/{}".format(self.SCRIPT_DIR, script),
+                    })
+
+        if 'logo' in self.props:
+            icon = os.path.basename(self.props['logo'])
+            files.append({
+                self.TYPE: 'icons',
+                self.NAME: icon,
+                self.DEST: "{}/{}".format(self.ICON_DIR, icon),
+            })
+
+
         # TODO (pjoseph): Add support for config scripts,
         # charms, etc
 
index ec21e3c..84fdf22 100644 (file)
@@ -35,6 +35,15 @@ class YangVnfd(ToscaResource):
                  ('mgmt_interface', 'http_endpoint', 'monitoring_param')
     vnf_prefix_type = 'tosca.nodes.nfv.riftio.'
 
+    VALUE_TYPE_CONVERSION_MAP =  {
+    'INTEGER' : 'integer',
+    'INT' : 'integer',
+    'STRING' : 'string',
+    'DECIMAL' : 'float',
+    'INTEGER': 'INTEGER',
+    'DECIMAL' : 'float'
+
+    }
 
     def __init__(self,
                  log,
@@ -100,7 +109,7 @@ class YangVnfd(ToscaResource):
                         for parameter in init_conf_prim['parameter']:
                             init_conf['parameter'].append({parameter['name']: parameter['value']})
                     init_config_prims.append(init_conf)
-                vnf_conf['initial_config_primitive'] = init_config_prims
+                vnf_conf['initial_config'] = init_config_prims
 
             self.vnf_configuration = vnf_conf
 
@@ -168,6 +177,9 @@ class YangVnfd(ToscaResource):
                     mon_param['url_path'] = param['http_endpoint_ref']
                 if 'json_query_method' in param:
                     mon_param['json_query_method'] = param['json_query_method'].lower()
+                #if 'value_type' in param:
+                #    mon_param['constraints'] = {}
+                #    mon_param['constraints']['value_type'] = YangVnfd.VALUE_TYPE_CONVERSION_MAP[param['value_type'].upper()]
                 if 'group_tag' in param:
                     ui_param['group_tag'] = param['group_tag']
                 if 'widget_type' in param:
@@ -210,7 +222,8 @@ class YangVnfd(ToscaResource):
         dic = deepcopy(self.yang)
         try:
             for key in self.REQUIRED_FIELDS:
-                self.props[key] = dic.pop(key)
+                if key in dic:
+                    self.props[key] = dic.pop(key)
 
             self.id = self.props[self.ID]
 
@@ -292,11 +305,13 @@ class YangVnfd(ToscaResource):
                     mon_param = {}
                     mon_param['properties'] = self.mon_param[0]
                     tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vdu.get_name(self.name)][self.CAPABILITIES]['monitoring_param'] = mon_param #TEST
-                if len(self.mon_param) == 2:
-                    mon_param = {}
-                    mon_param = {}
-                    mon_param['properties'] = self.mon_param[1]
-                    tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vdu.get_name(self.name)][self.CAPABILITIES]['monitoring_param_1'] = mon_param
+                if len(self.mon_param) > 1:
+                    for idx in range(1, len(self.mon_param)):
+                        monitor_param_name = "monitoring_param_{}".format(idx)
+                        mon_param = {}
+                        mon_param = {}
+                        mon_param['properties'] = self.mon_param[idx]
+                        tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vdu.get_name(self.name)][self.CAPABILITIES][monitor_param_name] = mon_param
 
         node = {}
         node[self.TYPE] = self.T_VNF1
@@ -363,13 +378,17 @@ class YangVnfd(ToscaResource):
         for vdu in self.vdus:
             if conn_point in vdu.cp_name_to_cp_node:
                 conn_point_node_name = vdu.cp_name_to_cp_node[conn_point]
-                self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.REQUIREMENTS].\
-                    append({virtualLink : "[{0}, {1}]".format(conn_point_node_name, "virtualLink")})
+                if {virtualLink : "[{0}, {1}]".format(conn_point_node_name, "virtualLink")} not in \
+                 self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.REQUIREMENTS]:
+                    self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.REQUIREMENTS].\
+                        append({virtualLink : "[{0}, {1}]".format(conn_point_node_name, "virtualLink")})
 
         if self.REQUIREMENTS not in self.tosca[self.NODE_TYPES][self.vnf_type]:
             self.tosca[self.NODE_TYPES][self.vnf_type][self.REQUIREMENTS] = []
-        self.tosca[self.NODE_TYPES][self.vnf_type][self.REQUIREMENTS].append({virtualLink : {
-                                                                        "type": "tosca.nodes.nfv.VL"}})
+        if {virtualLink : {"type": "tosca.nodes.nfv.VL"}} not in self.tosca[self.NODE_TYPES][self.vnf_type][self.REQUIREMENTS]:
+            self.tosca[self.NODE_TYPES][self.vnf_type][self.REQUIREMENTS].append({virtualLink : {
+                                                                            "type": "tosca.nodes.nfv.VL"}})
+
     def generate_forwarder_sub_mapping(self, sub_link):
         if self.CAPABILITIES not in self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING]:
             self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.CAPABILITIES] = {}
index 0919494..90288a8 100644 (file)
@@ -59,10 +59,10 @@ class YangTranslator(object):
             self.get_yangs()
         else:
             if 'nsd' in self.yangs:
-                self.output_files['nsd'].append(self.yangs['nsd'][0]['short_name'])
+                self.output_files['nsd'].append(self.yangs['nsd'][0]['short_name'].replace(' ','_'))
             if 'vnfd' in self.yangs:
                 for yang_vnfd in self.yangs['vnfd']:
-                    self.output_files['vnfd'].append(yang_vnfd['short_name'])
+                    self.output_files['vnfd'].append(yang_vnfd['short_name'].replace(' ','_'))
 
         self.node_translator = TranslateDescriptors(self.log,
                                                       self.yangs,
@@ -133,9 +133,9 @@ class YangTranslator(object):
                 raise ValidationError(message="No NSD or VNFD uploaded")
         else:
             if 'nsd' in self.yangs:
-                sub_folder_name = self.yangs['nsd'][0]['short_name']
+                sub_folder_name = self.yangs['nsd'][0]['short_name'].replace(' ','_')
             elif 'vnfd' in self.yangs:
-                sub_folder_name = self.yangs['vnfd'][0]['short_name']
+                sub_folder_name = self.yangs['vnfd'][0]['short_name'].replace(' ','_')
 
 
         subdir = os.path.join(output_dir, sub_folder_name)
@@ -147,14 +147,20 @@ class YangTranslator(object):
         def_dir = os.path.join(subdir, 'Definitions')
         os.makedirs(def_dir)
         shutil.copy2(riftio_src_file, def_dir + "/riftiotypes.yaml")
+        tosca_meta_entry_file = None
         for tmpl_key in tmpl_out:
             tmpl = tmpl_out[tmpl_key]
-            entry_file = os.path.join(def_dir, tmpl_key+'.yaml')
+            file_name = tmpl_key.replace(' ','_')
+            entry_file = os.path.join(def_dir, file_name+'.yaml')
+            if file_name.endswith('nsd'):
+                tosca_meta_entry_file = file_name
             self.log.debug(_("Writing file {0}").
                            format(entry_file))
             with open(entry_file, 'w+') as f:
                 f.write(tmpl[ToscaTemplate.TOSCA])
 
+        if tosca_meta_entry_file is None:
+            tosca_meta_entry_file = sub_folder_name
         # Create the Tosca meta
         meta_dir = os.path.join(subdir, 'TOSCA-Metadata')
         os.makedirs(meta_dir)
@@ -162,7 +168,7 @@ class YangTranslator(object):
 CSAR-Version: 1.1
 Created-By: RIFT.io
 Entry-Definitions: Definitions/'''
-        meta_data = "{}{}".format(meta, sub_folder_name+'.yaml')
+        meta_data = "{}{}".format(meta, tosca_meta_entry_file+'.yaml')
         meta_file = os.path.join(meta_dir, 'TOSCA.meta')
         self.log.debug(_("Writing file {0}:\n{1}").
                        format(meta_file, meta_data))
@@ -213,6 +219,15 @@ Entry-Definitions: Definitions/'''
                                     pkg.extract_file(script_file_map[fname],
                                                      dest_path)
                                     break
+                            elif ftype == 'icons':
+                                icon_file_map = \
+                                    rift.package.icon.PackageIconExtractor.package_icon_files(pkg)
+                                if fname in icon_file_map:
+                                    self.log.debug(_("Extracting script {0} to {1}").
+                                                   format(fname, dest_path))
+                                    pkg.extract_file(icon_file_map[fname],
+                                                     dest_path)
+                                    break
 
                             else:
                                 self.log.warn(_("Unknown file type {0}: {1}").
@@ -226,7 +241,7 @@ Entry-Definitions: Definitions/'''
             os.chdir(subdir)
 
             try:
-                zip_file = key + '.zip'
+                zip_file = sub_folder_name + '.zip'
                 zip_path = os.path.join(output_dir, zip_file)
                 self.log.debug(_("Creating zip file {0}").format(zip_path))
                 zip_cmd = "zip -r {}.partial ."