Merge branch 'stable-2.14' into stable-2.15
authorKlaus Aehlig <aehlig@google.com>
Thu, 12 Nov 2015 10:45:16 +0000 (11:45 +0100)
committerKlaus Aehlig <aehlig@google.com>
Thu, 12 Nov 2015 10:52:25 +0000 (11:52 +0100)
* stable-2.14
  Fix faulty iallocator type check
  Improve cfgupgrade output in case of errors

* stable-2.13
  Extend timeout for gnt-cluster renew-crypto
  Reduce flakyness of GetCmdline test on slow machines
  Remove duplicated words

* stable-2.12
  Revert "Also consider connection time out a network error"
  Clone lists before modifying
  Make lockConfig call retryable
  Return the correct error code in the post-upgrade script
  Make openssl refrain from DH altogether
  Fix upgrades of instances with missing creation time

* stable-2.11
  (no changes)

* stable-2.10
  Remove -X from hspace man page
  Make htools tolerate missing "dtotal" and "dfree" on luxi

Signed-off-by: Klaus Aehlig <aehlig@google.com>
Reviewed-by: Lisa Velden <velden@google.com>

13 files changed:
lib/client/gnt_node.py
lib/masterd/iallocator.py
lib/mcpu.py
lib/rpc/transport.py
lib/rpc_defs.py
lib/tools/cfgupgrade.py
man/hspace.rst
src/Ganeti/Constants.hs
src/Ganeti/WConfd/Core.hs
test/data/cluster_config_2.11.json
test/py/ganeti.utils.process_unittest.py
tools/cfgupgrade
tools/post-upgrade

index 22e5107..87f3d19 100644 (file)
@@ -317,8 +317,7 @@ def AddNode(opts, args):
              "Performing this operation is going to perform the following\n"
              "changes to the target machine (%s) and the current cluster\n"
              "nodes:\n"
-             "* A new SSH daemon key pair is generated is generated on\n"
-             "  the target machine.\n"
+             "* A new SSH daemon key pair is generated on the target machine.\n"
              "* The public SSH keys of all master candidates of the cluster\n"
              "  are added to the target machine's 'authorized_keys' file.\n"
              "* In case the target machine is a master candidate, its newly\n"
index 7871dff..728a02b 100644 (file)
@@ -369,7 +369,7 @@ class IAReqNodeEvac(IARequestBase):
   REQ_PARAMS = [
     ("instances", _STRING_LIST),
     ("evac_mode", ht.TEvacMode),
-    ("ignore_soft_errors", ht.TBool),
+    ("ignore_soft_errors", ht.TMaybe(ht.TBool)),
     ]
   REQ_RESULT = _NEVAC_RESULT
 
index 35616c0..e0289bf 100644 (file)
@@ -219,7 +219,7 @@ def _SetBaseOpParams(src, defcomment, dst):
     dst.comment = defcomment
 
   if hasattr(src, constants.OPCODE_REASON):
-    dst.reason = getattr(dst, constants.OPCODE_REASON, [])
+    dst.reason = list(getattr(dst, constants.OPCODE_REASON, []))
     dst.reason.extend(getattr(src, constants.OPCODE_REASON, []))
 
 
index 0350fa2..8271016 100644 (file)
@@ -223,8 +223,7 @@ class Transport:
     for try_no in range(0, retries):
       try:
         return fn(try_no)
-      except (socket.error, errors.ConnectionClosedError,
-              errors.TimeoutError) as ex:
+      except (socket.error, errors.ConnectionClosedError) as ex:
         on_error(ex)
         # we retry on a network error, unless it's the last try
         if try_no == retries - 1:
index b38ea1f..09b2fa8 100644 (file)
@@ -564,7 +564,7 @@ _NODE_CALLS = [
     ("readd", None,
      "Whether this is a readd operation.")],
     None, None, "Remove a node's SSH key from the other nodes' key files."),
