New feature: Support static IP in VNF connection points 67/767/1
authorPhilip Joseph <philip.joseph@riftio.com>
Thu, 8 Dec 2016 09:14:58 +0000 (04:14 -0500)
committerPhilip Joseph <philip.joseph@riftio.com>
Thu, 8 Dec 2016 10:20:06 +0000 (05:20 -0500)
Signed-off-by: Philip Joseph <philip.joseph@riftio.com>
examples/ping_pong_ns/rift/mano/examples/ping_pong_nsd.py
models/plugins/yang/nsd.yang
models/plugins/yang/vnfd.yang
rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/openstack_drv.py
rwcal/plugins/vala/rwcal_openstack/rwcal_openstack.py
rwcal/plugins/yang/rwcal.yang
rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/rwnsmtasklet.py
rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py

index d84a912..db066f8 100755 (executable)
@@ -127,7 +127,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):
+                num_vms=1, image_md5sum=None, mano_ut=False, use_static_ip=False):
         self.descriptor = RwVnfdYang.YangData_Vnfd_VnfdCatalog()
         self.id = str(uuid.uuid1())
         vnfd = self.descriptor.vnfd.add()
@@ -156,6 +156,11 @@ class VirtualNetworkFunction(ManoDescriptor):
             cp = vnfd.connection_point.add()
             cp.type_yang = 'VPORT'
             cp.name = '%s/cp%d' % (self.name, i)
+            if use_static_ip:
+                if 'pong_' in self.name:
+                    cp.static_ip_address = '31.31.31.31'
+                else:
+                    cp.static_ip_address = '31.31.31.32'
 
         if endpoint is not None:
             endp = VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd_HttpEndpoint(
@@ -892,6 +897,7 @@ def generate_ping_pong_descriptors(fmt="json",
                                    ex_pong_userdata=None,
                                    use_placement_group=True,
                                    use_ns_init_conf=True,
+                                   use_static_ip=False,
                                    ):
     # List of connection point groups
     # Each connection point group refers to a virtual link
@@ -936,6 +942,7 @@ def generate_ping_pong_descriptors(fmt="json",
             num_vms=num_vnf_vms,
             image_md5sum=ping_md5sum,
             mano_ut=mano_ut,
+            use_static_ip=use_static_ip,
             )
 
     pong = VirtualNetworkFunction("pong_vnfd%s" % (suffix))
@@ -976,6 +983,7 @@ def generate_ping_pong_descriptors(fmt="json",
             num_vms=num_vnf_vms,
             image_md5sum=pong_md5sum,
             mano_ut=mano_ut,
+            use_static_ip=use_static_ip,
             )
 
     # Initialize the member VNF index
index 31750ca..84b6325 100644 (file)
@@ -292,9 +292,9 @@ module nsd
           }
         }
 
-         leaf vnfd-id-ref {
-           description
-               "A reference to a vnfd. This is a
+        leaf vnfd-id-ref {
+          description
+            "A reference to a vnfd. This is a
                 leafref to path:
                     ../../nsd:constituent-vnfd
                     + [nsd:id = current()/../nsd:id-ref]
@@ -304,12 +304,12 @@ module nsd
                 to leafref, whose target is in a different module.
                 Once that is resovled this will switched to use
                 leafref";
-           type string;
-         }
+          type string;
+        }
 
-         leaf vnfd-connection-point-ref {
-           description
-               "A reference to a connection point name
+        leaf vnfd-connection-point-ref {
+          description
+            "A reference to a connection point name
                 in a vnfd. This is a leafref to path:
                     /vnfd:vnfd-catalog/vnfd:vnfd
                     + [vnfd:id = current()/../nsd:vnfd-id-ref]
@@ -319,7 +319,7 @@ module nsd
                 to leafref, whose target is in a different module.
                 Once that is resovled this will switched to use
                 leafref";
-            type string;
+          type string;
         }
       }
 
index 5dc19ce..46c5edd 100644 (file)
@@ -67,6 +67,11 @@ module vnfd
       description "Type of the connection point.";
       type manotypes:connection-point-type;
     }
+
+    leaf static-ip-address {
+      description "Static IP address for the connection point";
+      type inet:ip-address;
+    }
   }
 
   grouping virtual-interface {
@@ -271,6 +276,7 @@ module vnfd
             }
           }
         }
