Merge "Fix bug #502"
[osm/N2VC.git] / n2vc / vnf.py
index d6c87dc..075d235 100644 (file)
@@ -397,11 +397,34 @@ 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):
         """Execute a primitive of a charm for Day 1 or Day 2 configuration.
 
@@ -432,22 +455,28 @@ 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):
@@ -554,7 +583,50 @@ class N2VC:
             if parameter['value'] == "<rw_mgmt_ip>":
                 params[param] = str(values[parameter['value']])
             else:
-                params[param] = str(parameter['value'])
+                """
+                The Juju API uses strictly typed data-types, so we must make
+                sure the parameters from the VNFD match the appropriate type.
+
+                The honus will still be on the operator, to make sure the
+                data-type in the VNFD matches the one in the charm. N2VC will
+                raise N2VCPrimitiveExecutionFailed when there is a mismatch.
+
+                There are three data types supported by the YANG model:
+                # - STRING
+                # - INTEGER
+                # - BOOLEAN
+
+                Each parameter will look like this:
+                {
+                    'seq': '3',
+                    'name': 'testint',
+                    'parameter': [
+                        {
+                            'name': 'interval',
+                            'data-type': 'INTEGER',
+                            'value': 20
+                        }
+                    ]
+                }
+                """
+
+                if 'value' in parameter:
+                    # String is the default format
+                    val = str(parameter['value'])
+
+                    # If the data-type is explicitly set, cast to that type.
+                    if 'data-type' in parameter:
+                        dt = parameter['data-type'].upper()
+                        if dt == "INTEGER":
+                            val = int(val)
+
+                        elif dt == "BOOLEAN":
+                            if val in ['true', 'false', '0', '1']:
+                                val = True
+                            else:
+                                val = False
+
+                    params[param] = val
         return params
 
     def _get_config_from_yang(self, config_primitive, values):