def test_get_qos_policy_group_name_from_spec_info(self): expected = 'openstack-%s' % fake.VOLUME_ID result = na_utils.get_qos_policy_group_name_from_info( fake.QOS_POLICY_GROUP_INFO) self.assertEqual(expected, result)
def test_get_qos_policy_group_name_from_legacy_info(self): expected = fake.QOS_POLICY_GROUP_NAME result = na_utils.get_qos_policy_group_name_from_info( fake.LEGACY_QOS_POLICY_GROUP_INFO) self.assertEqual(expected, result)
def manage_existing(self, volume, existing_ref): """Brings an existing storage object under Cinder management. existing_ref can contain source-id or source-name or both. source-id: lun uuid. source-name: complete lun path eg. /vol/vol0/lun. """ lun = self._get_existing_vol_with_manage_ref(existing_ref) extra_specs = na_utils.get_volume_extra_specs(volume) self._check_volume_type_for_lun(volume, lun, existing_ref, extra_specs) qos_policy_group_info = self._setup_qos_for_volume(volume, extra_specs) qos_policy_group_name = na_utils.get_qos_policy_group_name_from_info(qos_policy_group_info) path = lun.get_metadata_property("Path") if lun.name == volume["name"]: new_path = path LOG.info(_LI("LUN with given ref %s need not be renamed " "during manage operation."), existing_ref) else: (rest, splitter, name) = path.rpartition("/") new_path = "%s/%s" % (rest, volume["name"]) self.zapi_client.move_lun(path, new_path) lun = self._get_existing_vol_with_manage_ref({"source-name": new_path}) if qos_policy_group_name is not None: self.zapi_client.set_lun_qos_policy_group(new_path, qos_policy_group_name) self._add_lun_to_table(lun) LOG.info( _LI("Manage operation completed for LUN with new path" " %(path)s and uuid %(uuid)s."), {"path": lun.get_metadata_property("Path"), "uuid": lun.get_metadata_property("UUID")}, )
def test_get_qos_policy_group_name_from_none_qos_info(self): expected = None result = na_utils.get_qos_policy_group_name_from_info( fake.QOS_POLICY_GROUP_INFO_NONE) self.assertEqual(expected, result)
def _set_qos_policy_group_on_volume(self, volume, qos_policy_group_info): if qos_policy_group_info is None: return qos_policy_group_name = na_utils.get_qos_policy_group_name_from_info(qos_policy_group_info) if qos_policy_group_name is None: return target_path = "%s" % (volume["name"]) share = volume_utils.extract_host(volume["host"], level="pool") export_path = share.split(":")[1] flex_vol_name = self.zapi_client.get_vol_by_junc_vserver(self.vserver, export_path) self.zapi_client.file_assign_qos(flex_vol_name, qos_policy_group_name, target_path)
def create_volume(self, volume): """Driver entry point for creating a new volume (Data ONTAP LUN).""" LOG.debug('create_volume on %s', volume['host']) # get Data ONTAP volume name as pool name pool_name = volume_utils.extract_host(volume['host'], level='pool') if pool_name is None: msg = _("Pool is not available in the volume host field.") raise exception.InvalidHost(reason=msg) extra_specs = na_utils.get_volume_extra_specs(volume) lun_name = volume['name'] size = int(volume['size']) * units.Gi metadata = {'OsType': self.lun_ostype, 'SpaceReserved': self.lun_space_reservation, 'Path': '/vol/%s/%s' % (pool_name, lun_name)} qos_policy_group_info = self._setup_qos_for_volume(volume, extra_specs) qos_policy_group_name = ( na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info)) try: self._create_lun(pool_name, lun_name, size, metadata, qos_policy_group_name) except Exception: LOG.exception(_LE("Exception creating LUN %(name)s in pool " "%(pool)s."), {'name': lun_name, 'pool': pool_name}) self._mark_qos_policy_group_for_deletion(qos_policy_group_info) msg = _("Volume %s could not be created.") raise exception.VolumeBackendAPIException(data=msg % ( volume['name'])) LOG.debug('Created LUN with name %(name)s and QoS info %(qos)s', {'name': lun_name, 'qos': qos_policy_group_info}) metadata['Path'] = '/vol/%s/%s' % (pool_name, lun_name) metadata['Volume'] = pool_name metadata['Qtree'] = None handle = self._create_lun_handle(metadata) self._add_lun_to_table(NetAppLun(handle, lun_name, size, metadata)) model_update = self._get_volume_model_update(volume) return model_update
def _set_qos_policy_group_on_volume(self, volume, qos_policy_group_info): if qos_policy_group_info is None: return qos_policy_group_name = na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info) if qos_policy_group_name is None: return target_path = '%s' % (volume['name']) share = volume_utils.extract_host(volume['host'], level='pool') __, export_path = na_utils.get_export_host_junction_path(share) flex_vol_name = self.zapi_client.get_vol_by_junc_vserver(self.vserver, export_path) self.zapi_client.file_assign_qos(flex_vol_name, qos_policy_group_name, target_path)
def create_volume(self, volume): """Driver entry point for creating a new volume (Data ONTAP LUN).""" LOG.debug('create_volume on %s', volume['host']) # get Data ONTAP volume name as pool name pool_name = volume_utils.extract_host(volume['host'], level='pool') if pool_name is None: msg = _("Pool is not available in the volume host field.") raise exception.InvalidHost(reason=msg) extra_specs = na_utils.get_volume_extra_specs(volume) lun_name = volume['name'] size = int(volume['size']) * units.Gi metadata = {'OsType': self.lun_ostype, 'SpaceReserved': 'true', 'Path': '/vol/%s/%s' % (pool_name, lun_name)} qos_policy_group_info = self._setup_qos_for_volume(volume, extra_specs) qos_policy_group_name = ( na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info)) try: self._create_lun(pool_name, lun_name, size, metadata, qos_policy_group_name) except Exception: LOG.exception(_LE("Exception creating LUN %(name)s in pool " "%(pool)s."), {'name': lun_name, 'pool': pool_name}) self._mark_qos_policy_group_for_deletion(qos_policy_group_info) msg = _("Volume %s could not be created.") raise exception.VolumeBackendAPIException(data=msg % ( volume['name'])) LOG.debug('Created LUN with name %(name)s and QoS info %(qos)s', {'name': lun_name, 'qos': qos_policy_group_info}) metadata['Path'] = '/vol/%s/%s' % (pool_name, lun_name) metadata['Volume'] = pool_name metadata['Qtree'] = None handle = self._create_lun_handle(metadata) self._add_lun_to_table(NetAppLun(handle, lun_name, size, metadata))
def create_volume(self, volume): """Driver entry point for creating a new volume (Data ONTAP LUN).""" LOG.debug("create_volume on %s", volume["host"]) # get Data ONTAP volume name as pool name pool_name = volume_utils.extract_host(volume["host"], level="pool") if pool_name is None: msg = _("Pool is not available in the volume host field.") raise exception.InvalidHost(reason=msg) extra_specs = na_utils.get_volume_extra_specs(volume) lun_name = volume["name"] size = int(volume["size"]) * units.Gi metadata = { "OsType": self.lun_ostype, "SpaceReserved": self.lun_space_reservation, "Path": "/vol/%s/%s" % (pool_name, lun_name), } qos_policy_group_info = self._setup_qos_for_volume(volume, extra_specs) qos_policy_group_name = na_utils.get_qos_policy_group_name_from_info(qos_policy_group_info) try: self._create_lun(pool_name, lun_name, size, metadata, qos_policy_group_name) except Exception: LOG.exception( _LE("Exception creating LUN %(name)s in pool " "%(pool)s."), {"name": lun_name, "pool": pool_name} ) self._mark_qos_policy_group_for_deletion(qos_policy_group_info) msg = _("Volume %s could not be created.") raise exception.VolumeBackendAPIException(data=msg % (volume["name"])) LOG.debug( "Created LUN with name %(name)s and QoS info %(qos)s", {"name": lun_name, "qos": qos_policy_group_info} ) metadata["Path"] = "/vol/%s/%s" % (pool_name, lun_name) metadata["Volume"] = pool_name metadata["Qtree"] = None handle = self._create_lun_handle(metadata) self._add_lun_to_table(NetAppLun(handle, lun_name, size, metadata))
def _clone_source_to_destination(self, source, destination_volume): source_size = source['size'] destination_size = destination_volume['size'] source_name = source['name'] destination_name = destination_volume['name'] extra_specs = na_utils.get_volume_extra_specs(destination_volume) qos_policy_group_info = self._setup_qos_for_volume( destination_volume, extra_specs) qos_policy_group_name = (na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info)) try: self._clone_lun(source_name, destination_name, space_reserved=self.lun_space_reservation, qos_policy_group_name=qos_policy_group_name) if destination_size != source_size: try: self._extend_volume(destination_volume, destination_size, qos_policy_group_name) except Exception: with excutils.save_and_reraise_exception(): LOG.error("Resizing %s failed. Cleaning volume.", destination_volume['id']) self.delete_volume(destination_volume) return self._get_volume_model_update(destination_volume) except Exception: LOG.exception( "Exception cloning volume %(name)s from source " "volume %(source)s.", { 'name': destination_name, 'source': source_name }) self._mark_qos_policy_group_for_deletion(qos_policy_group_info) msg = _("Volume %s could not be created from source volume.") raise exception.VolumeBackendAPIException(data=msg % destination_name)
def _clone_source_to_destination(self, source, destination_volume): source_size = source['size'] destination_size = destination_volume['size'] source_name = source['name'] destination_name = destination_volume['name'] extra_specs = na_utils.get_volume_extra_specs(destination_volume) qos_policy_group_info = self._setup_qos_for_volume( destination_volume, extra_specs) qos_policy_group_name = ( na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info)) try: self._clone_lun(source_name, destination_name, space_reserved=self.lun_space_reservation, qos_policy_group_name=qos_policy_group_name) if destination_size != source_size: try: self._extend_volume(destination_volume, destination_size, qos_policy_group_name) except Exception: with excutils.save_and_reraise_exception(): LOG.error( _LE("Resizing %s failed. Cleaning volume."), destination_volume['id']) self.delete_volume(destination_volume) return self._get_volume_model_update(destination_volume) except Exception: LOG.exception(_LE("Exception cloning volume %(name)s from source " "volume %(source)s."), {'name': destination_name, 'source': source_name}) self._mark_qos_policy_group_for_deletion(qos_policy_group_info) msg = _("Volume %s could not be created from source volume.") raise exception.VolumeBackendAPIException( data=msg % destination_name)
def manage_existing(self, volume, existing_ref): """Brings an existing storage object under Cinder management. existing_ref can contain source-id or source-name or both. source-id: lun uuid. source-name: complete lun path eg. /vol/vol0/lun. """ lun = self._get_existing_vol_with_manage_ref(existing_ref) extra_specs = na_utils.get_volume_extra_specs(volume) self._check_volume_type_for_lun(volume, lun, existing_ref, extra_specs) qos_policy_group_info = self._setup_qos_for_volume(volume, extra_specs) qos_policy_group_name = (na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info)) is_adaptive = na_utils.is_qos_policy_group_spec_adaptive( qos_policy_group_info) path = lun.get_metadata_property('Path') if lun.name == volume['name']: new_path = path LOG.info( "LUN with given ref %s need not be renamed " "during manage operation.", existing_ref) else: (rest, splitter, name) = path.rpartition('/') new_path = '%s/%s' % (rest, volume['name']) self.zapi_client.move_lun(path, new_path) lun = self._get_existing_vol_with_manage_ref( {'source-name': new_path}) if qos_policy_group_name is not None: self.zapi_client.set_lun_qos_policy_group(new_path, qos_policy_group_name, is_adaptive) self._add_lun_to_table(lun) LOG.info( "Manage operation completed for LUN with new path" " %(path)s and uuid %(uuid)s.", { 'path': lun.get_metadata_property('Path'), 'uuid': lun.get_metadata_property('UUID') }) return self._get_volume_model_update(volume)
def extend_volume(self, volume, new_size): """Driver entry point to increase the size of a volume.""" extra_specs = na_utils.get_volume_extra_specs(volume) # Create volume copy with new size for size-dependent QOS specs volume_copy = copy.copy(volume) volume_copy['size'] = new_size qos_policy_group_info = self._setup_qos_for_volume( volume_copy, extra_specs) qos_policy_group_name = (na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info)) try: self._extend_volume(volume, new_size, qos_policy_group_name) except Exception: with excutils.save_and_reraise_exception(): # If anything went wrong, revert QoS settings self._setup_qos_for_volume(volume, extra_specs)
def extend_volume(self, volume, new_size): """Driver entry point to increase the size of a volume.""" extra_specs = na_utils.get_volume_extra_specs(volume) # Create volume copy with new size for size-dependent QOS specs volume_copy = copy.copy(volume) volume_copy['size'] = new_size qos_policy_group_info = self._setup_qos_for_volume(volume_copy, extra_specs) qos_policy_group_name = ( na_utils.get_qos_policy_group_name_from_info( qos_policy_group_info)) try: self._extend_volume(volume, new_size, qos_policy_group_name) except Exception: with excutils.save_and_reraise_exception(): # If anything went wrong, revert QoS settings self._setup_qos_for_volume(volume, extra_specs)
def test_get_qos_policy_group_name_from_info_no_info(self): result = na_utils.get_qos_policy_group_name_from_info(None) self.assertIsNone(result)
def test_get_qos_policy_group_name_from_info(self): expected = 'openstack-%s' % fake.VOLUME_ID result = na_utils.get_qos_policy_group_name_from_info( fake.QOS_POLICY_GROUP_INFO) self.assertEqual(expected, result)