Revision ea9d3b40
b/lib/cli.py | ||
---|---|---|
108 | 108 |
"IGNORE_REMOVE_FAILURES_OPT", |
109 | 109 |
"IGNORE_SECONDARIES_OPT", |
110 | 110 |
"IGNORE_SIZE_OPT", |
111 |
"INCLUDEDEFAULTS_OPT", |
|
111 | 112 |
"INTERVAL_OPT", |
112 | 113 |
"MAC_PREFIX_OPT", |
113 | 114 |
"MAINTAIN_NODE_HEALTH_OPT", |
... | ... | |
237 | 238 |
"FormatQueryResult", |
238 | 239 |
"FormatParamsDictInfo", |
239 | 240 |
"FormatPolicyInfo", |
241 |
"PrintIPolicyCommand", |
|
240 | 242 |
"PrintGenericInfo", |
241 | 243 |
"GenerateTable", |
242 | 244 |
"AskUser", |
... | ... | |
1621 | 1623 |
action="store_false", |
1622 | 1624 |
help="Don't check for conflicting IPs") |
1623 | 1625 |
|
1626 |
INCLUDEDEFAULTS_OPT = cli_option("--include-defaults", dest="include_defaults", |
|
1627 |
default=False, action="store_true", |
|
1628 |
help="Include default values") |
|
1629 |
|
|
1624 | 1630 |
#: Options provided by all commands |
1625 | 1631 |
COMMON_OPTS = [DEBUG_OPT, REASON_OPT] |
1626 | 1632 |
|
... | ... | |
3751 | 3757 |
return ret |
3752 | 3758 |
|
3753 | 3759 |
|
3760 |
def _PrintSpecsParameters(buf, specs): |
|
3761 |
values = ("%s=%s" % (par, val) for (par, val) in sorted(specs.items())) |
|
3762 |
buf.write(",".join(values)) |
|
3763 |
|
|
3764 |
|
|
3765 |
def PrintIPolicyCommand(buf, ipolicy, isgroup): |
|
3766 |
"""Print the command option used to generate the given instance policy. |
|
3767 |
|
|
3768 |
Currently only the parts dealing with specs are supported. |
|
3769 |
|
|
3770 |
@type buf: StringIO |
|
3771 |
@param buf: stream to write into |
|
3772 |
@type ipolicy: dict |
|
3773 |
@param ipolicy: instance policy |
|
3774 |
@type isgroup: bool |
|
3775 |
@param isgroup: whether the policy is at group level |
|
3776 |
|
|
3777 |
""" |
|
3778 |
if not isgroup: |
|
3779 |
stdspecs = ipolicy.get("std") |
|
3780 |
if stdspecs: |
|
3781 |
buf.write(" %s " % IPOLICY_STD_SPECS_STR) |
|
3782 |
_PrintSpecsParameters(buf, stdspecs) |
|
3783 |
minmax = ipolicy.get("minmax") |
|
3784 |
if minmax: |
|
3785 |
minspecs = minmax.get("min") |
|
3786 |
maxspecs = minmax.get("max") |
|
3787 |
if minspecs and maxspecs: |
|
3788 |
buf.write(" %s " % IPOLICY_BOUNDS_SPECS_STR) |
|
3789 |
buf.write("min:") |
|
3790 |
_PrintSpecsParameters(buf, minspecs) |
|
3791 |
buf.write("/max:") |
|
3792 |
_PrintSpecsParameters(buf, maxspecs) |
|
3793 |
|
|
3794 |
|
|
3754 | 3795 |
def ConfirmOperation(names, list_type, text, extra=""): |
3755 | 3796 |
"""Ask the user to confirm an operation on a list of list_type. |
3756 | 3797 |
|
b/lib/client/gnt_cluster.py | ||
---|---|---|
26 | 26 |
# W0614: Unused import %s from wildcard import (since we need cli) |
27 | 27 |
# C0103: Invalid name gnt-cluster |
28 | 28 |
|
29 |
from cStringIO import StringIO |
|
29 | 30 |
import os.path |
30 | 31 |
import time |
31 | 32 |
import OpenSSL |
... | ... | |
1491 | 1492 |
return _off_fn(opts, node_list, inst_map) |
1492 | 1493 |
|
1493 | 1494 |
|
1495 |
def _GetCreateCommand(info): |
|
1496 |
buf = StringIO() |
|
1497 |
buf.write("gnt-cluster init") |
|
1498 |
PrintIPolicyCommand(buf, info["ipolicy"], False) |
|
1499 |
buf.write(" ") |
|
1500 |
buf.write(info["name"]) |
|
1501 |
return buf.getvalue() |
|
1502 |
|
|
1503 |
|
|
1504 |
def ShowCreateCommand(opts, args): |
|
1505 |
"""Shows the command that can be used to re-create the cluster. |
|
1506 |
|
|
1507 |
Currently it works only for ipolicy specs. |
|
1508 |
|
|
1509 |
""" |
|
1510 |
cl = GetClient(query=True) |
|
1511 |
result = cl.QueryClusterInfo() |
|
1512 |
ToStdout(_GetCreateCommand(result)) |
|
1513 |
|
|
1514 |
|
|
1494 | 1515 |
commands = { |
1495 | 1516 |
"init": ( |
1496 | 1517 |
InitCluster, [ArgHost(min=1, max=1)], |
... | ... | |
1603 | 1624 |
"deactivate-master-ip": ( |
1604 | 1625 |
DeactivateMasterIp, ARGS_NONE, [CONFIRM_OPT], "", |
1605 | 1626 |
"Deactivates the master IP"), |
1627 |
"show-ispecs-cmd": ( |
|
1628 |
ShowCreateCommand, ARGS_NONE, [], "", |
|
1629 |
"Show the command line to re-create the cluster"), |
|
1606 | 1630 |
} |
1607 | 1631 |
|
1608 | 1632 |
|
b/lib/client/gnt_group.py | ||
---|---|---|
24 | 24 |
# W0401: Wildcard import ganeti.cli |
25 | 25 |
# W0614: Unused import %s from wildcard import (since we need cli) |
26 | 26 |
|
27 |
from cStringIO import StringIO |
|
28 |
|
|
27 | 29 |
from ganeti.cli import * |
28 | 30 |
from ganeti import constants |
29 | 31 |
from ganeti import opcodes |
... | ... | |
313 | 315 |
]) |
314 | 316 |
|
315 | 317 |
|
318 |
def _GetCreateCommand(group): |
|
319 |
(name, ipolicy) = group |
|
320 |
buf = StringIO() |
|
321 |
buf.write("gnt-group add") |
|
322 |
PrintIPolicyCommand(buf, ipolicy, True) |
|
323 |
buf.write(" ") |
|
324 |
buf.write(name) |
|
325 |
return buf.getvalue() |
|
326 |
|
|
327 |
|
|
328 |
def ShowCreateCommand(opts, args): |
|
329 |
"""Shows the command that can be used to re-create a node group. |
|
330 |
|
|
331 |
Currently it works only for ipolicy specs. |
|
332 |
|
|
333 |
""" |
|
334 |
cl = GetClient(query=True) |
|
335 |
selected_fields = ["name"] |
|
336 |
if opts.include_defaults: |
|
337 |
selected_fields += ["ipolicy"] |
|
338 |
else: |
|
339 |
selected_fields += ["custom_ipolicy"] |
|
340 |
result = cl.QueryGroups(names=args, fields=selected_fields, |
|
341 |
use_locking=False) |
|
342 |
|
|
343 |
for group in result: |
|
344 |
ToStdout(_GetCreateCommand(group)) |
|
345 |
|
|
346 |
|
|
316 | 347 |
commands = { |
317 | 348 |
"add": ( |
318 | 349 |
AddGroup, ARGS_ONE_GROUP, |
... | ... | |
366 | 397 |
"info": ( |
367 | 398 |
GroupInfo, ARGS_MANY_GROUPS, [], "[<group_name>...]", |
368 | 399 |
"Show group information"), |
400 |
"show-ispecs-cmd": ( |
|
401 |
ShowCreateCommand, ARGS_MANY_GROUPS, [INCLUDEDEFAULTS_OPT], |
|
402 |
"[--include-defaults] [<group_name>...]", |
|
403 |
"Show the command line to re-create a group"), |
|
369 | 404 |
} |
370 | 405 |
|
371 | 406 |
|
b/man/gnt-cluster.rst | ||
---|---|---|
152 | 152 |
its integer fields in a latin friendly way. This allows further |
153 | 153 |
diffusion of Ganeti among ancient cultures. |
154 | 154 |
|
155 |
SHOW-ISPECS-CMD |
|
156 |
~~~~~~~~~~~~~~~ |
|
157 |
|
|
158 |
**show-ispecs-cmd** |
|
159 |
|
|
160 |
Shows the command line that can be used to recreate the cluster with the |
|
161 |
same options relative to specs in the instance policies. |
|
162 |
|
|
155 | 163 |
INIT |
156 | 164 |
~~~~ |
157 | 165 |
|
b/man/gnt-group.rst | ||
---|---|---|
257 | 257 |
INFO |
258 | 258 |
~~~~ |
259 | 259 |
|
260 |
**info** [group...]
|
|
260 |
**info** [*group*...]
|
|
261 | 261 |
|
262 | 262 |
Shows config information for all (or given) groups. |
263 | 263 |
|
264 |
SHOW-ISPECS-CMD |
|
265 |
~~~~~~~~~~~~~~~ |
|
266 |
|
|
267 |
**show-ispecs-cmd** [\--include-defaults] [*group*...] |
|
268 |
|
|
269 |
Shows the command line that can be used to recreate the given groups (or |
|
270 |
all groups, if none is given) with the same options relative to specs in |
|
271 |
the instance policies. |
|
272 |
|
|
273 |
If ``--include-defaults`` is specified, include also the default values |
|
274 |
(i.e. the cluster-level settings), and not only the configuration items |
|
275 |
that a group overrides. |
|
276 |
|
|
264 | 277 |
|
265 | 278 |
.. vim: set textwidth=72 : |
266 | 279 |
.. Local Variables: |
b/test/py/ganeti.cli_unittest.py | ||
---|---|---|
1423 | 1423 |
self._TestFullISpecsInner(skel_ipolicy, exp_minmax1, None, |
1424 | 1424 |
False, fill_all) |
1425 | 1425 |
|
1426 |
|
|
1427 |
class TestPrintIPolicyCommand(unittest.TestCase): |
|
1428 |
"""Test case for cli.PrintIPolicyCommand""" |
|
1429 |
_SPECS1 = { |
|
1430 |
"par1": 42, |
|
1431 |
"par2": "xyz", |
|
1432 |
} |
|
1433 |
_SPECS1_STR = "par1=42,par2=xyz" |
|
1434 |
_SPECS2 = { |
|
1435 |
"param": 10, |
|
1436 |
"another_param": 101, |
|
1437 |
} |
|
1438 |
_SPECS2_STR = "another_param=101,param=10" |
|
1439 |
|
|
1440 |
def _CheckPrintIPolicyCommand(self, ipolicy, isgroup, expected): |
|
1441 |
buf = StringIO() |
|
1442 |
cli.PrintIPolicyCommand(buf, ipolicy, isgroup) |
|
1443 |
self.assertEqual(buf.getvalue(), expected) |
|
1444 |
|
|
1445 |
def testIgnoreStdForGroup(self): |
|
1446 |
self._CheckPrintIPolicyCommand({"std": self._SPECS1}, True, "") |
|
1447 |
|
|
1448 |
def testIgnoreEmpty(self): |
|
1449 |
policies = [ |
|
1450 |
{}, |
|
1451 |
{"std": {}}, |
|
1452 |
{"minmax": {}}, |
|
1453 |
{"minmax": { |
|
1454 |
"min": {}, |
|
1455 |
"max": {}, |
|
1456 |
}}, |
|
1457 |
{"minmax": { |
|
1458 |
"min": self._SPECS1, |
|
1459 |
"max": {}, |
|
1460 |
}}, |
|
1461 |
] |
|
1462 |
for pol in policies: |
|
1463 |
self._CheckPrintIPolicyCommand(pol, False, "") |
|
1464 |
|
|
1465 |
def testFullPolicies(self): |
|
1466 |
cases = [ |
|
1467 |
({"std": self._SPECS1}, |
|
1468 |
" %s %s" % (cli.IPOLICY_STD_SPECS_STR, self._SPECS1_STR)), |
|
1469 |
({"minmax": { |
|
1470 |
"min": self._SPECS1, |
|
1471 |
"max": self._SPECS2, |
|
1472 |
}}, |
|
1473 |
" %s min:%s/max:%s" % (cli.IPOLICY_BOUNDS_SPECS_STR, |
|
1474 |
self._SPECS1_STR, self._SPECS2_STR)), |
|
1475 |
] |
|
1476 |
for (pol, exp) in cases: |
|
1477 |
self._CheckPrintIPolicyCommand(pol, False, exp) |
|
1478 |
|
|
1479 |
|
|
1426 | 1480 |
if __name__ == "__main__": |
1427 | 1481 |
testutils.GanetiTestProgram() |
Also available in: Unified diff