def _get_vol_details(self, blockdevice_id): """ :param blockdevice_id - volume id :return:volume details :exception: Unknown volume """ # Need to query storage_instance to find attached initiators if not self._known(blockdevice_id): raise UnknownVolume(blockdevice_id) try: ai_name = self._vols[blockdevice_id]['ai_name'] si = get_datera_storageinst(self._api, ai_name) if len(si['active_initiators']) == 0: self._vols[blockdevice_id]['attached_to'] = None elif len(si['active_initiators']) == 1: self._vols[blockdevice_id]['attached_to'] = \ si['active_initiators'] else: raise DeviceExceptionAPIError(blockdevice_id) volume = self._vols[blockdevice_id]['volume'] return volume except DeviceExceptionObjNotFound as exc: raise UnknownVolume(blockdevice_id)
def validateVolume(self, blockdevice_id): try: vol = self._qsclient.get_volume(blockdevice_id) volName = vol._name if volName.find("flockerVol-") != 0: raise UnknownVolume(blockdevice_id) return vol except Exception as e: raise UnknownVolume(blockdevice_id)
def _get(self, blockdevice_id): """ :param blockdevice_id: - volume id :return:volume object """ try: volume = self.volume_list[str(blockdevice_id)] if volume is not None: return volume else: raise UnknownVolume(blockdevice_id) except: raise UnknownVolume(blockdevice_id)
def _get(self, blockdevice_id): for volume in self.list_volumes(): if volume.blockdevice_id == blockdevice_id: return volume Message.new(Error="Could Not Find Volume " + str(blockdevice_id)).write(_logger) raise UnknownVolume(blockdevice_id)
def detach_volume(self, blockdevice_id): """ Detach ``blockdevice_id`` from whatever host it is attached to. :param unicode blockdevice_id: The unique identifier for the block device being detached. :raises UnknownVolume: If the supplied ``blockdevice_id`` does not exist. :raises UnattachedVolume: If the supplied ``blockdevice_id`` is not attached to anything. :returns: ``None`` """ (target_disk, role_name, lun) = \ self._get_disk_vmname_lun(blockdevice_id) if target_disk is None: raise UnknownVolume(blockdevice_id) if lun is None: raise UnattachedVolume(blockdevice_id) # contrary to function name it doesn't delete by default, just detachs request = \ self._azure_service_client.delete_data_disk( service_name=self._service_name, deployment_name=self._service_name, role_name=role_name, lun=lun) self._wait_for_async(request.request_id, 5000) self._wait_for_detach(blockdevice_id)
def detach_volume(self, blockdevice_id): """ Detach ``blockdevice_id`` from whatever host it is attached to. :param unicode blockdevice_id: The unique identifier for the block device being detached. """ LOG.debug("Call detach_volume blockdevice_id=%s" % blockdevice_id) if not self.rest.is_lun(self.Pool, blockdevice_id): raise UnknownVolume(blockdevice_id) target_name = '{}{}.{}'.format(self.jovian_target_prefix, blockdevice_id, self._compute_instance_id) jcom.iscsiadm_logout_target(target_name, self.host, self.target_port) if not self.rest.is_target(self.Pool, target_name): raise UnattachedVolume(blockdevice_id) elif not self.rest.is_target_lun(self.Pool, target_name, blockdevice_id): self.rest.delete_target(self.Pool, target_name) raise UnattachedVolume(blockdevice_id) self.rest.detach_target_vol(self.Pool, target_name, blockdevice_id) self.rest.delete_target(self.Pool, target_name) jcom.rm_local_dir('/flocker/{}/'.format(blockdevice_id))
def destroy_volume(self, blockdevice_id): """ Destroy an existing volume. :param blockdevice_id: WWID in the reduxio :return: None """ logger.info('Destroying the volume with blockdevice id {} .'.format(blockdevice_id)) try: volume_info = self.find_volume_by_blockdevice_id(blockdevice_id) volume_name = volume_info[u'name'] logger.debug('Name of the Volume found is {} .'.format(volume_name)) except Exception as e: logger.error( "Unable to find the volume with the provided blockdevice_id {} .".format(blockdevice_id)) logger.error('Exception: ' + str(e)) raise UnknownVolume(e) try: logger.debug("Checking if the volume {} is attached to any node/s.".format(volume_name)) assignment_list = self._rdxapi.list_assignments(vol=volume_name) if (len(assignment_list) > 0): logger.error("Volume {} is attached to a node, so it cannot be destroyed.".format(volume_name)) raise VolumeAttached(blockdevice_id) # volume_name = self._rdxhelper._volume_name_from_id(str(dataset_id)) logger.debug("Trying to delete the volume {} .".format(volume_name)) self._rdxapi.delete_volume(name=volume_name) logger.info("Volume {} deleted successfully.".format(volume_name)) except Exception as e: logger.error("Destroy Volume {} failed.".format(volume_name)) logger.error('Exception: ' + str(e)) raise VolumeDestroyFailure(e)
def detach_volume(self, blockdevice_id): """ Detach ``blockdevice_id`` from whatever host it is attached to. :param blockdevice_id: The unique identifier for the block device being detached. :return: `None`` """ logger.info('detaching Volume with blockdevice id {} .'.format(blockdevice_id)) try: volumeinfo = self.find_volume_by_blockdevice_id(blockdevice_id) volume_name = volumeinfo[u'name'] logger.debug('Found the volume, volume name is {} .'.format(volume_name)) except Exception as e: logger.error('An error occurred finding the volume {} .'.format(blockdevice_id)) logger.error('Exception: ' + str(e)) raise UnknownVolume(e) try: assignmentlist = self.get_assignments_of_volume(blockdevice_id, volume_name) paths = find_paths(blockdevice_id) for path in paths: remove_device(path) logger.info("Revoking all hosts assigned to volume {} .".format(volume_name)) for assignment in assignmentlist: logger.debug("Revoking {} .".format(volume_name)) self._rdxapi.unassign(vol_name=volume_name, host_name=assignment[u'host']) rescan_iscsi_session() logger.debug("Volume {} successfully detached.".format(blockdevice_id)) except Exception as ex: logger.error('An error occurred while detaching volume {} .'.format(blockdevice_id)) logger.error('Exception: ' + str(ex)) raise Exception(ex)
def get_device_path(self, blockdevice_id): """ :param blockdevice_id: :return:the device path """ # Query LunID from XtremIO lunid = self.data.get_lun_map(blockdevice_id) output = check_output([b"/usr/bin/lsscsi"]) # lsscsi gives output in the following form: # [0:0:0:0] disk ATA ST91000640NS SN03 /dev/sdp # [1:0:0:0] disk DGC LUNZ 0532 /dev/sdb # [1:0:1:0] disk DGC LUNZ 0532 /dev/sdc # [8:0:0:0] disk MSFT Virtual HD 6.3 /dev/sdd # [9:0:0:0] disk XtremIO XtremApp 2400 /dev/sde # We shall parse the output above and give out path /dev/sde as in # this case for row in output.split('\n'): if re.search(r'XtremApp', row, re.I): if re.search(r'\d:\d:\d:' + str(lunid), row, re.I): device_name = re.findall(r'/\w+', row, re.I) if device_name: return FilePath(device_name[0] + device_name[1]) raise UnknownVolume(blockdevice_id)
def detach_volume(self, blockdevice_id): """ Detach ``blockdevice_id`` from whatever host it is attached to. :param unicode blockdevice_id: The unique identifier for the block device being detached. :raises UnknownVolume: If the supplied ``blockdevice_id`` does not exist. :raises UnattachedVolume: If the supplied ``blockdevice_id`` is not attached to anything. :returns: ``None`` """ _vmstate_lock.acquire() try: (target_disk, vm_name, lun) = \ self._get_disk_vmname_lun(blockdevice_id) if target_disk is None: raise UnknownVolume(blockdevice_id) if lun is None: raise UnattachedVolume(blockdevice_id) self._manager.detach_disk(vm_name, target_disk) finally: _vmstate_lock.release()
def get_device_path(self, blockdevice_id): """ Return the device path that has been allocated to the block device on the host to which it is currently attached. :param unicode blockdevice_id: The unique identifier for the block device. :returns: A ``FilePath`` for the device. """ LOG.debug("Call get_device_path blockdevice_id=%s" % blockdevice_id) if not self.rest.is_lun(self.Pool, blockdevice_id): raise UnknownVolume(blockdevice_id) target_name = '{}{}.{}'.format(self.jovian_target_prefix, blockdevice_id, self._compute_instance_id) if not self.rest.is_target(self.Pool, target_name): raise UnattachedVolume(blockdevice_id) path = jcom.get_local_disk_path(target_name) if path: LOG.debug('device_path was found: {}'.format(path)) return FilePath('/dev/' + str(path)) return None
def get_device_path(self, blockdevice_id): vol = self._get_solidfire_volume(blockdevice_id) if not vol: raise UnknownVolume(blockdevice_id) disk_by_path = utils.get_expected_disk_path(self.svip, vol['iqn']) return filepath.FilePath( utils.get_device_file_from_path(disk_by_path)).realpath()
def _extract_value(self, info_string, expect, index): data = info_string[index] tokenized = data.split(": ") if tokenized[0] == expect: return ''.join(tokenized[1:]).strip() else: raise UnknownVolume('value not found')
def return_multipath_device(self, blockdevice_id): """ :param blockdevice_id: :return: DeviveAbsPath - Multipath device path """ lunid = self.data.get_lun_map(blockdevice_id) try: #Query multipath for the device name output = check_output([b"multipath -v2 -ll"], shell=True) #multipath -v2 -ll sample output as below : #3514f0c5461400172 dm-5 XtremIO ,XtremApp #size=1.0M features='0' hwhandler='0' wp=rw #`-+- policy='queue-length 0' prio=0 status=active # |- 7:0:0:2 sdg 8:96 active faulty running # `- 3:0:0:2 sdf 8:80 active faulty running # Parse the above output for the device name under /dev/mapper for row in output.split('\n'): if re.search(r'XtremApp', row, re.I): deviceName = row.split(' ')[0] if re.search(r'\d:\d:\d:' + str(lunid), row, re.I): deviceAbsPath = EMCXtremIOBlockDeviceAPI.DEFAULT_MULTIPATH_DEVICE_PATH + deviceName if os.path.exists(deviceAbsPath): output = check_output([b"mkfs.ext3 " + deviceAbsPath], shell=True) return deviceAbsPath except Exception as ex: Message.new(value="Exception when quering for multipath device" ).write(_logger) raise UnknownVolume(blockdevice_id)
def _get_volume(self, blockdevice_id): volume = self.dbconn.get_volume_by_uuid(blockdevice_id) if volume is None: LOG.error("_get_volume: UnknownVolume, " + unicode(blockdevice_id)) raise UnknownVolume(unicode(blockdevice_id)) return volume
def resize_volume(self, blockdevice_id, size): """ Resize ``blockdevice_id``. This changes the amount of storage available. It does not change the data on the volume (including the filesystem). :param unicode blockdevice_id: The unique identifier for the block device being detached. :param int size: The required size, in bytes, of the volume. :raises UnknownVolume: If the supplied ``blockdevice_id`` does not exist. :returns: ``None`` """ vol = self._get_solidfire_volume(blockdevice_id) if not vol: raise UnknownVolume(blockdevice_id) if size <= vol['totalSize']: raise blockdevice.VolumeException(blockdevice_id) params = {'volumeID': vol['volumeID'], 'totalSize': int(size)} self.client.issue_request('ModifyVolume', params, version='5.0')
def get_device_path(self, blockdevice_id): """ Get device path for the CIO volume corresponding to the given block device. :param unicode blockdevice_id: CIO UUID for the volume to look up. :returns: A ``FilePath`` for the device. :raises UnknownVolume: If the supplied ``blockdevice_id`` does not exist. :raises UnattachedVolume: If the supplied ``blockdevice_id`` is not attached to a host. """ command = [b"/usr/bin/cio", b"vdinfo", b"-u", blockdevice_id, "-v"] output = check_output(command).split(b'\n')[0] cio_volume = output.split()[0] if cio_volume == "Fail:": raise UnknownVolume(blockdevice_id) command = [ b"/usr/bin/cio", b"vdinfo", b"-v", bytes(cio_volume), b"--attachstatus" ] compute_output = check_output(command).split(b'\n')[0] attached_to = compute_output.split()[0] if attached_to == "None": raise UnattachedVolume(blockdevice_id) compute_instance_id = self.compute_instance_id() if attached_to != compute_instance_id: # This is untested. See FLOC-2453. raise Exception("Volume is attached to {}, not to {}".format( attached_to, compute_instance_id)) return FilePath("/dev/vdisk/vd" + str(cio_volume))
def _get_vsphere_blockdevice_volume(self, blockdevice_id): logging.debug("Looking for {}", blockdevice_id) vol_list = self._list_vsphere_volumes() if blockdevice_id not in vol_list.keys(): logging.error("Volume not found for BlockDevice ID {} ".format( blockdevice_id)) raise UnknownVolume(blockdevice_id) return vol_list[blockdevice_id]
def _check_exists(self, blockdevice_id): """ Check if the image indicated by ``blockdevice_id`` already exists, and raise ``UnknownVolume`` if so. """ rbd_inst = rbd.RBD() all_images = rbd_inst.list(self._ioctx) if blockdevice_id not in all_images: raise UnknownVolume(unicode(blockdevice_id))
def find_volume_by_blockdevice_id(self, blockdevice_id): logger.debug('Trying to find the volume by blockdevice_id {} .'.format(blockdevice_id)) try: volumeinfo = self._rdxapi.find_volume_by_wwid(wwid=blockdevice_id)[0] uuid.UUID(volumeinfo[u'description']) except Exception as e: logger.error("Volume with blockdevice id {} does not exist.".format(blockdevice_id)) raise UnknownVolume(blockdevice_id) logger.debug('Found a Volume with blockdevice id {} .'.format(blockdevice_id)) return volumeinfo
def attach_volume(self, blockdevice_id, attach_to): """ Attach an CIO volume to given compute instance. :param unicode blockdevice_id: CIO UUID for volume to be attached. :param unicode attach_to: Instance id of CIO Compute instance to attached the blockdevice to. :raises UnknownVolume: If there does not exist a BlockDeviceVolume corresponding to the input blockdevice_id. :raises AlreadyAttachedVolume: If the input volume is already attached to a device. :raises AttachedUnexpectedDevice: If the attach operation fails to associate the volume with the expected OS device file. This indicates use on an unsupported OS, a misunderstanding of the CIO device assignment rules, or some other bug in this implementation. """ command = [ b"/usr/bin/cio", b"vdinfo", b"-u", unicode(blockdevice_id), b"-v" ] output = check_output(command).split(b'\n')[0] cio_volume = output.split()[0] if cio_volume == "Fail:": raise UnknownVolume(blockdevice_id) command = [ b"/usr/bin/cio", b"vdinfo", b"-v", bytes(cio_volume), b"--attachstatus" ] current_attachment = check_output(command).split(b'\n')[0] if current_attachment != "None": #if current_attachment == attach_to: raise AlreadyAttachedVolume(blockdevice_id) #else : # compute_instance_id = self.compute_instance_id() # if attach_to != compute_instance_id : # move_volume_command = [b"/usr/bin/cio", b"vdmv", b"-v", bytes(cio_volume), b"-N", attach_to] # command_output = check_output(move_volume_command).split(b'\n') else: if attach_to != None: add_attach_metadata_command = [ b"/usr/bin/cio", b"vdmod", b"-v", bytes(cio_volume), b"--attachstatus", attach_to ] command_output = check_output( add_attach_metadata_command).split(b'\n') command = [ b"/usr/bin/cio", b"vdinfo", b"-v", bytes(cio_volume), b"--datasetid" ] output = check_output(command).split(b'\n')[0] dataset_id = output.split()[0].decode("ascii") return _blockdevicevolume_from_cio_volume(bytes(cio_volume), datasetid=UUID(dataset_id), computeinstanceid=attach_to)
def attach_volume(self, blockdevice_id, attach_to): """ Attach ``blockdevice_id`` to ``host``. :param unicode blockdevice_id: The unique identifier for the block device being attached. :param unicode attach_to: An identifier like the one returned by the ``compute_instance_id`` method indicating the node to which to attach the volume. :raises UnknownVolume: If the supplied ``blockdevice_id`` does not exist. :raises AlreadyAttachedVolume: If the supplied ``blockdevice_id`` is already attached. :returns: A ``BlockDeviceVolume`` with a ``host`` attribute set to ``host``. """ log_info('Attempting to attach ' + str(blockdevice_id) + ' to ' + str(attach_to)) _vmstate_lock.acquire() try: # Make sure disk is present. Also, need the disk size is needed. disks = self._manager.list_disks() target_disk = None for disk in disks: if disk.name == blockdevice_id: target_disk = disk break if target_disk is None: raise UnknownVolume(blockdevice_id) (disk, vmname, lun) = self._get_disk_vmname_lun(blockdevice_id) if vmname is not None: if unicode(vmname) != self.compute_instance_id(): raise AlreadyAttachedVolume(blockdevice_id) else: return self._blockdevicevolume_from_azure_volume( blockdevice_id, target_disk.properties.content_length, attach_to) self._manager.attach_disk( str(attach_to), target_disk.name, int(GiB(bytes=target_disk.properties.content_length))) finally: _vmstate_lock.release() log_info('disk attached') return self._blockdevicevolume_from_azure_volume( blockdevice_id, target_disk.properties.content_length, attach_to)
def destroy_volume(self, blockdevice_id): """ Destroy the storage for the given unattached volume. :param: blockdevice_id - the volume id :raise: UnknownVolume is not found """ try: Message.new(Info="Destroying Volume" + str(blockdevice_id)).write(_logger) self.mgmt.request('volumes', 'DELETE', name=blockdevice_id) except DeviceExceptionObjNotFound as exc: raise UnknownVolume(blockdevice_id)
def destroy_volume(self, blockdevice_id): """ Destroy the storage for the given unattached volume. :param: blockdevice_id - the volume id :raise: UnknownVolume is not found """ if not self._known(blockdevice_id): raise UnknownVolume(blockdevice_id) ai_name = self._vols[blockdevice_id]['ai_name'] ai = get_datera_appinst(self._api, ai_name) if ai: ai.set(admin_state="offline", force=True) ai.delete() del self._vols[blockdevice_id] Message.new( Info='Deleted volume ' + blockdevice_id).write(_logger) else: Message.new( Info='ERROR deleting volume ' + blockdevice_id).write(_logger) raise UnknownVolume(blockdevice_id)
def iscsi_name_from_dataset_id(self, dataset_id): chan = self._cli_settings() try: cmd = 'volume show %s' % dataset_id chan.send(cmd + '\r') output = self.get_output(chan, ending_str='volume_%s' % dataset_id) iscsi_name = self._extract_value(output, 'iSCSI Name', 8) #if name trailed into next line if "ActualMembers" not in output[9]: iscsi_name += output[9] return iscsi_name except VolumeBackendAPIException as exc: raise UnknownVolume(dataset_id)
def attach_volume(self, blockdevice_id, attach_to): """ Attach ``blockdevice_id`` to ``host``. :param unicode blockdevice_id: The unique identifier for the block device being attached. :param unicode attach_to: An identifier like the one returned by the ``compute_instance_id`` method indicating the node to which to attach the volume. :raises UnknownVolume: If the supplied ``blockdevice_id`` does not exist. :raises AlreadyAttachedVolume: If the supplied ``blockdevice_id`` is already attached. :returns: A ``BlockDeviceVolume`` with a ``host`` attribute set to ``host``. """ volName = str(blockdevice_id) vdiskInfo = findVDisk(volName) if (vdiskInfo == None): raise UnknownVolume(blockdevice_id) computeHost = socket.getfqdn(attach_to) try: tgtHost = hedvigLookupTgt('wood', self.logger_) lunnum = hedvigGetLun(tgtHost, volName, self.logger_) except: raise Exception("Failed to get Lun number") if lunnum == -1: self.logger_.error("failed to add vDiskName:%s:tgtHost:%s", volName, tgtHost) raise Exception("Failed to add Lun") if (self._is_attached(tgtHost, lunnum) != None): raise AlreadyAttachedVolume(blockdevice_id) try: hedvigAddAccess(tgtHost, lunnum, socket.gethostbyname(socket.getfqdn(computeHost)), self.logger_) hedvigAddAccess(tgtHost, lunnum, socket.gethostbyname(socket.getfqdn()), self.logger_) targetName, portal = hedvigDoIscsiDiscovery( tgtHost, lunnum, self.logger_) except Exception as e: self.logger_.exception( "volume assignment to connector failed :volume:%s:connector:%s", volName, attach_to) return None return BlockDeviceVolume(blockdevice_id=unicode(blockdevice_id), size=vdiskInfo.size, attached_to=attach_to, dataset_id=UUID(blockdevice_id))
def _get_volume_object(self, blockdevice_id): """ Return VolInfo if exist else raise exception. :param unicode blockdevice_id: Name of the volume to check :raise: UnknownVolume - in case volume not exist :return: BlockDeviceVolume """ vol_objs = self._client.list_volumes(wwn=blockdevice_id) if not vol_objs: LOG.error("Volume does not exists: " + str(blockdevice_id)) raise UnknownVolume(blockdevice_id) return vol_objs[0]
def destroy_volume_folder(self): """ Destroy the volume folder :param: none """ try: Message.new(Info="Destroying Volume folder" + str(self._cluster_id)).write(_logger) self.mgmt.request(XtremIOMgmt.VOLUME_FOLDERS, XtremIOMgmt.DELETE, name=XtremIOMgmt.BASE_PATH + str(self._cluster_id)) except DeviceExceptionObjNotFound as exc: raise UnknownVolume(self._cluster_id)
def attach_volume(self, blockdevice_id, attach_to): with start_action(action_type=six.text_type( "flocker:node:agents:do:attach_volume"), blockdevice_id=blockdevice_id, droplet_id=attach_to): try: vol = self._get_volume(blockdevice_id) if vol.droplet_ids: raise AlreadyAttachedVolume(blockdevice_id) r = vol.attach(attach_to, vol.region["slug"]) if self._await_action_id(r['action']['id']): vol.droplet_ids = [attach_to] return self._to_block_device_volume(vol) except NotFoundError as _: raise UnknownVolume(blockdevice_id)
def logout(self, blockdevice_id): """ """ volName = str(blockdevice_id) if (findVDisk(volName) == None): raise UnknownVolume(blockdevice_id) tgtHost = hedvigLookupTgt('wood', self.logger_) lunnum = hedvigGetLun(tgtHost, volName, self.logger_) try: targetName, portal = hedvigDoIscsiDiscovery( tgtHost, lunnum, self.logger_) except Exception as e: targetName = None if (targetName == None): raise UnattachedVolume(blockdevice_id) hedvigDoIscsiLogout(targetName, portal, self.logger_)