Fix bug 733
[osm/N2VC.git] / n2vc / vnf.py
index 9f8360b..1ad6d06 100644 (file)
@@ -287,9 +287,10 @@ class N2VC:
 
         vdu:
             ...
-            relation:
-            -   provides: dataVM:db
-                requires: mgmtVM:app
+            vca-relations:
+                relation:
+                -   provides: dataVM:db
+                    requires: mgmtVM:app
 
         This tells N2VC that the charm referred to by the dataVM vdu offers a relation named 'db', and the mgmtVM vdu has an 'app' endpoint that should be connected to a database.
 
@@ -339,8 +340,9 @@ class N2VC:
         # Loop through relations
         for cfg in configs:
             if 'juju' in cfg:
+                juju = cfg['juju']
                 if 'relation' in juju:
-                    for rel in juju['relation']:
+                    for rel in juju['vca-relations']['relation']:
                         try:
 
                             # get the application name for the provides
@@ -443,11 +445,10 @@ class N2VC:
         # Register this application with the model-level event monitor #
         ################################################################
         if callback:
-            self.monitors[model_name].AddApplication(
+            self.log.debug("JujuApi: Registering callback for {}".format(
                 application_name,
-                callback,
-                *callback_args
-            )
+            ))
+            await self.Subscribe(model_name, application_name, callback, *callback_args)
 
         ########################################################
         # Check for specific machine placement (native charms) #
@@ -457,8 +458,8 @@ class N2VC:
             if all(k in machine_spec for k in ['host', 'user']):
                 # Enlist an existing machine as a Juju unit
                 machine = await model.add_machine(spec='ssh:{}@{}:{}'.format(
-                    machine_spec['user'],
-                    machine_spec['host'],
+                    machine_spec['username'],
+                    machine_spec['hostname'],
                     self.GetPrivateKeyPath(),
                 ))
                 to = machine.id
@@ -503,10 +504,19 @@ class N2VC:
             # Where to deploy the charm to.
             to=to,
         )
-
-        # Map the vdu id<->app name,
-        #
-        await self.Relate(model_name, vnfd)
+        #############################
+        # Map the vdu id<->app name #
+        #############################
+        try:
+            await self.Relate(model_name, vnfd)
+        except KeyError as ex:
+            # We don't currently support relations between NS and VNF/VDU charms
+            self.log.warn("[N2VC] Relations not supported: {}".format(ex))
+        except Exception as ex:
+            # This may happen if not all of the charms needed by the relation
+            # are ready. We can safely ignore this, because Relate will be
+            # retried when the endpoint of the relation is deployed.
+            self.log.warn("[N2VC] Relations not ready")
 
         # #######################################
         # # Execute initial config primitive(s) #
@@ -801,7 +811,7 @@ class N2VC:
             app = await self.get_application(model, application_name)
             if app:
                 # Remove this application from event monitoring
-                self.monitors[model_name].RemoveApplication(application_name)
+                await self.Unsubscribe(model_name, application_name)
 
                 # self.notify_callback(model_name, application_name, "removing", callback, *callback_args)
                 self.log.debug(
@@ -906,6 +916,33 @@ class N2VC:
             return True
         return False
 
+    async def Subscribe(self, ns_name, application_name, callback, *callback_args):
+        """Subscribe to callbacks for an application.
+
+        :param ns_name str: The name of the Network Service
+        :param application_name str: The name of the application
+        :param callback obj: The callback method
+        :param callback_args list: The list of arguments to append to calls to
+            the callback method
+        """
+        self.monitors[ns_name].AddApplication(
+            application_name,
+            callback,
+            *callback_args
+        )
+
+    async def Unsubscribe(self, ns_name, application_name):
+        """Unsubscribe to callbacks for an application.
+
+        Unsubscribes the caller from notifications from a deployed application.
+
+        :param ns_name str: The name of the Network Service
+        :param application_name str: The name of the application
+        """
+        self.monitors[ns_name].RemoveApplication(
+            application_name,
+        )
+
     # Non-public methods
     async def add_relation(self, model_name, relation1, relation2):
         """