Permalink
Browse files

Make snapshots with qemu-img instead of libvirt

 * snapshot is only supposed to snapshot the root drive, whereas
   libvirt snapshots snapshot the memory and all attached disks
 * removes silly qemu_img flag
 * fixes bug 946830

Change-Id: I6afc9dbaa855f06864cd5a37f89ad63555e35d23
  • Loading branch information...
1 parent 0b59188 commit f8300fde7574ed42570d391e9f9a7860af8e6f39 @vishvananda committed Mar 9, 2012
View
@@ -179,6 +179,10 @@
# nova/virt/xenapi/vm_utils.py: 'mkfs'
filters.CommandFilter("/sbin/mkfs", "root"),
+ # nova/virt/libvirt/utils.py: 'qemu-img'
+ filters.CommandFilter("/usr/bin/qemu-img", "root"),
+
# nova/virt/libvirt/connection.py:
filters.ReadFileFilter("/etc/iscsi/initiatorname.iscsi"),
+
]
@@ -61,6 +61,14 @@ def chown(path, owner):
pass
+def create_snapshot(disk_path, snapshot_name):
+ pass
+
+
+def delete_snapshot(disk_path, snapshot_name):
+ pass
+
+
def extract_snapshot(disk_path, source_fmt, snapshot_name, out_path, dest_fmt):
files[out_path] = ''
@@ -96,8 +96,11 @@ def __init__(self, fake_xml=None):
def name(self):
return "fake-domain %s" % self
- def snapshotCreateXML(self, *args):
- return FakeVirDomainSnapshot(self)
+ def create(self):
+ pass
+
+ def managedSave(self, *args):
+ pass
def createWithFlags(self, launch_flags):
pass
@@ -616,37 +616,40 @@ def snapshot(self, context, instance, image_href):
if 'container_format' in base:
metadata['container_format'] = base['container_format']
- # Make the snapshot
- snapshot_name = uuid.uuid4().hex
- snapshot_xml = """
- <domainsnapshot>
- <name>%s</name>
- </domainsnapshot>
- """ % snapshot_name
- snapshot_ptr = virt_dom.snapshotCreateXML(snapshot_xml, 0)
-
# Find the disk
xml_desc = virt_dom.XMLDesc(0)
domain = ElementTree.fromstring(xml_desc)
source = domain.find('devices/disk/source')
disk_path = source.get('file')
+ snapshot_name = uuid.uuid4().hex
+
+ # NOTE(vish): It may be safe to snapshot a disk that is actively
+ # being written to, but I'm being defensive here.
+ # The save ensures that libvirt doesn't have a file
+ # handle to the disk open before we start messing
+ # with it.
+ virt_dom.managedSave(0)
+ # Make the snapshot
+ libvirt_utils.create_snapshot(disk_path, snapshot_name)
+
# Export the snapshot to a raw image
with utils.tempdir() as tmpdir:
try:
out_path = os.path.join(tmpdir, snapshot_name)
libvirt_utils.extract_snapshot(disk_path, source_format,
snapshot_name, out_path,
image_format)
- # Upload that image to the image service
- with libvirt_utils.file_open(out_path) as image_file:
- image_service.update(context,
- image_href,
- metadata,
- image_file)
-
finally:
- snapshot_ptr.delete(0)
+ libvirt_utils.delete_snapshot(disk_path, snapshot_name)
+ virt_dom.create()
+
+ # Upload that image to the image service
+ with libvirt_utils.file_open(out_path) as image_file:
+ image_service.update(context,
+ image_href,
+ metadata,
+ image_file)
@exception.wrap_exception()
def reboot(self, instance, network_info, reboot_type='SOFT'):
View
@@ -24,17 +24,11 @@
from nova import exception
from nova import flags
-from nova.openstack.common import cfg
from nova import utils
from nova.virt import images
-qemu_img_opt = cfg.StrOpt('qemu_img',
- default='qemu-img',
- help='binary to use for qemu-img commands')
-
FLAGS = flags.FLAGS
-FLAGS.register_opt(qemu_img_opt)
def execute(*args, **kwargs):
@@ -63,7 +57,7 @@ def create_image(disk_format, path, size):
for megabytes, 'g' for gigabytes, 't' for terabytes). If no
prefix is given, it will be interpreted as bytes.
"""
- execute(FLAGS.qemu_img, 'create', '-f', disk_format, path, size)
+ execute('qemu-img', 'create', '-f', disk_format, path, size)
def create_cow_image(backing_file, path):
@@ -74,7 +68,7 @@ def create_cow_image(backing_file, path):
:param backing_file: Existing image on which to base the COW image
:param path: Desired location of the COW image
"""
- execute(FLAGS.qemu_img, 'create', '-f', 'qcow2', '-o',
+ execute('qemu-img', 'create', '-f', 'qcow2', '-o',
'cluster_size=2M,backing_file=%s' % backing_file, path)
@@ -85,7 +79,7 @@ def get_disk_size(path):
:returns: Size (in bytes) of the given disk image as it would be seen
by a virtual machine.
"""
- out, err = execute(FLAGS.qemu_img, 'info', path)
+ out, err = execute('qemu-img', 'info', path)
size = [i.split('(')[1].split()[0] for i in out.split('\n')
if i.strip().find('virtual size') >= 0]
return int(size[0])
@@ -97,7 +91,7 @@ def get_disk_backing_file(path):
:param path: Path to the disk image
:returns: a path to the image's backing store
"""
- out, err = execute(FLAGS.qemu_img, 'info', path)
+ out, err = execute('qemu-img', 'info', path)
backing_file = [i.split('actual path:')[1].strip()[:-1]
for i in out.split('\n') if 0 <= i.find('backing file')]
if backing_file:
@@ -168,7 +162,37 @@ def chown(path, owner):
:param path: File or directory whose ownership to change
:param owner: Desired new owner (given as uid or username)
"""
- utils.execute('chown', owner, path, run_as_root=True)
+ execute('chown', owner, path, run_as_root=True)
+
+
+def create_snapshot(disk_path, snapshot_name):
+ """Create a snapshot in a disk image
+
+ :param disk_path: Path to disk image
+ :param snapshot_name: Name of snapshot in disk image
+ """
+ qemu_img_cmd = ('qemu-img',
+ 'snapshot',
+ '-c',
+ snapshot_name,
+ disk_path)
+ # NOTE(vish): libvirt changes ownership of images
+ execute(*qemu_img_cmd, run_as_root=True)
+
+
+def delete_snapshot(disk_path, snapshot_name):
+ """Create a snapshot in a disk image
+
+ :param disk_path: Path to disk image
+ :param snapshot_name: Name of snapshot in disk image
+ """
+ qemu_img_cmd = ('qemu-img',
+ 'snapshot',
+ '-d',
+ snapshot_name,
+ disk_path)
+ # NOTE(vish): libvirt changes ownership of images
+ execute(*qemu_img_cmd, run_as_root=True)
def extract_snapshot(disk_path, source_fmt, snapshot_name, out_path, dest_fmt):
@@ -178,7 +202,7 @@ def extract_snapshot(disk_path, source_fmt, snapshot_name, out_path, dest_fmt):
:param snapshot_name: Name of snapshot in disk image
:param out_path: Desired path of extracted snapshot
"""
- qemu_img_cmd = (FLAGS.qemu_img,
+ qemu_img_cmd = ('qemu-img',
'convert',
'-f',
source_fmt,

0 comments on commit f8300fd

Please sign in to comment.