summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorEric Harney <eharney@redhat.com>2013-02-01 15:08:27 -0500
committerEric Harney <eharney@redhat.com>2013-02-13 11:35:21 -0500
commit8cf0178165dec3eac002159fd01af6930322bebb (patch)
tree6ad73796888ddc44bd65b390e48ae819686ce4d0 /nova
parent635faddd3744179b0b87666c08e50b97366bfe3e (diff)
downloadnova-8cf0178165dec3eac002159fd01af6930322bebb.tar.gz
nova-8cf0178165dec3eac002159fd01af6930322bebb.tar.xz
nova-8cf0178165dec3eac002159fd01af6930322bebb.zip
Add GlusterFS libvirt volume connector
This is to support GlusterFS as a storage backend for Cinder, which works similarly to the NFS backend. Change-Id: I047d58ba74d27273ba8f2639bcc77999f8be0f30
Diffstat (limited to 'nova')
-rw-r--r--nova/tests/test_libvirt_volume.py28
-rwxr-xr-xnova/virt/libvirt/driver.py4
-rw-r--r--nova/virt/libvirt/volume.py62
3 files changed, 92 insertions, 2 deletions
diff --git a/nova/tests/test_libvirt_volume.py b/nova/tests/test_libvirt_volume.py
index c0fa53506..0098215b2 100644
--- a/nova/tests/test_libvirt_volume.py
+++ b/nova/tests/test_libvirt_volume.py
@@ -392,3 +392,31 @@ class LibvirtVolumeTestCase(test.TestCase):
self.assertEqual(tree.get('type'), 'block')
self.assertEqual(tree.find('./source').get('dev'), aoedevpath)
libvirt_driver.disconnect_volume(connection_info, "vde")
+
+ def test_libvirt_glusterfs_driver(self):
+ mnt_base = '/mnt'
+ self.flags(glusterfs_mount_point_base=mnt_base)
+
+ libvirt_driver = volume.LibvirtGlusterfsVolumeDriver(self.fake_conn)
+ export_string = '192.168.1.1:/volume-00001'
+ name = 'volume-00001'
+ export_mnt_base = os.path.join(mnt_base,
+ libvirt_driver.get_hash_str(export_string))
+ file_path = os.path.join(export_mnt_base, name)
+
+ connection_info = {'data': {'export': export_string, 'name': name}}
+ disk_info = {
+ "bus": "virtio",
+ "dev": "vde",
+ "type": "disk",
+ }
+ conf = libvirt_driver.connect_volume(connection_info, disk_info)
+ tree = conf.format_dom()
+ self.assertEqual(tree.get('type'), 'file')
+ self.assertEqual(tree.find('./source').get('file'), file_path)
+ libvirt_driver.disconnect_volume(connection_info, "vde")
+
+ expected_commands = [
+ ('stat', export_mnt_base),
+ ('mount', '-t', 'glusterfs', export_string, export_mnt_base)]
+ self.assertEqual(self.executes, expected_commands)
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index bdb875ed3..4e2fb9d39 100755
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -152,7 +152,9 @@ libvirt_opts = [
'rbd=nova.virt.libvirt.volume.LibvirtNetVolumeDriver',
'sheepdog=nova.virt.libvirt.volume.LibvirtNetVolumeDriver',
'nfs=nova.virt.libvirt.volume.LibvirtNFSVolumeDriver',
- 'aoe=nova.virt.libvirt.volume.LibvirtAOEVolumeDriver'
+ 'aoe=nova.virt.libvirt.volume.LibvirtAOEVolumeDriver',
+ 'glusterfs='
+ 'nova.virt.libvirt.volume.LibvirtGlusterfsVolumeDriver'
],
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 9ec8f6bcb..c368f66f6 100644
--- a/nova/virt/libvirt/volume.py
+++ b/nova/virt/libvirt/volume.py
@@ -52,7 +52,11 @@ volume_opts = [
'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')
+ help='number of times to rediscover AoE target to find volume'),
+ cfg.StrOpt('glusterfs_mount_point_base',
+ default=paths.state_path_def('mnt'),
+ help='Dir where the glusterfs volume is mounted on the '
+ 'compute node'),
]
CONF = cfg.CONF
@@ -390,3 +394,59 @@ class LibvirtAOEVolumeDriver(LibvirtBaseVolumeDriver):
conf.source_type = "block"
conf.source_path = aoedevpath
return conf
+
+
+class LibvirtGlusterfsVolumeDriver(LibvirtBaseVolumeDriver):
+ """Class implements libvirt part of volume driver for GlusterFS."""
+
+ def __init__(self, connection):
+ """Create back-end to glusterfs."""
+ super(LibvirtGlusterfsVolumeDriver,
+ self).__init__(connection, is_block_dev=False)
+
+ def connect_volume(self, connection_info, mount_device):
+ """Connect the volume. Returns xml for libvirt."""
+ conf = super(LibvirtGlusterfsVolumeDriver,
+ self).connect_volume(connection_info, mount_device)
+ path = self._ensure_mounted(connection_info['data']['export'])
+ path = os.path.join(path, connection_info['data']['name'])
+ conf.source_type = 'file'
+ conf.source_path = path
+ return conf
+
+ def _ensure_mounted(self, glusterfs_export):
+ """
+ @type glusterfs_export: string
+ """
+ mount_path = os.path.join(CONF.glusterfs_mount_point_base,
+ self.get_hash_str(glusterfs_export))
+ self._mount_glusterfs(mount_path, glusterfs_export, ensure=True)
+ return mount_path
+
+ def _mount_glusterfs(self, mount_path, glusterfs_share, ensure=False):
+ """Mount glusterfs export to mount path."""
+ if not self._path_exists(mount_path):
+ utils.execute('mkdir', '-p', mount_path)
+
+ try:
+ utils.execute('mount', '-t', 'glusterfs', glusterfs_share,
+ mount_path,
+ run_as_root=True)
+ except exception.ProcessExecutionError as exc:
+ if ensure and 'already mounted' in exc.message:
+ LOG.warn(_("%s is already mounted"), glusterfs_share)
+ else:
+ raise
+
+ @staticmethod
+ def get_hash_str(base_str):
+ """returns string that represents hash of base_str (in hex format)."""
+ return hashlib.md5(base_str).hexdigest()
+
+ @staticmethod
+ def _path_exists(path):
+ """Check path."""
+ try:
+ return utils.execute('stat', path, run_as_root=True)
+ except exception.ProcessExecutionError:
+ return False