From 8fa717563707c1802345cff2c5d602c1f011dd3c Mon Sep 17 00:00:00 2001 From: Rafi Khardalian Date: Sun, 10 Feb 2013 06:27:54 +0000 Subject: Libvirt: Implement snapshots for LVM-backed roots Uses the built-in LVM snapshotting mechanism to create a new snapshot, use qemu-img to extract the full root into an image file, then delete the snapshot volume. Although we typically zero deleted LVM volumes manually, this is not necessary for snapshots, as LVM handles it for us (per the documentation). Change-Id: I82f21488671ffa3be3d0feba73ff631fa2a51ec0 Fixes: Bug 1120809 Flags: DocImpact --- nova/virt/libvirt/imagebackend.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py index 7e7175865..0a84b22e5 100755 --- a/nova/virt/libvirt/imagebackend.py +++ b/nova/virt/libvirt/imagebackend.py @@ -43,6 +43,10 @@ __imagebackend_opts = [ default=False, help='Create sparse logical volumes (with virtualsize)' ' if this flag is set to True.'), + cfg.IntOpt('libvirt_lvm_snapshot_size', + default='1000', + help='The amount of storage (in megabytes) to allocate for LVM' + ' snapshot copy-on-write blocks.'), ] CONF = cfg.CONF @@ -239,6 +243,11 @@ class Lvm(Image): self.sparse = CONF.libvirt_sparse_logical_volumes + if snapshot_name: + self.snapshot_name = snapshot_name + self.snapshot_path = os.path.join('/dev', self.vg, + self.snapshot_name) + def create_image(self, prepare_template, base, size, *args, **kwargs): @lockutils.synchronized(base, 'nova-', external=True, lock_path=self.lock_path) @@ -273,6 +282,21 @@ class Lvm(Image): with excutils.save_and_reraise_exception(): libvirt_utils.remove_logical_volumes(path) + def snapshot_create(self): + size = CONF.libvirt_lvm_snapshot_size + cmd = ('lvcreate', '-L', size, '-s', '--name', self.snapshot_name, + self.path) + libvirt_utils.execute(*cmd, run_as_root=True, attempts=3) + + def snapshot_extract(self, target, out_format): + images.convert_image(self.snapshot_path, target, out_format, + run_as_root=True) + + def snapshot_delete(self): + # NOTE (rmk): Snapshot volumes are automatically zeroed by LVM + cmd = ('lvremove', '-f', self.snapshot_path) + libvirt_utils.execute(*cmd, run_as_root=True, attempts=3) + class Backend(object): def __init__(self, use_cow): -- cgit