Commit 845b7ed1 authored by Santi Raffa's avatar Santi Raffa Committed by Thomas Thrainer

Gluster: mount automatically

Add parameters to the Gluster disk template so Gluster can manage the
mount point point autonomously.
Signed-off-by: default avatarSanti Raffa <rsanti@google.com>
Signed-off-by: default avatarThomas Thrainer <thomasth@google.com>
Reviewed-by: default avatarThomas Thrainer <thomasth@google.com>
parent ac156ecd
......@@ -1557,7 +1557,8 @@ class LUInstanceRename(LogicalUnit):
old_name = self.instance.name
rename_file_storage = False
if (self.instance.disk_template in constants.DTS_FILEBASED and
if (self.instance.disk_template in (constants.DT_FILE,
constants.DT_SHARED_FILE) and
self.op.new_name != self.instance.name):
old_file_storage_dir = os.path.dirname(
self.instance.disks[0].logical_id[1])
......
......@@ -460,7 +460,12 @@ def GenerateDiskTemplate(
vg = disk.get(constants.IDISK_VG, vgname)
return (vg, names[idx])
elif template_name in constants.DTS_FILEBASED:
elif template_name == constants.DT_GLUSTER:
logical_id_fn = lambda _1, disk_index, _2: \
(file_driver, "ganeti/%s.%d" % (instance_uuid,
disk_index))
elif template_name in constants.DTS_FILEBASED: # Gluster handled above
logical_id_fn = \
lambda _, disk_index, disk: (file_driver,
"%s/disk%d" % (file_storage_dir,
......
......@@ -292,7 +292,7 @@ def RemoveDisks(lu, instance, target_node_uuid=None, ignore_failures=False):
CheckDiskTemplateEnabled(lu.cfg.GetClusterInfo(), instance.disk_template)
if instance.disk_template in constants.DTS_FILEBASED:
if instance.disk_template in [constants.DT_FILE, constants.DT_SHARED_FILE]:
file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
if target_node_uuid:
tgt = target_node_uuid
......
......@@ -33,6 +33,7 @@ from ganeti import utils
from ganeti import errors
from ganeti import netutils
from ganeti import constants
from ganeti import ssconf
from ganeti.utils import io
from ganeti.storage import base
......@@ -277,9 +278,8 @@ class GlusterVolume(object):
class GlusterStorage(base.BlockDev):
"""File device using the Gluster backend.
This class represents a file storage backend device stored on Gluster. The
system administrator must mount the Gluster device himself at boot time before
Ganeti is run.
This class represents a file storage backend device stored on Gluster. Ganeti
mounts and unmounts the Gluster devices automatically.
The unique_id for the file device is a (file_driver, file_path) tuple.
......@@ -290,14 +290,24 @@ class GlusterStorage(base.BlockDev):
"""
if children:
base.ThrowError("Invalid setup for file device")
super(GlusterStorage, self).__init__(unique_id, children, size, params,
dyn_params)
if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
raise ValueError("Invalid configuration data %s" % str(unique_id))
self.driver = unique_id[0]
self.dev_path = unique_id[1]
self.file = FileDeviceHelper(self.dev_path)
try:
driver, path = unique_id
except ValueError: # wrong number of arguments
raise ValueError("Invalid configuration data %s" % repr(unique_id))
server_addr = params[constants.GLUSTER_HOST]
port = params[constants.GLUSTER_PORT]
volume = params[constants.GLUSTER_VOLUME]
self.volume = GlusterVolume(server_addr, port, volume)
self.path = path
self.driver = driver
self.full_path = io.PathJoin(self.volume.mount_point, self.path)
self.file = None
super(GlusterStorage, self).__init__(unique_id, children, size,
params, dyn_params)
self.Attach()
......@@ -341,7 +351,13 @@ class GlusterStorage(base.BlockDev):
@return: True if the removal was successful
"""
return self.file.Remove()
with self.volume.Mount():
self.file = FileDeviceHelper(self.full_path)
if self.file.Remove():
self.file = None
return True
else:
return False
def Rename(self, new_id):
"""Renames the file.
......@@ -367,6 +383,14 @@ class GlusterStorage(base.BlockDev):
@return: True if file exists
"""
try:
self.volume.Mount()
self.file = FileDeviceHelper(self.full_path)
self.dev_path = self.full_path
except Exception as err:
self.volume.Unmount()
raise err
self.attached = self.file.Exists()
return self.attached
......@@ -395,7 +419,18 @@ class GlusterStorage(base.BlockDev):
if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
raise ValueError("Invalid configuration data %s" % str(unique_id))
dev_path = unique_id[1]
full_path = unique_id[1]
server_addr = params[constants.GLUSTER_HOST]
port = params[constants.GLUSTER_PORT]
volume = params[constants.GLUSTER_VOLUME]
volume_obj = GlusterVolume(server_addr, port, volume)
full_path = io.PathJoin(volume_obj.mount_point, full_path)
# Possible optimization: defer actual creation to first Attach, rather
# than mounting and unmounting here, then remounting immediately after.
with volume_obj.Mount():
FileDeviceHelper.CreateFile(full_path, size, create_folders=True)
FileDeviceHelper.Create(dev_path, size)
return GlusterStorage(unique_id, children, size, params, dyn_params)
......@@ -2167,7 +2167,11 @@ diskDtTypes =
(drbdMinRate, VTypeInt),
(lvStripes, VTypeInt),
(rbdAccess, VTypeString),
(rbdPool, VTypeString)]
(rbdPool, VTypeString),
(glusterHost, VTypeString),
(glusterVolume, VTypeString),
(glusterPort, VTypeInt)
]
diskDtParameters :: FrozenSet String
diskDtParameters = ConstantUtils.mkSet (Map.keys diskDtTypes)
......@@ -3773,7 +3777,12 @@ diskLdDefaults =
, (ldpAccess, PyValueEx diskKernelspace)
])
, (DTSharedFile, Map.empty)
, (DTGluster, Map.empty)
, (DTGluster, Map.fromList
[ (rbdAccess, PyValueEx diskKernelspace)
, (glusterHost, PyValueEx glusterHostDefault)
, (glusterVolume, PyValueEx glusterVolumeDefault)
, (glusterPort, PyValueEx glusterPortDefault)
])
]
diskDtDefaults :: Map DiskTemplate (Map String PyValueEx)
......@@ -3806,7 +3815,12 @@ diskDtDefaults =
, (rbdAccess, PyValueEx diskKernelspace)
])
, (DTSharedFile, Map.empty)
, (DTGluster, Map.empty)
, (DTGluster, Map.fromList
[ (rbdAccess, PyValueEx diskKernelspace)
, (glusterHost, PyValueEx glusterHostDefault)
, (glusterVolume, PyValueEx glusterVolumeDefault)
, (glusterPort, PyValueEx glusterPortDefault)
])
]
niccDefaults :: Map String PyValueEx
......@@ -4592,6 +4606,26 @@ jstoreJobsPerArchiveDirectory = 10000
-- * Gluster settings
-- | Where Ganeti should manage Gluster volume mountpoints
glusterMountpoint :: String
glusterMountpoint = "/var/run/ganeti/gluster"
-- | Name of the Gluster host setting
glusterHost :: String
glusterHost = "host"
-- | Default value of the Gluster host setting
glusterHostDefault :: String
glusterHostDefault = "127.0.0.1"
-- | Name of the Gluster volume setting
glusterVolume :: String
glusterVolume = "volume"
-- | Default value of the Gluster volume setting
glusterVolumeDefault :: String
glusterVolumeDefault = "gv0"
-- | Name of the Gluster port setting
glusterPort :: String
glusterPort = "port"
-- | Default value of the Gluster port setting
glusterPortDefault :: Int
glusterPortDefault = 24007
......@@ -1106,11 +1106,19 @@ class TestGenerateDiskTemplate(CmdlibTestCase):
disk_template, disk_info, 2, disk_template,
file_storage_dir="/tmp", file_driver=constants.FD_BLKTAP)
self.assertEqual(map(operator.attrgetter("logical_id"), result), [
(constants.FD_BLKTAP, "/tmp/disk2"),
(constants.FD_BLKTAP, "/tmp/disk3"),
(constants.FD_BLKTAP, "/tmp/disk4"),
])
if disk_template == constants.DT_GLUSTER:
# Here "inst21662.example.com" is actually the instance UUID, not its
# name, so while this result looks wrong, it is actually correct.
expected = [(constants.FD_BLKTAP,
'ganeti/inst21662.example.com.%d' % x)
for x in (2,3,4)]
else:
expected = [(constants.FD_BLKTAP,
'/tmp/disk%d' % x)
for x in (2,3,4)]
self.assertEqual(map(operator.attrgetter("logical_id"), result),
expected)
def testBlock(self):
disk_info = [{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment