CLOUDSTACK-4832. Added support for https to marvin.

advanced.cfg: Contains three additional flags "useHttps,certCAPath,certPath"
for https usage in marvin for establishing cs connection. We will use the
configuraiton under advanced.cfg provided by user to establish connection over
https. If establishing the connection over https failed, then the default certs
will be used.  or else raise the exception, the existing http will work as it
is when useHttps flag set to "False"

Signed-off-by: Santhosh Edukulla <santhosh.eduku...@citrix.com>
Signed-off-by: Prasanna Santhanam <t...@apache.org>

Conflicts:
        tools/marvin/marvin/cloudstackConnection.py


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/6e1821f5
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/6e1821f5
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/6e1821f5

Branch: refs/heads/4.2
Commit: 6e1821f585df5c643873ab0ce1e7d91d1d94f00d
Parents: 0f0889a
Author: Santhosh Edukulla <santhosh.eduku...@citrix.com>
Authored: Fri Oct 11 23:27:35 2013 +0530
Committer: Girish Shilamkar <gir...@clogeny.com>
Committed: Fri Nov 8 14:40:58 2013 +0530

----------------------------------------------------------------------
 setup/dev/advanced.cfg                      |  6 +-
 tools/marvin/marvin/cloudstackConnection.py | 76 ++++++++++++++++++------
 tools/marvin/marvin/cloudstackTestClient.py |  8 +--
 tools/marvin/marvin/configGenerator.py      |  9 ++-
 tools/marvin/marvin/deployDataCenter.py     | 35 +++++------
 5 files changed, 84 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6e1821f5/setup/dev/advanced.cfg
