Fix bug 760
[osm/N2VC.git] / n2vc / vnf.py
index 0d9530e..c8ee2ef 100644 (file)
@@ -47,6 +47,9 @@ class NetworkServiceDoesNotExist(Exception):
     """The Network Service being acted against does not exist."""
 
 
+class PrimitiveDoesNotExist(Exception):
+    """The Primitive being executed does not exist."""
+
 # Quiet the debug logging
 logging.getLogger('websockets.protocol').setLevel(logging.INFO)
 logging.getLogger('juju.client.connection').setLevel(logging.WARN)
@@ -287,9 +290,10 @@ class N2VC:
 
         vdu:
             ...
-            relation:
-            -   provides: dataVM:db
-                requires: mgmtVM:app
+            vca-relationships:
+                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.
 
@@ -340,8 +344,8 @@ class N2VC:
         for cfg in configs:
             if 'juju' in cfg:
                 juju = cfg['juju']
-                if 'relation' in juju:
-                    for rel in juju['relation']:
+                if 'vca-relationships' in juju and 'relation' in juju['vca-relationships']:
+                    for rel in juju['vca-relationships']['relation']:
                         try:
 
                             # get the application name for the provides
@@ -457,8 +461,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 +507,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) #
@@ -713,16 +726,25 @@ class N2VC:
                     }
 
                     for primitive in sorted(primitives):
-                        uuids.append(
-                            await self.ExecutePrimitive(
-                                model_name,
-                                application_name,
-                                primitives[primitive]['name'],
-                                callback,
-                                callback_args,
-                                **primitives[primitive]['parameters'],
+                        try:
+                            # self.log.debug("Queuing action {}".format(primitives[primitive]['name']))
+                            uuids.append(
+                                await self.ExecutePrimitive(
+                                    model_name,
+                                    application_name,
+                                    primitives[primitive]['name'],
+                                    callback,
+                                    callback_args,
+                                    **primitives[primitive]['parameters'],
+                                )
                             )
-                        )
+                        except PrimitiveDoesNotExist as e:
+                            self.log.debug("Ignoring exception PrimitiveDoesNotExist: {}".format(e))
+                            pass
+                        except Exception as e:
+                            self.log.debug("XXXXXXXXXXXXXXXXXXXXXXXXX Unexpected exception: {}".format(e))
+                            raise e
+
             except N2VCPrimitiveExecutionFailed as e:
                 self.log.debug(
                     "[N2VC] Exception executing primitive: {}".format(e)
@@ -769,12 +791,22 @@ class N2VC:
             else:
                 app = await self.get_application(model, application_name)
                 if app:
+                    # Does this primitive exist?
+                    actions = await app.get_actions()
+
+                    if primitive not in actions.keys():
+                        raise PrimitiveDoesNotExist("Primitive {} does not exist".format(primitive))
+
                     # Run against the first (and probably only) unit in the app
                     unit = app.units[0]
                     if unit:
                         action = await unit.run_action(primitive, **params)
                         uuid = action.id
+        except PrimitiveDoesNotExist as e:
+            # Catch and raise this exception if it's thrown from the inner block
+            raise e
         except Exception as e:
+            # An unexpected exception was caught
             self.log.debug(
                 "Caught exception while executing primitive: {}".format(e)
             )