You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bf...@apache.org on 2013/04/26 21:38:21 UTC

[08/21] git commit: updated refs/heads/ui-add-remove-nics to b7b7753

Multiple fixes to marvin framework

1. adding hypervisor information to configs
    TODO: support for multi-hypervisor zones?
2. CLOUDSTACK-601: Marvin unicode decode errors when running mysql
queries via dbClient
3. adding keypair support for remotessh client

Signed-off-by: Prasanna Santhanam <ts...@apache.org>


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

Branch: refs/heads/ui-add-remove-nics
Commit: 2f40a90c53067c3901cf9e5c9a33309907e48aab
Parents: f429c66
Author: Ashutosh Kelkar <as...@clogeny.com>
Authored: Wed Apr 24 15:03:10 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Fri Apr 26 12:16:08 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/asyncJobMgr.py           |   70 ++-
 tools/marvin/marvin/cloudstackConnection.py  |   17 +-
 tools/marvin/marvin/cloudstackTestClient.py  |   53 ++-
 tools/marvin/marvin/dbConnection.py          |    6 +-
 tools/marvin/marvin/deployDataCenter.py      |    7 +
 tools/marvin/marvin/integration/lib/base.py  |  600 +++++++++++++++++++--
 tools/marvin/marvin/integration/lib/utils.py |   17 +-
 tools/marvin/marvin/remoteSSHClient.py       |   18 +-
 8 files changed, 669 insertions(+), 119 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/asyncJobMgr.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/asyncJobMgr.py b/tools/marvin/marvin/asyncJobMgr.py
index 40304fa..6984627 100644
--- a/tools/marvin/marvin/asyncJobMgr.py
+++ b/tools/marvin/marvin/asyncJobMgr.py
@@ -28,6 +28,8 @@ class job(object):
     def __init__(self):
         self.id = None
         self.cmd = None
+
+
 class jobStatus(object):
     def __init__(self):
         self.result = None
@@ -37,8 +39,11 @@ class jobStatus(object):
         self.duration = None
         self.jobId = None
         self.responsecls = None
+
     def __str__(self):
         return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
+
+
 class workThread(threading.Thread):
     def __init__(self, in_queue, outqueue, apiClient, db=None, lock=None):
         threading.Thread.__init__(self)
@@ -47,11 +52,11 @@ class workThread(threading.Thread):
         self.connection = apiClient.connection.__copy__()
         self.db = None
         self.lock = lock
-        
+
     def queryAsynJob(self, job):
         if job.jobId is None:
             return job
-        
+
         try:
             self.lock.acquire()
             result = self.connection.poll(job.jobId, job.responsecls).jobresult
@@ -59,10 +64,10 @@ class workThread(threading.Thread):
             result = str(e)
         finally:
             self.lock.release()
-            
+
         job.result = result
         return job
-        
+
     def executeCmd(self, job):
         cmd = job.cmd
 
@@ -70,14 +75,15 @@ class workThread(threading.Thread):
         jobId = None
         try:
             self.lock.acquire()
-            
+
             if cmd.isAsync == "false":
                 jobstatus.startTime = datetime.datetime.now()
-               
+
                 result = self.connection.make_request(cmd)
                 jobstatus.result = result
                 jobstatus.endTime = datetime.datetime.now()
-                jobstatus.duration = time.mktime(jobstatus.endTime.timetuple()) - time.mktime(jobstatus.startTime.timetuple())
+                jobstatus.duration = time.mktime(jobstatus.endTime.timetuple()) - time.mktime(
+                    jobstatus.startTime.timetuple())
             else:
                 result = self.connection.make_request(cmd, None, True)
                 if result is None:
@@ -99,9 +105,9 @@ class workThread(threading.Thread):
             jobstatus.result = sys.exc_info()
         finally:
             self.lock.release()
-        
+
         return jobstatus
-    
+
     def run(self):
         while self.inqueue.qsize() > 0:
             job = self.inqueue.get()
@@ -109,18 +115,20 @@ class workThread(threading.Thread):
                 jobstatus = self.queryAsynJob(job)
             else:
                 jobstatus = self.executeCmd(job)
-                
+
             self.output.put(jobstatus)
             self.inqueue.task_done()
-            
+
         '''release the resource'''
         self.connection.close()
 
+
 class jobThread(threading.Thread):
     def __init__(self, inqueue, interval):
         threading.Thread.__init__(self)
         self.inqueue = inqueue
         self.interval = interval
+
     def run(self):
         while self.inqueue.qsize() > 0:
             job = self.inqueue.get()
@@ -130,23 +138,25 @@ class jobThread(threading.Thread):
                 job.apiClient.connection.close()
             except:
                 pass
-            
+
             self.inqueue.task_done()
             time.sleep(self.interval)
-        
+
+
 class outputDict(object):
     def __init__(self):
         self.lock = threading.Condition()
-        self.dict = {}    
+        self.dict = {}
+
 
 class asyncJobMgr(object):
     def __init__(self, apiClient, db):
         self.inqueue = Queue.Queue()
-        self.output = outputDict() 
+        self.output = outputDict()
         self.outqueue = Queue.Queue()
         self.apiClient = apiClient
         self.db = db
-        
+
     def submitCmds(self, cmds):
         if not self.inqueue.empty():
             return False
@@ -160,11 +170,12 @@ class asyncJobMgr(object):
             id += 1
             ids.append(id)
         return ids
-    
+
     def updateTimeStamp(self, jobstatus):
         jobId = jobstatus.jobId
         if jobId is not None and self.db is not None:
-            result = self.db.execute("select job_status, created, last_updated from async_job where id=%s"%jobId)
+            result = self.db.execute(
+                "select job_status, created, last_updated from async_job where id='%s'" % str(jobId))
             if result is not None and len(result) > 0:
                 if result[0][0] == 1:
                     jobstatus.status = True
@@ -174,7 +185,7 @@ class asyncJobMgr(object):
                     jobstatus.endTime = result[0][2]
                     delta = jobstatus.endTime - jobstatus.startTime
                     jobstatus.duration = delta.total_seconds()
-    
+
     def waitForComplete(self, workers=10):
         self.inqueue.join()
         lock = threading.Lock()
@@ -183,28 +194,30 @@ class asyncJobMgr(object):
         for i in range(workers):
             worker = workThread(self.outqueue, resultQueue, self.apiClient, self.db, lock)
             worker.start()
-        
+
         self.outqueue.join()
-        
+
         asyncJobResult = []
         while resultQueue.qsize() > 0:
             jobstatus = resultQueue.get()
             self.updateTimeStamp(jobstatus)
             asyncJobResult.append(jobstatus)
-        
+
         return asyncJobResult
-    
+
     '''put commands into a queue at first, then start workers numbers threads to execute this commands'''
+
     def submitCmdsAndWait(self, cmds, workers=10):
         self.submitCmds(cmds)
         lock = threading.Lock()
         for i in range(workers):
             worker = workThread(self.inqueue, self.outqueue, self.apiClient, self.db, lock)
             worker.start()