----------------------------------------------------------------------
diff --git a/setup/dev/advanced.cfg b/setup/dev/advanced.cfg
index 4a48399..dfaba00 100644
--- a/setup/dev/advanced.cfg
+++ b/setup/dev/advanced.cfg
@@ -14,7 +14,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
 {
     "zones": [
         {
@@ -220,7 +219,10 @@
             "passwd": "password",
             "user": "root",
             "port": 8096,
-            "hypervisor" : "simulator"
+            "hypervisor": "simulator",
+       "useHttps": "True",
+       "certCAPath":  "NA",
+       "certPath":  "NA"
         }
     ]
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6e1821f5/tools/marvin/marvin/cloudstackConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackConnection.py 
b/tools/marvin/marvin/cloudstackConnection.py
index 8129396..e0671c9 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -34,28 +34,27 @@ from requests import RequestException
 class cloudConnection(object):
     """ Connections to make API calls to the cloudstack management server
     """
-    def __init__(self, mgtSvr, port=8096, user=None, passwd=None,
-                 apiKey=None, securityKey=None,
-                 asyncTimeout=3600, logging=None, scheme='http',
-                 path='client/api'):
+    def __init__(self, mgmtDet,asyncTimeout=3600, logging=None, 
scheme='http',path='client/api'):
         self.loglevel()  # Turn off requests logs
-        self.apiKey = apiKey
-        self.securityKey = securityKey
-        self.mgtSvr = mgtSvr
-        self.port = port
-        self.user = user
-        self.passwd = passwd
+        self.apiKey = mgmtDet.apiKey
+        self.securityKey = mgmtDet.securityKey
+        self.mgtSvr = mgmtDet.mgtSvrIp
+        self.port = mgmtDet.port
+        self.user = mgmtDet.user
+        self.passwd = mgmtDet.passwd
+        self.certCAPath = mgmtDet.certCAPath
+        self.certPath = mgmtDet.certPath
         self.logging = logging
         self.path = path
         self.retries = 5
+        self.protocol = "http"
         self.asyncTimeout = asyncTimeout
         self.auth = True
-        if port == 8096 or \
+        if self.port == 8096 or \
            (self.apiKey is None and self.securityKey is None):
             self.auth = False
-        if scheme not in ['http', 'https']:
-                raise RequestException("Protocol must be HTTP")
-        self.protocol = scheme
+        if mgmtDet.useHttps == "True":
+           self.protocol = "https"
         self.baseurl = "%s://%s:%d/%s"\
                        % (self.protocol, self.mgtSvr, self.port, self.path)
 
@@ -143,13 +142,49 @@ class cloudConnection(object):
             payload["signature"] = signature
 
         try:
-            if method == 'POST':
-                response = requests.post(self.baseurl, params=payload)
+            '''
+            https_flag : Signifies whether to verify connection over http or 
https, 
+                         if set to true uses https otherwise http
+            cert_path  : Signifies ca and cert path required by requests 
library for the connection
+            '''
+            https_flag  = False
+            cert_path    = ()
+            if self.protocol == "https":
+                https_flag = True
+                if self.certCAPath != "NA" and self.certPath  != "NA":
+                    cert_path = ( self.certCAPath,self.certPath )
+
+            '''
+            Verify whether protocol is "http", then call the request over http
+            '''
+            if self.protocol == "http":
+               if method == 'POST':
+                   response = requests.post(self.baseurl, params=payload, 
verify=https_flag)
+               else:
+                   response = requests.get(self.baseurl, params=payload,  
verify=https_flag)
             else:
-                response = requests.get(self.baseurl, params=payload)
+                '''
+                If protocol is https, then request the url with user provided 
certificates provided as part of cert
+                '''
+                try:
+                   if method == 'POST':
+                       response = requests.post(self.baseurl, params=payload, 
cert=cert_path, verify=https_flag)
+                   else:
+                       response = requests.get(self.baseurl, params=payload,  
cert=cert_path, verify=https_flag)
+                except Exception,e:
+                    '''
+                    If an exception occurs with current CA certs,\
+                     then try with default certs path, we dont need \
+                    to mention here the cert path
+                    '''
+                    self.logging.debug( "Creating CS connection over https \
+                                        didnt worked with user provided certs 
%s"%e )
+                    if method == 'POST':
+                        response = requests.post(self.baseurl, params=payload, 
verify=https_flag)
+                    else:
+                        response = requests.get(self.baseurl, params=payload,  
verify=https_flag)
         except ConnectionError, c:
-            self.logging.debug("Connection refused. Reason: %s : %s" %
-                               (self.baseurl, c))
+            self.logging.debug("Connection refused. Reason: %s : %s" 
%(self.baseurl, c))
             raise c
         except HTTPError, h:
             self.logging.debug("Server returned error code: %s" % h)
@@ -160,6 +195,9 @@ class cloudConnection(object):
         except RequestException, r:
             self.logging.debug("Error returned by server %s" % r)
             raise r
+        except Exception, e:
+            self.logging.debug("Error returned by server %s" % e)
+            raise e
         else:
             return response
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6e1821f5/tools/marvin/marvin/cloudstackTestClient.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackTestClient.py 
b/tools/marvin/marvin/cloudstackTestClient.py
index d9fa206..8d16cc1 100644
--- a/tools/marvin/marvin/cloudstackTestClient.py
+++ b/tools/marvin/marvin/cloudstackTestClient.py
@@ -37,13 +37,9 @@ from configGenerator import ConfigManager
 
 
 class cloudstackTestClient(object):
-    def __init__(self, mgtSvr=None, port=8096, user=None, passwd=None,
-                 apiKey=None, securityKey=None, asyncTimeout=3600,
-                 defaultWorkerThreads=10, logging=None):
+    def __init__(self,mgmtDetails,asyncTimeout=3600,defaultWorkerThreads=10, 
logging=None):
         self.connection = \
-            cloudstackConnection.cloudConnection(mgtSvr, port, user, passwd,
-                                                 apiKey, securityKey,
-                                                 asyncTimeout, logging)
+            cloudstackConnection.cloudConnection( 
mgmtDetails,asyncTimeout,logging)
         self.apiClient =\
             cloudstackAPIClient.CloudStackAPIClient(self.connection)
         self.dbConnection = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6e1821f5/tools/marvin/marvin/configGenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/configGenerator.py 
b/tools/marvin/marvin/configGenerator.py
index 590b64f..eb8dc2c 100644
--- a/tools/marvin/marvin/configGenerator.py
+++ b/tools/marvin/marvin/configGenerator.py
@@ -28,6 +28,9 @@ class managementServer(object):
         self.port = 8096
         self.apiKey = None
         self.securityKey = None
+   self.useHttps = None
+   self.certCAPath = None
+   self.certPath = None
 
 
 class dbServer(object):
@@ -951,7 +954,7 @@ def generate_setup_config(config, file=None):
 def get_setup_config(file):
     if not os.path.exists(file):
         raise IOError("config file %s not found. \
-please specify a valid config file" % file)
+                      please specify a valid config file" % file)
     config = cloudstackConfiguration()
     configLines = []
     with open(file, 'r') as fp:
@@ -959,7 +962,9 @@ please specify a valid config file" % file)
             ws = line.strip()
             if not ws.startswith("#"):
                 configLines.append(ws)
-    config = json.loads("\n".join(configLines))
+    k = json.loads("\n".join(configLines))
+    #config = json.loads("\n".join(configLines))
+    config = k
     return jsonHelper.jsonLoader(config)
 
 if __name__ == "__main__":

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6e1821f5/tools/marvin/marvin/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployDataCenter.py 
b/tools/marvin/marvin/deployDataCenter.py
index 8cc9cd4..efb4150 100644
--- a/tools/marvin/marvin/deployDataCenter.py
+++ b/tools/marvin/marvin/deployDataCenter.py
@@ -512,11 +512,9 @@ specify a valid config file" % cfgFile)
         try:
             self.config = configGenerator.get_setup_config(self.configFile)
         except:
-            raise cloudstackException.InvalidParameterException(
-                "Failed to load config %s" % self.configFile)
-
-        mgt = self.config.mgtSvr[0]
+            raise cloudstackException.InvalidParameterException("Failed to 
load config %s" % self.configFile)
 
+        mgtDetails = self.config.mgtSvr[0]
         loggers = self.config.logger
         testClientLogFile = None
         self.testCaseLogFile = None
@@ -535,38 +533,35 @@ specify a valid config file" % cfgFile)
             testClientLogger = logging.getLogger("testclient.testengine.run")
             fh = logging.FileHandler(testClientLogFile)
             fh.setFormatter(logging.
-                            Formatter("%(asctime)s - %(levelname)s - %(name)s\
- - %(message)s"))
+            Formatter("%(asctime)s - %(levelname)s - %(name)s\
+           - %(message)s"))
             testClientLogger.addHandler(fh)
             testClientLogger.setLevel(logging.INFO)
         self.testClientLogger = testClientLogger
 
         self.testClient = \
             cloudstackTestClient.\
-            cloudstackTestClient(mgt.mgtSvrIp, mgt.port, mgt.user, mgt.passwd,
-                                 mgt.apiKey, mgt.securityKey,
-                                 logging=self.testClientLogger)
-        if mgt.apiKey is None:
-            apiKey, securityKey = self.registerApiKey()
-            self.testClient = cloudstackTestClient.cloudstackTestClient(
-                mgt.mgtSvrIp, 8080,
-                mgt.user, mgt.passwd,
-                apiKey, securityKey,
-                logging=self.testClientLogger)
+            cloudstackTestClient( mgtDetails,logging=self.testClientLogger)
+
+        if mgtDetails.apiKey is None:
+           mgtDetails.apiKey,mgtDetails.securityKey = self.registerApiKey()
+           mgtDetails.port  = 8080
+                self.testClient = cloudstackTestClient.cloudstackTestClient( 
mgtDetails,logging=self.testClientLogger)
 
         """config database"""
         dbSvr = self.config.dbSvr
         if dbSvr is not None:
-            self.testClient.dbConfigure(dbSvr.dbSvr, dbSvr.port, dbSvr.user,
+            self.testClient.dbConfigure(dbSvr.dbSvr, dbSvr.port, dbSvr.user, \
                                         dbSvr.passwd, dbSvr.db)
 
         self.apiClient = self.testClient.getApiClient()
         """set hypervisor"""
-        if mgt.hypervisor:
-            self.apiClient.hypervisor = mgt.hypervisor
+        if mgtDetails.hypervisor:
+            self.apiClient.hypervisor = mgtDetails.hypervisor
         else:
             self.apiClient.hypervisor = "XenServer"  # Defaults to Xenserver
 
+
     def updateConfiguration(self, globalCfg):
         if globalCfg is None:
             return None
@@ -578,7 +573,6 @@ specify a valid config file" % cfgFile)
             self.apiClient.updateConfiguration(updateCfg)
 
     def copyAttributesToCommand(self, source, command):
-
         map(lambda attr: setattr(command, attr, getattr(source, attr, None)),
             filter(lambda attr: not attr.startswith("__") and
             attr not in ["required", "isAsync"], dir(command)))
@@ -586,7 +580,6 @@ specify a valid config file" % cfgFile)
     def configureS3(self, s3):
         if s3 is None:
             return
-
         command = addS3.addS3Cmd()
         self.copyAttributesToCommand(s3, command)
         self.apiClient.addS3(command)

Reply via email to