Added fix for CLOUDSTACK-6316

Added changes for CLOUDSTACK-6316.
More details in the bug

Signed-off-by: Santhosh Edukulla <Santhosh.Edukulla@citrix.com>
This commit is contained in:
Santhosh Edukulla 2014-04-01 20:58:11 +05:30 committed by SrikanteswaraRao Talluri
parent 70e104021c
commit 63d3688360
20 changed files with 932 additions and 848 deletions

View File

@ -24,6 +24,7 @@ from marvin.cloudstackAPI import *
from marvin.lib.utils import *
from marvin.lib.base import *
from marvin.lib.common import *
import time
class Services:
@ -619,11 +620,7 @@ class TestHostHighAvailability(cloudstackTestCase):
#verify the VM live migration happened to another running host
self.debug("Waiting for VM to come up")
wait_for_vm(
self.apiclient,
virtualmachineid=vm_with_ha_enabled.id,
interval=timeout
)
time.sleep(timeout)
vms = VirtualMachine.list(
self.apiclient,
@ -751,11 +748,7 @@ class TestHostHighAvailability(cloudstackTestCase):
#verify the VM live migration happened to another running host
self.debug("Waiting for VM to come up")
wait_for_vm(
self.apiclient,
virtualmachineid=vm_with_ha_disabled.id,
interval=timeout
)
time.sleep(timeout)
vms = VirtualMachine.list(
self.apiclient,

View File

@ -15,4 +15,4 @@
# specific language governing permissions and limitations
# under the License.
#Marvin - The cloudstack test client
# Marvin - The cloudstack test client

View File

@ -26,12 +26,14 @@ import datetime
class job(object):
def __init__(self):
self.id = None
self.cmd = None
class jobStatus(object):
def __init__(self):
self.result = None
self.status = None
@ -47,6 +49,7 @@ class jobStatus(object):
class workThread(threading.Thread):
def __init__(self, in_queue, outqueue, apiClient, db=None, lock=None):
threading.Thread.__init__(self)
self.inqueue = in_queue
@ -62,7 +65,7 @@ class workThread(threading.Thread):
try:
self.lock.acquire()
result = self.connection.poll(job.jobId, job.responsecls).jobresult
except cloudstackException.CloudstackAPIException, e:
except cloudstackException.CloudstackAPIException as e:
result = str(e)
finally:
self.lock.release()
@ -102,7 +105,7 @@ class workThread(threading.Thread):
except:
pass
jobstatus.status = True
except cloudstackException.CloudstackAPIException, e:
except cloudstackException.CloudstackAPIException as e:
jobstatus.result = str(e)
jobstatus.status = False
except:
@ -129,6 +132,7 @@ class workThread(threading.Thread):
class jobThread(threading.Thread):
def __init__(self, inqueue, interval):
threading.Thread.__init__(self)
self.inqueue = inqueue
@ -149,12 +153,14 @@ class jobThread(threading.Thread):
class outputDict(object):
def __init__(self):
self.lock = threading.Condition()
self.dict = {}
class asyncJobMgr(object):
def __init__(self, apiClient, db):
self.inqueue = Queue.Queue()
self.output = outputDict()

View File

@ -21,9 +21,9 @@ import base64
import hmac
import hashlib
import time
from cloudstackAPI import *
import jsonHelper
from codes import (
from .cloudstackAPI import *
from . import jsonHelper
from .codes import (
FAILED,
INVALID_RESPONSE,
INVALID_INPUT,
@ -42,12 +42,14 @@ from marvin.cloudstackException import GetDetailExceptionInfo
class CSConnection(object):
'''
@Desc: Connection Class to make API\Command calls to the
CloudStack Management Server
Sends the GET\POST requests to CS based upon the
information provided and retrieves the parsed response.
'''
def __init__(self, mgmtDet, asyncTimeout=3600, logger=None,
path='client/api'):
self.apiKey = mgmtDet.apiKey
@ -56,10 +58,9 @@ class CSConnection(object):
self.port = mgmtDet.port
self.user = mgmtDet.user
self.passwd = mgmtDet.passwd
self.certPath = ()
if mgmtDet.certCAPath != "NA" and mgmtDet.certPath != "NA":
self.certPath = (mgmtDet.certCAPath, mgmtDet.certPath)
else:
self.certPath = ()
self.logger = logger
self.path = path
self.retries = 5
@ -94,28 +95,33 @@ class CSConnection(object):
cmd = queryAsyncJobResult.queryAsyncJobResultCmd()
cmd.jobid = jobid
timeout = self.asyncTimeout
start_time = time.time()
end_time = time.time()
async_response = FAILED
self.logger.debug("=== Jobid: %s Started ===" % (str(jobid)))
while timeout > 0:
async_response = self.\
marvinRequest(cmd, response_type=response_cmd)
if async_response != FAILED:
job_status = async_response.jobstatus
if job_status in [JOB_FAILED, JOB_CANCELLED]:
self.logger.debug("=====JobId:%s Either "
"got Cancelled or Failed======"
% (str(jobid)))
return FAILED
if job_status == JOB_SUCCEEDED:
self.logger.debug("======JobId:%s Succeeded====="
% (str(jobid)))
return async_response
if job_status in [JOB_FAILED,
JOB_CANCELLED,
JOB_SUCCEEDED]:
break
time.sleep(5)
timeout -= 5
self.logger.debug("JobId:%s is Still Processing, "
"Will TimeOut in:%s" % (str(jobid),
str(timeout)))
return FAILED
except Exception, e:
end_time = time.time()
tot_time = int(start_time - end_time)
self.logger.debug(
"===Jobid:%s ; StartTime:%s ; EndTime:%s ; "
"TotalTime:%s===" %
(str(jobid), str(time.ctime(start_time)),
str(time.ctime(end_time)), str(tot_time)))
return async_response
except Exception as e:
self.__lastError = GetDetailExceptionInfo(e)
self.logger.exception("__poll: Exception Occurred :%s" %
self.__lastError)
@ -165,11 +171,11 @@ class CSConnection(object):
cert=self.certPath,
verify=self.httpsFlag)
return response
except Exception, e:
self.__lastError = GetDetailExceptionInfo(e)
except Exception as e:
self.__lastError = e
self.logger.\
exception("__sendPostReqToCS : Exception "
"Occurred: %s" % self.__lastError)
"Occurred: %s" % str(self.__lastError))
return FAILED
def __sendGetReqToCS(self, url, payload):
@ -187,10 +193,10 @@ class CSConnection(object):
cert=self.certPath,
verify=self.httpsFlag)
return response
except Exception, e:
self.__lastError = GetDetailExceptionInfo(e)
except Exception as e:
self.__lastError = e
self.logger.exception("__sendGetReqToCS : Exception Occurred: %s" %
self.__lastError)
str(self.__lastError))
return FAILED
def __sendCmdToCS(self, command, auth=True, payload={}, method='GET'):
@ -213,8 +219,9 @@ class CSConnection(object):
payload["apiKey"] = self.apiKey
payload["signature"] = self.__sign(payload)
#Verify whether protocol is "http", then call the request over http
if self.protocol == "http" or self.protocol == "https":
# Verify whether protocol is "http" or "https", then send the
# request
if self.protocol in ["http", "https"]:
self.logger.debug("Payload: %s" % str(payload))
if method == 'POST':
self.logger.debug("=======Sending POST Cmd : %s======="
@ -227,7 +234,7 @@ class CSConnection(object):
else:
self.logger.exception("__sendCmdToCS: Invalid Protocol")
return FAILED
except Exception, e:
except Exception as e:
self.logger.exception("__sendCmdToCS: Exception:%s" %
GetDetailExceptionInfo(e))
return FAILED
@ -276,7 +283,7 @@ class CSConnection(object):
payload["%s[%d].%s" % (param, i, k)] = v
i += 1
return cmd_name.strip(), isAsync, payload
except Exception, e:
except Exception as e:
self.logger.\
exception("__sanitizeCmd: CmdName : "
"%s : Exception:%s" % (cmd_name,
@ -352,10 +359,13 @@ class CSConnection(object):
4. Check if the Command Response received above is valid or Not.
If not return Invalid Response
'''
return self.__parseAndGetResponse(cmd_response,
response_type,
is_async)
except Exception, e:
ret = self.__parseAndGetResponse(cmd_response,
response_type,
is_async)
if ret == FAILED:
raise self.__lastError
return ret
except Exception as e:
self.logger.exception("marvinRequest : CmdName: %s Exception: %s" %
(str(cmd), GetDetailExceptionInfo(e)))
return FAILED

View File

@ -21,6 +21,7 @@ from marvin.codes import (INVALID_INPUT, EXCEPTION_OCCURRED)
class CloudstackAPIException(Exception):
def __init__(self, cmd="", result=""):
self.errorMsg = "Execute cmd: %s failed, due to: %s" % (cmd, result)
@ -29,6 +30,7 @@ class CloudstackAPIException(Exception):
class InvalidParameterException(Exception):
def __init__(self, msg=''):
self.errorMsg = msg
@ -37,6 +39,7 @@ class InvalidParameterException(Exception):
class dbException(Exception):
def __init__(self, msg=''):
self.errorMsg = msg
@ -45,6 +48,7 @@ class dbException(Exception):
class internalError(Exception):
def __init__(self, msg=''):
self.errorMsg = msg

View File

@ -37,7 +37,7 @@ def user(Name, DomainName, AcctType):
class cloudstackTestCase(unittest.case.TestCase):
clstestclient = None
def assertElementInList(inp, toverify, responsevar=None, pos=0,
def assertElementInList(inp, toverify, responsevar=None, pos=0,
assertmsg="TC Failed for reason"):
'''
@Name: assertElementInList
@ -46,7 +46,7 @@ class cloudstackTestCase(unittest.case.TestCase):
Takes one additional argument of what message to assert with
when failed
'''
out = verifyElementInList(inp, toverify, responsevar, pos)
out = verifyElementInList(inp, toverify, responsevar, pos)
unittest.TestCase.assertEquals(out[0], PASS, "msg:%s" % out[1])
@classmethod

View File

@ -15,23 +15,20 @@
# specific language governing permissions and limitations
# under the License.
from cloudstackConnection import CSConnection
import asyncJobMgr
from dbConnection import DbConnection
from cloudstackAPI import *
import random
import string
import hashlib
from codes import (FAILED, PASS, ADMIN, DOMAIN_ADMIN,
USER, SUCCESS, XEN_SERVER)
from configGenerator import ConfigManager
from marvin.lib import utils
from marvin.cloudstackConnection import CSConnection
from marvin.asyncJobMgr import asyncJobMgr
from marvin.dbConnection import DbConnection
from marvin.cloudstackAPI import *
from marvin.codes import (FAILED, PASS, ADMIN, DOMAIN_ADMIN,
USER, SUCCESS, XEN_SERVER)
from marvin.configGenerator import ConfigManager
from marvin.cloudstackException import GetDetailExceptionInfo
from marvin.lib.utils import (random_gen, validateList)
from marvin.cloudstackAPI.cloudstackAPIClient import CloudStackAPIClient
class CSTestClient(object):
'''
@Desc : CloudStackTestClient is encapsulated entity for creating and
getting various clients viz., apiclient,
@ -46,13 +43,14 @@ class CSTestClient(object):
logger : provides logging facilities for this library
zone : The zone on which test suites using this test client will run
'''
def __init__(self, mgmt_details,
dbsvr_details,
async_timeout=3600,
default_worker_threads=10,
logger=None,
test_data_filepath=None,
zone=None):
zone=None,
hypervisor_type=None):
self.__mgmtDetails = mgmt_details
self.__dbSvrDetails = dbsvr_details
self.__csConnection = None
@ -60,15 +58,15 @@ class CSTestClient(object):
self.__testClient = None
self.__asyncTimeOut = async_timeout
self.__logger = logger
self.__defaultWorkerThreads = default_worker_threads
self.__apiClient = None
self.__userApiClient = None
self.__asyncJobMgr = None
self.__id = None
self.__hypervisor = None
self.__hypervisor = hypervisor_type
self.__testDataFilePath = test_data_filepath
self.__parsedTestDataConfig = None
self.__zone = zone
self.__setHypervisorInfo()
@property
def identifier(self):
@ -96,36 +94,30 @@ class CSTestClient(object):
Even, if it is not available, return None
@Output : Returns the Zone Name
'''
if self.__zone is None:
if self.__parsedTestDataConfig:
ret = self.__parsedTestDataConfig.get("zone")
if ret != "NA":
self.__zone = ret
return self.__zone
def getHypervisorInfo(self):
'''
@Name : getHypervisorInfo
@Desc : Provides the hypervisor Information to test users
@Output : Return Hypervisor Information
'''
if not self.__hypervisor:
if self.__mgmtDetails.hypervisor:
self.__hypervisor = self.__mgmtDetails.hypervisor
else:
self.__hypervisor = XEN_SERVER
return self.__hypervisor
def __setHypervisorToClient(self):
def __setHypervisorInfo(self):
'''
@Name : ___setHypervisorToClient
@Desc: Set the HyperVisor Details under API Client;
default to Xen
@Name : __setHypervisorInfo
@Desc: Set the HyperVisor details;
default to XenServer
'''
if self.__mgmtDetails.hypervisor:
self.__apiClient.hypervisor = self.__mgmtDetails.hypervisor
else:
self.__apiClient.hypervisor = XEN_SERVER
try:
if not self.__hypervisor:
self.__hypervisor = XEN_SERVER
return SUCCESS
except Exception as e:
print "\n Exception Occurred Under __setHypervisorInfo " \
"%s" % GetDetailExceptionInfo(e)
return FAILED
def __createApiClient(self):
try:
@ -178,12 +170,8 @@ class CSTestClient(object):
self.__asyncTimeOut,
self.__logger)
self.__apiClient = CloudStackAPIClient(self.__csConnection)
'''
Set the HyperVisor Details to Client default to Xen
'''
self.__setHypervisorToClient()
return SUCCESS
except Exception, e:
except Exception as e:
self.__logger.exception(" Exception Occurred Under "
"__createApiClient: %s" %
GetDetailExceptionInfo(e))
@ -210,16 +198,18 @@ class CSTestClient(object):
'''
@Name : ___getKeys
@Desc : Retrieves the API and Secret Key for the provided Userid
@Input: userid: Userid to register
@Output: FAILED or tuple with apikey and secretkey
'''
try:
register_user = registerUserKeys.registerUserKeysCmd()
register_user.id = userid
register_user_res = \
self.__apiClient.registerUserKeys(register_user)
if register_user_res == FAILED:
if not register_user_res:
return FAILED
return (register_user_res.apikey, register_user_res.secretkey)
except Exception, e:
except Exception as e:
self.__logger.exception("Exception Occurred Under __geKeys : "
"%s" % GetDetailExceptionInfo(e))
return FAILED
@ -247,14 +237,21 @@ class CSTestClient(object):
configuration file. They can overwrite it with
providing their own configuration file as well.
'''
'''
1. Check Config,Zone,Hypervisor Information
'''
self.__configObj = ConfigManager(self.__testDataFilePath)
if self.__configObj:
self.__parsedTestDataConfig = self.__configObj.getConfig()
self.__logger.debug("Parsing Test data successful")
else:
self.__logger.error("createTestClient : Not able to create "
if not self.__configObj or not self.__hypervisor:
self.__logger.error("createTestClient : "
"Either Hypervisor is None or "
"Not able to create "
"ConfigManager Object")
return FAILED
self.__parsedTestDataConfig = self.__configObj.getConfig()
self.__logger.debug("Parsing Test data successful")
'''
2. Create DB Connection
'''
@ -265,12 +262,12 @@ class CSTestClient(object):
ret = self.__createApiClient()
if ret == FAILED:
self.__logger.\
error("********Test Client Creation Failed********")
error("==== Test Client Creation Failed ====")
else:
self.__logger.\
debug("********Test Client Creation Successful********")
debug("==== Test Client Creation Successful ====")
return ret
except Exception, e:
except Exception as e:
self.__logger.exception("Exception Occurred "
"Under createTestClient "
": %s" % GetDetailExceptionInfo(e))
@ -302,6 +299,10 @@ class CSTestClient(object):
@Name : ___createUserApiClient
@Desc : Creates a User API Client with given
UserName\DomainName Parameters
@Input: UserName: Username to be created in cloudstack
DomainName: Domain under which the above account be created
accType: Type of Account EX: Root,Non Root etc
@Output: Return the API client for the user
'''
try:
if not self.isAdminContext():
@ -364,9 +365,9 @@ class CSTestClient(object):
self.__csConnection.logger)
self.__userApiClient = CloudStackAPIClient(newUserConnection)
self.__userApiClient.connection = newUserConnection
self.__userApiClient.hypervisor = self.__apiClient.hypervisor
self.__userApiClient.hypervisor = self.__hypervisor
return self.__userApiClient
except Exception, e:
except Exception as e:
self.__logger.exception("Exception Occurred "
"Under getUserApiClient : %s" %
GetDetailExceptionInfo(e))
@ -399,16 +400,12 @@ class CSTestClient(object):
def getUserApiClient(self, account, domain, type=0):
"""
@Name : getUserApiClient
@Desc : Provides the User API Client to Users
@Desc : Provides the User API Client to test Users
0 - user ; 1 - admin;2 - domain admin
@OutPut : FAILED In case of an issue
else User API Client
"""
return FAILED if (self.__createUserApiClient(account,
domain,
type)
== FAILED) \
else self.__userApiClient
return self.__createUserApiClient(account, domain, type)
def submitCmdsAndWait(self, cmds, workers=1):
'''

View File

@ -25,6 +25,7 @@ import urllib2
class cmdParameterProperty(object):
def __init__(self):
self.name = None
self.required = False
@ -34,6 +35,7 @@ class cmdParameterProperty(object):
class cloudStackCmd(object):
def __init__(self):
self.name = ""
self.desc = ""
@ -43,6 +45,7 @@ class cloudStackCmd(object):
class CodeGenerator(object):
"""
Apache CloudStack- marvin python classes can be generated from the json
returned by API discovery or from the xml spec of commands generated by
@ -208,12 +211,12 @@ class CodeGenerator(object):
body += self.space + '@property' + self.newline
body += self.space + 'def id(self):' + self.newline
body += self.space*2 + 'return self._id' + self.newline
body += self.space * 2 + 'return self._id' + self.newline
body += self.newline
body += self.space + '@id.setter' + self.newline
body += self.space + 'def id(self, identifier):' + self.newline
body += self.space*2 + 'self._id = identifier' + self.newline
body += self.space * 2 + 'self._id = identifier' + self.newline
body += self.newline
for cmdName in self.cmdsName:
@ -340,7 +343,7 @@ class CodeGenerator(object):
paramProperty.desc = response['description']
if 'type' in response:
if response['type'] in ['list', 'map', 'set']:
#Here list becomes a subproperty
# Here list becomes a subproperty
if 'response' in response:
for innerResponse in response['response']:
subProperty =\
@ -394,7 +397,7 @@ class CodeGenerator(object):
csCmd.request.append(paramProperty)
for response in cmd['response']:
#FIXME: ExtractImage related APIs return empty dicts in response
# FIXME: ExtractImage related APIs return empty dicts in response
if len(response) > 0:
paramProperty = self.constructResponseFromJSON(response)
csCmd.response.append(paramProperty)

View File

@ -5,7 +5,8 @@ test_data = {
"regionendpoint": "http://region2:8080/client"
},
"zone": "NA",
"domain": { "name": "domain" },
"hypervisor": "XenServer",
"vdomain": { "name": "domain" },
"email" : "test@test.com",
"gateway" : "172.1.1.1",
"netmask" : "255.255.255.0",

View File

@ -25,6 +25,7 @@ from marvin.config.test_data import test_data
class managementServer(object):
def __init__(self):
self.mgtSvrIp = None
self.port = 8096
@ -36,6 +37,7 @@ class managementServer(object):
class dbServer(object):
def __init__(self):
self.dbSvr = None
self.port = 3306
@ -85,6 +87,7 @@ class zone(object):
class trafficType(object):
def __init__(self, typ, labeldict=None):
self.typ = typ # Guest/Management/Public
if labeldict:
@ -97,6 +100,7 @@ class trafficType(object):
class pod(object):
def __init__(self):
self.gateway = None
self.name = None
@ -111,6 +115,7 @@ class pod(object):
class VmwareDc(object):
def __init__(self):
self.zoneid = None
self.name = None
@ -120,6 +125,7 @@ class VmwareDc(object):
class cluster(object):
def __init__(self):
self.clustername = None
self.clustertype = None
@ -134,6 +140,7 @@ class cluster(object):
class host(object):
def __init__(self):
self.hypervisor = None
self.password = None
@ -151,6 +158,7 @@ class host(object):
class physicalNetwork(object):
def __init__(self):
self.name = None
self.tags = []
@ -165,6 +173,7 @@ class physicalNetwork(object):
class provider(object):
def __init__(self, name=None):
self.name = name
self.state = None
@ -175,6 +184,7 @@ class provider(object):
class network(object):
def __init__(self):
self.displaytext = None
self.name = None
@ -187,6 +197,7 @@ class network(object):
class iprange(object):
def __init__(self):
'''tagged/untagged'''
self.gateway = None
@ -200,12 +211,14 @@ class iprange(object):
class primaryStorage(object):
def __init__(self):
self.name = None
self.url = None
class secondaryStorage(object):
def __init__(self):
self.url = None
self.provider = None
@ -213,6 +226,7 @@ class secondaryStorage(object):
class cacheStorage(object):
def __init__(self):
self.url = None
self.provider = None
@ -220,6 +234,7 @@ class cacheStorage(object):
class s3(object):
def __init__(self):
self.accesskey = None
self.secretkey = None
@ -232,6 +247,7 @@ class s3(object):
class netscaler(object):
def __init__(self, hostname=None, username='nsroot', password='nsroot'):
self.hostname = hostname
self.username = username
@ -248,11 +264,12 @@ class netscaler(object):
def __repr__(self):
req = zip(self.__dict__.keys(), self.__dict__.values())
return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
for r in req])
return self.hostname + "?" + "&".join(["=".join([r[0], r[1]])
for r in req])
class srx(object):
def __init__(self, hostname=None, username='root', password='admin'):
self.hostname = hostname
self.username = username
@ -271,11 +288,12 @@ class srx(object):
def __repr__(self):
req = zip(self.__dict__.keys(), self.__dict__.values())
return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
for r in req])
return self.hostname + "?" + "&".join(["=".join([r[0], r[1]])
for r in req])
class bigip(object):
def __init__(self, hostname=None, username='root', password='default'):
self.hostname = hostname
self.username = username
@ -292,11 +310,12 @@ class bigip(object):
def __repr__(self):
req = zip(self.__dict__.keys(), self.__dict__.values())
return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
for r in req])
return self.hostname + "?" + "&".join(["=".join([r[0], r[1]])
for r in req])
class ConfigManager(object):
'''
@Name: ConfigManager
@Desc: 1. It provides the basic configuration facilities to marvin.
@ -328,6 +347,7 @@ class ConfigManager(object):
8. Users can use their own configuration file passed to
"getConfig" API,once configObj is returned.
'''
def __init__(self, cfg_file=None):
self.__filePath = cfg_file
self.__parsedCfgDict = None
@ -364,8 +384,8 @@ class ConfigManager(object):
configLines.append(ws)
config = json.loads("\n".join(configLines))
config_dict = config
except Exception, e:
#Will replace with log once we have logging done
except Exception as e:
# Will replace with log once we have logging done
print "\n Exception occurred under ConfigManager:__parseConfig" \
" :%s", GetDetailExceptionInfo(e)
finally:
@ -413,9 +433,9 @@ class ConfigManager(object):
def getDeviceUrl(obj):
req = zip(obj.__dict__.keys(), obj.__dict__.values())
if obj.hostname:
return "http://" + obj.hostname+"?" + "&".join(["=".join([r[0],
r[1]])
for r in req])
return "http://" + obj.hostname + "?" + "&".join(["=".join([r[0],
r[1]])
for r in req])
else:
return None
@ -430,11 +450,11 @@ def descSetupInBasicMode():
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)
z.name = "test" + str(l)
z.networktype = 'Basic'
z.securitygroupenabled = 'True'
#If security groups are reqd
# If security groups are reqd
sgprovider = provider()
sgprovider.broadcastdomainrange = 'Pod'
sgprovider.name = 'SecurityGroupProvider'
@ -460,15 +480,15 @@ def descSetupInBasicMode():
ip = iprange()
ip.gateway = p.gateway
ip.netmask = p.netmask
ip.startip = "192.168.%d.%d" % (i, j*20)
ip.endip = "192.168.%d.%d" % (i, j*20+10)
ip.startip = "192.168.%d.%d" % (i, j * 20)
ip.endip = "192.168.%d.%d" % (i, j * 20 + 10)
p.guestIpRanges.append(ip)
'''add 10 clusters'''
for j in range(2):
c = cluster()
c.clustername = "test"+str(l)+str(i) + str(j)
c.clustername = "test" + str(l) + str(i) + str(j)
c.clustertype = "CloudManaged"
c.hypervisor = "Simulator"
@ -477,15 +497,16 @@ def descSetupInBasicMode():
h = host()
h.username = "root"
h.password = "password"
memory = 8*1024*1024*1024
localstorage = 1*1024*1024*1024*1024
memory = 8 * 1024 * 1024 * 1024
localstorage = 1 * 1024 * 1024 * 1024 * 1024
h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
c.hosts.append(h)
'''add 2 primary storages'''
for m in range(2):
primary = primaryStorage()
primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
primary.name = "primary" + \
str(l) + str(i) + str(j) + str(m)
primary.url = "nfs://localhost/path%s" % (str(l) + str(i) +
str(j) + str(m))
c.primaryStorages.append(primary)
@ -497,7 +518,7 @@ def descSetupInBasicMode():
'''add two secondary'''
for i in range(5):
secondary = secondaryStorage()
secondary.url = "nfs://localhost/path"+str(l) + str(i)
secondary.url = "nfs://localhost/path" + str(l) + str(i)
z.secondaryStorages.append(secondary)
zs.zones.append(z)
@ -539,7 +560,7 @@ def descSetupInEipMode():
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)
z.name = "test" + str(l)
z.networktype = 'Basic'
ips = iprange()
@ -550,7 +571,7 @@ def descSetupInEipMode():
ips.netmask = "255.255.255.0"
z.ipranges.append(ips)
#If security groups are reqd
# If security groups are reqd
sgprovider = provider()
sgprovider.broadcastdomainrange = 'Pod'
sgprovider.name = 'SecurityGroupProvider'
@ -584,15 +605,15 @@ def descSetupInEipMode():
ip = iprange()
ip.gateway = p.gateway
ip.netmask = p.netmask
ip.startip = "192.168.%d.%d" % (i, j*20)
ip.endip = "192.168.%d.%d" % (i, j*20+10)
ip.startip = "192.168.%d.%d" % (i, j * 20)
ip.endip = "192.168.%d.%d" % (i, j * 20 + 10)
p.guestIpRanges.append(ip)
'''add 10 clusters'''
for j in range(2):
c = cluster()
c.clustername = "test"+str(l)+str(i) + str(j)
c.clustername = "test" + str(l) + str(i) + str(j)
c.clustertype = "CloudManaged"
c.hypervisor = "Simulator"
@ -607,7 +628,8 @@ def descSetupInEipMode():
'''add 2 primary storages'''
for m in range(2):
primary = primaryStorage()
primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
primary.name = "primary" + \
str(l) + str(i) + str(j) + str(m)
primary.url = "nfs://localhost/path%s" % (str(l) + str(i)
+ str(j)
+ str(m))
@ -620,7 +642,7 @@ def descSetupInEipMode():
'''add two secondary'''
for i in range(5):
secondary = secondaryStorage()
secondary.url = "nfs://localhost/path"+str(l) + str(i)
secondary.url = "nfs://localhost/path" + str(l) + str(i)
z.secondaryStorages.append(secondary)
zs.zones.append(z)
@ -660,7 +682,7 @@ def descSetupInAdvancedMode():
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)
z.name = "test" + str(l)
z.networktype = 'Advanced'
z.guestcidraddress = "10.1.1.0/24"
z.vlan = "100-2000"
@ -696,7 +718,7 @@ def descSetupInAdvancedMode():
'''add 10 clusters'''
for j in range(2):
c = cluster()
c.clustername = "test"+str(l)+str(i) + str(j)
c.clustername = "test" + str(l) + str(i) + str(j)
c.clustertype = "CloudManaged"
c.hypervisor = "Simulator"
@ -707,7 +729,7 @@ def descSetupInAdvancedMode():
h.password = "password"
memory = 8 * 1024 * 1024 * 1024
localstorage = 1 * 1024 * 1024 * 1024 * 1024
#h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
# h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
# memory=%d&localstorage=%d"%(l, i, j, k, memory,
# localstorage)
h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
@ -716,8 +738,9 @@ def descSetupInAdvancedMode():
'''add 2 primary storages'''
for m in range(2):
primary = primaryStorage()
primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
#primary.url = "nfs://localhost/path%s/size=%d" %
primary.name = "primary" + \
str(l) + str(i) + str(j) + str(m)
# primary.url = "nfs://localhost/path%s/size=%d" %
# (str(l) + str(i) + str(j) + str(m), size)
primary.url = "nfs://localhost/path%s" % (str(l) + str(i)
+ str(j)
@ -731,7 +754,7 @@ def descSetupInAdvancedMode():
'''add two secondary'''
for i in range(5):
secondary = secondaryStorage()
secondary.url = "nfs://localhost/path"+str(l) + str(i)
secondary.url = "nfs://localhost/path" + str(l) + str(i)
z.secondaryStorages.append(secondary)
'''add default public network'''
@ -781,7 +804,7 @@ def descSetupInAdvancedsgMode():
z.dns2 = "8.8.4.4"
z.internaldns1 = "192.168.110.254"
z.internaldns2 = "192.168.110.253"
z.name = "test"+str(l)
z.name = "test" + str(l)
z.networktype = 'Advanced'
z.vlan = "100-2000"
z.securitygroupenabled = "true"
@ -790,7 +813,7 @@ def descSetupInAdvancedsgMode():
pn.name = "test-network"
pn.traffictypes = [trafficType("Guest"), trafficType("Management")]
#If security groups are reqd
# If security groups are reqd
sgprovider = provider()
sgprovider.broadcastdomainrange = 'ZONE'
sgprovider.name = 'SecurityGroupProvider'
@ -810,7 +833,7 @@ def descSetupInAdvancedsgMode():
'''add 10 clusters'''
for j in range(2):
c = cluster()
c.clustername = "test"+str(l)+str(i) + str(j)
c.clustername = "test" + str(l) + str(i) + str(j)
c.clustertype = "CloudManaged"
c.hypervisor = "Simulator"
@ -821,17 +844,18 @@ def descSetupInAdvancedsgMode():
h.password = "password"
memory = 8 * 1024 * 1024 * 1024
localstorage = 1 * 1024 * 1024 * 1024 * 1024
#h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
#memory=%d&localstorage=%d" % (l, i, j, k, memory,
#localstorage)
# h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
# memory=%d&localstorage=%d" % (l, i, j, k, memory,
# localstorage)
h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
c.hosts.append(h)
'''add 2 primary storages'''
for m in range(2):
primary = primaryStorage()
primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
#primary.url = "nfs://localhost/path%s/size=%d" % \
primary.name = "primary" + \
str(l) + str(i) + str(j) + str(m)
# primary.url = "nfs://localhost/path%s/size=%d" % \
#(str(l) + str(i) + str(j) + str(m), size)
primary.url = "nfs://localhost/path%s" % \
(str(l) + str(i) + str(j) + str(m))
@ -844,7 +868,7 @@ def descSetupInAdvancedsgMode():
'''add two secondary'''
for i in range(5):
secondary = secondaryStorage()
secondary.url = "nfs://localhost/path"+str(l) + str(i)
secondary.url = "nfs://localhost/path" + str(l) + str(i)
z.secondaryStorages.append(secondary)
'''add default guest network'''
@ -904,7 +928,7 @@ def getSetupConfig(file):
configLines.append(ws)
config = json.loads("\n".join(configLines))
return jsonHelper.jsonLoader(config)
except Exception, e:
except Exception as e:
print "\nException Occurred under getSetupConfig %s" % \
GetDetailExceptionInfo(e)

View File

@ -26,6 +26,7 @@ import os
class DbConnection(object):
def __init__(self, host="localhost", port=3306, user='cloud',
passwd='cloud', db='cloud'):
self.host = host
@ -51,7 +52,7 @@ class DbConnection(object):
try:
resultRow = cursor.fetchall()
except errors.InterfaceError:
#Raised on empty result - DML
# Raised on empty result - DML
resultRow = []
return resultRow

View File

@ -15,13 +15,13 @@
# specific language governing permissions and limitations
# under the License.
from tcExecuteEngine import TestCaseExecuteEngine
from .tcExecuteEngine import TestCaseExecuteEngine
import sys
import os
import traceback
import time
from argparse import ArgumentParser
from marvinInit import MarvinInit
from .marvinInit import MarvinInit
from marvin.codes import (SUCCESS,
FAILED,
EXCEPTION,
@ -96,7 +96,7 @@ def startMarvin(cfg_file, load_flag):
else:
print "\nMarvin Initialization Failed"
exit(1)
except Exception, e:
except Exception as e:
print "\n Exception occurred while starting Marvin %s" % str(e)
exit(1)

File diff suppressed because it is too large Load Diff

View File

@ -18,11 +18,13 @@
import cloudstackException
import json
import inspect
from cloudstackAPI import *
from marvin.cloudstackAPI import *
class jsonLoader(object):
'''The recursive class for building and representing objects with.'''
def __init__(self, obj):
for k in obj:
v = obj[k]
@ -52,6 +54,7 @@ class jsonLoader(object):
class jsonDump(object):
@staticmethod
def __serialize(obj):
"""Recursively walk object's hierarchy."""
@ -247,7 +250,7 @@ due to missing parameter jobid"
}'''
try:
asynJob = getResultObj(result)
except cloudstackException.CloudstackAPIException, e:
except cloudstackException.CloudstackAPIException as e:
print e
result = '{ "queryasyncjobresultresponse" : {} }'

View File

@ -24,26 +24,17 @@ for starting it.
3. Deploys the Data Center based upon input.
'''
import marvin
from marvin import configGenerator
from marvin.configGenerator import getSetupConfig
from marvin.marvinLog import MarvinLog
from marvin.deployDataCenter import DeployDataCenters
from marvin.cloudstackTestClient import CSTestClient
from marvin.cloudstackException import GetDetailExceptionInfo
from marvin.codes import(
PASS,
YES,
NO,
XEN_SERVER,
SUCCESS,
FAILED
)
import sys
import time
import os
import logging
import string
import random
from sys import exit
class MarvinInit:
@ -51,7 +42,8 @@ class MarvinInit:
def __init__(self, config_file,
deploy_dc_flag=None,
test_mod_name="deploydc",
zone=None):
zone=None,
hypervisor_type=None):
self.__configFile = config_file
self.__deployFlag = deploy_dc_flag
self.__logFolderPath = None
@ -62,6 +54,7 @@ class MarvinInit:
self.__testDataFilePath = None
self.__zoneForTests = zone
self.__parsedConfig = None
self.__hypervisorType = hypervisor_type
def __parseConfig(self):
'''
@ -74,8 +67,7 @@ class MarvinInit:
if not os.path.isfile(self.__configFile):
print "\n=== Marvin Parse Config Init Failed ==="
return FAILED
self.__parsedConfig = configGenerator.\
getSetupConfig(self.__configFile)
self.__parsedConfig = getSetupConfig(self.__configFile)
print "\n=== Marvin Parse Config Successful ==="
return SUCCESS
except Exception as e:
@ -107,6 +99,26 @@ class MarvinInit:
"/results.txt", "w")
return self.__tcResultFile
def __setHypervisorAndZoneInfo(self):
'''
@Name : __setHypervisorAndZoneInfo
@Desc: Set the HyperVisor and Zone details;
default to XenServer
'''
try:
if not self.__hypervisorType:
self.__hypervisorType = XEN_SERVER
if not self.__zoneForTests:
if self.__parsedConfig:
for zone in self.__parsedConfig.zones:
self.__zoneForTests = zone.name
break
return SUCCESS
except Exception as e:
print "\n Exception Occurred Under init " \
"%s" % GetDetailExceptionInfo(e)
return FAILED
def init(self):
'''
@Name : init
@ -120,6 +132,7 @@ class MarvinInit:
'''
try:
if ((self.__parseConfig() != FAILED) and
(self.__setHypervisorAndZoneInfo())and
(self.__setTestDataPath() != FAILED) and
(self.__initLogging() != FAILED) and
(self.__createTestClient() != FAILED) and
@ -153,7 +166,7 @@ class MarvinInit:
if ret != FAILED:
self.__logFolderPath = log_obj.getLogFolderPath()
self.__tcRunLogger = log_obj.getLogger()
print "\n=== Marvin Init Logging Sccessful==="
print "\n=== Marvin Init Logging Successful==="
return SUCCESS
return FAILED
except Exception as e:
@ -175,11 +188,12 @@ class MarvinInit:
logger=self.__tcRunLogger,
test_data_filepath=
self.__testDataFilePath,
zone=self.__zoneForTests)
zone=self.__zoneForTests,
hypervisor_type=
self.__hypervisorType)
if self.__testClient:
return self.__testClient.createTestClient()
else:
return FAILED
return FAILED
except Exception as e:
print "\n Exception Occurred Under __createTestClient : %s" % \
GetDetailExceptionInfo(e)
@ -195,7 +209,7 @@ class MarvinInit:
if ((self.__parsedConfig.TestData is not None) and
(self.__parsedConfig.TestData.Path is not None)):
self.__testDataFilePath = self.__parsedConfig.TestData.Path
print "\n=== Marvin TestData Successful==="
print "\n=== Marvin Setting TestData Successful==="
return SUCCESS
except Exception as e:
print "\nException Occurred Under __setTestDataPath : %s" % \

