From 54b042df7e4d950ecf9b5e8fa81373c63d71cf14 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Fri, 23 Sep 2016 13:48:09 -0400 Subject: [PATCH] Fix usability issue when attaching block device When attaching a block device to the container, nova's client allows the user to chose the block device to be used. When nova-lxd, the block device that is created inside the container has the same device minor/major as the host. This can cause confusion for the user when the user attaches a block device to the instance and the block device in the container does not match reality. To solve this, we create the device inside the container as the user has requested. However, we specifity the device major/minor of the host's block device in the LXD profile so that the container can access the block device that was made available to the container via cinder. This was discovered by tempest while running unit tests against nova-lxd. Change-Id: I3be43168fe39efeeef5f7b6e57a45e93e3738820 Signed-off-by: Chuck Short --- nova/tests/unit/virt/lxd/test_driver.py | 14 ++++++++++---- nova/virt/lxd/driver.py | 6 ++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/nova/tests/unit/virt/lxd/test_driver.py b/nova/tests/unit/virt/lxd/test_driver.py index aba4c0e2..2f03f5ad 100644 --- a/nova/tests/unit/virt/lxd/test_driver.py +++ b/nova/tests/unit/virt/lxd/test_driver.py @@ -776,18 +776,24 @@ class LXDDriverTest(test.NoDBTestCase): self.assertEqual(0, self.client.profiles.get.call_count) container.stop.assert_called_once_with(wait=True) - @mock.patch('os.readlink') - def test_attach_volume(self, readlink): + @mock.patch('os.major') + @mock.patch('os.minor') + @mock.patch('os.stat') + @mock.patch('os.path.realpath') + def test_attach_volume(self, realpath, stat, minor, major): profile = mock.Mock() self.client.profiles.get.return_value = profile - readlink.return_value = '/dev/sdc' + realpath.return_value = '/dev/sdc' + stat.return_value.st_rdev = 2080 + minor.return_value = 32 + major.return_value = 8 ctx = context.get_admin_context() instance = fake_instance.fake_instance_obj(ctx, name='test') connection_info = fake_connection_info( {'id': 1, 'name': 'volume-00000001'}, '10.0.2.15:3260', 'iqn.2010-10.org.openstack:volume-00000001', auth=True) - mountpoint = mock.Mock() + mountpoint = '/dev/sdd' lxd_driver = driver.LXDDriver(None) lxd_driver.init_host(None) diff --git a/nova/virt/lxd/driver.py b/nova/virt/lxd/driver.py index 90f6de8b..7653511f 100644 --- a/nova/virt/lxd/driver.py +++ b/nova/virt/lxd/driver.py @@ -474,12 +474,14 @@ class LXDDriver(driver.ComputeDriver): device_info = self.storage_driver.connect_volume( connection_info['data']) - disk = os.readlink(device_info['path']).rpartition("/")[2] + disk = os.stat(os.path.realpath(device_info['path'])) vol_id = connection_info['data']['volume_id'] disk_device = { vol_id: { - 'path': '/dev/%s' % disk, + 'path': mountpoint, + 'major': '%s' % os.major(disk.st_rdev), + 'minor': '%s' % os.minor(disk.st_rdev), 'type': 'unix-block' } }