#
import asyncio
+import gi
import os
import stat
import subprocess
RwConmanYang as conmanY,
ProtobufC,
)
+gi.require_version('RwKeyspec', '1.0')
+from gi.repository.RwKeyspec import quoted_key
import rift.tasklets
+import rift.package.script
+import rift.package.store
from . import rwconman_conagent as conagent
from . import RiftCM_rpc
from . import riftcm_config_plugin
+
if sys.version_info < (3, 4, 4):
asyncio.ensure_future = asyncio.async
-def get_vnf_unique_name(nsr_name, vnfr_short_name, member_vnf_index):
- return "{}.{}.{}".format(nsr_name, vnfr_short_name, member_vnf_index)
+def get_vnf_unique_name(nsr_name, vnfr_name, member_vnf_index):
+ return "{}.{}.{}".format(nsr_name, vnfr_name, member_vnf_index)
+
class ConmanConfigError(Exception):
pass
pass
+class ScriptNotFoundError(InitialConfigError):
+ pass
+
+
def log_this_vnf(vnf_cfg):
log_vnf = ""
used_item_list = ['nsr_name', 'vnfr_name', 'member_vnf_index', 'mgmt_ip_address']
self._log = log
self._loop = loop
self._parent = parent
+ self._project = parent._project
+
self._nsr_dict = {}
self.pending_cfg = {}
self.terminate_cfg = {}
self.pending_tasks = [] # User for NSRid get retry
# (mainly excercised at restart case)
- self._config_xpath = "C,/cm-config"
- self._opdata_xpath = "D,/rw-conman:cm-state"
- self.cm_config = conmanY.SoConfig()
- # RO specific configuration
- self.ro_config = {}
- for key in self.cm_config.ro_endpoint.fields:
- self.ro_config[key] = None
+ self._opdata_xpath = self._project.add_project("D,/rw-conman:cm-state")
# Initialize cm-state
self.cm_state = {}
self.cm_state['states'] = "Initialized"
# Initialize objects to register
- self.cmdts_obj = ConfigManagerDTS(self._log, self._loop, self, self._dts)
+ self.cmdts_obj = ConfigManagerDTS(self._log, self._loop, self, self._dts, self._project)
self._config_agent_mgr = conagent.RiftCMConfigAgent(
self._dts,
self._log,
self._loop,
self,
)
+
+ self.riftcm_rpc_handler = RiftCM_rpc.RiftCMRPCHandler(self._dts, self._log, self._loop, self._project,
+ PretendNsm(
+ self._dts, self._log, self._loop, self))
+
self.reg_handles = [
self.cmdts_obj,
self._config_agent_mgr,
- RiftCM_rpc.RiftCMRPCHandler(self._dts, self._log, self._loop,
- PretendNsm(
- self._dts, self._log, self._loop, self)),
+ self.riftcm_rpc_handler
]
+ self._op_reg = None
def is_nsr_valid(self, nsr_id):
if nsr_id in self._nsr_dict:
def add_to_pending_tasks(self, task):
if self.pending_tasks:
for p_task in self.pending_tasks:
- if p_task['nsrid'] == task['nsrid']:
+ if (p_task['nsrid'] == task['nsrid']) and \
+ (p_task['event'] == task['event']):
# Already queued
return
try:
self.pending_tasks.append(task)
self._log.debug("add_to_pending_tasks (nsrid:%s)",
task['nsrid'])
- if len(self.pending_tasks) == 1:
+ if len(self.pending_tasks) >= 1:
self._loop.create_task(self.ConfigManagerConfig_pending_loop())
# TBD - change to info level
self._log.debug("Started pending_loop!")
+
except Exception as e:
self._log.error("Failed adding to pending tasks (%s)", str(e))
"""
if self.pending_tasks:
self._log.debug("self.pending_tasks len=%s", len(self.pending_tasks))
- task = self.pending_tasks[0]
+ task = self.pending_tasks.pop(0)
done = False
if 'nsrid' in task:
nsrid = task['nsrid']
- self._log.debug("Will execute pending task for NSR id(%s)", nsrid)
+ self._log.debug("Will execute pending task for NSR id: %s", nsrid)
try:
# Try to configure this NSR
task['retries'] -= 1
- done = yield from self.config_NSR(nsrid)
+ done = yield from self.config_NSR(nsrid, task['event'])
self._log.info("self.config_NSR status=%s", done)
except Exception as e:
- self._log.error("Failed(%s) configuring NSR(%s)," \
+ self._log.error("Failed(%s) configuring NSR(%s) for task %s," \
"retries remained:%d!",
- str(e), nsrid, task['retries'])
- finally:
- self.pending_tasks.remove(task)
+ str(e), nsrid, task['event'] , task['retries'])
+ self._log.exception(e)
+ if task['event'] == 'terminate':
+ # Ignore failure
+ done = True
if done:
- self._log.debug("Finished pending task NSR id(%s):", nsrid)
+ self._log.debug("Finished pending task NSR id: %s", nsrid)
else:
self._log.error("Failed configuring NSR(%s), retries remained:%d!",
nsrid, task['retries'])
# Initialize all handles that needs to be registered
for reg in self.reg_handles:
yield from reg.register()
-
+
+ def deregister(self):
+ # De-register all reg handles
+ self._log.debug("De-register ConfigManagerConfig for project {}".
+ format(self._project))
+
+ for reg in self.reg_handles:
+ reg.deregister()
+ reg = None
+
+ self._op_reg.delete_element(self._opdata_xpath)
+ self._op_reg.deregister()
+
@asyncio.coroutine
def register_cm_state_opdata(self):
conmanY.RecordState.CFG_PROCESS : "cfg_process",
conmanY.RecordState.CFG_PROCESS_FAILED : "cfg_process_failed",
conmanY.RecordState.CFG_SCHED : "cfg_sched",
- conmanY.RecordState.CFG_DELAY : "cfg_delay",
conmanY.RecordState.CONNECTING : "connecting",
conmanY.RecordState.FAILED_CONNECTION : "failed_connection",
- conmanY.RecordState.NETCONF_CONNECTED : "netconf_connected",
- conmanY.RecordState.NETCONF_SSH_CONNECTED : "netconf_ssh_connected",
- conmanY.RecordState.RESTCONF_CONNECTED : "restconf_connected",
conmanY.RecordState.CFG_SEND : "cfg_send",
conmanY.RecordState.CFG_FAILED : "cfg_failed",
conmanY.RecordState.READY_NO_CFG : "ready_no_cfg",
conmanY.RecordState.READY : "ready",
+ conmanY.RecordState.TERMINATE : "terminate",
}
return state_dict[state]
self._log.debug("Received cm-state: msg=%s, action=%s", msg, action)
if action == rwdts.QueryAction.READ:
- show_output = conmanY.CmOpdata()
- show_output.from_dict(self.cm_state)
self._log.debug("Responding to SHOW cm-state: %s", self.cm_state)
+ show_output = conmanY.YangData_RwProject_Project_CmState()
+ show_output.from_dict(self.cm_state)
xact_info.respond_xpath(rwdts.XactRspCode.ACK,
xpath=self._opdata_xpath,
msg=show_output)
try:
handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare)
- yield from self._dts.register(xpath=self._opdata_xpath,
- handler=handler,
- flags=rwdts.Flag.PUBLISHER)
+ self._op_reg = yield from self._dts.register(xpath=self._opdata_xpath,
+ handler=handler,
+ flags=rwdts.Flag.PUBLISHER)
self._log.info("Successfully registered for opdata(%s)", self._opdata_xpath)
except Exception as e:
self._log.error("Failed to register for opdata as (%s)", e)
+
+ def get_config_method(self, vnf_config):
+ cfg_types = ['juju', 'script']
+ for method in cfg_types:
+ if method in vnf_config:
+ return method
+ return None
@asyncio.coroutine
def process_nsd_vnf_configuration(self, nsr_obj, vnfr):
- def get_config_method(vnf_config):
- cfg_types = ['netconf', 'juju', 'script']
- for method in cfg_types:
- if method in vnf_config:
- return method
- return None
-
- def get_cfg_file_extension(method, configuration_options):
- ext_dict = {
- "netconf" : "xml",
- "script" : {
- "bash" : "sh",
- "expect" : "exp",
- },
- "juju" : "yml"
- }
-
- if method == "netconf":
- return ext_dict[method]
- elif method == "script":
- return ext_dict[method][configuration_options['script_type']]
- elif method == "juju":
- return ext_dict[method]
- else:
- return "cfg"
-
- # This is how the YAML file should look like,
- # This routine will be called for each VNF, so keep appending the file.
- # priority order is determined by the number,
- # hence no need to generate the file in that order. A dictionary will be
- # used that will take care of the order by number.
- '''
- 1 : <== This is priority
- name : trafsink_vnfd
- member_vnf_index : 2
- configuration_delay : 120
- configuration_type : netconf
- configuration_options :
- username : admin
- password : admin
- port : 2022
- target : running
- 2 :
- name : trafgen_vnfd
- member_vnf_index : 1
- configuration_delay : 0
- configuration_type : netconf
- configuration_options :
- username : admin
- password : admin
- port : 2022
- target : running
- '''
+ # Get vnf_configuration from vnfr
+ vnf_config = vnfr['vnf_configuration']
# Save some parameters needed as short cuts in flat structure (Also generated)
vnf_cfg = vnfr['vnf_cfg']
# Prepare unique name for this VNF
vnf_cfg['vnf_unique_name'] = get_vnf_unique_name(
- vnf_cfg['nsr_name'], vnfr['short_name'], vnfr['member_vnf_index_ref'])
-
- nsr_obj.cfg_path_prefix = '{}/{}_{}'.format(
- nsr_obj.this_nsr_dir, vnfr['short_name'], vnfr['member_vnf_index_ref'])
- nsr_vnfr = '{}/{}_{}'.format(
- vnf_cfg['nsr_name'], vnfr['short_name'], vnfr['member_vnf_index_ref'])
-
- # Get vnf_configuration from vnfr
- vnf_config = vnfr['vnf_configuration']
+ vnf_cfg['nsr_name'], vnfr['name'], vnfr['member_vnf_index_ref'])
self._log.debug("vnf_configuration = %s", vnf_config)
- # Create priority dictionary
- cfg_priority_order = 0
- if ('config_attributes' in vnf_config and
- 'config_priority' in vnf_config['config_attributes']):
- cfg_priority_order = vnf_config['config_attributes']['config_priority']
+ method = self.get_config_method(vnf_config)
- if cfg_priority_order not in nsr_obj.nsr_cfg_config_attributes_dict:
- # No VNFR with this priority yet, initialize the list
- nsr_obj.nsr_cfg_config_attributes_dict[cfg_priority_order] = []
-
- method = get_config_method(vnf_config)
if method is not None:
- # Create all sub dictionaries first
- config_priority = {
- 'id' : vnfr['id'],
- 'name' : vnfr['short_name'],
- 'member_vnf_index' : vnfr['member_vnf_index_ref'],
- }
-
- if 'config_delay' in vnf_config['config_attributes']:
- config_priority['configuration_delay'] = vnf_config['config_attributes']['config_delay']
- vnf_cfg['config_delay'] = config_priority['configuration_delay']
-
- configuration_options = {}
self._log.debug("config method=%s", method)
- config_priority['configuration_type'] = method
vnf_cfg['config_method'] = method
# Set config agent based on method
self._config_agent_mgr.set_config_agent(
- nsr_obj.agent_nsr, vnf_cfg['agent_vnfr'], method)
-
- cfg_opt_list = [
- 'port', 'target', 'script_type', 'ip_address', 'user', 'secret',
- ]
- for cfg_opt in cfg_opt_list:
- if cfg_opt in vnf_config[method]:
- configuration_options[cfg_opt] = vnf_config[method][cfg_opt]
- vnf_cfg[cfg_opt] = configuration_options[cfg_opt]
-
- cfg_opt_list = ['mgmt_ip_address', 'username', 'password']
- for cfg_opt in cfg_opt_list:
- if cfg_opt in vnf_config['config_access']:
- configuration_options[cfg_opt] = vnf_config['config_access'][cfg_opt]
- vnf_cfg[cfg_opt] = configuration_options[cfg_opt]
-
- # Add to the cp_dict
- vnf_cp_dict = nsr_obj._cp_dict[vnfr['member_vnf_index_ref']]
- vnf_cp_dict['rw_mgmt_ip'] = vnf_cfg['mgmt_ip_address']
- vnf_cp_dict['rw_username'] = vnf_cfg['username']
- vnf_cp_dict['rw_password'] = vnf_cfg['password']
-
+ nsr_obj.agent_nsr, vnf_cfg['agent_vnfr'], method)
+ else:
+ self._log.info("VNF:(%s) is not to be configured by Configuration Manager!",
+ log_this_vnf(vnfr['vnf_cfg']))
+ yield from nsr_obj.update_vnf_cm_state(vnfr, conmanY.RecordState.READY_NO_CFG)
- # TBD - see if we can neatly include the config in "config_attributes" file, no need though
- #config_priority['config_template'] = vnf_config['config_template']
- # Create config file
- vnf_cfg['juju_script'] = os.path.join(self._parent.cfg_dir, 'juju_if.py')
+ # Update the cm-state
+ nsr_obj.populate_cm_state_from_vnf_cfg()
- if 'config_template' in vnf_config:
- vnf_cfg['cfg_template'] = '{}_{}_template.cfg'.format(nsr_obj.cfg_path_prefix, config_priority['configuration_type'])
- vnf_cfg['cfg_file'] = '{}.{}'.format(nsr_obj.cfg_path_prefix, get_cfg_file_extension(method, configuration_options))
- vnf_cfg['xlate_script'] = os.path.join(self._parent.cfg_dir, 'xlate_cfg.py')
- try:
- # Now write this template into file
- with open(vnf_cfg['cfg_template'], "w") as cf:
- cf.write(vnf_config['config_template'])
- except Exception as e:
- self._log.error("Processing NSD, failed to generate configuration template : %s (Error : %s)",
- vnf_config['config_template'], str(e))
- raise
+ @asyncio.coroutine
+ def update_config_primitives(self, nsr_obj):
+
+ # Process all config-primitives in the member VNFs
+ for vnfr in nsr_obj.vnfrs:
+ vnfd = vnfr['vnf_cfg']['agent_vnfr'].vnfd
- self._log.debug("VNF endpoint so far: %s", vnf_cfg)
+ try:
+ prims = vnfd.vnf_configuration.config_primitive
+ if not prims:
+ self._log.debug("VNFR {} with VNFD {} has no config primitives defined".
+ format(vnfr['name'], vnfd.name))
+ return
+ except AttributeError as e:
+ self._log.error("No config primitives found on VNFR {} ({})".
+ format(vnfr['name'], vnfd.name))
+ continue
+
+ cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
+ srcs = cm_state['config_parameter']['config_parameter_source']
+ reqs = cm_state['config_parameter']['config_parameter_request']
+
+ vnf_configuration = vnfd.vnf_configuration.as_dict()
+ vnf_configuration['config_primitive'] = []
+
+ for prim in prims:
+ confp = prim.as_dict()
+ if 'parameter' not in confp:
+ continue
- # Populate filled up dictionary
- config_priority['configuration_options'] = configuration_options
- nsr_obj.nsr_cfg_config_attributes_dict[cfg_priority_order].append(config_priority)
- nsr_obj.num_vnfs_to_cfg += 1
- nsr_obj._vnfr_dict[vnf_cfg['vnf_unique_name']] = vnfr
- nsr_obj._vnfr_dict[vnfr['id']] = vnfr
+ for param in confp['parameter']:
+ # First check the param in capabilities
+ found = False
+ for src in srcs:
+ for p in src['parameter']:
+ if (p['config_primitive_ref'] == confp['name']) \
+ and (p['parameter_ref'] == param['name']):
+ param['default_value'] = src['value']
+ found = True
+ break
+ if found:
+ break
+
+ if not found:
+ for req in reqs:
+ for p in req['parameter']:
+ if (p['config_primitive_ref'] == confp['name']) \
+ and (p['parameter_ref'] == param['name']):
+ param['default_value'] = req['value']
+ found = True
+ break
+ if found:
+ break
+
+ self._log.debug("Config primitive: {}".format(confp))
+ vnf_configuration['config_primitive'].append(confp)
+
+ cm_state['vnf_configuration'] = vnf_configuration
- self._log.debug("VNF:(%s) config_attributes = %s",
- log_this_vnf(vnfr['vnf_cfg']),
- nsr_obj.nsr_cfg_config_attributes_dict)
+ @asyncio.coroutine
+ def get_resolved_xpath(self, xpath, name, vnf_name, xpath_prefix):
+ # For now, use DTS to resolve the path
+ # TODO (pjoseph): Add better xpath support
+
+ dts_path = xpath
+ if xpath.startswith('../'):
+ prefix = xpath_prefix
+ xp = xpath
+ while xp.startswith('../'):
+ idx = prefix.rfind('/')
+ if idx == -1:
+ raise ValueError("VNF {}, Did not find the xpath specified: {}".
+ format(vnf_name, xpath))
+ prefix = prefix[:idx]
+ xp = xp[3:]
+
+ dts_path = prefix + '/' + xp
+
+ elif xpath.startswith('/'):
+ dts_path = 'C,' + xpath
+ elif xpath.startswith('C,/') or xpath.startswith('D,/'):
+ dts_path = xpath
else:
- self._log.info("VNF:(%s) is not to be configured by Configuration Manager!",
- log_this_vnf(vnfr['vnf_cfg']))
- yield from nsr_obj.update_vnf_cm_state(vnfr, conmanY.RecordState.READY_NO_CFG)
+ self._log.error("Invalid xpath {} for source {} in VNF {}".
+ format(xpath, name, vnf_name))
+ raise ValueError("Descriptor xpath {} in source {} for VNF {} "
+ "is invalid".
+ format(xpath, name, vnf_name))
- # Update the cm-state
- nsr_obj.populate_vm_state_from_vnf_cfg()
+ dts_path = self._project.add_project(dts_path)
+ return dts_path
@asyncio.coroutine
- def config_NSR(self, id):
+ def resolve_xpath(self, xpath, name, vnfd):
+ xpath_prefix = "C,/project-vnfd:vnfd-catalog/vnfd[id={}]/config-parameter" \
+ "/config-parameter-source[name={}]" \
+ "/descriptor".format(quoted_key(vnfd.id), quoted_key(name))
+
+ dts_path = yield from self.get_resolved_xpath(xpath, name,
+ vnfd.name, xpath_prefix)
+ idx = dts_path.rfind('/')
+ if idx == -1:
+ raise ValueError("VNFD {}, descriptor xpath {} should point to " \
+ "an attribute".format(vnfd.name, xpath))
+
+ attr = dts_path[idx+1:]
+ dts_path = dts_path[:idx]
+ self._log.debug("DTS path: {}, attribute: {}".format(dts_path, attr))
+
+ resp = yield from self.cmdts_obj.get_xpath(dts_path)
+ if resp is None:
+ raise ValueError("Xpath {} in capability {} for VNFD {} is not found".
+ format(xpath, name, vnfd.name))
+ self._log.debug("DTS response: {}".format(resp.as_dict()))
+
+ try:
+ val = getattr(resp, attr)
+ except AttributeError as e:
+ self._log.error("Did not find attribute : {}".format(attr))
+ try:
+ val = getattr(resp, attr.replace('-', '_'))
+ except AttributeError as e:
+ raise ValueError("Did not find attribute {} in XPath {} "
+ "for capability {} in VNF {}".
+ format(attr, dts_path, vnfd.name))
- def my_yaml_dump(config_attributes_dict, yf):
+ self._log.debug("XPath {}: {}".format(xpath, val))
+ return val
- yaml_dict = dict(sorted(config_attributes_dict.items()))
- yf.write(yaml.dump(yaml_dict, default_flow_style=False))
-
- nsr_dict = self._nsr_dict
- self._log.info("Configure NSR, id = %s", id)
+ @asyncio.coroutine
+ def resolve_attribute(self, attribute, name, vnfd, vnfr):
+ idx = attribute.rfind(',')
+ if idx == -1:
+ raise ValueError ("Invalid attribute {} for capability {} in "
+ "VNFD specified".
+ format(attribute, name, vnfd.name))
+ xpath = attribute[:idx].strip()
+ attr = attribute[idx+1:].strip()
+ self._log.debug("Attribute {}, {}".format(xpath, attr))
+ if xpath.startswith('C,/'):
+ raise ValueError("Attribute {} for capability {} in VNFD cannot "
+ "be a config".
+ format(attribute, name, vnfd.name))
+
+ xpath_prefix = "D,/vnfr:vnfr-catalog/vnfr[id={}]/config_parameter" \
+ "/config-parameter-source[name={}]" \
+ "/attribute".format(quoted_key(vnfr['id']), quoted_key(name))
+ dts_path = yield from self.get_resolved_xpath(xpath, name,
+ vnfr['name'],
+ xpath_prefix)
+ self._log.debug("DTS query: {}".format(dts_path))
+
+ resp = yield from self.cmdts_obj.get_xpath(dts_path)
+ if resp is None:
+ raise ValueError("Attribute {} in request {} for VNFD {} is " \
+ "not found".
+ format(xpath, name, vnfd.name))
+ self._log.debug("DTS response: {}".format(resp.as_dict()))
- #####################TBD###########################
- # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_create_nsr', self.id, self._nsd)
- # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_nsr_active', self.id, self._vnfrs)
-
try:
- if id not in nsr_dict:
- nsr_obj = ConfigManagerNSR(self._log, self._loop, self, id)
- nsr_dict[id] = nsr_obj
- else:
- self._log.info("NSR(%s) is already initialized!", id)
- nsr_obj = nsr_dict[id]
- except Exception as e:
- self._log.error("Failed creating NSR object for (%s) as (%s)", id, str(e))
- raise
+ val = getattr(resp, attr)
+ except AttributeError as e:
+ self._log.debug("Did not find attribute {}".format(attr))
+ try:
+ val = getattr(resp, attr.replace('-', '_'))
+ except AttributeError as e:
+ raise ValueError("Did not find attribute {} in XPath {} "
+ "for source {} in VNF {}".
+ format(attr, dts_path, vnfd.name))
- # Try to configure this NSR only if not already processed
- if nsr_obj.cm_nsr['state'] != nsr_obj.state_to_string(conmanY.RecordState.INIT):
- self._log.debug("NSR(%s) is already processed, state=%s",
- nsr_obj.nsr_name, nsr_obj.cm_nsr['state'])
- yield from nsr_obj.publish_cm_state()
- return True
+ self._log.debug("Attribute {}: {}".format(attribute, val))
+ return val
- cmdts_obj = self.cmdts_obj
+ @asyncio.coroutine
+ def process_vnf_config_parameter(self, nsr_obj):
+ nsd = nsr_obj.agent_nsr.nsd
+
+ # Process all capabilities in all the member VNFs
+ for vnfr in nsr_obj.vnfrs:
+ vnfd = vnfr['vnf_cfg']['agent_vnfr'].vnfd
+
+ try:
+ cparam = vnfd.config_parameter
+ except AttributeError as e:
+ self._log.debug("VNFR {} does not have VNF config parameter".
+ format(vnfr.name))
+ continue
+
+ srcs = []
+ try:
+ srcs = cparam.config_parameter_source
+ except AttributeError as e:
+ self._log.debug("VNFR {} has no source defined".
+ format(vnfr.name))
+
+ # Get the cm state dict for this vnfr
+ cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
+
+ cm_srcs = []
+ for src in srcs:
+ self._log.debug("VNFR {}: source {}".
+ format(vnfr['name'], src.as_dict()))
+
+ param_refs = []
+ for p in src.parameter:
+ param_refs.append({
+ 'config_primitive_ref': p.config_primitive_name_ref,
+ 'parameter_ref': p.config_primitive_parameter_ref
+ })
+
+ try:
+ val = src.value
+ self._log.debug("Got value {}".format(val))
+ if val:
+ cm_srcs.append({'name': src.name,
+ 'value': str(val),
+ 'parameter': param_refs})
+ continue
+ except AttributeError as e:
+ pass
+
+ try:
+ xpath = src.descriptor
+ # resolve xpath
+ if xpath:
+ val = yield from self.resolve_xpath(xpath, src.name, vnfd)
+ self._log.debug("Got xpath value: {}".format(val))
+ cm_srcs.append({'name': src.name,
+ 'value': str(val),
+ 'parameter': param_refs})
+ continue
+ except AttributeError as e:
+ pass
+
+ try:
+ attribute = src.attribute
+ # resolve attribute
+ if attribute:
+ val = yield from self.resolve_attribute(attribute,
+ src.name,
+ vnfd, vnfr)
+ self._log.debug("Got attribute value: {}".format(val))
+ cm_srcs.append({'name': src.name,
+ 'value': str(val),
+ 'parameter': param_refs})
+ continue
+ except AttributeError as e:
+ pass
+
+ try:
+ prim = src.primitive_ref
+ if prim:
+ raise NotImplementedError("{}: VNF config parameter {}"
+ "source support for config"
+ "primitive not yet supported".
+ format(vnfr.name, prim))
+ except AttributeError as e:
+ pass
+
+ self._log.debug("VNF config parameter sources: {}".format(cm_srcs))
+ cm_state['config_parameter']['config_parameter_source'] = cm_srcs
+
+ try:
+ reqs = cparam.config_parameter_request
+ except AttributeError as e:
+ self._log.debug("VNFR {} has no requests defined".
+ format(vnfr.name))
+ continue
+
+ cm_reqs = []
+ for req in reqs:
+ self._log.debug("VNFR{}: request {}".
+ format(vnfr['name'], req.as_dict()))
+ param_refs = []
+ for p in req.parameter:
+ param_refs.append({
+ 'config_primitive_ref': p.config_primitive_name_ref,
+ 'parameter_ref': p.config_primitive_parameter_ref
+ })
+ cm_reqs.append({'name': req.name,
+ 'parameter': param_refs})
+
+ self._log.debug("VNF requests: {}".format(cm_reqs))
+ cm_state['config_parameter']['config_parameter_request'] = cm_reqs
+
+ # Publish all config parameter for the VNFRs
+ # yield from nsr_obj.publish_cm_state()
+
+ cparam_map = []
try:
- # Fetch NSR
- nsr = yield from cmdts_obj.get_nsr(id)
- self._log.debug("Full NSR : %s", nsr)
- if nsr['operational_status'] != "running":
- self._log.info("NSR(%s) is not ready yet!", nsr['nsd_name_ref'])
- return False
- self._nsr = nsr
-
- # Create Agent NSR class
- nsr_config = yield from cmdts_obj.get_nsr_config(id)
- self._log.debug("NSR {} config: {}".format(id, nsr_config))
- nsr_obj.agent_nsr = riftcm_config_plugin.RiftCMnsr(nsr, nsr_config)
+ cparam_map = nsd.config_parameter_map
+ except AttributeError as e:
+ self._log.warning("No config parameter map specified for nsr: {}".
+ format(nsr_obj.nsr_name))
+
+ for cp in cparam_map:
+ src_vnfr = nsr_obj.agent_nsr.get_member_vnfr(
+ cp.config_parameter_source.member_vnf_index_ref)
+ cm_state = nsr_obj.find_vnfr_cm_state(src_vnfr.id)
+ if cm_state is None:
+ raise ValueError("Config parameter sources are not defined "
+ "for VNF member {} ({})".
+ format(cp.config_parameter_source.member_vnf_index_ref,
+ src_vnfr.name))
+ srcs = cm_state['config_parameter']['config_parameter_source']
+
+ src_attr = cp.config_parameter_source.config_parameter_source_ref
+ val = None
+ for src in srcs:
+ if src['name'] == src_attr:
+ val = src['value']
+ break
+
+ req_vnfr = nsr_obj.agent_nsr.get_member_vnfr(
+ cp.config_parameter_request.member_vnf_index_ref)
+ req_attr = cp.config_parameter_request.config_parameter_request_ref
+ cm_state = nsr_obj.find_vnfr_cm_state(req_vnfr.id)
+ try:
+ cm_reqs = cm_state['config_parameter']['config_parameter_request']
+ except KeyError as e:
+ raise ValueError("VNFR index {} ({}) has no requests defined".
+ format(cp.config_parameter_reequest.member_vnf_index_ref,
+ req_vnfr['name']))
+
+ for i, item in enumerate(cm_reqs):
+ if item['name'] == req_attr:
+ item['value'] = str(val)
+ cm_reqs[i] = item
+ self._log.debug("Request in VNFR {}: {}".
+ format(req_vnfr.name, item))
+ break
+
+ yield from self.update_config_primitives(nsr_obj)
+ # TODO: Confd crashing with the config-parameter publish
+ # So removing config-parameter and publishing cm-state
+ for vnfr in nsr_obj.vnfrs:
+ # Get the cm state dict for this vnfr
+ cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
+ del cm_state['config_parameter']['config_parameter_source']
+ del cm_state['config_parameter']['config_parameter_request']
+
+ # Publish resolved dependencies for the VNFRs
+ yield from nsr_obj.publish_cm_state()
+
+ @asyncio.coroutine
+ def config_NSR(self, id, event):
+
+ cmdts_obj = self.cmdts_obj
+ if event == 'running':
+ self._log.info("Configure NSR running, id = %s", id)
try:
- yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.RECEIVED)
+ nsr_obj = None
+ try:
+ if id not in self._nsr_dict:
+ nsr_obj = ConfigManagerNSR(self._log, self._loop, self, self._project, id)
+ self._nsr_dict[id] = nsr_obj
+ else:
+ self._log.info("NSR(%s) is already initialized!", id)
+ nsr_obj = self._nsr_dict[id]
+
+ except Exception as e:
+ self._log.error("Failed creating NSR object for (%s) as (%s)", id, str(e))
+ raise e
+
+ # Try to configure this NSR only if not already processed
+ if nsr_obj.cm_nsr['state'] != nsr_obj.state_to_string(conmanY.RecordState.INIT):
+ self._log.debug("NSR(%s) is already processed, state=%s",
+ nsr_obj.nsr_name, nsr_obj.cm_nsr['state'])
+ # Publish again in case NSM restarted
+ yield from nsr_obj.publish_cm_state()
+ return True
+
+ # Fetch NSR
+ nsr = yield from cmdts_obj.get_nsr(id)
+ self._log.debug("Full NSR : %s", nsr)
+ if nsr['operational_status'] != "running":
+ self._log.info("NSR(%s) is not ready yet!", nsr['nsd_name_ref'])
+ return False
+ self._nsr = nsr
+
+ # Create Agent NSR class
+ nsr_config = yield from cmdts_obj.get_nsr_config(id)
+ self._log.debug("NSR {} config: {}".format(id, nsr_config))
+
+ if nsr_config is None:
+ # The NST Terminate has been initiated before the configuration. Hence
+ # not proceeding with config.
+ self._log.warning("NSR - %s is deleted before Configuration. Not proceeding with configuration.", id)
+ return True
+
+ nsr_obj.agent_nsr = riftcm_config_plugin.RiftCMnsr(nsr, nsr_config,
+ self._project)
+
+ unique_cfg_vnfr_list = list()
+ unique_agent_vnfr_list = list()
+ try:
+ yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.RECEIVED)
- # Parse NSR
- if nsr is not None:
nsr_obj.set_nsr_name(nsr['name_ref'])
- nsr_dir = os.path.join(self._parent.cfg_dir, nsr_obj.nsr_name)
- self._log.info("Checking NS config directory: %s", nsr_dir)
- if not os.path.isdir(nsr_dir):
- os.makedirs(nsr_dir)
- # self._log.critical("NS %s is not to be configured by Service Orchestrator!", nsr_obj.nsr_name)
- # yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.READY_NO_CFG)
- # return
-
- nsr_obj.set_config_dir(self)
-
for const_vnfr in nsr['constituent_vnfr_ref']:
self._log.debug("Fetching VNFR (%s)", const_vnfr['vnfr_id'])
vnfr_msg = yield from cmdts_obj.get_vnfr(const_vnfr['vnfr_id'])
if vnfr_msg:
vnfr = vnfr_msg.as_dict()
- self._log.info("create VNF:{}/{}".format(nsr_obj.nsr_name, vnfr['short_name']))
+ self._log.info("create VNF:{}/{} operational status {}".format(nsr_obj.nsr_name, vnfr['name'], vnfr['operational_status']))
agent_vnfr = yield from nsr_obj.add_vnfr(vnfr, vnfr_msg)
+ method = self.get_config_method(vnfr['vnf_configuration'])
+ if method is not None:
+ unique_cfg_vnfr_list.append(vnfr)
+ unique_agent_vnfr_list.append(agent_vnfr)
- # Preserve order, self.process_nsd_vnf_configuration()
- # sets up the config agent based on the method
+ # Process VNF Cfg
+ # Set up the config agent based on the method
yield from self.process_nsd_vnf_configuration(nsr_obj, vnfr)
- yield from self._config_agent_mgr.invoke_config_agent_plugins(
- 'notify_create_vnfr',
- nsr_obj.agent_nsr,
- agent_vnfr)
-
- #####################TBD###########################
- # self._log.debug("VNF active. Apply initial config for vnfr {}".format(vnfr.name))
- # yield from self._config_agent_mgr.invoke_config_agent_plugins('apply_initial_config',
- # vnfr.id, vnfr)
- # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_terminate_vnf', self.id, vnfr)
+ else:
+ self._log.warning("NSR %s, VNFR not found yet (%s)", nsr_obj.nsr_name, const_vnfr['vnfr_id'])
- except Exception as e:
- self._log.error("Failed processing NSR (%s) as (%s)", nsr_obj.nsr_name, str(e))
- self._log.exception(e)
- yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
- raise
-
- try:
- # Generate config_config_attributes.yaml (For debug reference)
- with open(nsr_obj.config_attributes_file, "w") as yf:
- my_yaml_dump(nsr_obj.nsr_cfg_config_attributes_dict, yf)
- except Exception as e:
- self._log.error("NS:(%s) failed to write config attributes file as (%s)", nsr_obj.nsr_name, str(e))
+ # Process VNF config parameter
+ yield from self.process_vnf_config_parameter(nsr_obj)
- try:
- # Generate nsr_xlate_dict.yaml (For debug reference)
- with open(nsr_obj.xlate_dict_file, "w") as yf:
- yf.write(yaml.dump(nsr_obj._cp_dict, default_flow_style=False))
- except Exception as e:
- self._log.error("NS:(%s) failed to write nsr xlate tags file as (%s)", nsr_obj.nsr_name, str(e))
+ # Invoke the config agent plugin
+ for agent_vnfr in unique_agent_vnfr_list:
+ yield from self._config_agent_mgr.invoke_config_agent_plugins(
+ 'notify_create_vnfr',
+ nsr_obj.agent_nsr,
+ agent_vnfr)
- self._log.debug("Starting to configure each VNF")
+ except Exception as e:
+ self._log.error("Failed processing NSR (%s) as (%s)", nsr_obj.nsr_name, str(e))
+ self._log.exception(e)
+ yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
+ raise e
- # Check if this NS has input parametrs
- self._log.info("Checking NS configuration order: %s", nsr_obj.config_attributes_file)
+ self._log.debug("Starting to configure each VNF")
- if os.path.exists(nsr_obj.config_attributes_file):
- # Apply configuration is specified order
try:
- # Go in loop to configure by specified order
- self._log.info("Using Dynamic configuration input parametrs for NS: %s", nsr_obj.nsr_name)
-
- # cfg_delay = nsr_obj.nsr_cfg_config_attributes_dict['configuration_delay']
- # if cfg_delay:
- # self._log.info("Applying configuration delay for NS (%s) ; %d seconds",
- # nsr_obj.nsr_name, cfg_delay)
- # yield from asyncio.sleep(cfg_delay, loop=self._loop)
-
- for config_attributes_dict in nsr_obj.nsr_cfg_config_attributes_dict.values():
- # Iterate through each priority level
- for vnf_config_attributes_dict in config_attributes_dict:
- # Iterate through each vnfr at this priority level
-
- # Make up vnf_unique_name with vnfd name and member index
- #vnfr_name = "{}.{}".format(nsr_obj.nsr_name, vnf_config_attributes_dict['name'])
- vnf_unique_name = get_vnf_unique_name(
- nsr_obj.nsr_name,
- vnf_config_attributes_dict['name'],
- str(vnf_config_attributes_dict['member_vnf_index']),
- )
- self._log.info("NS (%s) : VNF (%s) - Processing configuration attributes",
- nsr_obj.nsr_name, vnf_unique_name)
+ for cfg_vnfr in unique_cfg_vnfr_list:
+ # Apply configuration
+ vnf_unique_name = get_vnf_unique_name(
+ nsr_obj.nsr_name,
+ cfg_vnfr['name'],
+ str(cfg_vnfr['member_vnf_index_ref']),
+ )
- # Find vnfr for this vnf_unique_name
- if vnf_unique_name not in nsr_obj._vnfr_dict:
- self._log.error("NS (%s) - Can not find VNF to be configured: %s", nsr_obj.nsr_name, vnf_unique_name)
- else:
- # Save this unique VNF's config input parameters
- nsr_obj.vnf_config_attributes_dict[vnf_unique_name] = vnf_config_attributes_dict
- nsr_obj.ConfigVNF(nsr_obj._vnfr_dict[vnf_unique_name])
+ # Find vnfr for this vnf_unique_name
+ if vnf_unique_name not in nsr_obj._vnfr_dict:
+ self._log.error("NS (%s) - Can not find VNF to be configured: %s", nsr_obj.nsr_name, vnf_unique_name)
+ else:
+ # Save this unique VNF's config input parameters
+ nsr_obj.ConfigVNF(nsr_obj._vnfr_dict[vnf_unique_name])
# Now add the entire NS to the pending config list.
- self._log.info("Scheduling NSR:{} configuration".format(nsr_obj.nsr_name))
- self._parent.add_to_pending(nsr_obj)
+ self._log.info("Scheduling NSR:{} configuration ".format(nsr_obj.nsr_name))
+ self._parent.add_to_pending(nsr_obj, unique_cfg_vnfr_list)
self._parent.add_nsr_obj(nsr_obj)
except Exception as e:
self._log.error("Failed processing input parameters for NS (%s) as %s", nsr_obj.nsr_name, str(e))
+ self._log.exception(e)
raise
- else:
- self._log.error("No configuration input parameters for NSR (%s)", nsr_obj.nsr_name)
- except Exception as e:
- self._log.error("Failed to configure NS (%s) as (%s)", nsr_obj.nsr_name, str(e))
- yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
- raise
+ except Exception as e:
+ self._log.exception(e)
+ if nsr_obj:
+ self._log.error("Failed to configure NS (%s) as (%s)", nsr_obj.nsr_name, str(e))
+ yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
+ raise e
+
+ elif event == 'terminate':
+ self._log.info("Configure NSR terminate, id = %s", id)
+ nsr_obj = self._parent.get_nsr_obj(id)
+ if nsr_obj is None:
+ # Can be none if the terminate is called again due to DTS query
+ return True
+
+ try:
+ yield from self.process_ns_terminate_config(nsr_obj, self._project.name)
+ except Exception as e:
+ self._log.warn("Terminate config failed for NSR {}: {}".
+ format(id, e))
+ self._log.exception(e)
+
+ try:
+ yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.TERMINATE)
+ yield from self.terminate_NSR(id)
+ except Exception as e:
+ self._log.error("Terminate failed for NSR {}: {}".
+ format(id, e))
+ self._log.exception(e)
return True
@asyncio.coroutine
def terminate_NSR(self, id):
- nsr_dict = self._nsr_dict
- if id not in nsr_dict:
+ if id not in self._nsr_dict:
self._log.error("NSR(%s) does not exist!", id)
return
else:
+ nsr_obj = self._nsr_dict[id]
+
# Remove this NSR if we have it on pending task list
for task in self.pending_tasks:
if task['nsrid'] == id:
self.del_from_pending_tasks(task)
- # Remove this object from global list
- nsr_obj = nsr_dict.pop(id, None)
-
- # Remove this NS cm-state from global status list
- self.cm_state['cm_nsr'].remove(nsr_obj.cm_nsr)
-
- # Also remove any scheduled configuration event
+ # Remove any scheduled configuration event
for nsr_obj_p in self._parent.pending_cfg:
if nsr_obj_p == nsr_obj:
assert id == nsr_obj_p._nsr_id
- #self._parent.pending_cfg.remove(nsr_obj_p)
- # Mark this as being deleted so we do not try to configure it if we are in cfg_delay (will wake up and continue to process otherwise)
+ # Mark this as being deleted so we do not try to reconfigure it
+ # if we are in cfg_delay (will wake up and continue to process otherwise)
nsr_obj_p.being_deleted = True
self._log.info("Removed scheduled configuration for NSR(%s)", nsr_obj.nsr_name)
- self._parent.remove_nsr_obj(id)
-
# Call Config Agent to clean up for each VNF
for agent_vnfr in nsr_obj.agent_nsr.vnfrs:
yield from self._config_agent_mgr.invoke_config_agent_plugins(
nsr_obj.agent_nsr,
agent_vnfr)
- # publish delete cm-state (cm-nsr)
- yield from nsr_obj.delete_cm_nsr()
+ self._log.info("NSR(%s/%s) is terminated", nsr_obj.nsr_name, id)
+
+ @asyncio.coroutine
+ def delete_NSR(self, id):
+ if id not in self._nsr_dict:
+ self._log.debug("NSR(%s) does not exist!", id)
+ return
+ else:
+ # Remove this NSR if we have it on pending task list
+ for task in self.pending_tasks:
+ if task['nsrid'] == id:
+ self.del_from_pending_tasks(task)
+
+ # Remove this object from global list
+ nsr_obj = self._nsr_dict.pop(id, None)
+
+ # Remove this NS cm-state from global status list
+ self.cm_state['cm_nsr'].remove(nsr_obj.cm_nsr)
+
+ self._parent.remove_nsr_obj(id)
- #####################TBD###########################
- # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_terminate_ns', self.id)
+ # publish delete cm-state (cm-nsr)
+ yield from nsr_obj.delete_cm_nsr()
+
+ # Deleting any config jobs for NSR.
+ job_manager = self.riftcm_rpc_handler.job_manager.handler
+ job_manager._terminate_nsr(id)
+
+ #####################TBD###########################
+ # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_terminate_ns', self.id)
- self._log.info("NSR(%s/%s) is deleted", nsr_obj.nsr_name, id)
+ self._log.info("NSR(%s/%s) is deleted", nsr_obj.nsr_name, id)
@asyncio.coroutine
def process_initial_config(self, nsr_obj, conf, script, vnfr_name=None):
v['name'] = vnfr['name']
v['mgmt_ip_address'] = vnfr['vnf_cfg']['mgmt_ip_address']
v['mgmt_port'] = vnfr['vnf_cfg']['port']
+ v['datacenter'] = vnfr['datacenter']
if 'dashboard_url' in vnfr:
v['dashboard_url'] = vnfr['dashboard_url']
if 'connection_point' in vnfr:
v['connection_point'] = []
for cp in vnfr['connection_point']:
- v['connection_point'].append(
- {
- 'name': cp['name'],
- 'ip_address': cp['ip_address'],
- }
- )
+ cp_info = dict(name=cp['name'],
+ ip_address=cp['ip_address'],
+ mac_address=cp.get('mac_address', None),
+ connection_point_id=cp.get('connection_point_id',None))
+
+ if 'virtual_cps' in cp:
+ cp_info['virtual_cps'] = [ {k:v for k,v in vcp.items()
+ if k in ['ip_address', 'mac_address']}
+ for vcp in cp['virtual_cps'] ]
+ v['connection_point'].append(cp_info)
- v['vdur'] = []
- vdu_data = []
- for vdu in vnfr['vdur']:
- d = {}
- for k in ['name','management_ip', 'vm_management_ip', 'id']:
- if k in vdu:
- d[k] = vdu[k]
- vdu_data.append(d)
- v['vdur'] = vdu_data
+
+ if 'vdur' in vnfr:
+ vdu_data = [(vdu.get('name',None), vdu.get('management_ip',None), vdu.get('vm_management_ip',None), vdu.get('id',None))
+ for vdu in vnfr['vdur']]
+
+ v['vdur'] = [ dict(zip(['name', 'management_ip', 'vm_management_ip', 'id', 'vdu_id_ref'] , data)) for data in vdu_data ]
inp['vnfr'][vnfr['member_vnf_index_ref']] = v
try:
os.remove(inp_file)
except Exception as e:
- self._log.debug("Error removing input file {}: {}".
+ self._log.error("Error removing input file {}: {}".
format(inp_file, e))
- def get_script_file(self, script_name, d_name, d_id, d_type):
- # Get the full path to the script
- script = ''
- # If script name starts with /, assume it is full path
- if script_name[0] == '/':
- # The script has full path, use as is
- script = script_name
- else:
- script = os.path.join(os.environ['RIFT_ARTIFACTS'],
- 'launchpad/packages',
- d_type,
- d_id,
- d_name,
- 'scripts',
- script_name)
- self._log.debug("Checking for script at %s", script)
- if not os.path.exists(script):
- self._log.warning("Did not find script %s", script)
- script = os.path.join(os.environ['RIFT_INSTALL'],
- 'usr/bin',
- script_name)
-
- # Seen cases in jenkins, where the script execution fails
- # with permission denied. Setting the permission on script
- # to make sure it has execute permission
- perm = os.stat(script).st_mode
- if not (perm & stat.S_IXUSR):
- self._log.warning("NSR/VNFR {} initial config script {} " \
+ def get_script_file(self, script_name, d_name, d_id, d_type, project=None):
+ # Get the full path to the script
+ script = os.path.join(os.getenv('RIFT_VAR_ROOT'),
+ 'launchpad/packages',
+ d_type,
+ project if project else "",
+ d_id,
+ 'scripts',
+ script_name)
+
+ self._log.debug("Checking for script at %s", script)
+ if not os.path.exists(script):
+ err_msg = ("{} {}: Did not find script {} for config".
+ format(d_type, d_name, script))
+ self._log.error(err_msg)
+ raise ScriptNotFoundError(err_msg)
+
+ # Seen cases in jenkins, where the script execution fails
+ # with permission denied. Setting the permission on script
+ # to make sure it has execute permission
+ perm = os.stat(script).st_mode
+ if not (perm & stat.S_IXUSR):
+ self._log.warning("NSR/VNFR {} script {} " \
"without execute permission: {}".
format(d_name, script, perm))
- os.chmod(script, perm | stat.S_IXUSR)
- return script
+ os.chmod(script, perm | stat.S_IXUSR)
+ return script
@asyncio.coroutine
- def process_ns_initial_config(self, nsr_obj):
- '''Apply the initial-config-primitives specified in NSD'''
-
+ def process_ns_initial_config(self, nsr_obj, project=None):
+ '''Apply the initial-service-primitives specified in NSD'''
nsr = yield from self.cmdts_obj.get_nsr(nsr_obj.nsr_id)
- if 'initial_config_primitive' not in nsr:
+ self._log.debug("NS initial config: {}".format(nsr))
+ if 'initial_service_primitive' not in nsr:
return
-
if nsr is not None:
nsd = yield from self.cmdts_obj.get_nsd(nsr_obj.nsr_id)
- for conf in nsr['initial_config_primitive']:
+ for conf in nsr['initial_service_primitive']:
self._log.debug("NSR {} initial config: {}".
format(nsr_obj.nsr_name, conf))
script = self.get_script_file(conf['user_defined_script'],
nsd.name,
nsd.id,
- 'nsd')
+ 'nsd',
+ project
+ )
yield from self.process_initial_config(nsr_obj, conf, script)
@asyncio.coroutine
- def process_vnf_initial_config(self, nsr_obj, vnfr):
+ def process_vnf_initial_config(self, nsr_obj, vnfr, project=None):
'''Apply the initial-config-primitives specified in VNFD'''
-
vnfr_name = vnfr.name
vnfd = vnfr.vnfd
vnf_cfg = vnfd.vnf_configuration
for conf in vnf_cfg.initial_config_primitive:
- self._log.debug("VNFR {} initial config: {}".
- format(vnfr_name, conf))
+ self._log.debug("VNFR {} initial config: {} for vnfd id {}".
+ format(vnfr_name, conf, vnfd.id))
if not conf.user_defined_script:
- self._log.debug("VNFR {} did not fine user defined script: {}".
+ self._log.debug("VNFR {} did not find user defined script: {}".
format(vnfr_name, conf))
continue
script = self.get_script_file(conf.user_defined_script,
vnfd.name,
vnfd.id,
- 'vnfd')
+ 'vnfd',
+ project
+ )
yield from self.process_initial_config(nsr_obj,
conf.as_dict(),
script,
vnfr_name=vnfr_name)
+ @asyncio.coroutine
+ def process_ns_terminate_config(self, nsr_obj, project=None):
+ '''Apply the terminate-service-primitives specified in NSD'''
+
+ nsr = self._nsr
+ if 'terminate_service_primitive' not in nsr:
+ return
+
+ if nsr is not None:
+ nsd = nsr_obj.agent_nsr.nsd
+ for conf in nsr['terminate_service_primitive']:
+ self._log.debug("NSR {} terminate service: {}".
+ format(nsr_obj.nsr_name, conf))
+ script = self.get_script_file(conf['user_defined_script'],
+ nsd.name,
+ nsd.id,
+ 'nsd',
+ project)
+
+ try:
+ yield from self.process_initial_config(nsr_obj, conf, script)
+
+ except Exception as e:
+ # Ignore any failures on terminate
+ self._log.warning("NSR {} terminate config script {} failed: {}".
+ format(nsr_obj.nsr_name, script, e))
+ break
+
class ConfigManagerNSR(object):
- def __init__(self, log, loop, parent, id):
+ def __init__(self, log, loop, parent, project, id):
self._log = log
self._loop = loop
self._rwcal = None
self._cp_dict = {}
self._nsr_id = id
self._parent = parent
+ self._project = project
self._log.info("Instantiated NSR entry for id=%s", id)
self.nsr_cfg_config_attributes_dict = {}
self.vnf_config_attributes_dict = {}
@property
def nsr_opdata_xpath(self):
''' Returns full xpath for this NSR cm-state opdata '''
- return(
- "D,/rw-conman:cm-state" +
- "/rw-conman:cm-nsr[rw-conman:id='{}']"
- ).format(self._nsr_id)
+ return self._project.add_project((
+ "D,/rw-conman:cm-state/rw-conman:cm-nsr[rw-conman:id={}]"
+ ).format(quoted_key(self._nsr_id)))
@property
def vnfrs(self):
def publish_cm_state(self):
''' This function publishes cm_state for this NSR '''
- cm_state = conmanY.CmOpdata()
+ cm_state = conmanY.YangData_RwProject_Project_CmState()
cm_state_nsr = cm_state.cm_nsr.add()
cm_state_nsr.from_dict(self.cm_nsr)
#with self._dts.transaction() as xact:
self.nsr_name = name
self.cm_nsr['name'] = name
- def set_config_dir(self, caller):
- self.this_nsr_dir = os.path.join(
- caller._parent.cfg_dir, self.nsr_name, caller._nsr['name_ref'])
- if not os.path.exists(self.this_nsr_dir):
- os.makedirs(self.this_nsr_dir)
- self._log.debug("NSR:(%s), Created configuration directory(%s)",
- caller._nsr['name_ref'], self.this_nsr_dir)
- self.config_attributes_file = os.path.join(self.this_nsr_dir, "configuration_config_attributes.yml")
- self.xlate_dict_file = os.path.join(self.this_nsr_dir, "nsr_xlate_dict.yml")
-
- def xlate_conf(self, vnfr, vnf_cfg):
-
- # If configuration type is not already set, try to read from attributes
- if vnf_cfg['interface_type'] is None:
- # Prepare unique name for this VNF
- vnf_unique_name = get_vnf_unique_name(
- vnf_cfg['nsr_name'],
- vnfr['short_name'],
- vnfr['member_vnf_index_ref'],
- )
-
- # Find this particular (unique) VNF's config attributes
- if (vnf_unique_name in self.vnf_config_attributes_dict):
- vnf_cfg_config_attributes_dict = self.vnf_config_attributes_dict[vnf_unique_name]
- vnf_cfg['interface_type'] = vnf_cfg_config_attributes_dict['configuration_type']
- if 'configuration_options' in vnf_cfg_config_attributes_dict:
- cfg_opts = vnf_cfg_config_attributes_dict['configuration_options']
- for key, value in cfg_opts.items():
- vnf_cfg[key] = value
-
- cfg_path_prefix = '{}/{}/{}_{}'.format(
- self._parent._parent.cfg_dir,
- vnf_cfg['nsr_name'],
- vnfr['short_name'],
- vnfr['member_vnf_index_ref'],
- )
-
- vnf_cfg['cfg_template'] = '{}_{}_template.cfg'.format(cfg_path_prefix, vnf_cfg['interface_type'])
- vnf_cfg['cfg_file'] = '{}.cfg'.format(cfg_path_prefix)
- vnf_cfg['xlate_script'] = self._parent._parent.cfg_dir + '/xlate_cfg.py'
-
- self._log.debug("VNF endpoint so far: %s", vnf_cfg)
-
- self._log.info("Checking cfg_template %s", vnf_cfg['cfg_template'])
- if os.path.exists(vnf_cfg['cfg_template']):
- return True
- return False
-
def ConfigVNF(self, vnfr):
vnf_cfg = vnfr['vnf_cfg']
if (vnf_cm_state['state'] == self.state_to_string(conmanY.RecordState.READY_NO_CFG)
or
vnf_cm_state['state'] == self.state_to_string(conmanY.RecordState.READY)):
- self._log.warning("NS/VNF (%s/%s) is already configured! Skipped.", self.nsr_name, vnfr['short_name'])
+ self._log.warning("NS/VNF (%s/%s) is already configured! Skipped.", self.nsr_name, vnfr['name'])
return
#UPdate VNF state
self._cp_dict['rw_mgmt_ip'] = vnf_cfg['mgmt_ip_address']
self._cp_dict['rw_username'] = vnf_cfg['username']
self._cp_dict['rw_password'] = vnf_cfg['password']
- ############################################################
- # TBD - Need to lookup above 3 for a given VNF, not global #
- # Once we do that no need to dump below file again before #
- # each VNF configuration translation. #
- # This will require all existing config templates to be #
- # changed for above three tags to include member index #
- ############################################################
- try:
- nsr_obj = vnf_cfg['nsr_obj']
- # Generate config_config_attributes.yaml (For debug reference)
- with open(nsr_obj.xlate_dict_file, "w") as yf:
- yf.write(yaml.dump(nsr_obj._cp_dict, default_flow_style=False))
- except Exception as e:
- self._log.error("NS:(%s) failed to write nsr xlate tags file as (%s)", nsr_obj.nsr_name, str(e))
-
- if 'cfg_template' in vnf_cfg:
- script_cmd = 'python3 {} -i {} -o {} -x "{}"'.format(vnf_cfg['xlate_script'], vnf_cfg['cfg_template'], vnf_cfg['cfg_file'], self.xlate_dict_file)
- self._log.debug("xlate script command (%s)", script_cmd)
- #xlate_msg = subprocess.check_output(script_cmd).decode('utf-8')
- xlate_msg = subprocess.check_output(script_cmd, shell=True).decode('utf-8')
- self._log.info("xlate script output (%s)", xlate_msg)
except Exception as e:
vnf_cm_state['state'] = self.state_to_string(conmanY.RecordState.CFG_PROCESS_FAILED)
- self._log.error("Failed to execute translation script for VNF: %s with (%s)", log_this_vnf(vnf_cfg), str(e))
+ self._log.error("Failed to set tags for VNF: %s with (%s)", log_this_vnf(vnf_cfg), str(e))
return
self._log.info("Applying config to VNF: %s = %s!", log_this_vnf(vnf_cfg), vnf_cfg)
try:
- #self.vnf_cfg_list.append(vnf_cfg)
self._log.debug("Scheduled configuration!")
vnf_cm_state['state'] = self.state_to_string(conmanY.RecordState.CFG_SCHED)
except Exception as e:
{
'cm_vnfr': [
{
- 'cfg_location': 'location1',
- 'cfg_type': 'script',
'connection_point': [
{'ip_address': '1.1.1.1', 'name': 'vnf1cp1'},
{'ip_address': '1.1.1.2', 'name': 'vnf1cp2'}
'state': 'init'
},
{
- 'cfg_location': 'location2',
- 'cfg_type': 'netconf',
'connection_point': [{'ip_address': '2.1.1.1', 'name': 'vnf2cp1'},
{'ip_address': '2.1.1.2', 'name': 'vnf2cp2'}],
'id': 'vnfrid2',
'states': 'Initialized, '
})
- def populate_vm_state_from_vnf_cfg(self):
+ def populate_cm_state_from_vnf_cfg(self):
# Fill in each VNFR from this nsr object
vnfr_list = self._vnfr_list
for vnfr in vnfr_list:
# Fill in VNF configuration details
vnf_cm_state['cfg_type'] = vnf_cfg['config_method']
- vnf_cm_state['cfg_location'] = vnf_cfg['cfg_file']
# Fill in each connection-point for this VNF
if "connection_point" in vnfr:
cp_list = vnfr['connection_point']
for cp_item_dict in cp_list:
- vnf_cm_state['connection_point'].append(
- {
- 'name' : cp_item_dict['name'],
- 'ip_address' : cp_item_dict['ip_address'],
- }
- )
+ try:
+ vnf_cm_state['connection_point'].append(
+ {
+ 'name' : cp_item_dict['name'],
+ 'ip_address' : cp_item_dict['ip_address'],
+ 'connection_point_id' : cp_item_dict['connection_point_id'],
+ }
+ )
+ except Exception:
+ # Added to make mano_ut work
+ pass
def state_to_string(self, state):
state_dict = {
conmanY.RecordState.CFG_PROCESS : "cfg_process",
conmanY.RecordState.CFG_PROCESS_FAILED : "cfg_process_failed",
conmanY.RecordState.CFG_SCHED : "cfg_sched",
- conmanY.RecordState.CFG_DELAY : "cfg_delay",
conmanY.RecordState.CONNECTING : "connecting",
conmanY.RecordState.FAILED_CONNECTION : "failed_connection",
- conmanY.RecordState.NETCONF_CONNECTED : "netconf_connected",
- conmanY.RecordState.NETCONF_SSH_CONNECTED : "netconf_ssh_connected",
- conmanY.RecordState.RESTCONF_CONNECTED : "restconf_connected",
conmanY.RecordState.CFG_SEND : "cfg_send",
conmanY.RecordState.CFG_FAILED : "cfg_failed",
conmanY.RecordState.READY_NO_CFG : "ready_no_cfg",
conmanY.RecordState.READY : "ready",
+ conmanY.RecordState.TERMINATE : "terminate",
}
return state_dict[state]
# Not found, Create and Initialize this VNF cm-state
vnf_cm_state = {
'id' : vnfr['id'],
- 'name' : vnfr['short_name'],
+ 'name' : vnfr['name'],
'state' : self.state_to_string(conmanY.RecordState.RECEIVED),
'mgmt_interface' :
{
'ip_address' : vnf_cfg['mgmt_ip_address'],
'port' : vnf_cfg['port'],
},
- 'cfg_type' : vnf_cfg['config_method'],
- 'cfg_location' : vnf_cfg['cfg_file'],
'connection_point' : [],
+ 'config_parameter' :
+ {
+ 'config_parameter_source' : [],
+ 'config_parameter_request' : [],
+ },
}
self.cm_nsr['cm_vnfr'].append(vnf_cm_state)
vnf_cm_state = self.find_vnfr_cm_state(vnfr['id'])
if vnf_cm_state is None:
self._log.error("No opdata found for NS/VNF:%s/%s!",
- self.nsr_name, vnfr['short_name'])
+ self.nsr_name, vnfr['name'])
return
if vnf_cm_state['state'] != self.state_to_string(state):
yield from self.publish_cm_state()
self._log.info("VNF ({}/{}/{}) state change: {} -> {}"
.format(self.nsr_name,
- vnfr['short_name'],
+ vnfr['name'],
vnfr['member_vnf_index_ref'],
old_state,
vnf_cm_state['state']))
self._cp_dict[vnfr['member_vnf_index_ref']].update(subnet)
self._cp_dict.update(subnet)
self._log.debug("VNF:(%s) Updated assigned subnet = %s",
- vnfr['short_name'], subnet)
+ vnfr['name'], subnet)
except Exception as e:
self._log.error("VNF:(%s) VLR Error = %s",
- vnfr['short_name'], e)
-
+ vnfr['name'], e)
+
if vnfr['id'] not in self._vnfr_dict:
- self._log.info("NSR(%s) : Adding VNF Record for name=%s, id=%s", self._nsr_id, vnfr['short_name'], vnfr['id'])
+ self._log.info("NSR(%s) : Adding VNF Record for name=%s, id=%s", self._nsr_id, vnfr['name'], vnfr['id'])
# Add this vnfr to the list for show, or single traversal
self._vnfr_list.append(vnfr)
else:
- self._log.warning("NSR(%s) : VNF Record for name=%s, id=%s already exists, overwriting", self._nsr_id, vnfr['short_name'], vnfr['id'])
+ self._log.warning("NSR(%s) : VNF Record for name=%s, id=%s already exists, overwriting",
+ self._nsr_id, vnfr['name'], vnfr['id'])
# Make vnfr available by id as well as by name
- unique_name = get_vnf_unique_name(self.nsr_name, vnfr['short_name'], vnfr['member_vnf_index_ref'])
+ unique_name = get_vnf_unique_name(self.nsr_name, vnfr['name'], vnfr['member_vnf_index_ref'])
self._vnfr_dict[unique_name] = vnfr
self._vnfr_dict[vnfr['id']] = vnfr
'agent_vnfr' : self.agent_nsr.add_vnfr(vnfr, vnfr_msg),
'nsr_name' : self.nsr_name,
'nsr_id' : self._nsr_id,
- 'vnfr_name' : vnfr['short_name'],
+ 'vnfr_name' : vnfr['name'],
'member_vnf_index' : vnfr['member_vnf_index_ref'],
'port' : 0,
- 'username' : 'admin',
- 'password' : 'admin',
+ 'username' : '@rift',
+ 'password' : 'rift',
'config_method' : 'None',
'protocol' : 'None',
'mgmt_ip_address' : '0.0.0.0',
'script_type' : 'bash',
}
+ ##########################
# Update the mgmt ip address
# In case the config method is none, this is not
# updated later
except Exception as e:
self._log.warn(
"VNFR {}({}), unable to retrieve mgmt ip address: {}".
- format(vnfr['short_name'], vnfr['id'], e))
+ format(vnfr['name'], vnfr['id'], e))
vnfr['vnf_cfg'] = vnf_cfg
self.find_or_create_vnfr_cm_state(vnf_cfg)
cp_list += vdur['internal_connection_point']
for cp_item_dict in cp_list:
+ if 'ip_address' not in cp_item_dict:
+ self._log.error("connection point {} doesnot have an ip address assigned ".
+ format(cp_item_dict['name']))
+ continue
# Populate global dictionary
self._cp_dict[
cp_item_dict['name']
if 'internal_vlr' in vnfr:
for ivlr in vnfr['internal_vlr']:
yield from populate_subnets_from_vlr(ivlr['vlr_ref'])
-
+
# Update vnfr
vnf_cfg['agent_vnfr']._vnfr = vnfr
return vnf_cfg['agent_vnfr']
@staticmethod
def nsr_opdata(k=None):
return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
- ("[nsr:ns-instance-config-ref='{}']".format(k) if k is not None else ""))
+ ("[nsr:ns-instance-config-ref={}]".format(quoted_key(k)) if k is not None else ""))
@staticmethod
def nsd_msg(k=None):
- return ("C,/nsd:nsd-catalog/nsd:nsd" +
- "[nsd:id = '{}']".format(k) if k is not None else "")
+ return ("C,/project-nsd:nsd-catalog/project-nsd:nsd" +
+ "[project-nsd:id={}]".format(quoted_key(k)) if k is not None else "")
@staticmethod
def vnfr_opdata(k=None):
return ("D,/vnfr:vnfr-catalog/vnfr:vnfr" +
- ("[vnfr:id='{}']".format(k) if k is not None else ""))
+ ("[vnfr:id={}]".format(quoted_key(k)) if k is not None else ""))
@staticmethod
- def vnfd(k=None):
+ def vnfd_path(k=None):
return ("C,/vnfd:vnfd-catalog/vnfd:vnfd" +
- ("[vnfd:id='{}']".format(k) if k is not None else ""))
+ ("[vnfd:id={}]".format(quoted_key(k)) if k is not None else ""))
@staticmethod
def config_agent(k=None):
return ("D,/rw-config-agent:config-agent/rw-config-agent:account" +
- ("[rw-config-agent:name='{}']".format(k) if k is not None else ""))
+ ("[rw-config-agent:name={}]".format(quoted_key(k)) if k is not None else ""))
@staticmethod
def nsr_config(k=None):
- return ("C,/nsr:ns-instance-config/nsr:nsr[nsr:id='{}']".format(k) if k is not None else "")
+ return ("C,/nsr:ns-instance-config/nsr:nsr" +
+ ("[nsr:id={}]".format(quoted_key(k)) if k is not None else ""))
@staticmethod
def vlr(k=None):
- return ("D,/vlr:vlr-catalog/vlr:vlr[vlr:id='{}']".format(k) if k is not None else "")
+ return ("D,/vlr:vlr-catalog/vlr:vlr" +
+ ("[vlr:id={}]".format(quoted_key(k)) if k is not None else ""))
class ConfigManagerDTS(object):
''' This class either reads from DTS or publishes to DTS '''
- def __init__(self, log, loop, parent, dts):
+ def __init__(self, log, loop, parent, dts, project):
self._log = log
self._loop = loop
self._parent = parent
self._dts = dts
+ self._project = project
@asyncio.coroutine
- def _read_dts(self, xpath, do_trace=False):
+ def _read_dts(self, path, do_trace=False):
+ xpath = self._project.add_project(path)
self._log.debug("_read_dts path = %s", xpath)
flags = rwdts.XactFlag.MERGE
+ flags += rwdts.XactFlag.TRACE if do_trace else 0
res_iter = yield from self._dts.query_read(
xpath, flags=flags
)
return results
+ @asyncio.coroutine
+ def get_xpath(self, xpath):
+ self._log.debug("Attempting to get xpath: {}".format(xpath))
+ resp = yield from self._read_dts(xpath, False)
+ if len(resp) > 0:
+ self._log.debug("Got DTS resp: {}".format(resp[0]))
+ return resp[0]
+ return None
+
@asyncio.coroutine
def get_nsr(self, id):
self._log.debug("Attempting to get NSR: %s", id)
return vnfr_msg
@asyncio.coroutine
- def get_vnfd(self, vnfd_id):
- self._log.debug("Attempting to get VNFD: %s", vnfd_id)
- vnfdl = yield from self._read_dts(XPaths.vnfd(vnfd_id), do_trace=False)
+ def get_vnfd(self, id):
+ self._log.debug("Attempting to get VNFD: %s", XPaths.vnfd_path(id))
+ vnfdl = yield from self._read_dts(XPaths.vnfd_path(id), do_trace=False)
vnfd_msg = None
if len(vnfdl) > 0:
vnfd_msg = vnfdl[0]
@asyncio.coroutine
def get_vlr(self, id):
self._log.debug("Attempting to get VLR subnet: %s", id)
- vlrl = yield from self._read_dts(XPaths.vlr(id), do_trace=True)
+ vlrl = yield from self._read_dts(XPaths.vlr(id), do_trace=False)
vlr_msg = None
if len(vlrl) > 0:
vlr_msg = vlrl[0]
return cfgagentl
@asyncio.coroutine
- def update(self, path, msg, flags=rwdts.XactFlag.REPLACE):
+ def update(self, xpath, msg, flags=rwdts.XactFlag.REPLACE):
"""
Update a cm-state (cm-nsr) record in DTS with the path and message
"""
+ path = self._project.add_project(xpath)
self._log.debug("Updating cm-state %s:%s dts_pub_hdl = %s", path, msg, self.dts_pub_hdl)
self.dts_pub_hdl.update_element(path, msg, flags)
self._log.debug("Updated cm-state, %s:%s", path, msg)
@asyncio.coroutine
- def delete(self, path):
+ def delete(self, xpath):
"""
Delete cm-nsr record in DTS with the path only
"""
+ path = self._project.add_project(xpath)
self._log.debug("Deleting cm-nsr %s dts_pub_hdl = %s", path, self.dts_pub_hdl)
self.dts_pub_hdl.delete_element(path)
self._log.debug("Deleted cm-nsr, %s", path)
def register(self):
yield from self.register_to_publish()
yield from self.register_for_nsr()
-
+
+ def deregister(self):
+ self._log.debug("De-registering conman config for project {}".
+ format(self._project.name))
+ if self.dts_reg_hdl:
+ self.dts_reg_hdl.deregister()
+ self.dts_reg_hdl = None
+
+ if self.dts_pub_hdl:
+ self.dts_pub_hdl.deregister()
+ self.dts_pub_hdl = None
+
@asyncio.coroutine
def register_to_publish(self):
''' Register to DTS for publishing cm-state opdata '''
- xpath = "D,/rw-conman:cm-state/rw-conman:cm-nsr"
+ xpath = self._project.add_project("D,/rw-conman:cm-state/rw-conman:cm-nsr")
self._log.debug("Registering to publish cm-state @ %s", xpath)
hdl = rift.tasklets.DTS.RegistrationHandler()
with self._dts.group_create() as group:
@property
def nsr_xpath(self):
- return "D,/nsr:ns-instance-opdata/nsr:nsr"
+ return self._project.add_project("D,/nsr:ns-instance-opdata/nsr:nsr")
@asyncio.coroutine
def register_for_nsr(self):
if (query_action == rwdts.QueryAction.UPDATE or
query_action == rwdts.QueryAction.CREATE):
- msg_dict = msg.as_dict()
- # Update Each NSR/VNFR state)
- if ('operational_status' in msg_dict and
- msg_dict['operational_status'] == 'running'):
+ # Update Each NSR/VNFR state
+ if msg.operational_status in ['running', 'terminate']:
# Add to the task list
- self._parent.add_to_pending_tasks({'nsrid' : msg_dict['ns_instance_config_ref'], 'retries' : 5})
+ self._parent.add_to_pending_tasks({
+ 'nsrid' : msg.ns_instance_config_ref,
+ 'retries' : 5,
+ 'event' : msg.operational_status,
+ })
+
elif query_action == rwdts.QueryAction.DELETE:
nsr_id = msg.ns_instance_config_ref
- asyncio.ensure_future(self._parent.terminate_NSR(nsr_id), loop=self._loop)
+ self._log.debug("Got terminate for NSR id %s", nsr_id)
+ asyncio.ensure_future(self._parent.delete_NSR(nsr_id), loop=self._loop)
+
else:
raise NotImplementedError(
"%s action on cm-state not supported",