Add support for LXC volumes.

This introduces volume support for LXC containers in Nova.
The way that this works is that when a device is attached to an
LXC container is that, the xml is parsed to find out which device to
connect to the LXC container, binds the device to the LXC container,
and allow the device through cgroups.
This bug fixes LP: #924601.
Change-Id: I00b41426ae8354b3cd4212655ecb48319a63aa9b
Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
Chuck Short
2012年01月31日 20:53:24 -05:00
parent 799713e4db
commit e40b659d32

View File

@@ -195,6 +195,27 @@ class LibvirtVolumeTestCase(test.TestCase):
libvirt_driver.disconnect_volume(connection_info, mount_device)
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):
def setUp(self):

View File

@@ -106,6 +106,26 @@ def extend(image, size):
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):
"""Provide operations on a disk image file."""

View File

@@ -449,7 +449,11 @@ class LibvirtConnection(driver.ComputeDriver):
xml = self.volume_driver_method('connect_volume',
connection_info,
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
def _get_disk_xml(xml, device):
@@ -476,12 +480,64 @@ class LibvirtConnection(driver.ComputeDriver):
xml = self._get_disk_xml(virt_dom.XMLDesc(0), mount_device)
if not xml:
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:
self.volume_driver_method('disconnect_volume',
connection_info,
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()
def snapshot(self, context, instance, image_href):
"""Create snapshot from a running VM instance.
Reference in New Issue
openstack/nova
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.

The note is not visible to the blocked user.