From 8aad7a202c058e019e2fa39a41231d3b7a6626c2 Mon Sep 17 00:00:00 2001 From: Antoine Millet Date: Thu, 11 Jun 2015 18:29:29 +0200 Subject: [PATCH] Implemented new-gen VM migrations --- cloudcontrol/node/hypervisor/__init__.py | 52 ++++++++++++++++++- .../node/hypervisor/domains/__init__.py | 24 +++++++++ cloudcontrol/node/hypervisor/jobs.py | 2 + 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/cloudcontrol/node/hypervisor/__init__.py b/cloudcontrol/node/hypervisor/__init__.py index b82f39c..bbbdafe 100644 --- a/cloudcontrol/node/hypervisor/__init__.py +++ b/cloudcontrol/node/hypervisor/__init__.py @@ -36,7 +36,7 @@ from cloudcontrol.node.exc import ( UndefinedDomain, DRBDError, PoolStorageError ) from cloudcontrol.node.hypervisor.jobs import ( - ImportVolume, ExportVolume, TCPTunnel, DRBD, + ImportVolume, ExportVolume, TCPTunnel, DRBD ) from cloudcontrol.node.utils import execute @@ -318,6 +318,56 @@ class Handler(HostHandler): logger.error(msg) raise UndefinedDomain(msg) + @libvirt_handler + def vm_reset(self, name): + logger.debug('VM reset %s', name) + try: + self.hypervisor.domains[name].reset() + except libvirt.libvirtError: + logger.exception('Error while resetting VM %s', name) + raise + except KeyError: + msg = 'Cannot reset VM %s because it is not defined' % name + logger.error(msg) + raise UndefinedDomain(msg) + + @libvirt_handler + def vm_cycle(self, name): + logger.debug('VM cycle %s', name) + try: + self.hypervisor.domains[name].destroy() + time.sleep(1) + self.hypervisor.domains[name].start() + except libvirt.libvirtError: + logger.exception('Error while cycle VM %s', name) + raise + except KeyError: + msg = 'Cannot cycle VM %s because it is not defined' % name + logger.error(msg) + raise UndefinedDomain(msg) + + @libvirt_handler + def vm_change_title(self, name, new_title): + logger.debug('VM edit title %s', name) + try: + self.hypervisor.domains[name].title = new_title + except libvirt.libvirtError: + logger.exception('Error while changing VM title %s', name) + raise + except KeyError: + msg = 'Cannot change title open VM %s because it is not defined' % name + logger.error(msg) + raise UndefinedDomain(msg) + + @libvirt_handler + def vm_migrate(self, name, dest_uri, live=False): + try: + dom = self.hypervisor.domains[name] + except KeyError: + raise UndefinedDomain('Cannot migrate VM %s because it is not defined', name) + + dom.migrate(dest_uri, live=live) + @libvirt_handler def vm_migrate_tunneled(self, name, tun_res, migtun_res, unsafe=False, timeout=60.): diff --git a/cloudcontrol/node/hypervisor/domains/__init__.py b/cloudcontrol/node/hypervisor/domains/__init__.py index 5628e06..7a0f2c3 100644 --- a/cloudcontrol/node/hypervisor/domains/__init__.py +++ b/cloudcontrol/node/hypervisor/domains/__init__.py @@ -512,3 +512,27 @@ class VirtualMachine(object): self.from_tunnel = None self.from_stream = None + + def migrate(self, dest_uri, live=False): + volumes = list(self.iter_disks()) # Store volumes for future cleanup + + flags = (libvirt.VIR_MIGRATE_PEER2PEER + | libvirt.VIR_MIGRATE_PERSIST_DEST + | libvirt.VIR_MIGRATE_UNDEFINE_SOURCE) + + if live: + flags |= (libvirt.VIR_MIGRATE_LIVE + | libvirt.VIR_MIGRATE_NON_SHARED_DISK + | libvirt.VIR_MIGRATE_AUTO_CONVERGE) + else: + flags |= libvirt.VIR_MIGRATE_OFFLINE + + error = self.lv_dom.migrateToURI3(dest_uri, {}, flags) + + if error: + raise RuntimeError('Unable to migrate VM') + else: + if live: # In live mode, we are responsible for source volume cleaning + for volume in volumes: + # Delete VM storage after migration success: + self.hypervisor.storage.delete_volume(volume.storage, volume.name) diff --git a/cloudcontrol/node/hypervisor/jobs.py b/cloudcontrol/node/hypervisor/jobs.py index 6598daf..0dbe85a 100644 --- a/cloudcontrol/node/hypervisor/jobs.py +++ b/cloudcontrol/node/hypervisor/jobs.py @@ -30,6 +30,8 @@ from xml.etree import ElementTree as et import pyev +from cloudcontrol.common.jobs import Job + from cloudcontrol.node.exc import TunnelError, DRBDAllocationError, DRBDError from cloudcontrol.node.jobs import BaseIOJob, ForkedJob from cloudcontrol.node.utils import SocketBuffer, subproc_call, Singleton -- GitLab