-        
+
         return self.waitForComplete(workers)
 
     '''submit one job and execute the same job ntimes, with nums_threads of threads'''
+
     def submitJobExecuteNtimes(self, job, ntimes=1, nums_threads=1, interval=1):
         inqueue1 = Queue.Queue()
         lock = threading.Condition()
@@ -213,22 +226,23 @@ class asyncJobMgr(object):
             setattr(newjob, "apiClient", copy.copy(self.apiClient))
             setattr(newjob, "lock", lock)
             inqueue1.put(newjob)
-        
+
         for i in range(nums_threads):
             work = jobThread(inqueue1, interval)
             work.start()
         inqueue1.join()
-        
+
     '''submit n jobs, execute them with nums_threads of threads'''
+
     def submitJobs(self, jobs, nums_threads=1, interval=1):
         inqueue1 = Queue.Queue()
         lock = threading.Condition()
-    
+
         for job in jobs:
             setattr(job, "apiClient", copy.copy(self.apiClient))
             setattr(job, "lock", lock)
             inqueue1.put(job)
-        
+
         for i in range(nums_threads):
             work = jobThread(inqueue1, interval)
             work.start()

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/cloudstackConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py
index 5d30803..9a4c387 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -33,13 +33,18 @@ from requests import RequestException
 class cloudConnection(object):
     """ Connections to make API calls to the cloudstack management server
     """
