Revision 845b7ed1

b/lib/cmdlib/instance.py
1557 1557
    old_name = self.instance.name
1558 1558

  
1559 1559
    rename_file_storage = False
1560
    if (self.instance.disk_template in constants.DTS_FILEBASED and
1560
    if (self.instance.disk_template in (constants.DT_FILE,
1561
                                        constants.DT_SHARED_FILE) and
1561 1562
        self.op.new_name != self.instance.name):
1562 1563
      old_file_storage_dir = os.path.dirname(
1563 1564
                               self.instance.disks[0].logical_id[1])
b/lib/cmdlib/instance_storage.py
460 460
        vg = disk.get(constants.IDISK_VG, vgname)
461 461
        return (vg, names[idx])
462 462

  
463
    elif template_name in constants.DTS_FILEBASED:
463
    elif template_name == constants.DT_GLUSTER:
464
      logical_id_fn = lambda _1, disk_index, _2: \
465
        (file_driver, "ganeti/%s.%d" % (instance_uuid,
466
                                        disk_index))
467

  
468
    elif template_name in constants.DTS_FILEBASED: # Gluster handled above
464 469
      logical_id_fn = \
465 470
        lambda _, disk_index, disk: (file_driver,
466 471
                                     "%s/disk%d" % (file_storage_dir,
b/lib/cmdlib/instance_utils.py
292 292

  
293 293
  CheckDiskTemplateEnabled(lu.cfg.GetClusterInfo(), instance.disk_template)
294 294

  
295
  if instance.disk_template in constants.DTS_FILEBASED:
295
  if instance.disk_template in [constants.DT_FILE, constants.DT_SHARED_FILE]:
296 296
    file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
297 297
    if target_node_uuid:
298 298
      tgt = target_node_uuid
b/lib/storage/gluster.py
33 33
from ganeti import errors
34 34
from ganeti import netutils
35 35
from ganeti import constants
36
from ganeti import ssconf
36 37

  
37 38
from ganeti.utils import io
38 39
from ganeti.storage import base
......
277 278
class GlusterStorage(base.BlockDev):
278 279
  """File device using the Gluster backend.
279 280

  
280
  This class represents a file storage backend device stored on Gluster. The
281
  system administrator must mount the Gluster device himself at boot time before
282
  Ganeti is run.
281
  This class represents a file storage backend device stored on Gluster. Ganeti
282
  mounts and unmounts the Gluster devices automatically.
283 283

  
284 284
  The unique_id for the file device is a (file_driver, file_path) tuple.
285 285

  
......
290 290
    """
291 291
    if children:
292 292
      base.ThrowError("Invalid setup for file device")
293
    super(GlusterStorage, self).__init__(unique_id, children, size, params,
294
                                         dyn_params)
295
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
296
      raise ValueError("Invalid configuration data %s" % str(unique_id))
297
    self.driver = unique_id[0]
298
    self.dev_path = unique_id[1]
299 293

  
300
    self.file = FileDeviceHelper(self.dev_path)
294
    try:
295
      driver, path = unique_id
296
    except ValueError: # wrong number of arguments
297
      raise ValueError("Invalid configuration data %s" % repr(unique_id))
298

  
299
    server_addr = params[constants.GLUSTER_HOST]
300
    port = params[constants.GLUSTER_PORT]
301
    volume = params[constants.GLUSTER_VOLUME]
302

  
303
    self.volume = GlusterVolume(server_addr, port, volume)
304
    self.path = path
305
    self.driver = driver
306
    self.full_path = io.PathJoin(self.volume.mount_point, self.path)
307
    self.file = None
308

  
309
    super(GlusterStorage, self).__init__(unique_id, children, size,
310
                                         params, dyn_params)
301 311

  
302 312
    self.Attach()
303 313

  
......
341 351
    @return: True if the removal was successful
342 352

  
343 353
    """
344
    return self.file.Remove()
354
    with self.volume.Mount():
355
      self.file = FileDeviceHelper(self.full_path)
356
      if self.file.Remove():
357
        self.file = None
358
        return True
359
      else:
360
        return False
345 361

  
346 362
  def Rename(self, new_id):
347 363
    """Renames the file.
......
367 383
    @return: True if file exists
368 384

  
369 385
    """
386
    try:
387
      self.volume.Mount()
388
      self.file = FileDeviceHelper(self.full_path)
389
      self.dev_path = self.full_path
390
    except Exception as err:
391
      self.volume.Unmount()
392
      raise err
393

  
370 394
    self.attached = self.file.Exists()
371 395
    return self.attached
372 396

  
......
395 419
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
396 420
      raise ValueError("Invalid configuration data %s" % str(unique_id))
397 421

  
398
    dev_path = unique_id[1]
422
    full_path = unique_id[1]
423

  
424
    server_addr = params[constants.GLUSTER_HOST]
425
    port = params[constants.GLUSTER_PORT]
426
    volume = params[constants.GLUSTER_VOLUME]
427

  
428
    volume_obj = GlusterVolume(server_addr, port, volume)
429
    full_path = io.PathJoin(volume_obj.mount_point, full_path)
430

  
431
    # Possible optimization: defer actual creation to first Attach, rather
432
    # than mounting and unmounting here, then remounting immediately after.
433
    with volume_obj.Mount():
434
      FileDeviceHelper.CreateFile(full_path, size, create_folders=True)
399 435

  
400
    FileDeviceHelper.Create(dev_path, size)
401 436
    return GlusterStorage(unique_id, children, size, params, dyn_params)
b/src/Ganeti/Constants.hs
2167 2167
                (drbdMinRate, VTypeInt),
2168 2168
                (lvStripes, VTypeInt),
2169 2169
                (rbdAccess, VTypeString),
2170
                (rbdPool, VTypeString)]
2170
                (rbdPool, VTypeString),
2171
                (glusterHost, VTypeString),
2172
                (glusterVolume, VTypeString),
2173
                (glusterPort, VTypeInt)
2174
               ]
2171 2175

  
2172 2176
diskDtParameters :: FrozenSet String
2173 2177
diskDtParameters = ConstantUtils.mkSet (Map.keys diskDtTypes)
......
3773 3777
            , (ldpAccess, PyValueEx diskKernelspace)
3774 3778
            ])
3775 3779
  , (DTSharedFile, Map.empty)
3776
  , (DTGluster, Map.empty)
3780
  , (DTGluster, Map.fromList
3781
                [ (rbdAccess, PyValueEx diskKernelspace)
3782
                , (glusterHost, PyValueEx glusterHostDefault)
3783
                , (glusterVolume, PyValueEx glusterVolumeDefault)
3784
                , (glusterPort, PyValueEx glusterPortDefault)
3785
                ])
3777 3786
  ]
3778 3787

  
3779 3788
diskDtDefaults :: Map DiskTemplate (Map String PyValueEx)
......
3806 3815
                   , (rbdAccess, PyValueEx diskKernelspace)
3807 3816
                   ])
3808 3817
  , (DTSharedFile, Map.empty)
3809
  , (DTGluster, Map.empty)
3818
  , (DTGluster, Map.fromList
3819
                [ (rbdAccess, PyValueEx diskKernelspace)
3820
                , (glusterHost, PyValueEx glusterHostDefault)
3821
                , (glusterVolume, PyValueEx glusterVolumeDefault)
3822
                , (glusterPort, PyValueEx glusterPortDefault)
3823
                ])
3810 3824
  ]
3811 3825

  
3812 3826
niccDefaults :: Map String PyValueEx
......
4592 4606

  
4593 4607
-- * Gluster settings
4594 4608

  
4595
-- | Where Ganeti should manage Gluster volume mountpoints
4596
glusterMountpoint :: String
4597
glusterMountpoint = "/var/run/ganeti/gluster"
4609
-- | Name of the Gluster host setting
4610
glusterHost :: String
4611
glusterHost = "host"
4612

  
4613
-- | Default value of the Gluster host setting
4614
glusterHostDefault :: String
4615
glusterHostDefault = "127.0.0.1"
4616

  
4617
-- | Name of the Gluster volume setting
4618
glusterVolume :: String
4619
glusterVolume = "volume"
4620

  
4621
-- | Default value of the Gluster volume setting
4622
glusterVolumeDefault :: String
4623
glusterVolumeDefault = "gv0"
4624

  
4625
-- | Name of the Gluster port setting
4626
glusterPort :: String
4627
glusterPort = "port"
4628

  
4629
-- | Default value of the Gluster port setting
4630
glusterPortDefault :: Int
4631
glusterPortDefault = 24007
b/test/py/cmdlib/instance_unittest.py
1106 1106
        disk_template, disk_info, 2, disk_template,
1107 1107
        file_storage_dir="/tmp", file_driver=constants.FD_BLKTAP)
1108 1108

  
1109
      self.assertEqual(map(operator.attrgetter("logical_id"), result), [
1110
        (constants.FD_BLKTAP, "/tmp/disk2"),
1111
        (constants.FD_BLKTAP, "/tmp/disk3"),
1112
        (constants.FD_BLKTAP, "/tmp/disk4"),
1113
        ])
1109
      if disk_template == constants.DT_GLUSTER:
1110
        # Here "inst21662.example.com" is actually the instance UUID, not its
1111
        # name, so while this result looks wrong, it is actually correct.
1112
        expected = [(constants.FD_BLKTAP,
1113
                     'ganeti/inst21662.example.com.%d' % x)
1114
                    for x in (2,3,4)]
1115
      else:
1116
        expected = [(constants.FD_BLKTAP,
1117
                     '/tmp/disk%d' % x)
1118
                    for x in (2,3,4)]
1119

  
1120
      self.assertEqual(map(operator.attrgetter("logical_id"), result),
1121
                       expected)
1114 1122

  
1115 1123
  def testBlock(self):
1116 1124
    disk_info = [{

Also available in: Unified diff