Move disk template unit tests to test/py/cmdlib/
[ganeti-local] / tools / cluster-merge
index 7897e81..066440e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2010 Google Inc.
+# Copyright (C) 2010, 2012 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -40,6 +40,8 @@ from ganeti import constants
 from ganeti import errors
 from ganeti import ssh
 from ganeti import utils
+from ganeti import pathutils
+from ganeti import compat
 
 
 _GROUPS_MERGE = "merge"
@@ -133,7 +135,7 @@ class Merger(object):
   """Handling the merge.
 
   """
-  RUNNING_STATUSES = frozenset([
+  RUNNING_STATUSES = compat.UniqueFrozenset([
     constants.INSTST_RUNNING,
     constants.INSTST_ERRORUP,
     ])
@@ -192,16 +194,16 @@ class Merger(object):
       utils.WriteFile(key_path, mode=0600, data=result.stdout)
 
       result = self._RunCmd(cluster, "gnt-node list -o name,offline"
-                            " --no-header --separator=,", private_key=key_path)
+                            " --no-headers --separator=,", private_key=key_path)
       if result.failed:
         raise errors.RemoteError("Unable to retrieve list of nodes from %s."
                                  " Fail reason: %s; output: %s" %
                                  (cluster, result.fail_reason, result.output))
-      nodes_statuses = [line.split(',') for line in result.stdout.splitlines()]
+      nodes_statuses = [line.split(",") for line in result.stdout.splitlines()]
       nodes = [node_status[0] for node_status in nodes_statuses
                if node_status[1] == "N"]
 
-      result = self._RunCmd(cluster, "gnt-instance list -o name --no-header",
+      result = self._RunCmd(cluster, "gnt-instance list -o name --no-headers",
                             private_key=key_path)
       if result.failed:
         raise errors.RemoteError("Unable to retrieve list of instances from"
@@ -209,7 +211,7 @@ class Merger(object):
                                  (cluster, result.fail_reason, result.output))
       instances = result.stdout.splitlines()
 
-      path = utils.PathJoin(constants.DATA_DIR, "ssconf_%s" %
+      path = utils.PathJoin(pathutils.DATA_DIR, "ssconf_%s" %
                             constants.SS_MASTER_NODE)
       result = self._RunCmd(cluster, "cat %s" % path, private_key=key_path)
       if result.failed:
@@ -253,10 +255,10 @@ class Merger(object):
     """
     for _ in range(max_attempts):
       result = self.ssh_runner.Run(hostname=hostname, command=command,
-                                 user=user, use_cluster_key=use_cluster_key,
-                                 strict_host_check=strict_host_check,
-                                 private_key=private_key, batch=batch,
-                                 ask_key=ask_key)
+                                   user=user, use_cluster_key=use_cluster_key,
+                                   strict_host_check=strict_host_check,
+                                   private_key=private_key, batch=batch,
+                                   ask_key=ask_key)
       if not result.failed:
         break
 
@@ -308,7 +310,7 @@ class Merger(object):
     """
     for data in self.merger_data:
       result = self._RunCmd(data.master_node,
-                            "gnt-cluster deactivate-master-ip")
+                            "gnt-cluster deactivate-master-ip --yes")
 
       if result.failed:
         raise errors.RemoteError("Unable to remove master IP on %s."
@@ -321,7 +323,7 @@ class Merger(object):
     """Stop all daemons on merging nodes.
 
     """
-    cmd = "%s stop-all" % constants.DAEMON_UTIL
+    cmd = "%s stop-all" % pathutils.DAEMON_UTIL
     for data in self.merger_data:
       for node in data.nodes:
         result = self._RunCmd(node, cmd, max_attempts=3)
@@ -339,7 +341,7 @@ class Merger(object):
     """
     for data in self.merger_data:
       result = self._RunCmd(data.cluster, "cat %s" %
-                                          constants.CLUSTER_CONF_FILE)
+                                          pathutils.CLUSTER_CONF_FILE)
 
       if result.failed:
         raise errors.RemoteError("Unable to retrieve remote config on %s."
@@ -358,7 +360,7 @@ class Merger(object):
     @raise errors.CommandError: If unable to kill
 
     """
-    result = utils.RunCmd([constants.DAEMON_UTIL, "stop-master"])
+    result = utils.RunCmd([pathutils.DAEMON_UTIL, "stop-master"])
     if result.failed:
       raise errors.CommandError("Unable to stop master daemons."
                                 " Fail reason: %s; output: %s" %
@@ -391,17 +393,13 @@ class Merger(object):
         # Update the DRBD port assignments
         # This is a little bit hackish
         for dsk in instance_info.disks:
-          if dsk.dev_type in constants.LDS_DRBD:
+          if dsk.dev_type in constants.DTS_DRBD:
             port = my_config.AllocatePort()
 
             logical_id = list(dsk.logical_id)
             logical_id[2] = port
             dsk.logical_id = tuple(logical_id)
 
-            physical_id = list(dsk.physical_id)
-            physical_id[1] = physical_id[3] = port
-            dsk.physical_id = tuple(physical_id)
-
         my_config.AddInstance(instance_info,
                               _CLUSTERMERGE_ECID + str(fake_ec_id))
         fake_ec_id += 1
@@ -433,9 +431,11 @@ class Merger(object):
     check_params_strict = [
       "volume_group_name",
     ]
-    if constants.ENABLE_FILE_STORAGE:
+    if my_cluster.IsFileStorageEnabled() or \
+        other_cluster.IsFileStorageEnabled():
       check_params_strict.append("file_storage_dir")
-    if constants.ENABLE_SHARED_FILE_STORAGE:
+    if my_cluster.IsSharedFileStorageEnabled() or \
+        other_cluster.IsSharedFileStorageEnabled():
       check_params_strict.append("shared_file_storage_dir")
     check_params.extend(check_params_strict)
 
@@ -634,7 +634,7 @@ class Merger(object):
     if no_vote:
       env["EXTRA_MASTERD_ARGS"] = "--no-voting --yes-do-it"
 
-    result = utils.RunCmd([constants.DAEMON_UTIL, "start-master"], env=env)
+    result = utils.RunCmd([pathutils.DAEMON_UTIL, "start-master"], env=env)
     if result.failed:
       raise errors.CommandError("Couldn't start ganeti master."
                                 " Fail reason: %s; output: %s" %
@@ -648,8 +648,9 @@ class Merger(object):
     """
     for data in self.merger_data:
       for node in data.nodes:
+        logging.info("Readding node %s", node)
         result = utils.RunCmd(["gnt-node", "add", "--readd",
-                               "--no-ssh-key-check", "--force-join", node])
+                               "--no-ssh-key-check", node])
         if result.failed:
           logging.error("%s failed to be readded. Reason: %s, output: %s",
                          node, result.fail_reason, result.output)
@@ -658,7 +659,7 @@ class Merger(object):
     if result.failed:
       raise errors.CommandError("Redistribution failed. Fail reason: %s;"
                                 " output: %s" % (result.fail_reason,
-                                                result.output))
+                                                 result.output))
 
   # R0201: Method could be a function
   def _StartupAllInstances(self): # pylint: disable=R0201
@@ -729,7 +730,7 @@ class Merger(object):
 
       rbsteps.append("Restore %s from another master candidate"
                      " and restart master daemon" %
-                     constants.CLUSTER_CONF_FILE)
+                     pathutils.CLUSTER_CONF_FILE)
       self._MergeConfig()
       self._StartMasterDaemon(no_vote=True)
 
@@ -779,28 +780,6 @@ class Merger(object):
     shutil.rmtree(self.work_dir)
 
 
-def SetupLogging(options):
-  """Setting up logging infrastructure.
-
-  @param options: Parsed command line options
-
-  """
-  formatter = logging.Formatter("%(asctime)s: %(levelname)s %(message)s")
-
-  stderr_handler = logging.StreamHandler()
-  stderr_handler.setFormatter(formatter)
-  if options.debug:
-    stderr_handler.setLevel(logging.NOTSET)
-  elif options.verbose:
-    stderr_handler.setLevel(logging.INFO)
-  else:
-    stderr_handler.setLevel(logging.WARNING)
-
-  root_logger = logging.getLogger("")
-  root_logger.setLevel(logging.NOTSET)
-  root_logger.addHandler(stderr_handler)
-
-
 def main():
   """Main routine.
 
@@ -819,7 +798,7 @@ def main():
 
   (options, args) = parser.parse_args()
 
-  SetupLogging(options)
+  utils.SetupToolLogging(options.debug, options.verbose)
 
   if not args:
     parser.error("No clusters specified")