-    def __init__(self, mgtSvr, port=8096, apiKey=None, securityKey=None,
+    def __init__(self, mgtSvr, port=8096, user=None, passwd=None,
+                 apiKey=None, securityKey=None,
                  asyncTimeout=3600, logging=None, scheme='http',
                  path='client/api'):
         self.apiKey = apiKey
         self.securityKey = securityKey
         self.mgtSvr = mgtSvr
         self.port = port
+        if user:
+            self.user = user
+        if passwd:
+            self.passwd = passwd
         self.logging = logging
         self.path = path
         self.retries = 5
@@ -55,9 +60,10 @@ class cloudConnection(object):
                        % (self.protocol, self.mgtSvr, self.port, self.path)
 
     def __copy__(self):
-        return cloudConnection(self.mgtSvr, self.port, self.apiKey,
-                               self.securityKey, self.asyncTimeout,
-                               self.logging, self.protocol, self.path)
+        return cloudConnection(self.mgtSvr, self.port, self.user, self.passwd,
+                               self.apiKey, self.securityKey,
+                               self.asyncTimeout, self.logging, self.protocol,
+                               self.path)
 
     def poll(self, jobid, response):
         """
@@ -200,7 +206,8 @@ class cloudConnection(object):
         @return:
         """
         cmdname, isAsync, payload = self.sanitize_command(cmd)
-        self.logging.debug("sending %s request: %s %s" % (method, cmdname, str(payload)))
+        self.logging.debug("sending %s request: %s %s" % (method, cmdname,
+                                                          str(payload)))
         response = self.request(
             cmdname, self.auth, payload=payload, method=method)
         self.logging.debug("Request: %s Response: %s" %

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/cloudstackTestClient.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackTestClient.py b/tools/marvin/marvin/cloudstackTestClient.py
index 85552ed..d85a61c 100644
--- a/tools/marvin/marvin/cloudstackTestClient.py
+++ b/tools/marvin/marvin/cloudstackTestClient.py
@@ -18,24 +18,29 @@
 import cloudstackConnection
 import asyncJobMgr
 import dbConnection
-from cloudstackAPI import * 
+from cloudstackAPI import *
 import random
 import string
 import hashlib
 
 class cloudstackTestClient(object):
-    def __init__(self, mgtSvr=None, port=8096, apiKey = None, securityKey = None, asyncTimeout=3600,
+    def __init__(self, mgtSvr=None, port=8096, user=None, passwd=None,
+                 apiKey=None, securityKey=None, asyncTimeout=3600,
                  defaultWorkerThreads=10, logging=None):
-        self.connection = cloudstackConnection.cloudConnection(mgtSvr, port, apiKey, securityKey, asyncTimeout, logging)
+        self.connection = \
+        cloudstackConnection.cloudConnection(
+                                    mgtSvr, port, user,
+                                    passwd, apiKey, securityKey,
+                                    asyncTimeout, logging)
         self.apiClient = cloudstackAPIClient.CloudStackAPIClient(self.connection)
         self.dbConnection = None
         self.asyncJobMgr = None
         self.ssh = None
         self.defaultWorkerThreads = defaultWorkerThreads
-        
+
     def dbConfigure(self, host="localhost", port=3306, user='cloud', passwd='cloud', db='cloud'):
         self.dbConnection = dbConnection.dbConnection(host, port, user, passwd, db)
-    
+
     def isAdminContext(self):
         """
         A user is a regular user if he fails to listDomains;
@@ -53,7 +58,7 @@ class cloudstackTestClient(object):
                 return 2 #domain-admin
         except:
             return 0 #user
-    
+
     def random_gen(self, size=6, chars=string.ascii_uppercase + string.digits):
         """Generate Random Strings of variable length"""
         return ''.join(random.choice(chars) for x in range(size))
@@ -61,7 +66,7 @@ class cloudstackTestClient(object):
     def createUserApiClient(self, UserName, DomainName, acctType=0):
         if not self.isAdminContext():
             return self.apiClient
-        
+
         listDomain = listDomains.listDomainsCmd()
         listDomain.listall = True
         listDomain.name = DomainName
@@ -73,11 +78,11 @@ class cloudstackTestClient(object):
             cdomain.name = DomainName
             domain = self.apiClient.createDomain(cdomain)
             domId = domain.id
-            
+
         mdf = hashlib.md5()
         mdf.update("password")
         mdf_pass = mdf.hexdigest()
-        
+
         cmd = listAccounts.listAccountsCmd()
         cmd.name = UserName
         cmd.domainid = domId
@@ -95,46 +100,47 @@ class cloudstackTestClient(object):
             createAcctCmd.username = UserName
             acct = self.apiClient.createAccount(createAcctCmd)
             acctId = acct.id
-        
-        listuser = listUsers.listUsersCmd() 
+
+        listuser = listUsers.listUsersCmd()
         listuser.username = UserName
-        
+
         listuserRes = self.apiClient.listUsers(listuser)
         userId = listuserRes[0].id
         apiKey = listuserRes[0].apikey
         securityKey = listuserRes[0].secretkey
-     
+
         if apiKey is None:
             registerUser = registerUserKeys.registerUserKeysCmd()
             registerUser.id = userId
             registerUserRes = self.apiClient.registerUserKeys(registerUser)
             apiKey = registerUserRes.apikey
             securityKey = registerUserRes.secretkey
-        
+
         newUserConnection = cloudstackConnection.cloudConnection(self.connection.mgtSvr, self.connection.port,
+            self.connection.user, self.connection.passwd,
             apiKey, securityKey, self.connection.asyncTimeout, self.connection.logging)
         self.userApiClient = cloudstackAPIClient.CloudStackAPIClient(newUserConnection)
         self.userApiClient.connection = newUserConnection
         return self.userApiClient
-        
+
     def close(self):
         if self.connection is not None:
             self.connection.close()
-        
+
     def getDbConnection(self):
         return self.dbConnection
 
     def executeSql(self, sql=None):
         if sql is None or self.dbConnection is None:
             return None
-        
+
         return self.dbConnection.execute()
-    
+
     def executeSqlFromFile(self, sqlFile=None):
         if sqlFile is None or self.dbConnection is None:
             return None
         return self.dbConnection.executeSqlFromFile(sqlFile)
-    
+
     def getApiClient(self):
         return self.apiClient
 
@@ -151,18 +157,21 @@ class cloudstackTestClient(object):
 
 
     '''FixME, httplib has issue if more than one thread submitted'''
+
     def submitCmdsAndWait(self, cmds, workers=1):
         if self.asyncJobMgr is None:
             self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)
         return self.asyncJobMgr.submitCmdsAndWait(cmds, workers)
-    
+
     '''submit one job and execute the same job ntimes, with nums_threads of threads'''
+
     def submitJob(self, job, ntimes=1, nums_threads=10, interval=1):
         if self.asyncJobMgr is None:
             self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)
         self.asyncJobMgr.submitJobExecuteNtimes(job, ntimes, nums_threads, interval)
-        
-    '''submit n jobs, execute them with nums_threads of threads'''    
+
+    '''submit n jobs, execute them with nums_threads of threads'''
+
     def submitJobs(self, jobs, nums_threads=10, interval=1):
         if self.asyncJobMgr is None:
             self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/dbConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/dbConnection.py b/tools/marvin/marvin/dbConnection.py
index 8fa8643..958299a 100644
--- a/tools/marvin/marvin/dbConnection.py
+++ b/tools/marvin/marvin/dbConnection.py
@@ -37,7 +37,11 @@ class dbConnection(object):
             return None
 
         resultRow = []
-        with contextlib.closing(mysql.connector.connect(host=self.host, port=self.port, user=self.user, password=self.passwd, db=self.database)) as conn:
+        with contextlib.closing(mysql.connector.connect(host=str(self.host),
+                                                        port=int(self.port),
+                                                        user=str(self.user),
+                                                        password=str(self.passwd),
+                                                        db=str(self.database))) as conn:
             conn.autocommit = True
             with contextlib.closing(conn.cursor(buffered=True)) as cursor:
                 cursor.execute(sql, params)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py
index d358789..5ca1ebf 100644
--- a/tools/marvin/marvin/deployDataCenter.py
+++ b/tools/marvin/marvin/deployDataCenter.py
@@ -402,6 +402,7 @@ class deployDataCenters():
 
         self.testClient = \
         cloudstackTestClient.cloudstackTestClient(mgt.mgtSvrIp, mgt.port, \
+                                                  mgt.user, mgt.passwd, \
                                                   mgt.apiKey, \
                                                   mgt.securityKey, \
                                             logging=self.testClientLogger)
@@ -409,6 +410,7 @@ class deployDataCenters():
             apiKey, securityKey = self.registerApiKey()
             self.testClient = \
             cloudstackTestClient.cloudstackTestClient(mgt.mgtSvrIp, 8080, \
+                                                      mgt.user, mgt.passwd, \
                                                       apiKey, securityKey, \
                                              logging=self.testClientLogger)
 
@@ -419,6 +421,11 @@ class deployDataCenters():
                                       dbSvr.passwd, dbSvr.db)
 
         self.apiClient = self.testClient.getApiClient()
+        """set hypervisor"""
+        if mgt.hypervisor:
+            self.apiClient.hypervisor = mgt.hypervisor
+        else:
+            self.apiClient.hypervisor = "XenServer"     #Defaults to Xenserver
 
     def updateConfiguration(self, globalCfg):
         if globalCfg is None:

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/integration/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py
index 6c28523..1d86c6c 100755
--- a/tools/marvin/marvin/integration/lib/base.py
+++ b/tools/marvin/marvin/integration/lib/base.py
@@ -5,9 +5,9 @@
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
-# 
+#
 #   http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -22,7 +22,7 @@
 import marvin
 from utils import is_server_ssh_ready, random_gen
 from marvin.cloudstackAPI import *
-#Import System modules
+# Import System modules
 import time
 import hashlib
 import base64
@@ -54,8 +54,12 @@ class Domain:
             cmd.parentdomainid = parentdomainid
         elif "parentdomainid" in services:
             cmd.parentdomainid = services["parentdomainid"]
-
-        return Domain(apiclient.createDomain(cmd).__dict__)
+        try:
+            domain = apiclient.createDomain(cmd)
+            if domain is not None:
+                return Domain(domain.__dict__)
+        except Exception as e:
+            raise e
 
     def delete(self, apiclient, cleanup=None):
         """Delete an domain"""
@@ -83,7 +87,7 @@ class Account:
         """Creates an account"""
         cmd = createAccount.createAccountCmd()
 
-        #0 - User, 1 - Root Admin, 2 - Domain Admin
+        # 0 - User, 1 - Root Admin, 2 - Domain Admin
         cmd.accounttype = 2 if (admin and domainid) else int(admin)
 
         cmd.email = services["email"]
@@ -213,14 +217,15 @@ class VirtualMachine:
         else:
             self.ssh_port = 22
         self.ssh_client = None
-        #extract out the ipaddress
+        # extract out the ipaddress
         self.ipaddress = self.nic[0].ipaddress
 
     @classmethod
     def create(cls, apiclient, services, templateid=None, accountid=None,
                     domainid=None, zoneid=None, networkids=None, serviceofferingid=None,
                     securitygroupids=None, projectid=None, startvm=None,
-                    diskofferingid=None, affinitygroupnames=None, hostid=None, mode='basic', method='GET'):
+                    diskofferingid=None, affinitygroupnames=None, group=None,
+                    hostid=None, keypair=None, mode='basic', method='GET'):
         """Create the instance"""
 
         cmd = deployVirtualMachine.deployVirtualMachineCmd()
@@ -234,7 +239,13 @@ class VirtualMachine:
             cmd.zoneid = zoneid
         elif "zoneid" in services:
             cmd.zoneid = services["zoneid"]
-        cmd.hypervisor = services["hypervisor"]
+        cmd.hypervisor = apiclient.hypervisor
+
+        if "displayname" in services:
+            cmd.displayname = services["displayname"]
+
+        if "name" in services:
+            cmd.name = services["name"]
 
         if accountid:
             cmd.account = accountid
@@ -256,9 +267,16 @@ class VirtualMachine:
         elif "template" in services:
             cmd.templateid = services["template"]
 
-        if "diskoffering" in services:
+        if diskofferingid:
+            cmd.diskofferingid = diskofferingid
+        elif "diskoffering" in services:
             cmd.diskofferingid = services["diskoffering"]
 
+        if keypair:
+            cmd.keypair = keypair
+        elif "keypair" in services:
+            cmd.keypair = services["keypair"]
+
         if securitygroupids:
             cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids]
 
@@ -282,6 +300,15 @@ class VirtualMachine:
 
         virtual_machine = apiclient.deployVirtualMachine(cmd, method=method)
 
+        if group:
+            cmd.group = group
+        virtual_machine = apiclient.deployVirtualMachine(cmd)
+
+        if startvm == False:
+            virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress
+            virtual_machine.public_ip = virtual_machine.nic[0].ipaddress
+            return VirtualMachine(virtual_machine.__dict__, services)
+
         # VM should be in Running state after deploy
         timeout = 10
         while True:
@@ -308,14 +335,14 @@ class VirtualMachine:
                                            virtual_machine.domainid,
                                            services
                                            )
-            fw_rule = FireWallRule.create(
+            FireWallRule.create(
                                           apiclient,
                                           ipaddressid=public_ip.ipaddress.id,
                                           protocol='TCP',
                                           cidrlist=['0.0.0.0/0'],
                                           startport=22,
                                           endport=22
-                            )
+                               )
             nat_rule = NATRule.create(
                                     apiclient,
                                     virtual_machine,
@@ -348,7 +375,13 @@ class VirtualMachine:
         cmd.id = self.id
         apiclient.rebootVirtualMachine(cmd)
 
-    def get_ssh_client(self, ipaddress=None, reconnect=False, port=None):
+    def recover(self, apiclient):
+        """Recover the instance"""
+        cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
+        cmd.id = self.id
+        apiclient.recoverVirtualMachine(cmd)
+
+    def get_ssh_client(self, ipaddress=None, reconnect=False, port=None, keyPairFileLocation=None):
         """Get SSH object of VM"""
 
         # If NAT Rules are not created while VM deployment in Advanced mode
@@ -358,27 +391,56 @@ class VirtualMachine:
         if port:
             self.ssh_port = port
 
+        if keyPairFileLocation is not None:
+            self.password = None
+
         if reconnect:
             self.ssh_client = is_server_ssh_ready(
                                                     self.ssh_ip,
                                                     self.ssh_port,
                                                     self.username,
-                                                    self.password
+                                                    self.password,
+                                                    keyPairFileLocation=keyPairFileLocation
                                                 )
         self.ssh_client = self.ssh_client or is_server_ssh_ready(
                                                     self.ssh_ip,
                                                     self.ssh_port,
                                                     self.username,
-                                                    self.password
+                                                    self.password,
+                                                    keyPairFileLocation=keyPairFileLocation
                                                 )
         return self.ssh_client
 
+    def resetSshKey(self, apiclient, **kwargs):
+        """Resets SSH key"""
+
+        cmd = resetSSHKeyForVirtualMachine.resetSSHKeyForVirtualMachineCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.resetSSHKeyForVirtualMachine(cmd))
+
+    def update(self, apiclient, **kwargs):
+        """Updates the VM data"""
+
+        cmd = updateVirtualMachine.updateVirtualMachineCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.updateVirtualMachine(cmd))
+
     def delete(self, apiclient):
         """Destroy an Instance"""
         cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
         cmd.id = self.id
         apiclient.destroyVirtualMachine(cmd)
 
+    def migrate(self, apiclient, hostid=None):
+        """migrate an Instance"""
+        cmd = migrateVirtualMachine.migrateVirtualMachineCmd()
+        cmd.virtualmachineid = self.id
+        if hostid:
+            cmd.hostid = hostid
+        apiclient.migrateVirtualMachine(cmd)
+
     def attach_volume(self, apiclient, volume):
         """Attach volume to instance"""
         cmd = attachVolume.attachVolumeCmd()
@@ -394,7 +456,7 @@ class VirtualMachine:
 
     def add_nic(self, apiclient, networkId):
         """Add a NIC to a VM"""
-        cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd();
+        cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd()
         cmd.virtualmachineid = self.id
         cmd.networkid = networkId
         return apiclient.addNicToVirtualMachine(cmd)
@@ -413,6 +475,26 @@ class VirtualMachine:
         cmd.virtualmachineid = self.id
         return apiclient.updateDefaultNicForVirtualMachine(cmd)
 
+    def attach_iso(self, apiclient, iso):
+        """Attach ISO to instance"""
+        cmd = attachIso.attachIsoCmd()
+        cmd.id = iso.id
+        cmd.virtualmachineid = self.id
+        return apiclient.attachIso(cmd)
+
+    def detach_iso(self, apiclient):
+        """Detach ISO to instance"""
+        cmd = detachIso.detachIsoCmd()
+        cmd.id = self.id
+        return apiclient.detachIso(cmd)
+
+    def change_service_offering(self, apiclient, serviceOfferingId):
+        """Change service offering of the instance"""
+        cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
+        cmd.id = self.id
+        cmd.serviceofferingid = serviceOfferingId
+        return apiclient.changeServiceForVirtualMachine(cmd)
+
     @classmethod
     def list(cls, apiclient, **kwargs):
         """List all VMs matching criteria"""
@@ -428,16 +510,14 @@ class VirtualMachine:
         cmd.id = self.id
         try:
             response = apiclient.resetPasswordForVirtualMachine(cmd)
-            print response
         except Exception as e:
             raise Exception("Reset Password failed! - %s" % e)
-        print type(response)
         if isinstance(response, list):
             return response[0].password
 
 
 class Volume:
-    """Manage Volume Lifecycle
+    """Manage Volume Life cycle
     """
     def __init__(self, items):
         self.__dict__.update(items)
@@ -533,7 +613,7 @@ class Volume:
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return(apiclient.listVolumes(cmd))
 
-    def resize(cls, apiclient, **kwargs):
+    def resize(self, apiclient, **kwargs):
         """Resize a volume"""
         cmd = resizeVolume.resizeVolumeCmd()
         cmd.id = self.id
@@ -541,6 +621,58 @@ class Volume:
         return(apiclient.resizeVolume(cmd))
 
     @classmethod
+    def upload(cls, apiclient, services, zoneid=None, account=None, domainid=None, url=None):
+        """Uploads the volume to specified account"""
+
+        cmd = uploadVolume.uploadVolumeCmd()
+        if zoneid:
+            cmd.zoneid = zoneid
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        cmd.format = services["format"]
+        cmd.name = services["diskname"]
+        if url:
+            cmd.url = url
+        else:
+            cmd.url = services["url"]
+        return Volume(apiclient.uploadVolume(cmd).__dict__)
+
+    def wait_for_upload(self, apiclient, timeout=5, interval=60):
+        """Wait for upload"""
+        # Sleep to ensure template is in proper state before download
+        time.sleep(interval)
+
+        while True:
+            volume_response = Volume.list(
+                                    apiclient,
+                                    id=self.id,
+                                    zoneid=self.zoneid,
+                                    )
+            if isinstance(volume_response, list):
+
+                volume = volume_response[0]
+                # If volume is ready,
+                # volume.state = Allocated
+                if volume.state == 'Uploaded':
+                    break
+
+                elif 'Uploading' in volume.state:
+                    time.sleep(interval)
+
+                elif 'Installing' not in volume.state:
+                    raise Exception(
+                        "Error in uploading volume: status - %s" %
+                                                            volume.state)
+            elif timeout == 0:
+                break
+
+            else:
+                time.sleep(interval)
+                timeout = timeout - 1
+        return
+
     def migrate(cls, apiclient, **kwargs):
         """Migrate a volume"""
         cmd = migrateVolume.migrateVolumeCmd()
@@ -592,7 +724,7 @@ class Template:
     def create(cls, apiclient, services, volumeid=None,
                account=None, domainid=None, projectid=None):
         """Create template from Volume"""
-        #Create template from Virtual machine and Volume ID
+        # Create template from Virtual machine and Volume ID
         cmd = createTemplate.createTemplateCmd()
         cmd.displaytext = services["displaytext"]
         cmd.name = "-".join([services["name"], random_gen()])
@@ -617,7 +749,6 @@ class Template:
         cmd.ispublic = services["ispublic"] if "ispublic" in services else False
         cmd.isextractable = services["isextractable"] if "isextractable" in services else False
         cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
-        cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
 
         if volumeid:
             cmd.volumeid = volumeid
@@ -637,12 +768,12 @@ class Template:
                                                 account=None, domainid=None):
         """Create template from URL"""
 
-        #Create template from Virtual machine and Volume ID
+        # Create template from Virtual machine and Volume ID
         cmd = registerTemplate.registerTemplateCmd()
         cmd.displaytext = services["displaytext"]
         cmd.name = "-".join([services["name"], random_gen()])
         cmd.format = services["format"]
-        cmd.hypervisor = services["hypervisor"]
+        cmd.hypervisor = apiclient.hypervisor
 
         if "ostypeid" in services:
             cmd.ostypeid = services["ostypeid"]
@@ -689,7 +820,7 @@ class Template:
     def create_from_snapshot(cls, apiclient, snapshot, services,
                                                         random_name=True):
         """Create Template from snapshot"""
-        #Create template from Virtual machine and Snapshot ID
+        # Create template from Virtual machine and Snapshot ID
         cmd = createTemplate.createTemplateCmd()
         cmd.displaytext = services["displaytext"]
         cmd.name = "-".join([
@@ -726,7 +857,7 @@ class Template:
 
     def download(self, apiclient, timeout=5, interval=60):
         """Download Template"""
-        #Sleep to ensure template is in proper state before download
+        # Sleep to ensure template is in proper state before download
         time.sleep(interval)
 
         while True:
@@ -789,7 +920,7 @@ class Iso:
     def create(cls, apiclient, services, account=None, domainid=None,
                                                         projectid=None):
         """Create an ISO"""
-        #Create ISO from URL
+        # Create ISO from URL
         cmd = registerIso.registerIsoCmd()
         cmd.displaytext = services["displaytext"]
         cmd.name = services["name"]
@@ -841,7 +972,7 @@ class Iso:
 
     def download(self, apiclient, timeout=5, interval=60):
         """Download an ISO"""
-        #Ensuring ISO is successfully downloaded
+        # Ensuring ISO is successfully downloaded
         while True:
             time.sleep(interval)
 
@@ -853,7 +984,6 @@ class Iso:
                 response = iso_response[0]
                 # Again initialize timeout to avoid listISO failure
                 timeout = 5
-                print response.status
                 # Check whether download is in progress(for Ex:10% Downloaded)
                 # or ISO is 'Successfully Installed'
                 if response.status == 'Successfully Installed':
@@ -940,7 +1070,7 @@ class NATRule:
 
     @classmethod
     def create(cls, apiclient, virtual_machine, services, ipaddressid=None,
-                                                            projectid=None, networkid=None):
+               projectid=None, openfirewall=False, networkid=None, vpcid=None):
         """Create Port forwarding rule"""
         cmd = createPortForwardingRule.createPortForwardingRuleCmd()
 
@@ -951,15 +1081,24 @@ class NATRule:
 
         cmd.privateport = services["privateport"]
         cmd.publicport = services["publicport"]
+        if "privateendport" in services:
+            cmd.privateendport = services["privateendport"]
+        if "publicendport" in services:
+            cmd.publicendport = services["publicendport"]
         cmd.protocol = services["protocol"]
         cmd.virtualmachineid = virtual_machine.id
 
         if projectid:
             cmd.projectid = projectid
 
+        if openfirewall:
+            cmd.openfirewall = True
+
         if networkid:
             cmd.networkid = networkid
 
+        if vpcid:
+            cmd.vpcid = vpcid
         return NATRule(apiclient.createPortForwardingRule(cmd).__dict__)
 
     def delete(self, apiclient):
@@ -985,10 +1124,10 @@ class StaticNATRule:
         self.__dict__.update(items)
 
     @classmethod
-    def create(cls, apiclient, services, ipaddressid=None, vpcid=None):
+    def create(cls, apiclient, services, ipaddressid=None, networkid=None, vpcid=None):
         """Creates static ip forwarding rule"""
 
-        cmd = createIpForwardingRule.createIpForwardingRuleCmd()
+        cmd = createFirewallRule.createFirewallRuleCmd()
         cmd.protocol = services["protocol"]
         cmd.startport = services["startport"]
 
@@ -1003,10 +1142,12 @@ class StaticNATRule:
         elif "ipaddressid" in services:
             cmd.ipaddressid = services["ipaddressid"]
 
+        if networkid:
+            cmd.networkid = networkid
+
         if vpcid:
             cmd.vpcid = vpcid
-
-        return StaticNATRule(apiclient.createIpForwardingRule(cmd).__dict__)
+        return StaticNATRule(apiclient.createFirewallRule(cmd).__dict__)
 
     def delete(self, apiclient):
         """Delete IP forwarding rule"""
@@ -1024,12 +1165,14 @@ class StaticNATRule:
         return(apiclient.listIpForwardingRules(cmd))
 
     @classmethod
-    def enable(cls, apiclient, ipaddressid, virtualmachineid):
+    def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None):
         """Enables Static NAT rule"""
 
         cmd = enableStaticNat.enableStaticNatCmd()
         cmd.ipaddressid = ipaddressid
         cmd.virtualmachineid = virtualmachineid
+        if networkid:
+            cmd.networkid = networkid
         apiclient.enableStaticNat(cmd)
         return
 
@@ -1105,6 +1248,14 @@ class ServiceOffering:
         if "storagetype" in services:
             cmd.storagetype = services["storagetype"]
 
+        if "systemvmtype" in services:
+            cmd.systemvmtype = services['systemvmtype']
+
+        if "issystem" in services:
+            cmd.issystem = services['issystem']
+
+        if "tags" in services:
+            cmd.tags = services["tags"]
         # Service Offering private to that domain
         if domainid:
             cmd.domainid = domainid
@@ -1183,20 +1334,25 @@ class NetworkOffering:
         cmd.displaytext = "-".join([services["displaytext"], random_gen()])
         cmd.name = "-".join([services["name"], random_gen()])
         cmd.guestiptype = services["guestiptype"]
-        cmd.supportedservices = services["supportedservices"]
+        cmd.supportedservices = ''
+        if "supportedservices" in services:
+            cmd.supportedservices = services["supportedservices"]
         cmd.traffictype = services["traffictype"]
 
+        if "useVpc" in services:
+            cmd.useVpc = services["useVpc"]
         cmd.serviceProviderList = []
-        for service, provider in services["serviceProviderList"].items():
-            cmd.serviceProviderList.append({
+        if "serviceProviderList" in services:
+            for service, provider in services["serviceProviderList"].items():
+                cmd.serviceProviderList.append({
                                             'service': service,
                                             'provider': provider
                                            })
         if "servicecapabilitylist" in services:
-            cmd.servicecapabilitylist = []
+            cmd.serviceCapabilityList = []
             for service, capability in services["servicecapabilitylist"].items():
                 for ctype, value in capability.items():
-                    cmd.servicecapabilitylist.append({
+                    cmd.serviceCapabilityList.append({
                                             'service': service,
                                             'capabilitytype': ctype,
                                             'capabilityvalue': value
@@ -1205,6 +1361,7 @@ class NetworkOffering:
             cmd.specifyVlan = services["specifyVlan"]
         if "specifyIpRanges" in services:
             cmd.specifyIpRanges = services["specifyIpRanges"]
+        cmd.availability = 'Optional'
 
         [setattr(cmd, k, v) for k, v in kwargs.items()]
 
@@ -1275,7 +1432,7 @@ class LoadBalancerRule:
 
     @classmethod
     def create(cls, apiclient, services, ipaddressid=None, accountid=None,
-                            networkid=None, projectid=None, domainid=None):
+               networkid=None, vpcid=None, projectid=None, domainid=None):
         """Create Load balancing Rule"""
 
         cmd = createLoadBalancerRule.createLoadBalancerRuleCmd()
@@ -1293,6 +1450,8 @@ class LoadBalancerRule:
         if domainid:
             cmd.domainid = domainid
 
+        if vpcid:
+            cmd.vpcid = vpcid
         cmd.name = services["name"]
         cmd.algorithm = services["alg"]
         cmd.privateport = services["privateport"]
@@ -1359,19 +1518,19 @@ class LoadBalancerRule:
             for name, value in param.items():
                 cmd.param.append({'name': name, 'value': value})
         return apiclient.createLBStickinessPolicy(cmd)
-    
+
     def deleteSticky(self, apiclient, id):
         """Deletes stickyness policy"""
-        
+
         cmd = deleteLBStickinessPolicy.deleteLBStickinessPolicyCmd()
         cmd.id = id
         return apiclient.deleteLBStickinessPolicy(cmd)
-    
+
     @classmethod
     def listStickyPolicies(cls, apiclient, lbruleid, **kwargs):
         """Lists stickiness policies for load balancing rule"""
-        
-        cmd= listLBStickinessPolicies.listLBStickinessPoliciesCmd()
+
+        cmd = listLBStickinessPolicies.listLBStickinessPoliciesCmd()
         cmd.lbruleid = lbruleid
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return apiclient.listLBStickinessPolicies(cmd)
@@ -1396,7 +1555,7 @@ class Cluster:
         """Create Cluster"""
         cmd = addCluster.addClusterCmd()
         cmd.clustertype = services["clustertype"]
-        cmd.hypervisor = services["hypervisor"]
+        cmd.hypervisor = apiclient.hypervisor
 
         if zoneid:
             cmd.zoneid = zoneid
@@ -1446,7 +1605,7 @@ class Host:
         """Create Host in cluster"""
 
         cmd = addHost.addHostCmd()
-        cmd.hypervisor = services["hypervisor"]
+        cmd.hypervisor = apiclient.hypervisor
         cmd.url = services["url"]
         cmd.clusterid = cluster.id
 
@@ -1494,6 +1653,29 @@ class Host:
         return apiclient.prepareHostForMaintenance(cmd)
 
     @classmethod
+    def enableMaintenance(cls, apiclient, id):
+        """enables maintainance mode Host"""
+
+        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
+        cmd.id = id
+        return apiclient.prepareHostForMaintenance(cmd)
+
+    def cancelMaintenance(self, apiclient):
+        """Cancels maintainance mode Host"""
+
+        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+        cmd.id = self.id
+        return apiclient.cancelHostMaintenance(cmd)
+
+    @classmethod
+    def cancelMaintenance(cls, apiclient, id):
+        """Cancels maintainance mode Host"""
+
+        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+        cmd.id = id
+        return apiclient.cancelHostMaintenance(cmd)
+
+    @classmethod
     def list(cls, apiclient, **kwargs):
         """List all Hosts matching criteria"""
 
@@ -1586,7 +1768,8 @@ class Network:
 
     @classmethod
     def create(cls, apiclient, services, accountid=None, domainid=None,
-               networkofferingid=None, projectid=None, zoneid=None,
+               networkofferingid=None, projectid=None,
+               subdomainaccess=None, zoneid=None,
                gateway=None, netmask=None, vpcid=None, guestcidr=None):
         """Create Network for account"""
         cmd = createNetwork.createNetworkCmd()
@@ -1603,6 +1786,9 @@ class Network:
         elif "zoneid" in services:
             cmd.zoneid = services["zoneid"]
 
+        if subdomainaccess is not None:
+            cmd.subdomainaccess = subdomainaccess
+
         if gateway:
             cmd.gateway = gateway
         elif "gateway" in services:
@@ -1717,7 +1903,7 @@ class Vpn:
 
     @classmethod
     def create(cls, apiclient, publicipid, account=None, domainid=None,
-                                                            projectid=None, vpcid=None):
+                        projectid=None, networkid=None, vpcid=None):
         """Create VPN for Public IP address"""
         cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd()
         cmd.publicipid = publicipid
@@ -1727,6 +1913,8 @@ class Vpn:
             cmd.domainid = domainid
         if projectid:
             cmd.projectid = projectid
+        if networkid:
+            cmd.networkid = networkid
         if vpcid:
             cmd.vpcid = vpcid
         return Vpn(apiclient.createRemoteAccessVpn(cmd).__dict__)
@@ -1755,10 +1943,11 @@ class VpnUser:
 
     @classmethod
     def create(cls, apiclient, username, password, account=None, domainid=None,
-               projectid=None):
+               projectid=None, rand_name=True):
         """Create VPN user"""
         cmd = addVpnUser.addVpnUserCmd()
-        cmd.username = username
+        cmd.username = "-".join([username,
+                                 random_gen()]) if rand_name else username
         cmd.password = password
 
         if account:
@@ -1997,6 +2186,7 @@ class PhysicalNetwork:
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return map(lambda pn : PhysicalNetwork(pn.__dict__), apiclient.listPhysicalNetworks(cmd))
 
+
 class SecurityGroup:
     """Manage Security Groups"""
 
@@ -2364,6 +2554,104 @@ class NetworkServiceProvider:
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return(apiclient.listNetworkServiceProviders(cmd))
 
+
+class Router:
+    """Manage router life cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def start(cls, apiclient, id):
+        """Starts the router"""
+        cmd = startRouter.startRouterCmd()
+        cmd.id = id
+        return apiclient.startRouter(cmd)
+
+    @classmethod
+    def stop(cls, apiclient, id, forced=None):
+        """Stops the router"""
+        cmd = stopRouter.stopRouterCmd()
+        cmd.id = id
+        if forced:
+            cmd.forced = forced
+        return apiclient.stopRouter(cmd)
+
+    @classmethod
+    def reboot(cls, apiclient, id):
+        """Reboots the router"""
+        cmd = rebootRouter.rebootRouterCmd()
+        cmd.id = id
+        return apiclient.rebootRouter(cmd)
+
+    @classmethod
+    def destroy(cls, apiclient, id):
+        """Destroy the router"""
+        cmd = destroyRouter.destroyRouterCmd()
+        cmd.id = id
+        return apiclient.destroyRouter(cmd)
+
+    @classmethod
+    def change_service_offering(cls, apiclient, id, serviceofferingid):
+        """Change service offering of the router"""
+        cmd = changeServiceForRouter.changeServiceForRouterCmd()
+        cmd.id = id
+        cmd.serviceofferingid = serviceofferingid
+        return apiclient.changeServiceForRouter(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List routers"""
+
+        cmd = listRouters.listRoutersCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listRouters(cmd))
+
+
+class Tag:
+    """Manage tags"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, resourceIds, resourceType, tags):
+        """Create tags"""
+
+        cmd = createTags.createTagsCmd()
+        cmd.resourceIds = resourceIds
+        cmd.resourcetype = resourceType
+        cmd.tags = []
+        for key, value in tags.items():
+            cmd.tags.append({
+                             'key': key,
+                             'value': value
+                            })
+        return Tag(apiclient.createTags(cmd).__dict__)
+
+    def delete(self, apiclient, resourceIds, resourceType, tags):
+        """Delete tags"""
+
+        cmd = deleteTags.deleteTagsCmd()
+        cmd.resourceIds = resourceIds
+        cmd.resourcetype = resourceType
+        cmd.tags = []
+        for key, value in tags.items():
+            cmd.tags.append({
+                             'key': key,
+                             'value': value
+                             })
+        apiclient.deleteTags(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all tags matching the criteria"""
+
+        cmd = listTags.listTagsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listTags(cmd))
+
+
 class VpcOffering:
     """Manage VPC offerings"""
 
@@ -2417,7 +2705,7 @@ class VPC:
 
     @classmethod
     def create(cls, apiclient, services, vpcofferingid,
-               zoneid, networkDomain=None, account=None, domainid=None):
+                    zoneid, networkDomain=None, account=None, domainid=None):
         """Creates the virtual private connection (VPC)"""
 
         cmd = createVPC.createVPCCmd()
@@ -2467,6 +2755,40 @@ class VPC:
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return(apiclient.listVPCs(cmd))
 
+
+class PrivateGateway:
+    """Manage private gateway lifecycle"""
+    def create(cls, apiclient, gateway, ipaddress, netmask, vlan, vpcid,
+                                                    physicalnetworkid=None):
+        """Create private gateway"""
+
+        cmd = createPrivateGateway.createPrivateGatewayCmd()
+        cmd.gateway = gateway
+        cmd.ipaddress = ipaddress
+        cmd.netmask = netmask
+        cmd.vlan = vlan
+        cmd.vpcid = vpcid
+        if physicalnetworkid:
+            cmd.physicalnetworkid = physicalnetworkid
+
+        return PrivateGateway(apiclient.createPrivateGateway(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete private gateway"""
+
+        cmd = deletePrivateGateway.deletePrivateGatewayCmd()
+        cmd.id = self.id
+        return apiclient.deletePrivateGateway(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List private gateways"""
+
+        cmd = listPrivateGateways.listPrivateGatewaysCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listPrivateGateways(cmd))
+
+
 class AffinityGroup:
     def __init__(self, items):
         self.__dict__.update(items)
@@ -2495,9 +2817,35 @@ class AffinityGroup:
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return(apiclient.listVPCs(cmd))
 
+class StaticRoute:
+    """Manage static route lifecycle"""
+    @classmethod
+    def create(cls, apiclient, cidr, gatewayid):
+        """Create static route"""
+
+        cmd = createStaticRoute.createStaticRouteCmd()
+        cmd.cidr = cidr
+        cmd.gatewayid = gatewayid
+        return StaticRoute(apiclient.createStaticRoute(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete static route"""
+
+        cmd = deleteStaticRoute.deleteStaticRouteCmd()
+        cmd.id = self.id
+        return apiclient.deleteStaticRoute(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List static route"""
+
+        cmd = listStaticRoutes.listStaticRoutesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listStaticRoutes(cmd))
+
+
 class VNMC:
     """Manage VNMC lifecycle"""
-
     def __init__(self, items):
         self.__dict__.update(items)
 
@@ -2526,13 +2874,153 @@ class VNMC:
         [setattr(cmd, k, v) for k, v in kwargs.items()]
         return(apiclient.listCiscoVnmcResources(cmd))
 
-class ASA1000V:
-    """Manage ASA 1000v lifecycle"""
+
+class SSHKeyPair:
+    """Manage SSH Key pairs"""
+
+    def __init__(self, items, services):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, name=None, account=None,
+                    domainid=None, projectid=None):
+        """Creates SSH keypair"""
+        cmd = createSSHKeyPair.createSSHKeyPairCmd()
+        cmd.name = name
+        if account is not None:
+            cmd.account = account
+        if domainid is not None:
+            cmd.domainid = domainid
+        if projectid is not None:
+            cmd.projectid = projectid
+        return (apiclient.createSSHKeyPair(cmd))
+
+    def delete(self, apiclient):
+        """Delete SSH key pair"""
+        cmd = deleteSSHKeyPair.deleteSSHKeyPairCmd()
+        cmd.name = self.name
+        apiclient.deleteSSHKeyPair(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all SSH key pairs"""
+        cmd = listSSHKeyPairs.listSSHKeyPairsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listSSHKeyPairs(cmd))
+
+
+class Capacities:
+    """Manage Capacities"""
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists capacities"""
+
+        cmd = listCapacity.listCapacityCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listCapacity(cmd))
+
+
+class Alert:
+    """Manage alerts"""
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists alerts"""
+
+        cmd = listAlerts.listAlertsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listAlerts(cmd))
+
+
+class InstanceGroup:
+    """Manage VM instance groups"""
 
     def __init__(self, items):
         self.__dict__.update(items)
 
     @classmethod
+    def create(cls, apiclient, name=None, account=None, domainid=None,
+               projectid=None, networkid=None, rand_name=True):
+        """Creates instance groups"""
+
+        cmd = createInstanceGroup.createInstanceGroupCmd()
+        cmd.name = "-".join([name, random_gen()]) if rand_name else name
+        if account is not None:
+            cmd.account = account
+        if domainid is not None:
+            cmd.domainid = domainid
+        if projectid is not None:
+            cmd.projectid = projectid
+        if networkid is not None:
+            cmd.networkid = networkid
+        return InstanceGroup(apiclient.createInstanceGroup(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete instance group"""
+        cmd = deleteInstanceGroup.deleteInstanceGroupCmd()
+        cmd.id = self.id
+        apiclient.deleteInstanceGroup(cmd)
+
+    def update(self, apiclient, **kwargs):
+        """Updates the instance groups"""
+        cmd = updateInstanceGroup.updateInstanceGroupCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return (apiclient.updateInstanceGroup(cmd))
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all instance groups"""
+        cmd = listInstanceGroups.listInstanceGroupsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return (apiclient.listInstanceGroups(cmd))
+
+    def startInstances(self, apiclient):
+        """Starts all instances in a VM tier"""
+
+        cmd = startVirtualMachine.startVirtualMachineCmd()
+        cmd.group = self.id
+        return apiclient.startVirtualMachine(cmd)
+
+    def stopInstances(self, apiclient):
+        """Stops all instances in a VM tier"""
+
+        cmd = stopVirtualMachine.stopVirtualMachineCmd()
+        cmd.group = self.id
+        return apiclient.stopVirtualMachine(cmd)
+
+    def rebootInstances(self, apiclient):
+        """Reboot all instances in a VM tier"""
+
+        cmd = rebootVirtualMachine.rebootVirtualMachineCmd()
+        cmd.group = self.id
+        return apiclient.rebootVirtualMachine(cmd)
+
+    def deleteInstances(self, apiclient):
+        """Stops all instances in a VM tier"""
+
+        cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
+        cmd.group = self.id
+        return apiclient.destroyVirtualMachine(cmd)
+
+    def changeServiceOffering(self, apiclient, serviceOfferingId):
+        """Change service offering of the vm tier"""
+
+        cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
+        cmd.group = self.id
+        cmd.serviceofferingid = serviceOfferingId
+        return apiclient.changeServiceForVirtualMachine(cmd)
+
+    def recoverInstances(self, apiclient):
+        """Recover the instances from vm tier"""
+        cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
+        cmd.group = self.id
+        apiclient.recoverVirtualMachine(cmd)
+
+
+class ASA1000V:
+    """Manage ASA 1000v lifecycle"""
     def create(cls, apiclient, hostname, insideportprofile, clusterid, physicalnetworkid):
         """Registers ASA 1000v appliance"""
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/integration/lib/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/integration/lib/utils.py b/tools/marvin/marvin/integration/lib/utils.py
index cff24a1..6892c41 100644
--- a/tools/marvin/marvin/integration/lib/utils.py
+++ b/tools/marvin/marvin/integration/lib/utils.py
@@ -106,12 +106,17 @@ def cleanup_resources(api_client, resources):
         obj.delete(api_client)
 
 
-def is_server_ssh_ready(ipaddress, port, username, password, retries=50):
+def is_server_ssh_ready(ipaddress, port, username, password, retries=50, keyPairFileLocation=None):
     """Return ssh handle else wait till sshd is running"""
     loop_cnt = retries
     while True:
         try:
-            ssh = remoteSSHClient(ipaddress, port, username, password)
+            ssh = remoteSSHClient(
+                                    host=ipaddress,
+                                    port=port,
+                                    user=username,
+                                    passwd=password,
+                                    keyPairFileLocation=keyPairFileLocation)
         except Exception as e:
             if loop_cnt == 0:
                 raise e
@@ -149,12 +154,16 @@ def fetch_api_client(config_file='datacenterCfg'):
                                             )
 
 
-def get_process_status(hostip, port, username, password, linklocalip, process):
+def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None):
     """Double hop and returns a process status"""
 
     #SSH to the machine
     ssh = remoteSSHClient(hostip, port, username, password)
-    ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+    if str(hypervisor).lower() == 'vmware':
+        ssh_command = "ssh -i /var/lib/cloud/management/.ssh/id_rsa -ostricthostkeychecking=no "
+    else:
+        ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+
     ssh_command = ssh_command + \
                     "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % (
                                                                 linklocalip,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2f40a90c/tools/marvin/marvin/remoteSSHClient.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/remoteSSHClient.py b/tools/marvin/marvin/remoteSSHClient.py
index 4fb2f0d..04450fd 100644
--- a/tools/marvin/marvin/remoteSSHClient.py
+++ b/tools/marvin/marvin/remoteSSHClient.py
@@ -23,11 +23,12 @@ import logging
 from contextlib import closing
 
 class remoteSSHClient(object):
-    def __init__(self, host, port, user, passwd, retries = 10, log_lvl=logging.INFO):
+    def __init__(self, host, port, user, passwd, retries = 10, log_lvl=logging.INFO, keyPairFileLocation=None):
         self.host = host
         self.port = port
         self.user = user
         self.passwd = passwd
+        self.keyPairFile = keyPairFileLocation
         self.ssh = paramiko.SSHClient()
         self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
         self.logger = logging.getLogger('sshClient')
@@ -38,8 +39,19 @@ class remoteSSHClient(object):
         retry_count = retries
         while True:
             try:
-                self.ssh.connect(str(host),int(port), user, passwd)
-                self.logger.debug("SSH connect: %s@%s with passwd %s"%(user, str(host), passwd))
+                if keyPairFileLocation == None:
+                    self.ssh.connect(str(host),int(port), user, passwd)
+                    self.logger.debug("SSH connect: %s@%s with passwd %s"%(user, str(host), passwd))
+                else:
+                    self.ssh.connect(
+                                        hostname=str(host),
+                                        port=int(port),
+                                        username=str(user),
+                                        key_filename=str(keyPairFileLocation),
+                                        look_for_keys=False
+                                    )
+                    self.logger.debug("connecting to server %s with user %s key %s"%(str(host), user, keyPairFileLocation))
+                    self.logger.debug("SSH connect: %s@%s with passwd %s"%(user, str(host), passwd))
             except paramiko.SSHException, sshex:
                 if retry_count == 0:
                     raise cloudstackException.InvalidParameterException(repr(sshex))