View File

@ -28,6 +28,7 @@ from marvin.cloudstackException import GetDetailExceptionInfo
class MarvinLog:
'''
@Name : MarvinLog
@Desc : provides interface for logging to marvin
@ -89,7 +90,7 @@ class MarvinLog:
stream.setLevel(log_level)
self.__logger.addHandler(stream)
return SUCCESS
except Exception, e:
except Exception as e:
print "\nException Occurred Under " \
"__setLogHandler %s" % GetDetailExceptionInfo(e)
return FAILED
@ -104,7 +105,7 @@ class MarvinLog:
try:
if os.path.isdir(logfolder_to_remove):
os.rmdir(logfolder_to_remove)
except Exception, e:
except Exception as e:
print "\n Exception Occurred Under __cleanPreviousLogs :%s" % \
GetDetailExceptionInfo(e)
return FAILED
@ -151,8 +152,8 @@ class MarvinLog:
log_cfg.__dict__.get('LogFolderPath') + "/MarvinLogs"
self.__logFolderDir = temp_dir + "//" + temp_path
print "\n*********Log Folder Path: %s. " \
"All logs will be available here **************" \
print "\n==== Log Folder Path: %s. " \
"All logs will be available here ====" \
% str(self.__logFolderDir)
os.makedirs(self.__logFolderDir)
@ -171,7 +172,7 @@ class MarvinLog:
log_level=logging.FATAL)
return SUCCESS
return FAILED
except Exception, e:
except Exception as e:
print "\n Exception Occurred Under createLogs :%s" % \
GetDetailExceptionInfo(e)
return FAILED

View File

@ -61,7 +61,8 @@ class MarvinPlugin(Plugin):
self.__startTime = None
self.__testName = None
self.__tcRunLogger = None
self.__testModName = None
self.__testModName = ''
self.__hypervisorType = None
Plugin.__init__(self)
def configure(self, options, conf):
@ -70,15 +71,15 @@ class MarvinPlugin(Plugin):
self.enabled (True|False) determines whether marvin's tests will run.
By default non-default plugins like marvin will be disabled
"""
self.enabled = True
if hasattr(options, self.enableOpt):
if not getattr(options, self.enableOpt):
self.enabled = False
return
else:
self.enabled = True
self.__configFile = options.configFile
self.__deployDcFlag = options.deployDc
self.__zoneForTests = options.zone
self.__hypervisorType = options.hypervisor_type
self.conf = conf
if self.startMarvin() == FAILED:
print "\nStarting Marvin Failed, exiting. Please Check"
@ -105,6 +106,11 @@ class MarvinPlugin(Plugin):
default=None,
dest="zone",
help="Runs all tests against this specified zone")
parser.add_option("--hypervisor", action="store",
default=None,
dest="hypervisor_type",
help="Runs all tests against the specified "
"zone and hypervisor Type")
Plugin.options(self, parser, env)
def wantClass(self, cls):
@ -148,9 +154,10 @@ class MarvinPlugin(Plugin):
self._injectClients(cls)
def beforeTest(self, test):
#self.__testModName = test.__str__()
self.__testModName = test.__str__()
self.__testName = test.__str__().split()[0]
self.__testClient.identifier = '-'.join([self.__identifier, self.__testName])
self.__testClient.identifier = '-'.\
join([self.__identifier, self.__testName])
if self.__tcRunLogger:
self.__tcRunLogger.name = test.__str__()
@ -199,19 +206,6 @@ class MarvinPlugin(Plugin):
self.printMsg(FAILED, self.__testName, GetDetailExceptionInfo(err))
self.__testResult = FAILED
def __getModName(self, inp, type='file'):
'''
@Desc : Returns the module name from the path
@Output: trimmed down module name, used for logging
@Input: type:Whether the type is file or dir
inp:input element
'''
if type == 'file':
temp = os.path.splitext(inp)[0]
return os.path.split(temp)[-1]
if type == 'dir':
return os.path.split(inp)[-1]
def startMarvin(self):
'''
@Name : startMarvin
@ -225,7 +219,8 @@ class MarvinPlugin(Plugin):
obj_marvininit = MarvinInit(self.__configFile,
self.__deployDcFlag,
None,
self.__zoneForTests)
self.__zoneForTests,
self.__hypervisorType)
if obj_marvininit and obj_marvininit.init() == SUCCESS:
self.__testClient = obj_marvininit.getTestClient()
self.__tcRunLogger = obj_marvininit.getLogger()

