Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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()
Пример #5
0
    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)
Пример #6
0
    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'])
Пример #7
0
    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()
Пример #8
0
    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()
Пример #9
0
    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()
Пример #10
0
 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)
Пример #11
0
    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))
Пример #12
0
 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()
Пример #13
0
    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}
Пример #14
0
 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 {}
Пример #15
0
 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 {}
Пример #16
0
 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)
Пример #17
0
    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()
Пример #18
0
    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)
Пример #19
0
    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}
Пример #20
0
 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'
Пример #21
0
 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'
Пример #22
0
 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'
Пример #23
0
 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'
Пример #24
0
 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)
Пример #25
0
    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
Пример #26
0
    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()
Пример #27
0
    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
Пример #28
0
    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
Пример #29
0
    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
        }
Пример #30
0
 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()
Пример #31
0
    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
Пример #32
0
 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)
Пример #33
0
 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)
Пример #34
0
 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()
Пример #35
0
 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
Пример #36
0
 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
Пример #37
0
    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()
Пример #38
0
    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}
Пример #39
0
    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()
Пример #40
0
    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()
Пример #41
0
 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
Пример #42
0
 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()
Пример #43
0
    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()
Пример #44
0
    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'])
Пример #45
0
 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)
Пример #46
0
    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()
Пример #47
0
    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()
Пример #48
0
    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()
Пример #49
0
    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}
Пример #50
0
 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)
Пример #51
0
    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))
Пример #52
0
    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
Пример #53
0
    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
        }
Пример #54
0
    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
        }
Пример #55
0
    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}
Пример #56
0
    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}
Пример #57
0
    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
        }
Пример #58
0
    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
Пример #59
0
    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}