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): ...@@ -1557,7 +1557,8 @@ class LUInstanceRename(LogicalUnit):
old_name = self.instance.name old_name = self.instance.name
rename_file_storage = False 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): self.op.new_name != self.instance.name):
old_file_storage_dir = os.path.dirname( old_file_storage_dir = os.path.dirname(
self.instance.disks[0].logical_id[1]) self.instance.disks[0].logical_id[1])
......
...@@ -460,7 +460,12 @@ def GenerateDiskTemplate( ...@@ -460,7 +460,12 @@ def GenerateDiskTemplate(
vg = disk.get(constants.IDISK_VG, vgname) vg = disk.get(constants.IDISK_VG, vgname)
return (vg, names[idx]) 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 = \ logical_id_fn = \
lambda _, disk_index, disk: (file_driver, lambda _, disk_index, disk: (file_driver,
"%s/disk%d" % (file_storage_dir, "%s/disk%d" % (file_storage_dir,
......
...@@ -292,7 +292,7 @@ def RemoveDisks(lu, instance, target_node_uuid=None, ignore_failures=False): ...@@ -292,7 +292,7 @@ def RemoveDisks(lu, instance, target_node_uuid=None, ignore_failures=False):
CheckDiskTemplateEnabled(lu.cfg.GetClusterInfo(), instance.disk_template) 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]) file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
if target_node_uuid: if target_node_uuid:
tgt = target_node_uuid tgt = target_node_uuid
......
...@@ -33,6 +33,7 @@ from ganeti import utils ...@@ -33,6 +33,7 @@ from ganeti import utils
from ganeti import errors from ganeti import errors
from ganeti import netutils from ganeti import netutils
from ganeti import constants from ganeti import constants
from ganeti import ssconf
from ganeti.utils import io from ganeti.utils import io
from ganeti.storage import base from ganeti.storage import base
...@@ -277,9 +278,8 @@ class GlusterVolume(object): ...@@ -277,9 +278,8 @@ class GlusterVolume(object):
class GlusterStorage(base.BlockDev): class GlusterStorage(base.BlockDev):
"""File device using the Gluster backend. """File device using the Gluster backend.
This class represents a file storage backend device stored on Gluster. The This class represents a file storage backend device stored on Gluster. Ganeti
system administrator must mount the Gluster device himself at boot time before mounts and unmounts the Gluster devices automatically.
Ganeti is run.
The unique_id for the file device is a (file_driver, file_path) tuple. The unique_id for the file device is a (file_driver, file_path) tuple.
...@@ -290,14 +290,24 @@ class GlusterStorage(base.BlockDev): ...@@ -290,14 +290,24 @@ class GlusterStorage(base.BlockDev):
""" """
if children: if children:
base.ThrowError("Invalid setup for file device") 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() self.Attach()
...@@ -341,7 +351,13 @@ class GlusterStorage(base.BlockDev): ...@@ -341,7 +351,13 @@ class GlusterStorage(base.BlockDev):
@return: True if the removal was successful @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): def Rename(self, new_id):
"""Renames the file. """Renames the file.
...@@ -367,6 +383,14 @@ class GlusterStorage(base.BlockDev): ...@@ -367,6 +383,14 @@ class GlusterStorage(base.BlockDev):
@return: True if file exists @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() self.attached = self.file.Exists()
return self.attached return self.attached
...@@ -395,7 +419,18 @@ class GlusterStorage(base.BlockDev): ...@@ -395,7 +419,18 @@ class GlusterStorage(base.BlockDev):
if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2: if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
raise ValueError("Invalid configuration data %s" % str(unique_id)) 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) return GlusterStorage(unique_id, children, size, params, dyn_params)
...@@ -2167,7 +2167,11 @@ diskDtTypes = ...@@ -2167,7 +2167,11 @@ diskDtTypes =
(drbdMinRate, VTypeInt), (drbdMinRate, VTypeInt),
(lvStripes, VTypeInt), (lvStripes, VTypeInt),
(rbdAccess, VTypeString), (rbdAccess, VTypeString),
(rbdPool, VTypeString)] (rbdPool, VTypeString),
(glusterHost, VTypeString),
(glusterVolume, VTypeString),
(glusterPort, VTypeInt)
]
diskDtParameters :: FrozenSet String diskDtParameters :: FrozenSet String
diskDtParameters = ConstantUtils.mkSet (Map.keys diskDtTypes) diskDtParameters = ConstantUtils.mkSet (Map.keys diskDtTypes)
...@@ -3773,7 +3777,12 @@ diskLdDefaults = ...@@ -3773,7 +3777,12 @@ diskLdDefaults =
, (ldpAccess, PyValueEx diskKernelspace) , (ldpAccess, PyValueEx diskKernelspace)
]) ])
, (DTSharedFile, Map.empty) , (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) diskDtDefaults :: Map DiskTemplate (Map String PyValueEx)
...@@ -3806,7 +3815,12 @@ diskDtDefaults = ...@@ -3806,7 +3815,12 @@ diskDtDefaults =
, (rbdAccess, PyValueEx diskKernelspace) , (rbdAccess, PyValueEx diskKernelspace)
]) ])
, (DTSharedFile, Map.empty) , (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 niccDefaults :: Map String PyValueEx
...@@ -4592,6 +4606,26 @@ jstoreJobsPerArchiveDirectory = 10000 ...@@ -4592,6 +4606,26 @@ jstoreJobsPerArchiveDirectory = 10000
-- * Gluster settings -- * Gluster settings
-- | Where Ganeti should manage Gluster volume mountpoints -- | Name of the Gluster host setting
glusterMountpoint :: String glusterHost :: String
glusterMountpoint = "/var/run/ganeti/gluster" 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): ...@@ -1106,11 +1106,19 @@ class TestGenerateDiskTemplate(CmdlibTestCase):
disk_template, disk_info, 2, disk_template, disk_template, disk_info, 2, disk_template,
file_storage_dir="/tmp", file_driver=constants.FD_BLKTAP) file_storage_dir="/tmp", file_driver=constants.FD_BLKTAP)
self.assertEqual(map(operator.attrgetter("logical_id"), result), [ if disk_template == constants.DT_GLUSTER:
(constants.FD_BLKTAP, "/tmp/disk2"), # Here "inst21662.example.com" is actually the instance UUID, not its
(constants.FD_BLKTAP, "/tmp/disk3"), # name, so while this result looks wrong, it is actually correct.
(constants.FD_BLKTAP, "/tmp/disk4"), 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): def testBlock(self):
disk_info = [{ 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