Revision 1a615be0 tools/cluster-merge
b/tools/cluster-merge | ||
---|---|---|
42 | 42 |
from ganeti import utils |
43 | 43 |
|
44 | 44 |
|
45 |
_GROUPS_MERGE = "merge" |
|
46 |
_GROUPS_RENAME = "rename" |
|
47 |
_CLUSTERMERGE_ECID = "clustermerge-ecid" |
|
48 |
|
|
45 | 49 |
PAUSE_PERIOD_OPT = cli.cli_option("-p", "--watcher-pause-period", default=1800, |
46 | 50 |
action="store", type="int", |
47 | 51 |
dest="pause_period", |
48 | 52 |
help=("Amount of time in seconds watcher" |
49 | 53 |
" should be suspended from running")) |
50 |
_CLUSTERMERGE_ECID = "clustermerge-ecid" |
|
54 |
GROUPS_OPT = cli.cli_option("--groups", default=None, metavar="STRATEGY", |
|
55 |
choices=(_GROUPS_MERGE, _GROUPS_RENAME), dest="groups", |
|
56 |
help=("How to handle groups that have the" |
|
57 |
" same name (One of: %s/%s)" % |
|
58 |
(_GROUPS_MERGE, _GROUPS_RENAME))) |
|
51 | 59 |
|
52 | 60 |
|
53 | 61 |
def Flatten(unflattened_list): |
... | ... | |
92 | 100 |
"""Handling the merge. |
93 | 101 |
|
94 | 102 |
""" |
95 |
def __init__(self, clusters, pause_period): |
|
103 |
def __init__(self, clusters, pause_period, groups):
|
|
96 | 104 |
"""Initialize object with sane defaults and infos required. |
97 | 105 |
|
98 | 106 |
@param clusters: The list of clusters to merge in |
99 | 107 |
@param pause_period: The time watcher shall be disabled for |
108 |
@param groups: How to handle group conflicts |
|
100 | 109 |
|
101 | 110 |
""" |
102 | 111 |
self.merger_data = [] |
... | ... | |
105 | 114 |
self.work_dir = tempfile.mkdtemp(suffix="cluster-merger") |
106 | 115 |
(self.cluster_name, ) = cli.GetClient().QueryConfigValues(["cluster_name"]) |
107 | 116 |
self.ssh_runner = ssh.SshRunner(self.cluster_name) |
117 |
self.groups = groups |
|
108 | 118 |
|
109 | 119 |
def Setup(self): |
110 | 120 |
"""Sets up our end so we can do the merger. |
... | ... | |
304 | 314 |
ConfigWriter.AddNodeGroup takes care of making sure there are no conflicts. |
305 | 315 |
""" |
306 | 316 |
# pylint: disable-msg=R0201 |
307 |
for grp in other_config.GetAllNodeGroupsInfo().values(): |
|
317 |
logging.info("Node group conflict strategy: %s" % self.groups) |
|
318 |
|
|
319 |
my_grps = my_config.GetAllNodeGroupsInfo().values() |
|
320 |
other_grps = other_config.GetAllNodeGroupsInfo().values() |
|
321 |
|
|
322 |
# Check for node group naming conflicts: |
|
323 |
conflicts = [] |
|
324 |
for other_grp in other_grps: |
|
325 |
for my_grp in my_grps: |
|
326 |
if other_grp.name == my_grp.name: |
|
327 |
conflicts.append(other_grp) |
|
328 |
|
|
329 |
if conflicts: |
|
330 |
conflict_names = utils.CommaJoin([g.name for g in conflicts]) |
|
331 |
logging.info("Node groups in both local and remote cluster: %s" % |
|
332 |
conflict_names) |
|
333 |
|
|
334 |
# User hasn't specified how to handle conflicts |
|
335 |
if not self.groups: |
|
336 |
raise errors.CommandError("The following node group(s) are in both" |
|
337 |
" clusters, and no merge strategy has been" |
|
338 |
" supplied (see the --groups option): %s" % |
|
339 |
conflict_names) |
|
340 |
|
|
341 |
# User wants to rename conflicts |
|
342 |
if self.groups == _GROUPS_RENAME: |
|
343 |
for grp in conflicts: |
|
344 |
new_name = "%s-%s" % (grp.name, other_config.GetClusterName()) |
|
345 |
logging.info("Renaming remote node group from %s to %s" |
|
346 |
" to resolve conflict" % (grp.name, new_name)) |
|
347 |
grp.name = new_name |
|
348 |
|
|
349 |
for grp in other_grps: |
|
308 | 350 |
#TODO: handle node group conflicts |
309 | 351 |
my_config.AddNodeGroup(grp, _CLUSTERMERGE_ECID) |
310 | 352 |
|
... | ... | |
483 | 525 |
""" |
484 | 526 |
program = os.path.basename(sys.argv[0]) |
485 | 527 |
|
486 |
parser = optparse.OptionParser(usage=("%prog [--debug|--verbose]" |
|
528 |
parser = optparse.OptionParser(usage=("%%prog [--debug|--verbose]"
|
|
487 | 529 |
" [--watcher-pause-period SECONDS]" |
488 |
" <cluster> <cluster...>"), |
|
530 |
" [--groups [%s|%s]]" |
|
531 |
" <cluster> [<cluster...>]" % |
|
532 |
(_GROUPS_MERGE, _GROUPS_RENAME)), |
|
489 | 533 |
prog=program) |
490 | 534 |
parser.add_option(cli.DEBUG_OPT) |
491 | 535 |
parser.add_option(cli.VERBOSE_OPT) |
492 | 536 |
parser.add_option(PAUSE_PERIOD_OPT) |
537 |
parser.add_option(GROUPS_OPT) |
|
493 | 538 |
|
494 | 539 |
(options, args) = parser.parse_args() |
495 | 540 |
|
... | ... | |
498 | 543 |
if not args: |
499 | 544 |
parser.error("No clusters specified") |
500 | 545 |
|
501 |
cluster_merger = Merger(utils.UniqueSequence(args), options.pause_period) |
|
546 |
cluster_merger = Merger(utils.UniqueSequence(args), options.pause_period, |
|
547 |
options.groups) |
|
502 | 548 |
try: |
503 | 549 |
try: |
504 | 550 |
cluster_merger.Setup() |
Also available in: Unified diff