diff options
-rw-r--r-- | nova/tests/test_libvirt.py | 21 | ||||
-rw-r--r-- | nova/virt/disk/api.py | 20 | ||||
-rw-r--r-- | nova/virt/libvirt/connection.py | 60 |
3 files changed, 99 insertions, 2 deletions
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index dbcccb11e..66a8db2b5 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -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): diff --git a/nova/virt/disk/api.py b/nova/virt/disk/api.py index fd0eec79d..f1f60414b 100644 --- a/nova/virt/disk/api.py +++ b/nova/virt/disk/api.py @@ -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.""" diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index adf7aa295..efd972b4b 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -453,7 +453,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): @@ -480,13 +484,65 @@ 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. |