+
         uses manotypes:provider-network;
       }
 
index 943cdd5..5f44e5e 100644 (file)
@@ -1393,19 +1393,28 @@ class NeutronDriver(object):
               name (string)      : Name of the port
               network_id(string) : UUID of the network_id identifying the network to which port belongs
               subnet_id(string)  : UUID of the subnet_id from which IP-address will be assigned to port
+              ip_address(string) : Static IP address to assign to the port
               vnic_type(string)  : Possible values are "normal", "direct", "macvtap"
            }
         Returns:
            port_id (string)   : UUID of the port
+
+        NOTE: Either subnet_id or ip_address need to be specified.
         """
         params = {
             "port": {
                 "admin_state_up"    : kwargs['admin_state_up'],
                 "name"              : kwargs['name'],
                 "network_id"        : kwargs['network_id'],
-                "fixed_ips"         : [ {"subnet_id": kwargs['subnet_id']}],
                 "binding:vnic_type" : kwargs['port_type']}}
 
+        if 'ip_address' in kwargs:
+            params["port"]["fixed_ips"] = [{"ip_address": kwargs['ip_address']}]
+        else:
+            params["port"]["fixed_ips"] = [{"subnet_id": kwargs['subnet_id']}]
+
+        logger.debug("Port create params: {}".format(params))
+
         ntconn = self._get_neutron_connection()
         try:
             port  = ntconn.create_port(params)
@@ -1861,7 +1870,7 @@ class OpenstackDriver(object):
             return pool_list[0]
         else:
             return None
-        
+
     def neutron_port_list(self, **kwargs):
         return self.neutron_drv.port_list(**kwargs)
 
@@ -1869,11 +1878,18 @@ class OpenstackDriver(object):
         return self.neutron_drv.port_get(port_id)
 
     def neutron_port_create(self, **kwargs):
-        subnets = [subnet for subnet in self.neutron_drv.subnet_list() if subnet['network_id'] == kwargs['network_id']]
-        assert len(subnets) == 1
-        kwargs['subnet_id'] = subnets[0]['id']
+
+        if 'ip_address' not in kwargs:
+            subnets = [subnet for subnet in self.neutron_drv.subnet_list()
+                       if subnet['network_id'] == kwargs['network_id']]
+            assert len(subnets) == 1
+            kwargs['subnet_id'] = subnets[0]['id']
+
         if not 'admin_state_up' in kwargs:
             kwargs['admin_state_up'] = True
+
+        logger.debug("Port create params: {}".
+                     format(kwargs))
         port_id =  self.neutron_drv.port_create(**kwargs)
 
         if 'vm_id' in kwargs:
index 05dc498..3bdf882 100644 (file)
@@ -1460,6 +1460,7 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud):
            account  - a cloud account
            c_point  - connection_points
         """
+
         kwargs = {}
         kwargs['name'] = c_point.name
         kwargs['network_id'] = c_point.virtual_link_id
@@ -1472,11 +1473,16 @@ class RwcalOpenstackPlugin(GObject.Object, RwCal.Cloud):
         else:
             raise NotImplementedError("Port Type: %s not supported" %(c_point.type_yang))
 
+        if c_point.static_ip_address:
+            kwargs["ip_address"] = c_point.static_ip_address
+
         with self._use_driver(account) as drv:
             if c_point.has_field('security_group'):
                 group = drv.neutron_security_group_by_name(c_point.security_group)
                 if group is not None:
                     kwargs['security_groups'] = [group['id']]
+            self.log.debug("Create connection point port : {}".
+                           format(kwargs))
             return drv.neutron_port_create(**kwargs)
 
     def _allocate_floating_ip(self, drv, pool_name):
index 76bd38b..37a9f18 100644 (file)
@@ -43,6 +43,10 @@ module rwcal
     prefix "manotypes";
   }
 
+  import ietf-inet-types {
+    prefix "inet";
+  }
+
   revision 2014-12-30 {
     description
         "Initial revision.";
@@ -972,6 +976,11 @@ module rwcal
         type string;
       }
 