-  ("node_ssh_keys_renew", MULTI, None, constants.RPC_TMO_SLOW, [
+  ("node_ssh_keys_renew", MULTI, None, constants.RPC_TMO_4HRS, [
     ("node_uuids", None, "UUIDs of the nodes whose key is renewed"),
     ("node_names", None, "Names of the nodes whose key is renewed"),
     ("master_candidate_uuids", None, "List of UUIDs of master candidates."),
index cfe37ad..e071b79 100644 (file)
@@ -115,7 +115,7 @@ def OrFail(description=None):
         f(self)
       except BaseException, e:
         msg = "%s failed:\n%s" % (description or f.func_name, e)
-        logging.error(msg)
+        logging.exception(msg)
         self.config_data = safety
         self.errors.append(msg)
     return wrapped
@@ -188,7 +188,7 @@ class CfgUpgrade(object):
       if config_revision != 0:
         logging.warning("Config revision is %s, not 0", config_revision)
       if not self.UpgradeAll():
-        raise Error("Upgrade failed:\n%s", '\n'.join(self.errors))
+        raise Error("Upgrade failed:\n%s" % '\n'.join(self.errors))
 
     elif config_major == TARGET_MAJOR and config_minor == TARGET_MINOR:
       logging.info("No changes necessary")
@@ -607,7 +607,9 @@ class CfgUpgrade(object):
       for disk in iobj["disks"]:
         duuid = disk["uuid"]
         disk["serial_no"] = 1
-        disk["ctime"] = disk["mtime"] = iobj["ctime"]
+        # Instances may not have the ctime value, and the Haskell serialization
+        # will have set it to zero.
+        disk["ctime"] = disk["mtime"] = iobj.get("ctime", 0)
         self.config_data["disks"][duuid] = disk
         disk_uuids.append(duuid)
       iobj["disks"] = disk_uuids
index 45065af..1259f25 100644 (file)
@@ -16,7 +16,7 @@ SYNOPSIS
 
 Backend options:
 
-{ **-m** *cluster* | **-L[** *path* **] [-X]** | **-t** *data-file* |
+{ **-m** *cluster* | **-L[** *path* **]** | **-t** *data-file* |
 **\--simulate** *spec* | **-I** *path* }
 
 
index ac1f4fd..6452962 100644 (file)
@@ -600,7 +600,7 @@ rsaKeyBits = 2048
 -- after it's been removed. Use the "openssl" utility to check the
 -- allowed ciphers, e.g.  "openssl ciphers -v HIGH:-DES".
 opensslCiphers :: String
-opensslCiphers = "HIGH:-DES:-3DES:-EXPORT:-ADH"
+opensslCiphers = "HIGH:-DES:-3DES:-EXPORT:-DH"
 
 -- * X509
 
index d327002..8c0306c 100644 (file)
@@ -44,7 +44,7 @@ module Ganeti.WConfd.Core where
 import Control.Arrow ((&&&))
 import Control.Concurrent (myThreadId)
 import Control.Lens.Setter (set)
-import Control.Monad (liftM, unless, when)
+import Control.Monad (liftM, unless)
 import qualified Data.Map as M
 import qualified Data.Set as S
 import Language.Haskell.TH (Name)
@@ -117,16 +117,22 @@ lockConfig
     -> Bool -- ^ set to 'True' if the lock should be shared
     -> WConfdMonad (J.MaybeForJSON ConfigData)
 lockConfig cid shared = do
-  let reqtype = if shared then ReqShared else ReqExclusive
-  -- warn if we already have the lock, this shouldn't happen
+  let (reqtype, owntype) = if shared
+                             then (ReqShared, L.OwnShared)
+                             else (ReqExclusive, L.OwnExclusive)
   la <- readLockAllocation
-  when (L.holdsLock cid ConfigLock L.OwnShared la)
-       . failError $ "Client " ++ show cid ++
-                     " already holds a config lock"
-  waiting <- tryUpdateLocks cid [(ConfigLock, reqtype)]
-  liftM J.MaybeForJSON $ case waiting of
-    []  -> liftM Just CW.readConfig
-    _   -> return Nothing
+  if L.holdsLock cid ConfigLock owntype la
+    then do
+      -- warn if we already have the lock, but continue (with no-op)
+      -- on the locks
+      logWarning $ "Client " ++ show cid ++ " asked to lock the config"
+                   ++ " while owning the lock"
+      liftM (J.MaybeForJSON . Just) CW.readConfig
+    else do
+      waiting <- tryUpdateLocks cid [(ConfigLock, reqtype)]
+      liftM J.MaybeForJSON $ case waiting of
+        []  -> liftM Just CW.readConfig
+        _   -> return Nothing
 
 -- | Release the config lock, if the client currently holds it.
 unlockConfig
index d4c5f5b..dc8a4e6 100644 (file)
             "admin_state": "up",
             "admin_state_source": "admin",
             "beparams": {},
-            "ctime": 1355186880.451181,
             "disk_template": "plain",
             "disks": [
                 {
index 5b2107f..82fc81e 100755 (executable)
@@ -745,7 +745,7 @@ class RunInSeparateProcess(unittest.TestCase):
 
 class GetCmdline(unittest.TestCase):
   def test(self):
-    sample_cmd = "sleep 2; true"
+    sample_cmd = "sleep 20; true"
     pid = subprocess.Popen(sample_cmd, shell=True).pid
     cmdline = utils.GetProcCmdline(pid)
     # As the popen will quote and pass on the sample_cmd, it should be returned
index ce18108..31da116 100755 (executable)
@@ -35,9 +35,17 @@ example, 'set' is a 'list'.
 
 """
 
-from ganeti.tools.cfgupgrade import CfgUpgrade, ParseOptions
+from ganeti.tools.cfgupgrade import CfgUpgrade, Error, ParseOptions
 
 
 if __name__ == "__main__":
   opts, args = ParseOptions()
-  CfgUpgrade(opts, args).Run()
+  try:
+    CfgUpgrade(opts, args).Run()
+  except Error as e:
+    if opts.debug:
+      # If debugging, we want to see the original stack trace.
+      raise
+    else:
+      # Else silence it for the sake of convenience.
+      raise SystemExit(e)
index 08ade62..530124b 100644 (file)
@@ -51,12 +51,15 @@ def main():
 
   version = utils.version.ParseVersion(versionstring)
 
+  error_code = 0
+
   if utils.version.IsBefore(version, 2, 12, 5):
     result = utils.RunCmd(["gnt-cluster", "renew-crypto",
                            "--new-node-certificates", "-f"])
     if result.failed:
       cli.ToStderr("Failed to create node certificates: %s; Output %s" %
                    (result.fail_reason, result.output))
+      error_code = 1
 
   if utils.version.IsBefore(version, 2, 13, 0):
     result = utils.RunCmd(["gnt-cluster", "renew-crypto",
@@ -64,8 +67,9 @@ def main():
     if result.failed:
       cli.ToStderr("Failed to create SSH keys: %s; Output %s" %
                    (result.fail_reason, result.output))
+      error_code = 1
 
-  return 0
+  return error_code
 
 if __name__ == "__main__":
   exit(main())