Revision 59726e15

b/Makefile.am
345 345
	lib/utils/hash.py \
346 346
	lib/utils/io.py \
347 347
	lib/utils/log.py \
348
	lib/utils/lvm.py \
348 349
	lib/utils/mlock.py \
349 350
	lib/utils/nodesetup.py \
350 351
	lib/utils/process.py \
b/lib/backend.py
762 762
    result[constants.NV_VGLIST] = utils.ListVolumeGroups()
763 763

  
764 764
  if constants.NV_PVLIST in what and vm_capable:
765
    result[constants.NV_PVLIST] = \
766
      bdev.LogicalVolume.GetPVInfo(what[constants.NV_PVLIST],
767
                                   filter_allocatable=False)
765
    val = bdev.LogicalVolume.GetPVInfo(what[constants.NV_PVLIST],
766
                                       filter_allocatable=False)
767
    result[constants.NV_PVLIST] = map(objects.LvmPvInfo.ToDict, val)
768 768

  
769 769
  if constants.NV_VERSION in what:
770 770
    result[constants.NV_VERSION] = (constants.PROTOCOL_VERSION,
b/lib/bdev.py
537 537
    pvs_info = cls.GetPVInfo([vg_name])
538 538
    if not pvs_info:
539 539
      _ThrowError("Can't compute PV info for vg %s", vg_name)
540
    pvs_info.sort()
541
    pvs_info.reverse()
540
    pvs_info.sort(key=(lambda pv: pv.free), reverse=True)
542 541

  
543
    pvlist = [pv[1] for pv in pvs_info]
542
    pvlist = [pv.name for pv in pvs_info]
544 543
    if compat.any(":" in v for v in pvlist):
545 544
      _ThrowError("Some of your PVs have the invalid character ':' in their"
546 545
                  " name, this is not supported - please filter them out"
547 546
                  " in lvm.conf using either 'filter' or 'preferred_names'")
548
    free_size = sum([pv[0] for pv in pvs_info])
547
    free_size = sum([pv.free for pv in pvs_info])
549 548
    current_pvs = len(pvlist)
550 549
    desired_stripes = params[constants.LDP_STRIPES]
551 550
    stripes = min(current_pvs, desired_stripes)
......
613 612
    @param filter_allocatable: whether to skip over unallocatable PVs
614 613

  
615 614
    @rtype: list
616
    @return: list of tuples (free_space, name) with free_space in mebibytes
615
    @return: list of objects.LvmPvInfo objects
617 616

  
618 617
    """
619 618
    try:
620 619
      info = cls._GetVolumeInfo("pvs", ["pv_name", "vg_name", "pv_free",
621
                                        "pv_attr"])
620
                                        "pv_attr", "pv_size"])
622 621
    except errors.GenericError, err:
623 622
      logging.error("Can't get PV information: %s", err)
624 623
      return None
625 624

  
626 625
    data = []
627
    for pv_name, vg_name, pv_free, pv_attr in info:
626
    for (pv_name, vg_name, pv_free, pv_attr, pv_size) in info:
628 627
      # (possibly) skip over pvs which are not allocatable
629 628
      if filter_allocatable and pv_attr[0] != "a":
630 629
        continue
631 630
      # (possibly) skip over pvs which are not in the right volume group(s)
632 631
      if vg_names and vg_name not in vg_names:
633 632
        continue
634
      data.append((float(pv_free), pv_name, vg_name))
633
      pvi = objects.LvmPvInfo(name=pv_name, vg_name=vg_name,
634
                              size=float(pv_size), free=float(pv_free),
635
                              attributes=pv_attr)
636
      data.append(pvi)
635 637

  
636 638
    return data
637 639

  
b/lib/cmdlib.py
2424 2424
                                            constants.MIN_VG_SIZE)
2425 2425
      _ErrorIf(vgstatus, constants.CV_ENODELVM, node, vgstatus)
2426 2426

  
2427
    # check pv names
2428
    pvlist = nresult.get(constants.NV_PVLIST, None)
2429
    test = pvlist is None
2427
    # check pv names (and possibly sizes)
2428
    pvlist_dict = nresult.get(constants.NV_PVLIST, None)
2429
    test = pvlist_dict is None
2430 2430
    _ErrorIf(test, constants.CV_ENODELVM, node, "Can't get PV list from node")
2431 2431
    if not test:
2432
      pvlist = map(objects.LvmPvInfo.FromDict, pvlist_dict)
2432 2433
      # check that ':' is not present in PV names, since it's a
2433 2434
      # special character for lvcreate (denotes the range of PEs to
2434 2435
      # use on the PV)
2435
      for _, pvname, owner_vg in pvlist:
2436
        test = ":" in pvname
2436
      for pv in pvlist:
2437
        test = ":" in pv.name
2437 2438
        _ErrorIf(test, constants.CV_ENODELVM, node,
2438 2439
                 "Invalid character ':' in PV '%s' of VG '%s'",
2439
                 pvname, owner_vg)
2440
                 pv.name, pv.vg_name)
2440 2441

  
2441 2442
  def _VerifyNodeBridges(self, ninfo, nresult, bridges):
2442 2443
    """Check the node bridges.
b/lib/objects.py
2059 2059
    cfp = cls()
2060 2060
    cfp.readfp(buf)
2061 2061
    return cfp
2062

  
2063

  
2064
class LvmPvInfo(ConfigObject):
2065
  """Information about an LVM physical volume (PV).
2066

  
2067
  @type name: string
2068
  @ivar name: name of the PV
2069
  @type vg_name: string
2070
  @ivar vg_name: name of the volume group containing the PV
2071
  @type size: float
2072
  @ivar size: size of the PV in MiB
2073
  @type free: float
2074
  @ivar free: free space in the PV, in MiB
2075
  @type attributes: string
2076
  @ivar attributes: PV attributes
2077
  """
2078
  __slots__ = [
2079
    "name",
2080
    "vg_name",
2081
    "size",
2082
    "free",
2083
    "attributes",
2084
    ]
2085

  
2086
  def IsEmpty(self):
2087
    """Is this PV empty?
2088

  
2089
    """
2090
    return self.size <= (self.free + 1)
2091

  
2092
  def IsAllocatable(self):
2093
    """Is this PV allocatable?
2094

  
2095
    """
2096
    return ("a" in self.attributes)
b/lib/utils/__init__.py
48 48
from ganeti.utils.hash import *
49 49
from ganeti.utils.io import *
50 50
from ganeti.utils.log import *
51
from ganeti.utils.lvm import *
51 52
from ganeti.utils.mlock import *
52 53
from ganeti.utils.nodesetup import *
53 54
from ganeti.utils.process import *
......
488 489
  return True
489 490

  
490 491

  
491
def CheckVolumeGroupSize(vglist, vgname, minsize):
492
  """Checks if the volume group list is valid.
493

  
494
  The function will check if a given volume group is in the list of
495
  volume groups and has a minimum size.
496

  
497
  @type vglist: dict
498
  @param vglist: dictionary of volume group names and their size
499
  @type vgname: str
500
  @param vgname: the volume group we should check
501
  @type minsize: int
502
  @param minsize: the minimum size we accept
503
  @rtype: None or str
504
  @return: None for success, otherwise the error message
505

  
506
  """
507
  vgsize = vglist.get(vgname, None)
508
  if vgsize is None:
509
    return "volume group '%s' missing" % vgname
510
  elif vgsize < minsize:
511
    return ("volume group '%s' too small (%s MiB required, %d MiB found)" %
512
            (vgname, minsize, vgsize))
513
  return None
514

  
515

  
516 492
def SplitTime(value):
517 493
  """Splits time as floating point number into a tuple.
518 494

  
b/lib/utils/lvm.py
1
#
2
#
3

  
4
# Copyright (C) 2006, 2007, 2010, 2011, 2012 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21
"""Utility functions for LVM.
22

  
23
"""
24

  
25
def CheckVolumeGroupSize(vglist, vgname, minsize):
26
  """Checks if the volume group list is valid.
27

  
28
  The function will check if a given volume group is in the list of
29
  volume groups and has a minimum size.
30

  
31
  @type vglist: dict
32
  @param vglist: dictionary of volume group names and their size
33
  @type vgname: str
34
  @param vgname: the volume group we should check
35
  @type minsize: int
36
  @param minsize: the minimum size we accept
37
  @rtype: None or str
38
  @return: None for success, otherwise the error message
39

  
40
  """
41
  vgsize = vglist.get(vgname, None)
42
  if vgsize is None:
43
    return "volume group '%s' missing" % vgname
44
  elif vgsize < minsize:
45
    return ("volume group '%s' too small (%s MiB required, %d MiB found)" %
46
            (vgname, minsize, vgsize))
47
  return None

Also available in: Unified diff