Revision 1a615be0

b/doc/cluster-merge.rst
23 23

  
24 24
The usage of ``cluster-merge`` is as follows::
25 25

  
26
  cluster-merge [--debug|--verbose] [--watcher-pause-period SECONDS] <cluster> \
27
  <cluster...>
26
  cluster-merge [--debug|--verbose] [--watcher-pause-period SECONDS] \
27
  [--groups [merge|rename]] <cluster> [<cluster...>]
28 28

  
29 29
You can provide multiple clusters. The tool will then go over every
30 30
cluster in serial and perform the steps to merge it into the invoking
......
39 39
``--watcher-pause-period``
40 40
  Define the period of time in seconds the watcher shall be disabled,
41 41
  default is 1800 seconds (30 minutes).
42
``--groups``
43
  This option controls how ``cluster-merge`` handles duplicate node
44
  group names on the merging clusters. If ``merge`` is specified then
45
  all node groups with the same name will be merged into one. If
46
  ``rename`` is specified, then conflicting node groups on the remove
47
  clusters will have their cluster name appended to the group name. If
48
  this option is not speicifed, then ``cluster-merge`` will refuse to
49
  continue if it finds conflicting group names, otherwise it will
50
  proceed as normal.
42 51

  
43 52

  
44 53
Rollback
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