Unify the “--backend-parameters” option
[ganeti-local] / lib / config.py
index ba4bbdf..91621b9 100644 (file)
@@ -35,6 +35,7 @@ import os
 import tempfile
 import random
 import logging
+import time
 
 from ganeti import errors
 from ganeti import locking
@@ -708,6 +709,7 @@ class ConfigWriter:
           " MAC address '%s' already in use." % (instance.name, nic.mac))
 
     instance.serial_no = 1
+    instance.ctime = instance.mtime = time.time()
     self._config_data.instances[instance.name] = instance
     self._config_data.cluster.serial_no += 1
     self._UnlockedReleaseDRBDMinors(instance.name)
@@ -729,6 +731,7 @@ class ConfigWriter:
     if instance.admin_up != status:
       instance.admin_up = status
       instance.serial_no += 1
+      instance.mtime = time.time()
       self._WriteConfig()
 
   @locking.ssynchronized(_config_lock)
@@ -860,6 +863,7 @@ class ConfigWriter:
     logging.info("Adding node %s to configuration" % node.name)
 
     node.serial_no = 1
+    node.ctime = node.mtime = time.time()
     self._config_data.nodes[node.name] = node
     self._config_data.cluster.serial_no += 1
     self._WriteConfig()
@@ -1031,19 +1035,18 @@ class ConfigWriter:
 
     """
     self._config_data.serial_no += 1
+    self._config_data.mtime = time.time()
 
   def _OpenConfig(self):
     """Read the config data from disk.
 
     """
-    f = open(self._cfg_file, 'r')
+    raw_data = utils.ReadFile(self._cfg_file)
+
     try:
-      try:
-        data = objects.ConfigData.FromDict(serializer.Load(f.read()))
-      except Exception, err:
-        raise errors.ConfigurationError(err)
-    finally:
-      f.close()
+      data = objects.ConfigData.FromDict(serializer.Load(raw_data))
+    except Exception, err:
+      raise errors.ConfigurationError(err)
 
     # Make sure the configuration has the right version
     _ValidateConfig(data)
@@ -1087,7 +1090,7 @@ class ConfigWriter:
     result = rpc.RpcRunner.call_upload_file(node_list, self._cfg_file,
                                             address_list=addr_list)
     for to_node, to_result in result.items():
-      msg = to_result.RemoteFailMsg()
+      msg = to_result.fail_msg
       if msg:
         msg = ("Copy of file %s to node %s failed: %s" %
                (self._cfg_file, to_node, msg))
@@ -1108,16 +1111,9 @@ class ConfigWriter:
       destination = self._cfg_file
     self._BumpSerialNo()
     txt = serializer.Dump(self._config_data.ToDict())
-    dir_name, file_name = os.path.split(destination)
-    fd, name = tempfile.mkstemp('.newconfig', file_name, dir_name)
-    f = os.fdopen(fd, 'w')
-    try:
-      f.write(txt)
-      os.fsync(f.fileno())
-    finally:
-      f.close()
-    # we don't need to do os.close(fd) as f.close() did it
-    os.rename(name, destination)
+
+    utils.WriteFile(destination, data=txt)
+
     self.write_count += 1
 
     # and redistribute the config file to master candidates
@@ -1130,7 +1126,7 @@ class ConfigWriter:
           self._UnlockedGetNodeList(),
           self._UnlockedGetSsconfValues())
         for nname, nresu in result.items():
-          msg = nresu.RemoteFailMsg()
+          msg = nresu.fail_msg
           if msg:
             logging.warning("Error while uploading ssconf files to"
                             " node %s: %s", nname, msg)
@@ -1148,12 +1144,20 @@ class ConfigWriter:
     instance_names = utils.NiceSort(self._UnlockedGetInstanceList())
     node_names = utils.NiceSort(self._UnlockedGetNodeList())
     node_info = [self._UnlockedGetNodeInfo(name) for name in node_names]
+    node_pri_ips = ["%s %s" % (ninfo.name, ninfo.primary_ip)
+                    for ninfo in node_info]
+    node_snd_ips = ["%s %s" % (ninfo.name, ninfo.secondary_ip)
+                    for ninfo in node_info]
 
     instance_data = fn(instance_names)
     off_data = fn(node.name for node in node_info if node.offline)
     on_data = fn(node.name for node in node_info if not node.offline)
     mc_data = fn(node.name for node in node_info if node.master_candidate)
+    mc_ips_data = fn(node.primary_ip for node in node_info
+                     if node.master_candidate)
     node_data = fn(node_names)
+    node_pri_ips_data = fn(node_pri_ips)
+    node_snd_ips_data = fn(node_snd_ips)
 
     cluster = self._config_data.cluster
     cluster_tags = fn(cluster.GetTags())
@@ -1162,10 +1166,13 @@ class ConfigWriter:
       constants.SS_CLUSTER_TAGS: cluster_tags,
       constants.SS_FILE_STORAGE_DIR: cluster.file_storage_dir,
       constants.SS_MASTER_CANDIDATES: mc_data,
+      constants.SS_MASTER_CANDIDATES_IPS: mc_ips_data,
       constants.SS_MASTER_IP: cluster.master_ip,
       constants.SS_MASTER_NETDEV: cluster.master_netdev,
       constants.SS_MASTER_NODE: cluster.master_node,
       constants.SS_NODE_LIST: node_data,
+      constants.SS_NODE_PRIMARY_IPS: node_pri_ips_data,
+      constants.SS_NODE_SECONDARY_IPS: node_snd_ips_data,
       constants.SS_OFFLINE_NODES: off_data,
       constants.SS_ONLINE_NODES: on_data,
       constants.SS_INSTANCE_LIST: instance_data,
@@ -1238,10 +1245,12 @@ class ConfigWriter:
       raise errors.ConfigurationError("Configuration updated since object"
                                       " has been read or unknown object")
     target.serial_no += 1
+    target.mtime = now = time.time()
 
     if update_serial:
       # for node updates, we need to increase the cluster serial too
       self._config_data.cluster.serial_no += 1
+      self._config_data.cluster.mtime = now
 
     if isinstance(target, objects.Instance):
       self._UnlockedReleaseDRBDMinors(target.name)