From 2771835cd1d9c80b2b3f1f376e699ac609313845 Mon Sep 17 00:00:00 2001
From: Michael Hanselmann <hansmi@google.com>
Date: Mon, 10 May 2010 17:26:32 +0200
Subject: [PATCH] RAPI QA: Use RAPI client

Signed-off-by: Michael Hanselmann <hansmi@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>
---
 qa/ganeti-qa.py |   5 ++-
 qa/qa_rapi.py   | 111 ++++++++++++++----------------------------------
 2 files changed, 35 insertions(+), 81 deletions(-)

diff --git a/qa/ganeti-qa.py b/qa/ganeti-qa.py
index 64026c606..b3c7d91e5 100755
--- a/qa/ganeti-qa.py
+++ b/qa/ganeti-qa.py
@@ -281,10 +281,13 @@ def main():
 
   rapi_user = "ganeti-qa"
   rapi_secret = utils.GenerateSecret()
-  qa_rapi.OpenerFactory.SetCredentials(rapi_user, rapi_secret)
 
   RunEnvTests()
   SetupCluster(rapi_user, rapi_secret)
+
+  # Load RAPI certificate
+  qa_rapi.Setup(rapi_user, rapi_secret)
+
   RunClusterTests()
   RunOsTests()
 
diff --git a/qa/qa_rapi.py b/qa/qa_rapi.py
index cefed6614..639f62a92 100644
--- a/qa/qa_rapi.py
+++ b/qa/qa_rapi.py
@@ -22,12 +22,17 @@
 
 """
 
-import urllib2
+import tempfile
 
 from ganeti import utils
 from ganeti import constants
 from ganeti import errors
 from ganeti import serializer
+from ganeti import cli
+from ganeti import rapi
+
+import ganeti.rapi.client
+import ganeti.rapi.client_utils
 
 import qa_config
 import qa_utils
@@ -37,58 +42,38 @@ from qa_utils import (AssertEqual, AssertNotEqual, AssertIn, AssertMatch,
                       StartSSH)
 
 
-class OpenerFactory:
-  """A factory singleton to construct urllib opener chain.
-
-  This is needed because qa_config is not initialized yet at module load time
-
-  """
-  _opener = None
-  _rapi_user = None
-  _rapi_secret = None
-
-  @classmethod
-  def SetCredentials(cls, rapi_user, rapi_secret):
-    """Set the credentials for authorized access.
-
-    """
-    cls._rapi_user = rapi_user
-    cls._rapi_secret = rapi_secret
+_rapi_ca = None
+_rapi_client = None
 
-  @classmethod
-  def Opener(cls):
-    """Construct the opener if not yet done.
 
-    """
-    if not cls._opener:
-      if not cls._rapi_user or not cls._rapi_secret:
-        raise errors.ProgrammerError("SetCredentials was never called.")
+def Setup(username, password):
+  """Configures the RAPI client.
 
-      # Create opener which doesn't try to look for proxies and does auth
-      master = qa_config.GetMasterNode()
-      host = master["primary"]
-      port = qa_config.get("rapi-port", default=constants.DEFAULT_RAPI_PORT)
-      passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
-      passman.add_password(None, 'https://%s:%s' % (host, port),
-                           cls._rapi_user,
-                           cls._rapi_secret)
-      authhandler = urllib2.HTTPBasicAuthHandler(passman)
-      cls._opener = urllib2.build_opener(urllib2.ProxyHandler({}), authhandler)
+  """
+  global _rapi_ca
+  global _rapi_client
 
-    return cls._opener
+  master = qa_config.GetMasterNode()
 
+  # Load RAPI certificate from master node
+  cmd = ["cat", constants.RAPI_CERT_FILE]
 
-class RapiRequest(urllib2.Request):
-  """This class supports other methods beside GET/POST.
+  # Write to temporary file
+  _rapi_ca = tempfile.NamedTemporaryFile()
+  _rapi_ca.write(qa_utils.GetCommandOutput(master["primary"],
+                                           utils.ShellQuoteArgs(cmd)))
+  _rapi_ca.flush()
 
-  """
+  port = qa_config.get("rapi-port", default=constants.DEFAULT_RAPI_PORT)
+  cfg_ssl = rapi.client.CertAuthorityVerify(cafile=_rapi_ca.name)
 
-  def __init__(self, method, url, headers, data):
-    urllib2.Request.__init__(self, url, data=data, headers=headers)
-    self._method = method
+  _rapi_client = rapi.client.GanetiRapiClient(master["primary"], port=port,
+                                              username=username,
+                                              password=password,
+                                              config_ssl_verification=cfg_ssl,
+                                              ignore_proxy=True)
 
-  def get_method(self):
-    return self._method
+  print "RAPI protocol version: %s" % _rapi_client.GetVersion()
 
 
 INSTANCE_FIELDS = ("name", "os", "pnode", "snodes",
@@ -119,43 +104,12 @@ def Enabled():
 
 
 def _DoTests(uris):
-  master = qa_config.GetMasterNode()
-  host = master["primary"]
-  port = qa_config.get("rapi-port", default=constants.DEFAULT_RAPI_PORT)
   results = []
 
   for uri, verify, method, body in uris:
     assert uri.startswith("/")
 
-    url = "https://%s:%s%s" % (host, port, uri)
-
-    headers = {}
-
-    if body:
-      data = serializer.DumpJson(body, indent=False)
-      headers["Content-Type"] = "application/json"
-    else:
-      data = None
-
-    if headers or data:
-      details = []
-      if headers:
-        details.append("headers=%s" %
-                       serializer.DumpJson(headers, indent=False).rstrip())
-      if data:
-        details.append("data=%s" % data.rstrip())
-      info = "(%s)" % (", ".join(details), )
-    else:
-      info = ""
-
-    print "Testing %s %s %s..." % (method, url, info)
-
-    req = RapiRequest(method, url, headers, data)
-    response = OpenerFactory.Opener().open(req)
-
-    AssertEqual(response.info()["Content-type"], "application/json")
-
-    data = serializer.LoadJson(response.read())
+    data = _rapi_client._SendRequest(method, uri, None, body)
 
     if verify is not None:
       if callable(verify):
@@ -305,10 +259,7 @@ def _WaitForRapiJob(job_id):
     ("/2/jobs/%s" % job_id, _VerifyJob, "GET", None),
     ])
 
-  # FIXME: Use "gnt-job watch" until RAPI supports waiting for job
-  cmd = ["gnt-job", "watch", str(job_id)]
-  AssertEqual(StartSSH(master["primary"],
-                       utils.ShellQuoteArgs(cmd)).wait(), 0)
+  rapi.client_utils.PollJob(_rapi_client, job_id, cli.StdioJobPollReportCb())
 
 
 def TestRapiInstanceAdd(node):
-- 
GitLab