+      leaf static-ip-address {
+        description "Static IP address for the connection point";
+        type inet:ip-address;
+      }
+
       uses connection-point-type;
     }
 
@@ -1049,6 +1058,11 @@ module rwcal
         default false;
       }
 
+      leaf static-ip-address {
+        description "Static IP address for the connection point";
+        type inet:ip-address;
+      }
+
       uses connection-point-type;
     }
 
index 718d2b1..fff855e 100755 (executable)
@@ -961,7 +961,8 @@ class VirtualNetworkFunctionRecord(object):
 
         vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict(vnfr_dict)
 
-        vnfr.vnfd = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vnfd.from_dict(self.vnfd.as_dict())
+        vnfr.vnfd = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vnfd.from_dict(self.vnfd.as_dict(),
+                                                                           ignore_missing_keys=True)
         vnfr.member_vnf_index_ref = self.member_vnf_index
         vnfr.vnf_configuration.from_dict(self._vnfd.vnf_configuration.as_dict())
 
@@ -1083,6 +1084,13 @@ class VirtualNetworkFunctionRecord(object):
                 continue
 
             cpr.vlr_ref = vlr_ref.id
+
+            try:
+                if conn_p.static_ip_address:
+                    cpr.static_ip_address = conn_p.static_ip_address
+            except AttributeError as e:
+                pass
+
             self.vnfr_msg.connection_point.append(cpr)
             self._log.debug("Connection point [%s] added, vnf id=%s vnfd id=%s",
                             cpr, self.vnfr_msg.id, self.vnfr_msg.vnfd.id)
@@ -3266,7 +3274,11 @@ class NsrDtsHandler(object):
             def begin_instantiation(nsr):
                 # Begin instantiation
                 self._log.info("Beginning NS instantiation: %s", nsr.id)
-                yield from self._nsm.instantiate_ns(nsr.id, xact)
+                try:
+                    yield from self._nsm.instantiate_ns(nsr.id, xact)
+                except Exception as e:
+                    self._log.exception(e)
+                    raise e
 
             self._log.debug("Got nsr apply (xact: %s) (action: %s)(scr: %s)",
                             xact, action, scratch)
