summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Baptiste RANSY <openstack@alyseo.com>2013-02-02 00:56:20 +0100
committerJean-Baptiste RANSY <jean-baptiste.ransy@alyseo.com>2013-02-12 13:24:41 +0100
commit43d1410ebfe09eeb0fd6f1731519a711a607a00f (patch)
tree278381dd5fa9dda93cdc0cadabb4ca2a833f66f5
parentfc7cece8392e66f7e0d11959bc7df7be8bf1a3d8 (diff)
downloadnova-43d1410ebfe09eeb0fd6f1731519a711a607a00f.tar.gz
nova-43d1410ebfe09eeb0fd6f1731519a711a607a00f.tar.xz
nova-43d1410ebfe09eeb0fd6f1731519a711a607a00f.zip
Adding support for AoE block storage SANs.
Adding support for AoE (ATA over Ethernet) block storage SANs. AoE initiator driver is supported on all Linux initiators (released under GPL), ATA over Ethernet (AoE) Linux driver for all 3.x and 2.6 kernels. Implements blueprint libvirt-aoe - Fix (minor) Redundant exception caching Change-Id: I00de13eb2d4bd1105b9eb68f1465825414e2d5d7
-rw-r--r--etc/nova/rootwrap.d/compute.filters5
-rw-r--r--nova/tests/test_libvirt_volume.py28
-rw-r--r--nova/virt/libvirt/driver.py3
-rw-r--r--nova/virt/libvirt/volume.py68
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 6cc8ee2f6..6b93729e5 100644
--- a/nova/tests/test_libvirt_volume.py
+++ b/nova/tests/test_libvirt_volume.py
@@ -324,3 +324,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 fef44d6b6..ae240657d 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -150,7 +150,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 f8ed95e0f..886371aad 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
@@ -315,3 +318,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