summaryrefslogtreecommitdiffstats
path: root/nova/virt
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-02-08 00:19:45 +0000
committerGerrit Code Review <review@openstack.org>2013-02-08 00:19:45 +0000
commit148b34feefbaed561b1269c53320638fa71abfcf (patch)
tree7e080780873fdba92d85c18346c455ada6147b4f /nova/virt
parentbce3806efec31fb0fa536b152d763b333d75120d (diff)
parentf0c9c85760605f0b7460d9bc08ac79487703a6fd (diff)
Merge "Recache or rebuild missing images on hard_reboot"
Diffstat (limited to 'nova/virt')
-rwxr-xr-x[-rw-r--r--]nova/virt/baremetal/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/driver.py3
-rwxr-xr-x[-rw-r--r--]nova/virt/fake.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/hyperv/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/libvirt/driver.py64
-rwxr-xr-x[-rw-r--r--]nova/virt/libvirt/imagebackend.py23
-rwxr-xr-x[-rw-r--r--]nova/virt/powervm/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/vmwareapi/driver.py2
-rwxr-xr-x[-rw-r--r--]nova/virt/xenapi/driver.py2
9 files changed, 60 insertions, 42 deletions
diff --git a/nova/virt/baremetal/driver.py b/nova/virt/baremetal/driver.py
index 43af951fd..9160485a6 100644..100755
--- a/nova/virt/baremetal/driver.py
+++ b/nova/virt/baremetal/driver.py
@@ -271,7 +271,7 @@ class BareMetalDriver(driver.ComputeDriver):
LOG.warning(_("Failed to update state record for "
"baremetal node %s") % instance['uuid'])
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
node = _get_baremetal_node_by_instance_uuid(instance['uuid'])
ctx = nova_context.get_admin_context()
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index 747b60714..ba0dfbafe 100644..100755
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -239,7 +239,7 @@ class ComputeDriver(object):
# TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot the specified instance.
@@ -254,7 +254,6 @@ class ComputeDriver(object):
:py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info`
:param reboot_type: Either a HARD or SOFT reboot
"""
- # TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
def get_console_pool_info(self, console_type):
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index 5a5bb7b13..30a5fc758 100644..100755
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -129,7 +129,7 @@ class FakeDriver(driver.ComputeDriver):
raise exception.InstanceNotRunning(instance_id=instance['uuid'])
update_task_state(task_state=task_states.IMAGE_UPLOADING)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
pass
diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py
index e8bf8c416..4af3b8b05 100644..100755
--- a/nova/virt/hyperv/driver.py
+++ b/nova/virt/hyperv/driver.py
@@ -52,7 +52,7 @@ class HyperVDriver(driver.ComputeDriver):
self._vmops.spawn(context, instance, image_meta, injected_files,
admin_password, network_info, block_device_info)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
self._vmops.reboot(instance, network_info, reboot_type)
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 666eb66f3..cf926a14c 100644..100755
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -957,7 +957,7 @@ class LibvirtDriver(driver.ComputeDriver):
libvirt_utils.extract_snapshot(disk_delta, 'qcow2', None,
out_path, image_format)
- def reboot(self, instance, network_info, reboot_type='SOFT',
+ def reboot(self, context, instance, network_info, reboot_type='SOFT',
block_device_info=None):
"""Reboot a virtual machine, given an instance reference."""
if reboot_type == 'SOFT':
@@ -969,7 +969,8 @@ class LibvirtDriver(driver.ComputeDriver):
else:
LOG.warn(_("Failed to soft reboot instance."),
instance=instance)
- return self._hard_reboot(instance, network_info, block_device_info)
+ return self._hard_reboot(context, instance, network_info,
+ block_device_info)
def _soft_reboot(self, instance):
"""Attempt to shutdown and restart the instance gracefully.
@@ -1015,7 +1016,8 @@ class LibvirtDriver(driver.ComputeDriver):
greenthread.sleep(1)
return False
- def _hard_reboot(self, instance, network_info, block_device_info=None):
+ def _hard_reboot(self, context, instance, network_info,
+ block_device_info=None):
"""Reboot a virtual machine, given an instance reference.
Performs a Libvirt reset (if supported) on the domain.
@@ -1035,6 +1037,13 @@ class LibvirtDriver(driver.ComputeDriver):
xml = self.to_xml(instance, network_info, disk_info,
block_device_info=block_device_info,
write_to_disk=True)
+
+ # NOTE (rmk): Re-populate any missing backing files.
+ disk_info_json = self.get_instance_disk_info(instance['name'], xml)
+ self._create_images_and_backing(context, instance, disk_info_json)
+
+ # Initialize all the necessary networking, block devices and
+ # start the instance.
self._create_domain_and_network(xml, instance, network_info,
block_device_info)
@@ -1103,7 +1112,7 @@ class LibvirtDriver(driver.ComputeDriver):
# Instance is not up and could be in an unknown state.
# Be as absolute as possible about getting it back into
# a known and running state.
- self._hard_reboot(instance, network_info, block_device_info)
+ self._hard_reboot(context, instance, network_info, block_device_info)
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
@@ -2834,8 +2843,17 @@ class LibvirtDriver(driver.ComputeDriver):
greenthread.sleep(1)
def pre_block_migration(self, ctxt, instance, disk_info_json):
- """Preparation block migration.
+ """Preparation for block migration."""
+ # NOTE (rmk): When preparing for a block migration, the instance dir
+ # should not exist on the destination hypervisor.
+ instance_dir = libvirt_utils.get_instance_path(instance)
+ if os.path.exists(instance_dir):
+ raise exception.DestinationDiskExists(path=instance_dir)
+ os.mkdir(instance_dir)
+ self._create_images_and_backing(ctxt, instance, disk_info_json)
+ def _create_images_and_backing(self, ctxt, instance, disk_info_json):
+ """
:params ctxt: security context
:params instance:
nova.db.sqlalchemy.models.Instance object
@@ -2845,19 +2863,14 @@ class LibvirtDriver(driver.ComputeDriver):
"""
disk_info = jsonutils.loads(disk_info_json)
-
- # make instance directory
instance_dir = libvirt_utils.get_instance_path(instance)
- if os.path.exists(instance_dir):
- raise exception.DestinationDiskExists(path=instance_dir)
- os.mkdir(instance_dir)
for info in disk_info:
base = os.path.basename(info['path'])
# Get image type and create empty disk image, and
# create backing file in case of qcow2.
instance_disk = os.path.join(instance_dir, base)
- if not info['backing_file']:
+ if not info['backing_file'] and not os.path.exists(instance_disk):
libvirt_utils.create_image(info['type'], instance_disk,
info['disk_size'])
else:
@@ -2910,10 +2923,9 @@ class LibvirtDriver(driver.ComputeDriver):
dom = self._lookup_by_name(instance_ref["name"])
self._conn.defineXML(dom.XMLDesc(0))
- def get_instance_disk_info(self, instance_name):
+ def get_instance_disk_info(self, instance_name, xml=None):
"""Preparation block migration.
- :params ctxt: security context
:params instance_ref:
nova.db.sqlalchemy.models.Instance object
instance object that is migrated.
@@ -2926,18 +2938,22 @@ class LibvirtDriver(driver.ComputeDriver):
'disk_size':'83886080'},...]"
"""
- disk_info = []
+ # NOTE (rmk): Passing the domain XML into this function is optional.
+ # When it is not passed, we attempt to extract it from
+ # the pre-existing definition.
+ if xml is None:
+ try:
+ virt_dom = self._lookup_by_name(instance_name)
+ xml = virt_dom.XMLDesc(0)
+ except libvirt.libvirtError as ex:
+ error_code = ex.get_error_code()
+ msg = _("Error from libvirt while getting description of "
+ "%(instance_name)s: [Error Code %(error_code)s] "
+ "%(ex)s") % locals()
+ LOG.warn(msg)
+ raise exception.InstanceNotFound(instance_id=instance_name)
- virt_dom = self._lookup_by_name(instance_name)
- try:
- xml = virt_dom.XMLDesc(0)
- except libvirt.libvirtError as ex:
- error_code = ex.get_error_code()
- msg = _("Error from libvirt while getting description of "
- "%(instance_name)s: [Error Code %(error_code)s] "
- "%(ex)s") % locals()
- LOG.warn(msg)
- raise exception.InstanceNotFound(instance_id=instance_name)
+ disk_info = []
doc = etree.fromstring(xml)
disk_nodes = doc.findall('.//devices/disk')
path_nodes = doc.findall('.//devices/disk/source')
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index 0815c142f..0d5e8cb66 100644..100755
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -120,12 +120,12 @@ class Image(object):
if not os.path.exists(target):
fetch_func(target=target, *args, **kwargs)
- if not os.path.exists(self.path):
- base_dir = os.path.join(CONF.instances_path, CONF.base_dir_name)
- if not os.path.exists(base_dir):
- fileutils.ensure_tree(base_dir)
- base = os.path.join(base_dir, filename)
+ base_dir = os.path.join(CONF.instances_path, CONF.base_dir_name)
+ if not os.path.exists(base_dir):
+ fileutils.ensure_tree(base_dir)
+ base = os.path.join(base_dir, filename)
+ if not os.path.exists(self.path) or not os.path.exists(base):
self.create_image(call_if_not_exists, base, size,
*args, **kwargs)
@@ -160,8 +160,9 @@ class Raw(Image):
prepare_template(target=self.path, *args, **kwargs)
else:
prepare_template(target=base, *args, **kwargs)
- with utils.remove_path_on_error(self.path):
- copy_raw_image(base, self.path, size)
+ if not os.path.exists(self.path):
+ with utils.remove_path_on_error(self.path):
+ copy_raw_image(base, self.path, size)
def snapshot(self, name):
return snapshots.RawSnapshot(self.path, name)
@@ -183,9 +184,11 @@ class Qcow2(Image):
if size:
disk.extend(target, size)
- prepare_template(target=base, *args, **kwargs)
- with utils.remove_path_on_error(self.path):
- copy_qcow2_image(base, self.path, size)
+ if not os.path.exists(base):
+ prepare_template(target=base, *args, **kwargs)
+ if not os.path.exists(self.path):
+ with utils.remove_path_on_error(self.path):
+ copy_qcow2_image(base, self.path, size)
def snapshot(self, name):
return snapshots.Qcow2Snapshot(self.path, name)
diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py
index baf9bf12d..dd0f473a6 100644..100755
--- a/nova/virt/powervm/driver.py
+++ b/nova/virt/powervm/driver.py
@@ -101,7 +101,7 @@ class PowerVMDriver(driver.ComputeDriver):
"""Destroy (shutdown and delete) the specified instance."""
self._powervm.destroy(instance['name'], destroy_disks)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot the specified instance.
diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py
index 3e9269530..19f984c7d 100644..100755
--- a/nova/virt/vmwareapi/driver.py
+++ b/nova/virt/vmwareapi/driver.py
@@ -180,7 +180,7 @@ class VMwareESXDriver(driver.ComputeDriver):
"""Create snapshot from a running VM instance."""
self._vmops.snapshot(context, instance, name, update_task_state)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot VM instance."""
self._vmops.reboot(instance, network_info)
diff --git a/nova/virt/xenapi/driver.py b/nova/virt/xenapi/driver.py
index 46b759f43..c1a578f3b 100644..100755
--- a/nova/virt/xenapi/driver.py
+++ b/nova/virt/xenapi/driver.py
@@ -193,7 +193,7 @@ class XenAPIDriver(driver.ComputeDriver):
"""Create snapshot from a running VM instance."""
self._vmops.snapshot(context, instance, image_id, update_task_state)
- def reboot(self, instance, network_info, reboot_type,
+ def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None):
"""Reboot VM instance."""
self._vmops.reboot(instance, reboot_type)