From a1de4b18bb064ae7515a94f4766fc6a6dc89ef9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Nussbaumer?= <rn@google.com>
Date: Tue, 14 Dec 2010 17:15:18 +0100
Subject: [PATCH] QA: Add some basic OOB tests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: RenΓ© Nussbaumer <rn@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 qa/ganeti-qa.py   |   1 +
 qa/qa-sample.json |   3 +-
 qa/qa_node.py     | 133 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/qa/ganeti-qa.py b/qa/ganeti-qa.py
index c350571f1..1089567fb 100755
--- a/qa/ganeti-qa.py
+++ b/qa/ganeti-qa.py
@@ -238,6 +238,7 @@ def RunCommonNodeTests():
   """
   RunTestIf("node-volumes", qa_node.TestNodeVolumes)
   RunTestIf("node-storage", qa_node.TestNodeStorage)
+  RunTestIf("node-oob", qa_node.TestOutOfBand)
 
 
 def RunGroupListTests():
diff --git a/qa/qa-sample.json b/qa/qa-sample.json
index 8c42c3081..911662a0a 100644
--- a/qa/qa-sample.json
+++ b/qa/qa-sample.json
@@ -40,7 +40,7 @@
       "group2",
       "group3"
     ]
-  }
+  },
 
   "tests": {
     "env": true,
@@ -71,6 +71,7 @@
     "node-readd": true,
     "node-storage": true,
     "node-modify": true,
+    "node-oob": true,
 
     "# This test needs at least three nodes": null,
     "node-evacuate": false,
diff --git a/qa/qa_node.py b/qa/qa_node.py
index 6e3e0a7a6..c29f49176 100644
--- a/qa/qa_node.py
+++ b/qa/qa_node.py
@@ -22,6 +22,7 @@
 from ganeti import utils
 from ganeti import constants
 from ganeti import query
+from ganeti import serializer
 
 import qa_config
 import qa_error
@@ -192,6 +193,138 @@ def TestNodeModify(node):
                  "--auto-promote", node["primary"]])
 
 
+def _CreateOobScriptStructure():
+  """Create a simple OOB handling script and its structure."""
+  master = qa_config.GetMasterNode()
+
+  data_path = qa_utils.UploadData(master["primary"], "")
+  verify_path = qa_utils.UploadData(master["primary"], "")
+  exit_code_path = qa_utils.UploadData(master["primary"], "")
+
+  oob_script = (("#!/bin/bash\n"
+                 "echo \"$@\" > %s\n"
+                 "cat %s\n"
+                 "exit $(< %s)\n") %
+                (utils.ShellQuote(verify_path), utils.ShellQuote(data_path),
+                 utils.ShellQuote(exit_code_path)))
+  oob_path = qa_utils.UploadData(master["primary"], oob_script, mode=0700)
+
+  return [oob_path, verify_path, data_path, exit_code_path]
+
+
+def _UpdateOobFile(path, data):
+  """Updates the data file with data."""
+  master = qa_config.GetMasterNode()
+  qa_utils.UploadData(master["primary"], data, filename=path)
+
+
+def _AssertOobCall(verify_path, expected_args):
+  """Assert the OOB call was performed with expetected args."""
+  master = qa_config.GetMasterNode()
+
+  verify_output_cmd = utils.ShellQuoteArgs(["cat", verify_path])
+  output = qa_utils.GetCommandOutput(master["primary"], verify_output_cmd)
+
+  qa_utils.AssertEqual(expected_args, output.strip())
+
+
+def TestOutOfBand():
+  """gnt-node power"""
+  master = qa_config.GetMasterNode()
+
+  (oob_path, verify_path,
+   data_path, exit_code_path) = _CreateOobScriptStructure()
+
+  try:
+    AssertCommand(["gnt-cluster", "modify", "--node-parameters",
+                   "oob_program=%s" % oob_path])
+
+    # No data, exit 0
+    _UpdateOobFile(exit_code_path, "0")
+
+    AssertCommand(["gnt-node", "power", "on", master["primary"]])
+    _AssertOobCall(verify_path, "power-on %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "off", master["primary"]])
+    _AssertOobCall(verify_path, "power-off %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "cycle", master["primary"]])
+    _AssertOobCall(verify_path, "power-cycle %s" % master["primary"])
+
+    # This command should fail as it expects output which isn't provided yet
+    # But it should have called the oob helper nevermind
+    AssertCommand(["gnt-node", "power", "status", master["primary"]],
+                  fail=True)
+    _AssertOobCall(verify_path, "power-status %s" % master["primary"])
+
+    # Data, exit 0
+    _UpdateOobFile(data_path, serializer.DumpJson({ "powered": True }))
+
+    AssertCommand(["gnt-node", "power", "status", master["primary"]])
+    _AssertOobCall(verify_path, "power-status %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "on", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-on %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "off", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-off %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "cycle", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-cycle %s" % master["primary"])
+
+    # Data, exit 1 (all should fail)
+    _UpdateOobFile(exit_code_path, "1")
+
+    AssertCommand(["gnt-node", "power", "on", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-on %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "off", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-off %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "cycle", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-cycle %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "status", master["primary"]],
+                  fail=True)
+    _AssertOobCall(verify_path, "power-status %s" % master["primary"])
+
+    # No data, exit 1 (all should fail)
+    _UpdateOobFile(data_path, "")
+    AssertCommand(["gnt-node", "power", "on", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-on %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "off", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-off %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "cycle", master["primary"]], fail=True)
+    _AssertOobCall(verify_path, "power-cycle %s" % master["primary"])
+
+    AssertCommand(["gnt-node", "power", "status", master["primary"]],
+                  fail=True)
+    _AssertOobCall(verify_path, "power-status %s" % master["primary"])
+
+    # Different OOB script for node
+    verify_path2 = qa_utils.UploadData(master["primary"], "")
+    oob_script = ("#!/bin/sh\n"
+                  "echo \"$@\" > %s\n") % verify_path2
+    oob_path2 = qa_utils.UploadData(master["primary"], oob_script, mode=0700)
+
+    try:
+      AssertCommand(["gnt-node", "modify", "--node-parameters",
+                     "oob_program=%s" % oob_path2, master["primary"]])
+      AssertCommand(["gnt-node", "power", "on", master["primary"]])
+      _AssertOobCall(verify_path2, "power-on %s" % master["primary"])
+    finally:
+      AssertCommand(["gnt-node", "modify", "--node-parameters",
+                     "oob_program=default", master["primary"]])
+      AssertCommand(["rm", "-f", oob_path2, verify_path2])
+  finally:
+    AssertCommand(["gnt-cluster", "modify", "--node-parameters",
+                   "oob_program=default"])
+    AssertCommand(["rm", "-f", oob_path, verify_path, data_path,
+                   exit_code_path])
+
+
 def TestNodeList():
   """gnt-node list"""
   qa_utils.GenericQueryTest("gnt-node", query.NODE_FIELDS.keys())
-- 
GitLab