def CreateVolume(self, request, context): request_uuid = str(uuid.uuid4())[:8] Utils.validate_param_exists(request, 'name') request_name = request.name nvmesh_vol_name = Utils.volume_id_to_nvmesh_name(request_name) log = self.logger.getChild("CreateVolume:%s(request:%s)" % (request_name, request_uuid)) volume_cache = self.volume_to_zone_mapping.get_or_create_new( nvmesh_vol_name) if volume_cache.lock.locked(): log.debug( "volume already has a request in a progress, waiting for lock to be released" ) with volume_cache.lock: log.debug("processing request") if volume_cache.csi_volume: if volume_cache.csi_volume.capacity_bytes != self._parse_required_capacity( request.capacity_range): raise DriverError( StatusCode.FAILED_PRECONDITION, 'Volume already exists with different capacity') log.info('Returning volume from cache') return CreateVolumeResponse(volume=volume_cache.csi_volume) csiVolume = self.do_create_volume(log, nvmesh_vol_name, request) volume_cache.csi_volume = csiVolume return CreateVolumeResponse(volume=csiVolume)
def DeleteVolume(self, request, context): Utils.validate_param_exists(request, 'volume_id') volume_id = request.volume_id log = self.logger.getChild("DeleteVolume-%s" % volume_id) log.debug('delete called') zone, nvmesh_vol_name = Utils.zone_and_vol_name_from_co_id(volume_id) #secrets = request.secrets volume_api = VolumeAPIPool.get_volume_api_for_zone(zone, log) err, out = volume_api.delete([NVMeshVolume(_id=nvmesh_vol_name)]) if err: log.error(err) raise DriverError(StatusCode.INTERNAL, err) log.debug(out) if not out[0]['success']: err = out[0]['error'] if err == "Couldn't find the specified volume" or err.startswith( "Failed to find marked volume"): # Idempotency - Trying to remove a Volume that doesn't exists, perhaps already deleted # should return success log.debug("Volume already deleted") pass else: raise DriverError(StatusCode.FAILED_PRECONDITION, err) else: log.debug("Volume deleted successfully from zone %s" % zone) self.volume_to_zone_mapping.remove(nvmesh_vol_name) return DeleteVolumeResponse()
def DeleteVolume(self, request, context): Utils.validate_param_exists(request, 'volume_id') volume_id = request.volume_id nvmesh_vol_name = volume_id #secrets = request.secrets err, out = VolumeAPI().delete([NVMeshVolume(_id=nvmesh_vol_name)]) if err: self.logger.error(err) raise DriverError(StatusCode.INTERNAL, err) self.logger.debug(out) if not out[0]['success']: err = out[0]['error'] if err == "Couldn't find the specified volume": # Idempotency - Trying to remove a Volume that doesn't exists, perhaps already deleted # should return success pass else: raise DriverError(StatusCode.FAILED_PRECONDITION, err) return DeleteVolumeResponse()
def CreateVolume(self, request, context): Utils.validate_param_exists(request, 'name') name = request.name capacity = self._parse_required_capacity(request.capacity_range) parameters = request.parameters #UNUSED - secrets = request.secrets #UNUSED - volume_content_source = request.volume_content_source #UNUSED - accessibility_requirements = request.accessibility_requirements reqJson = MessageToJson(request) self.logger.debug('create volume request: {}'.format(reqJson)) reqDict = MessageToDict(request) capabilities = reqDict['volumeCapabilities'] is_file_system = False is_block_device = False csi_metadata = {'csi_name': name, 'capabilities': capabilities} for capability in capabilities: if 'mount' in capability: is_file_system = True csi_metadata['fsType'] = capability['mount']['fsType'] else: csi_metadata['block'] = True access_mode = capability['accessMode']['mode'] if Consts.AccessMode.fromCsiString( access_mode) not in Consts.AccessMode.allowed_access_modes( ): self.logger.warning( 'Requested mode {} is not enforced by NVMesh Storage backend' .format(access_mode)) if is_file_system and is_block_device: raise DriverError( StatusCode.INVALID_ARGUMENT, 'Error: Contradicting capabilities both Block Volume and FileSystem Volume were requested for volume {}. request: {}' .format(name, reqJson)) nvmesh_vol_name = Utils.volume_id_to_nvmesh_name(name) nvmesh_params = {} self.logger.debug('create volume parameters: {}'.format(parameters)) if 'vpg' in parameters: self.logger.debug('Creating Volume from VPG {}'.format( parameters['vpg'])) nvmesh_params['VPG'] = parameters['vpg'] # This is a workaround since the nvmesh create volume api expects a 'RAIDLevel' # but if 'VPG' is present 'RAIDLevel' field will be ignored # and the RAIDLevel will be fetched from the VPG. nvmesh_params['RAIDLevel'] = RAIDLevels.CONCATENATED else: self.logger.debug('Creating without VPG') for param in parameters: nvmesh_params[param] = parameters[param] self._handle_non_vpg_params(nvmesh_params) self.logger.debug('nvmesh_params = {}'.format(nvmesh_params)) volume = NVMeshVolume(name=nvmesh_vol_name, capacity=capacity, csi_metadata=csi_metadata, **nvmesh_params) self.logger.debug('Creating volume: {}'.format(str(volume))) err, data = VolumeAPI().save([volume]) if err: raise DriverError( StatusCode.RESOURCE_EXHAUSTED, 'Error: {} Details: {} Volume Requested: {}'.format( err, data, str(volume))) elif not type(data) == list or not data[0]['success']: if 'Name already Exists' in data[0]['error']: existing_capacity = self._get_nvmesh_volume_capacity( nvmesh_vol_name) if capacity == existing_capacity: # Idempotency - same Name same Capacity - return success pass else: raise DriverError( StatusCode.ALREADY_EXISTS, 'Error: {} Details: {}'.format(err, data)) else: raise DriverError(StatusCode.RESOURCE_EXHAUSTED, 'Error: {} Details: {}'.format(err, data)) err, details = self._wait_for_volume_status( volume._id, NVMeshConsts.VolumeStatuses.ONLINE) if err: if err == 'Timed out Waiting for Volume to be Online': raise DriverError(StatusCode.FAILED_PRECONDITION, 'Error: {} Details: {}'.format(err, details)) else: raise DriverError(StatusCode.INVALID_ARGUMENT, err) else: self.logger.debug(details) # we return the nvmesh_vol_name that we created to the CO # all subsequent requests for this volume will have volume_id of the nvmesh volume name csiVolume = Volume(volume_id=nvmesh_vol_name, capacity_bytes=capacity) return CreateVolumeResponse(volume=csiVolume)