LGTM, thanks!
On Tue, Dec 17, 2013 at 10:28 AM, Santi Raffa <[email protected]> wrote: > Add parameters to the Gluster disk template so Gluster can manage the > mount point point autonomously. > > Signed-off-by: Santi Raffa <[email protected]> > --- > lib/cmdlib/instance.py | 3 +- > lib/cmdlib/instance_storage.py | 7 +++- > lib/cmdlib/instance_utils.py | 2 +- > lib/storage/gluster.py | 61 > +++++++++++++++++++++++++++-------- > src/Ganeti/Constants.hs | 46 ++++++++++++++++++++++---- > test/py/cmdlib/instance_unittest.py | 18 ++++++++--- > 6 files changed, 110 insertions(+), 27 deletions(-) > > diff --git a/lib/cmdlib/instance.py b/lib/cmdlib/instance.py > index 11a2b03..9665b6f 100644 > --- a/lib/cmdlib/instance.py > +++ b/lib/cmdlib/instance.py > @@ -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]) > diff --git a/lib/cmdlib/instance_storage.py > b/lib/cmdlib/instance_storage.py > index 641b253..333de1b 100644 > --- a/lib/cmdlib/instance_storage.py > +++ b/lib/cmdlib/instance_storage.py > @@ -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, > diff --git a/lib/cmdlib/instance_utils.py b/lib/cmdlib/instance_utils.py > index 752e66d..9e10fd1 100644 > --- a/lib/cmdlib/instance_utils.py > +++ b/lib/cmdlib/instance_utils.py > @@ -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 > diff --git a/lib/storage/gluster.py b/lib/storage/gluster.py > index 9790d55..e8f485d 100644 > --- a/lib/storage/gluster.py > +++ b/lib/storage/gluster.py > @@ -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 > @@ -278,9 +279,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. > > @@ -291,14 +291,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() > > @@ -342,7 +352,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. > @@ -368,6 +384,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 > > @@ -396,7 +420,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) > diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs > index 427e5db..654429e 100644 > --- a/src/Ganeti/Constants.hs > +++ b/src/Ganeti/Constants.hs > @@ -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 > diff --git a/test/py/cmdlib/instance_unittest.py > b/test/py/cmdlib/instance_unittest.py > index 448d7c9..49a054e 100644 > --- a/test/py/cmdlib/instance_unittest.py > +++ b/test/py/cmdlib/instance_unittest.py > @@ -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 = [{ > -- > 1.7.10.4 > > -- Thomas Thrainer | Software Engineer | [email protected] | Google Germany GmbH Dienerstr. 12 80331 München Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschäftsführer: Graham Law, Christine Elizabeth Flores
