Find WIM before creating local networks 09/7009/7
authorAnderson Bravalheri <a.bravalheri@bristol.ac.uk>
Fri, 30 Nov 2018 09:55:29 +0000 (09:55 +0000)
committerAnderson Bravalheri <a.bravalheri@bristol.ac.uk>
Fri, 18 Jan 2019 12:24:01 +0000 (12:24 +0000)
The usage of the wim_account information for create networks inside the
VIMs/datacenters should be developed in future commits

Change-Id: I545455f23cbde9071b2bdc91ae032b7a76e0eefe
Signed-off-by: Anderson Bravalheri <a.bravalheri@bristol.ac.uk>
osm_ro/nfvo.py
osm_ro/wim/engine.py
osm_ro/wim/persistence.py
osm_ro/wim/tests/test_engine.py

index 7b8a820..b1c86f9 100644 (file)
@@ -61,6 +61,7 @@ from .http_tools import errors as httperrors
 from .wim.engine import WimEngine
 from .wim.persistence import WimPersistence
 from copy import deepcopy
+from pprint import pformat
 #
 
 global global_config
@@ -3034,6 +3035,8 @@ def create_instance(mydb, tenant_id, instance_dict):
     # Auxiliary dictionaries from x to y
     sce_net2instance = {}
     net2task_id = {'scenario': {}}
+    # Mapping between local networks and WIMs
+    wim_usage = {}
 
     def ip_profile_IM2RO(ip_profile_im):
         # translate from input format to database format
@@ -3177,6 +3180,18 @@ def create_instance(mydb, tenant_id, instance_dict):
             if not involved_datacenters:
                 involved_datacenters.append(default_datacenter_id)
 
+            # --> WIM
+            # TODO: use this information during network creation
+            wim_account_id = None
+            if len(involved_datacenters) > 1 and 'uuid' in sce_net:
+                # OBS: sce_net without uuid are used internally to VNFs
+                # and the assumption is that VNFs will not be split among
+                # different datacenters
+                wim_account_id = wim_engine.find_suitable_wim_account(
+                    involved_datacenters, tenant_id)
+                wim_usage[sce_net['uuid']] = wim_account_id
+            # <-- WIM
+
             descriptor_net = {}
             if instance_dict.get("networks") and instance_dict["networks"].get(sce_net["name"]):
                 descriptor_net = instance_dict["networks"][sce_net["name"]]
@@ -3499,7 +3514,8 @@ def create_instance(mydb, tenant_id, instance_dict):
         db_instance_action["number_tasks"] = task_index
 
         # --> WIM
-        wan_links = wim_engine.derive_wan_links(db_instance_nets, tenant_id)
+        logger.debug('wim_usage:\n%s\n\n', pformat(wim_usage))
+        wan_links = wim_engine.derive_wan_links(wim_usage, db_instance_nets, tenant_id)
         wim_actions = wim_engine.create_actions(wan_links)
         wim_actions, db_instance_action = (
             wim_engine.incorporate_actions(wim_actions, db_instance_action))
index dde5dee..fcb3477 100644 (file)
@@ -247,7 +247,7 @@ class WimEngine(object):
         """Find a single WIM that is able to connect all the datacenters
         listed
 
-        Raises
+        Raises:
             NoWimConnectedToDatacenters: if no WIM connected to all datacenters
                 at once is found
         """
@@ -261,14 +261,35 @@ class WimEngine(object):
         #       used here)
         return suitable_wim_ids[0]
 
+    def find_suitable_wim_account(self, datacenter_ids, tenant):
+        """Find a WIM account that is able to connect all the datacenters
+        listed
+
+        Arguments:
+            datacenter_ids (list): List of UUIDs of all the datacenters (vims),
+                that need to be connected.
+            tenant (str): UUID of the OSM tenant
+
+        Returns:
+            str: UUID of the WIM account that is able to connect all the
+                 datacenters.
+        """
+        wim_id = self.find_common_wim(datacenter_ids, tenant)
+        return self.persist.get_wim_account_by(wim_id, tenant)['uuid']
+
     def derive_wan_link(self,
+                        wim_usage,
                         instance_scenario_id, sce_net_id,
                         networks, tenant):
         """Create a instance_wim_nets record for the given information"""
-        datacenters = [n['datacenter_id'] for n in networks]
-        wim_id = self.find_common_wim(datacenters, tenant)
-
-        account = self.persist.get_wim_account_by(wim_id, tenant)
+        if sce_net_id in wim_usage:
+            account_id = wim_usage[sce_net_id]
+            account = self.persist.get_wim_account_by(uuid=account_id)
+            wim_id = account['wim_id']
+        else:
+            datacenters = [n['datacenter_id'] for n in networks]
+            wim_id = self.find_common_wim(datacenters, tenant)
+            account = self.persist.get_wim_account_by(wim_id, tenant)
 
         return {
             'uuid': str(uuid4()),
@@ -278,15 +299,17 @@ class WimEngine(object):
             'wim_account_id': account['uuid']
         }
 
-    def derive_wan_links(self, networks, tenant=None):
+    def derive_wan_links(self, wim_usage, networks, tenant=None):
         """Discover and return what are the wan_links that have to be created
         considering a set of networks (VLDs) required for a scenario instance
         (NSR).
 
         Arguments:
+            wim_usage(dict): Mapping between sce_net_id and wim_id
             networks(list): Dicts containing the information about the networks
                 that will be instantiated to materialize a Network Service
                 (scenario) instance.
+                Corresponding to the ``instance_net`` record.
 
         Returns:
             list: list of WAN links to be written to the database
@@ -302,7 +325,8 @@ class WimEngine(object):
                       if counter > 1]
 
         return [
-            self.derive_wan_link(key[0], key[1], grouped_networks[key], tenant)
+            self.derive_wan_link(wim_usage,
+                                 key[0], key[1], grouped_networks[key], tenant)
             for key in wan_groups
         ]
 
index 8a74d49..8f95d56 100644 (file)
@@ -363,10 +363,10 @@ class WimPersistence(object):
             kwargs.setdefault('WHERE', {'wim_account.uuid': uuid})
         return self.query(FROM=_WIM_ACCOUNT_JOIN, **kwargs)
 
-    def get_wim_account_by(self, wim=None, tenant=None, **kwargs):
+    def get_wim_account_by(self, wim=None, tenant=None, uuid=None, **kwargs):
         """Similar to ``get_wim_accounts_by``, but ensuring just one result"""
         kwargs.setdefault('error_if_multiple', True)
-        return self.get_wim_accounts_by(wim, tenant, **kwargs)[0]
+        return self.get_wim_accounts_by(wim, tenant, uuid, **kwargs)[0]
 
     def get_wim_accounts(self, **kwargs):
         """Retrieve all the accounts from the database"""
index 6fb2d8c..9bb7bca 100644 (file)
@@ -163,8 +163,7 @@ class TestWimEngine(unittest.TestCase):
         # When we receive a list of 4 instance nets, representing
         # 2 VLDs connecting 2 datacenters each
         instance_nets = eg.instance_nets(2, 2)
-        wan_links = engine.derive_wan_links(
-            instance_nets, uuid('tenant0'))
+        wan_links = engine.derive_wan_links({}, instance_nets, uuid('tenant0'))
 
         # Then we should derive 2 wan_links with the same instance_scenario_id
         # and different scenario_network_id