summaryrefslogtreecommitdiffstats
path: root/nova/virt
diff options
context:
space:
mode:
authorJosh Kearney <josh@jk0.org>2011-03-23 23:16:46 -0500
committerJosh Kearney <josh@jk0.org>2011-03-23 23:16:46 -0500
commit2f6aff324009be63ad2368295d5af01dcd040c4d (patch)
tree4bd93aee816759216c04b1320a0fed103c021473 /nova/virt
parent90ce5030c29274e63d45b34ec1e50b0078c63b2f (diff)
parentaf22892a2b1dc413f7d11c2f6efe2f820e3257ed (diff)
Merged trunk
Diffstat (limited to 'nova/virt')
-rw-r--r--nova/virt/hyperv.py3
-rw-r--r--nova/virt/libvirt_conn.py4
-rw-r--r--nova/virt/xenapi/vmops.py91
-rw-r--r--nova/virt/xenapi_conn.py4
4 files changed, 80 insertions, 22 deletions
diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py
index 29d18dac5..75fed6d4f 100644
--- a/nova/virt/hyperv.py
+++ b/nova/virt/hyperv.py
@@ -467,3 +467,6 @@ class HyperVConnection(object):
if vm is None:
raise exception.NotFound('Cannot detach volume from missing %s '
% instance_name)
+
+ def poll_rescued_instances(self, timeout):
+ pass
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 214670180..67094320e 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -417,6 +417,10 @@ class LibvirtConnection(object):
self.reboot(instance)
@exception.wrap_exception
+ def poll_rescued_instances(self, timeout):
+ pass
+
+ @exception.wrap_exception
def spawn(self, instance):
xml = self.to_xml(instance)
db.instance_set_state(context.get_admin_context(),
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index c88853afb..84cf836ac 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -51,6 +51,7 @@ class VMOps(object):
def __init__(self, session):
self.XenAPI = session.get_imported_xenapi()
self._session = session
+ self.poll_rescue_last_ran = None
VMHelper.XenAPI = self.XenAPI
@@ -492,6 +493,10 @@ class VMOps(object):
except self.XenAPI.Failure, exc:
LOG.exception(exc)
+ def _shutdown_rescue(self, rescue_vm_ref):
+ """Shutdown a rescue instance"""
+ self._session.call_xenapi("Async.VM.hard_shutdown", rescue_vm_ref)
+
def _destroy_vdis(self, instance, vm_ref):
"""Destroys all VDIs associated with a VM"""
instance_id = instance.id
@@ -509,6 +514,24 @@ class VMOps(object):
except self.XenAPI.Failure, exc:
LOG.exception(exc)
+ def _destroy_rescue_vdis(self, rescue_vm_ref):
+ """Destroys all VDIs associated with a rescued VM"""
+ vdi_refs = VMHelper.lookup_vm_vdis(self._session, rescue_vm_ref)
+ for vdi_ref in vdi_refs:
+ try:
+ self._session.call_xenapi("Async.VDI.destroy", vdi_ref)
+ except self.XenAPI.Failure:
+ continue
+
+ def _destroy_rescue_vbds(self, rescue_vm_ref):
+ """Destroys all VBDs tied to a rescue VM"""
+ vbd_refs = self._session.get_xenapi().VM.get_VBDs(rescue_vm_ref)
+ for vbd_ref in vbd_refs:
+ vbd_rec = self._session.get_xenapi().VBD.get_record(vbd_ref)
+ if vbd_rec["userdevice"] == "1": # primary VBD is always 1
+ VMHelper.unplug_vbd(self._session, vbd_ref)
+ VMHelper.destroy_vbd(self._session, vbd_ref)
+
def _destroy_kernel_ramdisk(self, instance, vm_ref):
"""
Three situations can occur:
@@ -559,6 +582,14 @@ class VMOps(object):
LOG.debug(_("Instance %(instance_id)s VM destroyed") % locals())
+ def _destroy_rescue_instance(self, rescue_vm_ref):
+ """Destroy a rescue instance"""
+ self._destroy_rescue_vbds(rescue_vm_ref)
+ self._shutdown_rescue(rescue_vm_ref)
+ self._destroy_rescue_vdis(rescue_vm_ref)
+
+ self._session.call_xenapi("Async.VM.destroy", rescue_vm_ref)
+
def destroy(self, instance):
"""
Destroy VM instance
@@ -662,40 +693,56 @@ class VMOps(object):
"""
rescue_vm_ref = VMHelper.lookup(self._session,
- str(instance.name) + "-rescue")
+ str(instance.name) + "-rescue")
if not rescue_vm_ref:
raise exception.NotFound(_(
"Instance is not in Rescue Mode: %s" % instance.name))
original_vm_ref = VMHelper.lookup(self._session, instance.name)
- vbd_refs = self._session.get_xenapi().VM.get_VBDs(rescue_vm_ref)
-
instance._rescue = False
- for vbd_ref in vbd_refs:
- _vbd_ref = self._session.get_xenapi().VBD.get_record(vbd_ref)
- if _vbd_ref["userdevice"] == "1":
- VMHelper.unplug_vbd(self._session, vbd_ref)
- VMHelper.destroy_vbd(self._session, vbd_ref)
+ self._destroy_rescue_instance(rescue_vm_ref)
+ self._release_bootlock(original_vm_ref)
+ self._start(instance, original_vm_ref)
- task1 = self._session.call_xenapi("Async.VM.hard_shutdown",
- rescue_vm_ref)
- self._session.wait_for_task(task1, instance.id)
+ def poll_rescued_instances(self, timeout):
+ """Look for expirable rescued instances
+ - forcibly exit rescue mode for any instances that have been
+ in rescue mode for >= the provided timeout
+ """
+ last_ran = self.poll_rescue_last_ran
+ if last_ran:
+ if not utils.is_older_than(last_ran, timeout):
+ # Do not run. Let's bail.
+ return
+ else:
+ # Update the time tracker and proceed.
+ self.poll_rescue_last_ran = utils.utcnow()
+ else:
+ # We need a base time to start tracking.
+ self.poll_rescue_last_ran = utils.utcnow()
+ return
- vdi_refs = VMHelper.lookup_vm_vdis(self._session, rescue_vm_ref)
- for vdi_ref in vdi_refs:
- try:
- task = self._session.call_xenapi('Async.VDI.destroy', vdi_ref)
- self._session.wait_for_task(task, instance.id)
- except self.XenAPI.Failure:
- continue
+ rescue_vms = []
+ for instance in self.list_instances():
+ if instance.endswith("-rescue"):
+ rescue_vms.append(dict(name=instance,
+ vm_ref=VMHelper.lookup(self._session,
+ instance)))
- task2 = self._session.call_xenapi('Async.VM.destroy', rescue_vm_ref)
- self._session.wait_for_task(task2, instance.id)
+ for vm in rescue_vms:
+ rescue_name = vm["name"]
+ rescue_vm_ref = vm["vm_ref"]
- self._release_bootlock(original_vm_ref)
- self._start(instance, original_vm_ref)
+ self._destroy_rescue_instance(rescue_vm_ref)
+
+ original_name = vm["name"].split("-rescue", 1)[0]
+ original_vm_ref = VMHelper.lookup(self._session, original_name)
+
+ self._release_bootlock(original_vm_ref)
+ self._session.call_xenapi("VM.start", original_vm_ref, False,
+ False)
def get_info(self, instance):
"""Return data about VM instance"""
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index da2fb51f1..2884687fb 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -223,6 +223,10 @@ class XenAPIConnection(object):
"""Unrescue the specified instance"""
self._vmops.unrescue(instance, callback)
+ def poll_rescued_instances(self, timeout):
+ """Poll for rescued instances"""
+ self._vmops.poll_rescued_instances(timeout)
+
def reset_network(self, instance):
"""reset networking for specified instance"""
self._vmops.reset_network(instance)