Revision 63c73073 lib/bdev.py

b/lib/bdev.py
29 29
import pyparsing as pyp
30 30
import os
31 31
import logging
32
import math
32 33

  
33 34
from ganeti import utils
34 35
from ganeti import errors
......
523 524
    self.major = self.minor = self.pe_size = self.stripe_count = None
524 525
    self.Attach()
525 526

  
527
  @staticmethod
528
  def _GetStdPvSize(pvs_info):
529
    """Return the the standard PV size (used with exclusive storage).
530

  
531
    @param pvs_info: list of objects.LvmPvInfo, cannot be empty
532
    @rtype: float
533
    @return: size in MiB
534

  
535
    """
536
    assert len(pvs_info) > 0
537
    smallest = min([pv.size for pv in pvs_info])
538
    return smallest / (1 + constants.PART_MARGIN + constants.PART_RESERVED)
539

  
540
  @staticmethod
541
  def _ComputeNumPvs(size, pvs_info):
542
    """Compute the number of PVs needed for an LV (with exclusive storage).
543

  
544
    @type size: float
545
    @param size: LV size
546
    @param pvs_info: list of objects.LvmPvInfo, cannot be empty
547
    @rtype: integer
548
    @return: number of PVs needed
549
    """
550
    assert len(pvs_info) > 0
551
    pv_size = float(LogicalVolume._GetStdPvSize(pvs_info))
552
    return int(math.ceil(float(size) / pv_size))
553

  
554
  @staticmethod
555
  def _GetEmptyPvNames(pvs_info, max_pvs=None):
556
    """Return a list of empty PVs, by name.
557

  
558
    """
559
    empty_pvs = filter(objects.LvmPvInfo.IsEmpty, pvs_info)
560
    if max_pvs is not None:
561
      empty_pvs = empty_pvs[:max_pvs]
562
    return map((lambda pv: pv.name), empty_pvs)
563

  
526 564
  @classmethod
527 565
  def Create(cls, unique_id, children, size, params, excl_stor):
528 566
    """Create a new logical volume.
......
536 574
    cls._ValidateName(lv_name)
537 575
    pvs_info = cls.GetPVInfo([vg_name])
538 576
    if not pvs_info:
539
      _ThrowError("Can't compute PV info for vg %s", vg_name)
577
      if excl_stor:
578
        msg = "No (empty) PVs found"
579
      else:
580
        msg = "Can't compute PV info for vg %s" % vg_name
581
      _ThrowError(msg)
540 582
    pvs_info.sort(key=(lambda pv: pv.free), reverse=True)
541 583

  
542 584
    pvlist = [pv.name for pv in pvs_info]
......
544 586
      _ThrowError("Some of your PVs have the invalid character ':' in their"
545 587
                  " name, this is not supported - please filter them out"
546 588
                  " in lvm.conf using either 'filter' or 'preferred_names'")
547
    free_size = sum([pv.free for pv in pvs_info])
589

  
548 590
    current_pvs = len(pvlist)
549 591
    desired_stripes = params[constants.LDP_STRIPES]
550 592
    stripes = min(current_pvs, desired_stripes)
551
    if stripes < desired_stripes:
552
      logging.warning("Could not use %d stripes for VG %s, as only %d PVs are"
553
                      " available.", desired_stripes, vg_name, current_pvs)
554 593

  
555
    # The size constraint should have been checked from the master before
556
    # calling the create function.
557
    if free_size < size:
558
      _ThrowError("Not enough free space: required %s,"
559
                  " available %s", size, free_size)
560
    cmd = ["lvcreate", "-L%dm" % size, "-n%s" % lv_name]
594
    if excl_stor:
595
      err_msgs = utils.LvmExclusiveCheckNodePvs(pvs_info)
596
      if err_msgs:
597
        for m in err_msgs:
598
          logging.warning(m)
599
      req_pvs = cls._ComputeNumPvs(size, pvs_info)
600
      pvlist = cls._GetEmptyPvNames(pvs_info, req_pvs)
601
      current_pvs = len(pvlist)
602
      if current_pvs < req_pvs:
603
        _ThrowError("Not enough empty PVs to create a disk of %d MB:"
604
                    " %d available, %d needed", size, current_pvs, req_pvs)
605
      assert current_pvs == len(pvlist)
606
      if stripes > current_pvs:
607
        # No warning issued for this, as it's no surprise
608
        stripes = current_pvs
609

  
610
    else:
611
      if stripes < desired_stripes:
612
        logging.warning("Could not use %d stripes for VG %s, as only %d PVs are"
613
                        " available.", desired_stripes, vg_name, current_pvs)
614
      free_size = sum([pv.free for pv in pvs_info])
615
      # The size constraint should have been checked from the master before
616
      # calling the create function.
617
      if free_size < size:
618
        _ThrowError("Not enough free space: required %s,"
619
                    " available %s", size, free_size)
620

  
561 621
    # If the free space is not well distributed, we won't be able to
562 622
    # create an optimally-striped volume; in that case, we want to try
563 623
    # with N, N-1, ..., 2, and finally 1 (non-stripped) number of
564 624
    # stripes
625
    cmd = ["lvcreate", "-L%dm" % size, "-n%s" % lv_name]
565 626
    for stripes_arg in range(stripes, 0, -1):
566 627
      result = utils.RunCmd(cmd + ["-i%d" % stripes_arg] + [vg_name] + pvlist)
567 628
      if not result.failed:

Also available in: Unified diff