View File

@ -28,19 +28,21 @@ import time
from marvin.cloudstackException import (
internalError,
GetDetailExceptionInfo
)
)
import contextlib
import logging
from marvin.codes import (
SUCCESS, FAILED, INVALID_INPUT, EXCEPTION_OCCURRED
)
)
from contextlib import closing
class SshClient(object):
'''
Added timeout flag for ssh connect calls.Default to 3.0 seconds
'''
def __init__(self, host, port, user, passwd, retries=20, delay=30,
log_lvl=logging.DEBUG, keyPairFiles=None, timeout=10.0):
self.host = None
@ -58,8 +60,8 @@ class SshClient(object):
ch.setLevel(log_lvl)
self.logger.addHandler(ch)
#Check invalid host value and raise exception
#Atleast host is required for connection
# Check invalid host value and raise exception
# Atleast host is required for connection
if host is not None and host != '':
self.host = host
if retries is not None and retries > 0:
@ -126,15 +128,15 @@ class SshClient(object):
% (str(self.host), str(self.port)))
ret = SUCCESS
break
except BadHostKeyException, e:
except BadHostKeyException as e:
except_msg = GetDetailExceptionInfo(e)
except AuthenticationException, e:
except AuthenticationException as e:
except_msg = GetDetailExceptionInfo(e)
except SSHException, e:
except SSHException as e:
except_msg = GetDetailExceptionInfo(e)
except socket.error, e:
except socket.error as e:
except_msg = GetDetailExceptionInfo(e)
except Exception, e:
except Exception as e:
except_msg = GetDetailExceptionInfo(e)
finally:
if self.retryCnt == 0 or ret == SUCCESS:
@ -188,7 +190,7 @@ class SshClient(object):
sftp = SFTPClient.from_transport(transport)
try:
sftp.put(srcFile, destPath)
except IOError, e:
except IOError as e:
raise e
def __del__(self):

View File

@ -23,6 +23,7 @@ from functools import partial
class TestCaseExecuteEngine(object):
def __init__(self, testclient, config, tc_logger=None, debug_stream=None):
"""
Initialize the testcase execution engine, just the basics here
@ -53,7 +54,7 @@ class TestCaseExecuteEngine(object):
if isinstance(test, unittest.BaseTestSuite):
self.injectTestCase(test)
else:
#inject testclient and logger into each unittest
# inject testclient and logger into each unittest
self.tcRunLogger.name = test.__str__()
setattr(test, "testClient", self.testclient)
setattr(test, "config", self.config)

View File

@ -23,6 +23,7 @@ from time import sleep as delay
class TestSetupSuccess(cloudstackTestCase):
"""
Test to verify if the cloudstack is ready to launch tests upon
1. Verify that system VMs are up and running in all zones