def sync_with_hypervisor(vmachineguid, storagedriver_id=None): """ Updates a given vmachine with data retrieved from a given pmachine :param vmachineguid: Guid of the virtual machine :param storagedriver_id: Storage Driver hosting the vmachine """ try: vmachine = VMachine(vmachineguid) except Exception as ex: VMachineController._logger.info('Cannot get VMachine object: {0}'.format(str(ex))) raise vm_object = None if vmachine.pmachine.mgmtcenter and storagedriver_id is not None and vmachine.devicename is not None: try: mgmt_center = Factory.get_mgmtcenter(vmachine.pmachine) storagedriver = StorageDriverList.get_by_storagedriver_id(storagedriver_id) VMachineController._logger.info('Syncing vMachine (name {0}) with Management center {1}'.format(vmachine.name, vmachine.pmachine.mgmtcenter.name)) vm_object = mgmt_center.get_vm_agnostic_object(devicename=vmachine.devicename, ip=storagedriver.storage_ip, mountpoint=storagedriver.mountpoint) except Exception as ex: VMachineController._logger.info('Error while fetching vMachine info from management center: {0}'.format(str(ex))) if vm_object is None and storagedriver_id is None and vmachine.hypervisor_id is not None and vmachine.pmachine is not None: try: # Only the vmachine was received, so base the sync on hypervisor id and pmachine hypervisor = Factory.get(vmachine.pmachine) VMachineController._logger.info('Syncing vMachine (name {0})'.format(vmachine.name)) vm_object = hypervisor.get_vm_agnostic_object(vmid=vmachine.hypervisor_id) except Exception as ex: VMachineController._logger.info('Error while fetching vMachine info from hypervisor: {0}'.format(str(ex))) if vm_object is None and storagedriver_id is not None and vmachine.devicename is not None: try: # Storage Driver id was given, using the devicename instead (to allow hypervisor id updates # which can be caused by re-adding a vm to the inventory) pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) storagedriver = StorageDriverList.get_by_storagedriver_id(storagedriver_id) hypervisor = Factory.get(pmachine) if not hypervisor.file_exists(storagedriver, hypervisor.clean_vmachine_filename(vmachine.devicename)): return vmachine.pmachine = pmachine vmachine.save() VMachineController._logger.info('Syncing vMachine (device {0}, ip {1}, mountpoint {2})'.format(vmachine.devicename, storagedriver.storage_ip, storagedriver.mountpoint)) vm_object = hypervisor.get_vm_object_by_devicename(devicename=vmachine.devicename, ip=storagedriver.storage_ip, mountpoint=storagedriver.mountpoint) except Exception as ex: VMachineController._logger.info('Error while fetching vMachine info from hypervisor using devicename: {0}'.format(str(ex))) if vm_object is None: message = 'Not enough information to sync vmachine' VMachineController._logger.info('Error: {0}'.format(message)) raise RuntimeError(message) VMachineController.update_vmachine_config(vmachine, vm_object)
def sync_with_hypervisor(vmachineguid, storagedriver_id=None): """ Updates a given vmachine with data retreived from a given pmachine """ try: vmachine = VMachine(vmachineguid) if storagedriver_id is None and vmachine.hypervisor_id is not None and vmachine.pmachine is not None: # Only the vmachine was received, so base the sync on hypervisorid and pmachine hypervisor = Factory.get(vmachine.pmachine) logger.info('Syncing vMachine (name {})'.format(vmachine.name)) vm_object = hypervisor.get_vm_agnostic_object( vmid=vmachine.hypervisor_id) elif storagedriver_id is not None and vmachine.devicename is not None: # Storage Driver id was given, using the devicename instead (to allow hypervisorid updates # which can be caused by re-adding a vm to the inventory) pmachine = PMachineList.get_by_storagedriver_id( storagedriver_id) storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) hypervisor = Factory.get(pmachine) if not hypervisor.file_exists( vmachine.vpool, hypervisor.clean_vmachine_filename( vmachine.devicename)): return vmachine.pmachine = pmachine vmachine.save() logger.info( 'Syncing vMachine (device {}, ip {}, mtpt {})'.format( vmachine.devicename, storagedriver.storage_ip, storagedriver.mountpoint)) vm_object = hypervisor.get_vm_object_by_devicename( devicename=vmachine.devicename, ip=storagedriver.storage_ip, mountpoint=storagedriver.mountpoint) else: message = 'Not enough information to sync vmachine' logger.info('Error: {0}'.format(message)) raise RuntimeError(message) except Exception as ex: logger.info('Error while fetching vMachine info: {0}'.format( str(ex))) raise if vm_object is None: message = 'Could not retreive hypervisor vmachine object' logger.info('Error: {0}'.format(message)) raise RuntimeError(message) else: VMachineController.update_vmachine_config(vmachine, vm_object)
def sync_with_mgmtcenter(disk, pmachine, storagedriver): """ Update disk info using management center (if available) If no management center, try with hypervisor If no info retrieved, use devicename @param disk: vDisk hybrid (vdisk to be updated) @param pmachine: pmachine hybrid (pmachine running the storagedriver) @param storagedriver: storagedriver hybrid (storagedriver serving the vdisk) """ disk_name = None if pmachine.mgmtcenter is not None: logger.debug( 'Sync vdisk {0} with management center {1} on storagedriver {2}' .format(disk.name, pmachine.mgmtcenter.name, storagedriver.name)) mgmt = Factory.get_mgmtcenter(mgmt_center=pmachine.mgmtcenter) volumepath = disk.devicename mountpoint = storagedriver.mountpoint devicepath = '{0}/{1}'.format(mountpoint, volumepath) try: disk_mgmt_center_info = mgmt.get_vdisk_model_by_devicepath( devicepath) if disk_mgmt_center_info is not None: disk_name = disk_mgmt_center_info.get('name') except Exception as ex: logger.error( 'Failed to sync vdisk {0} with mgmt center {1}. {2}'. format(disk.name, pmachine.mgmtcenter.name, str(ex))) if disk_name is None: logger.info('Sync vdisk with hypervisor on {0}'.format( pmachine.name)) try: hv = Factory.get(pmachine) info = hv.get_vm_agnostic_object(disk.vmachine.hypervisor_id) for disk in info['disks']: if disk['filename'] == disk.devicename: disk_name = disk['name'] break except Exception as ex: logger.error('Failed to get vdisk info from hypervisor. %s' % ex) if disk_name is None: logger.info('No info retrieved from hypervisor, using devicename') disk_name = disk.devicename.split('/')[-1].split('.')[0] if disk_name is not None: disk.name = disk_name 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 delete_from_voldrv(name, storagedriver_id): """ This method will delete a vmachine based on the name of the vmx given """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) if pmachine.hvtype not in ['VMWARE', 'KVM']: return hypervisor = Factory.get(pmachine) name = hypervisor.clean_vmachine_filename(name) if pmachine.hvtype == 'VMWARE': storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) vpool = storagedriver.vpool else: vpool = None vm = VMachineList.get_by_devicename_and_vpool(name, vpool) if vm is not None: MessageController.fire(MessageController.Type.EVENT, { 'type': 'vmachine_deleted', 'metadata': { 'name': vm.name } }) vm.delete(abandon=['vdisks'])
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 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 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 create(self, request): """ Creates a Management Center """ serializer = FullSerializer( MgmtCenter, instance=MgmtCenter(), data=request.DATA, allow_passwords=True) if serializer.is_valid(): mgmt_center = serializer.object duplicate = MgmtCenterList.get_by_ip(mgmt_center.ip) if duplicate is None: try: mgmt_center_client = Factory.get_mgmtcenter( mgmt_center=mgmt_center) is_mgmt_center = mgmt_center_client.test_connection() except Exception as ex: logger.debug('Management center testing: {0}'.format(ex)) raise NotAcceptable('The given information is invalid.') if not is_mgmt_center: raise NotAcceptable( 'The given information is not for a Management center.' ) mgmt_center.save() return Response( serializer.data, status=status.HTTP_201_CREATED) else: raise NotAcceptable( 'A Mangement Center with this ip already exists.') else: return Response( serializer.errors, status=status.HTTP_400_BAD_REQUEST)
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 delete_from_voldrv(volumename, storagedriver_id): """ Delete a disk Triggered by volumedriver messages on the queue @param volumename: volume id of the disk """ _ = storagedriver_id # For logging purposes disk = VDiskList.get_vdisk_by_volume_id(volumename) if disk is not None: mutex = VolatileMutex('{}_{}'.format(volumename, disk.devicename)) try: mutex.acquire(wait=20) pmachine = None try: pmachine = PMachineList.get_by_storagedriver_id(disk.storagedriver_id) except RuntimeError as ex: if 'could not be found' not in str(ex): raise # else: pmachine can't be loaded, because the volumedriver doesn't know about it anymore if pmachine is not None: limit = 5 hypervisor = Factory.get(pmachine) exists = hypervisor.file_exists(disk.vpool, disk.devicename) while limit > 0 and exists is True: time.sleep(1) exists = hypervisor.file_exists(disk.vpool, disk.devicename) limit -= 1 if exists is True: logger.info('Disk {0} still exists, ignoring delete'.format(disk.devicename)) return logger.info('Delete disk {}'.format(disk.name)) disk.delete() finally: mutex.release()
def clone(diskguid, snapshotid, devicename, pmachineguid, machinename, machineguid=None): """ Clone a disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) description = '{} {}'.format(machinename, devicename) properties_to_clone = ['description', 'size', 'type', 'retentionpolicyguid', 'snapshotpolicyguid', 'autobackup'] vdisk = VDisk(diskguid) location = hypervisor.get_backing_disk_path(machinename, devicename) new_vdisk = VDisk() new_vdisk.copy(vdisk, include=properties_to_clone) new_vdisk.parent_vdisk = vdisk new_vdisk.name = '{0}-clone'.format(vdisk.name) new_vdisk.description = description new_vdisk.devicename = hypervisor.clean_backing_disk_filename(location) new_vdisk.parentsnapshot = snapshotid new_vdisk.vmachine = VMachine(machineguid) if machineguid else vdisk.vmachine new_vdisk.vpool = vdisk.vpool new_vdisk.save() try: storagedriver = StorageDriverList.get_by_storagedriver_id(vdisk.storagedriver_id) if storagedriver is None: raise RuntimeError('Could not find StorageDriver with id {0}'.format(vdisk.storagedriver_id)) mds_service = MDSServiceController.get_preferred_mds(storagedriver.storagerouter, vdisk.vpool) if mds_service is None: raise RuntimeError('Could not find a MDS service') logger.info('Clone snapshot {} of disk {} to location {}'.format(snapshotid, vdisk.name, location)) volume_id = vdisk.storagedriver_client.create_clone( target_path=location, metadata_backend_config=MDSMetaDataBackendConfig([MDSNodeConfig(address=str(mds_service.service.storagerouter.ip), port=mds_service.service.ports[0])]), parent_volume_id=str(vdisk.volume_id), parent_snapshot_id=str(snapshotid), node_id=str(vdisk.storagedriver_id) ) except Exception as ex: logger.error('Caught exception during clone, trying to delete the volume. {0}'.format(ex)) new_vdisk.delete() VDiskController.delete_volume(location) raise new_vdisk.volume_id = volume_id new_vdisk.save() try: MDSServiceController.ensure_safety(new_vdisk) except Exception as ex: logger.error('Caught exception during "ensure_safety" {0}'.format(ex)) return {'diskguid': new_vdisk.guid, 'name': new_vdisk.name, 'backingdevice': location}
def _hosts(self): """ Returns all hosts (not only those known to OVS) managed by the Management center """ mgmt_center = Factory.get_mgmtcenter(mgmt_center=self) if mgmt_center is not None: return mgmt_center.get_hosts() else: return {}
def unconfigure_vpool_for_host(pmachine_guid, vpool_guid): pmachine = PMachine(pmachine_guid) mgmt_center_client = None try: mgmt_center_client = Factory.get_mgmtcenter(pmachine=pmachine) except Exception as ex: logger.error('Cannot get management center client: {0}'.format(ex)) if mgmt_center_client is not None: logger.info('Unconfiguring vPool {0} on host {1}'.format(vpool_guid, pmachine.name)) mgmt_center_client.unconfigure_vpool_for_host(vpool_guid, False, pmachine.ip)
def sync_with_mgmtcenter(disk, pmachine, storagedriver): """ Update disk info using management center (if available) If no management center, try with hypervisor If no info retrieved, use devicename @param disk: vDisk hybrid (vdisk to be updated) @param pmachine: pmachine hybrid (pmachine running the storagedriver) @param storagedriver: storagedriver hybrid (storagedriver serving the vdisk) """ disk_name = None if pmachine.mgmtcenter is not None: logger.debug('Sync vdisk {0} with management center {1} on storagedriver {2}'.format(disk.name, pmachine.mgmtcenter.name, storagedriver.name)) mgmt = Factory.get_mgmtcenter(mgmt_center = pmachine.mgmtcenter) volumepath = disk.devicename mountpoint = storagedriver.mountpoint devicepath = '{0}/{1}'.format(mountpoint, volumepath) try: disk_mgmt_center_info = mgmt.get_vdisk_model_by_devicepath(devicepath) if disk_mgmt_center_info is not None: disk_name = disk_mgmt_center_info.get('name') except Exception as ex: logger.error('Failed to sync vdisk {0} with mgmt center {1}. {2}'.format(disk.name, pmachine.mgmtcenter.name, str(ex))) if disk_name is None: logger.info('Sync vdisk with hypervisor on {0}'.format(pmachine.name)) try: hv = Factory.get(pmachine) info = hv.get_vm_agnostic_object(disk.vmachine.hypervisor_id) for disk in info['disks']: if disk['filename'] == disk.devicename: disk_name = disk['name'] break except Exception as ex: logger.error('Failed to get vdisk info from hypervisor. %s' % ex) if disk_name is None: logger.info('No info retrieved from hypervisor, using devicename') disk_name = disk.devicename.split('/')[-1].split('.')[0] if disk_name is not None: disk.name = disk_name disk.save()
def sync_with_hypervisor(vmachineguid, storagedriver_id=None): """ Updates a given vmachine with data retreived from a given pmachine """ try: vmachine = VMachine(vmachineguid) if storagedriver_id is None and vmachine.hypervisor_id is not None and vmachine.pmachine is not None: # Only the vmachine was received, so base the sync on hypervisorid and pmachine hypervisor = Factory.get(vmachine.pmachine) logger.info('Syncing vMachine (name {})'.format(vmachine.name)) vm_object = hypervisor.get_vm_agnostic_object(vmid=vmachine.hypervisor_id) elif storagedriver_id is not None and vmachine.devicename is not None: # Storage Driver id was given, using the devicename instead (to allow hypervisorid updates # which can be caused by re-adding a vm to the inventory) pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) storagedriver = StorageDriverList.get_by_storagedriver_id(storagedriver_id) hypervisor = Factory.get(pmachine) if not hypervisor.file_exists(vmachine.vpool, hypervisor.clean_vmachine_filename(vmachine.devicename)): return vmachine.pmachine = pmachine vmachine.save() logger.info('Syncing vMachine (device {}, ip {}, mtpt {})'.format(vmachine.devicename, storagedriver.storage_ip, storagedriver.mountpoint)) vm_object = hypervisor.get_vm_object_by_devicename(devicename=vmachine.devicename, ip=storagedriver.storage_ip, mountpoint=storagedriver.mountpoint) else: message = 'Not enough information to sync vmachine' logger.info('Error: {0}'.format(message)) raise RuntimeError(message) except Exception as ex: logger.info('Error while fetching vMachine info: {0}'.format(str(ex))) raise if vm_object is None: message = 'Could not retreive hypervisor vmachine object' logger.info('Error: {0}'.format(message)) raise RuntimeError(message) else: VMachineController.update_vmachine_config(vmachine, vm_object)
def create_from_template(diskguid, machinename, devicename, pmachineguid, machineguid=None, storagedriver_guid=None): """ Create a disk from a template @param parentdiskguid: guid of the disk @param location: location where virtual device should be created (eg: myVM) @param devicename: device file name for the disk (eg: mydisk-flat.vmdk) @param machineguid: guid of the machine to assign disk to @return diskguid: guid of new disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) disk_path = hypervisor.get_disk_path(machinename, devicename) description = '{} {}'.format(machinename, devicename) properties_to_clone = [ 'description', 'size', 'type', 'retentionpolicyid', 'snapshotpolicyid', 'vmachine', 'vpool'] disk = VDisk(diskguid) if disk.vmachine and not disk.vmachine.is_vtemplate: # Disk might not be attached to a vmachine, but still be a template raise RuntimeError('The given disk does not belong to a template') if storagedriver_guid is not None: storagedriver_id = StorageDriver(storagedriver_guid).storagedriver_id else: storagedriver_id = disk.storagedriver_id new_disk = VDisk() new_disk.copy(disk, include=properties_to_clone) new_disk.vpool = disk.vpool new_disk.devicename = hypervisor.clean_backing_disk_filename(disk_path) new_disk.parent_vdisk = disk new_disk.name = '{}-clone'.format(disk.name) new_disk.description = description new_disk.vmachine = VMachine(machineguid) if machineguid else disk.vmachine new_disk.save() logger.info('Create disk from template {} to new disk {} to location {}'.format( disk.name, new_disk.name, disk_path )) try: volume_id = disk.storagedriver_client.create_clone_from_template(disk_path, str(disk.volume_id), node_id=str(storagedriver_id)) new_disk.volume_id = volume_id new_disk.save() except Exception as ex: logger.error('Clone disk on volumedriver level failed with exception: {0}'.format(str(ex))) new_disk.delete() raise return {'diskguid': new_disk.guid, 'name': new_disk.name, 'backingdevice': disk_path}
def _hypervisor_status(self): """ Fetches the Status of the vMachine. """ if self.hypervisor_id is None or self.pmachine is None: return 'UNKNOWN' hv = hvFactory.get(self.pmachine) try: return hv.get_state(self.hypervisor_id) except: return 'UNKNOWN'
def _host_status(self): """ Returns the host status as reported by the management center (e.g. vCenter Server) """ mgmtcentersdk = hvFactory.get_mgmtcenter(self) if mgmtcentersdk: if self.hypervisor_id: return mgmtcentersdk.get_host_status_by_pk(self.hypervisor_id) if self.ip: return mgmtcentersdk.get_host_status_by_ip(self.ip) return 'UNKNOWN'
def _host_status(self): """ Returns the host status as reported by the management center (e.g. vCenter Server) """ mgmtcentersdk = Factory.get_mgmtcenter(self) if mgmtcentersdk: if self.hypervisor_id: return mgmtcentersdk.get_host_status_by_pk(self.hypervisor_id) if self.ip: return mgmtcentersdk.get_host_status_by_ip(self.ip) return 'UNKNOWN'
def unconfigure_vpool_for_host(pmachine_guid, vpool_guid): pmachine = PMachine(pmachine_guid) mgmt_center_client = None try: mgmt_center_client = Factory.get_mgmtcenter(pmachine=pmachine) except Exception as ex: logger.error('Cannot get management center client: {0}'.format(ex)) if mgmt_center_client is not None: logger.info('Unconfiguring vPool {0} on host {1}'.format( vpool_guid, pmachine.name)) mgmt_center_client.unconfigure_vpool_for_host( vpool_guid, False, pmachine.ip)
def is_host_configured(pmachine_guid): pmachine = PMachine(pmachine_guid) mgmt_center_client = None try: mgmt_center_client = Factory.get_mgmtcenter(pmachine=pmachine) except Exception as ex: if pmachine.mgmtcenter_guid: logger.error('Cannot get management center client: {0}'.format(ex)) if mgmt_center_client is not None: return mgmt_center_client.is_host_configured(pmachine.ip) return False
def delete(machineguid): """ Delete a vmachine @param machineguid: guid of the machine """ machine = VMachine(machineguid) storagedriver_mountpoint, storagedriver_storage_ip = None, None try: storagedriver = [ storagedriver for storagedriver in machine.vpool.storagedrivers if storagedriver.storagerouter.pmachine_guid == machine.pmachine_guid ][0] storagedriver_mountpoint = storagedriver.mountpoint storagedriver_storage_ip = storagedriver.storage_ip except Exception as ex: logger.debug( 'No mountpoint info could be retrieved. Reason: {0}'.format( str(ex))) storagedriver_mountpoint = None disks_info = [] for vd in machine.vdisks: for storagedriver in vd.vpool.storagedrivers: if storagedriver.storagerouter.pmachine_guid == machine.pmachine_guid: disks_info.append( (storagedriver.mountpoint, vd.devicename)) if machine.pmachine: # Allow hypervisor id node, lookup strategy is hypervisor dependent try: hypervisor_id = machine.hypervisor_id if machine.pmachine.hvtype == 'KVM': hypervisor_id = machine.name # On KVM we can lookup the machine by name, not by id hv = Factory.get(machine.pmachine) hv.delete_vm(hypervisor_id, storagedriver_mountpoint, storagedriver_storage_ip, machine.devicename, disks_info, True) except Exception as exception: logger.error('Deletion of vm on hypervisor failed: {0}'.format( str(exception)), print_msg=True) for disk in machine.vdisks: logger.debug('Deleting disk {0} with guid: {1}'.format( disk.name, disk.guid)) for junction in disk.mds_services: junction.delete() disk.delete() logger.debug('Deleting vmachine {0} with guid {1}'.format( machine.name, machine.guid)) machine.delete()
def clone(machineguid, timestamp, name): """ Clone a vmachine using the disk snapshot based on a snapshot timestamp @param machineguid: guid of the machine to clone @param timestamp: timestamp of the disk snapshots to use for the clone @param name: name for the new machine """ machine = VMachine(machineguid) disks = {} for snapshot in machine.snapshots: if snapshot['timestamp'] == timestamp: for diskguid, snapshotguid in snapshot['snapshots'].iteritems( ): disks[diskguid] = snapshotguid new_machine = VMachine() new_machine.copy(machine) new_machine.name = name new_machine.pmachine = machine.pmachine new_machine.save() new_disk_guids = [] disks_by_order = sorted(machine.vdisks, key=lambda x: x.order) for currentDisk in disks_by_order: if machine.is_vtemplate and currentDisk.templatesnapshot: snapshotid = currentDisk.templatesnapshot else: snapshotid = disks[currentDisk.guid] prefix = '%s-clone' % currentDisk.name result = VDiskController.clone( diskguid=currentDisk.guid, snapshotid=snapshotid, devicename=prefix, pmachineguid=new_machine.pmachine_guid, machinename=new_machine.name, machineguid=new_machine.guid) new_disk_guids.append(result['diskguid']) hv = Factory.get(machine.pmachine) try: result = hv.clone_vm(machine.hypervisor_id, name, disks, None, True) except: VMachineController.delete(machineguid=new_machine.guid) raise new_machine.hypervisor_id = result new_machine.save() return new_machine.guid
def is_host_configured(pmachine_guid): pmachine = PMachine(pmachine_guid) mgmt_center_client = None try: mgmt_center_client = Factory.get_mgmtcenter(pmachine=pmachine) except Exception as ex: if pmachine.mgmtcenter_guid: MgmtCenterController._logger.error( 'Cannot get management center client: {0}'.format(ex)) if mgmt_center_client is not None: return mgmt_center_client.is_host_configured(pmachine.ip) return False
def clone(diskguid, snapshotid, devicename, pmachineguid, machinename, machineguid=None, **kwargs): """ Clone a disk @param location: location where virtual device should be created (eg: myVM) @param devicename: device file name for the disk (eg: mydisk-flat.vmdk) @param parentdiskguid: guid of the disk @param snapshotid: guid of the snapshot @param machineguid: guid of the machine to assign disk to """ _ = kwargs pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) description = '{} {}'.format(machinename, devicename) properties_to_clone = [ 'description', 'size', 'type', 'retentionpolicyguid', 'snapshotpolicyguid', 'autobackup' ] new_disk = VDisk() disk = VDisk(diskguid) _log = 'Clone snapshot {} of disk {} to location {}' _location = hypervisor.get_backing_disk_path(machinename, devicename) _id = '{}'.format(disk.volume_id) _snap = '{}'.format(snapshotid) logger.info(_log.format(_snap, disk.name, _location)) volume_id = disk.storagedriver_client.create_clone( _location, _id, _snap) new_disk.copy(disk, include=properties_to_clone) new_disk.parent_vdisk = disk new_disk.name = '{}-clone'.format(disk.name) new_disk.description = description new_disk.volume_id = volume_id new_disk.devicename = hypervisor.clean_backing_disk_filename(_location) new_disk.parentsnapshot = snapshotid new_disk.vmachine = VMachine( machineguid) if machineguid else disk.vmachine new_disk.vpool = disk.vpool new_disk.save() return { 'diskguid': new_disk.guid, 'name': new_disk.name, 'backingdevice': _location }
def unconfigure_host(pmachine_guid, mgmtcenter_guid, update_link): pmachine = PMachine(pmachine_guid) mgmt_center = MgmtCenter(mgmtcenter_guid) mgmt_center_client = None try: mgmt_center_client = Factory.get_mgmtcenter(mgmt_center=mgmt_center) except Exception as ex: logger.error('Cannot get management center client: {0}'.format(ex)) if mgmt_center_client is not None: logger.info('Unconfiguring host {0} from management center {1}'.format(pmachine.name, mgmt_center.name)) mgmt_center_client.unconfigure_host(pmachine.ip) if update_link is True: pmachine.mgmtcenter = None pmachine.save()
def clone(machineguid, timestamp, name): """ Clone a vmachine using the disk snapshot based on a snapshot timestamp @param machineguid: guid of the machine to clone @param timestamp: timestamp of the disk snapshots to use for the clone @param name: name for the new machine """ machine = VMachine(machineguid) disks = {} for snapshot in machine.snapshots: if snapshot['timestamp'] == timestamp: for diskguid, snapshotguid in snapshot['snapshots'].iteritems(): disks[diskguid] = snapshotguid new_machine = VMachine() new_machine.copy(machine) new_machine.name = name new_machine.pmachine = machine.pmachine new_machine.save() new_disk_guids = [] disks_by_order = sorted(machine.vdisks, key=lambda x: x.order) for currentDisk in disks_by_order: if machine.is_vtemplate and currentDisk.templatesnapshot: snapshotid = currentDisk.templatesnapshot else: snapshotid = disks[currentDisk.guid] prefix = '%s-clone' % currentDisk.name result = VDiskController.clone(diskguid=currentDisk.guid, snapshotid=snapshotid, devicename=prefix, pmachineguid=new_machine.pmachine_guid, machinename=new_machine.name, machineguid=new_machine.guid) new_disk_guids.append(result['diskguid']) hv = Factory.get(machine.pmachine) try: result = hv.clone_vm(machine.hypervisor_id, name, disks, None, True) except: VMachineController.delete(machineguid=new_machine.guid) raise new_machine.hypervisor_id = result new_machine.save() return new_machine.guid
def sync_with_hypervisor(vpool_guid): """ Syncs all vMachines of a given vPool with the hypervisor """ vpool = VPool(vpool_guid) for storagedriver in vpool.storagedrivers: pmachine = storagedriver.storagerouter.pmachine hypervisor = Factory.get(pmachine) for vm_object in hypervisor.get_vms_by_nfs_mountinfo(storagedriver.storage_ip, storagedriver.mountpoint): search_vpool = None if pmachine.hvtype == 'KVM' else vpool vmachine = VMachineList.get_by_devicename_and_vpool( devicename=vm_object['backing']['filename'], vpool=search_vpool ) VMachineController.update_vmachine_config(vmachine, vm_object, pmachine)
def sync_with_hypervisor(vpool_guid): """ Syncs all vMachines of a given vPool with the hypervisor :param vpool_guid: Guid of the vPool to synchronize """ vpool = VPool(vpool_guid) if vpool.status != VPool.STATUSES.RUNNING: raise ValueError('Synchronizing with hypervisor is only allowed if your vPool is in {0} status'.format(VPool.STATUSES.RUNNING)) for storagedriver in vpool.storagedrivers: pmachine = storagedriver.storagerouter.pmachine hypervisor = Factory.get(pmachine) for vm_object in hypervisor.get_vms_by_nfs_mountinfo(storagedriver.storage_ip, storagedriver.mountpoint): search_vpool = None if pmachine.hvtype == 'KVM' else vpool vmachine = VMachineList.get_by_devicename_and_vpool(devicename=vm_object['backing']['filename'], vpool=search_vpool) VMachineController.update_vmachine_config(vmachine, vm_object, pmachine)
def configure_host(pmachine_guid, mgmtcenter_guid, update_link): pmachine = PMachine(pmachine_guid) mgmt_center = MgmtCenter(mgmtcenter_guid) mgmt_center_client = None try: mgmt_center_client = Factory.get_mgmtcenter( mgmt_center=mgmt_center) except Exception as ex: logger.error('Cannot get management center client: {0}'.format(ex)) if mgmt_center_client is not None: logger.info('Configuring host {0} on management center {1}'.format( pmachine.name, mgmt_center.name)) mgmt_center_client.configure_host(pmachine.ip) if update_link is True: pmachine.mgmtcenter = mgmt_center pmachine.save()
def test_connection(mgmt_center_guid): """ Test management center connection """ mgmt_center = MgmtCenter(mgmt_center_guid) try: mgmt_center_client = Factory.get_mgmtcenter(mgmt_center=mgmt_center) except Exception as ex: logger.error('Cannot get mgmt center client: {0}'.format(ex)) return None try: is_mgmt_center = mgmt_center_client.test_connection() except Exception as ex: logger.error('Cannot test connection: {0}'.format(ex)) return False return is_mgmt_center
def test_connection(mgmt_center_guid): """ Test mgmtcenter connection """ mgmt_center = MgmtCenter(mgmt_center_guid) try: mgmt_center_client = Factory.get_mgmtcenter( mgmt_center=mgmt_center) except Exception as ex: logger.error('Cannot get mgmt center client: %s' % ex) return None try: is_mgmt_center = mgmt_center_client.test_connection() except Exception as ex: logger.error('Cannot test connection: %s' % ex) return False return is_mgmt_center
def rename_from_voldrv(old_name, new_name, storagedriver_id): """ This machine will handle the rename of a vmx file :param old_name: Old name of vmx :param new_name: New name for the vmx :param storagedriver_id: Storage Driver hosting the vmachine """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) if pmachine.hvtype not in ['VMWARE', 'KVM']: return hypervisor = Factory.get(pmachine) if pmachine.hvtype == 'VMWARE': storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) vpool = storagedriver.vpool else: vpool = None old_name = hypervisor.clean_vmachine_filename(old_name) new_name = hypervisor.clean_vmachine_filename(new_name) scenario = hypervisor.get_rename_scenario(old_name, new_name) if scenario == 'RENAME': # Most likely a change from path. Updating path vm = VMachineList.get_by_devicename_and_vpool(old_name, vpool) if vm is not None: vm.devicename = new_name vm.save() elif scenario == 'UPDATE': vm = VMachineList.get_by_devicename_and_vpool(new_name, vpool) if vm is None: # The vMachine doesn't seem to exist, so it's likely the create didn't came trough # Let's create it anyway VMachineController.update_from_voldrv( new_name, storagedriver_id=storagedriver_id) vm = VMachineList.get_by_devicename_and_vpool(new_name, vpool) if vm is None: raise RuntimeError( 'Could not create vMachine on rename. Aborting.') try: VMachineController.sync_with_hypervisor( vm.guid, storagedriver_id=storagedriver_id) vm.status = 'SYNC' except: vm.status = 'SYNC_NOK' vm.save()
def clone(diskguid, snapshotid, devicename, pmachineguid, machinename, machineguid=None): """ Clone a disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) description = "{} {}".format(machinename, devicename) properties_to_clone = ["description", "size", "type", "retentionpolicyguid", "snapshotpolicyguid", "autobackup"] vdisk = VDisk(diskguid) location = hypervisor.get_backing_disk_path(machinename, devicename) new_vdisk = VDisk() new_vdisk.copy(vdisk, include=properties_to_clone) new_vdisk.parent_vdisk = vdisk new_vdisk.name = "{0}-clone".format(vdisk.name) new_vdisk.description = description new_vdisk.devicename = hypervisor.clean_backing_disk_filename(location) new_vdisk.parentsnapshot = snapshotid new_vdisk.vmachine = VMachine(machineguid) if machineguid else vdisk.vmachine new_vdisk.vpool = vdisk.vpool new_vdisk.save() storagedriver = StorageDriverList.get_by_storagedriver_id(vdisk.storagedriver_id) if storagedriver is None: raise RuntimeError("Could not find StorageDriver with id {0}".format(vdisk.storagedriver_id)) mds_service = MDSServiceController.get_preferred_mds(storagedriver.storagerouter, vdisk.vpool) if mds_service is None: raise RuntimeError("Could not find a MDS service") logger.info("Clone snapshot {} of disk {} to location {}".format(snapshotid, vdisk.name, location)) volume_id = vdisk.storagedriver_client.create_clone( target_path=location, metadata_backend_config=MDSMetaDataBackendConfig( [MDSNodeConfig(address=str(mds_service.service.storagerouter.ip), port=mds_service.service.ports[0])] ), parent_volume_id=str(vdisk.volume_id), parent_snapshot_id=str(snapshotid), node_id=str(vdisk.storagedriver_id), ) new_vdisk.volume_id = volume_id new_vdisk.save() MDSServiceController.ensure_safety(new_vdisk) return {"diskguid": new_vdisk.guid, "name": new_vdisk.name, "backingdevice": location}
def rename_from_voldrv(volumename, volume_old_path, volume_new_path, storagedriver_id): """ Rename a disk Triggered by volumedriver messages @param volumename: volume id of the disk @param volume_old_path: old path on hypervisor to the volume @param volume_new_path: new path on hypervisor to the volume """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) hypervisor = Factory.get(pmachine) volume_old_path = hypervisor.clean_backing_disk_filename(volume_old_path) volume_new_path = hypervisor.clean_backing_disk_filename(volume_new_path) disk = VDiskList.get_vdisk_by_volume_id(volumename) if disk: logger.info("Move disk {} from {} to {}".format(disk.name, volume_old_path, volume_new_path)) disk.devicename = volume_new_path disk.save()
def update_vmachine_name(instance_id, old_name, new_name): """ Update a vMachine name: find vmachine by management center instance id, set new name :param instance_id: ID for the virtual machine known by management center :param old_name: Old name of the virtual machine :param new_name: New name for the virtual machine """ vmachine = None for mgmt_center in MgmtCenterList.get_mgmtcenters(): mgmt = Factory.get_mgmtcenter(mgmt_center=mgmt_center) try: machine_info = mgmt.get_vmachine_device_info(instance_id) file_name = machine_info['file_name'] host_name = machine_info['host_name'] vpool_name = machine_info['vpool_name'] storage_router = StorageRouterList.get_by_name(host_name) machine_id = storage_router.machine_id device_name = '{0}/{1}'.format(machine_id, file_name) vp = VPoolList.get_vpool_by_name(vpool_name) vmachine = VMachineList.get_by_devicename_and_vpool( device_name, vp) if vmachine: break vmachine = VMachineList.get_by_devicename_and_vpool( device_name, None) if vmachine: break except Exception as ex: logger.info( 'Trying to get mgmt center failed for vmachine {0}. {1}'. format(old_name, ex)) if not vmachine: logger.error('No vmachine found for name {0}'.format(old_name)) return vpool = vmachine.vpool mutex = VolatileMutex('{0}_{1}'.format( old_name, vpool.guid if vpool is not None else 'none')) try: mutex.acquire(wait=5) vmachine.name = new_name vmachine.save() finally: mutex.release()
def test_connection(mgmt_center_guid): """ Test management center connection """ mgmt_center = MgmtCenter(mgmt_center_guid) try: mgmt_center_client = Factory.get_mgmtcenter( mgmt_center=mgmt_center) except Exception as ex: MgmtCenterController._logger.error( 'Cannot get mgmt center client: {0}'.format(ex)) return None try: is_mgmt_center = mgmt_center_client.test_connection() except Exception as ex: MgmtCenterController._logger.error( 'Cannot test connection: {0}'.format(ex)) return False return is_mgmt_center
def delete_from_voldrv(volumename, storagedriver_id): """ Delete a disk Triggered by volumedriver messages on the queue @param volumename: volume id of the disk """ _ = storagedriver_id # For logging purposes disk = VDiskList.get_vdisk_by_volume_id(volumename) if disk is not None: mutex = VolatileMutex('{}_{}'.format(volumename, disk.devicename)) try: mutex.acquire(wait=20) pmachine = None try: pmachine = PMachineList.get_by_storagedriver_id( disk.storagedriver_id) except RuntimeError as ex: if 'could not be found' not in str(ex): raise # else: pmachine can't be loaded, because the volumedriver doesn't know about it anymore if pmachine is not None: limit = 5 storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) hypervisor = Factory.get(pmachine) exists = hypervisor.file_exists(storagedriver, disk.devicename) while limit > 0 and exists is True: time.sleep(1) exists = hypervisor.file_exists( storagedriver, disk.devicename) limit -= 1 if exists is True: logger.info( 'Disk {0} still exists, ignoring delete'.format( disk.devicename)) return logger.info('Delete disk {}'.format(disk.name)) for mds_service in disk.mds_services: mds_service.delete() disk.delete() finally: mutex.release()
def rename_from_voldrv(old_name, new_name, storagedriver_id): """ This machine will handle the rename of a vmx file :param old_name: Old name of vmx :param new_name: New name for the vmx :param storagedriver_id: Storage Driver hosting the vmachine """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) if pmachine.hvtype not in ['VMWARE', 'KVM']: return hypervisor = Factory.get(pmachine) if pmachine.hvtype == 'VMWARE': storagedriver = StorageDriverList.get_by_storagedriver_id(storagedriver_id) vpool = storagedriver.vpool else: vpool = None old_name = hypervisor.clean_vmachine_filename(old_name) new_name = hypervisor.clean_vmachine_filename(new_name) scenario = hypervisor.get_rename_scenario(old_name, new_name) if scenario == 'RENAME': # Most likely a change from path. Updating path vm = VMachineList.get_by_devicename_and_vpool(old_name, vpool) if vm is not None: vm.devicename = new_name vm.save() elif scenario == 'UPDATE': vm = VMachineList.get_by_devicename_and_vpool(new_name, vpool) if vm is None: # The vMachine doesn't seem to exist, so it's likely the create didn't came trough # Let's create it anyway VMachineController.update_from_voldrv(new_name, storagedriver_id=storagedriver_id) vm = VMachineList.get_by_devicename_and_vpool(new_name, vpool) if vm is None: raise RuntimeError('Could not create vMachine on rename. Aborting.') try: VMachineController.sync_with_hypervisor(vm.guid, storagedriver_id=storagedriver_id) vm.status = 'SYNC' except: vm.status = 'SYNC_NOK' vm.save()
def delete_from_voldrv(name, storagedriver_id): """ This method will delete a vmachine based on the name of the vmx given """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) if pmachine.hvtype not in ['VMWARE', 'KVM']: return hypervisor = Factory.get(pmachine) name = hypervisor.clean_vmachine_filename(name) if pmachine.hvtype == 'VMWARE': storagedriver = StorageDriverList.get_by_storagedriver_id(storagedriver_id) vpool = storagedriver.vpool else: vpool = None vm = VMachineList.get_by_devicename_and_vpool(name, vpool) if vm is not None: MessageController.fire(MessageController.Type.EVENT, {'type': 'vmachine_deleted', 'metadata': {'name': vm.name}}) vm.delete(abandon=['vdisks'])
def sync_with_hypervisor(vpool_guid): """ Syncs all vMachines of a given vPool with the hypervisor :param vpool_guid: Guid of the vPool to synchronize """ vpool = VPool(vpool_guid) if vpool.status != VPool.STATUSES.RUNNING: raise ValueError( 'Synchronizing with hypervisor is only allowed if your vPool is in {0} status' .format(VPool.STATUSES.RUNNING)) for storagedriver in vpool.storagedrivers: pmachine = storagedriver.storagerouter.pmachine hypervisor = Factory.get(pmachine) for vm_object in hypervisor.get_vms_by_nfs_mountinfo( storagedriver.storage_ip, storagedriver.mountpoint): search_vpool = None if pmachine.hvtype == 'KVM' else vpool vmachine = VMachineList.get_by_devicename_and_vpool( devicename=vm_object['backing']['filename'], vpool=search_vpool) VMachineController.update_vmachine_config( vmachine, vm_object, pmachine)
def delete(machineguid): """ Delete a vmachine @param machineguid: guid of the machine """ machine = VMachine(machineguid) storagedriver_mountpoint, storagedriver_storage_ip = None, None try: storagedriver = [storagedriver for storagedriver in machine.vpool.storagedrivers if storagedriver.storagerouter.pmachine_guid == machine.pmachine_guid][0] storagedriver_mountpoint = storagedriver.mountpoint storagedriver_storage_ip = storagedriver.storage_ip except Exception as ex: VMachineController._logger.debug('No mountpoint info could be retrieved. Reason: {0}'.format(str(ex))) storagedriver_mountpoint = None disks_info = [] for vd in machine.vdisks: for storagedriver in vd.vpool.storagedrivers: if storagedriver.storagerouter.pmachine_guid == machine.pmachine_guid: disks_info.append((storagedriver.mountpoint, vd.devicename)) if machine.pmachine: # Allow hypervisor id node, lookup strategy is hypervisor dependent try: hypervisor_id = machine.hypervisor_id if machine.pmachine.hvtype == 'KVM': hypervisor_id = machine.name # On KVM we can lookup the machine by name, not by id hv = Factory.get(machine.pmachine) hv.delete_vm(hypervisor_id, storagedriver_mountpoint, storagedriver_storage_ip, machine.devicename, disks_info, True) except Exception as exception: VMachineController._logger.error('Deletion of vm on hypervisor failed: {0}'.format(str(exception)), print_msg=True) for disk in machine.vdisks: VMachineController._logger.debug('Deleting disk {0} with guid: {1}'.format(disk.name, disk.guid)) for junction in disk.mds_services: junction.delete() disk.delete() VMachineController._logger.debug('Deleting vmachine {0} with guid {1}'.format(machine.name, machine.guid)) machine.delete()
def rename_from_voldrv(volumename, volume_old_path, volume_new_path, storagedriver_id): """ Rename a disk Triggered by volumedriver messages @param volumename: volume id of the disk @param volume_old_path: old path on hypervisor to the volume @param volume_new_path: new path on hypervisor to the volume """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) hypervisor = Factory.get(pmachine) volume_old_path = hypervisor.clean_backing_disk_filename( volume_old_path) volume_new_path = hypervisor.clean_backing_disk_filename( volume_new_path) disk = VDiskList.get_vdisk_by_volume_id(volumename) if disk: logger.info('Move disk {} from {} to {}'.format( disk.name, volume_old_path, volume_new_path)) disk.devicename = volume_new_path disk.save()
def update_vmachine_name(instance_id, old_name, new_name): """ Update a vMachine name: find vmachine by management center instance id, set new name :param instance_id: ID for the virtual machine known by management center :param old_name: Old name of the virtual machine :param new_name: New name for the virtual machine """ vmachine = None for mgmt_center in MgmtCenterList.get_mgmtcenters(): mgmt = Factory.get_mgmtcenter(mgmt_center = mgmt_center) try: machine_info = mgmt.get_vmachine_device_info(instance_id) file_name = machine_info['file_name'] host_name = machine_info['host_name'] vpool_name = machine_info['vpool_name'] storage_router = StorageRouterList.get_by_name(host_name) machine_id = storage_router.machine_id device_name = '{0}/{1}'.format(machine_id, file_name) vp = VPoolList.get_vpool_by_name(vpool_name) vmachine = VMachineList.get_by_devicename_and_vpool(device_name, vp) if vmachine: break vmachine = VMachineList.get_by_devicename_and_vpool(device_name, None) if vmachine: break except Exception as ex: VMachineController._logger.info('Trying to get mgmt center failed for vmachine {0}. {1}'.format(old_name, ex)) if not vmachine: VMachineController._logger.error('No vmachine found for name {0}'.format(old_name)) return vpool = vmachine.vpool mutex = volatile_mutex('{0}_{1}'.format(old_name, vpool.guid if vpool is not None else 'none')) try: mutex.acquire(wait=5) vmachine.name = new_name vmachine.save() finally: mutex.release()
def clone(diskguid, snapshotid, devicename, pmachineguid, machinename, machineguid=None, **kwargs): """ Clone a disk @param location: location where virtual device should be created (eg: myVM) @param devicename: device file name for the disk (eg: mydisk-flat.vmdk) @param parentdiskguid: guid of the disk @param snapshotid: guid of the snapshot @param machineguid: guid of the machine to assign disk to """ _ = kwargs pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) description = '{} {}'.format(machinename, devicename) properties_to_clone = ['description', 'size', 'type', 'retentionpolicyguid', 'snapshotpolicyguid', 'autobackup'] new_disk = VDisk() disk = VDisk(diskguid) _log = 'Clone snapshot {} of disk {} to location {}' _location = hypervisor.get_backing_disk_path(machinename, devicename) _id = '{}'.format(disk.volume_id) _snap = '{}'.format(snapshotid) logger.info(_log.format(_snap, disk.name, _location)) volume_id = disk.storagedriver_client.create_clone(_location, _id, _snap) new_disk.copy(disk, include=properties_to_clone) new_disk.parent_vdisk = disk new_disk.name = '{}-clone'.format(disk.name) new_disk.description = description new_disk.volume_id = volume_id new_disk.devicename = hypervisor.clean_backing_disk_filename(_location) new_disk.parentsnapshot = snapshotid new_disk.vmachine = VMachine(machineguid) if machineguid else disk.vmachine new_disk.vpool = disk.vpool new_disk.save() return {'diskguid': new_disk.guid, 'name': new_disk.name, 'backingdevice': _location}
def create(self, request): """ Creates a Management Center """ serializer = FullSerializer(MgmtCenter, instance=MgmtCenter(), data=request.DATA, allow_passwords=True) if serializer.is_valid(): mgmt_center = serializer.object duplicate = MgmtCenterList.get_by_ip(mgmt_center.ip) if duplicate is None: try: mgmt_center_client = Factory.get_mgmtcenter(mgmt_center=mgmt_center) is_mgmt_center = mgmt_center_client.test_connection() except Exception as ex: logger.debug('Management center testing: {0}'.format(ex)) raise NotAcceptable('The given information is invalid.') if not is_mgmt_center: raise NotAcceptable('The given information is not for a Management center.') mgmt_center.save() return Response(serializer.data, status=status.HTTP_201_CREATED) else: raise NotAcceptable('A Mangement Center with this ip already exists.') else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def update_from_voldrv(name, storagedriver_id): """ This method will update/create a vmachine based on a given vmx/xml file """ pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) if pmachine.hvtype not in ['VMWARE', 'KVM']: return hypervisor = Factory.get(pmachine) name = hypervisor.clean_vmachine_filename(name) storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) vpool = storagedriver.vpool machine_ids = [ storagedriver.storagerouter.machine_id for storagedriver in vpool.storagedrivers ] if hypervisor.should_process(name, machine_ids=machine_ids): if pmachine.hvtype == 'VMWARE': storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) vpool = storagedriver.vpool else: vpool = None pmachine = PMachineList.get_by_storagedriver_id(storagedriver_id) mutex = VolatileMutex('{}_{}'.format( name, vpool.guid if vpool is not None else 'none')) try: mutex.acquire(wait=120) limit = 5 exists = hypervisor.file_exists(storagedriver, name) while limit > 0 and exists is False: time.sleep(1) exists = hypervisor.file_exists(storagedriver, name) limit -= 1 if exists is False: logger.info( 'Could not locate vmachine with name {0} on vpool {1}'. format(name, vpool.name)) vmachine = VMachineList.get_by_devicename_and_vpool( name, vpool) if vmachine is not None: VMachineController.delete_from_voldrv( name, storagedriver_id=storagedriver_id) return finally: mutex.release() try: mutex.acquire(wait=5) vmachine = VMachineList.get_by_devicename_and_vpool( name, vpool) if not vmachine: vmachine = VMachine() vmachine.vpool = vpool vmachine.pmachine = pmachine vmachine.status = 'CREATED' vmachine.devicename = name vmachine.save() finally: mutex.release() if pmachine.hvtype == 'KVM': try: VMachineController.sync_with_hypervisor( vmachine.guid, storagedriver_id=storagedriver_id) vmachine.status = 'SYNC' except: vmachine.status = 'SYNC_NOK' vmachine.save() else: logger.info('Ignored invalid file {0}'.format(name))
def create_from_template(name, machineguid, pmachineguid, description=None): """ Create a new vmachine using an existing vmachine template @param machineguid: guid of the template vmachine @param name: name of new vmachine @param pmachineguid: guid of hypervisor to create new vmachine on @return: guid of the newly created vmachine | False on any failure """ template_vm = VMachine(machineguid) if not template_vm.is_vtemplate: return False target_pm = PMachine(pmachineguid) target_hypervisor = Factory.get(target_pm) storagerouters = [ sr for sr in StorageRouterList.get_storagerouters() if sr.pmachine_guid == target_pm.guid ] if len(storagerouters) == 1: target_storagerouter = storagerouters[0] else: raise ValueError( 'Pmachine {} has no StorageRouter assigned to it'.format( pmachineguid)) routing_key = "sr.{0}".format(target_storagerouter.machine_id) vpool = None vpool_guids = set() if template_vm.vpool is not None: vpool = template_vm.vpool vpool_guids.add(vpool.guid) for disk in template_vm.vdisks: vpool = disk.vpool vpool_guids.add(vpool.guid) if len(vpool_guids) != 1: raise RuntimeError( 'Only 1 vpool supported on template disk(s) - {0} found!'. format(len(vpool_guids))) if not template_vm.pmachine.hvtype == target_pm.hvtype: raise RuntimeError('Source and target hypervisor not identical') # Currently, only one vPool is supported, so we can just use whatever the `vpool` variable above # was set to as 'the' vPool for the code below. This obviously will have to change once vPool mixes # are supported. target_storagedriver = None source_storagedriver = None for vpool_storagedriver in vpool.storagedrivers: if vpool_storagedriver.storagerouter.pmachine_guid == target_pm.guid: target_storagedriver = vpool_storagedriver if vpool_storagedriver.storagerouter.pmachine_guid == template_vm.pmachine_guid: source_storagedriver = vpool_storagedriver if target_storagedriver is None: raise RuntimeError('Volume not served on target hypervisor') source_hv = Factory.get(template_vm.pmachine) target_hv = Factory.get(target_pm) if not source_hv.is_datastore_available( source_storagedriver.storage_ip, source_storagedriver.mountpoint): raise RuntimeError('Datastore unavailable on source hypervisor') if not target_hv.is_datastore_available( target_storagedriver.storage_ip, target_storagedriver.mountpoint): raise RuntimeError('Datastore unavailable on target hypervisor') source_vm = source_hv.get_vm_object(template_vm.hypervisor_id) if not source_vm: raise RuntimeError('VM with key reference {0} not found'.format( template_vm.hypervisor_id)) name_duplicates = VMachineList.get_vmachine_by_name(name) if name_duplicates is not None and len(name_duplicates) > 0: raise RuntimeError( 'A vMachine with name {0} already exists'.format(name)) vm_path = target_hypervisor.get_vmachine_path( name, target_storagedriver.storagerouter.machine_id) new_vm = VMachine() new_vm.copy(template_vm) new_vm.hypervisor_id = '' new_vm.vpool = template_vm.vpool new_vm.pmachine = target_pm new_vm.name = name new_vm.description = description new_vm.is_vtemplate = False new_vm.devicename = target_hypervisor.clean_vmachine_filename(vm_path) new_vm.status = 'CREATED' new_vm.save() storagedrivers = [ storagedriver for storagedriver in vpool.storagedrivers if storagedriver.storagerouter.pmachine_guid == new_vm.pmachine_guid ] if len(storagedrivers) == 0: raise RuntimeError( 'Cannot find Storage Driver serving {0} on {1}'.format( vpool.name, new_vm.pmachine.name)) storagedriverguid = storagedrivers[0].guid disks = [] disks_by_order = sorted(template_vm.vdisks, key=lambda x: x.order) try: for disk in disks_by_order: prefix = '{0}-clone'.format(disk.name) result = VDiskController.create_from_template( diskguid=disk.guid, devicename=prefix, pmachineguid=target_pm.guid, machinename=new_vm.name, machineguid=new_vm.guid, storagedriver_guid=storagedriverguid) disks.append(result) logger.debug('Disk appended: {0}'.format(result)) except Exception as exception: logger.error('Creation of disk {0} failed: {1}'.format( disk.name, str(exception)), print_msg=True) VMachineController.delete.s(machineguid=new_vm.guid).apply_async( routing_key=routing_key) raise try: result = target_hv.create_vm_from_template( name, source_vm, disks, target_storagedriver.storage_ip, target_storagedriver.mountpoint, wait=True) except Exception as exception: logger.error('Creation of vm {0} on hypervisor failed: {1}'.format( new_vm.name, str(exception)), print_msg=True) VMachineController.delete.s(machineguid=new_vm.guid).apply_async( routing_key=routing_key) raise new_vm.hypervisor_id = result new_vm.status = 'SYNC' new_vm.save() return new_vm.guid
def clone(diskguid, snapshotid, devicename, pmachineguid, machinename, machineguid=None): """ Clone a disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) description = '{} {}'.format(machinename, devicename) properties_to_clone = [ 'description', 'size', 'type', 'retentionpolicyguid', 'snapshotpolicyguid', 'autobackup' ] vdisk = VDisk(diskguid) location = hypervisor.get_backing_disk_path(machinename, devicename) new_vdisk = VDisk() new_vdisk.copy(vdisk, include=properties_to_clone) new_vdisk.parent_vdisk = vdisk new_vdisk.name = '{0}-clone'.format(vdisk.name) new_vdisk.description = description new_vdisk.devicename = hypervisor.clean_backing_disk_filename(location) new_vdisk.parentsnapshot = snapshotid new_vdisk.vmachine = VMachine( machineguid) if machineguid else vdisk.vmachine new_vdisk.vpool = vdisk.vpool new_vdisk.save() try: storagedriver = StorageDriverList.get_by_storagedriver_id( vdisk.storagedriver_id) if storagedriver is None: raise RuntimeError( 'Could not find StorageDriver with id {0}'.format( vdisk.storagedriver_id)) mds_service = MDSServiceController.get_preferred_mds( storagedriver.storagerouter, vdisk.vpool) if mds_service is None: raise RuntimeError('Could not find a MDS service') logger.info('Clone snapshot {} of disk {} to location {}'.format( snapshotid, vdisk.name, location)) volume_id = vdisk.storagedriver_client.create_clone( target_path=location, metadata_backend_config=MDSMetaDataBackendConfig([ MDSNodeConfig(address=str( mds_service.service.storagerouter.ip), port=mds_service.service.ports[0]) ]), parent_volume_id=str(vdisk.volume_id), parent_snapshot_id=str(snapshotid), node_id=str(vdisk.storagedriver_id)) except Exception as ex: logger.error( 'Caught exception during clone, trying to delete the volume. {0}' .format(ex)) new_vdisk.delete() VDiskController.delete_volume(location) raise new_vdisk.volume_id = volume_id new_vdisk.save() try: MDSServiceController.ensure_safety(new_vdisk) except Exception as ex: logger.error( 'Caught exception during "ensure_safety" {0}'.format(ex)) return { 'diskguid': new_vdisk.guid, 'name': new_vdisk.name, 'backingdevice': location }
def create_from_template(diskguid, machinename, devicename, pmachineguid, machineguid=None, storagedriver_guid=None): """ Create a disk from a template @param devicename: device file name for the disk (eg: mydisk-flat.vmdk) @param machineguid: guid of the machine to assign disk to @return diskguid: guid of new disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) disk_path = hypervisor.get_disk_path(machinename, devicename) description = '{} {}'.format(machinename, devicename) properties_to_clone = [ 'description', 'size', 'type', 'retentionpolicyid', 'snapshotpolicyid', 'vmachine', 'vpool' ] vdisk = VDisk(diskguid) if vdisk.vmachine and not vdisk.vmachine.is_vtemplate: # Disk might not be attached to a vmachine, but still be a template raise RuntimeError('The given vdisk does not belong to a template') if storagedriver_guid is not None: storagedriver_id = StorageDriver( storagedriver_guid).storagedriver_id else: storagedriver_id = vdisk.storagedriver_id storagedriver = StorageDriverList.get_by_storagedriver_id( storagedriver_id) if storagedriver is None: raise RuntimeError( 'Could not find StorageDriver with id {0}'.format( storagedriver_id)) new_vdisk = VDisk() new_vdisk.copy(vdisk, include=properties_to_clone) new_vdisk.vpool = vdisk.vpool new_vdisk.devicename = hypervisor.clean_backing_disk_filename( disk_path) new_vdisk.parent_vdisk = vdisk new_vdisk.name = '{}-clone'.format(vdisk.name) new_vdisk.description = description new_vdisk.vmachine = VMachine( machineguid) if machineguid else vdisk.vmachine new_vdisk.save() mds_service = MDSServiceController.get_preferred_mds( storagedriver.storagerouter, vdisk.vpool) if mds_service is None: raise RuntimeError('Could not find a MDS service') logger.info( 'Create disk from template {} to new disk {} to location {}'. format(vdisk.name, new_vdisk.name, disk_path)) try: volume_id = vdisk.storagedriver_client.create_clone_from_template( target_path=disk_path, metadata_backend_config=MDSMetaDataBackendConfig([ MDSNodeConfig(address=str( mds_service.service.storagerouter.ip), port=mds_service.service.ports[0]) ]), parent_volume_id=str(vdisk.volume_id), node_id=str(storagedriver_id)) new_vdisk.volume_id = volume_id new_vdisk.save() MDSServiceController.ensure_safety(new_vdisk) except Exception as ex: logger.error( 'Clone disk on volumedriver level failed with exception: {0}'. format(str(ex))) new_vdisk.delete() raise return { 'diskguid': new_vdisk.guid, 'name': new_vdisk.name, 'backingdevice': disk_path }
def create_from_template(diskguid, machinename, devicename, pmachineguid, machineguid=None, storagedriver_guid=None): """ Create a disk from a template @param devicename: device file name for the disk (eg: mydisk-flat.vmdk) @param machineguid: guid of the machine to assign disk to @return diskguid: guid of new disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) disk_path = hypervisor.get_disk_path(machinename, devicename) description = '{} {}'.format(machinename, devicename) properties_to_clone = [ 'description', 'size', 'type', 'retentionpolicyid', 'snapshotpolicyid', 'vmachine', 'vpool'] vdisk = VDisk(diskguid) if vdisk.vmachine and not vdisk.vmachine.is_vtemplate: # Disk might not be attached to a vmachine, but still be a template raise RuntimeError('The given vdisk does not belong to a template') if storagedriver_guid is not None: storagedriver_id = StorageDriver(storagedriver_guid).storagedriver_id else: storagedriver_id = vdisk.storagedriver_id storagedriver = StorageDriverList.get_by_storagedriver_id(storagedriver_id) if storagedriver is None: raise RuntimeError('Could not find StorageDriver with id {0}'.format(storagedriver_id)) new_vdisk = VDisk() new_vdisk.copy(vdisk, include=properties_to_clone) new_vdisk.vpool = vdisk.vpool new_vdisk.devicename = hypervisor.clean_backing_disk_filename(disk_path) new_vdisk.parent_vdisk = vdisk new_vdisk.name = '{}-clone'.format(vdisk.name) new_vdisk.description = description new_vdisk.vmachine = VMachine(machineguid) if machineguid else vdisk.vmachine new_vdisk.save() mds_service = MDSServiceController.get_preferred_mds(storagedriver.storagerouter, vdisk.vpool) if mds_service is None: raise RuntimeError('Could not find a MDS service') logger.info('Create disk from template {} to new disk {} to location {}'.format( vdisk.name, new_vdisk.name, disk_path )) try: volume_id = vdisk.storagedriver_client.create_clone_from_template( target_path=disk_path, metadata_backend_config=MDSMetaDataBackendConfig([MDSNodeConfig(address=str(mds_service.service.storagerouter.ip), port=mds_service.service.ports[0])]), parent_volume_id=str(vdisk.volume_id), node_id=str(storagedriver_id) ) new_vdisk.volume_id = volume_id new_vdisk.save() MDSServiceController.ensure_safety(new_vdisk) except Exception as ex: logger.error('Clone disk on volumedriver level failed with exception: {0}'.format(str(ex))) new_vdisk.delete() raise return {'diskguid': new_vdisk.guid, 'name': new_vdisk.name, 'backingdevice': disk_path}
def clone(diskguid, snapshotid, devicename, pmachineguid, machinename=None, machineguid=None, detached=False): """ Clone a disk :param diskguid: Guid of the disk to clone :param snapshotid: ID of the snapshot to clone from :param devicename: Name of the device to use in clone's description :param pmachineguid: Guid of the physical machine :param machinename: Name of the machine the disk is attached to :param machineguid: Guid of the machine :param detached: Boolean indicating the disk is attached to a machine or not """ # 1. Validations name_regex = "^[0-9a-zA-Z][-_a-zA-Z0-9]{1,48}[a-zA-Z0-9]$" if not re.match(name_regex, devicename): raise RuntimeError("Invalid name for virtual disk clone") if VDiskList.get_vdisk_by_name(vdiskname=devicename) is not None: raise RuntimeError("A virtual disk with this name already exists") vdisk = VDisk(diskguid) storagedriver = StorageDriverList.get_by_storagedriver_id(vdisk.storagedriver_id) if storagedriver is None: raise RuntimeError('Could not find StorageDriver with ID {0}'.format(vdisk.storagedriver_id)) if machineguid is not None and detached is True: raise ValueError('A vMachine GUID was specified while detached is True') # 2. Create new snapshot if required if snapshotid is None: timestamp = str(int(time.time())) metadata = {'label': '', 'is_consistent': False, 'timestamp': timestamp, 'machineguid': machineguid, 'is_automatic': True} sd_snapshot_id = VDiskController.create_snapshot(diskguid, metadata) tries = 25 # 5 minutes while snapshotid is None and tries > 0: time.sleep(25 - tries) tries -= 1 vdisk.invalidate_dynamics(['snapshots']) for snapshot in vdisk.snapshots: if snapshot['guid'] != sd_snapshot_id: continue if snapshot['in_backend'] is True: snapshotid = snapshot['guid'] if snapshotid is None: try: VDiskController.delete_snapshot(diskguid=diskguid, snapshotid=sd_snapshot_id) except: pass raise RuntimeError('Could not find created snapshot in time') # 3. Model new cloned virtual disk hypervisor = Factory.get(PMachine(pmachineguid)) location = hypervisor.get_disk_path(machinename, devicename) new_vdisk = VDisk() new_vdisk.copy(vdisk, include=['description', 'size', 'type', 'retentionpolicyguid', 'snapshotpolicyguid', 'autobackup']) new_vdisk.parent_vdisk = vdisk new_vdisk.name = devicename new_vdisk.description = devicename if machinename is None else '{0} {1}'.format(machinename, devicename) new_vdisk.devicename = hypervisor.clean_backing_disk_filename(location) new_vdisk.parentsnapshot = snapshotid if detached is False: new_vdisk.vmachine = VMachine(machineguid) if machineguid else vdisk.vmachine new_vdisk.vpool = vdisk.vpool new_vdisk.save() # 4. Configure Storage Driver try: mds_service = MDSServiceController.get_preferred_mds(storagedriver.storagerouter, vdisk.vpool) if mds_service is None: raise RuntimeError('Could not find a MDS service') logger.info('Clone snapshot {0} of disk {1} to location {2}'.format(snapshotid, vdisk.name, location)) backend_config = MDSMetaDataBackendConfig([MDSNodeConfig(address=str(mds_service.service.storagerouter.ip), port=mds_service.service.ports[0])]) volume_id = vdisk.storagedriver_client.create_clone(target_path=location, metadata_backend_config=backend_config, parent_volume_id=str(vdisk.volume_id), parent_snapshot_id=str(snapshotid), node_id=str(vdisk.storagedriver_id)) except Exception as ex: logger.error('Caught exception during clone, trying to delete the volume. {0}'.format(ex)) try: VDiskController.clean_bad_disk(new_vdisk.guid) except Exception as ex2: logger.exception('Exception during exception handling of "create_clone_from_template" : {0}'.format(str(ex2))) raise new_vdisk.volume_id = volume_id new_vdisk.save() # 5. Check MDS & DTL for new clone try: MDSServiceController.ensure_safety(new_vdisk) except Exception as ex: logger.error('Caught exception during "ensure_safety" {0}'.format(ex)) VDiskController.dtl_checkup.delay(vdisk_guid=new_vdisk.guid) return {'diskguid': new_vdisk.guid, 'name': new_vdisk.name, 'backingdevice': location}
def create_from_template(diskguid, machinename, devicename, pmachineguid, machineguid=None, storagedriver_guid=None): """ Create a disk from a template @param parentdiskguid: guid of the disk @param location: location where virtual device should be created (eg: myVM) @param devicename: device file name for the disk (eg: mydisk-flat.vmdk) @param machineguid: guid of the machine to assign disk to @return diskguid: guid of new disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) disk_path = hypervisor.get_disk_path(machinename, devicename) description = '{} {}'.format(machinename, devicename) properties_to_clone = [ 'description', 'size', 'type', 'retentionpolicyid', 'snapshotpolicyid', 'vmachine', 'vpool' ] disk = VDisk(diskguid) if disk.vmachine and not disk.vmachine.is_vtemplate: # Disk might not be attached to a vmachine, but still be a template raise RuntimeError('The given disk does not belong to a template') if storagedriver_guid is not None: storagedriver_id = StorageDriver( storagedriver_guid).storagedriver_id else: storagedriver_id = disk.storagedriver_id new_disk = VDisk() new_disk.copy(disk, include=properties_to_clone) new_disk.vpool = disk.vpool new_disk.devicename = hypervisor.clean_backing_disk_filename(disk_path) new_disk.parent_vdisk = disk new_disk.name = '{}-clone'.format(disk.name) new_disk.description = description new_disk.vmachine = VMachine( machineguid) if machineguid else disk.vmachine new_disk.save() logger.info( 'Create disk from template {} to new disk {} to location {}'. format(disk.name, new_disk.name, disk_path)) try: volume_id = disk.storagedriver_client.create_clone_from_template( disk_path, str(disk.volume_id), node_id=str(storagedriver_id)) new_disk.volume_id = volume_id new_disk.save() except Exception as ex: logger.error( 'Clone disk on volumedriver level failed with exception: {0}'. format(str(ex))) new_disk.delete() raise return { 'diskguid': new_disk.guid, 'name': new_disk.name, 'backingdevice': disk_path }
def clone(machineguid, timestamp, name): """ Clone a vmachine using the disk snapshot based on a snapshot timestamp @param machineguid: guid of the machine to clone @param timestamp: timestamp of the disk snapshots to use for the clone @param name: name for the new machine """ machine = VMachine(machineguid) timestamp = str(timestamp) if timestamp not in (snap['timestamp'] for snap in machine.snapshots): raise RuntimeError('Invalid timestamp provided, not a valid snapshot of this vmachine.') vpool = None storagerouter = None if machine.pmachine is not None and machine.pmachine.hvtype == 'VMWARE': for vdisk in machine.vdisks: if vdisk.vpool is not None: vpool = vdisk.vpool break for vdisk in machine.vdisks: if vdisk.storagerouter_guid: storagerouter = StorageRouter(vdisk.storagerouter_guid) break hv = Factory.get(machine.pmachine) vm_path = hv.get_vmachine_path(name, storagerouter.machine_id if storagerouter is not None else '') # mutex in sync_with_hypervisor uses "None" for KVM hvtype mutex = volatile_mutex('{0}_{1}'.format(hv.clean_vmachine_filename(vm_path), vpool.guid if vpool is not None else 'none')) disks = {} for snapshot in machine.snapshots: if snapshot['timestamp'] == timestamp: for diskguid, snapshotguid in snapshot['snapshots'].iteritems(): disks[diskguid] = snapshotguid try: mutex.acquire(wait=120) new_machine = VMachine() new_machine.copy(machine) new_machine.name = name new_machine.devicename = hv.clean_vmachine_filename(vm_path) new_machine.pmachine = machine.pmachine new_machine.save() finally: mutex.release() new_disk_guids = [] vm_disks = [] mountpoint = None disks_by_order = sorted(machine.vdisks, key=lambda x: x.order) try: for currentDisk in disks_by_order: if machine.is_vtemplate and currentDisk.templatesnapshot: snapshotid = currentDisk.templatesnapshot else: snapshotid = disks[currentDisk.guid] prefix = '%s-clone' % currentDisk.name result = VDiskController.clone(diskguid=currentDisk.guid, snapshotid=snapshotid, devicename=prefix, pmachineguid=new_machine.pmachine_guid, machinename=new_machine.name, machineguid=new_machine.guid) new_disk_guids.append(result['diskguid']) mountpoint = StorageDriverList.get_by_storagedriver_id(currentDisk.storagedriver_id).mountpoint vm_disks.append(result) except Exception as ex: VMachineController._logger.error('Failed to clone disks. {0}'.format(ex)) VMachineController.delete(machineguid=new_machine.guid) raise try: result = hv.clone_vm(machine.hypervisor_id, name, vm_disks, mountpoint) except Exception as ex: VMachineController._logger.error('Failed to clone vm. {0}'.format(ex)) VMachineController.delete(machineguid=new_machine.guid) raise try: mutex.acquire(wait=120) new_machine.hypervisor_id = result new_machine.save() finally: mutex.release() return new_machine.guid
def create_from_template(diskguid, devicename, pmachineguid, machinename='', machineguid=None): """ Create a disk from a template :param diskguid: Guid of the disk :param machinename: Name of the machine :param devicename: Device file name for the disk (eg: my_disk-flat.vmdk) :param pmachineguid: Guid of pmachine to create new vdisk on :param machineguid: Guid of the machine to assign disk to :return diskguid: Guid of new disk """ pmachine = PMachine(pmachineguid) hypervisor = Factory.get(pmachine) if machineguid is not None: new_vdisk_vmachine = VMachine(machineguid) machinename = new_vdisk_vmachine.name disk_path = hypervisor.get_disk_path(machinename, devicename) description = '{0} {1}'.format(machinename, devicename) properties_to_clone = [ 'description', 'size', 'type', 'retentionpolicyid', 'snapshotpolicyid', 'vmachine', 'vpool'] vdisk = VDisk(diskguid) if vdisk.vmachine and not vdisk.vmachine.is_vtemplate: # Disk might not be attached to a vmachine, but still be a template raise RuntimeError('The given vdisk does not belong to a template') if not vdisk.is_vtemplate: raise RuntimeError('The given vdisk is not a template') storagedriver = None for sd in vdisk.vpool.storagedrivers: if sd.storagerouter_guid in pmachine.storagerouters_guids: storagedriver = sd break if storagedriver is None: raise RuntimeError('Could not find Storage Driver') new_vdisk = VDisk() new_vdisk.copy(vdisk, include=properties_to_clone) new_vdisk.vpool = vdisk.vpool new_vdisk.devicename = hypervisor.clean_backing_disk_filename(disk_path) new_vdisk.parent_vdisk = vdisk new_vdisk.name = '{0}-clone'.format(vdisk.name) new_vdisk.description = description new_vdisk.vmachine = new_vdisk_vmachine if machineguid else vdisk.vmachine new_vdisk.save() mds_service = MDSServiceController.get_preferred_mds(storagedriver.storagerouter, new_vdisk.vpool) if mds_service is None: raise RuntimeError('Could not find a MDS service') logger.info('Create disk from template {0} to new disk {1} to location {2}'.format(vdisk.name, new_vdisk.name, disk_path)) try: backend_config = MDSNodeConfig(address=str(mds_service.service.storagerouter.ip), port=mds_service.service.ports[0]) volume_id = vdisk.storagedriver_client.create_clone_from_template(target_path=disk_path, metadata_backend_config=MDSMetaDataBackendConfig([backend_config]), parent_volume_id=str(vdisk.volume_id), node_id=str(storagedriver.storagedriver_id)) new_vdisk.volume_id = volume_id new_vdisk.save() MDSServiceController.ensure_safety(new_vdisk) VDiskController.dtl_checkup.delay(vdisk_guid=new_vdisk.guid) except Exception as ex: logger.error('Clone disk on volumedriver level failed with exception: {0}'.format(str(ex))) try: VDiskController.clean_bad_disk(new_vdisk.guid) except Exception as ex2: logger.exception('Exception during exception handling of "create_clone_from_template" : {0}'.format(str(ex2))) raise ex return {'diskguid': new_vdisk.guid, 'name': new_vdisk.name, 'backingdevice': disk_path}