Revision 06fb92cf
b/lib/cmdlib/node.py | ||
---|---|---|
1173 | 1173 |
es_flags = rpc.GetExclusiveStorageForNodeNames(lu.cfg, toquery_nodes) |
1174 | 1174 |
# FIXME: This currently maps everything to lvm, this should be more |
1175 | 1175 |
# flexible |
1176 |
storage_units = [(constants.ST_LVM_VG, lu.cfg.GetVGName())]
|
|
1177 |
node_data = lu.rpc.call_node_info(toquery_nodes, storage_units,
|
|
1176 |
vg_req = rpc.BuildVgInfoQuery(lu.cfg)
|
|
1177 |
node_data = lu.rpc.call_node_info(toquery_nodes, vg_req,
|
|
1178 | 1178 |
[lu.cfg.GetHypervisorType()], es_flags) |
1179 | 1179 |
live_data = dict((name, rpc.MakeLegacyNodeInfo(nresult.payload)) |
1180 | 1180 |
for (name, nresult) in node_data.items() |
b/lib/masterd/iallocator.py | ||
---|---|---|
431 | 431 |
node_whitelist = None |
432 | 432 |
|
433 | 433 |
es_flags = rpc.GetExclusiveStorageForNodeNames(cfg, node_list) |
434 |
vg_name = cfg.GetVGName() |
|
435 |
if vg_name is not None: |
|
436 |
has_lvm = True |
|
437 |
vg_req = [(constants.ST_LVM_VG, vg_name)] |
|
438 |
else: |
|
439 |
has_lvm = False |
|
440 |
vg_req = [] |
|
434 |
vg_req = rpc.BuildVgInfoQuery(cfg) |
|
435 |
has_lvm = bool(vg_req) |
|
441 | 436 |
node_data = self.rpc.call_node_info(node_list, vg_req, |
442 | 437 |
[hypervisor_name], es_flags) |
443 | 438 |
node_iinfo = \ |
... | ... | |
554 | 549 |
if has_lvm: |
555 | 550 |
total_disk = get_attr("vg_size") |
556 | 551 |
free_disk = get_attr("vg_free") |
552 |
total_spindles = get_attr("spindles_total") |
|
553 |
free_spindles = get_attr("spindles_free") |
|
557 | 554 |
else: |
558 | 555 |
# we didn't even ask the node for VG status, so use zeros |
559 | 556 |
total_disk = free_disk = 0 |
557 |
total_spindles = free_spindles = 0 |
|
560 | 558 |
|
561 | 559 |
# compute memory used by instances |
562 | 560 |
pnr_dyn = { |
... | ... | |
565 | 563 |
"free_memory": mem_free, |
566 | 564 |
"total_disk": total_disk, |
567 | 565 |
"free_disk": free_disk, |
566 |
"total_spindles": total_spindles, |
|
567 |
"free_spindles": free_spindles, |
|
568 | 568 |
"total_cpus": get_attr("cpu_total"), |
569 | 569 |
"i_pri_memory": i_p_mem, |
570 | 570 |
"i_pri_up_memory": i_p_up_mem, |
b/lib/query.py | ||
---|---|---|
1160 | 1160 |
"dtotal": ("DTotal", QFT_UNIT, "vg_size", |
1161 | 1161 |
"Total disk space in volume group used for instance disk" |
1162 | 1162 |
" allocation"), |
1163 |
"spfree": ("SpFree", QFT_NUMBER, "spindles_free", |
|
1164 |
"Available spindles in volume group (exclusive storage only)"), |
|
1165 |
"sptotal": ("SpTotal", QFT_NUMBER, "spindles_total", |
|
1166 |
"Total spindles in volume group (exclusive storage only)"), |
|
1163 | 1167 |
"mfree": ("MFree", QFT_UNIT, "memory_free", |
1164 | 1168 |
"Memory available for instance allocations"), |
1165 | 1169 |
"mnode": ("MNode", QFT_UNIT, "memory_dom0", |
b/lib/rapi/rlib2.py | ||
---|---|---|
81 | 81 |
] + _COMMON_FIELDS |
82 | 82 |
|
83 | 83 |
N_FIELDS = ["name", "offline", "master_candidate", "drained", |
84 |
"dtotal", "dfree", |
|
84 |
"dtotal", "dfree", "sptotal", "spfree",
|
|
85 | 85 |
"mtotal", "mnode", "mfree", |
86 | 86 |
"pinst_cnt", "sinst_cnt", |
87 | 87 |
"ctotal", "cnodes", "csockets", |
b/lib/rpc.py | ||
---|---|---|
584 | 584 |
return [(d.ToDict(), uid) for d, uid in value] |
585 | 585 |
|
586 | 586 |
|
587 |
def BuildVgInfoQuery(cfg): |
|
588 |
"""Build a query about the default VG for C{node_info}. |
|
589 |
|
|
590 |
The result of the RPC can be parsed with L{MakeLegacyNodeInfo}. |
|
591 |
|
|
592 |
@type cfg: L{config.ConfigWriter} |
|
593 |
@param cfg: Cluster configuration |
|
594 |
@rtype: list |
|
595 |
@return: argument suitable for L{rpc.RpcRunner.call_node_info} |
|
596 |
|
|
597 |
""" |
|
598 |
vg_name = cfg.GetVGName() |
|
599 |
if vg_name: |
|
600 |
ret = [ |
|
601 |
(constants.ST_LVM_VG, vg_name), |
|
602 |
(constants.ST_LVM_PV, vg_name), |
|
603 |
] |
|
604 |
else: |
|
605 |
ret = [] |
|
606 |
return ret |
|
607 |
|
|
608 |
|
|
587 | 609 |
def MakeLegacyNodeInfo(data, require_vg_info=True): |
588 | 610 |
"""Formats the data returned by L{rpc.RpcRunner.call_node_info}. |
589 | 611 |
|
... | ... | |
599 | 621 |
ret = utils.JoinDisjointDicts(hv_info, {"bootid": bootid}) |
600 | 622 |
|
601 | 623 |
if require_vg_info or vgs_info: |
602 |
(vg0_info, ) = vgs_info |
|
624 |
(vg0_info, vg0_spindles) = vgs_info
|
|
603 | 625 |
ret = utils.JoinDisjointDicts(vg0_info, ret) |
626 |
ret["spindles_free"] = vg0_spindles["vg_free"] |
|
627 |
ret["spindles_total"] = vg0_spindles["vg_size"] |
|
604 | 628 |
|
605 | 629 |
return ret |
606 | 630 |
|
b/qa/qa_rapi.py | ||
---|---|---|
110 | 110 |
"beparams", "hvparams", |
111 | 111 |
"oper_state", "oper_ram", "oper_vcpus", "status", "tags") |
112 | 112 |
|
113 |
NODE_FIELDS = ("name", "dtotal", "dfree", |
|
113 |
NODE_FIELDS = ("name", "dtotal", "dfree", "sptotal", "spfree",
|
|
114 | 114 |
"mtotal", "mnode", "mfree", |
115 | 115 |
"pinst_cnt", "sinst_cnt", "tags") |
116 | 116 |
|
b/src/Ganeti/JSON.hs | ||
---|---|---|
5 | 5 |
|
6 | 6 |
{- |
7 | 7 |
|
8 |
Copyright (C) 2009, 2010, 2011, 2012 Google Inc. |
|
8 |
Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
|
|
9 | 9 |
|
10 | 10 |
This program is free software; you can redistribute it and/or modify |
11 | 11 |
it under the terms of the GNU General Public License as published by |
... | ... | |
36 | 36 |
, fromJVal |
37 | 37 |
, jsonHead |
38 | 38 |
, getMaybeJsonHead |
39 |
, getMaybeJsonElem |
|
39 | 40 |
, asJSObject |
40 | 41 |
, asObjectList |
41 | 42 |
, tryFromObj |
... | ... | |
186 | 187 |
getMaybeJsonHead [] _ = J.JSNull |
187 | 188 |
getMaybeJsonHead (x:_) f = maybe J.JSNull J.showJSON (f x) |
188 | 189 |
|
190 |
-- | Helper for extracting Maybe values from a list that might be too short. |
|
191 |
getMaybeJsonElem :: (J.JSON b) => [a] -> Int -> (a -> Maybe b) -> J.JSValue |
|
192 |
getMaybeJsonElem [] _ _ = J.JSNull |
|
193 |
getMaybeJsonElem xs 0 f = getMaybeJsonHead xs f |
|
194 |
getMaybeJsonElem (_:xs) n f |
|
195 |
| n < 0 = J.JSNull |
|
196 |
| otherwise = getMaybeJsonElem xs (n - 1) f |
|
197 |
|
|
189 | 198 |
-- | Converts a JSON value into a JSON object. |
190 | 199 |
asJSObject :: (Monad m) => J.JSValue -> m (J.JSObject J.JSValue) |
191 | 200 |
asJSObject (J.JSObject a) = return a |
b/src/Ganeti/Query/Node.hs | ||
---|---|---|
64 | 64 |
"Available disk space in volume group") |
65 | 65 |
, ("dtotal", "DTotal", QFTUnit, "vg_size", |
66 | 66 |
"Total disk space in volume group used for instance disk allocation") |
67 |
, ("spfree", "SpFree", QFTNumber, "spindles_free", |
|
68 |
"Available spindles in volume group (exclusive storage only)") |
|
69 |
, ("sptotal", "SpTotal", QFTNumber, "spindles_total", |
|
70 |
"Total spindles in volume group (exclusive storage only)") |
|
67 | 71 |
, ("mfree", "MFree", QFTUnit, "memory_free", |
68 | 72 |
"Memory available for instance allocations") |
69 | 73 |
, ("mnode", "MNode", QFTUnit, "memory_dom0", |
... | ... | |
87 | 91 |
getMaybeJsonHead (rpcResNodeInfoVgInfo res) vgInfoVgFree |
88 | 92 |
nodeLiveFieldExtract "dtotal" res = |
89 | 93 |
getMaybeJsonHead (rpcResNodeInfoVgInfo res) vgInfoVgSize |
94 |
nodeLiveFieldExtract "spfree" res = |
|
95 |
getMaybeJsonElem (rpcResNodeInfoVgInfo res) 1 vgInfoVgFree |
|
96 |
nodeLiveFieldExtract "sptotal" res = |
|
97 |
getMaybeJsonElem (rpcResNodeInfoVgInfo res) 1 vgInfoVgSize |
|
90 | 98 |
nodeLiveFieldExtract "mfree" res = |
91 | 99 |
jsonHead (rpcResNodeInfoHvInfo res) hvInfoMemoryFree |
92 | 100 |
nodeLiveFieldExtract "mnode" res = |
... | ... | |
226 | 234 |
collectLiveData True cfg nodes = do |
227 | 235 |
let vgs = maybeToList . clusterVolumeGroupName $ configCluster cfg |
228 | 236 |
-- FIXME: This currently sets every storage unit to LVM |
229 |
storage_units = zip (repeat T.StorageLvmVg) vgs |
|
237 |
storage_units = zip (repeat T.StorageLvmVg) vgs ++ |
|
238 |
zip (repeat T.StorageLvmPv) vgs |
|
230 | 239 |
hvs = [getDefaultHypervisor cfg] |
231 | 240 |
step n (bn, gn, em) = |
232 | 241 |
let ndp' = getNodeNdParams cfg n |
b/test/py/ganeti.query_unittest.py | ||
---|---|---|
436 | 436 |
"mtotal": 4096, |
437 | 437 |
"dfree": 5 * 1024 * 1024, |
438 | 438 |
"dtotal": 100 * 1024 * 1024, |
439 |
"spfree": 0, |
|
440 |
"sptotal": 0, |
|
439 | 441 |
} |
440 | 442 |
|
441 | 443 |
assert (sorted(query._NODE_LIVE_FIELDS.keys()) == |
b/test/py/ganeti.rpc_unittest.py | ||
---|---|---|
891 | 891 |
|
892 | 892 |
class TestLegacyNodeInfo(unittest.TestCase): |
893 | 893 |
KEY_BOOT = "bootid" |
894 |
KEY_VG = "disk_free" |
|
894 |
KEY_VG0 = "name" |
|
895 |
KEY_VG1 = "vg_free" |
|
896 |
KEY_VG2 = "vg_size" |
|
895 | 897 |
KEY_HV = "cpu_count" |
898 |
KEY_SP1 = "spindles_free" |
|
899 |
KEY_SP2 = "spindles_total" |
|
896 | 900 |
VAL_BOOT = 0 |
897 |
VAL_VG = 1 |
|
901 |
VAL_VG0 = "xy" |
|
902 |
VAL_VG1 = 11 |
|
903 |
VAL_VG2 = 12 |
|
898 | 904 |
VAL_HV = 2 |
899 |
DICT_VG = {KEY_VG: VAL_VG} |
|
905 |
VAL_SP0 = "ab" |
|
906 |
VAL_SP1 = 31 |
|
907 |
VAL_SP2 = 32 |
|
908 |
DICT_VG = { |
|
909 |
KEY_VG0: VAL_VG0, |
|
910 |
KEY_VG1: VAL_VG1, |
|
911 |
KEY_VG2: VAL_VG2, |
|
912 |
} |
|
900 | 913 |
DICT_HV = {KEY_HV: VAL_HV} |
901 |
STD_LST = [VAL_BOOT, [DICT_VG], [DICT_HV]] |
|
914 |
DICT_SP = { |
|
915 |
KEY_VG0: VAL_SP0, |
|
916 |
KEY_VG1: VAL_SP1, |
|
917 |
KEY_VG2: VAL_SP2, |
|
918 |
} |
|
919 |
STD_LST = [VAL_BOOT, [DICT_VG, DICT_SP], [DICT_HV]] |
|
902 | 920 |
STD_DICT = { |
903 | 921 |
KEY_BOOT: VAL_BOOT, |
904 |
KEY_VG: VAL_VG, |
|
905 |
KEY_HV: VAL_HV |
|
922 |
KEY_VG0: VAL_VG0, |
|
923 |
KEY_VG1: VAL_VG1, |
|
924 |
KEY_VG2: VAL_VG2, |
|
925 |
KEY_HV: VAL_HV, |
|
926 |
KEY_SP1: VAL_SP1, |
|
927 |
KEY_SP2: VAL_SP2, |
|
906 | 928 |
} |
907 | 929 |
|
908 | 930 |
def testStandard(self): |
Also available in: Unified diff