diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-02-12 20:44:53 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-02-12 20:44:53 +0000 |
| commit | a692ba301bc9127c79b2b32c6762f0d5e56be256 (patch) | |
| tree | 9139e626050e3a67cc813431d00dc85166483ecf | |
| parent | 03835879c68b361c6ca1e845bdc0a73cb2fdf4f3 (diff) | |
| parent | 43d1410ebfe09eeb0fd6f1731519a711a607a00f (diff) | |
Merge "Adding support for AoE block storage SANs."
| -rw-r--r-- | etc/nova/rootwrap.d/compute.filters | 5 | ||||
| -rw-r--r-- | nova/tests/test_libvirt_volume.py | 28 | ||||
| -rwxr-xr-x | nova/virt/libvirt/driver.py | 3 | ||||
| -rw-r--r-- | nova/virt/libvirt/volume.py | 68 |
4 files changed, 103 insertions, 1 deletions
diff --git a/etc/nova/rootwrap.d/compute.filters b/etc/nova/rootwrap.d/compute.filters index 9562a23aa..6396315b9 100644 --- a/etc/nova/rootwrap.d/compute.filters +++ b/etc/nova/rootwrap.d/compute.filters @@ -88,6 +88,11 @@ dd: CommandFilter, /bin/dd, root # nova/virt/xenapi/volume_utils.py: 'iscsiadm', '-m', ... iscsiadm: CommandFilter, iscsiadm, root +# nova/virt/libvirt/volume.py: 'aoe-revalidate', aoedev +# nova/virt/libvirt/volume.py: 'aoe-discover' +aoe-revalidate: CommandFilter, /usr/sbin/aoe-revalidate, root +aoe-discover: CommandFilter, /usr/sbin/aoe-discover, root + # nova/virt/xenapi/vm_utils.py: parted, --script, ... # nova/virt/xenapi/vm_utils.py: 'parted', '--script', dev_path, ..*. parted: CommandFilter, parted, root diff --git a/nova/tests/test_libvirt_volume.py b/nova/tests/test_libvirt_volume.py index b9f95735f..c0fa53506 100644 --- a/nova/tests/test_libvirt_volume.py +++ b/nova/tests/test_libvirt_volume.py @@ -364,3 +364,31 @@ class LibvirtVolumeTestCase(test.TestCase): ('stat', export_mnt_base), ('mount', '-t', 'nfs', export_string, export_mnt_base)] self.assertEqual(self.executes, expected_commands) + + def aoe_connection(self, shelf, lun): + return { + 'driver_volume_type': 'aoe', + 'data': { + 'target_shelf': shelf, + 'target_lun': lun, + } + } + + def test_libvirt_aoe_driver(self): + # NOTE(jbr_) exists is to make driver assume connecting worked + self.stubs.Set(os.path, 'exists', lambda x: True) + libvirt_driver = volume.LibvirtAOEVolumeDriver(self.fake_conn) + shelf = '100' + lun = '1' + connection_info = self.aoe_connection(shelf, lun) + disk_info = { + "bus": "virtio", + "dev": "vde", + "type": "disk", + } + conf = libvirt_driver.connect_volume(connection_info, disk_info) + tree = conf.format_dom() + aoedevpath = '/dev/etherd/e%s.%s' % (shelf, lun) + self.assertEqual(tree.get('type'), 'block') + self.assertEqual(tree.find('./source').get('dev'), aoedevpath) + libvirt_driver.disconnect_volume(connection_info, "vde") diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 7e34aef3d..b65789b10 100755 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -151,7 +151,8 @@ libvirt_opts = [ 'fake=nova.virt.libvirt.volume.LibvirtFakeVolumeDriver', 'rbd=nova.virt.libvirt.volume.LibvirtNetVolumeDriver', 'sheepdog=nova.virt.libvirt.volume.LibvirtNetVolumeDriver', - 'nfs=nova.virt.libvirt.volume.LibvirtNFSVolumeDriver' + 'nfs=nova.virt.libvirt.volume.LibvirtNFSVolumeDriver', + 'aoe=nova.virt.libvirt.volume.LibvirtAOEVolumeDriver' ], help='Libvirt handlers for remote volumes.'), cfg.StrOpt('libvirt_disk_prefix', diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py index 724a859b8..9ec8f6bcb 100644 --- a/nova/virt/libvirt/volume.py +++ b/nova/virt/libvirt/volume.py @@ -50,6 +50,9 @@ volume_opts = [ default=None, help='Mount options passed to the nfs client. See section ' 'of the nfs man page for details'), + cfg.StrOpt('num_aoe_discover_tries', + default=3, + help='number of times to rediscover AoE target to find volume') ] CONF = cfg.CONF @@ -322,3 +325,68 @@ class LibvirtNFSVolumeDriver(LibvirtBaseVolumeDriver): return utils.execute('stat', path, run_as_root=True) except exception.ProcessExecutionError: return False + + +class LibvirtAOEVolumeDriver(LibvirtBaseVolumeDriver): + """Driver to attach AoE volumes to libvirt.""" + def __init__(self, connection): + super(LibvirtAOEVolumeDriver, + self).__init__(connection, is_block_dev=True) + + def _aoe_discover(self): + """Call aoe-discover (aoe-tools) AoE Discover.""" + (out, err) = utils.execute('aoe-discover', + run_as_root=True, check_exit_code=0) + return (out, err) + + def _aoe_revalidate(self, aoedev): + """Revalidate the LUN Geometry (When an AoE ID is reused).""" + (out, err) = utils.execute('aoe-revalidate', aoedev, + run_as_root=True, check_exit_code=0) + return (out, err) + + def connect_volume(self, connection_info, mount_device): + shelf = connection_info['data']['target_shelf'] + lun = connection_info['data']['target_lun'] + aoedev = 'e%s.%s' % (shelf, lun) + aoedevpath = '/dev/etherd/%s' % (aoedev) + + if os.path.exists(aoedevpath): + # NOTE(jbr_): If aoedevpath already exists, revalidate the LUN. + self._aoe_revalidate(aoedev) + else: + # NOTE(jbr_): If aoedevpath does not exist, do a discover. + self._aoe_discover() + + #NOTE(jbr_): Device path is not always present immediately + def _wait_for_device_discovery(aoedevpath, mount_device): + tries = self.tries + if os.path.exists(aoedevpath): + raise utils.LoopingCallDone() + + if self.tries >= CONF.num_aoe_discover_tries: + raise exception.NovaException(_("AoE device not found at %s") % + (aoedevpath)) + LOG.warn(_("AoE volume not yet found at: %(aoedevpath)s. " + "Try number: %(tries)s") % + locals()) + + self._aoe_discover() + self.tries = self.tries + 1 + + self.tries = 0 + timer = utils.FixedIntervalLoopingCall(_wait_for_device_discovery, + aoedevpath, mount_device) + timer.start(interval=2).wait() + + tries = self.tries + if tries != 0: + LOG.debug(_("Found AoE device %(aoedevpath)s " + "(after %(tries)s rediscover)") % + locals()) + + conf = super(LibvirtAOEVolumeDriver, + self).connect_volume(connection_info, mount_device) + conf.source_type = "block" + conf.source_path = aoedevpath + return conf |
