Fixes bug Snapshotting LXC instance fails
Fixes bug 1058273. The path of the disk for snapshotting LXC instance is debugged. Also, virt_dom.managedSave(0) and self._create_domain(domain=virt_dom) are not called for LXC instance, because they are supported by libvirt. Change-Id: Idf8275a0222b2eb289e16dd245f7721e17fce21d
This commit is contained in:
parent
a0fcd12480
commit
b60646965d
|
@ -1210,6 +1210,45 @@ class LibvirtConnTestCase(test.TestCase):
|
|||
self.assertEquals(snapshot['disk_format'], 'ami')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_lxc_snapshot_in_ami_format(self):
|
||||
self.flags(libvirt_snapshots_directory='./',
|
||||
libvirt_type='lxc')
|
||||
|
||||
# Start test
|
||||
image_service = nova.tests.image.fake.FakeImageService()
|
||||
|
||||
# Assign different image_ref from nova/images/fakes for testing ami
|
||||
test_instance = copy.deepcopy(self.test_instance)
|
||||
test_instance["image_ref"] = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'
|
||||
|
||||
# Assuming that base image already exists in image_service
|
||||
instance_ref = db.instance_create(self.context, test_instance)
|
||||
properties = {'instance_id': instance_ref['id'],
|
||||
'user_id': str(self.context.user_id)}
|
||||
snapshot_name = 'test-snap'
|
||||
sent_meta = {'name': snapshot_name, 'is_public': False,
|
||||
'status': 'creating', 'properties': properties}
|
||||
# Create new image. It will be updated in snapshot method
|
||||
# To work with it from snapshot, the single image_service is needed
|
||||
recv_meta = image_service.create(context, sent_meta)
|
||||
|
||||
self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
|
||||
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
|
||||
self.mox.StubOutWithMock(libvirt_driver.utils, 'execute')
|
||||
libvirt_driver.utils.execute = self.fake_execute
|
||||
libvirt_driver.libvirt_utils.disk_type = "qcow2"
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
conn = libvirt_driver.LibvirtDriver(False)
|
||||
conn.snapshot(self.context, instance_ref, recv_meta['id'])
|
||||
|
||||
snapshot = image_service.show(context, recv_meta['id'])
|
||||
self.assertEquals(snapshot['properties']['image_state'], 'available')
|
||||
self.assertEquals(snapshot['status'], 'active')
|
||||
self.assertEquals(snapshot['disk_format'], 'ami')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_snapshot_in_raw_format(self):
|
||||
self.flags(libvirt_snapshots_directory='./')
|
||||
|
||||
|
@ -1249,6 +1288,46 @@ class LibvirtConnTestCase(test.TestCase):
|
|||
self.assertEquals(snapshot['disk_format'], 'raw')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_lxc_snapshot_in_raw_format(self):
|
||||
self.flags(libvirt_snapshots_directory='./',
|
||||
libvirt_type='lxc')
|
||||
|
||||
# Start test
|
||||
image_service = nova.tests.image.fake.FakeImageService()
|
||||
|
||||
# Assuming that base image already exists in image_service
|
||||
instance_ref = db.instance_create(self.context, self.test_instance)
|
||||
properties = {'instance_id': instance_ref['id'],
|
||||
'user_id': str(self.context.user_id)}
|
||||
snapshot_name = 'test-snap'
|
||||
sent_meta = {'name': snapshot_name, 'is_public': False,
|
||||
'status': 'creating', 'properties': properties}
|
||||
# Create new image. It will be updated in snapshot method
|
||||
# To work with it from snapshot, the single image_service is needed
|
||||
recv_meta = image_service.create(context, sent_meta)
|
||||
|
||||
self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
|
||||
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
|
||||
self.mox.StubOutWithMock(libvirt_driver.utils, 'execute')
|
||||
libvirt_driver.utils.execute = self.fake_execute
|
||||
self.stubs.Set(libvirt_driver.libvirt_utils, 'disk_type', 'raw')
|
||||
|
||||
def convert_image(source, dest, out_format):
|
||||
libvirt_driver.libvirt_utils.files[dest] = ''
|
||||
|
||||
images.convert_image = convert_image
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
conn = libvirt_driver.LibvirtDriver(False)
|
||||
conn.snapshot(self.context, instance_ref, recv_meta['id'])
|
||||
|
||||
snapshot = image_service.show(context, recv_meta['id'])
|
||||
self.assertEquals(snapshot['properties']['image_state'], 'available')
|
||||
self.assertEquals(snapshot['status'], 'active')
|
||||
self.assertEquals(snapshot['disk_format'], 'raw')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_snapshot_in_qcow2_format(self):
|
||||
self.flags(snapshot_image_format='qcow2',
|
||||
libvirt_snapshots_directory='./')
|
||||
|
@ -1284,6 +1363,42 @@ class LibvirtConnTestCase(test.TestCase):
|
|||
self.assertEquals(snapshot['disk_format'], 'qcow2')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_lxc_snapshot_in_qcow2_format(self):
|
||||
self.flags(snapshot_image_format='qcow2',
|
||||
libvirt_snapshots_directory='./',
|
||||
libvirt_type='lxc')
|
||||
|
||||
# Start test
|
||||
image_service = nova.tests.image.fake.FakeImageService()
|
||||
|
||||
# Assuming that base image already exists in image_service
|
||||
instance_ref = db.instance_create(self.context, self.test_instance)
|
||||
properties = {'instance_id': instance_ref['id'],
|
||||
'user_id': str(self.context.user_id)}
|
||||
snapshot_name = 'test-snap'
|
||||
sent_meta = {'name': snapshot_name, 'is_public': False,
|
||||
'status': 'creating', 'properties': properties}
|
||||
# Create new image. It will be updated in snapshot method
|
||||
# To work with it from snapshot, the single image_service is needed
|
||||
recv_meta = image_service.create(context, sent_meta)
|
||||
|
||||
self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
|
||||
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
|
||||
self.mox.StubOutWithMock(libvirt_driver.utils, 'execute')
|
||||
libvirt_driver.utils.execute = self.fake_execute
|
||||
libvirt_driver.libvirt_utils.disk_type = "qcow2"
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
conn = libvirt_driver.LibvirtDriver(False)
|
||||
conn.snapshot(self.context, instance_ref, recv_meta['id'])
|
||||
|
||||
snapshot = image_service.show(context, recv_meta['id'])
|
||||
self.assertEquals(snapshot['properties']['image_state'], 'available')
|
||||
self.assertEquals(snapshot['status'], 'active')
|
||||
self.assertEquals(snapshot['disk_format'], 'qcow2')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_snapshot_no_image_architecture(self):
|
||||
self.flags(libvirt_snapshots_directory='./')
|
||||
|
||||
|
@ -1321,6 +1436,44 @@ class LibvirtConnTestCase(test.TestCase):
|
|||
self.assertEquals(snapshot['status'], 'active')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_lxc_snapshot_no_image_architecture(self):
|
||||
self.flags(libvirt_snapshots_directory='./',
|
||||
libvirt_type='lxc')
|
||||
|
||||
# Start test
|
||||
image_service = nova.tests.image.fake.FakeImageService()
|
||||
|
||||
# Assign different image_ref from nova/images/fakes for
|
||||
# testing different base image
|
||||
test_instance = copy.deepcopy(self.test_instance)
|
||||
test_instance["image_ref"] = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
|
||||
|
||||
# Assuming that base image already exists in image_service
|
||||
instance_ref = db.instance_create(self.context, test_instance)
|
||||
properties = {'instance_id': instance_ref['id'],
|
||||
'user_id': str(self.context.user_id)}
|
||||
snapshot_name = 'test-snap'
|
||||
sent_meta = {'name': snapshot_name, 'is_public': False,
|
||||
'status': 'creating', 'properties': properties}
|
||||
# Create new image. It will be updated in snapshot method
|
||||
# To work with it from snapshot, the single image_service is needed
|
||||
recv_meta = image_service.create(context, sent_meta)
|
||||
|
||||
self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
|
||||
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
|
||||
self.mox.StubOutWithMock(libvirt_driver.utils, 'execute')
|
||||
libvirt_driver.utils.execute = self.fake_execute
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
conn = libvirt_driver.LibvirtDriver(False)
|
||||
conn.snapshot(self.context, instance_ref, recv_meta['id'])
|
||||
|
||||
snapshot = image_service.show(context, recv_meta['id'])
|
||||
self.assertEquals(snapshot['properties']['image_state'], 'available')
|
||||
self.assertEquals(snapshot['status'], 'active')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_snapshot_no_original_image(self):
|
||||
self.flags(libvirt_snapshots_directory='./')
|
||||
|
||||
|
@ -1354,6 +1507,40 @@ class LibvirtConnTestCase(test.TestCase):
|
|||
self.assertEquals(snapshot['status'], 'active')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_lxc_snapshot_no_original_image(self):
|
||||
self.flags(libvirt_snapshots_directory='./',
|
||||
libvirt_type='lxc')
|
||||
|
||||
# Start test
|
||||
image_service = nova.tests.image.fake.FakeImageService()
|
||||
|
||||
# Assign a non-existent image
|
||||
test_instance = copy.deepcopy(self.test_instance)
|
||||
test_instance["image_ref"] = '661122aa-1234-dede-fefe-babababababa'
|
||||
|
||||
instance_ref = db.instance_create(self.context, test_instance)
|
||||
properties = {'instance_id': instance_ref['id'],
|
||||
'user_id': str(self.context.user_id)}
|
||||
snapshot_name = 'test-snap'
|
||||
sent_meta = {'name': snapshot_name, 'is_public': False,
|
||||
'status': 'creating', 'properties': properties}
|
||||
recv_meta = image_service.create(context, sent_meta)
|
||||
|
||||
self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
|
||||
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
|
||||
self.mox.StubOutWithMock(libvirt_driver.utils, 'execute')
|
||||
libvirt_driver.utils.execute = self.fake_execute
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
conn = libvirt_driver.LibvirtDriver(False)
|
||||
conn.snapshot(self.context, instance_ref, recv_meta['id'])
|
||||
|
||||
snapshot = image_service.show(context, recv_meta['id'])
|
||||
self.assertEquals(snapshot['properties']['image_state'], 'available')
|
||||
self.assertEquals(snapshot['status'], 'active')
|
||||
self.assertEquals(snapshot['name'], snapshot_name)
|
||||
|
||||
def test_attach_invalid_volume_type(self):
|
||||
self.create_fake_libvirt_mock()
|
||||
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
|
||||
|
|
|
@ -830,8 +830,10 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
(state, _max_mem, _mem, _cpus, _t) = virt_dom.info()
|
||||
state = LIBVIRT_POWER_STATE[state]
|
||||
|
||||
if state == power_state.RUNNING:
|
||||
virt_dom.managedSave(0)
|
||||
# NOTE(dkang): managedSave does not work for LXC
|
||||
if FLAGS.libvirt_type != 'lxc':
|
||||
if state == power_state.RUNNING:
|
||||
virt_dom.managedSave(0)
|
||||
|
||||
# Make the snapshot
|
||||
snapshot = self.image_backend.snapshot(disk_path, snapshot_name,
|
||||
|
@ -848,8 +850,11 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
snapshot.extract(out_path, image_format)
|
||||
finally:
|
||||
snapshot.delete()
|
||||
if state == power_state.RUNNING:
|
||||
self._create_domain(domain=virt_dom)
|
||||
# NOTE(dkang): because previous managedSave is not called
|
||||
# for LXC, _create_domain must not be called.
|
||||
if FLAGS.libvirt_type != 'lxc':
|
||||
if state == power_state.RUNNING:
|
||||
self._create_domain(domain=virt_dom)
|
||||
|
||||
# Upload that image to the image service
|
||||
with libvirt_utils.file_open(out_path) as image_file:
|
||||
|
|
|
@ -417,8 +417,14 @@ def find_disk(virt_dom):
|
|||
May be file or device"""
|
||||
xml_desc = virt_dom.XMLDesc(0)
|
||||
domain = etree.fromstring(xml_desc)
|
||||
source = domain.find('devices/disk/source')
|
||||
disk_path = source.get('file') or source.get('dev')
|
||||
if FLAGS.libvirt_type == 'lxc':
|
||||
source = domain.find('devices/filesystem/source')
|
||||
disk_path = source.get('dir')
|
||||
disk_path = disk_path[0:disk_path.rfind('rootfs')]
|
||||
disk_path = os.path.join(disk_path, 'disk')
|
||||
else:
|
||||
source = domain.find('devices/disk/source')
|
||||
disk_path = source.get('file') or source.get('dev')
|
||||
|
||||
if not disk_path:
|
||||
raise RuntimeError(_("Can't retrieve root device path "
|
||||
|
|
Loading…
Reference in New Issue