def clone(machineguid, timestamp, name): """ Clone a vmachine using the disk snapshot based on a snapshot timestamp @param machineguid: guid of the machine to clone @param timestamp: timestamp of the disk snapshots to use for the clone @param name: name for the new machine """ machine = VMachine(machineguid) disks = {} for snapshot in machine.snapshots: if snapshot['timestamp'] == timestamp: for diskguid, snapshotguid in snapshot['snapshots'].iteritems( ): disks[diskguid] = snapshotguid new_machine = VMachine() new_machine.copy(machine) new_machine.name = name new_machine.pmachine = machine.pmachine new_machine.save() new_disk_guids = [] disks_by_order = sorted(machine.vdisks, key=lambda x: x.order) for currentDisk in disks_by_order: if machine.is_vtemplate and currentDisk.templatesnapshot: snapshotid = currentDisk.templatesnapshot else: snapshotid = disks[currentDisk.guid] prefix = '%s-clone' % currentDisk.name result = VDiskController.clone( diskguid=currentDisk.guid, snapshotid=snapshotid, devicename=prefix, pmachineguid=new_machine.pmachine_guid, machinename=new_machine.name, machineguid=new_machine.guid) new_disk_guids.append(result['diskguid']) hv = Factory.get(machine.pmachine) try: result = hv.clone_vm(machine.hypervisor_id, name, disks, None, True) except: VMachineController.delete(machineguid=new_machine.guid) raise new_machine.hypervisor_id = result new_machine.save() return new_machine.guid
def clone(machineguid, timestamp, name): """ Clone a vmachine using the disk snapshot based on a snapshot timestamp @param machineguid: guid of the machine to clone @param timestamp: timestamp of the disk snapshots to use for the clone @param name: name for the new machine """ machine = VMachine(machineguid) disks = {} for snapshot in machine.snapshots: if snapshot['timestamp'] == timestamp: for diskguid, snapshotguid in snapshot['snapshots'].iteritems(): disks[diskguid] = snapshotguid new_machine = VMachine() new_machine.copy(machine) new_machine.name = name new_machine.pmachine = machine.pmachine new_machine.save() new_disk_guids = [] disks_by_order = sorted(machine.vdisks, key=lambda x: x.order) for currentDisk in disks_by_order: if machine.is_vtemplate and currentDisk.templatesnapshot: snapshotid = currentDisk.templatesnapshot else: snapshotid = disks[currentDisk.guid] prefix = '%s-clone' % currentDisk.name result = VDiskController.clone(diskguid=currentDisk.guid, snapshotid=snapshotid, devicename=prefix, pmachineguid=new_machine.pmachine_guid, machinename=new_machine.name, machineguid=new_machine.guid) new_disk_guids.append(result['diskguid']) hv = Factory.get(machine.pmachine) try: result = hv.clone_vm(machine.hypervisor_id, name, disks, None, True) except: VMachineController.delete(machineguid=new_machine.guid) raise new_machine.hypervisor_id = result new_machine.save() return new_machine.guid
def create_from_template(name, machineguid, pmachineguid, description=None): """ Create a new vmachine using an existing vmachine template @param machineguid: guid of the template vmachine @param name: name of new vmachine @param pmachineguid: guid of hypervisor to create new vmachine on @return: guid of the newly created vmachine | False on any failure """ template_vm = VMachine(machineguid) if not template_vm.is_vtemplate: return False target_pm = PMachine(pmachineguid) target_hypervisor = Factory.get(target_pm) storagerouters = [ sr for sr in StorageRouterList.get_storagerouters() if sr.pmachine_guid == target_pm.guid ] if len(storagerouters) == 1: target_storagerouter = storagerouters[0] else: raise ValueError( 'Pmachine {} has no StorageRouter assigned to it'.format( pmachineguid)) routing_key = "sr.{0}".format(target_storagerouter.machine_id) vpool = None vpool_guids = set() if template_vm.vpool is not None: vpool = template_vm.vpool vpool_guids.add(vpool.guid) for disk in template_vm.vdisks: vpool = disk.vpool vpool_guids.add(vpool.guid) if len(vpool_guids) != 1: raise RuntimeError( 'Only 1 vpool supported on template disk(s) - {0} found!'. format(len(vpool_guids))) if not template_vm.pmachine.hvtype == target_pm.hvtype: raise RuntimeError('Source and target hypervisor not identical') # Currently, only one vPool is supported, so we can just use whatever the `vpool` variable above # was set to as 'the' vPool for the code below. This obviously will have to change once vPool mixes # are supported. target_storagedriver = None source_storagedriver = None for vpool_storagedriver in vpool.storagedrivers: if vpool_storagedriver.storagerouter.pmachine_guid == target_pm.guid: target_storagedriver = vpool_storagedriver if vpool_storagedriver.storagerouter.pmachine_guid == template_vm.pmachine_guid: source_storagedriver = vpool_storagedriver if target_storagedriver is None: raise RuntimeError('Volume not served on target hypervisor') source_hv = Factory.get(template_vm.pmachine) target_hv = Factory.get(target_pm) if not source_hv.is_datastore_available( source_storagedriver.storage_ip, source_storagedriver.mountpoint): raise RuntimeError('Datastore unavailable on source hypervisor') if not target_hv.is_datastore_available( target_storagedriver.storage_ip, target_storagedriver.mountpoint): raise RuntimeError('Datastore unavailable on target hypervisor') source_vm = source_hv.get_vm_object(template_vm.hypervisor_id) if not source_vm: raise RuntimeError('VM with key reference {0} not found'.format( template_vm.hypervisor_id)) name_duplicates = VMachineList.get_vmachine_by_name(name) if name_duplicates is not None and len(name_duplicates) > 0: raise RuntimeError( 'A vMachine with name {0} already exists'.format(name)) vm_path = target_hypervisor.get_vmachine_path( name, target_storagedriver.storagerouter.machine_id) new_vm = VMachine() new_vm.copy(template_vm) new_vm.hypervisor_id = '' new_vm.vpool = template_vm.vpool new_vm.pmachine = target_pm new_vm.name = name new_vm.description = description new_vm.is_vtemplate = False new_vm.devicename = target_hypervisor.clean_vmachine_filename(vm_path) new_vm.status = 'CREATED' new_vm.save() storagedrivers = [ storagedriver for storagedriver in vpool.storagedrivers if storagedriver.storagerouter.pmachine_guid == new_vm.pmachine_guid ] if len(storagedrivers) == 0: raise RuntimeError( 'Cannot find Storage Driver serving {0} on {1}'.format( vpool.name, new_vm.pmachine.name)) storagedriverguid = storagedrivers[0].guid disks = [] disks_by_order = sorted(template_vm.vdisks, key=lambda x: x.order) try: for disk in disks_by_order: prefix = '{0}-clone'.format(disk.name) result = VDiskController.create_from_template( diskguid=disk.guid, devicename=prefix, pmachineguid=target_pm.guid, machinename=new_vm.name, machineguid=new_vm.guid, storagedriver_guid=storagedriverguid) disks.append(result) logger.debug('Disk appended: {0}'.format(result)) except Exception as exception: logger.error('Creation of disk {0} failed: {1}'.format( disk.name, str(exception)), print_msg=True) VMachineController.delete.s(machineguid=new_vm.guid).apply_async( routing_key=routing_key) raise try: result = target_hv.create_vm_from_template( name, source_vm, disks, target_storagedriver.storage_ip, target_storagedriver.mountpoint, wait=True) except Exception as exception: logger.error('Creation of vm {0} on hypervisor failed: {1}'.format( new_vm.name, str(exception)), print_msg=True) VMachineController.delete.s(machineguid=new_vm.guid).apply_async( routing_key=routing_key) raise new_vm.hypervisor_id = result new_vm.status = 'SYNC' new_vm.save() return new_vm.guid
def 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 :param description: Description for the machine :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 {0} 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)) disks = [] disks_by_order = sorted(template_vm.vdisks, key=lambda x: x.order) for disk in disks_by_order: try: 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 ) disks.append(result) VMachineController._logger.debug('Disk appended: {0}'.format(result)) except Exception as exception: VMachineController._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: VMachineController._logger.error('Creation of vm {0} on hypervisor failed: {1}'.format(new_vm.name, str(exception)), print_msg=True) VMachineController.delete.s(machineguid=new_vm.guid).apply_async(routing_key = routing_key) raise new_vm.hypervisor_id = result new_vm.status = 'SYNC' new_vm.save() return new_vm.guid
def clone(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