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
This commit is contained in:
Jean-Baptiste RANSY
2013-02-02 00:56:20 +01:00
committed by Jean-Baptiste RANSY
parent fc7cece839
commit 43d1410ebf
4 changed files with 103 additions and 1 deletions

View File

@@ -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

View File

@@ -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")

View File

@@ -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',

View File

@@ -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