def devicename_exists(self, vpool, name=None, names=None): """ Checks whether a given name can be created on the vpool :param vpool: vPool object :type vpool: VPool :param name: Candidate name :type name: str :param names: Candidate names :type names: list :return: Whether the devicename exists :rtype: bool """ error_message = None if not (name is None) ^ (names is None): error_message = 'Either the name (string) or the names (list of strings) parameter must be passed' if name is not None and not isinstance(name, basestring): error_message = 'The name parameter must be a string' if names is not None and not isinstance(names, list): error_message = 'The names parameter must be a list of strings' if error_message is not None: raise HttpNotAcceptableException(error_description=error_message, error='impossible_request') if name is not None: devicename = VDiskController.clean_devicename(name) return VDiskList.get_by_devicename_and_vpool(devicename, vpool) is not None for name in names: devicename = VDiskController.clean_devicename(name) if VDiskList.get_by_devicename_and_vpool(devicename, vpool) is not None: return True return False
def getVDisk(path, vpool=None, timeout=None): url = urlparse.urlparse(path) if url.netloc == "": path = path.replace("{}:".format(url.scheme), "{}://".format(url.scheme)) url = urlparse.urlparse(path) path = "/" + url.path.strip("/") path = path.split(":")[0] # cause yeah putting nonestandard url params if not path.endswith(".raw"): path += ".raw" elif not url.scheme: parts = url.path.split("/")[1:] # remove first slash if parts[0] == "mnt": vpool = parts[1] path = "/" + "/".join(parts[2:]) vpool = _getVPoolByUrl(url, vpool) disk = VDiskList.get_by_devicename_and_vpool(path, vpool) if timeout is not None: start = time.time() while not disk and start + timeout > time.time(): time.sleep(2) disk = VDiskList.get_by_devicename_and_vpool(path, vpool) return disk
def devicename_exists(self, vpool, name=None, names=None): """ Checks whether a given name can be created on the vpool :param vpool: vPool object :type vpool: VPool :param name: Candidate name :type name: str :param names: Candidate names :type names: list :return: Whether the devicename exists :rtype: bool """ error_message = None if not (name is None) ^ (names is None): error_message = 'Either the name (string) or the names (list of strings) parameter must be passed' if name is not None and not isinstance(name, basestring): error_message = 'The name parameter must be a string' if names is not None and not isinstance(names, list): error_message = 'The names parameter must be a list of strings' if error_message is not None: raise HttpNotAcceptableException(error_description=error_message, error='impossible_request') if name is not None: devicename = VDiskController.clean_devicename(name) return VDiskList.get_by_devicename_and_vpool(devicename, vpool) is not None for name in names: devicename = VDiskController.clean_devicename(name) if VDiskList.get_by_devicename_and_vpool(devicename, vpool) is not None: return True return False
def resize_from_voldrv(volumename, volumesize, volumepath, storagedriver_id): """ Resize a disk Triggered by volumedriver messages on the queue @param volumepath: path on hypervisor to the volume @param volumename: volume id of the disk @param volumesize: size of the volume """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) hypervisor = Factory.get(pmachine) volumepath = hypervisor.clean_backing_disk_filename(volumepath) mutex = VolatileMutex('{}_{}'.format(volumename, volumepath)) try: mutex.acquire(wait=30) disk = VDiskList.get_vdisk_by_volume_id(volumename) if disk is None: disk = VDiskList.get_by_devicename_and_vpool( volumepath, storagedriver.vpool) if disk is None: disk = VDisk() finally: mutex.release() disk.devicename = volumepath disk.volume_id = volumename disk.size = volumesize disk.vpool = storagedriver.vpool disk.save()
def resize_from_voldrv(volumename, volumesize, volumepath, storagedriver_id): """ Resize a disk Triggered by volumedriver messages on the queue @param volumepath: path on hypervisor to the volume @param volumename: volume id of the disk @param volumesize: size of the volume """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) storagedriver = StorageDriverList.get_by_storagedriver_id(storagedriver_id) hypervisor = Factory.get(pmachine) volumepath = hypervisor.clean_backing_disk_filename(volumepath) mutex = VolatileMutex('{}_{}'.format(volumename, volumepath)) try: mutex.acquire(wait=30) disk = VDiskList.get_vdisk_by_volume_id(volumename) if disk is None: disk = VDiskList.get_by_devicename_and_vpool(volumepath, storagedriver.vpool) if disk is None: disk = VDisk() finally: mutex.release() disk.devicename = volumepath disk.volume_id = volumename disk.size = volumesize disk.vpool = storagedriver.vpool disk.save() VDiskController.sync_with_mgmtcenter(disk, pmachine, storagedriver) MDSServiceController.ensure_safety(disk)
def update_vdisk_name(volume_id, old_name, new_name): """ Update a vDisk name using Management Center: set new name """ vdisk = None for mgmt_center in MgmtCenterList.get_mgmtcenters(): mgmt = Factory.get_mgmtcenter(mgmt_center = mgmt_center) try: disk_info = mgmt.get_vdisk_device_info(volume_id) device_path = disk_info['device_path'] vpool_name = disk_info['vpool_name'] vp = VPoolList.get_vpool_by_name(vpool_name) file_name = os.path.basename(device_path) vdisk = VDiskList.get_by_devicename_and_vpool(file_name, vp) if vdisk: break except Exception as ex: logger.info('Trying to get mgmt center failed for disk {0} with volume_id {1}. {2}'.format(old_name, volume_id, ex)) if not vdisk: logger.error('No vdisk found for name {0}'.format(old_name)) return vpool = vdisk.vpool mutex = VolatileMutex('{}_{}'.format(old_name, vpool.guid if vpool is not None else 'none')) try: mutex.acquire(wait=5) vdisk.name = new_name vdisk.save() finally: mutex.release()
def get_vdisk_by_name(vdisk_name, vpool_name): """ Fetch disk partitions by disk guid :param vdisk_name: location of a vdisk on a vpool (e.g. /mnt/vpool/test.raw = test.raw, /mnt/vpool/volumes/test.raw = volumes/test.raw ) :type vdisk_name: str :param vpool_name: name of a existing vpool :type vpool_name: str :return: a vdisk object :rtype: ovs.dal.hybrids.vdisk """ vpool = VPoolList.get_vpool_by_name(vpool_name) if vpool: if not vdisk_name.startswith("/"): vdisk_name = "/{0}".format(vdisk_name) if not vdisk_name.endswith('.raw'): vdisk_name = '{0}.raw'.format(vdisk_name) vdisk = VDiskList.get_by_devicename_and_vpool(vdisk_name, vpool) if vdisk: return vdisk else: raise VDiskNotFoundError( "VDisk with name `{0}` not found on vPool `{1}`!".format( vdisk_name, vpool_name)) else: raise VPoolNotFoundError( "vPool with name `{0}` cannot be found!".format(vpool_name))
def create_new(diskname, size, storagedriver_guid): """ Create a new vdisk/volume using filesystem calls :param diskname: name of the disk :param size: size of the disk (GB) :param storagedriver_guid: guid of the Storagedriver :return: guid of the new disk """ logger.info('Creating new empty disk {0} of {1} GB'.format(diskname, size)) storagedriver = StorageDriver(storagedriver_guid) vp_mountpoint = storagedriver.mountpoint hypervisor = Factory.get(storagedriver.storagerouter.pmachine) disk_path = hypervisor.clean_backing_disk_filename(hypervisor.get_disk_path(None, diskname)) location = os.path.join(vp_mountpoint, disk_path) VDiskController.create_volume(location, size) backoff = 1 timeout = 30 # seconds start = time.time() while time.time() < start + timeout: vdisk = VDiskList.get_by_devicename_and_vpool(disk_path, storagedriver.vpool) if vdisk is None: logger.debug('Waiting for disk to be picked up by voldrv') time.sleep(backoff) backoff += 1 else: return vdisk.guid raise RuntimeError('Disk {0} was not created in {1} seconds.'.format(diskname, timeout))
def update_vdisk_name(volume_id, old_name, new_name): """ Update a vDisk name using Management Center: set new name """ vdisk = None for mgmt_center in MgmtCenterList.get_mgmtcenters(): mgmt = Factory.get_mgmtcenter(mgmt_center=mgmt_center) try: disk_info = mgmt.get_vdisk_device_info(volume_id) device_path = disk_info['device_path'] vpool_name = disk_info['vpool_name'] vp = VPoolList.get_vpool_by_name(vpool_name) file_name = os.path.basename(device_path) vdisk = VDiskList.get_by_devicename_and_vpool(file_name, vp) if vdisk: break except Exception as ex: logger.info( 'Trying to get mgmt center failed for disk {0} with volume_id {1}. {2}' .format(old_name, volume_id, ex)) if not vdisk: logger.error('No vdisk found for name {0}'.format(old_name)) return vpool = vdisk.vpool mutex = VolatileMutex('{}_{}'.format( old_name, vpool.guid if vpool is not None else 'none')) try: mutex.acquire(wait=5) vdisk.name = new_name vdisk.save() finally: mutex.release()
def delete_volume(vdisk, vpool, loop_device=None, root_client=None, wait=True): """ Delete a volume :param vdisk: Virtual disk to delete :param vpool: vPool which hosts the Virtual Disk :param loop_device: Loop device where volume is mounted on :param root_client: SSHClient object :param wait: Wait for the volume to be deleted from model :return: None """ location = GeneralVDisk.get_filesystem_location(vpool=vpool, vdisk_name=vdisk.name) if root_client is None: root_client = SSHClient('127.0.0.1', username='******') if loop_device is not None: GeneralVDisk.disconnect_volume(loop_device, root_client) root_client.file_delete(location) if wait is True: counter = 0 timeout = 60 volume_name = '/' + os.path.basename(location) while True and counter < timeout: time.sleep(1) vdisks = VDiskList.get_by_devicename_and_vpool(volume_name, vpool) if vdisks is None: break counter += 1 if counter == timeout: raise RuntimeError('Disk {0} was not deleted from model after {1} seconds'.format(volume_name, timeout))
def getVDisk(path, vpool=None, timeout=None): url = urlparse.urlparse(path) if url.netloc == '': path = path.replace('{}:'.format(url.scheme), '{}://'.format(url.scheme)) url = urlparse.urlparse(path) path = '/' + url.path.strip('/') path = path.split(':')[0] # cause yeah putting nonestandard url params if not path.endswith('.raw'): path += '.raw' elif not url.scheme: parts = url.path.split('/')[1:] # remove first slash if parts[0] == 'mnt': vpool = parts[1] path = '/' + '/'.join(parts[2:]) vpool = _getVPoolByUrl(url, vpool) disk = VDiskList.get_by_devicename_and_vpool(path, vpool) if timeout is not None: start = time.time() while not disk and start + timeout > time.time(): time.sleep(2) disk = VDiskList.get_by_devicename_and_vpool(path, vpool) return disk
def create_volume(size, vpool, name=None, loop_device=None, root_client=None, wait=True): """ Create a volume :param size: Size of the volume (in GB) :param vpool: vPool to create a volume for :param name: Name for the volume :param loop_device: Loop device to use to mount volume on :param root_client: SSHClient object :param wait: Wait for the volume to be created on volumedriver and in model :return: Newly created Virtual Disk """ location = GeneralVDisk.get_filesystem_location(vpool=vpool, vdisk_name=name if name is not None else uuid.uuid4()) if root_client is None: root_client = SSHClient('127.0.0.1', username='******') try: if loop_device is not None: root_client.run('umount /mnt/{0}'.format(loop_device), allow_nonzero=True, allow_insecure=True) root_client.run(['truncate', '-s', '{0}G'.format(size), location]) root_client.dir_create(['/mnt/{0}'.format(loop_device)]) root_client.run(['mkfs.ext4', '-F', location]) root_client.run(['mount', '-o', 'loop', location, '/mnt/{0}'.format(loop_device)]) else: root_client.run(['truncate', '-s', '{0}G'.format(size), location]) except CalledProcessError as cpe: GeneralVDisk.logger.error(str(cpe)) if loop_device is not None: root_client.run('umount /mnt/{0}'.format(loop_device), allow_nonzero=True, allow_insecure=True) root_client.run('rm {0}'.format(location), allow_nonzero=True, allow_insecure=True) root_client.run('rmdir /mnt/{0}'.format(loop_device), allow_nonzero=True, allow_insecure=True) raise vdisk = None if wait is True: counter = 0 timeout = 60 volume_name = '/' + os.path.basename(location) while True and counter < timeout: time.sleep(1) vdisk = VDiskList.get_by_devicename_and_vpool(volume_name, vpool) if vdisk is not None: break counter += 1 if counter == timeout: raise RuntimeError('Disk {0} did not show up in model after {1} seconds'.format(volume_name, timeout)) return vdisk
def _ovs_devicename_in_vdisklist(self, devicename, exists = True, retry=10): if devicename is None: raise RuntimeError('Devicename is None, expecting a string.') self._debug('find device {0} in ovs model'.format(devicename)) attempt = 0 while attempt <= int(retry): self._get_vpool() vdisk = VDiskList.get_by_devicename_and_vpool(devicename, self.vpool) if exists: if vdisk is not None: return True else: if vdisk is None: return True self._debug('not found, sleep 1') attempt += 1 time.sleep(2) self._debug('still not found, return') return False
def _ovs_devicename_in_vdisklist(self, devicename, exists = True, retry=10): if devicename is None: raise RuntimeError('Devicename is None, expecting a string.') self._debug('find device {0} in ovs model'.format(devicename)) attempt = 0 while attempt <= int(retry): self._get_vpool() vdisk = VDiskList.get_by_devicename_and_vpool(devicename, self.vpool) if exists: if vdisk is not None: return True else: if vdisk is None: return True self._debug('not found, sleep 1') attempt += 1 time.sleep(2) self._debug('still not found, return') return False
def get_vdisk_by_name(vdisk_name, vpool_name): """ Fetch disk partitions by disk guid :param vdisk_name: location of a vdisk on a vpool (e.g. /mnt/vpool/test.raw = test.raw, /mnt/vpool/volumes/test.raw = volumes/test.raw ) :type vdisk_name: str :param vpool_name: name of a existing vpool :type vpool_name: str :return: a vdisk object :rtype: ovs.dal.hybrids.vdisk.VDisk """ vpool = VPoolList.get_vpool_by_name(vpool_name) if vpool: vdisk = VDiskList.get_by_devicename_and_vpool('/{0}'.format(vdisk_name), vpool) if vdisk: return vdisk else: raise VDiskNotFoundError("VDisk with name `{0}` not found!".format(vdisk_name)) else: raise VPoolNotFoundError("vPool with name `{0}` cannot be found!".format(vpool_name))
def _get_ovs_vdisk_by_devicename(self, devicename): if self._ovs_devicename_in_vdisklist(devicename): return VDiskList.get_by_devicename_and_vpool( devicename, self.vpool) raise ValueError('No such devicename %s in OVS model' % devicename)
def update_vmachine_config(vmachine, vm_object, pmachine=None): """ Update a vMachine configuration with a given vMachine configuration """ try: vdisks_synced = 0 if vmachine.name is None: MessageController.fire( MessageController.Type.EVENT, { 'type': 'vmachine_created', 'metadata': { 'name': vm_object['name'] } }) elif vmachine.name != vm_object['name']: MessageController.fire( MessageController.Type.EVENT, { 'type': 'vmachine_renamed', 'metadata': { 'old_name': vmachine.name, 'new_name': vm_object['name'] } }) if pmachine is not None: vmachine.pmachine = pmachine vmachine.name = vm_object['name'] vmachine.hypervisor_id = vm_object['id'] vmachine.devicename = vm_object['backing']['filename'] vmachine.save() # Updating and linking disks storagedrivers = StorageDriverList.get_storagedrivers() datastores = dict([('{}:{}'.format(storagedriver.storage_ip, storagedriver.mountpoint), storagedriver) for storagedriver in storagedrivers]) vdisk_guids = [] for disk in vm_object['disks']: if disk['datastore'] in vm_object['datastores']: datastore = vm_object['datastores'][disk['datastore']] if datastore in datastores: vdisk = VDiskList.get_by_devicename_and_vpool( disk['filename'], datastores[datastore].vpool) if vdisk is None: # The disk couldn't be located, but is in our datastore. We might be in a recovery scenario vdisk = VDisk() vdisk.vpool = datastores[datastore].vpool vdisk.reload_client() vdisk.devicename = disk['filename'] vdisk.volume_id = vdisk.storagedriver_client.get_volume_id( str(disk['backingfilename'])) vdisk.size = vdisk.info['volume_size'] MDSServiceController.ensure_safety(vdisk) # Update the disk with information from the hypervisor if vdisk.vmachine is None: MessageController.fire( MessageController.Type.EVENT, { 'type': 'vdisk_attached', 'metadata': { 'vmachine_name': vmachine.name, 'vdisk_name': disk['name'] } }) vdisk.vmachine = vmachine vdisk.name = disk['name'] vdisk.order = disk['order'] vdisk.save() vdisk_guids.append(vdisk.guid) vdisks_synced += 1 for vdisk in vmachine.vdisks: if vdisk.guid not in vdisk_guids: MessageController.fire( MessageController.Type.EVENT, { 'type': 'vdisk_detached', 'metadata': { 'vmachine_name': vmachine.name, 'vdisk_name': vdisk.name } }) vdisk.vmachine = None vdisk.save() logger.info( 'Updating vMachine finished (name {}, {} vdisks (re)linked)'. format(vmachine.name, vdisks_synced)) except Exception as ex: logger.info('Error during vMachine update: {0}'.format(str(ex))) raise
def update_vmachine_config(vmachine, vm_object, pmachine=None): """ Update a vMachine configuration with a given vMachine configuration :param vmachine: Virtual Machine to update :param vm_object: New virtual machine info :param pmachine: Physical machine of the virtual machine """ try: vdisks_synced = 0 if vmachine.name is None: MessageController.fire(MessageController.Type.EVENT, {'type': 'vmachine_created', 'metadata': {'name': vm_object['name']}}) elif vmachine.name != vm_object['name']: MessageController.fire(MessageController.Type.EVENT, {'type': 'vmachine_renamed', 'metadata': {'old_name': vmachine.name, 'new_name': vm_object['name']}}) if pmachine is not None: vmachine.pmachine = pmachine vmachine.name = vm_object['name'] vmachine.hypervisor_id = vm_object['id'] vmachine.devicename = vm_object['backing']['filename'] vmachine.save() # Updating and linking disks storagedrivers = StorageDriverList.get_storagedrivers() datastores = dict([('{0}:{1}'.format(storagedriver.storage_ip, storagedriver.mountpoint), storagedriver) for storagedriver in storagedrivers]) vdisk_guids = [] mutex = volatile_mutex('{0}_{1}'.format(vmachine.name, vmachine.devicename)) for disk in vm_object['disks']: ensure_safety = False if disk['datastore'] in vm_object['datastores']: datastore = vm_object['datastores'][disk['datastore']] if datastore in datastores: try: mutex.acquire(wait=10) vdisk = VDiskList.get_by_devicename_and_vpool(disk['filename'], datastores[datastore].vpool) if vdisk is None: # The disk couldn't be located, but is in our datastore. We might be in a recovery scenario vdisk = VDisk() vdisk.vpool = datastores[datastore].vpool vdisk.reload_client() vdisk.devicename = disk['filename'] vdisk.volume_id = vdisk.storagedriver_client.get_volume_id(str(disk['backingfilename'])) vdisk.size = vdisk.info['volume_size'] vdisk.metadata = {'lba_size': vdisk.info['lba_size'], 'cluster_multiplier': vdisk.info['cluster_multiplier']} # Create the disk in a locked context, but don't execute long running-task in same context vdisk.save() ensure_safety = True finally: mutex.release() if ensure_safety: MDSServiceController.ensure_safety(vdisk) VDiskController.dtl_checkup(vdisk_guid=vdisk.guid) # Update the disk with information from the hypervisor if vdisk.vmachine is None: MessageController.fire(MessageController.Type.EVENT, {'type': 'vdisk_attached', 'metadata': {'vmachine_name': vmachine.name, 'vdisk_name': disk['name']}}) vdisk.vmachine = vmachine vdisk.name = disk['name'] vdisk.order = disk['order'] vdisk.save() vdisk_guids.append(vdisk.guid) vdisks_synced += 1 for vdisk in vmachine.vdisks: if vdisk.guid not in vdisk_guids: MessageController.fire(MessageController.Type.EVENT, {'type': 'vdisk_detached', 'metadata': {'vmachine_name': vmachine.name, 'vdisk_name': vdisk.name}}) vdisk.vmachine = None vdisk.save() VMachineController._logger.info('Updating vMachine finished (name {0}, {1} vdisks (re)linked)'.format( vmachine.name, vdisks_synced )) except Exception as ex: VMachineController._logger.info('Error during vMachine update: {0}'.format(str(ex))) raise
def update_vmachine_config(vmachine, vm_object, pmachine=None): """ Update a vMachine configuration with a given vMachine configuration :param vmachine: Virtual Machine to update :param vm_object: New virtual machine info :param pmachine: Physical machine of the virtual machine """ try: vdisks_synced = 0 if vmachine.name is None: MessageController.fire(MessageController.Type.EVENT, {'type': 'vmachine_created', 'metadata': {'name': vm_object['name']}}) elif vmachine.name != vm_object['name']: MessageController.fire(MessageController.Type.EVENT, {'type': 'vmachine_renamed', 'metadata': {'old_name': vmachine.name, 'new_name': vm_object['name']}}) if pmachine is not None: vmachine.pmachine = pmachine vmachine.name = vm_object['name'] vmachine.hypervisor_id = vm_object['id'] vmachine.devicename = vm_object['backing']['filename'] vmachine.save() # Updating and linking disks storagedrivers = StorageDriverList.get_storagedrivers() datastores = dict([('{0}:{1}'.format(storagedriver.storage_ip, storagedriver.mountpoint), storagedriver) for storagedriver in storagedrivers]) vdisk_guids = [] mutex = volatile_mutex('{0}_{1}'.format(vmachine.name, vmachine.devicename)) for disk in vm_object['disks']: ensure_safety = False if disk['datastore'] in vm_object['datastores']: datastore = vm_object['datastores'][disk['datastore']] if datastore in datastores: try: mutex.acquire(wait=10) vdisk = VDiskList.get_by_devicename_and_vpool(disk['filename'], datastores[datastore].vpool) if vdisk is None: # The disk couldn't be located, but is in our datastore. We might be in a recovery scenario vdisk = VDisk() vdisk.vpool = datastores[datastore].vpool vdisk.reload_client() vdisk.devicename = disk['filename'] vdisk.volume_id = vdisk.storagedriver_client.get_volume_id(str(disk['backingfilename'])) vdisk.size = vdisk.info['volume_size'] vdisk.metadata = {'lba_size': vdisk.info['lba_size'], 'cluster_multiplier': vdisk.info['cluster_multiplier']} # Create the disk in a locked context, but don't execute long running-task in same context vdisk.save() ensure_safety = True finally: mutex.release() if ensure_safety: MDSServiceController.ensure_safety(vdisk) VDiskController.dtl_checkup(vdisk_guid=vdisk.guid) # Update the disk with information from the hypervisor if vdisk.vmachine is None: MessageController.fire(MessageController.Type.EVENT, {'type': 'vdisk_attached', 'metadata': {'vmachine_name': vmachine.name, 'vdisk_name': disk['name']}}) vdisk.vmachine = vmachine vdisk.name = disk['name'] vdisk.order = disk['order'] vdisk.save() vdisk_guids.append(vdisk.guid) vdisks_synced += 1 for vdisk in vmachine.vdisks: if vdisk.guid not in vdisk_guids: MessageController.fire(MessageController.Type.EVENT, {'type': 'vdisk_detached', 'metadata': {'vmachine_name': vmachine.name, 'vdisk_name': vdisk.name}}) vdisk.vmachine = None vdisk.save() VMachineController._logger.info('Updating vMachine finished (name {0}, {1} vdisks (re)linked)'.format( vmachine.name, vdisks_synced )) except Exception as ex: VMachineController._logger.info('Error during vMachine update: {0}'.format(str(ex))) raise
def update_vmachine_config(vmachine, vm_object, pmachine=None): """ Update a vMachine configuration with a given vMachine configuration """ try: vdisks_synced = 0 if vmachine.name is None: MessageController.fire(MessageController.Type.EVENT, {'type': 'vmachine_created', 'metadata': {'name': vm_object['name']}}) elif vmachine.name != vm_object['name']: MessageController.fire(MessageController.Type.EVENT, {'type': 'vmachine_renamed', 'metadata': {'old_name': vmachine.name, 'new_name': vm_object['name']}}) if pmachine is not None: vmachine.pmachine = pmachine vmachine.name = vm_object['name'] vmachine.hypervisor_id = vm_object['id'] vmachine.devicename = vm_object['backing']['filename'] vmachine.save() # Updating and linking disks storagedrivers = StorageDriverList.get_storagedrivers() datastores = dict([('{}:{}'.format(storagedriver.storage_ip, storagedriver.mountpoint), storagedriver) for storagedriver in storagedrivers]) vdisk_guids = [] for disk in vm_object['disks']: if disk['datastore'] in vm_object['datastores']: datastore = vm_object['datastores'][disk['datastore']] if datastore in datastores: vdisk = VDiskList.get_by_devicename_and_vpool(disk['filename'], datastores[datastore].vpool) if vdisk is None: # The disk couldn't be located, but is in our datastore. We might be in a recovery scenario vdisk = VDisk() vdisk.vpool = datastores[datastore].vpool vdisk.reload_client() vdisk.devicename = disk['filename'] vdisk.volume_id = vdisk.storagedriver_client.get_volume_id(str(disk['backingfilename'])) vdisk.size = vdisk.info['volume_size'] # Update the disk with information from the hypervisor if vdisk.vmachine is None: MessageController.fire(MessageController.Type.EVENT, {'type': 'vdisk_attached', 'metadata': {'vmachine_name': vmachine.name, 'vdisk_name': disk['name']}}) vdisk.vmachine = vmachine vdisk.name = disk['name'] vdisk.order = disk['order'] vdisk.save() vdisk_guids.append(vdisk.guid) vdisks_synced += 1 for vdisk in vmachine.vdisks: if vdisk.guid not in vdisk_guids: MessageController.fire(MessageController.Type.EVENT, {'type': 'vdisk_detached', 'metadata': {'vmachine_name': vmachine.name, 'vdisk_name': vdisk.name}}) vdisk.vmachine = None vdisk.save() logger.info('Updating vMachine finished (name {}, {} vdisks (re)linked)'.format( vmachine.name, vdisks_synced )) except Exception as ex: logger.info('Error during vMachine update: {0}'.format(str(ex))) raise
def _get_ovs_vdisk_by_devicename(self, devicename): if self._ovs_devicename_in_vdisklist(devicename): return VDiskList.get_by_devicename_and_vpool(devicename, self.vpool) raise ValueError('No such devicename {0} in OVS model'.format(devicename))
def check_scrubbing_test(): """ Check scrubbing of vdisks test """ initial_counter = 100 step = 5 vdisk = None vpool_name = General.get_config().get('vpool', 'name') vpool = GeneralVPool.get_vpool_by_name(vpool_name=vpool_name) assert vpool, "No vpool found where one was expected" template_folder = GeneralVMachine.template_target_folder image_name = GeneralVMachine.template_image disk_name = "scrubdisk" GeneralVMachine.logger.info("Starting RAW disk creation") out, err, _ = General.execute_command('qemu-img convert -O raw {0}{1} /mnt/{2}/{3}.raw'.format(template_folder, image_name, vpool_name, disk_name)) if err: GeneralVMachine.logger.error("Error while creating raw disk: {0}".format(err)) def snapshot_vdisk(vdisk): metadata = {'label': 'snap-' + vdisk.name, 'is_consistent': True, 'timestamp': time.time(), 'is_automatic': False, 'is_sticky': False} VDiskController.create_snapshot(vdisk.guid, metadata) counter = initial_counter while counter and vdisk is None: time.sleep(step) vdisk = VDiskList.get_by_devicename_and_vpool('/' + disk_name + '.raw', vpool) counter -= step assert counter > 0, "Vdisk with name {0} didn't appear in the model after 60 seconds".format(disk_name) # snapshot disks for the first time snapshot_vdisk(vdisk) counter = initial_counter while counter > 0: time.sleep(step) out, err, _ = General.execute_command('dd if=/dev/zero of=/mnt/{0}/{1}.raw bs=10K count=1000 conv=notrunc'.format(vpool_name, disk_name)) counter -= step snapshot_vdisk(vdisk) # saving disk 'stored' info / the only attribute that is lowered after scrubbing vdisk.invalidate_dynamics(['statistics']) disk_backend_data = vdisk.statistics['stored'] # deleting middle snapshots for snapshot in vdisk.snapshots[1:-1]: VDiskController.delete_snapshot(vdisk.guid, snapshot['guid']) # starting scrubber try: GenericController.execute_scrub() # waiting for model to catch up counter = initial_counter while counter > 0: time.sleep(step) vdisk.invalidate_dynamics(['statistics']) # checking result of scrub work if vdisk.statistics['stored'] < disk_backend_data: GeneralVMachine.logger.info("It took {0} seconds for the value to change from {1} to {2}\n".format((initial_counter - counter) * step, disk_backend_data, vdisk.statistics['stored'])) break counter -= step finally: # removing vdisk GeneralVMachine.logger.info("Removing vpool vdisks from {0} vpool".format(vpool_name)) out, err, _ = General.execute_command("rm -rf /mnt/{0}/*.raw".format(vpool_name)) if err: GeneralVMachine.logger.error("Error while removing vdisk: {0}".format(err)) assert counter > 0, "Scrubbing didn't run as expected, backend size of vdisk remained at {0}:\n".format(disk_backend_data)