"IGNORE_REMOVE_FAILURES_OPT",
"IGNORE_SECONDARIES_OPT",
"IGNORE_SIZE_OPT",
+ "INCLUDEDEFAULTS_OPT",
"INTERVAL_OPT",
"MAC_PREFIX_OPT",
"MAINTAIN_NODE_HEALTH_OPT",
"FormatQueryResult",
"FormatParamsDictInfo",
"FormatPolicyInfo",
+ "PrintIPolicyCommand",
"PrintGenericInfo",
"GenerateTable",
"AskUser",
action="store_false",
help="Don't check for conflicting IPs")
+INCLUDEDEFAULTS_OPT = cli_option("--include-defaults", dest="include_defaults",
+ default=False, action="store_true",
+ help="Include default values")
+
#: Options provided by all commands
COMMON_OPTS = [DEBUG_OPT, REASON_OPT]
return ret
+def _PrintSpecsParameters(buf, specs):
+ values = ("%s=%s" % (par, val) for (par, val) in sorted(specs.items()))
+ buf.write(",".join(values))
+
+
+def PrintIPolicyCommand(buf, ipolicy, isgroup):
+ """Print the command option used to generate the given instance policy.
+
+ Currently only the parts dealing with specs are supported.
+
+ @type buf: StringIO
+ @param buf: stream to write into
+ @type ipolicy: dict
+ @param ipolicy: instance policy
+ @type isgroup: bool
+ @param isgroup: whether the policy is at group level
+
+ """
+ if not isgroup:
+ stdspecs = ipolicy.get("std")
+ if stdspecs:
+ buf.write(" %s " % IPOLICY_STD_SPECS_STR)
+ _PrintSpecsParameters(buf, stdspecs)
+ minmax = ipolicy.get("minmax")
+ if minmax:
+ minspecs = minmax.get("min")
+ maxspecs = minmax.get("max")
+ if minspecs and maxspecs:
+ buf.write(" %s " % IPOLICY_BOUNDS_SPECS_STR)
+ buf.write("min:")
+ _PrintSpecsParameters(buf, minspecs)
+ buf.write("/max:")
+ _PrintSpecsParameters(buf, maxspecs)
+
+
def ConfirmOperation(names, list_type, text, extra=""):
"""Ask the user to confirm an operation on a list of list_type.
# W0614: Unused import %s from wildcard import (since we need cli)
# C0103: Invalid name gnt-cluster
+from cStringIO import StringIO
import os.path
import time
import OpenSSL
return _off_fn(opts, node_list, inst_map)
+def _GetCreateCommand(info):
+ buf = StringIO()
+ buf.write("gnt-cluster init")
+ PrintIPolicyCommand(buf, info["ipolicy"], False)
+ buf.write(" ")
+ buf.write(info["name"])
+ return buf.getvalue()
+
+
+def ShowCreateCommand(opts, args):
+ """Shows the command that can be used to re-create the cluster.
+
+ Currently it works only for ipolicy specs.
+
+ """
+ cl = GetClient(query=True)
+ result = cl.QueryClusterInfo()
+ ToStdout(_GetCreateCommand(result))
+
+
commands = {
"init": (
InitCluster, [ArgHost(min=1, max=1)],
"deactivate-master-ip": (
DeactivateMasterIp, ARGS_NONE, [CONFIRM_OPT], "",
"Deactivates the master IP"),
+ "show-ispecs-cmd": (
+ ShowCreateCommand, ARGS_NONE, [], "",
+ "Show the command line to re-create the cluster"),
}
# W0401: Wildcard import ganeti.cli
# W0614: Unused import %s from wildcard import (since we need cli)
+from cStringIO import StringIO
+
from ganeti.cli import *
from ganeti import constants
from ganeti import opcodes
])
+def _GetCreateCommand(group):
+ (name, ipolicy) = group
+ buf = StringIO()
+ buf.write("gnt-group add")
+ PrintIPolicyCommand(buf, ipolicy, True)
+ buf.write(" ")
+ buf.write(name)
+ return buf.getvalue()
+
+
+def ShowCreateCommand(opts, args):
+ """Shows the command that can be used to re-create a node group.
+
+ Currently it works only for ipolicy specs.
+
+ """
+ cl = GetClient(query=True)
+ selected_fields = ["name"]
+ if opts.include_defaults:
+ selected_fields += ["ipolicy"]
+ else:
+ selected_fields += ["custom_ipolicy"]
+ result = cl.QueryGroups(names=args, fields=selected_fields,
+ use_locking=False)
+
+ for group in result:
+ ToStdout(_GetCreateCommand(group))
+
+
commands = {
"add": (
AddGroup, ARGS_ONE_GROUP,
"info": (
GroupInfo, ARGS_MANY_GROUPS, [], "[<group_name>...]",
"Show group information"),
+ "show-ispecs-cmd": (
+ ShowCreateCommand, ARGS_MANY_GROUPS, [INCLUDEDEFAULTS_OPT],
+ "[--include-defaults] [<group_name>...]",
+ "Show the command line to re-create a group"),
}
its integer fields in a latin friendly way. This allows further
diffusion of Ganeti among ancient cultures.
+SHOW-ISPECS-CMD
+~~~~~~~~~~~~~~~
+
+**show-ispecs-cmd**
+
+Shows the command line that can be used to recreate the cluster with the
+same options relative to specs in the instance policies.
+
INIT
~~~~
INFO
~~~~
-**info** [group...]
+**info** [*group*...]
Shows config information for all (or given) groups.
+SHOW-ISPECS-CMD
+~~~~~~~~~~~~~~~
+
+**show-ispecs-cmd** [\--include-defaults] [*group*...]
+
+Shows the command line that can be used to recreate the given groups (or
+all groups, if none is given) with the same options relative to specs in
+the instance policies.
+
+If ``--include-defaults`` is specified, include also the default values
+(i.e. the cluster-level settings), and not only the configuration items
+that a group overrides.
+
.. vim: set textwidth=72 :
.. Local Variables:
self._TestFullISpecsInner(skel_ipolicy, exp_minmax1, None,
False, fill_all)
+
+class TestPrintIPolicyCommand(unittest.TestCase):
+ """Test case for cli.PrintIPolicyCommand"""
+ _SPECS1 = {
+ "par1": 42,
+ "par2": "xyz",
+ }
+ _SPECS1_STR = "par1=42,par2=xyz"
+ _SPECS2 = {
+ "param": 10,
+ "another_param": 101,
+ }
+ _SPECS2_STR = "another_param=101,param=10"
+
+ def _CheckPrintIPolicyCommand(self, ipolicy, isgroup, expected):
+ buf = StringIO()
+ cli.PrintIPolicyCommand(buf, ipolicy, isgroup)
+ self.assertEqual(buf.getvalue(), expected)
+
+ def testIgnoreStdForGroup(self):
+ self._CheckPrintIPolicyCommand({"std": self._SPECS1}, True, "")
+
+ def testIgnoreEmpty(self):
+ policies = [
+ {},
+ {"std": {}},
+ {"minmax": {}},
+ {"minmax": {
+ "min": {},
+ "max": {},
+ }},
+ {"minmax": {
+ "min": self._SPECS1,
+ "max": {},
+ }},
+ ]
+ for pol in policies:
+ self._CheckPrintIPolicyCommand(pol, False, "")
+
+ def testFullPolicies(self):
+ cases = [
+ ({"std": self._SPECS1},
+ " %s %s" % (cli.IPOLICY_STD_SPECS_STR, self._SPECS1_STR)),
+ ({"minmax": {
+ "min": self._SPECS1,
+ "max": self._SPECS2,
+ }},
+ " %s min:%s/max:%s" % (cli.IPOLICY_BOUNDS_SPECS_STR,
+ self._SPECS1_STR, self._SPECS2_STR)),
+ ]
+ for (pol, exp) in cases:
+ self._CheckPrintIPolicyCommand(pol, False, exp)
+
+
if __name__ == "__main__":
testutils.GanetiTestProgram()