Revision 9bcef16f
b/Makefile.am | ||
---|---|---|
244 | 244 |
lib/client/gnt_instance.py \ |
245 | 245 |
lib/client/gnt_job.py \ |
246 | 246 |
lib/client/gnt_node.py \ |
247 |
lib/client/gnt_os.py |
|
247 |
lib/client/gnt_os.py \ |
|
248 |
lib/client/gnt_storage.py |
|
248 | 249 |
|
249 | 250 |
hypervisor_PYTHON = \ |
250 | 251 |
lib/hypervisor/__init__.py \ |
... | ... | |
483 | 484 |
scripts/gnt-instance \ |
484 | 485 |
scripts/gnt-job \ |
485 | 486 |
scripts/gnt-node \ |
486 |
scripts/gnt-os |
|
487 |
scripts/gnt-os \ |
|
488 |
scripts/gnt-storage |
|
487 | 489 |
|
488 | 490 |
PYTHON_BOOTSTRAP_SBIN = \ |
489 | 491 |
daemons/ganeti-masterd \ |
b/autotools/build-bash-completion | ||
---|---|---|
341 | 341 |
WriteCompReply(sw, "-W \"$(_ganeti_instances)\"", cur=cur) |
342 | 342 |
elif suggest == cli.OPT_COMPL_ONE_OS: |
343 | 343 |
WriteCompReply(sw, "-W \"$(_ganeti_os)\"", cur=cur) |
344 |
elif suggest == cli.OPT_COMPL_ONE_EXTSTORAGE: |
|
345 |
WriteCompReply(sw, "-W \"$(_ganeti_extstorage)\"", cur=cur) |
|
344 | 346 |
elif suggest == cli.OPT_COMPL_ONE_IALLOCATOR: |
345 | 347 |
WriteCompReply(sw, "-W \"$(_ganeti_iallocator)\"", cur=cur) |
346 | 348 |
elif suggest == cli.OPT_COMPL_ONE_NODEGROUP: |
... | ... | |
446 | 448 |
choices = "$(_ganeti_jobs)" |
447 | 449 |
elif isinstance(arg, cli.ArgOs): |
448 | 450 |
choices = "$(_ganeti_os)" |
451 |
elif isinstance(arg, cli.ArgExtStorage): |
|
452 |
choices = "$(_ganeti_extstorage)" |
|
449 | 453 |
elif isinstance(arg, cli.ArgFile): |
450 | 454 |
choices = "" |
451 | 455 |
compgenargs.append("-f") |
b/lib/backend.py | ||
---|---|---|
2443 | 2443 |
return result |
2444 | 2444 |
|
2445 | 2445 |
|
2446 |
def DiagnoseExtStorage(top_dirs=None): |
|
2447 |
"""Compute the validity for all ExtStorage Providers. |
|
2448 |
|
|
2449 |
@type top_dirs: list |
|
2450 |
@param top_dirs: the list of directories in which to |
|
2451 |
search (if not given defaults to |
|
2452 |
L{constants.ES_SEARCH_PATH}) |
|
2453 |
@rtype: list of L{objects.ExtStorage} |
|
2454 |
@return: a list of tuples (name, path, status, diagnose, parameters) |
|
2455 |
for all (potential) ExtStorage Providers under all |
|
2456 |
search paths, where: |
|
2457 |
- name is the (potential) ExtStorage Provider |
|
2458 |
- path is the full path to the ExtStorage Provider |
|
2459 |
- status True/False is the validity of the ExtStorage Provider |
|
2460 |
- diagnose is the error message for an invalid ExtStorage Provider, |
|
2461 |
otherwise empty |
|
2462 |
- parameters is a list of (name, help) parameters, if any |
|
2463 |
|
|
2464 |
""" |
|
2465 |
if top_dirs is None: |
|
2466 |
top_dirs = constants.ES_SEARCH_PATH |
|
2467 |
|
|
2468 |
result = [] |
|
2469 |
for dir_name in top_dirs: |
|
2470 |
if os.path.isdir(dir_name): |
|
2471 |
try: |
|
2472 |
f_names = utils.ListVisibleFiles(dir_name) |
|
2473 |
except EnvironmentError, err: |
|
2474 |
logging.exception("Can't list the ExtStorage directory %s: %s", |
|
2475 |
dir_name, err) |
|
2476 |
break |
|
2477 |
for name in f_names: |
|
2478 |
es_path = utils.PathJoin(dir_name, name) |
|
2479 |
status, es_inst = bdev.ExtStorageFromDisk(name, base_dir=dir_name) |
|
2480 |
if status: |
|
2481 |
diagnose = "" |
|
2482 |
parameters = es_inst.supported_parameters |
|
2483 |
else: |
|
2484 |
diagnose = es_inst |
|
2485 |
parameters = [] |
|
2486 |
result.append((name, es_path, status, diagnose, parameters)) |
|
2487 |
|
|
2488 |
return result |
|
2489 |
|
|
2490 |
|
|
2446 | 2491 |
def BlockdevGrow(disk, amount, dryrun): |
2447 | 2492 |
"""Grow a stack of block devices. |
2448 | 2493 |
|
b/lib/cli.py | ||
---|---|---|
248 | 248 |
"ArgJobId", |
249 | 249 |
"ArgNode", |
250 | 250 |
"ArgOs", |
251 |
"ArgExtStorage", |
|
251 | 252 |
"ArgSuggest", |
252 | 253 |
"ArgUnknown", |
253 | 254 |
"OPT_COMPL_INST_ADD_NODES", |
... | ... | |
257 | 258 |
"OPT_COMPL_ONE_NODE", |
258 | 259 |
"OPT_COMPL_ONE_NODEGROUP", |
259 | 260 |
"OPT_COMPL_ONE_OS", |
261 |
"OPT_COMPL_ONE_EXTSTORAGE", |
|
260 | 262 |
"cli_option", |
261 | 263 |
"SplitNodeOption", |
262 | 264 |
"CalculateOSNames", |
... | ... | |
390 | 392 |
""" |
391 | 393 |
|
392 | 394 |
|
395 |
class ArgExtStorage(_Argument): |
|
396 |
"""ExtStorage argument. |
|
397 |
|
|
398 |
""" |
|
399 |
|
|
400 |
|
|
393 | 401 |
ARGS_NONE = [] |
394 | 402 |
ARGS_MANY_INSTANCES = [ArgInstance()] |
395 | 403 |
ARGS_MANY_NODES = [ArgNode()] |
... | ... | |
636 | 644 |
OPT_COMPL_ONE_NODE, |
637 | 645 |
OPT_COMPL_ONE_INSTANCE, |
638 | 646 |
OPT_COMPL_ONE_OS, |
647 |
OPT_COMPL_ONE_EXTSTORAGE, |
|
639 | 648 |
OPT_COMPL_ONE_IALLOCATOR, |
640 | 649 |
OPT_COMPL_INST_ADD_NODES, |
641 |
OPT_COMPL_ONE_NODEGROUP) = range(100, 107)
|
|
650 |
OPT_COMPL_ONE_NODEGROUP) = range(100, 108)
|
|
642 | 651 |
|
643 | 652 |
OPT_COMPL_ALL = frozenset([ |
644 | 653 |
OPT_COMPL_MANY_NODES, |
645 | 654 |
OPT_COMPL_ONE_NODE, |
646 | 655 |
OPT_COMPL_ONE_INSTANCE, |
647 | 656 |
OPT_COMPL_ONE_OS, |
657 |
OPT_COMPL_ONE_EXTSTORAGE, |
|
648 | 658 |
OPT_COMPL_ONE_IALLOCATOR, |
649 | 659 |
OPT_COMPL_INST_ADD_NODES, |
650 | 660 |
OPT_COMPL_ONE_NODEGROUP, |
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 constants |
|
31 |
from ganeti import opcodes |
|
32 |
from ganeti import utils |
|
33 |
|
|
34 |
|
|
35 |
def ShowExtStorageInfo(opts, args): |
|
36 |
"""List detailed information about ExtStorage providers. |
|
37 |
|
|
38 |
@param opts: the command line options selected by the user |
|
39 |
@type args: list |
|
40 |
@param args: empty list or list of ExtStorage providers' names |
|
41 |
@rtype: int |
|
42 |
@return: the desired exit code |
|
43 |
|
|
44 |
""" |
|
45 |
op = opcodes.OpExtStorageDiagnose(output_fields=["name", "nodegroup_status", |
|
46 |
"parameters"], |
|
47 |
names=[]) |
|
48 |
|
|
49 |
result = SubmitOpCode(op, opts=opts) |
|
50 |
|
|
51 |
if not result: |
|
52 |
ToStderr("Can't get the ExtStorage providers list") |
|
53 |
return 1 |
|
54 |
|
|
55 |
do_filter = bool(args) |
|
56 |
|
|
57 |
for (name, nodegroup_data, parameters) in result: |
|
58 |
if do_filter: |
|
59 |
if name not in args: |
|
60 |
continue |
|
61 |
else: |
|
62 |
args.remove(name) |
|
63 |
|
|
64 |
nodegroups_valid = [] |
|
65 |
for nodegroup_name, nodegroup_status in nodegroup_data.iteritems(): |
|
66 |
if nodegroup_status: |
|
67 |
nodegroups_valid.append(nodegroup_name) |
|
68 |
|
|
69 |
ToStdout("%s:", name) |
|
70 |
|
|
71 |
if nodegroups_valid != []: |
|
72 |
ToStdout(" - Valid for nodegroups:") |
|
73 |
for ndgrp in utils.NiceSort(nodegroups_valid): |
|
74 |
ToStdout(" %s", ndgrp) |
|
75 |
ToStdout(" - Supported parameters:") |
|
76 |
for pname, pdesc in parameters: |
|
77 |
ToStdout(" %s: %s", pname, pdesc) |
|
78 |
else: |
|
79 |
ToStdout(" - Invalid for all nodegroups") |
|
80 |
|
|
81 |
ToStdout("") |
|
82 |
|
|
83 |
if args: |
|
84 |
for name in args: |
|
85 |
ToStdout("%s: Not Found", name) |
|
86 |
ToStdout("") |
|
87 |
|
|
88 |
return 0 |
|
89 |
|
|
90 |
|
|
91 |
def _ExtStorageStatus(status, diagnose): |
|
92 |
"""Beautifier function for ExtStorage status. |
|
93 |
|
|
94 |
@type status: boolean |
|
95 |
@param status: is the ExtStorage provider valid |
|
96 |
@type diagnose: string |
|
97 |
@param diagnose: the error message for invalid ExtStorages |
|
98 |
@rtype: string |
|
99 |
@return: a formatted status |
|
100 |
|
|
101 |
""" |
|
102 |
if status: |
|
103 |
return "valid" |
|
104 |
else: |
|
105 |
return "invalid - %s" % diagnose |
|
106 |
|
|
107 |
|
|
108 |
def DiagnoseExtStorage(opts, args): |
|
109 |
"""Analyse all ExtStorage providers. |
|
110 |
|
|
111 |
@param opts: the command line options selected by the user |
|
112 |
@type args: list |
|
113 |
@param args: should be an empty list |
|
114 |
@rtype: int |
|
115 |
@return: the desired exit code |
|
116 |
|
|
117 |
""" |
|
118 |
op = opcodes.OpExtStorageDiagnose(output_fields=["name", "node_status", |
|
119 |
"nodegroup_status"], |
|
120 |
names=[]) |
|
121 |
|
|
122 |
result = SubmitOpCode(op, opts=opts) |
|
123 |
|
|
124 |
if not result: |
|
125 |
ToStderr("Can't get the list of ExtStorage providers") |
|
126 |
return 1 |
|
127 |
|
|
128 |
for provider_name, node_data, nodegroup_data in result: |
|
129 |
|
|
130 |
nodes_valid = {} |
|
131 |
nodes_bad = {} |
|
132 |
nodegroups_valid = {} |
|
133 |
nodegroups_bad = {} |
|
134 |
|
|
135 |
# Per node diagnose |
|
136 |
for node_name, node_info in node_data.iteritems(): |
|
137 |
if node_info: # at least one entry in the per-node list |
|
138 |
(fo_path, fo_status, fo_msg, fo_params) = node_info.pop(0) |
|
139 |
fo_msg = "%s (path: %s)" % (_ExtStorageStatus(fo_status, fo_msg), |
|
140 |
fo_path) |
|
141 |
if fo_params: |
|
142 |
fo_msg += (" [parameters: %s]" % |
|
143 |
utils.CommaJoin([v[0] for v in fo_params])) |
|
144 |
else: |
|
145 |
fo_msg += " [no parameters]" |
|
146 |
if fo_status: |
|
147 |
nodes_valid[node_name] = fo_msg |
|
148 |
else: |
|
149 |
nodes_bad[node_name] = fo_msg |
|
150 |
else: |
|
151 |
nodes_bad[node_name] = "ExtStorage provider not found" |
|
152 |
|
|
153 |
# Per nodegroup diagnose |
|
154 |
for nodegroup_name, nodegroup_status in nodegroup_data.iteritems(): |
|
155 |
status = nodegroup_status |
|
156 |
if status: |
|
157 |
nodegroups_valid[nodegroup_name] = "valid" |
|
158 |
else: |
|
159 |
nodegroups_bad[nodegroup_name] = "invalid" |
|
160 |
|
|
161 |
def _OutputPerNodegroupStatus(msg_map): |
|
162 |
map_k = utils.NiceSort(msg_map.keys()) |
|
163 |
for nodegroup in map_k: |
|
164 |
ToStdout(" For nodegroup: %s --> %s", nodegroup, |
|
165 |
msg_map[nodegroup]) |
|
166 |
|
|
167 |
def _OutputPerNodeStatus(msg_map): |
|
168 |
map_k = utils.NiceSort(msg_map.keys()) |
|
169 |
for node_name in map_k: |
|
170 |
ToStdout(" Node: %s, status: %s", node_name, msg_map[node_name]) |
|
171 |
|
|
172 |
# Print the output |
|
173 |
st_msg = "Provider: %s" % provider_name |
|
174 |
ToStdout(st_msg) |
|
175 |
ToStdout("---") |
|
176 |
_OutputPerNodeStatus(nodes_valid) |
|
177 |
_OutputPerNodeStatus(nodes_bad) |
|
178 |
ToStdout(" --") |
|
179 |
_OutputPerNodegroupStatus(nodegroups_valid) |
|
180 |
_OutputPerNodegroupStatus(nodegroups_bad) |
|
181 |
ToStdout("") |
|
182 |
|
|
183 |
return 0 |
|
184 |
|
|
185 |
|
|
186 |
commands = { |
|
187 |
"diagnose": ( |
|
188 |
DiagnoseExtStorage, ARGS_NONE, [PRIORITY_OPT], |
|
189 |
"", "Diagnose all ExtStorage providers"), |
|
190 |
"info": ( |
|
191 |
ShowExtStorageInfo, [ArgOs()], [PRIORITY_OPT], |
|
192 |
"", "Show info about ExtStorage providers"), |
|
193 |
} |
|
194 |
|
|
195 |
|
|
196 |
def Main(): |
|
197 |
return GenericMain(commands) |
b/lib/cmdlib.py | ||
---|---|---|
4930 | 4930 |
return self.oq.OldStyleQuery(self) |
4931 | 4931 |
|
4932 | 4932 |
|
4933 |
class _ExtStorageQuery(_QueryBase): |
|
4934 |
FIELDS = query.EXTSTORAGE_FIELDS |
|
4935 |
|
|
4936 |
def ExpandNames(self, lu): |
|
4937 |
# Lock all nodes in shared mode |
|
4938 |
# Temporary removal of locks, should be reverted later |
|
4939 |
# TODO: reintroduce locks when they are lighter-weight |
|
4940 |
lu.needed_locks = {} |
|
4941 |
#self.share_locks[locking.LEVEL_NODE] = 1 |
|
4942 |
#self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET |
|
4943 |
|
|
4944 |
# The following variables interact with _QueryBase._GetNames |
|
4945 |
if self.names: |
|
4946 |
self.wanted = self.names |
|
4947 |
else: |
|
4948 |
self.wanted = locking.ALL_SET |
|
4949 |
|
|
4950 |
self.do_locking = self.use_locking |
|
4951 |
|
|
4952 |
def DeclareLocks(self, lu, level): |
|
4953 |
pass |
|
4954 |
|
|
4955 |
@staticmethod |
|
4956 |
def _DiagnoseByProvider(rlist): |
|
4957 |
"""Remaps a per-node return list into an a per-provider per-node dictionary |
|
4958 |
|
|
4959 |
@param rlist: a map with node names as keys and ExtStorage objects as values |
|
4960 |
|
|
4961 |
@rtype: dict |
|
4962 |
@return: a dictionary with extstorage providers as keys and as |
|
4963 |
value another map, with nodes as keys and tuples of |
|
4964 |
(path, status, diagnose, parameters) as values, eg:: |
|
4965 |
|
|
4966 |
{"provider1": {"node1": [(/usr/lib/..., True, "", [])] |
|
4967 |
"node2": [(/srv/..., False, "missing file")] |
|
4968 |
"node3": [(/srv/..., True, "", [])] |
|
4969 |
} |
|
4970 |
|
|
4971 |
""" |
|
4972 |
all_es = {} |
|
4973 |
# we build here the list of nodes that didn't fail the RPC (at RPC |
|
4974 |
# level), so that nodes with a non-responding node daemon don't |
|
4975 |
# make all OSes invalid |
|
4976 |
good_nodes = [node_name for node_name in rlist |
|
4977 |
if not rlist[node_name].fail_msg] |
|
4978 |
for node_name, nr in rlist.items(): |
|
4979 |
if nr.fail_msg or not nr.payload: |
|
4980 |
continue |
|
4981 |
for (name, path, status, diagnose, params) in nr.payload: |
|
4982 |
if name not in all_es: |
|
4983 |
# build a list of nodes for this os containing empty lists |
|
4984 |
# for each node in node_list |
|
4985 |
all_es[name] = {} |
|
4986 |
for nname in good_nodes: |
|
4987 |
all_es[name][nname] = [] |
|
4988 |
# convert params from [name, help] to (name, help) |
|
4989 |
params = [tuple(v) for v in params] |
|
4990 |
all_es[name][node_name].append((path, status, diagnose, params)) |
|
4991 |
return all_es |
|
4992 |
|
|
4993 |
def _GetQueryData(self, lu): |
|
4994 |
"""Computes the list of nodes and their attributes. |
|
4995 |
|
|
4996 |
""" |
|
4997 |
# Locking is not used |
|
4998 |
assert not (compat.any(lu.glm.is_owned(level) |
|
4999 |
for level in locking.LEVELS |
|
5000 |
if level != locking.LEVEL_CLUSTER) or |
|
5001 |
self.do_locking or self.use_locking) |
|
5002 |
|
|
5003 |
valid_nodes = [node.name |
|
5004 |
for node in lu.cfg.GetAllNodesInfo().values() |
|
5005 |
if not node.offline and node.vm_capable] |
|
5006 |
pol = self._DiagnoseByProvider(lu.rpc.call_extstorage_diagnose(valid_nodes)) |
|
5007 |
|
|
5008 |
data = {} |
|
5009 |
|
|
5010 |
nodegroup_list = lu.cfg.GetNodeGroupList() |
|
5011 |
|
|
5012 |
for (es_name, es_data) in pol.items(): |
|
5013 |
# For every provider compute the nodegroup validity. |
|
5014 |
# To do this we need to check the validity of each node in es_data |
|
5015 |
# and then construct the corresponding nodegroup dict: |
|
5016 |
# { nodegroup1: status |
|
5017 |
# nodegroup2: status |
|
5018 |
# } |
|
5019 |
ndgrp_data = {} |
|
5020 |
for nodegroup in nodegroup_list: |
|
5021 |
ndgrp = lu.cfg.GetNodeGroup(nodegroup) |
|
5022 |
|
|
5023 |
nodegroup_nodes = ndgrp.members |
|
5024 |
nodegroup_name = ndgrp.name |
|
5025 |
node_statuses = [] |
|
5026 |
|
|
5027 |
for node in nodegroup_nodes: |
|
5028 |
if node in valid_nodes: |
|
5029 |
if es_data[node] != []: |
|
5030 |
node_status = es_data[node][0][1] |
|
5031 |
node_statuses.append(node_status) |
|
5032 |
else: |
|
5033 |
node_statuses.append(False) |
|
5034 |
|
|
5035 |
if False in node_statuses: |
|
5036 |
ndgrp_data[nodegroup_name] = False |
|
5037 |
else: |
|
5038 |
ndgrp_data[nodegroup_name] = True |
|
5039 |
|
|
5040 |
# Compute the provider's parameters |
|
5041 |
parameters = set() |
|
5042 |
for idx, esl in enumerate(es_data.values()): |
|
5043 |
valid = bool(esl and esl[0][1]) |
|
5044 |
if not valid: |
|
5045 |
break |
|
5046 |
|
|
5047 |
node_params = esl[0][3] |
|
5048 |
if idx == 0: |
|
5049 |
# First entry |
|
5050 |
parameters.update(node_params) |
|
5051 |
else: |
|
5052 |
# Filter out inconsistent values |
|
5053 |
parameters.intersection_update(node_params) |
|
5054 |
|
|
5055 |
params = list(parameters) |
|
5056 |
|
|
5057 |
# Now fill all the info for this provider |
|
5058 |
info = query.ExtStorageInfo(name=es_name, node_status=es_data, |
|
5059 |
nodegroup_status=ndgrp_data, |
|
5060 |
parameters=params) |
|
5061 |
|
|
5062 |
data[es_name] = info |
|
5063 |
|
|
5064 |
# Prepare data in requested order |
|
5065 |
return [data[name] for name in self._GetNames(lu, pol.keys(), None) |
|
5066 |
if name in data] |
|
5067 |
|
|
5068 |
|
|
5069 |
class LUExtStorageDiagnose(NoHooksLU): |
|
5070 |
"""Logical unit for ExtStorage diagnose/query. |
|
5071 |
|
|
5072 |
""" |
|
5073 |
REQ_BGL = False |
|
5074 |
|
|
5075 |
def CheckArguments(self): |
|
5076 |
self.eq = _ExtStorageQuery(qlang.MakeSimpleFilter("name", self.op.names), |
|
5077 |
self.op.output_fields, False) |
|
5078 |
|
|
5079 |
def ExpandNames(self): |
|
5080 |
self.eq.ExpandNames(self) |
|
5081 |
|
|
5082 |
def Exec(self, feedback_fn): |
|
5083 |
return self.eq.OldStyleQuery(self) |
|
5084 |
|
|
5085 |
|
|
4933 | 5086 |
class LUNodeRemove(LogicalUnit): |
4934 | 5087 |
"""Logical unit for removing a node. |
4935 | 5088 |
|
... | ... | |
15426 | 15579 |
constants.QR_NODE: _NodeQuery, |
15427 | 15580 |
constants.QR_GROUP: _GroupQuery, |
15428 | 15581 |
constants.QR_OS: _OsQuery, |
15582 |
constants.QR_EXTSTORAGE: _ExtStorageQuery, |
|
15429 | 15583 |
constants.QR_EXPORT: _ExportQuery, |
15430 | 15584 |
} |
15431 | 15585 |
|
b/lib/constants.py | ||
---|---|---|
1658 | 1658 |
QR_OS = "os" |
1659 | 1659 |
QR_JOB = "job" |
1660 | 1660 |
QR_EXPORT = "export" |
1661 |
QR_EXTSTORAGE = "extstorage" |
|
1661 | 1662 |
|
1662 | 1663 |
#: List of resources which can be queried using L{opcodes.OpQuery} |
1663 | 1664 |
QR_VIA_OP = frozenset([ |
... | ... | |
1667 | 1668 |
QR_GROUP, |
1668 | 1669 |
QR_OS, |
1669 | 1670 |
QR_EXPORT, |
1671 |
QR_EXTSTORAGE, |
|
1670 | 1672 |
]) |
1671 | 1673 |
|
1672 | 1674 |
#: List of resources which can be queried using Local UniX Interface |
b/lib/opcodes.py | ||
---|---|---|
1762 | 1762 |
OP_RESULT = _TOldQueryResult |
1763 | 1763 |
|
1764 | 1764 |
|
1765 |
# ExtStorage opcodes |
|
1766 |
class OpExtStorageDiagnose(OpCode): |
|
1767 |
"""Compute the list of external storage providers.""" |
|
1768 |
OP_PARAMS = [ |
|
1769 |
_POutputFields, |
|
1770 |
("names", ht.EmptyList, ht.TListOf(ht.TNonEmptyString), |
|
1771 |
"Which ExtStorage Provider to diagnose"), |
|
1772 |
] |
|
1773 |
|
|
1774 |
|
|
1765 | 1775 |
# Exports opcodes |
1766 | 1776 |
class OpBackupQuery(OpCode): |
1767 | 1777 |
"""Compute the list of exported images.""" |
b/lib/query.py | ||
---|---|---|
2180 | 2180 |
return _PrepareFieldList(fields, []) |
2181 | 2181 |
|
2182 | 2182 |
|
2183 |
class ExtStorageInfo(objects.ConfigObject): |
|
2184 |
__slots__ = [ |
|
2185 |
"name", |
|
2186 |
"node_status", |
|
2187 |
"nodegroup_status", |
|
2188 |
"parameters", |
|
2189 |
] |
|
2190 |
|
|
2191 |
|
|
2192 |
def _BuildExtStorageFields(): |
|
2193 |
"""Builds list of fields for extstorage provider queries. |
|
2194 |
|
|
2195 |
""" |
|
2196 |
fields = [ |
|
2197 |
(_MakeField("name", "Name", QFT_TEXT, "ExtStorage provider name"), |
|
2198 |
None, 0, _GetItemAttr("name")), |
|
2199 |
(_MakeField("node_status", "NodeStatus", QFT_OTHER, |
|
2200 |
"Status from node"), |
|
2201 |
None, 0, _GetItemAttr("node_status")), |
|
2202 |
(_MakeField("nodegroup_status", "NodegroupStatus", QFT_OTHER, |
|
2203 |
"Overall Nodegroup status"), |
|
2204 |
None, 0, _GetItemAttr("nodegroup_status")), |
|
2205 |
(_MakeField("parameters", "Parameters", QFT_OTHER, |
|
2206 |
"ExtStorage provider parameters"), |
|
2207 |
None, 0, _GetItemAttr("parameters")), |
|
2208 |
] |
|
2209 |
|
|
2210 |
return _PrepareFieldList(fields, []) |
|
2211 |
|
|
2212 |
|
|
2183 | 2213 |
def _JobUnavailInner(fn, ctx, (job_id, job)): # pylint: disable=W0613 |
2184 | 2214 |
"""Return L{_FS_UNAVAIL} if job is None. |
2185 | 2215 |
|
... | ... | |
2419 | 2449 |
#: Fields available for operating system queries |
2420 | 2450 |
OS_FIELDS = _BuildOsFields() |
2421 | 2451 |
|
2452 |
#: Fields available for extstorage provider queries |
|
2453 |
EXTSTORAGE_FIELDS = _BuildExtStorageFields() |
|
2454 |
|
|
2422 | 2455 |
#: Fields available for job queries |
2423 | 2456 |
JOB_FIELDS = _BuildJobFields() |
2424 | 2457 |
|
... | ... | |
2433 | 2466 |
constants.QR_LOCK: LOCK_FIELDS, |
2434 | 2467 |
constants.QR_GROUP: GROUP_FIELDS, |
2435 | 2468 |
constants.QR_OS: OS_FIELDS, |
2469 |
constants.QR_EXTSTORAGE: EXTSTORAGE_FIELDS, |
|
2436 | 2470 |
constants.QR_JOB: JOB_FIELDS, |
2437 | 2471 |
constants.QR_EXPORT: EXPORT_FIELDS, |
2438 | 2472 |
} |
b/lib/rpc_defs.py | ||
---|---|---|
435 | 435 |
], None, _OsGetPostProc, "Returns an OS definition"), |
436 | 436 |
] |
437 | 437 |
|
438 |
_EXTSTORAGE_CALLS = [ |
|
439 |
("extstorage_diagnose", MULTI, None, TMO_FAST, [], None, None, |
|
440 |
"Request a diagnose of ExtStorage Providers"), |
|
441 |
] |
|
442 |
|
|
438 | 443 |
_NODE_CALLS = [ |
439 | 444 |
("node_has_ip_address", SINGLE, None, TMO_FAST, [ |
440 | 445 |
("address", None, "IP address"), |
... | ... | |
503 | 508 |
"RpcClientDefault": \ |
504 | 509 |
_Prepare(_IMPEXP_CALLS + _X509_CALLS + _OS_CALLS + _NODE_CALLS + |
505 | 510 |
_FILE_STORAGE_CALLS + _MISC_CALLS + _INSTANCE_CALLS + |
506 |
_BLOCKDEV_CALLS + _STORAGE_CALLS), |
|
511 |
_BLOCKDEV_CALLS + _STORAGE_CALLS + _EXTSTORAGE_CALLS),
|
|
507 | 512 |
"RpcClientJobQueue": _Prepare([ |
508 | 513 |
("jobqueue_update", MULTI, None, TMO_URGENT, [ |
509 | 514 |
("file_name", None, None), |
b/lib/server/noded.py | ||
---|---|---|
830 | 830 |
required, name, checks, params = params |
831 | 831 |
return backend.ValidateOS(required, name, checks, params) |
832 | 832 |
|
833 |
# extstorage ----------------------- |
|
834 |
|
|
835 |
@staticmethod |
|
836 |
def perspective_extstorage_diagnose(params): |
|
837 |
"""Query detailed information about existing extstorage providers. |
|
838 |
|
|
839 |
""" |
|
840 |
return backend.DiagnoseExtStorage() |
|
841 |
|
|
833 | 842 |
# hooks ----------------------- |
834 | 843 |
|
835 | 844 |
@staticmethod |
Also available in: Unified diff