From 1125ecf9052b530f6335b896f7005594edf28672 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 9 Feb 2012 15:05:21 -0800 Subject: [PATCH] Fixes nova-volume support for multiple luns * stores lun in provider_location if specified * passes lun in iscsi_properties instead of hard coding * adds call to libvirt to list all used block devices * make sure to synchronize connect and disconnect commands * only disconnect from target if no luns are in use * allow double logins to targets * fixes typo in get_volume_connector in xenapi_connection * fixes bug 929790 Change-Id: I2466dc750a6fa5e0b07f94314d38873740aa6b29 --- nova/tests/test_libvirt.py | 89 +++++++++++++++++++++++++++++++++++++- nova/tests/test_xenapi.py | 1 + 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 2eede7ed..f0f1520e 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -124,7 +124,11 @@ class LibvirtVolumeTestCase(test.TestCase): def get_hypervisor_type(self): return self.hyperv - self.fake_conn = FakeLibvirtConnection("Xen") + + def get_all_block_devices(self): + return [] + + self.fake_conn = FakeLibvirtConnection() self.connr = { 'ip': '127.0.0.1', 'initiator': 'fake_initiator' @@ -167,6 +171,38 @@ class LibvirtVolumeTestCase(test.TestCase): '-p', location, '--op', 'delete')] self.assertEqual(self.executes, expected_commands) + def test_libvirt_iscsi_driver_still_in_use(self): + # NOTE(vish) exists is to make driver assume connecting worked + 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 + devs = ['/dev/disk/by-path/ip-%s-iscsi-%s-lun-1' % (location, iqn)] + self.stubs.Set(self.fake_conn, 'get_all_block_devices', lambda: devs) + 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) + expected_commands = [('iscsiadm', '-m', 'node', '-T', iqn, + '-p', location), + ('iscsiadm', '-m', 'node', '-T', iqn, + '-p', location, '--login'), + ('iscsiadm', '-m', 'node', '-T', iqn, + '-p', location, '--op', 'update', + '-n', 'node.startup', '-v', 'automatic')] + self.assertEqual(self.executes, expected_commands) + def test_libvirt_sheepdog_driver(self): vol_driver = volume_driver.SheepdogDriver() libvirt_driver = volume.LibvirtNetVolumeDriver(self.fake_conn) @@ -469,6 +505,57 @@ class LibvirtConnTestCase(test.TestCase): # Only one should be listed, since domain with ID 0 must be skiped self.assertEquals(len(instances), 1) + def test_get_all_block_devices(self): + xml = [ + # NOTE(vish): id 0 is skipped + None, + """ + + + + + + + + + + + """, + """ + + + + + + + + """, + """ + + + + + + + + + + + """, + ] + + def fake_lookup(id): + return FakeVirtDomain(xml[id]) + + self.mox.StubOutWithMock(connection.LibvirtConnection, '_conn') + connection.LibvirtConnection._conn.listDomainsID = lambda: range(4) + connection.LibvirtConnection._conn.lookupByID = fake_lookup + + self.mox.ReplayAll() + conn = connection.LibvirtConnection(False) + devices = conn.get_all_block_devices() + self.assertEqual(devices, ['/path/to/dev/1', '/path/to/dev/3']) + @test.skip_if(missing_libvirt(), "Test requires libvirt") def test_snapshot_in_ami_format(self): self.flags(image_service='nova.image.fake.FakeImageService') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 2673977f..f3b48a56 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -132,6 +132,7 @@ class XenAPIVolumeTestCase(test.TestCase): 'volume_id': 1, 'target_iqn': 'iqn.2010-10.org.openstack:volume-00000001', 'target_portal': '127.0.0.1:3260,fake', + 'target_lun': None, 'auth_method': 'CHAP', 'auth_method': 'fake', 'auth_method': 'fake',