index 8a4474e..e39a8ae 100755 (executable)
@@ -422,7 +422,7 @@ class VirtualDeploymentUnitRecord(object):
             icp_list.append({"name": cp.name,
                              "id": cp.id,
                              "type_yang": "VPORT",
-                             "ip_address": self.cp_ip_addr(cp.id)})
+                             "ip_address": self.cp_ip_addr(cp.name)})
 
             ii_list.append({"name": intf.name,
                             "vdur_internal_connection_point_ref": cp.id,
@@ -434,10 +434,10 @@ class VirtualDeploymentUnitRecord(object):
 
         ei_list = []
         for intf, cp, vlr in self._ext_intf:
-            ei_list.append({"name": cp,
-                            "vnfd_connection_point_ref": cp,
+            ei_list.append({"name": cp.name,
+                            "vnfd_connection_point_ref": cp.name,
                             "virtual_interface": {}})
-            self._vnfr.update_cp(cp, self.cp_ip_addr(cp), self.cp_id(cp))
+            self._vnfr.update_cp(cp.name, self.cp_ip_addr(cp.name), self.cp_id(cp.name))
 
         vdur_dict["external_interface"] = ei_list
 
@@ -573,10 +573,16 @@ class VirtualDeploymentUnitRecord(object):
 
         cp_list = []
         for intf, cp, vlr in self._ext_intf:
-            cp_info = {"name": cp,
+            cp_info = {"name": cp.name,
                        "virtual_link_id": vlr.network_id,
                        "type_yang": intf.virtual_interface.type_yang}
 
+            try:
+                if cp.static_ip_address:
+                    cp_info["static_ip_address"] = cp.static_ip_address
+            except AttributeError as e:
+                pass
+
             if (intf.virtual_interface.has_field('vpci') and
                     intf.virtual_interface.vpci is not None):
                 cp_info["vpci"] =  intf.virtual_interface.vpci
@@ -584,19 +590,28 @@ class VirtualDeploymentUnitRecord(object):
             if (vlr.has_field('ip_profile_params')) and (vlr.ip_profile_params.has_field('security_group')):
                 cp_info['security_group'] = vlr.ip_profile_params.security_group
 
+            self._log.debug("External CP info {}".format(cp_info))
             cp_list.append(cp_info)
 
-        for intf, cp, vlr in self._int_intf:
+        for intf, cp_id, vlr in self._int_intf:
+            cp = self.find_internal_cp_by_cp_id(cp_id)
+
+            cp_dict = {"name": cp_id,
+                       "virtual_link_id": vlr.network_id,
+                       "type_yang": intf.virtual_interface.type_yang}
+
             if (intf.virtual_interface.has_field('vpci') and
                     intf.virtual_interface.vpci is not None):
-                cp_list.append({"name": cp,
-                                "virtual_link_id": vlr.network_id,
-                                "type_yang": intf.virtual_interface.type_yang,
-                                "vpci": intf.virtual_interface.vpci})
-            else:
-                cp_list.append({"name": cp,
-                                "virtual_link_id": vlr.network_id,
-                                "type_yang": intf.virtual_interface.type_yang})
+                cp_dict["vpci"] = intf.virtual_interface.vpci
+
+            try:
+                if cp.static_ip_address:
+                    cp_dict["static_ip_address"] = cp.static_ip_address
+            except AttributeError as e:
+                pass
+
+            self._log.debug("Internal CP info {}".format(cp_info))
+            cp_list.append(cp_dict)
 
         vm_create_msg_dict["connection_points"] = cp_list
         vm_create_msg_dict.update(vdu_copy_dict)
@@ -680,28 +695,15 @@ class VirtualDeploymentUnitRecord(object):
                                 cp_name)
             return cp
 
-        def find_internal_vlr_by_cp_name(cp_name):
-            """ Find the VLR corresponding to the connection point name"""
-            cp = None
-
-            self._log.debug("find_internal_vlr_by_cp_name(%s) called",
-                            cp_name)
-
-            for int_cp in self._vdud.internal_connection_point:
-                self._log.debug("Checking for int cp %s in internal connection points",
-                                int_cp.id)
-                if int_cp.id == cp_name:
-                    cp = int_cp
-                    break
+        def find_internal_vlr_by_cp_id(cp_id):
+            self._log.debug("find_internal_vlr_by_cp_id(%s) called",
+                            cp_id)
 
-            if cp is None:
-                self._log.debug("Failed to find cp %s in internal connection points",
-                                cp_name)
-                msg = "Failed to find cp %s in internal connection points" % cp_name
-                raise VduRecordError(msg)
+            # Validate the cp
+            cp = self.find_internal_cp_by_cp_id(cp_id)
 
             # return the VLR associated with the connection point
-            return vnfr.find_vlr_by_cp(cp_name)
+            return vnfr.find_vlr_by_cp(cp_id)
 
         block = xact.block_create()
 
@@ -722,7 +724,7 @@ class VirtualDeploymentUnitRecord(object):
 
             vlr = vnfr.ext_vlr_by_id(cp.vlr_ref)
 
-            etuple = (ext_intf, cp.name, vlr)
+            etuple = (ext_intf, cp, vlr)
             self._ext_intf.append(etuple)
 
             self._log.debug("Created external interface tuple  : %s", etuple)
@@ -734,7 +736,7 @@ class VirtualDeploymentUnitRecord(object):
                             intf.name, cp_id)
 
             try:
-                vlr = find_internal_vlr_by_cp_name(cp_id)
+                vlr = find_internal_vlr_by_cp_id(cp_id)
             except Exception as e:
                 self._log.debug("Failed to find cp %s in internal VLR list", cp_id)
                 msg = "Failed to find cp %s in internal VLR list, e = %s" % (cp_id, e)
@@ -1738,7 +1740,7 @@ class VirtualNetworkFunctionRecord(object):
 
             def cpr_from_cp(cp):
                 """ Creates a record level connection point from the desciptor cp"""
-                cp_fields = ["name", "image", "vm-flavor"]
+                cp_fields = ["name", "image", "vm-flavor", "static_ip_address"]
                 cp_copy_dict = {k: v for k, v in cp.as_dict().items() if k in cp_fields}
                 cpr_dict = {}
                 cpr_dict.update(cp_copy_dict)