You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ts...@apache.org on 2013/04/26 08:47:46 UTC
git commit: updated refs/heads/master to 2f40a90
Updated Branches:
refs/heads/master f429c6687 -> 2f40a90c5
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/master
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))