From 1ada8dbd934164c007c5b81ea4273b4438350545 Mon Sep 17 00:00:00 2001 From: Philip Joseph Date: Fri, 23 Sep 2016 06:53:11 -0400 Subject: [PATCH] Bug 54 : Fix PE NS instantiation error Signed-off-by: Philip Joseph --- .../python/rift/mano/config_agent/operdata.py | 1 + .../rift/tasklets/rwconmantasklet/RiftCA.py | 22 +++ .../tasklets/rwconmantasklet/RiftCM_rpc.py | 166 +++++++++++++++++- .../rift/tasklets/rwconmantasklet/jujuconf.py | 31 +++- .../rwconmantasklet/riftcm_config_plugin.py | 7 + .../tasklets/rwnsmtasklet/openmano_nsm.py | 2 +- 6 files changed, 214 insertions(+), 15 deletions(-) diff --git a/common/python/rift/mano/config_agent/operdata.py b/common/python/rift/mano/config_agent/operdata.py index b941667f..6bbf7f25 100644 --- a/common/python/rift/mano/config_agent/operdata.py +++ b/common/python/rift/mano/config_agent/operdata.py @@ -557,6 +557,7 @@ class ConfigAgentJobMonitor(object): primitive.execution_id ) + self.log.debug("Action status: {}".format(resp)) status = resp['status'] if status == 'failed': self.log.warning("Execution of action {} failed: {}". diff --git a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCA.py b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCA.py index 4a95a7da..0400a54a 100644 --- a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCA.py +++ b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCA.py @@ -52,6 +52,28 @@ class RiftCAConfigPlugin(riftcm_config_plugin.RiftCMConfigPluginBase): def agent_type(self): return self._type + @property + def agent_data(self): + return dict( + type=self.agent_type, + name=self.name, + ) + + def vnfr(self, vnfr_id): + try: + vnfr = self._rift_vnfs[vnfr_id].vnfr + except KeyError: + self._log.debug("RiftCA: Did not find VNFR %s in Rift plugin", vnfr_id) + return None + + return vnfr + + def get_service_name(self, vnfr_id): + vnfr = self.vnfr(vnfr_id) + if vnfr: + return vnfr['name'] + return None + @asyncio.coroutine def notify_create_vlr(self, agent_nsr, agent_vnfr, vld, vlr): """ diff --git a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCM_rpc.py b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCM_rpc.py index 61b6bb20..03756d87 100644 --- a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCM_rpc.py +++ b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/RiftCM_rpc.py @@ -16,9 +16,16 @@ # import asyncio +import os +import re +import tempfile import time +import yaml + +from . import riftcm_config_plugin import rift.mano.config_agent + import gi gi.require_version('RwDts', '1.0') gi.require_version('RwNsrYang', '1.0') @@ -47,6 +54,9 @@ class RiftCMRPCHandler(object): self.job_manager = rift.mano.config_agent.ConfigAgentJobManager(dts, log, loop, nsm) + self._rift_install_dir = os.environ['RIFT_INSTALL'] + self._rift_artif_dir = os.environ['RIFT_ARTIFACTS'] + @property def reghs(self): """ Return registration handles """ @@ -102,6 +112,147 @@ class RiftCMRPCHandler(object): raise ValueError("Could not find nsr/vnf {}/{} primitive {}" .format(nsr_id, vnfr_id, primitive_name)) + @asyncio.coroutine + def _apply_ns_config(self, agent_nsr, agent_vnfrs, rpc_ip): + """ + Hook: Runs the user defined script. Feeds all the necessary data + for the script thro' yaml file. + + TBD: Add support to pass multiple CA accounts if configures + Remove apply_ns_config from the Config Agent Plugins + + Args: + rpc_ip (YangInput_Nsr_ExecNsConfigPrimitive): The input data. + nsr (NetworkServiceRecord): Description + vnfrs (dict): VNFR ID => VirtualNetworkFunctionRecord + + """ + def xlate(tag, tags): + # TBD + if tag is None or tags is None: + return tag + val = tag + if re.search('<.*>', tag): + try: + if tag == '': + val = tags['rw_mgmt_ip'] + except KeyError as e: + self._log.info("RiftCA: Did not get a value for tag %s, e=%s", + tag, e) + return val + + def get_meta(agent_nsr, agent_vnfrs): + unit_names, initial_params, vnfr_index_map, vnfr_data_map = {}, {}, {}, {} + + for vnfr_id in agent_nsr.vnfr_ids: + vnfr = agent_vnfrs[vnfr_id] + self._log.debug("CA_RPC: VNFR metadata: {}".format(vnfr)) + + # index->vnfr ref + vnfr_index_map[vnfr.member_vnf_index] = vnfr_id + vnfr_data_dict = dict() + if 'mgmt_interface' in vnfr.vnfr: + vnfr_data_dict['mgmt_interface'] = vnfr.vnfr['mgmt_interface'] + + vnfr_data_dict['connection_point'] = [] + if 'connection_point' in vnfr.vnfr: + for cp in vnfr.vnfr['connection_point']: + cp_dict = dict() + cp_dict['name'] = cp['name'] + cp_dict['ip_address'] = cp['ip_address'] + vnfr_data_dict['connection_point'].append(cp_dict) + + try: + vnfr_data_dict['vdur'] = [] + vdu_data = [(vdu['name'], vdu['management_ip'], vdu['vm_management_ip'], vdu['id']) + for vdu in vnfr.vnfr['vdur']] + + for data in vdu_data: + data = dict(zip(['name', 'management_ip', 'vm_management_ip', 'id'] , data)) + vnfr_data_dict['vdur'].append(data) + + vnfr_data_map[vnfr.member_vnf_index] = vnfr_data_dict + except KeyError as e: + self._log.warn("Error getting VDU data for VNFR {}".format(vnfr)) + + # Unit name + unit_names[vnfr_id] = None + for config_plugin in self.nsm.config_agent_plugins: + name = config_plugin.get_service_name(vnfr_id) + if name: + unit_names[vnfr_id] = name + break + + # Flatten the data for simplicity + param_data = {} + if 'initial_config_primitive' in vnfr.vnf_configuration: + for primitive in vnfr.vnf_configuration['initial_config_primitive']: + if 'parameter' in primitive: + for parameter in primitive['parameter']: + value = xlate(parameter['value'], vnfr.tags) + param_data[parameter.name] = value + + initial_params[vnfr_id] = param_data + + + return unit_names, initial_params, vnfr_index_map, vnfr_data_map + + def get_config_agent(): + ret = {} + for config_plugin in self.nsm.config_agent_plugins: + if config_plugin.agent_type in [riftcm_config_plugin.DEFAULT_CAP_TYPE]: + ret = config_plugin.agent_data + else: + # Currently the first non default plugin is returned + return config_plugin.agent_data + return ret + + unit_names, init_data, vnfr_index_map, vnf_data_map = get_meta(agent_nsr, agent_vnfrs) + + # The data consists of 4 sections + # 1. Account data + # 2. The input passed. + # 3. Juju unit names (keyed by vnfr ID). + # 4. Initial config data (keyed by vnfr ID). + data = dict() + data['config_agent'] = get_config_agent() + data["rpc_ip"] = rpc_ip.as_dict() + data["unit_names"] = unit_names + data["init_config"] = init_data + data["vnfr_index_map"] = vnfr_index_map + data["vnfr_data_map"] = vnfr_data_map + + tmp_file = None + with tempfile.NamedTemporaryFile(delete=False) as tmp_file: + tmp_file.write(yaml.dump(data, default_flow_style=True) + .encode("UTF-8")) + + self._log.debug("CA_RPC: Creating a temp file {} with input data: {}". + format(tmp_file.name, data)) + + # Get the full path to the script + script = '' + if rpc_ip.user_defined_script[0] == '/': + # The script has full path, use as is + script = rpc_ip.user_defined_script + else: + script = os.path.join(self._rift_artif_dir, 'launchpad/libs', agent_nsr.id, 'scripts', + rpc_ip.user_defined_script) + self.log.debug("CA_RPC: Checking for script in %s", script) + if not os.path.exists(script): + script = os.path.join(self._rift_install_dir, 'usr/bin', rpc_ip.user_defined_script) + + cmd = "{} {}".format(rpc_ip.user_defined_script, tmp_file.name) + self._log.debug("CA_RPC: Running the CMD: {}".format(cmd)) + + coro = asyncio.create_subprocess_shell(cmd, loop=self._loop, + stderr=asyncio.subprocess.PIPE) + process = yield from coro + err = yield from process.stderr.read() + task = self._loop.create_task(process.wait()) + + return task, err + @asyncio.coroutine def register(self): """ Register for NS monitoring read from dts """ @@ -161,14 +312,13 @@ class RiftCMRPCHandler(object): rpc_ip.user_defined_script = nsd_cfg_prim_msg.user_defined_script tasks = [] - for config_plugin in self.nsm.config_agent_plugins: - task, err = yield from config_plugin.apply_ns_config( - nsr, - vnfrs, - rpc_ip) - tasks.append(task) - if err: - rpc_op.job_status_details = err.decode() + task, err = yield from self._apply_ns_config( + nsr, + vnfrs, + rpc_ip) + tasks.append(task) + if err: + rpc_op.job_status_details = err.decode() self.job_manager.add_job(rpc_op, tasks) else: diff --git a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/jujuconf.py b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/jujuconf.py index 364546ad..1f0ed8ef 100644 --- a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/jujuconf.py +++ b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/jujuconf.py @@ -79,6 +79,16 @@ class JujuConfigPlugin(riftcm_config_plugin.RiftCMConfigPluginBase): return self._api @property + def agent_data(self): + return dict( + type=self.agent_type, + name=self.name, + host=self._ip_address, + port=self._port, + user=self._user, + secret=self._secret + ) + def vnfr(self, vnfr_id): try: vnfr = self._juju_vnfs[vnfr_id].vnfr @@ -88,6 +98,12 @@ class JujuConfigPlugin(riftcm_config_plugin.RiftCMConfigPluginBase): return vnfr + def get_service_name(self, vnfr_id): + vnfr = self.vnfr(vnfr_id) + if vnfr and 'vnf_juju_name' in vnfr: + return vnfr['vnf_juju_name'] + return None + def juju_log(self, level, name, log_str, *args): if name is not None: g_log_str = 'jujuCA:({}) {}'.format(name, log_str) @@ -531,11 +547,11 @@ class JujuConfigPlugin(riftcm_config_plugin.RiftCMConfigPluginBase): self._log.info("jujuCA:(%s) Action %s with params %s", vnfr['vnf_juju_name'], action, params) - resp = yield from self.api.execute_actions(action, params, - service=service) + resp = yield from self.api.execute_action(action, params, + service=service) if 'error' in resp: - self._log.error("Applying initial config failed: {}". - format(resp)) + self._log.error("Applying initial config failed for {} with {}: {}". + format(action, params, resp)) return False action_ids.append(resp['action']['tag']) @@ -554,7 +570,7 @@ class JujuConfigPlugin(riftcm_config_plugin.RiftCMConfigPluginBase): while pending: pending = False for act in action_ids: - resp = yield from self.api.get_action_status(act, service=service) + resp = yield from self.api.get_action_status(act) if 'error' in resp: self._log.error("Initial config failed: {}".format(resp)) return False @@ -647,7 +663,10 @@ class JujuConfigPlugin(riftcm_config_plugin.RiftCMConfigPluginBase): ''' try: - return self.api._get_action_status(execution_id) + self._log.debug("jujuCA: Get action status for {}".format(execution_id)) + resp = self.api._get_action_status(execution_id) + self._log.debug("jujuCA: Action status: {}".format(resp)) + return resp except Exception as e: self._log.error("jujuCA: Error fetching execution status for %s", execution_id) diff --git a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/riftcm_config_plugin.py b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/riftcm_config_plugin.py index 1540360f..4d0c700e 100644 --- a/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/riftcm_config_plugin.py +++ b/rwcm/plugins/rwconman/rift/tasklets/rwconmantasklet/riftcm_config_plugin.py @@ -166,6 +166,10 @@ class RiftCMConfigPluginBase(object): def name(self): raise NotImplementedError + @property + def agent_data(self): + raise NotImplementedError + @property def dts(self): return self._dts @@ -183,6 +187,9 @@ class RiftCMConfigPluginBase(object): return self._nsm + def vnfr(self, vnfr_id): + raise NotImplementedError + @abc.abstractmethod @asyncio.coroutine def apply_config(self, agent_nsr, agent_vnfr, config, rpc_ip): diff --git a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py index 5bf86dec..94206d57 100644 --- a/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py +++ b/rwlaunchpad/plugins/rwnsm/rift/tasklets/rwnsmtasklet/openmano_nsm.py @@ -239,7 +239,7 @@ class OpenmanoVnfr(object): class OpenmanoNsr(object): - TIMEOUT_SECS = 120 + TIMEOUT_SECS = 300 def __init__(self, dts, log, loop, publisher, cli_api, http_api, nsd_msg, nsr_config_msg,key_pairs): self._dts = dts -- 2.25.1