Improved Primitive support and better testing
[osm/N2VC.git] / n2vc / vnf.py
index 9641e73..7c39fa1 100644 (file)
@@ -98,6 +98,7 @@ class VCAMonitor(ModelObserver):
                                 self.ns_name,
                                 delta.data['application'],
                                 new_status,
+                                new.workload_status_message,
                                 *callback_args)
 
                 if old and not new:
@@ -107,6 +108,7 @@ class VCAMonitor(ModelObserver):
                             self.ns_name,
                             delta.data['application'],
                             "removed",
+                            "",
                             *callback_args)
             except Exception as e:
                 self.log.debug("[1] notify_callback exception {}".format(e))
@@ -212,10 +214,10 @@ class N2VC:
         """Close any open connections."""
         yield self.logout()
 
-    def notify_callback(self, model_name, application_name, status, callback=None, *callback_args):
+    def notify_callback(self, model_name, application_name, status, message, callback=None, *callback_args):
         try:
             if callback:
-                callback(model_name, application_name, status, *callback_args)
+                callback(model_name, application_name, status, message, *callback_args)
         except Exception as e:
             self.log.error("[0] notify_callback exception {}".format(e))
             raise e
@@ -246,10 +248,7 @@ class N2VC:
 
         Deploy the charm(s) referenced in a VNF Descriptor.
 
-        You can pass either the nsd record or the id of the network
-        service, but this method will fail without one of them.
-
-        :param str ns_name: The name of the network service
+        :param str model_name: The name of the network service.
         :param str application_name: The name of the application
         :param dict vnfd: The name of the application
         :param str charm_path: The path to the Juju charm
@@ -298,7 +297,7 @@ class N2VC:
         ########################################
         app = await self.get_application(model, application_name)
         if app:
-            raise JujuApplicationExists("Can't deploy application \"{}\" to model \"{}\" because it already exists.".format(application_name, model))
+            raise JujuApplicationExists("Can't deploy application \"{}\" to model \"{}\" because it already exists.".format(application_name, model_name))
 
         ################################################################
         # Register this application with the model-level event monitor #
@@ -376,10 +375,14 @@ class N2VC:
                 else:
                     seq = primitive['seq']
 
+                    params = {}
+                    if 'parameter' in primitive:
+                        params = primitive['parameter']
+
                     primitives[seq] = {
                         'name': primitive['name'],
                         'parameters': self._map_primitive_parameters(
-                            primitive['parameter'],
+                            params,
                             {'<rw_mgmt_ip>': rw_mgmt_ip}
                         ),
                     }
@@ -394,16 +397,51 @@ class N2VC:
                             **primitives[primitive]['parameters'],
                         )
             except N2VCPrimitiveExecutionFailed as e:
-                self.debug.log(
+                self.log.debug(
                     "[N2VC] Exception executing primitive: {}".format(e)
                 )
                 raise
 
+    async def GetPrimitiveStatus(self, model_name, uuid):
+        results = None
+        try:
+            if not self.authenticated:
+                await self.login()
+
+            # FIXME: This is hard-coded until model-per-ns is added
+            model_name = 'default'
+
+            model = await self.controller.get_model(model_name)
+
+            results = await model.get_action_output(uuid)
+
+            await model.disconnect()
+        except Exception as e:
+            self.log.debug(
+                "Caught exception while getting primitive status: {}".format(e)
+            )
+            raise N2VCPrimitiveExecutionFailed(e)
+
+        return results
+
+
     async def ExecutePrimitive(self, model_name, application_name, primitive, callback, *callback_args, **params):
-        """
-        Queue the execution of a primitive
+        """Execute a primitive of a charm for Day 1 or Day 2 configuration.
+
+        Execute a primitive defined in the VNF descriptor.
 
-        returns the UUID of the executed primitive
+        :param str model_name: The name of the network service.
+        :param str application_name: The name of the application
+        :param str primitive: The name of the primitive to execute.
+        :param obj callback: A callback function to receive status changes.
+        :param tuple callback_args: A list of arguments to be passed to the callback function.
+        :param dict params: A dictionary of key=value pairs representing the primitive's parameters
+          Examples::
+          {
+            'rw_mgmt_ip': '1.2.3.4',
+            # Pass the initial-config-primitives section of the vnf or vdu
+            'initial-config-primitives': {...}
+          }
         """
         uuid = None
         try:
@@ -417,25 +455,40 @@ class N2VC:
 
             if primitive == 'config':
                 # config is special, and expecting params to be a dictionary
-                self.log.debug("Setting charm configuration for {}".format(application_name))
-                self.log.debug(params['params'])
-                await self.set_config(model, application_name, params['params'])
+                await self.set_config(
+                    model,
+                    application_name,
+                    params['params'],
+                )
             else:
                 app = await self.get_application(model, application_name)
                 if app:
                     # Run against the first (and probably only) unit in the app
                     unit = app.units[0]
                     if unit:
-                        self.log.debug("Executing primitive {}".format(primitive))
+                        self.log.debug(
+                            "Executing primitive {}".format(primitive)
+                        )
                         action = await unit.run_action(primitive, **params)
                         uuid = action.id
                 await model.disconnect()
         except Exception as e:
-            self.log.debug("Caught exception while executing primitive: {}".format(e))
-            raise e
+            self.log.debug(
+                "Caught exception while executing primitive: {}".format(e)
+            )
+            raise N2VCPrimitiveExecutionFailed(e)
         return uuid
 
     async def RemoveCharms(self, model_name, application_name, callback=None, *callback_args):
+        """Remove a charm from the VCA.
+
+        Remove a charm referenced in a VNF Descriptor.
+
+        :param str model_name: The name of the network service.
+        :param str application_name: The name of the application
+        :param obj callback: A callback function to receive status changes.
+        :param tuple callback_args: A list of arguments to be passed to the callback function.
+        """
         try:
             if not self.authenticated:
                 await self.login()