X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=rwlaunchpad%2Fplugins%2Frwvnfm%2Frift%2Ftasklets%2Frwvnfmtasklet%2Frwvnfmtasklet.py;h=abf73aecdad2c75de891b25714f3aee2eb39f16b;hb=f49375710db1acf3cd74c8651d098b7a08e8d0b2;hp=e493d3a0651033084b08bad5d2b0ffab8b00a98a;hpb=30ee9b98b1255edd5ed79a31332b6dabbddb5823;p=osm%2FSO.git diff --git a/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py b/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py index e493d3a0..abf73aec 100755 --- a/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py +++ b/rwlaunchpad/plugins/rwvnfm/rift/tasklets/rwvnfmtasklet/rwvnfmtasklet.py @@ -51,6 +51,10 @@ import rift.package.store import rift.package.cloud_init import rift.package.script import rift.mano.dts as mano_dts +from rift.mano.utils.project import ( + ManoProject, + ProjectHandler, + ) class VMResourceError(Exception): @@ -162,7 +166,8 @@ class VDURecordState(enum.Enum): class VcsComponent(object): """ VCS Component within the VNF descriptor """ - def __init__(self, dts, log, loop, cluster_name, vcs_handler, component, mangled_name): + def __init__(self, dts, log, loop, cluster_name, + vcs_handler, component, mangled_name): self._dts = dts self._log = log self._loop = loop @@ -184,7 +189,7 @@ class VcsComponent(object): @property def path(self): """ The path for this object """ - return("D,/rw-manifest:manifest" + + return ("D,/rw-manifest:manifest" + "/rw-manifest:operational-inventory" + "/rw-manifest:component" + "[rw-manifest:component-name = '{}']").format(self.name) @@ -269,6 +274,7 @@ class VirtualDeploymentUnitRecord(object): dts, log, loop, + project, vdud, vnfr, mgmt_intf, @@ -280,6 +286,7 @@ class VirtualDeploymentUnitRecord(object): self._dts = dts self._log = log self._loop = loop + self._project = project self._vdud = vdud self._vnfr = vnfr self._mgmt_intf = mgmt_intf @@ -298,7 +305,8 @@ class VirtualDeploymentUnitRecord(object): self._rm_regh = None self._vm_resp = None self._vdud_cloud_init = None - self._vdur_console_handler = VnfrConsoleOperdataDtsHandler(dts, log, loop, self._vnfr._vnfm, self._vnfr.vnfr_id, self._vdur_id,self.vdu_id) + self._vdur_console_handler = VnfrConsoleOperdataDtsHandler( + dts, log, loop, self._vnfr._vnfm, self._vnfr.vnfr_id, self._vdur_id,self.vdu_id) @asyncio.coroutine def vdu_opdata_register(self): @@ -425,24 +433,22 @@ class VirtualDeploymentUnitRecord(object): metadata_list = list() for metadata_item in opvolume.custom_meta_data: metadata_list.append(metadata_item.as_dict()) - if 'guest_params' not in vdurvol_data[0]: - vdurvol_data[0]['guest_params'] = dict() - vdurvol_data[0]['guest_params']['custom_meta_data'] = metadata_list - - if self._vm_resp.has_field('custom_boot_data'): - vdur_dict['custom_boot_data'] = dict() - if self._vm_resp.custom_boot_data.has_field('custom_drive'): - vdur_dict['custom_boot_data']['custom_drive'] = self._vm_resp.custom_boot_data.custom_drive - if self._vm_resp.custom_boot_data.has_field('custom_meta_data'): + vdurvol_data[0]['custom_meta_data'] = metadata_list + + if self._vm_resp.has_field('supplemental_boot_data'): + vdur_dict['supplemental_boot_data'] = dict() + if self._vm_resp.supplemental_boot_data.has_field('boot_data_drive'): + vdur_dict['supplemental_boot_data']['boot_data_drive'] = self._vm_resp.supplemental_boot_data.boot_data_drive + if self._vm_resp.supplemental_boot_data.has_field('custom_meta_data'): metadata_list = list() - for metadata_item in self._vm_resp.custom_boot_data.custom_meta_data: + for metadata_item in self._vm_resp.supplemental_boot_data.custom_meta_data: metadata_list.append(metadata_item.as_dict()) - vdur_dict['custom_boot_data']['custom_meta_data'] = metadata_list - if self._vm_resp.custom_boot_data.has_field('custom_config_files'): + vdur_dict['supplemental_boot_data']['custom_meta_data'] = metadata_list + if self._vm_resp.supplemental_boot_data.has_field('config_file'): file_list = list() - for file_item in self._vm_resp.custom_boot_data.custom_config_files: + for file_item in self._vm_resp.supplemental_boot_data.config_file: file_list.append(file_item.as_dict()) - vdur_dict['custom_boot_data']['custom_config_files'] = file_list + vdur_dict['supplemental_boot_data']['config_file'] = file_list icp_list = [] ii_list = [] @@ -466,13 +472,13 @@ class VirtualDeploymentUnitRecord(object): ei_list = [] for intf, cp, vlr in self._ext_intf: - ei_list.append({"name": cp, - "vnfd_connection_point_ref": cp, + ei_list.append({"name": cp.name, + "vnfd_connection_point_ref": cp.name, "virtual_interface": {}}) - self._vnfr.update_cp(cp, - self.cp_ip_addr(cp), - self.cp_mac_addr(cp), - self.cp_id(cp)) + self._vnfr.update_cp(cp.name, + self.cp_ip_addr(cp.name), + self.cp_mac_addr(cp.name), + self.cp_id(cp.name)) vdur_dict["external_interface"] = ei_list @@ -481,14 +487,15 @@ class VirtualDeploymentUnitRecord(object): placement_groups.append(group.as_dict()) vdur_dict['placement_groups_info'] = placement_groups - return RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur.from_dict(vdur_dict) + return RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur.from_dict(vdur_dict) @property def resmgr_path(self): """ path for resource-mgr""" - return ("D,/rw-resource-mgr:resource-mgmt" + - "/vdu-event" + - "/vdu-event-data[event-id='{}']".format(self._request_id)) + xpath = self._project.add_project("D,/rw-resource-mgr:resource-mgmt" + + "/vdu-event" + + "/vdu-event-data[event-id='{}']".format(self._request_id)) + return xpath @property def vm_flavor_msg(self): @@ -523,6 +530,7 @@ class VirtualDeploymentUnitRecord(object): try: return cloud_init_extractor.read_script(stored_package, filename) except rift.package.cloud_init.CloudInitExtractionError as e: + self.instantiation_failed(str(e)) raise VirtualDeploymentUnitRecordError(e) else: self._log.debug("VDU Instantiation: cloud-init script not provided") @@ -542,15 +550,19 @@ class VirtualDeploymentUnitRecord(object): if availability_zones: if len(availability_zones) > 1: - self._log.error("Can not launch VDU: %s in multiple availability zones. Requested Zones: %s", self.name, availability_zones) - raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple availability zones. Requsted Zones".format(self.name, availability_zones)) + self._log.error("Can not launch VDU: %s in multiple availability zones. " + + "Requested Zones: %s", self.name, availability_zones) + raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple availability" + + " zones. Requsted Zones".format(self.name, availability_zones)) else: vm_create_msg_dict['availability_zone'] = availability_zones[0] if server_groups: if len(server_groups) > 1: - self._log.error("Can not launch VDU: %s in multiple Server Group. Requested Groups: %s", self.name, server_groups) - raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple Server Groups. Requsted Groups".format(self.name, server_groups)) + self._log.error("Can not launch VDU: %s in multiple Server Group. " + + "Requested Groups: %s", self.name, server_groups) + raise VNFMPlacementGroupError("Can not launch VDU: {} in multiple " + + "Server Groups. Requsted Groups".format(self.name, server_groups)) else: vm_create_msg_dict['server_group'] = server_groups[0] @@ -577,24 +589,24 @@ class VirtualDeploymentUnitRecord(object): def process_custom_bootdata(self, vm_create_msg_dict): """Process the custom boot data""" - if 'custom_config_files' not in vm_create_msg_dict['custom_boot_data']: + if 'config_file' not in vm_create_msg_dict['supplemental_boot_data']: return + self._vnfd_package_store.refresh() stored_package = self._vnfd_package_store.get_package(self._vnfr.vnfd_id) - script_extractor = rift.package.script.PackageScriptExtractor(self._log) - for custom_file_item in vm_create_msg_dict['custom_boot_data']['custom_config_files']: - if 'source' not in custom_file_item or 'dest' not in custom_file_item: + cloud_init_extractor = rift.package.cloud_init.PackageCloudInitExtractor(self._log) + for file_item in vm_create_msg_dict['supplemental_boot_data']['config_file']: + if 'source' not in file_item or 'dest' not in file_item: continue - source = custom_file_item['source'] + source = file_item['source'] # Find source file in scripts dir of VNFD - self._vnfd_package_store.refresh() self._log.debug("Checking for source config file at %s", source) try: - source_file_str = script_extractor.read_script(stored_package, source) - except rift.package.script.ScriptExtractionError as e: + source_file_str = cloud_init_extractor.read_script(stored_package, source) + except rift.package.cloud_init.CloudInitExtractionError as e: raise VirtualDeploymentUnitRecordError(e) # Update source file location with file contents - custom_file_item['source'] = source_file_str + file_item['source'] = source_file_str return @@ -605,7 +617,7 @@ class VirtualDeploymentUnitRecord(object): "hypervisor_epa", "host_epa", "volumes", - "custom_boot_data"] + "supplemental_boot_data"] self._log.debug("Creating params based on VDUD: %s", self._vdud) vdu_copy_dict = {k: v for k, v in self._vdud.as_dict().items() if k in vdu_fields} @@ -633,9 +645,12 @@ class VirtualDeploymentUnitRecord(object): cp_list = [] for intf, cp, vlr in self._ext_intf: - cp_info = {"name": cp, - "virtual_link_id": vlr.network_id, - "type_yang": intf.virtual_interface.type_yang} + cp_info = { "name": cp.name, + "virtual_link_id": vlr.network_id, + "type_yang": intf.virtual_interface.type_yang } + + if cp.has_field('port_security_enabled'): + cp_info["port_security_enabled"] = cp.port_security_enabled if (intf.virtual_interface.has_field('vpci') and intf.virtual_interface.vpci is not None): @@ -654,15 +669,22 @@ class VirtualDeploymentUnitRecord(object): "type_yang": intf.virtual_interface.type_yang, "vpci": intf.virtual_interface.vpci}) else: - cp_list.append({"name": cp, - "virtual_link_id": vlr.network_id, - "type_yang": intf.virtual_interface.type_yang}) + if cp.has_field('port_security_enabled'): + cp_list.append({"name": cp, + "virtual_link_id": vlr.network_id, + "type_yang": intf.virtual_interface.type_yang, + "port_security_enabled": cp.port_security_enabled}) + else: + cp_list.append({"name": cp, + "virtual_link_id": vlr.network_id, + "type_yang": intf.virtual_interface.type_yang}) + vm_create_msg_dict["connection_points"] = cp_list vm_create_msg_dict.update(vdu_copy_dict) self.process_placement_groups(vm_create_msg_dict) - if 'custom_boot_data' in vm_create_msg_dict: + if 'supplemental_boot_data' in vm_create_msg_dict: self.process_custom_bootdata(vm_create_msg_dict) msg = RwResourceMgrYang.VDUEventData() @@ -693,7 +715,7 @@ class VirtualDeploymentUnitRecord(object): self._rm_regh = None if self._vdur_console_handler is not None: - self._log.error("Deregistering vnfr vdur registration handle") + self._log.debug("Deregistering vnfr vdur registration handle") self._vdur_console_handler._regh.deregister() self._vdur_console_handler._regh = None @@ -781,7 +803,7 @@ class VirtualDeploymentUnitRecord(object): vlr = vnfr.ext_vlr_by_id(cp.vlr_ref) - etuple = (ext_intf, cp.name, vlr) + etuple = (ext_intf, cp, vlr) self._ext_intf.append(etuple) self._log.debug("Created external interface tuple : %s", etuple) @@ -942,8 +964,8 @@ class VirtualDeploymentUnitRecord(object): vm_resp = yield from self.create_resource(xact, vnfr, config) self._vm_resp = vm_resp - self._state = VDURecordState.RESOURCE_ALLOC_PENDING + self._log.debug("Requested VM from resource manager response %s", vm_resp) if vm_resp.resource_state == "active": @@ -986,13 +1008,16 @@ class VlRecordState(enum.Enum): class InternalVirtualLinkRecord(object): """ Internal Virtual Link record """ - def __init__(self, dts, log, loop, ivld_msg, vnfr_name, cloud_account_name): + def __init__(self, dts, log, loop, project, + ivld_msg, vnfr_name, cloud_account_name, ip_profile=None): self._dts = dts self._log = log self._loop = loop + self._project = project self._ivld_msg = ivld_msg self._vnfr_name = vnfr_name self._cloud_account_name = cloud_account_name + self._ip_profile = ip_profile self._vlr_req = self.create_vlr() self._vlr = None @@ -1006,7 +1031,10 @@ class InternalVirtualLinkRecord(object): @property def name(self): """ Name of this VL """ - return self._vnfr_name + "." + self._ivld_msg.name + if self._ivld_msg.vim_network_name: + return self._ivld_msg.vim_network_name + else: + return self._vnfr_name + "." + self._ivld_msg.name @property def network_id(self): @@ -1015,7 +1043,8 @@ class InternalVirtualLinkRecord(object): def vlr_path(self): """ VLR path for this VLR instance""" - return "D,/vlr:vlr-catalog/vlr:vlr[vlr:id = '{}']".format(self.vlr_id) + return self._project.add_project("D,/vlr:vlr-catalog/vlr:vlr[vlr:id = '{}']". + format(self.vlr_id)) def create_vlr(self): """ Create the VLR record which will be instantiated """ @@ -1025,6 +1054,7 @@ class InternalVirtualLinkRecord(object): "description", "version", "type_yang", + "vim_network_name", "provider_network"] vld_copy_dict = {k: v for k, v in self._ivld_msg.as_dict().items() if k in vld_fields} @@ -1033,9 +1063,13 @@ class InternalVirtualLinkRecord(object): "name": self.name, "cloud_account": self._cloud_account_name, } + + if self._ip_profile and self._ip_profile.has_field('ip_profile_params'): + vlr_dict['ip_profile_params' ] = self._ip_profile.ip_profile_params.as_dict() + vlr_dict.update(vld_copy_dict) - vlr = RwVlrYang.YangData_Vlr_VlrCatalog_Vlr.from_dict(vlr_dict) + vlr = RwVlrYang.YangData_RwProject_Project_VlrCatalog_Vlr.from_dict(vlr_dict) return vlr @asyncio.coroutine @@ -1132,6 +1166,7 @@ class VirtualNetworkFunctionRecord(object): self._dts = dts self._log = log self._loop = loop + self._project = vnfm._project self._cluster_name = cluster_name self._vnfr_msg = vnfr_msg self._vnfr_id = vnfr_msg.id @@ -1184,7 +1219,8 @@ class VirtualNetworkFunctionRecord(object): @staticmethod def vnfd_xpath(vnfd_id): """ VNFD xpath associated with this VNFR """ - return "C,/vnfd:vnfd-catalog/vnfd:vnfd[vnfd:id = '{}']".format(vnfd_id) + return ("C,/vnfd:vnfd-catalog/vnfd:vnfd[vnfd:id = '{}']". + format(vnfd_id)) @property def vnfd_ref_count(self): @@ -1265,7 +1301,7 @@ class VirtualNetworkFunctionRecord(object): def get_nsr_config(self): ### Need access to NS instance configuration for runtime resolution. ### This shall be replaced when deployment flavors are implemented - xpath = "C,/nsr:ns-instance-config" + xpath = self._project.add_project("C,/nsr:ns-instance-config") results = yield from self._dts.query_read(xpath, rwdts.XactFlag.MERGE) for result in results: @@ -1315,7 +1351,7 @@ class VirtualNetworkFunctionRecord(object): vnfd_fields = ["short_name", "vendor", "description", "version"] vnfd_copy_dict = {k: v for k, v in self.vnfd.as_dict().items() if k in vnfd_fields} - mgmt_intf = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_MgmtInterface() + mgmt_intf = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MgmtInterface() ip_address, port = self.mgmt_intf_info() if ip_address is not None: @@ -1335,8 +1371,8 @@ class VirtualNetworkFunctionRecord(object): vnfr_dict.update(vnfd_copy_dict) - vnfr_msg = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.from_dict(vnfr_dict) - vnfr_msg.vnfd = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vnfd.from_dict(self.vnfd.as_dict()) + vnfr_msg = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.from_dict(vnfr_dict) + vnfr_msg.vnfd = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vnfd.from_dict(self.vnfd.as_dict()) vnfr_msg.create_time = self._create_time vnfr_msg.uptime = int(time.time()) - self._create_time @@ -1357,13 +1393,13 @@ class VirtualNetworkFunctionRecord(object): vnfr_msg.dashboard_url = self.dashboard_url for cpr in self._cprs: - new_cp = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr.as_dict()) + new_cp = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr.as_dict()) vnfr_msg.connection_point.append(new_cp) if self._vnf_mon is not None: for monp in self._vnf_mon.msg: vnfr_msg.monitoring_param.append( - VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_MonitoringParam.from_dict(monp.as_dict())) + VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MonitoringParam.from_dict(monp.as_dict())) if self._vnfr.vnf_configuration is not None: vnfr_msg.vnf_configuration.from_dict(self._vnfr.vnf_configuration.as_dict()) @@ -1372,7 +1408,7 @@ class VirtualNetworkFunctionRecord(object): vnfr_msg.vnf_configuration.config_access.mgmt_ip_address = ip_address for group in self._vnfr_msg.placement_groups_info: - group_info = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_PlacementGroupsInfo() + group_info = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_PlacementGroupsInfo() group_info.from_dict(group.as_dict()) vnfr_msg.placement_groups_info.append(group_info) @@ -1402,7 +1438,7 @@ class VirtualNetworkFunctionRecord(object): @property def xpath(self): """ path for this VNFR """ - return("D,/vnfr:vnfr-catalog" + return self._project.add_project("D,/vnfr:vnfr-catalog" "/vnfr:vnfr[vnfr:id='{}']".format(self.vnfr_id)) @asyncio.coroutine @@ -1416,6 +1452,13 @@ class VirtualNetworkFunctionRecord(object): self._log.debug("Published VNFR path = [%s], record = [%s]", self.xpath, self.msg) + def resolve_vld_ip_profile(self, vnfd_msg, vld): + self._log.debug("Receieved ip profile ref is %s",vld.ip_profile_ref) + if not vld.has_field('ip_profile_ref'): + return None + profile = [profile for profile in vnfd_msg.ip_profiles if profile.name == vld.ip_profile_ref] + return profile[0] if profile else None + @asyncio.coroutine def create_vls(self): """ Publish The VLs associated with this VNF """ @@ -1431,7 +1474,8 @@ class VirtualNetworkFunctionRecord(object): loop=self._loop, ivld_msg=ivld_msg, vnfr_name=self.name, - cloud_account_name=self.cloud_account_name + cloud_account_name=self.cloud_account_name, + ip_profile=self.resolve_vld_ip_profile(self.vnfd, ivld_msg) ) self._vlrs.append(vlr) @@ -1469,7 +1513,7 @@ class VirtualNetworkFunctionRecord(object): for group_info in nsr_config.vnfd_placement_group_maps: if group_info.placement_group_ref == input_group.name and \ group_info.vnfd_id_ref == self.vnfd_id: - group = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo() + group = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo() group_dict = {k:v for k,v in group_info.as_dict().items() if (k != 'placement_group_ref' and k !='vnfd_id_ref')} @@ -1484,7 +1528,7 @@ class VirtualNetworkFunctionRecord(object): placement_groups = [] ### Step-1: Get VNF level placement groups for group in self._vnfr_msg.placement_groups_info: - #group_info = VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo() + #group_info = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vdur_PlacementGroupsInfo() #group_info.from_dict(group.as_dict()) placement_groups.append(group) @@ -1498,10 +1542,11 @@ class VirtualNetworkFunctionRecord(object): group_info = self.resolve_placement_group_cloud_construct(group, nsr_config) if group_info is None: - self._log.info("Could not resolve cloud-construct for placement group: %s", group.name) - ### raise VNFMPlacementGroupError("Could not resolve cloud-construct for placement group: {}".format(group.name)) + self._log.info("Could not resolve cloud-construct for " + + "placement group: %s", group.name) else: - self._log.info("Successfully resolved cloud construct for placement group: %s for VDU: %s in VNF: %s (Member Index: %s)", + self._log.info("Successfully resolved cloud construct for " + + "placement group: %s for VDU: %s in VNF: %s (Member Index: %s)", str(group_info), vdu.name, self.vnf_name, @@ -1510,6 +1555,10 @@ class VirtualNetworkFunctionRecord(object): return placement_groups + @asyncio.coroutine + def vdu_cloud_init_instantiation(self): + [vdu.vdud_cloud_init for vdu in self._vdus] + @asyncio.coroutine def create_vdus(self, vnfr, restart_mode=False): """ Create the VDUs associated with this VNF """ @@ -1549,6 +1598,7 @@ class VirtualNetworkFunctionRecord(object): dts=self._dts, log=self._log, loop=self._loop, + project = self._project, vdud=vdu, vnfr=vnfr, mgmt_intf=self.has_mgmt_interface(vdu), @@ -1574,8 +1624,8 @@ class VirtualNetworkFunctionRecord(object): vdu_id_pattern = re.compile(r"\{\{ vdu\[([^]]+)\]\S* \}\}") for vdu in self._vdus: - if vdu.vdud_cloud_init is not None: - for vdu_id in vdu_id_pattern.findall(vdu.vdud_cloud_init): + if vdu._vdud_cloud_init is not None: + for vdu_id in vdu_id_pattern.findall(vdu._vdud_cloud_init): if vdu_id != vdu.vdu_id: # This means that vdu.vdu_id depends upon vdu_id, # i.e. vdu_id must be instantiated before @@ -1603,7 +1653,6 @@ class VirtualNetworkFunctionRecord(object): # wait for the VDUR to enter a terminal state while vdu._state not in terminal: yield from asyncio.sleep(1, loop=self._loop) - # update the datastore datastore.update(vdu) @@ -1696,8 +1745,7 @@ class VirtualNetworkFunctionRecord(object): def vlr_xpath(self, vlr_id): """ vlr xpath """ - return( - "D,/vlr:vlr-catalog/" + return self._project.add_project("D,/vlr:vlr-catalog/" "vlr:vlr[vlr:id = '{}']".format(vlr_id)) def ext_vlr_by_id(self, vlr_id): @@ -1787,6 +1835,7 @@ class VirtualNetworkFunctionRecord(object): @asyncio.coroutine def instantiate(self, xact, restart_mode=False): """ instantiate this VNF """ + self._log.info("Instantiate VNF {}: {}".format(self._vnfr_id, self._state)) self.set_state(VirtualNetworkFunctionRecordState.VL_INIT_PHASE) self._rw_vnfd = yield from self._vnfm.fetch_vnfd(self._vnfd_id) @@ -1798,11 +1847,11 @@ class VirtualNetworkFunctionRecord(object): def cpr_from_cp(cp): """ Creates a record level connection point from the desciptor cp""" - cp_fields = ["name", "image", "vm-flavor"] + cp_fields = ["name", "image", "vm-flavor", "port_security_enabled"] cp_copy_dict = {k: v for k, v in cp.as_dict().items() if k in cp_fields} cpr_dict = {} cpr_dict.update(cp_copy_dict) - return VnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr_dict) + return VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_ConnectionPoint.from_dict(cpr_dict) self._log.debug("Fetching VLRs for VNFR id = %s, cps = %s", self._vnfr_id, self._vnfr.connection_point) @@ -1814,7 +1863,7 @@ class VirtualNetworkFunctionRecord(object): vlr_path = self.vlr_xpath(cp.vlr_ref) self._log.debug("Fetching VLR with path = %s", vlr_path) - res_iter = yield from self._dts.query_read(self.vlr_xpath(cp.vlr_ref), + res_iter = yield from self._dts.query_read(vlr_path, rwdts.XactFlag.MERGE) for i in res_iter: r = yield from i @@ -1837,15 +1886,16 @@ class VirtualNetworkFunctionRecord(object): yield from self.publish_inventory(xact) # Publish inventory - self._log.debug("VNFR-ID %s: Creating VLs", self._vnfr_id) + self._log.debug("Create VLs {}: {}".format(self._vnfr_id, self._state)) yield from self.create_vls() # publish the VNFR - self._log.debug("VNFR-ID %s: Publish VNFR", self._vnfr_id) + self._log.debug("Publish VNFR {}: {}".format(self._vnfr_id, self._state)) yield from self.publish(xact) + # instantiate VLs - self._log.debug("VNFR-ID %s: Instantiate VLs", self._vnfr_id) + self._log.debug("Instantiate VLs {}: {}".format(self._vnfr_id, self._state)) try: yield from self.instantiate_vls(xact, restart_mode) except Exception as e: @@ -1856,16 +1906,24 @@ class VirtualNetworkFunctionRecord(object): self.set_state(VirtualNetworkFunctionRecordState.VM_INIT_PHASE) # instantiate VDUs - self._log.debug("VNFR-ID %s: Create VDUs", self._vnfr_id) + self._log.debug("Create VDUs {}: {}".format(self._vnfr_id, self._state)) yield from self.create_vdus(self, restart_mode) + try: + yield from self.vdu_cloud_init_instantiation() + except Exception as e: + self.set_state(VirtualNetworkFunctionRecordState.FAILED) + self._state_failed_reason = str(e) + yield from self.publish(xact) + # publish the VNFR - self._log.debug("VNFR-ID %s: Publish VNFR", self._vnfr_id) + self._log.debug("VNFR {}: Publish VNFR with state {}". + format(self._vnfr_id, self._state)) yield from self.publish(xact) # instantiate VDUs # ToDo: Check if this should be prevented during restart - self._log.debug("VNFR-ID %s: Instantiate VDUs", self._vnfr_id) + self._log.debug("Instantiate VDUs {}: {}".format(self._vnfr_id, self._state)) _ = self._loop.create_task(self.instantiate_vdus(xact, self)) # publish the VNFR @@ -1945,6 +2003,14 @@ class VnfdDtsHandler(object): """ DTS registration handle """ return self._regh + def deregister(self): + '''De-register from DTS''' + self._log.debug("De-register VNFD DTS handler for project {}". + format(self._project)) + if self._regh: + self._regh.deregister() + self._regh = None + @asyncio.coroutine def register(self): """ Register for VNFD configuration""" @@ -1977,14 +2043,14 @@ class VnfdDtsHandler(object): xact_info.respond_xpath(rwdts.XactRspCode.ACK) - self._log.debug( - "Registering for VNFD config using xpath: %s", - VnfdDtsHandler.XPATH, - ) + xpath = self._vnfm._project.add_project(VnfdDtsHandler.XPATH) + self._log.debug("Registering for VNFD config using xpath: {}". + format(xpath)) + acg_hdl = rift.tasklets.AppConfGroup.Handler(on_apply=on_apply) with self._dts.appconf_group_create(handler=acg_hdl) as acg: self._regh = acg.register( - xpath=VnfdDtsHandler.XPATH, + xpath=xpath, flags=rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY, on_prepare=on_prepare) @@ -2007,6 +2073,14 @@ class VcsComponentDtsHandler(object): """ DTS registration handle """ return self._regh + def deregister(self): + '''De-register from DTS''' + self._log.debug("De-register VCS DTS handler for project {}". + format(self._project)) + if self._regh: + self._regh.deregister() + self._regh = None + @asyncio.coroutine def register(self): """ Registers VCS component dts publisher registration""" @@ -2032,11 +2106,16 @@ class VcsComponentDtsHandler(object): VcsComponentDtsHandler.XPATH, xact, path, msg) class VnfrConsoleOperdataDtsHandler(object): - """ registers 'D,/vnfr:vnfr-console/vnfr:vnfr[id]/vdur[id]' and handles CRUD from DTS""" + """ + Registers 'D,/rw-project:project/vnfr:vnfr-console/vnfr:vnfr[id]/vdur[id]' + and handles CRUD from DTS + """ + @property def vnfr_vdu_console_xpath(self): """ path for resource-mgr""" - return ("D,/rw-vnfr:vnfr-console/rw-vnfr:vnfr[rw-vnfr:id='{}']/rw-vnfr:vdur[vnfr:id='{}']".format(self._vnfr_id,self._vdur_id)) + return self._project.add_project("D,/rw-vnfr:vnfr-console/rw-vnfr:vnfr[rw-vnfr:id='{}']" + + "/rw-vnfr:vdur[vnfr:id='{}']".format(self._vnfr_id,self._vdur_id)) def __init__(self, dts, log, loop, vnfm, vnfr_id, vdur_id, vdu_id): self._dts = dts @@ -2049,6 +2128,16 @@ class VnfrConsoleOperdataDtsHandler(object): self._vdur_id = vdur_id self._vdu_id = vdu_id + self._project = vnfm._project + + def deregister(self): + '''De-register from DTS''' + self._log.debug("De-register VNFR console DTS handler for project {}". + format(self._project)) + if self._regh: + self._regh.deregister() + self._regh = None + @asyncio.coroutine def register(self): """ Register for VNFR VDU Operational Data read from dts """ @@ -2063,7 +2152,7 @@ class VnfrConsoleOperdataDtsHandler(object): ) if action == rwdts.QueryAction.READ: - schema = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur.schema() + schema = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur.schema() path_entry = schema.keyspec_to_entry(ks_path) self._log.debug("VDU Opdata path is {}".format(path_entry)) try: @@ -2080,7 +2169,7 @@ class VnfrConsoleOperdataDtsHandler(object): return with self._dts.transaction() as new_xact: resp = yield from vdur.read_resource(new_xact) - vdur_console = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur() + vdur_console = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur() vdur_console.id = self._vdur_id if resp.console_url: vdur_console.console_url = resp.console_url @@ -2089,7 +2178,7 @@ class VnfrConsoleOperdataDtsHandler(object): self._log.debug("Recevied console URL for vdu {} is {}".format(self._vdu_id,vdur_console)) except Exception: self._log.exception("Caught exception while reading VDU %s", self._vdu_id) - vdur_console = RwVnfrYang.YangData_RwVnfr_VnfrConsole_Vnfr_Vdur() + vdur_console = RwVnfrYang.YangData_RwProject_Project_VnfrConsole_Vnfr_Vdur() vdur_console.id = self._vdur_id vdur_console.console_url = 'none' @@ -2114,7 +2203,7 @@ class VnfrConsoleOperdataDtsHandler(object): class VnfrDtsHandler(object): - """ registers 'D,/vnfr:vnfr-catalog/vnfr:vnfr' and handles CRUD from DTS""" + """ registers 'D,/rw-project:project/vnfr:vnfr-catalog/vnfr:vnfr' and handles CRUD from DTS""" XPATH = "D,/vnfr:vnfr-catalog/vnfr:vnfr" def __init__(self, dts, log, loop, vnfm): @@ -2124,6 +2213,7 @@ class VnfrDtsHandler(object): self._vnfm = vnfm self._regh = None + self._project = vnfm._project @property def regh(self): @@ -2135,6 +2225,14 @@ class VnfrDtsHandler(object): """ Return VNF manager instance """ return self._vnfm + def deregister(self): + '''De-register from DTS''' + self._log.debug("De-register VNFR DTS handler for project {}". + format(self._project)) + if self._regh: + self._regh.deregister() + self._regh = None + @asyncio.coroutine def register(self): """ Register for vnfr create/update/delete/read requests from dts """ @@ -2196,7 +2294,7 @@ class VnfrDtsHandler(object): vnfr.set_state(VirtualNetworkFunctionRecordState.FAILED) yield from vnfr.publish(None) elif action == rwdts.QueryAction.DELETE: - schema = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.schema() + schema = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.schema() path_entry = schema.keyspec_to_entry(ks_path) vnfr = self._vnfm.get_vnfr(path_entry.key00.id) @@ -2215,7 +2313,7 @@ class VnfrDtsHandler(object): self._log.error("Caught exception while deleting vnfr %s", path_entry.key00.id) elif action == rwdts.QueryAction.UPDATE: - schema = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr.schema() + schema = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.schema() path_entry = schema.keyspec_to_entry(ks_path) vnfr = None try: @@ -2243,14 +2341,15 @@ class VnfrDtsHandler(object): xact_info.respond_xpath(rwdts.XactRspCode.ACK) - self._log.debug("Registering for VNFR using xpath: %s", - VnfrDtsHandler.XPATH,) + xpath = self._project.add_project(VnfrDtsHandler.XPATH) + self._log.debug("Registering for VNFR using xpath: {}". + format(xpath)) hdl = rift.tasklets.DTS.RegistrationHandler(on_commit=on_commit, on_prepare=on_prepare,) handlers = rift.tasklets.Group.Handler(on_event=on_event,) with self._dts.group_create(handler=handlers) as group: - self._regh = group.register(xpath=VnfrDtsHandler.XPATH, + self._regh = group.register(xpath=xpath, handler=hdl, flags=(rwdts.Flag.PUBLISHER | rwdts.Flag.NO_PREP_READ | @@ -2258,10 +2357,11 @@ class VnfrDtsHandler(object): rwdts.Flag.DATASTORE),) @asyncio.coroutine - def create(self, xact, path, msg): + def create(self, xact, xpath, msg): """ Create a VNFR record in DTS with path and message """ + path = self._project.add_project(xpath) self._log.debug("Creating VNFR xact = %s, %s:%s", xact, path, msg) @@ -2270,10 +2370,11 @@ class VnfrDtsHandler(object): xact, path, msg) @asyncio.coroutine - def update(self, xact, path, msg): + def update(self, xact, xpath, msg): """ Update a VNFR record in DTS with path and message """ + path = self._project.add_project(xpath) self._log.debug("Updating VNFR xact = %s, %s:%s", xact, path, msg) self.regh.update_element(path, msg) @@ -2281,10 +2382,11 @@ class VnfrDtsHandler(object): xact, path, msg) @asyncio.coroutine - def delete(self, xact, path): + def delete(self, xact, xpath): """ Delete a VNFR record in DTS with path and message """ + path = self._project.add_project(xpath) self._log.debug("Deleting VNFR xact = %s, %s", xact, path) self.regh.delete_element(path) self._log.debug("Deleted VNFR xact = %s, %s", xact, path) @@ -2312,6 +2414,14 @@ class VnfdRefCountDtsHandler(object): """ Return the NS manager instance """ return self._vnfm + def deregister(self): + '''De-register from DTS''' + self._log.debug("De-register VNFD Ref DTS handler for project {}". + format(self._project)) + if self._regh: + self._regh.deregister() + self._regh = None + @asyncio.coroutine def register(self): """ Register for VNFD ref count read from dts """ @@ -2326,7 +2436,7 @@ class VnfdRefCountDtsHandler(object): ) if action == rwdts.QueryAction.READ: - schema = RwVnfrYang.YangData_Vnfr_VnfrCatalog_VnfdRefCount.schema() + schema = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_VnfdRefCount.schema() path_entry = schema.keyspec_to_entry(ks_path) vnfd_list = yield from self._vnfm.get_vnfd_refcount(path_entry.key00.vnfd_id_ref) for xpath, msg in vnfd_list: @@ -2341,7 +2451,8 @@ class VnfdRefCountDtsHandler(object): hdl = rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare,) with self._dts.group_create() as group: - self._regh = group.register(xpath=VnfdRefCountDtsHandler.XPATH, + self._regh = group.register(xpath=self._vnfm._project.add_project( + VnfdRefCountDtsHandler.XPATH), handler=hdl, flags=rwdts.Flag.PUBLISHER, ) @@ -2469,16 +2580,18 @@ class VdurDatastore(object): class VnfManager(object): """ The virtual network function manager class """ - def __init__(self, dts, log, loop, cluster_name): + def __init__(self, dts, log, loop, project, cluster_name): self._dts = dts self._log = log self._loop = loop + self._project = project self._cluster_name = cluster_name self._vcs_handler = VcsComponentDtsHandler(dts, log, loop, self) self._vnfr_handler = VnfrDtsHandler(dts, log, loop, self) self._vnfr_ref_handler = VnfdRefCountDtsHandler(dts, log, loop, self) - self._nsr_handler = mano_dts.NsInstanceConfigSubscriber(log, dts, loop, callback=self.handle_nsr) + self._nsr_handler = mano_dts.NsInstanceConfigSubscriber( + log, dts, loop, project, callback=self.handle_nsr) self._dts_handlers = [VnfdDtsHandler(dts, log, loop, self), self._vnfr_handler, @@ -2505,6 +2618,11 @@ class VnfManager(object): for hdl in self._dts_handlers: yield from hdl.register() + def deregister(self): + self.log.debug("De-register VNFM project {}".format(self.name)) + for hdl in self._dts_handlers: + yield from hdl.deregister() + @asyncio.coroutine def run(self): """ Run this VNFM instance """ @@ -2590,11 +2708,13 @@ class VnfManager(object): @asyncio.coroutine def fetch_vnfd(self, vnfd_id): """ Fetch VNFDs based with the vnfd id""" - vnfd_path = VirtualNetworkFunctionRecord.vnfd_xpath(vnfd_id) + vnfd_path = self._project.add_project( + VirtualNetworkFunctionRecord.vnfd_xpath(vnfd_id)) self._log.debug("Fetch vnfd with path %s", vnfd_path) vnfd = None - res_iter = yield from self._dts.query_read(vnfd_path, rwdts.XactFlag.MERGE) + res_iter = yield from self._dts.query_read(vnfd_path, + rwdts.XactFlag.MERGE) for ent in res_iter: res = yield from ent @@ -2653,8 +2773,8 @@ class VnfManager(object): def vnfd_refcount_xpath(self, vnfd_id): """ xpath for ref count entry """ - return (VnfdRefCountDtsHandler.XPATH + - "[rw-vnfr:vnfd-id-ref = '{}']").format(vnfd_id) + return self._project.add_project(VnfdRefCountDtsHandler.XPATH + + "[rw-vnfr:vnfd-id-ref = '{}']").format(vnfd_id) @asyncio.coroutine def get_vnfd_refcount(self, vnfd_id): @@ -2662,12 +2782,12 @@ class VnfManager(object): vnfd_list = [] if vnfd_id is None or vnfd_id == "": for vnfd in self._vnfds_to_vnfr.keys(): - vnfd_msg = RwVnfrYang.YangData_Vnfr_VnfrCatalog_VnfdRefCount() + vnfd_msg = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_VnfdRefCount() vnfd_msg.vnfd_id_ref = vnfd vnfd_msg.instance_ref_count = self._vnfds_to_vnfr[vnfd] vnfd_list.append((self.vnfd_refcount_xpath(vnfd), vnfd_msg)) elif vnfd_id in self._vnfds_to_vnfr: - vnfd_msg = RwVnfrYang.YangData_Vnfr_VnfrCatalog_VnfdRefCount() + vnfd_msg = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_VnfdRefCount() vnfd_msg.vnfd_id_ref = vnfd_id vnfd_msg.instance_ref_count = self._vnfds_to_vnfr[vnfd_id] vnfd_list.append((self.vnfd_refcount_xpath(vnfd_id), vnfd_msg)) @@ -2675,6 +2795,31 @@ class VnfManager(object): return vnfd_list +class VnfmProject(ManoProject): + + def __init__(self, name, tasklet, **kw): + super(VnfmProject, self).__init__(tasklet.log, name) + self.update(tasklet) + + self._vnfm = None + + @asyncio.coroutine + def register (self): + try: + vm_parent_name = self._tasklet.tasklet_info.get_parent_vm_parent_instance_name() + assert vm_parent_name is not None + self._vnfm = VnfManager(self._dts, self.log, self.loop, self, vm_parent_name) + yield from self._vnfm.run() + except Exception: + print("Caught Exception in VNFM init:", sys.exc_info()[0]) + raise + + def deregister(self): + self._log.debug("De-register project {} for VnfmProject". + format(self.name)) + self._vnfm.deregister() + + class VnfmTasklet(rift.tasklets.Tasklet): """ VNF Manager tasklet class """ def __init__(self, *args, **kwargs): @@ -2683,7 +2828,12 @@ class VnfmTasklet(rift.tasklets.Tasklet): self.rwlog.set_subcategory("vnfm") self._dts = None - self._vnfm = None + self._project_handler = None + self.projects = {} + + @property + def dts(self): + return self._dts def start(self): try: @@ -2717,14 +2867,9 @@ class VnfmTasklet(rift.tasklets.Tasklet): @asyncio.coroutine def init(self): """ Task init callback """ - try: - vm_parent_name = self.tasklet_info.get_parent_vm_parent_instance_name() - assert vm_parent_name is not None - self._vnfm = VnfManager(self._dts, self.log, self.loop, vm_parent_name) - yield from self._vnfm.run() - except Exception: - print("Caught Exception in VNFM init:", sys.exc_info()[0]) - raise + self.log.debug("creating project handler") + self.project_handler = ProjectHandler(self, VnfmProject) + self.project_handler.register() @asyncio.coroutine def run(self):