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