666 |
666 |
return data
|
667 |
667 |
|
668 |
668 |
@classmethod
|
669 |
|
def GetPVInfo(cls, vg_names, filter_allocatable=True):
|
|
669 |
def GetPVInfo(cls, vg_names, filter_allocatable=True, include_lvs=False):
|
670 |
670 |
"""Get the free space info for PVs in a volume group.
|
671 |
671 |
|
672 |
672 |
@param vg_names: list of volume group names, if empty all will be returned
|
673 |
673 |
@param filter_allocatable: whether to skip over unallocatable PVs
|
|
674 |
@param include_lvs: whether to include a list of LVs hosted on each PV
|
674 |
675 |
|
675 |
676 |
@rtype: list
|
676 |
677 |
@return: list of objects.LvmPvInfo objects
|
677 |
678 |
|
678 |
679 |
"""
|
|
680 |
# We request "lv_name" field only if we care about LVs, so we don't get
|
|
681 |
# a long list of entries with many duplicates unless we really have to.
|
|
682 |
# The duplicate "pv_name" field will be ignored.
|
|
683 |
if include_lvs:
|
|
684 |
lvfield = "lv_name"
|
|
685 |
else:
|
|
686 |
lvfield = "pv_name"
|
679 |
687 |
try:
|
680 |
688 |
info = cls._GetVolumeInfo("pvs", ["pv_name", "vg_name", "pv_free",
|
681 |
|
"pv_attr", "pv_size"])
|
|
689 |
"pv_attr", "pv_size", lvfield])
|
682 |
690 |
except errors.GenericError, err:
|
683 |
691 |
logging.error("Can't get PV information: %s", err)
|
684 |
692 |
return None
|
685 |
693 |
|
|
694 |
# When asked for LVs, "pvs" may return multiple entries for the same PV-LV
|
|
695 |
# pair. We sort entries by PV name and then LV name, so it's easy to weed
|
|
696 |
# out duplicates.
|
|
697 |
if include_lvs:
|
|
698 |
info.sort(key=(lambda i: (i[0], i[5])))
|
686 |
699 |
data = []
|
687 |
|
for (pv_name, vg_name, pv_free, pv_attr, pv_size) in info:
|
|
700 |
lastpvi = None
|
|
701 |
for (pv_name, vg_name, pv_free, pv_attr, pv_size, lv_name) in info:
|
688 |
702 |
# (possibly) skip over pvs which are not allocatable
|
689 |
703 |
if filter_allocatable and pv_attr[0] != "a":
|
690 |
704 |
continue
|
691 |
705 |
# (possibly) skip over pvs which are not in the right volume group(s)
|
692 |
706 |
if vg_names and vg_name not in vg_names:
|
693 |
707 |
continue
|
694 |
|
pvi = objects.LvmPvInfo(name=pv_name, vg_name=vg_name,
|
695 |
|
size=float(pv_size), free=float(pv_free),
|
696 |
|
attributes=pv_attr)
|
697 |
|
data.append(pvi)
|
|
708 |
# Beware of duplicates (check before inserting)
|
|
709 |
if lastpvi and lastpvi.name == pv_name:
|
|
710 |
if include_lvs and lv_name:
|
|
711 |
if not lastpvi.lv_list or lastpvi.lv_list[-1] != lv_name:
|
|
712 |
lastpvi.lv_list.append(lv_name)
|
|
713 |
else:
|
|
714 |
if include_lvs and lv_name:
|
|
715 |
lvl = [lv_name]
|
|
716 |
else:
|
|
717 |
lvl = []
|
|
718 |
lastpvi = objects.LvmPvInfo(name=pv_name, vg_name=vg_name,
|
|
719 |
size=float(pv_size), free=float(pv_free),
|
|
720 |
attributes=pv_attr, lv_list=lvl)
|
|
721 |
data.append(lastpvi)
|
698 |
722 |
|
699 |
723 |
return data
|
700 |
724 |
|