New feature: Model changes for project support
[osm/SO.git] / examples / ping_pong_ns / rift / mano / examples / ping_pong_nsd.py
index 5348e00..b18deb7 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
-# 
-#   Copyright 2016 RIFT.IO Inc
+#
+#   Copyright 2016-2017 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.
 
 
 import argparse
+import simplejson
 import os
+import yaml
 import shutil
 import sys
 import uuid
 
+from xml.dom.minidom import parseString
+
 import gi
 gi.require_version('RwYang', '1.0')
+gi.require_version('RwProjectYang', '1.0')
 gi.require_version('RwVnfdYang', '1.0')
 gi.require_version('VnfdYang', '1.0')
 gi.require_version('RwNsdYang', '1.0')
@@ -37,6 +42,7 @@ from gi.repository import (
     RwVnfdYang,
     VnfdYang,
     RwYang,
+    RwProjectYang,
 )
 
 
@@ -95,15 +101,31 @@ class ManoDescriptor(object):
         for module in module_list:
             model.load_module(module)
 
-        if output_format == 'json':
-            with open('%s/%s.json' % (outdir, self.name), "w") as fh:
-                fh.write(self.descriptor.to_json(model))
+        # Need to extract the catalog part to dump as descriptor
+        if output_format in ['json', 'yaml']:
+            # Convert to yaml instead of directly using as_dict as
+            # this adds the namespaces correctly
+            ya = self.descriptor.to_yaml(model)
+            proj = yaml.load(ya)
+            desc = proj['rw-project:project'][0]
+
+            if output_format == 'json':
+                with open('%s/%s.json' % (outdir, self.name), "w") as fh:
+                    fh.write(simplejson.dumps(desc, indent=4))
+            elif output_format.strip() == 'yaml':
+                with open('%s/%s.yaml' % (outdir, self.name), "w") as fh:
+                    fh.write(yaml.dump(desc, default_flow_style=False))
         elif output_format.strip() == 'xml':
+            # Converting from dict to xml does not provide the
+            # required output. So using the PBCM to_xml and then
+            # printing only from the catalog tag.
             with open('%s/%s.xml' % (outdir, self.name), "w") as fh:
-                fh.write(self.descriptor.to_xml_v2(model))
-        elif output_format.strip() == 'yaml':
-            with open('%s/%s.yaml' % (outdir, self.name), "w") as fh:
-                fh.write(self.descriptor.to_yaml(model))
+                proj = self.descriptor.to_xml_v2(model)
+                dom = parseString(proj)
+                desc = dom.getElementsByTagName("vnfd:vnfd-catalog")
+                if not desc:
+                    desc = dom.getElementsByTagName("nsd:nsd-catalog")
+                fh.write(desc[0].toprettyxml())
         else:
             raise Exception("Invalid output format for the descriptor")
 
@@ -120,6 +142,7 @@ class VirtualNetworkFunction(ManoDescriptor):
         self.vnfd = None
         self.instance_count = instance_count
         self._placement_groups = []
+        self.use_vnf_init_conf = False
         super(VirtualNetworkFunction, self).__init__(name)
 
     def add_placement_group(self, group):
@@ -128,7 +151,7 @@ class VirtualNetworkFunction(ManoDescriptor):
     def compose(self, image_name, cloud_init="", cloud_init_file="", endpoint=None, mon_params=[],
                 mon_port=8888, mgmt_port=8888, num_vlr_count=1, num_ivlr_count=1,
                 num_vms=1, image_md5sum=None, mano_ut=False):
-        self.descriptor = RwVnfdYang.YangData_Vnfd_VnfdCatalog()
+        self.descriptor = RwVnfdYang.YangData_RwProject_Project_VnfdCatalog()
         self.id = str(uuid.uuid1())
         vnfd = self.descriptor.vnfd.add()
         vnfd.id = self.id
@@ -158,14 +181,14 @@ class VirtualNetworkFunction(ManoDescriptor):
             cp.name = '%s/cp%d' % (self.name, i)
 
         if endpoint is not None:
