Extend burnin to do NIC changes
[ganeti-local] / tools / cluster-merge
index e2fc848..f94a32f 100755 (executable)
@@ -24,7 +24,7 @@ The clusters have to run the same version of Ganeti!
 
 """
 
-# pylint: disable-msg=C0103
+# pylint: disable=C0103
 # C0103: Invalid name cluster-merge
 
 import logging
@@ -40,7 +40,6 @@ from ganeti import constants
 from ganeti import errors
 from ganeti import ssh
 from ganeti import utils
-from ganeti import netutils
 
 
 _GROUPS_MERGE = "merge"
@@ -111,7 +110,7 @@ class MergerData(object):
 
   """
   def __init__(self, cluster, key_path, nodes, instances, master_node,
-               master_ip, config_path=None):
+               config_path=None):
     """Initialize the container.
 
     @param cluster: The name of the cluster
@@ -119,7 +118,6 @@ class MergerData(object):
     @param nodes: List of online nodes in the merging cluster
     @param instances: List of instances running on merging cluster
     @param master_node: Name of the master node
-    @param master_ip: Cluster IP
     @param config_path: Path to the merging cluster config
 
     """
@@ -128,7 +126,6 @@ class MergerData(object):
     self.nodes = nodes
     self.instances = instances
     self.master_node = master_node
-    self.master_ip = master_ip
     self.config_path = config_path
 
 
@@ -195,16 +192,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"
@@ -221,17 +218,8 @@ class Merger(object):
                                  (cluster, result.fail_reason, result.output))
       master_node = result.stdout.strip()
 
-      path = utils.PathJoin(constants.DATA_DIR, "ssconf_%s" %
-                            constants.SS_MASTER_IP)
-      result = self._RunCmd(cluster, "cat %s" % path, private_key=key_path)
-      if result.failed:
-        raise errors.RemoteError("Unable to retrieve the master IP from"
-                                 " %s. Fail reason: %s; output: %s" %
-                                 (cluster, result.fail_reason, result.output))
-      master_ip = result.stdout.strip()
-
       self.merger_data.append(MergerData(cluster, key_path, nodes, instances,
-                                         master_node, master_ip))
+                                         master_node))
 
   def _PrepareAuthorizedKeys(self):
     """Prepare the authorized_keys on every merging node.
@@ -319,19 +307,9 @@ class Merger(object):
 
     """
     for data in self.merger_data:
-      master_ip_family = netutils.IPAddress.GetAddressFamily(data.master_ip)
-      master_ip_len = netutils.IP4Address.iplen
-      if master_ip_family == netutils.IP6Address.family:
-        master_ip_len = netutils.IP6Address.iplen
-      # Not using constants.IP_COMMAND_PATH because the command might run on a
-      # machine in which the ip path is different, so it's better to rely on
-      # $PATH.
-      cmd = "ip address del %s/%s dev $(cat %s)" % (
-             data.master_ip,
-             master_ip_len,
-             utils.PathJoin(constants.DATA_DIR, "ssconf_%s" %
-                            constants.SS_MASTER_NETDEV))
-      result = self._RunCmd(data.master_node, cmd, max_attempts=3)
+      result = self._RunCmd(data.master_node,
+                            "gnt-cluster deactivate-master-ip --yes")
+
       if result.failed:
         raise errors.RemoteError("Unable to remove master IP on %s."
                                  " Fail reason: %s; output: %s" %
@@ -374,7 +352,7 @@ class Merger(object):
       utils.WriteFile(data.config_path, data=result.stdout)
 
   # R0201: Method could be a function
-  def _KillMasterDaemon(self): # pylint: disable-msg=R0201
+  def _KillMasterDaemon(self): # pylint: disable=R0201
     """Kills the local master daemon.
 
     @raise errors.CommandError: If unable to kill
@@ -574,7 +552,7 @@ class Merger(object):
                                       other_cluster.cluster_name)
 
   # R0201: Method could be a function
-  def _GetOsHypervisor(self, cluster, os_name, hyp): # pylint: disable-msg=R0201
+  def _GetOsHypervisor(self, cluster, os_name, hyp): # pylint: disable=R0201
     if os_name in cluster.os_hvp:
       return cluster.os_hvp[os_name].get(hyp, None)
     else:
@@ -586,7 +564,7 @@ class Merger(object):
 
     ConfigWriter.AddNodeGroup takes care of making sure there are no conflicts.
     """
-    # pylint: disable-msg=R0201
+    # pylint: disable=R0201
     logging.info("Node group conflict strategy: %s", self.groups)
 
     my_grps = my_config.GetAllNodeGroupsInfo().values()
@@ -626,15 +604,15 @@ class Merger(object):
           for node_name in other_grp.members[:]:
             node = other_config.GetNodeInfo(node_name)
             # Access to a protected member of a client class
-            # pylint: disable-msg=W0212
+            # pylint: disable=W0212
             other_config._UnlockedRemoveNodeFromGroup(node)
 
             # Access to a protected member of a client class
-            # pylint: disable-msg=W0212
+            # pylint: disable=W0212
             my_grp_uuid = my_config._UnlockedLookupNodeGroup(other_grp.name)
 
             # Access to a protected member of a client class
-            # pylint: disable-msg=W0212
+            # pylint: disable=W0212
             my_config._UnlockedAddNodeToGroup(node, my_grp_uuid)
             node.group = my_grp_uuid
           # Remove from list of groups to add
@@ -645,7 +623,7 @@ class Merger(object):
       my_config.AddNodeGroup(grp, _CLUSTERMERGE_ECID)
 
   # R0201: Method could be a function
-  def _StartMasterDaemon(self, no_vote=False): # pylint: disable-msg=R0201
+  def _StartMasterDaemon(self, no_vote=False): # pylint: disable=R0201
     """Starts the local master daemon.
 
     @param no_vote: Should the masterd started without voting? default: False
@@ -670,6 +648,7 @@ 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])
         if result.failed:
@@ -683,7 +662,7 @@ class Merger(object):
                                                 result.output))
 
   # R0201: Method could be a function
-  def _StartupAllInstances(self): # pylint: disable-msg=R0201
+  def _StartupAllInstances(self): # pylint: disable=R0201
     """Starts up all instances (locally).
 
     @raise errors.CommandError: If unable to start clusters
@@ -698,7 +677,7 @@ class Merger(object):
 
   # R0201: Method could be a function
   # TODO: make this overridable, for some verify errors
-  def _VerifyCluster(self): # pylint: disable-msg=R0201
+  def _VerifyCluster(self): # pylint: disable=R0201
     """Runs gnt-cluster verify to verify the health.
 
     @raise errors.ProgrammError: If cluster fails on verification
@@ -739,12 +718,12 @@ class Merger(object):
                                   " mergees")
       logging.info("Disable watcher")
       self._DisableWatcher()
-      logging.info("Stop daemons on merging nodes")
-      self._StopDaemons()
       logging.info("Merging config")
       self._FetchRemoteConfig()
       logging.info("Removing master IPs on mergee master nodes")
       self._RemoveMasterIps()
+      logging.info("Stop daemons on merging nodes")
+      self._StopDaemons()
 
       logging.info("Stopping master daemon")
       self._KillMasterDaemon()