X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=rwcal%2Fplugins%2Fvala%2Frwcal_openstack%2Frift%2Frwcal%2Fopenstack%2Futils%2Fcompute.py;h=71529629dd9c7d9160a156013f471288da1fb4a4;hb=f314b4af9744068a7ed7a6a6314220c3aa857523;hp=55382017dee623142b458bc3e40fcdfff1f9d0e9;hpb=52558f6f42f4e636cc319664b834fb4a7f188957;p=osm%2FSO.git diff --git a/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/utils/compute.py b/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/utils/compute.py index 55382017..71529629 100644 --- a/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/utils/compute.py +++ b/rwcal/plugins/vala/rwcal_openstack/rift/rwcal/openstack/utils/compute.py @@ -60,12 +60,21 @@ class ComputeUtils(object): from already existing flavors Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: flavor_id(string): Flavor id for VDU instantiation None if no flavor could be found """ + + if vdu_params.vm_flavor.has_field('vm_flavor_name') and \ + vdu_params.vm_flavor.vm_flavor_name is not None: + nova_flavor_list = self.driver.nova_flavor_list() + for flavor in nova_flavor_list: + self.log.debug("Flavor {} ".format(flavor.get('name', ''))) + if flavor.get('name', '') == vdu_params.vm_flavor.vm_flavor_name: + return flavor['id'] + kwargs = { 'vcpus': vdu_params.vm_flavor.vcpu_count, 'ram' : vdu_params.vm_flavor.memory_mb, 'disk' : vdu_params.vm_flavor.storage_gb,} @@ -85,7 +94,7 @@ class ComputeUtils(object): is created. Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: flavor_id(string): Flavor id for VDU instantiation @@ -96,7 +105,7 @@ class ComputeUtils(object): flavor_id, vdu_params.name) return flavor_id - flavor = RwcalYang.FlavorInfoItem() + flavor = RwcalYang.YangData_RwProject_Project_VimResources_FlavorinfoList() flavor.name = str(uuid.uuid4()) epa_dict = { k: v for k, v in vdu_params.as_dict().items() @@ -115,7 +124,7 @@ class ComputeUtils(object): """ Creates flavor related arguments for VDU operation Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: A dictionary {'flavor_id': } @@ -127,7 +136,7 @@ class ComputeUtils(object): """ Creates image related arguments for VDU operation Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: A dictionary {'image_id': } @@ -173,11 +182,36 @@ class ComputeUtils(object): %(image_name, checksum)) return image['id'] + def resolve_volume_n_validate(self, volume_ref): + """ + Resolve the volume reference + + Arguments: + volume_ref (string): Name of volume reference + + Raises VolumeValidateError in case of Errors + """ + + for vol in self.driver._cinder_volume_list: + voldict = vol.to_dict() + if 'display_name' in voldict and voldict['display_name'] == volume_ref: + if 'status' in voldict: + if voldict['status'] == 'available': + return voldict['id'] + else: + self.log.error("Volume %s not in available state. Current state: %s", + volume_ref, voldict['status']) + raise VolumeValidateError("Volume with name %s found in incorrect (%s) state" + %(volume_ref, voldict['status'])) + + self.log.info("No volume found with matching name: %s ", volume_ref) + raise VolumeValidateError("No volume found with matching name: %s " %(volume_ref)) + def make_vdu_volume_args(self, volume, vdu_params): """ Arguments: - volume: Protobuf GI object RwcalYang.VDUInitParams_Volumes() - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + volume: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams_Volumes() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: A dictionary required to create volume for VDU @@ -186,23 +220,27 @@ class ComputeUtils(object): """ kwargs = dict() - if volume.has_field('volume_ref'): - self.log.error("Unsupported option found for volume: %s", volume.name) - raise VolumeValidateError("Unsupported option found for volume: %s" - %(volume.name)) - - kwargs['boot_index'] = volume.boot_priority + if 'boot_priority' in volume: + # Rift-only field + kwargs['boot_index'] = volume.boot_priority if volume.has_field("image"): # Support image->volume kwargs['source_type'] = "image" kwargs['uuid'] = self.resolve_image_n_validate(volume.image, volume.image_checksum) + kwargs['delete_on_termination'] = True + elif "volume_ref" in volume: + # Support volume-ref->volume (only ref) + # Rift-only field + kwargs['source_type'] = "volume" + kwargs['uuid'] = self.resolve_volume_n_validate(volume.volume_ref) + kwargs['delete_on_termination'] = False else: # Support blank->volume kwargs['source_type'] = "blank" + kwargs['delete_on_termination'] = True kwargs['device_name'] = volume.name kwargs['destination_type'] = "volume" kwargs['volume_size'] = volume.size - kwargs['delete_on_termination'] = True if volume.has_field('device_type'): if volume.device_type in ['cdrom', 'disk']: @@ -211,26 +249,16 @@ class ComputeUtils(object): self.log.error("Unsupported device_type <%s> found for volume: %s", volume.device_type, volume.name) raise VolumeValidateError("Unsupported device_type <%s> found for volume: %s" - %(volume.device_type, volume.name)) - else: - self.log.error("Mandatory field not specified for volume: %s", - volume.name) - raise VolumeValidateError("Mandatory field not specified for volume: %s" - %(volume.name)) + %(volume.device_type, volume.name)) if volume.has_field('device_bus'): if volume.device_bus in ['ide', 'virtio', 'scsi']: kwargs['disk_bus'] = volume.device_bus else: - self.log.error("Unsupported device_bus <%s> found for volume: %s", - volume.device_bus, volume.name) - raise VolumeValidateError("Unsupported device_bus <%s> found for volume: %s" - %(volume.device_bus, volume.name)) - else: - self.log.error("Mandatory field not specified for volume: %s", - volume.name) - raise VolumeValidateError("Mandatory field not specified for volume: %s" - %(volume.name)) + self.log.error("Unsupported device_type <%s> found for volume: %s", + volume.device_type, volume.name) + raise VolumeValidateError("Unsupported device_type <%s> found for volume: %s" + %(volume.device_type, volume.name)) return kwargs @@ -239,7 +267,7 @@ class ComputeUtils(object): Creates volume related arguments for VDU operation Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: A dictionary required for volumes creation for VDU instantiation @@ -247,17 +275,24 @@ class ComputeUtils(object): kwargs = dict() if vdu_params.has_field('volumes'): kwargs['block_device_mapping_v2'] = list() + bootvol_list = list() + othervol_list = list() # Ignore top-level image kwargs['image_id'] = "" for volume in vdu_params.volumes: - kwargs['block_device_mapping_v2'].append(self.make_vdu_volume_args(volume, vdu_params)) + if 'boot_priority' in volume: + bootvol_list.append(self.make_vdu_volume_args(volume, vdu_params)) + else: + othervol_list.append(self.make_vdu_volume_args(volume, vdu_params)) + # Sort block_device_mapping_v2 list by boot index, Openstack does not seem to respecting order by boot index + kwargs['block_device_mapping_v2'] = sorted(bootvol_list, key=lambda k: k['boot_index']) + othervol_list return kwargs def make_vdu_network_args(self, vdu_params): """ Creates VDU network related arguments for VDU operation Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: A dictionary {'port_list' : [ports], 'network_list': [networks]} @@ -265,6 +300,7 @@ class ComputeUtils(object): """ kwargs = dict() kwargs['port_list'], kwargs['network_list'] = self.driver.utils.network.setup_vdu_networking(vdu_params) + return kwargs @@ -272,7 +308,7 @@ class ComputeUtils(object): """ Creates VDU boot config related arguments for VDU operation Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: A dictionary { @@ -311,10 +347,13 @@ class ComputeUtils(object): try: # Rift model only if vdu_params.supplemental_boot_data.has_field('custom_meta_data'): - metadata = dict() for cm in vdu_params.supplemental_boot_data.custom_meta_data: - metadata[cm.name] = cm.value - kwargs['metadata'] = metadata + # Adding this condition as the list contains CLOUD_INIT Variables as + # well. CloudInit Variables such as password are visible on the OpenStack UI + # if not removed from the custom_meta_data list. + if cm.destination == 'CLOUD_METADATA': + metadata[cm.name] = cm.value + kwargs['metadata'] = metadata except Exception as e: pass @@ -342,7 +381,7 @@ class ComputeUtils(object): Function to create kwargs required for nova server placement Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() Returns: A dictionary { 'availability_zone' : < Zone >, 'scheduler_hints': } @@ -365,8 +404,8 @@ class ComputeUtils(object): Function to create kwargs required for nova security group Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() - account: Protobuf GI object RwcalYang.CloudAccount() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() + account: Protobuf GI object RwcalYang.YangData_RwProject_Project_CloudAccounts_CloudAccountList() Returns: A dictionary {'security_groups' : < group > } @@ -382,8 +421,8 @@ class ComputeUtils(object): Function to create kwargs required for nova_server_create API Arguments: - vdu_params: Protobuf GI object RwcalYang.VDUInitParams() - account: Protobuf GI object RwcalYang.CloudAccount() + vdu_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VduInitParams() + account: Protobuf GI object RwcalYang.YangData_RwProject_Project_CloudAccounts_CloudAccountList() Returns: A kwargs dictionary for VDU create operation @@ -423,6 +462,7 @@ class ComputeUtils(object): mgmt_ip = interface['addr'] elif interface['OS-EXT-IPS:type'] == 'floating': public_ip = interface['addr'] + return (mgmt_ip, public_ip) def get_vdu_epa_info(self, vm_info): @@ -448,7 +488,7 @@ class ComputeUtils(object): Arguments: vdu_id (string) : VDU Id (vm_info['id']) Returns: - A List of object RwcalYang.VDUInfoParams_ConnectionPoints() + A List of object RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList_ConnectionPoints() """ cp_list = [] @@ -456,7 +496,7 @@ class ComputeUtils(object): port_list = self.driver.neutron_port_list(**{'device_id': vdu_id}) for port in port_list: cp_info = self.driver.utils.network._parse_cp(port) - cp = RwcalYang.VDUInfoParams_ConnectionPoints() + cp = RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList_ConnectionPoints() cp.from_dict(cp_info.as_dict()) cp_list.append(cp) return cp_list @@ -507,18 +547,18 @@ class ComputeUtils(object): vm_info : A dictionary returned by novaclient library listing VM attributes Returns: - List of RwcalYang.VDUInfoParams_SupplementalBootData() + List of RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList_SupplementalBootData() """ supplemental_boot_data = None node_id = None if 'config_drive' in vm_info: - supplemental_boot_data = RwcalYang.VDUInfoParams_SupplementalBootData() + supplemental_boot_data = RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList_SupplementalBootData() supplemental_boot_data.boot_data_drive = vm_info['config_drive'] # Look for any metadata if 'metadata' not in vm_info: return node_id, supplemental_boot_data if supplemental_boot_data is None: - supplemental_boot_data = RwcalYang.VDUInfoParams_SupplementalBootData() + supplemental_boot_data = RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList_SupplementalBootData() for key, value in vm_info['metadata'].items(): if key == 'rift_node_id': node_id = value @@ -539,7 +579,7 @@ class ComputeUtils(object): vm_info : A dictionary returned by novaclient library listing VM attributes Returns: - List of RwcalYang.VDUInfoParams_Volumes() + List of RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList_Volumes() """ volumes = list() @@ -550,15 +590,21 @@ class ComputeUtils(object): return volumes for v in volume_list: - volume = RwcalYang.VDUInfoParams_Volumes() + volume = RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList_Volumes() try: volume.name = (v['device']).split('/')[2] volume.volume_id = v['volumeId'] details = self.driver.cinder_volume_get(volume.volume_id) - for k, v in details.metadata.items(): - vd = volume.custom_meta_data.add() - vd.name = k - vd.value = v + if details is None: + continue + try: + # Rift only + for k, v in details.metadata.items(): + vd = volume.custom_meta_data.add() + vd.name = k + vd.value = v + except Exception as e: + pass except Exception as e: self.log.exception("Exception %s occured during volume list parsing", str(e)) continue @@ -586,7 +632,7 @@ class ComputeUtils(object): except Exception as e: - self.log.exception("Exception %s occured during volume list parsing", str(e)) + self.log.warning("Exception %s occured during volume list parsing", str(e)) return console_url def parse_cloud_vdu_info(self, vm_info): @@ -597,16 +643,13 @@ class ComputeUtils(object): vm_info : A dictionary object return by novaclient library listing VM attributes Returns: - Protobuf GI Object of type RwcalYang.VDUInfoParams() + Protobuf GI Object of type RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList() """ - vdu = RwcalYang.VDUInfoParams() + vdu = RwcalYang.YangData_RwProject_Project_VnfResources_VduInfoList() vdu.name = vm_info['name'] vdu.vdu_id = vm_info['id'] vdu.cloud_type = 'openstack' - if 'config_drive' in vm_info: - vdu.supplemental_boot_data.boot_data_drive = vm_info['config_drive'] - if 'image' in vm_info and 'id' in vm_info['image']: vdu.image_id = vm_info['image']['id'] @@ -625,19 +668,24 @@ class ComputeUtils(object): if 'flavor' in vm_info and 'id' in vm_info['flavor']: vdu.flavor_id = vm_info['flavor']['id'] flavor_info = self.get_vdu_epa_info(vm_info) - vm_flavor = self.driver.utils.flavor.parse_vm_flavor_epa_info(flavor_info) - guest_epa = self.driver.utils.flavor.parse_guest_epa_info(flavor_info) - host_epa = self.driver.utils.flavor.parse_host_epa_info(flavor_info) - host_aggregates = self.driver.utils.flavor.parse_host_aggregate_epa_info(flavor_info) - - vdu.vm_flavor.from_dict(vm_flavor.as_dict()) - vdu.guest_epa.from_dict(guest_epa.as_dict()) - vdu.host_epa.from_dict(host_epa.as_dict()) - for aggr in host_aggregates: - ha = vdu.host_aggregate.add() - ha.from_dict(aggr.as_dict()) - - vdu.node_id, vdu.supplemental_boot_data = self._parse_vdu_boot_config_data(vm_info) + if flavor_info is not None: + vm_flavor = self.driver.utils.flavor.parse_vm_flavor_epa_info(flavor_info) + guest_epa = self.driver.utils.flavor.parse_guest_epa_info(flavor_info) + host_epa = self.driver.utils.flavor.parse_host_epa_info(flavor_info) + host_aggregates = self.driver.utils.flavor.parse_host_aggregate_epa_info(flavor_info) + + vdu.vm_flavor.from_dict(vm_flavor.as_dict()) + vdu.guest_epa.from_dict(guest_epa.as_dict()) + vdu.host_epa.from_dict(host_epa.as_dict()) + for aggr in host_aggregates: + ha = vdu.host_aggregate.add() + ha.from_dict(aggr.as_dict()) + + node_id, boot_data = self._parse_vdu_boot_config_data(vm_info) + if node_id: + vdu.node_id = node_id + if boot_data: + vdu.supplemental_boot_data = boot_data cp_list = self._parse_vdu_cp_info(vdu.vdu_id) for cp in cp_list: @@ -669,6 +717,5 @@ class ComputeUtils(object): port_list = self.driver.neutron_port_list(**{'device_id': vdu_id}) for port in port_list: - if ((port['device_owner'] == 'compute:None') or (port['device_owner'] == '')): - self.driver.neutron_port_delete(port['id']) + self.driver.neutron_port_delete(port['id'])