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)
Exemple #2
0
 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)
Exemple #5
0
 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
Exemple #8
0
    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
Exemple #12
0
 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)