Revision b954f097
b/Makefile.am | ||
---|---|---|
282 | 282 |
lib/client/gnt_job.py \ |
283 | 283 |
lib/client/gnt_node.py \ |
284 | 284 |
lib/client/gnt_network.py \ |
285 |
lib/client/gnt_os.py |
|
285 |
lib/client/gnt_os.py \ |
|
286 |
lib/client/gnt_storage.py |
|
286 | 287 |
|
287 | 288 |
hypervisor_PYTHON = \ |
288 | 289 |
lib/hypervisor/__init__.py \ |
... | ... | |
621 | 622 |
scripts/gnt-job \ |
622 | 623 |
scripts/gnt-network \ |
623 | 624 |
scripts/gnt-node \ |
624 |
scripts/gnt-os |
|
625 |
scripts/gnt-os \ |
|
626 |
scripts/gnt-storage |
|
625 | 627 |
|
626 | 628 |
PYTHON_BOOTSTRAP_SBIN = \ |
627 | 629 |
daemons/ganeti-masterd \ |
b/autotools/build-bash-completion | ||
---|---|---|
357 | 357 |
WriteCompReply(sw, "-W \"$(_ganeti_instances)\"", cur=cur) |
358 | 358 |
elif suggest == cli.OPT_COMPL_ONE_OS: |
359 | 359 |
WriteCompReply(sw, "-W \"$(_ganeti_os)\"", cur=cur) |
360 |
elif suggest == cli.OPT_COMPL_ONE_EXTSTORAGE: |
|
361 |
WriteCompReply(sw, "-W \"$(_ganeti_extstorage)\"", cur=cur) |
|
360 | 362 |
elif suggest == cli.OPT_COMPL_ONE_IALLOCATOR: |
361 | 363 |
WriteCompReply(sw, "-W \"$(_ganeti_iallocator)\"", cur=cur) |
362 | 364 |
elif suggest == cli.OPT_COMPL_ONE_NODEGROUP: |
... | ... | |
467 | 469 |
choices = "$(_ganeti_jobs)" |
468 | 470 |
elif isinstance(arg, cli.ArgOs): |
469 | 471 |
choices = "$(_ganeti_os)" |
472 |
elif isinstance(arg, cli.ArgExtStorage): |
|
473 |
choices = "$(_ganeti_extstorage)" |
|
470 | 474 |
elif isinstance(arg, cli.ArgFile): |
471 | 475 |
choices = "" |
472 | 476 |
compgenargs.append("-f") |
b/htest/Test/Ganeti/OpCodes.hs | ||
---|---|---|
291 | 291 |
genMaybe genNameNE <*> genMaybe genNamesNE |
292 | 292 |
"OP_OS_DIAGNOSE" -> |
293 | 293 |
OpCodes.OpOsDiagnose <$> genFieldsNE <*> genNamesNE |
294 |
"OP_EXT_STORAGE_DIAGNOSE" -> |
|
295 |
OpCodes.OpOsDiagnose <$> genFieldsNE <*> genNamesNE |
|
294 | 296 |
"OP_BACKUP_QUERY" -> |
295 | 297 |
OpCodes.OpBackupQuery <$> arbitrary <*> genNodeNamesNE |
296 | 298 |
"OP_BACKUP_PREPARE" -> |
b/htools/Ganeti/OpCodes.hs | ||
---|---|---|
444 | 444 |
, ("OpOsDiagnose", |
445 | 445 |
[ pOutputFields |
446 | 446 |
, pNames ]) |
447 |
, ("OpExtStorageDiagnose", |
|
448 |
[ pOutputFields |
|
449 |
, pNames ]) |
|
447 | 450 |
, ("OpBackupQuery", |
448 | 451 |
[ pUseLocking |
449 | 452 |
, pNodes |
b/lib/backend.py | ||
---|---|---|
2481 | 2481 |
return result |
2482 | 2482 |
|
2483 | 2483 |
|
2484 |
def DiagnoseExtStorage(top_dirs=None): |
|
2485 |
"""Compute the validity for all ExtStorage Providers. |
|
2486 |
|
|
2487 |
@type top_dirs: list |
|
2488 |
@param top_dirs: the list of directories in which to |
|
2489 |
search (if not given defaults to |
|
2490 |
L{pathutils.ES_SEARCH_PATH}) |
|
2491 |
@rtype: list of L{objects.ExtStorage} |
|
2492 |
@return: a list of tuples (name, path, status, diagnose, parameters) |
|
2493 |
for all (potential) ExtStorage Providers under all |
|
2494 |
search paths, where: |
|
2495 |
- name is the (potential) ExtStorage Provider |
|
2496 |
- path is the full path to the ExtStorage Provider |
|
2497 |
- status True/False is the validity of the ExtStorage Provider |
|
2498 |
- diagnose is the error message for an invalid ExtStorage Provider, |
|
2499 |
otherwise empty |
|
2500 |
- parameters is a list of (name, help) parameters, if any |
|
2501 |
|
|
2502 |
""" |
|
2503 |
if top_dirs is None: |
|
2504 |
top_dirs = pathutils.ES_SEARCH_PATH |
|
2505 |
|
|
2506 |
result = [] |
|
2507 |
for dir_name in top_dirs: |
|
2508 |
if os.path.isdir(dir_name): |
|
2509 |
try: |
|
2510 |
f_names = utils.ListVisibleFiles(dir_name) |
|
2511 |
except EnvironmentError, err: |
|
2512 |
logging.exception("Can't list the ExtStorage directory %s: %s", |
|
2513 |
dir_name, err) |
|
2514 |
break |
|
2515 |
for name in f_names: |
|
2516 |
es_path = utils.PathJoin(dir_name, name) |
|
2517 |
status, es_inst = bdev.ExtStorageFromDisk(name, base_dir=dir_name) |
|
2518 |
if status: |
|
2519 |
diagnose = "" |
|
2520 |
parameters = es_inst.supported_parameters |
|
2521 |
else: |
|
2522 |
diagnose = es_inst |
|
2523 |
parameters = [] |
|
2524 |
result.append((name, es_path, status, diagnose, parameters)) |
|
2525 |
|
|
2526 |
return result |
|
2527 |
|
|
2528 |
|
|
2484 | 2529 |
def BlockdevGrow(disk, amount, dryrun, backingstore): |
2485 | 2530 |
"""Grow a stack of block devices. |
2486 | 2531 |
|
b/lib/cli.py | ||
---|---|---|
262 | 262 |
"ArgNetwork", |
263 | 263 |
"ArgNode", |
264 | 264 |
"ArgOs", |
265 |
"ArgExtStorage", |
|
265 | 266 |
"ArgSuggest", |
266 | 267 |
"ArgUnknown", |
267 | 268 |
"OPT_COMPL_INST_ADD_NODES", |
... | ... | |
272 | 273 |
"OPT_COMPL_ONE_NODEGROUP", |
273 | 274 |
"OPT_COMPL_ONE_NETWORK", |
274 | 275 |
"OPT_COMPL_ONE_OS", |
276 |
"OPT_COMPL_ONE_EXTSTORAGE", |
|
275 | 277 |
"cli_option", |
276 | 278 |
"SplitNodeOption", |
277 | 279 |
"CalculateOSNames", |
... | ... | |
422 | 424 |
""" |
423 | 425 |
|
424 | 426 |
|
427 |
class ArgExtStorage(_Argument): |
|
428 |
"""ExtStorage argument. |
|
429 |
|
|
430 |
""" |
|
431 |
|
|
432 |
|
|
425 | 433 |
ARGS_NONE = [] |
426 | 434 |
ARGS_MANY_INSTANCES = [ArgInstance()] |
427 | 435 |
ARGS_MANY_NETWORKS = [ArgNetwork()] |
... | ... | |
672 | 680 |
OPT_COMPL_ONE_NODE, |
673 | 681 |
OPT_COMPL_ONE_INSTANCE, |
674 | 682 |
OPT_COMPL_ONE_OS, |
683 |
OPT_COMPL_ONE_EXTSTORAGE, |
|
675 | 684 |
OPT_COMPL_ONE_IALLOCATOR, |
676 | 685 |
OPT_COMPL_ONE_NETWORK, |
677 | 686 |
OPT_COMPL_INST_ADD_NODES, |
678 |
OPT_COMPL_ONE_NODEGROUP) = range(100, 108)
|
|
687 |
OPT_COMPL_ONE_NODEGROUP) = range(100, 109)
|
|
679 | 688 |
|
680 | 689 |
OPT_COMPL_ALL = compat.UniqueFrozenset([ |
681 | 690 |
OPT_COMPL_MANY_NODES, |
682 | 691 |
OPT_COMPL_ONE_NODE, |
683 | 692 |
OPT_COMPL_ONE_INSTANCE, |
684 | 693 |
OPT_COMPL_ONE_OS, |
694 |
OPT_COMPL_ONE_EXTSTORAGE, |
|
685 | 695 |
OPT_COMPL_ONE_IALLOCATOR, |
686 | 696 |
OPT_COMPL_ONE_NETWORK, |
687 | 697 |
OPT_COMPL_INST_ADD_NODES, |
b/lib/client/gnt_storage.py | ||
---|---|---|
1 |
# |
|
2 |
# |
|
3 |
|
|
4 |
# Copyright (C) 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 |
"""External Storage related commands""" |
|
22 |
|
|
23 |
# pylint: disable=W0401,W0613,W0614,C0103 |
|
24 |
# W0401: Wildcard import ganeti.cli |
|
25 |
# W0613: Unused argument, since all functions follow the same API |
|
26 |
# W0614: Unused import %s from wildcard import (since we need cli) |
|
27 |
# C0103: Invalid name gnt-storage |
|
28 |
|
|
29 |
from ganeti.cli import * |
|
30 |
from ganeti import opcodes |
|
31 |
from ganeti import utils |
|
32 |
|
|
33 |
|
|
34 |
def ShowExtStorageInfo(opts, args): |
|
35 |
"""List detailed information about ExtStorage providers. |
|
36 |
|
|
37 |
@param opts: the command line options selected by the user |
|
38 |
@type args: list |
|
39 |
@param args: empty list or list of ExtStorage providers' names |
|
40 |
@rtype: int |
|
41 |
@return: the desired exit code |
|
42 |
|
|
43 |
""" |
|
44 |
op = opcodes.OpExtStorageDiagnose(output_fields=["name", "nodegroup_status", |
|
45 |
"parameters"], |
|
46 |
names=[]) |
|
47 |
|
|
48 |
result = SubmitOpCode(op, opts=opts) |
|
49 |
|
|
50 |
if not result: |
|
51 |
ToStderr("Can't get the ExtStorage providers list") |
|
52 |
return 1 |
|
53 |
|
|
54 |
do_filter = bool(args) |
|
55 |
|
|
56 |
for (name, nodegroup_data, parameters) in result: |
|
57 |
if do_filter: |
|
58 |
if name not in args: |
|
59 |
continue |
|
60 |
else: |
|
61 |
args.remove(name) |
|
62 |
|
|
63 |
nodegroups_valid = [] |
|
64 |
for nodegroup_name, nodegroup_status in nodegroup_data.iteritems(): |
|
65 |
if nodegroup_status: |
|
66 |
nodegroups_valid.append(nodegroup_name) |
|
67 |
|
|
68 |
ToStdout("%s:", name) |
|
69 |
|
|
70 |
if nodegroups_valid != []: |
|
71 |
ToStdout(" - Valid for nodegroups:") |
|
72 |
for ndgrp in utils.NiceSort(nodegroups_valid): |
|
73 |
ToStdout(" %s", ndgrp) |
|
74 |
ToStdout(" - Supported parameters:") |
|
75 |
for pname, pdesc in parameters: |
|
76 |
ToStdout(" %s: %s", pname, pdesc) |
|
77 |
else: |
|
78 |
ToStdout(" - Invalid for all nodegroups") |
|
79 |
|
|
80 |
ToStdout("") |
|
81 |
|
|
82 |
if args: |
|
83 |
for name in args: |
|
84 |
ToStdout("%s: Not Found", name) |
|
85 |
ToStdout("") |
|
86 |
|
|
87 |
return 0 |
|
88 |
|
|
89 |
|
|
90 |
def _ExtStorageStatus(status, diagnose): |
|
91 |
"""Beautifier function for ExtStorage status. |
|
92 |
|
|
93 |
@type status: boolean |
|
94 |
@param status: is the ExtStorage provider valid |
|
95 |
@type diagnose: string |
|
96 |
@param diagnose: the error message for invalid ExtStorages |
|
97 |
@rtype: string |
|
98 |
@return: a formatted status |
|
99 |
|
|
100 |
""" |
|
101 |
if status: |
|
102 |
return "valid" |
|
103 |
else: |
|
104 |
return "invalid - %s" % diagnose |
|
105 |
|
|
106 |
|
|
107 |
def DiagnoseExtStorage(opts, args): |
|
108 |
"""Analyse all ExtStorage providers. |
|
109 |
|
|
110 |
@param opts: the command line options selected by the user |
|
111 |
@type args: list |
|
112 |
@param args: should be an empty list |
|
113 |
@rtype: int |
|
114 |
@return: the desired exit code |
|
115 |
|
|
116 |
""" |
|
117 |
op = opcodes.OpExtStorageDiagnose(output_fields=["name", "node_status", |
|
118 |
"nodegroup_status"], |
|
119 |
names=[]) |
|
120 |
|
|
121 |
result = SubmitOpCode(op, opts=opts) |
|
122 |
|
|
123 |
if not result: |
|
124 |
ToStderr("Can't get the list of ExtStorage providers") |
|
125 |
return 1 |
|
126 |
|
|
127 |
for provider_name, node_data, nodegroup_data in result: |
|
128 |
|
|
129 |
nodes_valid = {} |
|
130 |
nodes_bad = {} |
|
131 |
nodegroups_valid = {} |
|
132 |
nodegroups_bad = {} |
|
133 |
|
|
134 |
# Per node diagnose |
|
135 |
for node_name, node_info in node_data.iteritems(): |
|
136 |
if node_info: # at least one entry in the per-node list |
|
137 |
(fo_path, fo_status, fo_msg, fo_params) = node_info.pop(0) |
|
138 |
fo_msg = "%s (path: %s)" % (_ExtStorageStatus(fo_status, fo_msg), |
|
139 |
fo_path) |
|
140 |
if fo_params: |
|
141 |
fo_msg += (" [parameters: %s]" % |
|
142 |
utils.CommaJoin([v[0] for v in fo_params])) |
|
143 |
else: |
|
144 |
fo_msg += " [no parameters]" |
|
145 |
if fo_status: |
|
146 |
nodes_valid[node_name] = fo_msg |
|
147 |
else: |
|
148 |
nodes_bad[node_name] = fo_msg |
|
149 |
else: |
|
150 |
nodes_bad[node_name] = "ExtStorage provider not found" |
|
151 |
|
|
152 |
# Per nodegroup diagnose |
|
153 |
for nodegroup_name, nodegroup_status in nodegroup_data.iteritems(): |
|
154 |
status = nodegroup_status |
|
155 |
if status: |
|
156 |
nodegroups_valid[nodegroup_name] = "valid" |
|
157 |
else: |
|
158 |
nodegroups_bad[nodegroup_name] = "invalid" |
|
159 |
|
|
160 |
def _OutputPerNodegroupStatus(msg_map): |
|
161 |
map_k = utils.NiceSort(msg_map.keys()) |
|
162 |
for nodegroup in map_k: |
|
163 |
ToStdout(" For nodegroup: %s --> %s", nodegroup, |
|
164 |
msg_map[nodegroup]) |
|
165 |
|
|
166 |
def _OutputPerNodeStatus(msg_map): |
|
167 |
map_k = utils.NiceSort(msg_map.keys()) |
|
168 |
for node_name in map_k: |
|
169 |
ToStdout(" Node: %s, status: %s", node_name, msg_map[node_name]) |
|
170 |
|
|
171 |
# Print the output |
|
172 |
st_msg = "Provider: %s" % provider_name |
|
173 |
ToStdout(st_msg) |
|
174 |
ToStdout("---") |
|
175 |
_OutputPerNodeStatus(nodes_valid) |
|
176 |
_OutputPerNodeStatus(nodes_bad) |
|
177 |
ToStdout(" --") |
|
178 |
_OutputPerNodegroupStatus(nodegroups_valid) |
|
179 |
_OutputPerNodegroupStatus(nodegroups_bad) |
|
180 |
ToStdout("") |
|
181 |
|
|
182 |
return 0 |
|
183 |
|
|
184 |
|
|
185 |
commands = { |
|
186 |
"diagnose": ( |
|
187 |
DiagnoseExtStorage, ARGS_NONE, [PRIORITY_OPT], |
|
188 |
"", "Diagnose all ExtStorage providers"), |
|
189 |
"info": ( |
|
190 |
ShowExtStorageInfo, [ArgOs()], [PRIORITY_OPT], |
|
191 |
"", "Show info about ExtStorage providers"), |
|
192 |
} |
|
193 |
|
|
194 |
|
|
195 |
def Main(): |
|
196 |
return GenericMain(commands) |
b/lib/cmdlib.py | ||
---|---|---|
5163 | 5163 |
return self.oq.OldStyleQuery(self) |
5164 | 5164 |
|
5165 | 5165 |
|
5166 |
class _ExtStorageQuery(_QueryBase): |
|
5167 |
FIELDS = query.EXTSTORAGE_FIELDS |
|
5168 |
|
|
5169 |
def ExpandNames(self, lu): |
|
5170 |
# Lock all nodes in shared mode |
|
5171 |
# Temporary removal of locks, should be reverted later |
|
5172 |
# TODO: reintroduce locks when they are lighter-weight |
|
5173 |
lu.needed_locks = {} |
|
5174 |
#self.share_locks[locking.LEVEL_NODE] = 1 |
|
5175 |
#self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET |
|
5176 |
|
|
5177 |
# The following variables interact with _QueryBase._GetNames |
|
5178 |
if self.names: |
|
5179 |
self.wanted = self.names |
|
5180 |
else: |
|
5181 |
self.wanted = locking.ALL_SET |
|
5182 |
|
|
5183 |
self.do_locking = self.use_locking |
|
5184 |
|
|
5185 |
def DeclareLocks(self, lu, level): |
|
5186 |
pass |
|
5187 |
|
|
5188 |
@staticmethod |
|
5189 |
def _DiagnoseByProvider(rlist): |
|
5190 |
"""Remaps a per-node return list into an a per-provider per-node dictionary |
|
5191 |
|
|
5192 |
@param rlist: a map with node names as keys and ExtStorage objects as values |
|
5193 |
|
|
5194 |
@rtype: dict |
|
5195 |
@return: a dictionary with extstorage providers as keys and as |
|
5196 |
value another map, with nodes as keys and tuples of |
|
5197 |
(path, status, diagnose, parameters) as values, eg:: |
|
5198 |
|
|
5199 |
{"provider1": {"node1": [(/usr/lib/..., True, "", [])] |
|
5200 |
"node2": [(/srv/..., False, "missing file")] |
|
5201 |
"node3": [(/srv/..., True, "", [])] |
|
5202 |
} |
|
5203 |
|
|
5204 |
""" |
|
5205 |
all_es = {} |
|
5206 |
# we build here the list of nodes that didn't fail the RPC (at RPC |
|
5207 |
# level), so that nodes with a non-responding node daemon don't |
|
5208 |
# make all OSes invalid |
|
5209 |
good_nodes = [node_name for node_name in rlist |
|
5210 |
if not rlist[node_name].fail_msg] |
|
5211 |
for node_name, nr in rlist.items(): |
|
5212 |
if nr.fail_msg or not nr.payload: |
|
5213 |
continue |
|
5214 |
for (name, path, status, diagnose, params) in nr.payload: |
|
5215 |
if name not in all_es: |
|
5216 |
# build a list of nodes for this os containing empty lists |
|
5217 |
# for each node in node_list |
|
5218 |
all_es[name] = {} |
|
5219 |
for nname in good_nodes: |
|
5220 |
all_es[name][nname] = [] |
|
5221 |
# convert params from [name, help] to (name, help) |
|
5222 |
params = [tuple(v) for v in params] |
|
5223 |
all_es[name][node_name].append((path, status, diagnose, params)) |
|
5224 |
return all_es |
|
5225 |
|
|
5226 |
def _GetQueryData(self, lu): |
|
5227 |
"""Computes the list of nodes and their attributes. |
|
5228 |
|
|
5229 |
""" |
|
5230 |
# Locking is not used |
|
5231 |
assert not (compat.any(lu.glm.is_owned(level) |
|
5232 |
for level in locking.LEVELS |
|
5233 |
if level != locking.LEVEL_CLUSTER) or |
|
5234 |
self.do_locking or self.use_locking) |
|
5235 |
|
|
5236 |
valid_nodes = [node.name |
|
5237 |
for node in lu.cfg.GetAllNodesInfo().values() |
|
5238 |
if not node.offline and node.vm_capable] |
|
5239 |
pol = self._DiagnoseByProvider(lu.rpc.call_extstorage_diagnose(valid_nodes)) |
|
5240 |
|
|
5241 |
data = {} |
|
5242 |
|
|
5243 |
nodegroup_list = lu.cfg.GetNodeGroupList() |
|
5244 |
|
|
5245 |
for (es_name, es_data) in pol.items(): |
|
5246 |
# For every provider compute the nodegroup validity. |
|
5247 |
# To do this we need to check the validity of each node in es_data |
|
5248 |
# and then construct the corresponding nodegroup dict: |
|
5249 |
# { nodegroup1: status |
|
5250 |
# nodegroup2: status |
|
5251 |
# } |
|
5252 |
ndgrp_data = {} |
|
5253 |
for nodegroup in nodegroup_list: |
|
5254 |
ndgrp = lu.cfg.GetNodeGroup(nodegroup) |
|
5255 |
|
|
5256 |
nodegroup_nodes = ndgrp.members |
|
5257 |
nodegroup_name = ndgrp.name |
|
5258 |
node_statuses = [] |
|
5259 |
|
|
5260 |
for node in nodegroup_nodes: |
|
5261 |
if node in valid_nodes: |
|
5262 |
if es_data[node] != []: |
|
5263 |
node_status = es_data[node][0][1] |
|
5264 |
node_statuses.append(node_status) |
|
5265 |
else: |
|
5266 |
node_statuses.append(False) |
|
5267 |
|
|
5268 |
if False in node_statuses: |
|
5269 |
ndgrp_data[nodegroup_name] = False |
|
5270 |
else: |
|
5271 |
ndgrp_data[nodegroup_name] = True |
|
5272 |
|
|
5273 |
# Compute the provider's parameters |
|
5274 |
parameters = set() |
|
5275 |
for idx, esl in enumerate(es_data.values()): |
|
5276 |
valid = bool(esl and esl[0][1]) |
|
5277 |
if not valid: |
|
5278 |
break |
|
5279 |
|
|
5280 |
node_params = esl[0][3] |
|
5281 |
if idx == 0: |
|
5282 |
# First entry |
|
5283 |
parameters.update(node_params) |
|
5284 |
else: |
|
5285 |
# Filter out inconsistent values |
|
5286 |
parameters.intersection_update(node_params) |
|
5287 |
|
|
5288 |
params = list(parameters) |
|
5289 |
|
|
5290 |
# Now fill all the info for this provider |
|
5291 |
info = query.ExtStorageInfo(name=es_name, node_status=es_data, |
|
5292 |
nodegroup_status=ndgrp_data, |
|
5293 |
parameters=params) |
|
5294 |
|
|
5295 |
data[es_name] = info |
|
5296 |
|
|
5297 |
# Prepare data in requested order |
|
5298 |
return [data[name] for name in self._GetNames(lu, pol.keys(), None) |
|
5299 |
if name in data] |
|
5300 |
|
|
5301 |
|
|
5302 |
class LUExtStorageDiagnose(NoHooksLU): |
|
5303 |
"""Logical unit for ExtStorage diagnose/query. |
|
5304 |
|
|
5305 |
""" |
|
5306 |
REQ_BGL = False |
|
5307 |
|
|
5308 |
def CheckArguments(self): |
|
5309 |
self.eq = _ExtStorageQuery(qlang.MakeSimpleFilter("name", self.op.names), |
|
5310 |
self.op.output_fields, False) |
|
5311 |
|
|
5312 |
def ExpandNames(self): |
|
5313 |
self.eq.ExpandNames(self) |
|
5314 |
|
|
5315 |
def Exec(self, feedback_fn): |
|
5316 |
return self.eq.OldStyleQuery(self) |
|
5317 |
|
|
5318 |
|
|
5166 | 5319 |
class LUNodeRemove(LogicalUnit): |
5167 | 5320 |
"""Logical unit for removing a node. |
5168 | 5321 |
|
... | ... | |
16604 | 16757 |
constants.QR_GROUP: _GroupQuery, |
16605 | 16758 |
constants.QR_NETWORK: _NetworkQuery, |
16606 | 16759 |
constants.QR_OS: _OsQuery, |
16760 |
constants.QR_EXTSTORAGE: _ExtStorageQuery, |
|
16607 | 16761 |
constants.QR_EXPORT: _ExportQuery, |
16608 | 16762 |
} |
16609 | 16763 |
|
b/lib/constants.py | ||
---|---|---|
1732 | 1732 |
QR_JOB = "job" |
1733 | 1733 |
QR_EXPORT = "export" |
1734 | 1734 |
QR_NETWORK = "network" |
1735 |
QR_EXTSTORAGE = "extstorage" |
|
1735 | 1736 |
|
1736 | 1737 |
#: List of resources which can be queried using L{opcodes.OpQuery} |
1737 | 1738 |
QR_VIA_OP = compat.UniqueFrozenset([ |
... | ... | |
1742 | 1743 |
QR_OS, |
1743 | 1744 |
QR_EXPORT, |
1744 | 1745 |
QR_NETWORK, |
1746 |
QR_EXTSTORAGE, |
|
1745 | 1747 |
]) |
1746 | 1748 |
|
1747 | 1749 |
#: List of resources which can be queried using Local UniX Interface |
b/lib/opcodes.py | ||
---|---|---|
1807 | 1807 |
OP_RESULT = _TOldQueryResult |
1808 | 1808 |
|
1809 | 1809 |
|
1810 |
# ExtStorage opcodes |
|
1811 |
class OpExtStorageDiagnose(OpCode): |
|
1812 |
"""Compute the list of external storage providers.""" |
|
1813 |
OP_PARAMS = [ |
|
1814 |
_POutputFields, |
|
1815 |
("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), |
|
1816 |
"Which ExtStorage Provider to diagnose"), |
|
1817 |
] |
|
1818 |
OP_RESULT = _TOldQueryResult |
|
1819 |
|
|
1820 |
|
|
1810 | 1821 |
# Exports opcodes |
1811 | 1822 |
class OpBackupQuery(OpCode): |
1812 | 1823 |
"""Compute the list of exported images.""" |
b/lib/query.py | ||
---|---|---|
2234 | 2234 |
return _PrepareFieldList(fields, []) |
2235 | 2235 |
|
2236 | 2236 |
|
2237 |
class ExtStorageInfo(objects.ConfigObject): |
|
2238 |
__slots__ = [ |
|
2239 |
"name", |
|
2240 |
"node_status", |
|
2241 |
"nodegroup_status", |
|
2242 |
"parameters", |
|
2243 |
] |
|
2244 |
|
|
2245 |
|
|
2246 |
def _BuildExtStorageFields(): |
|
2247 |
"""Builds list of fields for extstorage provider queries. |
|
2248 |
|
|
2249 |
""" |
|
2250 |
fields = [ |
|
2251 |
(_MakeField("name", "Name", QFT_TEXT, "ExtStorage provider name"), |
|
2252 |
None, 0, _GetItemAttr("name")), |
|
2253 |
(_MakeField("node_status", "NodeStatus", QFT_OTHER, |
|
2254 |
"Status from node"), |
|
2255 |
None, 0, _GetItemAttr("node_status")), |
|
2256 |
(_MakeField("nodegroup_status", "NodegroupStatus", QFT_OTHER, |
|
2257 |
"Overall Nodegroup status"), |
|
2258 |
None, 0, _GetItemAttr("nodegroup_status")), |
|
2259 |
(_MakeField("parameters", "Parameters", QFT_OTHER, |
|
2260 |
"ExtStorage provider parameters"), |
|
2261 |
None, 0, _GetItemAttr("parameters")), |
|
2262 |
] |
|
2263 |
|
|
2264 |
return _PrepareFieldList(fields, []) |
|
2265 |
|
|
2266 |
|
|
2237 | 2267 |
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613 |
2238 | 2268 |
"""Return L{_FS_UNAVAIL} if job is None. |
2239 | 2269 |
|
... | ... | |
2595 | 2625 |
#: Fields available for operating system queries |
2596 | 2626 |
OS_FIELDS = _BuildOsFields() |
2597 | 2627 |
|
2628 |
#: Fields available for extstorage provider queries |
|
2629 |
EXTSTORAGE_FIELDS = _BuildExtStorageFields() |
|
2630 |
|
|
2598 | 2631 |
#: Fields available for job queries |
2599 | 2632 |
JOB_FIELDS = _BuildJobFields() |
2600 | 2633 |
|
... | ... | |
2612 | 2645 |
constants.QR_LOCK: LOCK_FIELDS, |
2613 | 2646 |
constants.QR_GROUP: GROUP_FIELDS, |
2614 | 2647 |
constants.QR_OS: OS_FIELDS, |
2648 |
constants.QR_EXTSTORAGE: EXTSTORAGE_FIELDS, |
|
2615 | 2649 |
constants.QR_JOB: JOB_FIELDS, |
2616 | 2650 |
constants.QR_EXPORT: EXPORT_FIELDS, |
2617 | 2651 |
constants.QR_NETWORK: NETWORK_FIELDS, |
b/lib/rpc_defs.py | ||
---|---|---|
451 | 451 |
], None, _OsGetPostProc, "Returns an OS definition"), |
452 | 452 |
] |
453 | 453 |
|
454 |
_EXTSTORAGE_CALLS = [ |
|
455 |
("extstorage_diagnose", MULTI, None, constants.RPC_TMO_FAST, [], None, None, |
|
456 |
"Request a diagnose of ExtStorage Providers"), |
|
457 |
] |
|
458 |
|
|
454 | 459 |
_NODE_CALLS = [ |
455 | 460 |
("node_has_ip_address", SINGLE, None, constants.RPC_TMO_FAST, [ |
456 | 461 |
("address", None, "IP address"), |
... | ... | |
530 | 535 |
"RpcClientDefault": |
531 | 536 |
_Prepare(_IMPEXP_CALLS + _X509_CALLS + _OS_CALLS + _NODE_CALLS + |
532 | 537 |
_FILE_STORAGE_CALLS + _MISC_CALLS + _INSTANCE_CALLS + |
533 |
_BLOCKDEV_CALLS + _STORAGE_CALLS), |
|
538 |
_BLOCKDEV_CALLS + _STORAGE_CALLS + _EXTSTORAGE_CALLS),
|
|
534 | 539 |
"RpcClientJobQueue": _Prepare([ |
535 | 540 |
("jobqueue_update", MULTI, None, constants.RPC_TMO_URGENT, [ |
536 | 541 |
("file_name", None, None), |
b/lib/server/noded.py | ||
---|---|---|
869 | 869 |
required, name, checks, params = params |
870 | 870 |
return backend.ValidateOS(required, name, checks, params) |
871 | 871 |
|
872 |
# extstorage ----------------------- |
|
873 |
|
|
874 |
@staticmethod |
|
875 |
def perspective_extstorage_diagnose(params): |
|
876 |
"""Query detailed information about existing extstorage providers. |
|
877 |
|
|
878 |
""" |
|
879 |
return backend.DiagnoseExtStorage() |
|
880 |
|
|
872 | 881 |
# hooks ----------------------- |
873 | 882 |
|
874 | 883 |
@staticmethod |
b/test/docs_unittest.py | ||
---|---|---|
58 | 58 |
opcodes.OpTagsSearch, |
59 | 59 |
opcodes.OpClusterActivateMasterIp, |
60 | 60 |
opcodes.OpClusterDeactivateMasterIp, |
61 |
opcodes.OpExtStorageDiagnose, |
|
61 | 62 |
|
62 | 63 |
# Difficult if not impossible |
63 | 64 |
opcodes.OpClusterDestroy, |
Also available in: Unified diff