Merge "Add support for LXC volumes."
This commit is contained in:
@@ -195,6 +195,27 @@ class LibvirtVolumeTestCase(test.TestCase):
|
|||||||
libvirt_driver.disconnect_volume(connection_info, mount_device)
|
libvirt_driver.disconnect_volume(connection_info, mount_device)
|
||||||
connection_info = vol_driver.terminate_connection(vol, self.connr)
|
connection_info = vol_driver.terminate_connection(vol, self.connr)
|
||||||
|
|
||||||
|
def test_libvirt_lxc_volume(self):
|
||||||
|
self.stubs.Set(os.path, 'exists', lambda x: True)
|
||||||
|
vol_driver = volume_driver.ISCSIDriver()
|
||||||
|
libvirt_driver = volume.LibvirtISCSIVolumeDriver(self.fake_conn)
|
||||||
|
location = '10.0.2.15:3260'
|
||||||
|
name = 'volume-00000001'
|
||||||
|
iqn = 'iqn.2010-10.org.openstack:%s' % name
|
||||||
|
vol = {'id': 1,
|
||||||
|
'name': name,
|
||||||
|
'provider_auth': None,
|
||||||
|
'provider_location': '%s,fake %s' % (location, iqn)}
|
||||||
|
connection_info = vol_driver.initialize_connection(vol, self.connr)
|
||||||
|
mount_device = "vde"
|
||||||
|
xml = libvirt_driver.connect_volume(connection_info, mount_device)
|
||||||
|
tree = xml_to_tree(xml)
|
||||||
|
dev_str = '/dev/disk/by-path/ip-%s-iscsi-%s-lun-0' % (location, iqn)
|
||||||
|
self.assertEqual(tree.get('type'), 'block')
|
||||||
|
self.assertEqual(tree.find('./source').get('dev'), dev_str)
|
||||||
|
libvirt_driver.disconnect_volume(connection_info, mount_device)
|
||||||
|
connection_info = vol_driver.terminate_connection(vol, self.connr)
|
||||||
|
|
||||||
|
|
||||||
class CacheConcurrencyTestCase(test.TestCase):
|
class CacheConcurrencyTestCase(test.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@@ -106,6 +106,26 @@ def extend(image, size):
|
|||||||
utils.execute('resize2fs', image, check_exit_code=False)
|
utils.execute('resize2fs', image, check_exit_code=False)
|
||||||
|
|
||||||
|
|
||||||
|
def bind(src, target, instance_name):
|
||||||
|
"""Bind device to a filesytem"""
|
||||||
|
if src:
|
||||||
|
utils.execute('touch', target, run_as_root=True)
|
||||||
|
utils.execute('mount', '-o', 'bind', src, target,
|
||||||
|
run_as_root=True)
|
||||||
|
s = os.stat(src)
|
||||||
|
cgroup_info = "c %s:%s rwm" % (os.major(s.st_rdev),
|
||||||
|
os.minor(s.st_rdev))
|
||||||
|
cgroups_path = \
|
||||||
|
"/sys/fs/cgroup/devices/sysdefault/libvirt/lxc/%s/devices.allow" \
|
||||||
|
% instance_name
|
||||||
|
utils.execute('echo', '>', cgroup_info, cgroups_path, run_as_root=True)
|
||||||
|
|
||||||
|
|
||||||
|
def unbind(target):
|
||||||
|
if target:
|
||||||
|
utils.execute('umount', target, run_as_root=True)
|
||||||
|
|
||||||
|
|
||||||
class _DiskImage(object):
|
class _DiskImage(object):
|
||||||
"""Provide operations on a disk image file."""
|
"""Provide operations on a disk image file."""
|
||||||
|
|
||||||
|
@@ -453,7 +453,11 @@ class LibvirtConnection(driver.ComputeDriver):
|
|||||||
xml = self.volume_driver_method('connect_volume',
|
xml = self.volume_driver_method('connect_volume',
|
||||||
connection_info,
|
connection_info,
|
||||||
mount_device)
|
mount_device)
|
||||||
virt_dom.attachDevice(xml)
|
|
||||||
|
if FLAGS.libvirt_type == 'lxc':
|
||||||
|
self._attach_lxc_volume(xml, virt_dom, instance_name)
|
||||||
|
else:
|
||||||
|
virt_dom.attachDevice(xml)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_disk_xml(xml, device):
|
def _get_disk_xml(xml, device):
|
||||||
@@ -480,12 +484,64 @@ class LibvirtConnection(driver.ComputeDriver):
|
|||||||
xml = self._get_disk_xml(virt_dom.XMLDesc(0), mount_device)
|
xml = self._get_disk_xml(virt_dom.XMLDesc(0), mount_device)
|
||||||
if not xml:
|
if not xml:
|
||||||
raise exception.DiskNotFound(location=mount_device)
|
raise exception.DiskNotFound(location=mount_device)
|
||||||
virt_dom.detachDevice(xml)
|
if FLAGS.libvirt_type == 'lxc':
|
||||||
|
self._detach_lxc_volume(xml, vort_dom, instance_name)
|
||||||
|
else:
|
||||||
|
virt_dom.detachDevice(xml)
|
||||||
finally:
|
finally:
|
||||||
self.volume_driver_method('disconnect_volume',
|
self.volume_driver_method('disconnect_volume',
|
||||||
connection_info,
|
connection_info,
|
||||||
mount_device)
|
mount_device)
|
||||||
|
|
||||||
|
@exception.wrap_exception()
|
||||||
|
def _attach_lxc_volume(self, xml, virt_dom, instance_name):
|
||||||
|
LOG.info(_('attaching LXC block device'))
|
||||||
|
|
||||||
|
lxc_container_root = self.get_lxc_container_root(virt_dom)
|
||||||
|
lxc_host_volume = self.get_lxc_host_device(xml)
|
||||||
|
lxc_container_device = self.get_lxc_container_target(xml)
|
||||||
|
lxc_container_target = "%s/%s" % (lxc_container_root,
|
||||||
|
lxc_container_device)
|
||||||
|
|
||||||
|
if lxc_container_target:
|
||||||
|
disk.bind(lxc_host_volume, lxc_container_target, instance_name)
|
||||||
|
|
||||||
|
@exception.wrap_exception()
|
||||||
|
def _detach_lxc_volume(self, xml, virt_dom, instance_name):
|
||||||
|
LOG.info(_('detaching LXC block device'))
|
||||||
|
|
||||||
|
lxc_container_root = self.get_lxc_container_root(virt_dom)
|
||||||
|
lxc_host_volume = self.get_lxc_host_device(xml)
|
||||||
|
lxc_container_device = self.get_lxc_container_target(xml)
|
||||||
|
lxc_container_target = "%s/%s" % (lxc_container_root,
|
||||||
|
lxc_container_device)
|
||||||
|
|
||||||
|
if lxc_container_target:
|
||||||
|
disk.unbind(lxc_container_target)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_lxc_container_root(virt_dom):
|
||||||
|
xml = virt_dom.XMLDesc(0)
|
||||||
|
doc = ElementTree.fromstring(xml)
|
||||||
|
filesystem_block = doc.findall('./devices/filesystem')
|
||||||
|
for cnt, filesystem_nodes in enumerate(filesystem_block):
|
||||||
|
return filesystem_nodes[cnt].get('dir')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_lxc_host_device(xml):
|
||||||
|
dom = minidom.parseString(xml)
|
||||||
|
|
||||||
|
for device in dom.getElementsByTagName('source'):
|
||||||
|
return device.getAttribute('dev')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_lxc_container_target(xml):
|
||||||
|
dom = minidom.parseString(xml)
|
||||||
|
|
||||||
|
for device in dom.getElementsByTagName('target'):
|
||||||
|
filesystem = device.getAttribute('dev')
|
||||||
|
return 'dev/%s' % filesystem
|
||||||
|
|
||||||
@exception.wrap_exception()
|
@exception.wrap_exception()
|
||||||
def snapshot(self, context, instance, image_href):
|
def snapshot(self, context, instance, image_href):
|
||||||
"""Create snapshot from a running VM instance.
|
"""Create snapshot from a running VM instance.
|
||||||
|
Reference in New Issue
Block a user