-            endp = VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd_HttpEndpoint(
+            endp = VnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd_HttpEndpoint(
                     path=endpoint, port=mon_port, polling_interval_secs=2
                     )
             vnfd.http_endpoint.append(endp)
 
         # Monitoring params
         for monp_dict in mon_params:
-            monp = VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd_MonitoringParam.from_dict(monp_dict)
+            monp = VnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd_MonitoringParam.from_dict(monp_dict)
             monp.http_endpoint_ref = endpoint
             vnfd.monitoring_param.append(monp)
 
@@ -214,12 +237,18 @@ class VirtualNetworkFunction(ManoDescriptor):
                 node = vdu.guest_epa.numa_node_policy.node.add()
                 node.id = 0
                 node.memory_mb = 512
-                node.vcpu = [0, 1]
+                vcpu = node.vcpu.add()
+                vcpu.id = 0
+                vcpu = node.vcpu.add()
+                vcpu.id = 1
 
                 node = vdu.guest_epa.numa_node_policy.node.add()
                 node.id = 1
                 node.memory_mb = 512
-                node.vcpu = [2, 3]
+                vcpu = node.vcpu.add()
+                vcpu.id = 2
+                vcpu = node.vcpu.add()
+                vcpu.id = 3
 
                 # specify the vswitch EPA
                 vdu.vswitch_epa.ovs_acceleration = 'DISABLED'
@@ -254,7 +283,8 @@ class VirtualNetworkFunction(ManoDescriptor):
                     internal_cp.name = cp_name + "/icp{}".format(i)
                     internal_cp.id = cp_name + "/icp{}".format(i)
                     internal_cp.type_yang = 'VPORT'
-                    internal_vlds[i].internal_connection_point_ref.append(internal_cp.id)
+                    ivld_cp = internal_vlds[i].internal_connection_point_ref.add()
+                    ivld_cp.id_ref = internal_cp.id
 
                     internal_interface = vdu.internal_interface.add()
                     internal_interface.name = 'fab%d' % i
@@ -294,7 +324,7 @@ class VirtualNetworkFunction(ManoDescriptor):
         dirpath = "%s/%s" % (outdir, self.name)
         if not os.path.exists(dirpath):
             os.makedirs(dirpath)
-        super(VirtualNetworkFunction, self).write_to_file(['vnfd', 'rw-vnfd'],
+        super(VirtualNetworkFunction, self).write_to_file(['rw-project', 'vnfd', 'rw-vnfd'],
                                                           dirpath,
                                                           output_format)
         self.add_scripts(outdir)
@@ -317,6 +347,22 @@ class VirtualNetworkFunction(ManoDescriptor):
         with open(script_file, "w") as f:
             f.write("{}".format(cfg))
 
+        # Copy the vnf_init_config script
+        if self.use_vnf_init_conf and ('ping' in self.name):
+            script_name = 'ping_set_rate.py'
+
+            src_path = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
+            script_src = os.path.join(src_path, script_name)
+            if not os.path.exists(script_src):
+                src_path = os.path.join(os.environ['RIFT_ROOT'],
+                                        'modules/core/mano/examples/ping_pong_ns/rift/mano/examples')
+                script_src = os.path.join(src_path, script_name)
+
+            dest_path = os.path.join(outdir, self.name, 'scripts')
+            os.makedirs(dest_path, exist_ok=True)
+
+            shutil.copy2(script_src, dest_path)
+
 
 class NetworkService(ManoDescriptor):
     def __init__(self, name):
@@ -325,7 +371,7 @@ class NetworkService(ManoDescriptor):
         self.vnfd_config = {}
         self._placement_groups = []
 
-    def ping_config(self, mano_ut, use_ns_init_conf):
+    def ping_config(self, mano_ut, use_ns_init_conf, use_vnf_init_conf):
         suffix = ''
         if mano_ut:
             ping_cfg = r'''
@@ -359,7 +405,10 @@ then
     echo "Failed to set server info for ping!"
     exit $rc
 fi
+''' % suffix
 
+            if use_vnf_init_conf is False:
+                 ping_cfg +='''
 curl -D /dev/stdout \
     -H "Accept: application/vnd.yang.data+xml" \
     -H "Content-Type: application/vnd.yang.data+json" \
@@ -373,7 +422,7 @@ then
     exit $rc
 fi
 
-''' % suffix
+'''
             if use_ns_init_conf:
                 ping_cfg += "exit 0\n"
             else:
@@ -522,7 +571,9 @@ exit 0
             })
             vnf_config.service_primitive.append(config)
 
-    def default_config(self, const_vnfd, vnfd, mano_ut, use_ns_init_conf):
+    def default_config(self, const_vnfd, vnfd, mano_ut,
+                       use_ns_init_conf,
+                       use_vnf_init_conf):
         vnf_config = vnfd.vnfd.vnf_configuration
 
         vnf_config.config_attributes.config_priority = 0
@@ -545,7 +596,23 @@ exit 0
 
         if vnfd.name == 'ping_vnfd' or vnfd.name == 'ping_vnfd_with_epa' or vnfd.name == 'ping_vnfd_aws':
             vnf_config.config_attributes.config_priority = 2
-            vnf_config.config_template = self.ping_config(mano_ut, use_ns_init_conf)
+            vnf_config.config_template = self.ping_config(mano_ut,
+                                                          use_ns_init_conf,
+                                                          use_vnf_init_conf)
+            if use_vnf_init_conf:
+                vnf_config.initial_config_primitive.add().from_dict(
+                    {
+                        "seq": 1,
+                        "name": "set ping rate",
+                        "user_defined_script": "ping_set_rate.py",
+                        "parameter": [
+                            {
+                                'name': 'rate',
+                                'value': '5',
+                            },
+                        ],
+                    }
+                )
 
     def ns_config(self, nsd, vnfd_list, mano_ut):
         # Used by scale group
@@ -588,7 +655,7 @@ exit 0
         self._placement_groups.append(placement_group)
 
     def create_mon_params(self, vnfds):
-        NsdMonParam = NsdYang.YangData_Nsd_NsdCatalog_Nsd_MonitoringParam
+        NsdMonParam = NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd_MonitoringParam
         param_id = 1
         for vnfd_obj in vnfds:
             for mon_param in vnfd_obj.vnfd.monitoring_param:
@@ -608,13 +675,16 @@ exit 0
 
 
 
-    def compose(self, vnfd_list, cpgroup_list, mano_ut, use_ns_init_conf=True):
+    def compose(self, vnfd_list, cpgroup_list, mano_ut,
+                use_ns_init_conf=True,
+                use_vnf_init_conf=True,):
 
         if mano_ut:
             # Disable NS initial config primitive
-            use_ns_init_conf=False
+            use_ns_init_conf = False
+            use_vnf_init_conf = False
 
-        self.descriptor = RwNsdYang.YangData_Nsd_NsdCatalog()
+        self.descriptor = RwNsdYang.YangData_RwProject_Project_NsdCatalog()
         self.id = str(uuid.uuid1())
         nsd = self.descriptor.nsd.add()
         self.nsd = nsd
@@ -626,7 +696,7 @@ exit 0
         nsd.description = 'Toy NS'
         nsd.version = '1.0'
         nsd.input_parameter_xpath.append(
-                NsdYang.YangData_Nsd_NsdCatalog_Nsd_InputParameterXpath(
+                NsdYang.YangData_RwProject_Project_NsdCatalog_Nsd_InputParameterXpath(
                     xpath="/nsd:nsd-catalog/nsd:nsd/nsd:vendor",
                     )
                 )
@@ -637,7 +707,7 @@ exit 0
         ip_profile.ip_profile_params.ip_version = "ipv4"
         ip_profile.ip_profile_params.subnet_address = "31.31.31.0/24"
         ip_profile.ip_profile_params.gateway_address = "31.31.31.210"
-        
+
         vld_id = 1
         for cpgroup in cpgroup_list:
             vld = nsd.vld.add()
@@ -652,7 +722,7 @@ exit 0
             vld.ip_profile_ref = 'InterVNFLink'
             for cp in cpgroup:
                 cpref = vld.vnfd_connection_point_ref.add()
-                cpref.member_vnf_index_ref = cp[0]
+                cpref.member_vnf_index_ref = str(cp[0])
                 cpref.vnfd_id_ref = cp[1]
                 cpref.vnfd_connection_point_ref = cp[2]
 
@@ -672,7 +742,7 @@ exit 0
 
                 constituent_vnfd.vnfd_id_ref = vnfd.descriptor.vnfd[0].id
                 self.default_config(constituent_vnfd, vnfd, mano_ut,
-                                    use_ns_init_conf,)
+                                    use_ns_init_conf, use_vnf_init_conf)
                 member_vnf_index += 1
 
         # Enable config primitives if either mano_ut or
@@ -708,7 +778,7 @@ exit 0
             for member_vnfd in placement_group.vnfd_list:
                 member = group.member_vnfd.add()
                 member.vnfd_id_ref = member_vnfd.descriptor.vnfd[0].id
-                member.member_vnf_index_ref = vnfd_index_map[member_vnfd]
+                member.member_vnf_index_ref = str(vnfd_index_map[member_vnfd])
 
         # self.create_mon_params(vnfd_list)
 
@@ -753,7 +823,7 @@ exit 0
         if not os.path.exists(dirpath):
             os.makedirs(dirpath)
 
-        super(NetworkService, self).write_to_file(["nsd", "rw-nsd"],
+        super(NetworkService, self).write_to_file(["rw-project", "nsd", "rw-nsd"],
                                                   dirpath,
                                                   output_format)
 
@@ -885,6 +955,7 @@ def generate_ping_pong_descriptors(fmt="json",
                                    ex_pong_userdata=None,
                                    use_placement_group=True,
                                    use_ns_init_conf=True,
+                                   use_vnf_init_conf=True,
                                    ):
     # List of connection point groups
     # Each connection point group refers to a virtual link
@@ -895,6 +966,7 @@ def generate_ping_pong_descriptors(fmt="json",
 
     suffix = ''
     ping = VirtualNetworkFunction("ping_vnfd%s" % (suffix), pingcount)
+    ping.use_vnf_init_conf = use_vnf_init_conf
 
     if use_placement_group:
         ### Add group name Eris
@@ -1034,7 +1106,8 @@ def generate_ping_pong_descriptors(fmt="json",
     nsd_catalog.compose(vnfd_list,
                         cpgroup_list,
                         mano_ut,
-                        use_ns_init_conf=use_ns_init_conf,)
+                        use_ns_init_conf=use_ns_init_conf,
+                        use_vnf_init_conf=use_vnf_init_conf,)
 
     if write_to_file:
         ping.write_to_file(out_dir, ping_fmt if ping_fmt is not None else fmt)