Revision 6c00b2c7
b/lib/cmdlib/node.py | ||
---|---|---|
1205 | 1205 |
# filter out non-vm_capable nodes |
1206 | 1206 |
toquery_node_uuids = [node.uuid for node in all_info.values() |
1207 | 1207 |
if node.vm_capable and node.uuid in node_uuids] |
1208 |
lvm_enabled = utils.storage.IsLvmEnabled( |
|
1209 |
lu.cfg.GetClusterInfo().enabled_disk_templates) |
|
1210 |
# FIXME: this per default asks for storage space information for all |
|
1211 |
# enabled disk templates. Fix this by making it possible to specify |
|
1212 |
# space report fields for specific disk templates. |
|
1213 |
raw_storage_units = utils.storage.GetStorageUnitsOfCluster( |
|
1214 |
lu.cfg, include_spindles=lvm_enabled) |
|
1208 |
default_template = lu.cfg.GetClusterInfo().enabled_disk_templates[0] |
|
1209 |
raw_storage_units = utils.storage.GetStorageUnits( |
|
1210 |
lu.cfg, [default_template]) |
|
1215 | 1211 |
storage_units = rpc.PrepareStorageUnitsForNodes( |
1216 | 1212 |
lu.cfg, raw_storage_units, toquery_node_uuids) |
1217 | 1213 |
default_hypervisor = lu.cfg.GetHypervisorType() |
... | ... | |
1220 | 1216 |
node_data = lu.rpc.call_node_info(toquery_node_uuids, storage_units, |
1221 | 1217 |
hvspecs) |
1222 | 1218 |
live_data = dict( |
1223 |
(uuid, rpc.MakeLegacyNodeInfo(nresult.payload, |
|
1224 |
require_spindles=lvm_enabled)) |
|
1219 |
(uuid, rpc.MakeLegacyNodeInfo(nresult.payload, default_template)) |
|
1225 | 1220 |
for (uuid, nresult) in node_data.items() |
1226 | 1221 |
if not nresult.fail_msg and nresult.payload) |
1227 | 1222 |
else: |
b/lib/masterd/iallocator.py | ||
---|---|---|
415 | 415 |
@return: the result of the node info RPC call |
416 | 416 |
|
417 | 417 |
""" |
418 |
if disk_templates: |
|
419 |
storage_units_raw = utils.storage.GetStorageUnits(self.cfg, |
|
420 |
disk_templates) |
|
421 |
else: |
|
422 |
# FIXME: eliminate this case |
|
423 |
storage_units_raw = utils.storage.GetStorageUnitsOfCluster( |
|
424 |
self.cfg, include_spindles=True) |
|
418 |
storage_units_raw = utils.storage.GetStorageUnits(self.cfg, disk_templates) |
|
425 | 419 |
storage_units = rpc.PrepareStorageUnitsForNodes(self.cfg, storage_units_raw, |
426 | 420 |
node_list) |
427 | 421 |
hvspecs = [(hypervisor_name, cluster_info.hvparams[hypervisor_name])] |
... | ... | |
587 | 581 |
total_disk = template_space_info["storage_size"] |
588 | 582 |
free_disk = template_space_info["storage_free"] |
589 | 583 |
|
584 |
total_spindles = 0 |
|
585 |
free_spindles = 0 |
|
590 | 586 |
if disk_template in constants.DTS_LVM: |
591 | 587 |
lvm_pv_info = utils.storage.LookupSpaceInfoByStorageType( |
592 | 588 |
space_info, constants.ST_LVM_PV) |
593 |
if not lvm_pv_info: |
|
594 |
raise errors.OpExecError("Node '%s' didn't return LVM pv space info." |
|
595 |
% (node_name)) |
|
596 |
total_spindles = lvm_pv_info["storage_size"] |
|
597 |
free_spindles = lvm_pv_info["storage_free"] |
|
598 |
else: |
|
599 |
total_spindles = 0 |
|
600 |
free_spindles = 0 |
|
589 |
if lvm_pv_info: |
|
590 |
total_spindles = lvm_pv_info["storage_size"] |
|
591 |
free_spindles = lvm_pv_info["storage_free"] |
|
601 | 592 |
return (total_disk, free_disk, total_spindles, free_spindles) |
602 | 593 |
|
603 | 594 |
@staticmethod |
b/lib/rpc.py | ||
---|---|---|
586 | 586 |
result["spindles_free"] = lvm_pv_info["storage_free"] |
587 | 587 |
result["spindles_total"] = lvm_pv_info["storage_size"] |
588 | 588 |
else: |
589 |
raise errors.OpExecError("No spindle storage information available.") |
|
589 |
result["spindles_free"] = 0 |
|
590 |
result["spindles_total"] = 0 |
|
590 | 591 |
|
591 | 592 |
|
592 |
def _AddDefaultStorageInfoToLegacyNodeInfo(result, space_info): |
|
593 |
"""Extracts the storage space information of the default storage type from |
|
593 |
def _AddStorageInfoToLegacyNodeInfoByTemplate( |
|
594 |
result, space_info, disk_template): |
|
595 |
"""Extracts the storage space information of the disk template from |
|
594 | 596 |
the space info and adds it to the result dictionary. |
595 | 597 |
|
596 | 598 |
@see: C{_AddSpindlesToLegacyNodeInfo} for parameter information. |
597 | 599 |
|
598 | 600 |
""" |
599 |
# Check if there is at least one row for non-spindle storage info. |
|
600 |
no_defaults = (len(space_info) < 1) or \ |
|
601 |
(space_info[0]["type"] == constants.ST_LVM_PV and len(space_info) == 1) |
|
602 |
|
|
603 |
default_space_info = None |
|
604 |
if no_defaults: |
|
605 |
logging.warning("No storage info provided for default storage type.") |
|
601 |
if utils.storage.DiskTemplateSupportsSpaceReporting(disk_template): |
|
602 |
disk_info = utils.storage.LookupSpaceInfoByDiskTemplate( |
|
603 |
space_info, disk_template) |
|
604 |
result["name"] = disk_info["name"] |
|
605 |
result["storage_free"] = disk_info["storage_free"] |
|
606 |
result["storage_size"] = disk_info["storage_size"] |
|
606 | 607 |
else: |
607 |
default_space_info = space_info[0] |
|
608 |
|
|
609 |
if default_space_info: |
|
610 |
result["name"] = default_space_info["name"] |
|
611 |
result["storage_free"] = default_space_info["storage_free"] |
|
612 |
result["storage_size"] = default_space_info["storage_size"] |
|
608 |
# FIXME: consider displaying '-' in this case |
|
609 |
result["storage_free"] = 0 |
|
610 |
result["storage_size"] = 0 |
|
613 | 611 |
|
614 | 612 |
|
615 |
def MakeLegacyNodeInfo(data, require_spindles=False):
|
|
613 |
def MakeLegacyNodeInfo(data, disk_template):
|
|
616 | 614 |
"""Formats the data returned by L{rpc.RpcRunner.call_node_info}. |
617 | 615 |
|
618 | 616 |
Converts the data into a single dictionary. This is fine for most use cases, |
619 | 617 |
but some require information from more than one volume group or hypervisor. |
620 | 618 |
|
621 |
@param require_spindles: add spindle storage information to the legacy node |
|
622 |
info |
|
623 |
|
|
624 | 619 |
""" |
625 | 620 |
(bootid, space_info, (hv_info, )) = data |
626 | 621 |
|
627 | 622 |
ret = utils.JoinDisjointDicts(hv_info, {"bootid": bootid}) |
628 | 623 |
|
629 |
if require_spindles: |
|
630 |
_AddSpindlesToLegacyNodeInfo(ret, space_info) |
|
631 |
_AddDefaultStorageInfoToLegacyNodeInfo(ret, space_info) |
|
624 |
_AddSpindlesToLegacyNodeInfo(ret, space_info) |
|
625 |
_AddStorageInfoToLegacyNodeInfoByTemplate(ret, space_info, disk_template) |
|
632 | 626 |
|
633 | 627 |
return ret |
634 | 628 |
|
b/lib/utils/storage.py | ||
---|---|---|
95 | 95 |
return (storage_type, None) |
96 | 96 |
|
97 | 97 |
|
98 |
def _GetDefaultStorageUnitForSpindles(cfg): |
|
99 |
"""Creates a 'spindle' storage unit, by retrieving the volume group |
|
100 |
name and associating it to the lvm-pv storage type. |
|
101 |
|
|
102 |
@rtype: (string, string) |
|
103 |
@return: tuple (storage_type, storage_key), where storage type is |
|
104 |
'lvm-pv' and storage_key the name of the default volume group |
|
105 |
|
|
106 |
""" |
|
107 |
return (constants.ST_LVM_PV, cfg.GetVGName()) |
|
108 |
|
|
109 |
|
|
110 |
def GetStorageUnitsOfCluster(cfg, include_spindles=False): |
|
111 |
"""Examines the cluster's configuration and returns a list of storage |
|
112 |
units and their storage keys, ordered by the order in which they |
|
113 |
are enabled. |
|
114 |
|
|
115 |
@type cfg: L{config.ConfigWriter} |
|
116 |
@param cfg: Cluster configuration |
|
117 |
@type include_spindles: boolean |
|
118 |
@param include_spindles: flag to include an extra storage unit for physical |
|
119 |
volumes |
|
120 |
@rtype: list of tuples (string, string) |
|
121 |
@return: list of storage units, each storage unit being a tuple of |
|
122 |
(storage_type, storage_key); storage_type is in |
|
123 |
C{constants.STORAGE_TYPES} and the storage_key a string to |
|
124 |
identify an entity of that storage type, for example a volume group |
|
125 |
name for LVM storage or a file for file storage. |
|
126 |
|
|
127 |
""" |
|
128 |
cluster_config = cfg.GetClusterInfo() |
|
129 |
storage_units = [] |
|
130 |
for disk_template in cluster_config.enabled_disk_templates: |
|
131 |
if constants.MAP_DISK_TEMPLATE_STORAGE_TYPE[disk_template]\ |
|
132 |
in constants.STS_REPORT: |
|
133 |
storage_units.append( |
|
134 |
_GetDefaultStorageUnitForDiskTemplate(cfg, disk_template)) |
|
135 |
if include_spindles: |
|
136 |
included_storage_types = set([st for (st, _) in storage_units]) |
|
137 |
if not constants.ST_LVM_PV in included_storage_types: |
|
138 |
storage_units.append( |
|
139 |
_GetDefaultStorageUnitForSpindles(cfg)) |
|
140 |
|
|
141 |
return storage_units |
|
98 |
def DiskTemplateSupportsSpaceReporting(disk_template): |
|
99 |
"""Check whether the disk template supports storage space reporting.""" |
|
100 |
return (constants.MAP_DISK_TEMPLATE_STORAGE_TYPE[disk_template] |
|
101 |
in constants.STS_REPORT) |
|
142 | 102 |
|
143 | 103 |
|
144 | 104 |
def GetStorageUnits(cfg, disk_templates): |
... | ... | |
162 | 122 |
""" |
163 | 123 |
storage_units = [] |
164 | 124 |
for disk_template in disk_templates: |
165 |
if constants.MAP_DISK_TEMPLATE_STORAGE_TYPE[disk_template]\ |
|
166 |
in constants.STS_REPORT: |
|
125 |
if DiskTemplateSupportsSpaceReporting(disk_template): |
|
167 | 126 |
storage_units.append( |
168 | 127 |
_GetDefaultStorageUnitForDiskTemplate(cfg, disk_template)) |
169 |
if len(set(disk_templates) & constants.DTS_LVM) > 0: |
|
170 |
storage_units.append( |
|
171 |
_GetDefaultStorageUnitForSpindles(cfg)) |
|
172 |
|
|
173 | 128 |
return storage_units |
174 | 129 |
|
175 | 130 |
|
b/test/py/ganeti.rpc_unittest.py | ||
---|---|---|
943 | 943 |
KEY_NAME: VAL_VG_NAME, |
944 | 944 |
KEY_STORAGE_FREE: VAL_VG_FREE, |
945 | 945 |
KEY_STORAGE_TOTAL: VAL_VG_TOTAL, |
946 |
KEY_SPINDLES_FREE: VAL_PV_FREE, |
|
947 |
KEY_SPINDLES_TOTAL: VAL_PV_TOTAL, |
|
946 | 948 |
KEY_CPU_COUNT: VAL_CPU_COUNT, |
947 | 949 |
} |
948 | 950 |
|
949 |
def testStandard(self):
|
|
950 |
result = rpc.MakeLegacyNodeInfo(self.STD_LST) |
|
951 |
def testWithSpindles(self):
|
|
952 |
result = rpc.MakeLegacyNodeInfo(self.STD_LST, constants.DT_PLAIN)
|
|
951 | 953 |
self.assertEqual(result, self.STD_DICT) |
952 | 954 |
|
953 |
def testSpindlesRequired(self): |
|
954 |
my_lst = [self.VAL_BOOT, [], [self.DICT_HV]] |
|
955 |
self.assertRaises(errors.OpExecError, rpc.MakeLegacyNodeInfo, my_lst, |
|
956 |
require_spindles=True) |
|
957 |
|
|
958 |
def testNoSpindlesRequired(self): |
|
959 |
my_lst = [self.VAL_BOOT, [], [self.DICT_HV]] |
|
960 |
result = rpc.MakeLegacyNodeInfo(my_lst, require_spindles = False) |
|
961 |
self.assertEqual(result, {self.KEY_BOOT: self.VAL_BOOT, |
|
962 |
self.KEY_CPU_COUNT: self.VAL_CPU_COUNT}) |
|
963 |
result = rpc.MakeLegacyNodeInfo(self.STD_LST, require_spindles = False) |
|
964 |
self.assertEqual(result, self.STD_DICT) |
|
965 |
|
|
966 |
|
|
967 |
class TestAddDefaultStorageInfoToLegacyNodeInfo(unittest.TestCase): |
|
968 |
|
|
969 |
def setUp(self): |
|
970 |
self.free_storage_file = 23 |
|
971 |
self.total_storage_file = 42 |
|
972 |
self.free_storage_lvm = 69 |
|
973 |
self.total_storage_lvm = 666 |
|
974 |
self.node_info = [{"name": "myfile", |
|
975 |
"type": constants.ST_FILE, |
|
976 |
"storage_free": self.free_storage_file, |
|
977 |
"storage_size": self.total_storage_file}, |
|
978 |
{"name": "myvg", |
|
979 |
"type": constants.ST_LVM_VG, |
|
980 |
"storage_free": self.free_storage_lvm, |
|
981 |
"storage_size": self.total_storage_lvm}, |
|
982 |
{"name": "myspindle", |
|
983 |
"type": constants.ST_LVM_PV, |
|
984 |
"storage_free": 33, |
|
985 |
"storage_size": 44}] |
|
986 |
|
|
987 |
def testAddDefaultStorageInfoToLegacyNodeInfo(self): |
|
988 |
result = {} |
|
989 |
rpc._AddDefaultStorageInfoToLegacyNodeInfo(result, self.node_info) |
|
990 |
self.assertEqual(self.free_storage_file, result["storage_free"]) |
|
991 |
self.assertEqual(self.total_storage_file, result["storage_size"]) |
|
992 |
|
|
993 |
def testAddDefaultStorageInfoToLegacyNodeInfoNoDefaults(self): |
|
994 |
result = {} |
|
995 |
rpc._AddDefaultStorageInfoToLegacyNodeInfo(result, self.node_info[-1:]) |
|
996 |
self.assertFalse("storage_free" in result) |
|
997 |
self.assertFalse("storage_size" in result) |
|
955 |
def testNoSpindles(self): |
|
956 |
my_lst = [self.VAL_BOOT, [self.DICT_VG], [self.DICT_HV]] |
|
957 |
result = rpc.MakeLegacyNodeInfo(my_lst, constants.DT_PLAIN) |
|
958 |
expected_dict = dict((k,v) for k, v in self.STD_DICT.iteritems()) |
|
959 |
expected_dict[self.KEY_SPINDLES_FREE] = 0 |
|
960 |
expected_dict[self.KEY_SPINDLES_TOTAL] = 0 |
|
961 |
self.assertEqual(result, expected_dict) |
|
998 | 962 |
|
999 | 963 |
|
1000 | 964 |
if __name__ == "__main__": |
b/test/py/ganeti.utils.storage_unittest.py | ||
---|---|---|
26 | 26 |
import unittest |
27 | 27 |
|
28 | 28 |
from ganeti import constants |
29 |
from ganeti import objects |
|
30 | 29 |
from ganeti.utils import storage |
31 | 30 |
|
32 | 31 |
import testutils |
... | ... | |
72 | 71 |
self.assertEqual(storage_type, constants.ST_DISKLESS) |
73 | 72 |
self.assertEqual(storage_key, None) |
74 | 73 |
|
75 |
def testGetDefaultStorageUnitForSpindles(self): |
|
76 |
(storage_type, storage_key) = \ |
|
77 |
storage._GetDefaultStorageUnitForSpindles(self._cfg) |
|
78 |
self.assertEqual(storage_type, constants.ST_LVM_PV) |
|
79 |
self.assertEqual(storage_key, self._default_vg_name) |
|
80 |
|
|
81 |
|
|
82 |
class TestGetStorageUnitsOfCluster(unittest.TestCase): |
|
83 |
|
|
84 |
def setUp(self): |
|
85 |
storage._GetDefaultStorageUnitForDiskTemplate = \ |
|
86 |
mock.Mock(return_value=("foo", "bar")) |
|
87 |
|
|
88 |
self._cluster_cfg = objects.Cluster() |
|
89 |
self._enabled_disk_templates = \ |
|
90 |
[constants.DT_DRBD8, constants.DT_PLAIN, constants.DT_FILE, |
|
91 |
constants.DT_SHARED_FILE] |
|
92 |
self._cluster_cfg.enabled_disk_templates = \ |
|
93 |
self._enabled_disk_templates |
|
94 |
self._cfg = mock.Mock() |
|
95 |
self._cfg.GetClusterInfo = mock.Mock(return_value=self._cluster_cfg) |
|
96 |
self._cfg.GetVGName = mock.Mock(return_value="some_vg_name") |
|
97 |
|
|
98 |
def testGetStorageUnitsOfCluster(self): |
|
99 |
storage_units = storage.GetStorageUnitsOfCluster(self._cfg) |
|
100 |
self.assertEqual(len(storage_units), len(self._enabled_disk_templates)) |
|
101 |
|
|
102 |
def testGetStorageUnitsOfClusterWithSpindles(self): |
|
103 |
storage_units = storage.GetStorageUnitsOfCluster( |
|
104 |
self._cfg, include_spindles=True) |
|
105 |
self.assertEqual(len(storage_units), len(self._enabled_disk_templates) + 1) |
|
106 |
self.assertTrue(constants.ST_LVM_PV in [st for (st, sk) in storage_units]) |
|
107 |
|
|
108 | 74 |
|
109 | 75 |
class TestGetStorageUnits(unittest.TestCase): |
110 | 76 |
|
... | ... | |
121 | 87 |
def testGetStorageUnitsLvm(self): |
122 | 88 |
disk_templates = [constants.DT_PLAIN, constants.DT_DRBD8] |
123 | 89 |
storage_units = storage.GetStorageUnits(self._cfg, disk_templates) |
124 |
self.assertEqual(len(storage_units), len(disk_templates) + 1)
|
|
90 |
self.assertEqual(len(storage_units), len(disk_templates)) |
|
125 | 91 |
|
126 | 92 |
|
127 | 93 |
class TestLookupSpaceInfoByStorageType(unittest.TestCase): |
Also available in: Unified diff