Revision a81c53c9

b/lib/config.py
77 77
    else:
78 78
      self._cfg_file = cfg_file
79 79
    self._temporary_ids = set()
80
    self._temporary_drbds = {}
80 81
    # Note: in order to prevent errors when resolving our name in
81 82
    # _DistributeConfig, we compute it here once and reuse it; it's
82 83
    # better to raise an error before starting to modify the config
......
307 308
    self._WriteConfig()
308 309
    return port
309 310

  
311
  def _ComputeDRBDMap(self, instance):
312
    """Compute the used DRBD minor/nodes.
313

  
314
    Return: dictionary of node_name: dict of minor: instance_name. The
315
    returned dict will have all the nodes in it (even if with an empty
316
    list).
317

  
318
    """
319
    def _AppendUsedPorts(instance_name, disk, used):
320
      if disk.dev_type == constants.LD_DRBD8 and len(disk.logical_id) == 5:
321
        nodeA, nodeB, dummy, minorA, minorB = disk.logical_id
322
        for node, port in ((nodeA, minorA), (nodeB, minorB)):
323
          assert node in used, "Instance node not found in node list"
324
          if port in used[node]:
325
            raise errors.ProgrammerError("DRBD minor already used:"
326
                                         " %s/%s, %s/%s" %
327
                                         (node, port, instance_name,
328
                                          used[node][port]))
329

  
330
          used[node][port] = instance_name
331
      if disk.children:
332
        for child in disk.children:
333
          _AppendUsedPorts(instance_name, child, used)
334

  
335
    my_dict = dict((node, {}) for node in self._config_data.nodes)
336
    for (node, minor), instance in self._temporary_drbds.iteritems():
337
      my_dict[node][minor] = instance
338
    for instance in self._config_data.instances.itervalues():
339
      for disk in instance.disks:
340
        _AppendUsedPorts(instance.name, disk, my_dict)
341
    return my_dict
342

  
343
  @locking.ssynchronized(_config_lock)
344
  def AllocateDRBDMinor(self, nodes, instance):
345
    """Allocate a drbd minor.
346

  
347
    The free minor will be automatically computed from the existing
348
    devices. A node can be given multiple times in order to allocate
349
    multiple minors. The result is the list of minors, in the same
350
    order as the passed nodes.
351

  
352
    """
353
    self._OpenConfig()
354

  
355
    d_map = self._ComputeDRBDMap(instance)
356
    result = []
357
    for nname in nodes:
358
      ndata = d_map[nname]
359
      if not ndata:
360
        # no minors used, we can start at 0
361
        result.append(0)
362
        ndata[0] = instance
363
        continue
364
      keys = ndata.keys()
365
      keys.sort()
366
      ffree = utils.FirstFree(keys)
367
      if ffree is None:
368
        # return the next minor
369
        # TODO: implement high-limit check
370
        minor = keys[-1] + 1
371
      else:
372
        minor = ffree
373
      result.append(minor)
374
      ndata[minor] = instance
375
      assert (nname, minor) not in self._temporary_drbds, \
376
             "Attempt to reuse reserved DRBD minor"
377
      self._temporary_drbds[(nname, minor)] = instance
378
    logging.debug("Request to allocate drbd minors, input: %s, returning %s",
379
                  nodes, result)
380
    return result
381

  
382
  @locking.ssynchronized(_config_lock)
383
  def ReleaseDRBDMinors(self, instance):
384
    """Release temporary drbd minors allocated for a given instance.
385

  
386
    This should be called on both the error paths and on the success
387
    paths (after the instance has been added or updated).
388

  
389
    @type instance: string
390
    @param instance: the instance for which temporary minors should be
391
                     released
392

  
393
    """
394
    for key, name in self._temporary_drbds.items():
395
      if name == instance:
396
        del self._temporary_drbds[key]
397

  
310 398
  @locking.ssynchronized(_config_lock, shared=1)
311 399
  def GetHostKey(self):
312 400
    """Return the rsa hostkey from the config.

Also available in: Unified diff