def test_create_volume_with_get_volume_illegal_object_name_exception(self, a_enter, get_volume, array_type): a_enter.return_value = self.mediator self.mediator.get_volume.side_effect = [array_errors.IllegalObjectName("vol")] context = utils.FakeContext() res = self.servicer.CreateVolume(self.request, context) msg = array_errors.IllegalObjectName("vol").message self.assertEqual(context.code, grpc.StatusCode.INVALID_ARGUMENT) self.assertTrue(msg in context.details) self.mediator.get_volume.assert_called_once_with(vol_name)
def _create_cli_volume(self, name, size_in_bytes, space_efficiency, pool): logger.info( "creating volume with name : {}. size : {} . in pool : {} with parameters : {}" .format(name, size_in_bytes, pool, space_efficiency)) try: size = self._convert_size_bytes(size_in_bytes) cli_kwargs = build_kwargs_from_parameters(space_efficiency, pool, name, size) self.client.svctask.mkvolume(**cli_kwargs) cli_volume = self._get_cli_volume(name) logger.info("finished creating cli volume : {}".format( cli_volume.name)) return cli_volume except (svc_errors.CommandExecutionError, CLIFailureError) as ex: if not is_warning_message(ex.my_message): logger.error(msg="Cannot create volume {0}, " "Reason is: {1}".format(name, ex)) if OBJ_ALREADY_EXIST in ex.my_message: raise array_errors.VolumeAlreadyExists(name, self.endpoint) if NAME_NOT_EXIST_OR_MEET_RULES in ex.my_message: raise array_errors.PoolDoesNotExist(pool, self.endpoint) if (POOL_NOT_MATCH_VOL_CAPABILITIES in ex.my_message or NOT_REDUCTION_POOL in ex.my_message): raise array_errors.PoolDoesNotMatchCapabilities( pool, space_efficiency, ex) if NOT_ENOUGH_EXTENTS_IN_POOL_CREATE in ex.my_message: raise array_errors.NotEnoughSpaceInPool(id_or_name=pool) if any(msg_id in ex.my_message for msg_id in (NON_ASCII_CHARS, INVALID_NAME, TOO_MANY_CHARS)): raise array_errors.IllegalObjectName(ex.my_message) raise ex except Exception as ex: logger.exception(ex) raise ex
def create_snapshot(self, name, volume_name, pool_id=None): logger.info("creating snapshot {0} from volume {1}".format( name, volume_name)) try: cli_snapshot = self.client.cmd.snapshot_create( name=name, vol=volume_name).as_single_element logger.info( "finished creating cli snapshot {0} from volume {1}".format( name, volume_name)) return self._generate_snapshot_response(cli_snapshot) except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise controller_errors.IllegalObjectName(ex.status) except xcli_errors.VolumeExistsError as ex: logger.exception(ex) raise controller_errors.SnapshotAlreadyExists(name, self.endpoint) except xcli_errors.VolumeBadNameError as ex: logger.exception(ex) raise controller_errors.ObjectNotFoundError(volume_name) except xcli_errors.OperationForbiddenForUserCategoryError as ex: logger.exception(ex) raise controller_errors.PermissionDeniedError( "create snapshot {0} from volume {1}".format( name, volume_name))
def create_volume(self, name, size_in_bytes, capabilities, pool): logger.info( "creating volume with name : {}. size : {} . in pool : {} with capabilities : {}" .format(name, size_in_bytes, pool, capabilities)) size_in_blocks = self._convert_size_bytes_to_blocks(size_in_bytes) try: cli_volume = self.client.cmd.vol_create( vol=name, size_blocks=size_in_blocks, pool=pool).as_single_element logger.info("finished creating cli volume : {}".format(cli_volume)) return self._generate_volume_response(cli_volume) except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise controller_errors.IllegalObjectName(ex.status) except xcli_errors.VolumeExistsError as ex: logger.exception(ex) raise controller_errors.VolumeAlreadyExists(name, self.endpoint) except xcli_errors.PoolDoesNotExistError as ex: logger.exception(ex) raise controller_errors.PoolDoesNotExist(pool, self.endpoint) except xcli_errors.OperationForbiddenForUserCategoryError as ex: logger.exception(ex) raise controller_errors.PermissionDeniedError( "create vol : {0}".format(name)) except xcli_errors.CommandFailedRuntimeError as ex: logger.exception(ex) if NO_ALLOCATION_SPACE_ERROR in ex.status: raise controller_errors.NotEnoughSpaceInPool(pool=pool)
def create_snapshot(self, volume_id, snapshot_name, pool=None): logger.info("creating snapshot {0} from volume {1}".format( snapshot_name, volume_id)) source_cli_volume = self._get_cli_object_by_wwn(volume_id) if pool and pool != source_cli_volume.pool_name: raise array_errors.SnapshotSourcePoolMismatch( snapshot_pool=pool, source_pool=source_cli_volume.pool_name) try: cli_snapshot = self.client.cmd.snapshot_create( name=snapshot_name, vol=source_cli_volume.name).as_single_element logger.info( "finished creating cli snapshot {0} from volume {1}".format( snapshot_name, volume_id)) return self._generate_snapshot_response(cli_snapshot) except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise array_errors.IllegalObjectName(ex.status) except xcli_errors.VolumeExistsError as ex: logger.exception(ex) raise array_errors.SnapshotAlreadyExists(snapshot_name, self.endpoint) except xcli_errors.VolumeBadNameError as ex: logger.exception(ex) raise array_errors.ObjectNotFoundError(volume_id) except xcli_errors.OperationForbiddenForUserCategoryError as ex: logger.exception(ex) raise array_errors.PermissionDeniedError( "create snapshot {0} from volume {1}".format( snapshot_name, volume_id))
def copy_to_existing_volume_from_snapshot(self, name, src_snap_name, src_snap_capacity_in_bytes, min_vol_size_in_bytes, pool=None): logger.debug( "Copy snapshot {0} data to volume {1}. Snapshot capacity {2}. Minimal requested volume capacity {3}".format( name, src_snap_name, src_snap_capacity_in_bytes, min_vol_size_in_bytes)) try: logger.debug("Formatting volume {0}".format(name)) self.client.cmd.vol_format(vol=name) logger.debug("Copying Snapshot {0} data to volume {1}.".format(name, src_snap_name)) self.client.cmd.vol_copy(vol_src=src_snap_name, vol_trg=name) if min_vol_size_in_bytes > src_snap_capacity_in_bytes: min_vol_size_in_blocks = self._convert_size_bytes_to_blocks(min_vol_size_in_bytes) logger.debug( "Increasing volume {0} size to {1} blocks.".format(name, min_vol_size_in_blocks)) self.client.cmd.vol_resize(vol=name, size_blocks=min_vol_size_in_blocks) except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise controller_errors.IllegalObjectName(ex.status) except xcli_errors.SourceVolumeBadNameError as ex: logger.exception(ex) raise controller_errors.SnapshotNotFoundError(src_snap_name) except (xcli_errors.VolumeBadNameError, xcli_errors.TargetVolumeBadNameError) as ex: logger.exception(ex) raise controller_errors.VolumeNotFoundError(name) except xcli_errors.OperationForbiddenForUserCategoryError as ex: logger.exception(ex) raise controller_errors.PermissionDeniedError("create vol : {0}".format(name))
def get_snapshot(self, snapshot_name, volume_context=None): logger.debug("Get snapshot : {}".format(snapshot_name)) try: cli_snapshot = self.client.cmd.vol_list(vol=snapshot_name).as_single_element except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise controller_errors.IllegalObjectName(ex.status) if not cli_snapshot: return None if not cli_snapshot.master_name: raise controller_errors.SnapshotNameBelongsToVolumeError(cli_snapshot.name, self.endpoint) array_snapshot = self._generate_snapshot_response(cli_snapshot) return array_snapshot
def get_volume(self, vol_name): logger.debug("Get volume : {}".format(vol_name)) try: cli_volume = self.client.cmd.vol_list( vol=vol_name).as_single_element except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise controller_errors.IllegalObjectName(ex.status) logger.debug("cli volume returned : {}".format(cli_volume)) if not cli_volume: raise controller_errors.VolumeNotFoundError(vol_name) array_vol = self._generate_volume_response(cli_volume) return array_vol
def _get_object_name_and_prefix(self, request, max_name_prefix_length, max_name_length, object_type, prefix_param_name): full_name = name = request.name prefix = "" if request.parameters and (prefix_param_name in request.parameters): prefix = request.parameters[prefix_param_name] if len(prefix) > max_name_prefix_length: raise controller_errors.IllegalObjectName( "The {} name prefix '{}' is too long, max allowed length is {}" .format(object_type, prefix, max_name_prefix_length)) full_name = self._join_object_prefix_with_name(prefix, name) if len(full_name) > max_name_length: hashed_name = utils.hash_string(name) full_name = self._join_object_prefix_with_name(prefix, hashed_name) return full_name[:max_name_length], prefix
def _get_object_final_name(self, volume_parameters, name, array_mediator, object_type): prefix = "" if volume_parameters.prefix: prefix = volume_parameters.prefix if len(prefix) > array_mediator.max_object_prefix_length: raise array_errors.IllegalObjectName( "The {} name prefix '{}' is too long, max allowed length is {}" .format(object_type, prefix, array_mediator.max_object_prefix_length)) if not prefix: prefix = array_mediator.default_object_prefix full_name = self._join_object_prefix_with_name(prefix, name) if len(full_name) > array_mediator.max_object_name_length: hashed_name = utils.hash_string(name) full_name = self._join_object_prefix_with_name(prefix, hashed_name) return full_name[:array_mediator.max_object_name_length]
def get_volume(self, volume_name, volume_context=None, volume_prefix=""): logger.debug("Get volume : {}".format(volume_name)) try: cli_volume = self.client.cmd.vol_list(vol=volume_name).as_single_element except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise controller_errors.IllegalObjectName(ex.status) logger.debug("cli volume returned : {}".format(cli_volume)) if not cli_volume: raise controller_errors.VolumeNotFoundError(volume_name) if cli_volume.master_name: raise controller_errors.VolumeNameBelongsToSnapshotError(volume_name, self.endpoint) array_vol = self._generate_volume_response(cli_volume) return array_vol
def _get_cli_volume(self, volume_name, not_exist_err=True): try: cli_volume = self.client.svcinfo.lsvdisk( bytes=True, object_id=volume_name).as_single_element if not cli_volume and not_exist_err: raise array_errors.ObjectNotFoundError(volume_name) return cli_volume except (svc_errors.CommandExecutionError, CLIFailureError) as ex: if not is_warning_message(ex.my_message): if (OBJ_NOT_FOUND in ex.my_message or NAME_NOT_EXIST_OR_MEET_RULES in ex.my_message): logger.info("volume not found") if not_exist_err: raise array_errors.ObjectNotFoundError(volume_name) if any(msg_id in ex.my_message for msg_id in (NON_ASCII_CHARS, VALUE_TOO_LONG)): raise array_errors.IllegalObjectName(ex.my_message) except Exception as ex: logger.exception(ex) raise ex
def test_create_volume_with_illegal_object_name_exception(self): self.create_volume_returns_error( return_code=grpc.StatusCode.INVALID_ARGUMENT, err=array_errors.IllegalObjectName("vol"))
def CreateVolume(self, request, context): set_current_thread_name(request.name) logger.info("create volume") try: utils.validate_create_volume_request(request) except ValidationException as ex: logger.error("failed request validation") logger.exception(ex) context.set_details(ex.message) context.set_code(grpc.StatusCode.INVALID_ARGUMENT) return csi_pb2.CreateVolumeResponse() volume_name = request.name logger.debug("volume name : {}".format(volume_name)) if config.PARAMETERS_PREFIX in request.parameters: volume_prefix = request.parameters[config.PARAMETERS_PREFIX] volume_full_name = volume_prefix + settings.NAME_PREFIX_SEPARATOR + volume_name else: volume_prefix = "" volume_full_name = volume_name secrets = request.secrets user, password, array_addresses = utils.get_array_connection_info_from_secret( secrets) pool = request.parameters[config.PARAMETERS_POOL] capabilities = { key: value for key, value in request.parameters.items() if key in [ config.PARAMETERS_CAPABILITIES_SPACEEFFICIENCY, ] } try: # TODO : pass multiple array addresses with ArrayConnectionManager(user, password, array_addresses) as array_mediator: logger.debug(array_mediator) if len(volume_prefix ) > array_mediator.max_volume_prefix_length: raise controller_errors.IllegalObjectName( "The volume name prefix {} is too long, max allowed length is {}" .format( volume_prefix, array_mediator.max_volume_prefix_length, )) if len(volume_full_name) > array_mediator.max_vol_name_length: raise controller_errors.IllegalObjectName( "The volume name {} is too long, max allowed length is {}" .format( volume_full_name, array_mediator.max_vol_name_length, )) size = request.capacity_range.required_bytes if size == 0: size = array_mediator.minimal_volume_size_in_bytes logger.debug( "requested size is 0 so the default size will be used : {0} " .format(size)) try: vol = array_mediator.get_volume( volume_full_name, volume_context=request.parameters, volume_prefix=volume_prefix, ) except controller_errors.VolumeNotFoundError as ex: logger.debug( "volume was not found. creating a new volume with parameters: {0}" .format(request.parameters)) array_mediator.validate_supported_capabilities( capabilities) vol = array_mediator.create_volume(volume_full_name, size, capabilities, pool, volume_prefix) else: logger.debug("volume found : {}".format(vol)) if not (vol.capacity_bytes == request.capacity_range.required_bytes): context.set_details( "Volume was already created with different size.") context.set_code(grpc.StatusCode.ALREADY_EXISTS) return csi_pb2.CreateVolumeResponse() logger.debug("generating create volume response") res = utils.generate_csi_create_volume_response(vol) logger.info("finished create volume") return res except (controller_errors.IllegalObjectName, controller_errors.StorageClassCapabilityNotSupported, controller_errors.PoolDoesNotExist, controller_errors.PoolDoesNotMatchCapabilities) as ex: context.set_details(ex.message) context.set_code(grpc.StatusCode.INVALID_ARGUMENT) return csi_pb2.CreateVolumeResponse() except controller_errors.PermissionDeniedError as ex: context.set_code(grpc.StatusCode.PERMISSION_DENIED) context.set_details(ex) return csi_pb2.CreateVolumeResponse() except controller_errors.VolumeAlreadyExists as ex: context.set_details(ex.message) context.set_code(grpc.StatusCode.ALREADY_EXISTS) return csi_pb2.CreateVolumeResponse() except Exception as ex: logger.error("an internal exception occurred") logger.exception(ex) context.set_code(grpc.StatusCode.INTERNAL) context.set_details( 'an internal exception occurred : {}'.format(ex)) return csi_pb2.CreateVolumeResponse()
def get_volume_name(self, volume_id): try: return self._get_object_name_by_wwn(volume_id) except xcli_errors.IllegalNameForObjectError as ex: logger.exception(ex) raise controller_errors.IllegalObjectName(ex.status)