3 # Copyright (c) 2017 IXIA and others.
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
15 from functest.opnfv_tests.vnf.ims.ixia.utils import IxRestUtils
18 kActionStateFinished = 'finished'
19 kActionStatusSuccessful = 'Successful'
20 kActionStatusError = 'Error'
21 kTestStateUnconfigured = 'Unconfigured'
23 logger = logging.getLogger(__name__)
26 def stripApiAndVersionFromURL(url):
28 # remove the slash (if any) at the beginning of the url
33 urlElements = url.split('/')
36 # strip the api/v0 part of the url
38 urlElements = urlElements[2:]
40 return '/'.join(urlElements)
43 def waitForActionToFinish(connection, replyObj, actionUrl):
45 This method waits for an action to finish executing. after a POST request
46 is sent in order to start an action, The HTTP reply will contain,
47 in the header, a 'location' field, that contains an URL.
48 The action URL contains the status of the action. we perform a GET on that
49 URL every 0.5 seconds until the action finishes with a success.
50 If the action fails, we will throw an error and
51 print the action's error message.
54 actionResultURL = replyObj.headers.get('location')
56 actionResultURL = stripApiAndVersionFromURL(actionResultURL)
57 actionFinished = False
59 while not actionFinished:
60 actionStatusObj = connection.httpGet(actionResultURL)
62 if actionStatusObj.state == kActionStateFinished:
63 if actionStatusObj.status == kActionStatusSuccessful:
66 errorMsg = "Error while executing action '%s'." \
69 if actionStatusObj.status == kActionStatusError:
70 errorMsg += actionStatusObj.error
79 def performGenericOperation(connection, url, payloadDict):
81 This will perform a generic operation on the given url,
82 it will wait for it to finish.
85 data = IxRestUtils.formatDictToJSONPayload(payloadDict)
86 reply = connection.httpPost(url=url, data=data)
88 waitForActionToFinish(connection, reply, url)
93 def performGenericPost(connection, listUrl, payloadDict):
95 This will perform a generic POST method on a given url
98 data = IxRestUtils.formatDictToJSONPayload(payloadDict)
100 reply = connection.httpPost(url=listUrl, data=data)
102 newObjPath = reply.headers['location']
104 raise Exception('Location header is not present. \
105 Please check if the action was created successfully.')
107 newObjID = newObjPath.split('/')[-1]
111 def performGenericDelete(connection, listUrl, payloadDict):
113 This will perform a generic DELETE method on a given url
116 data = IxRestUtils.formatDictToJSONPayload(payloadDict)
118 reply = connection.httpDelete(url=listUrl, data=data)
122 def performGenericPatch(connection, url, payloadDict):
124 This will perform a generic PATCH method on a given url
127 data = IxRestUtils.formatDictToJSONPayload(payloadDict)
129 reply = connection.httpPatch(url=url, data=data)
133 def createSession(connection, ixLoadVersion):
135 This method is used to create a new session.
136 It will return the url of the newly created session
139 sessionsUrl = 'sessions'
140 data = {'ixLoadVersion': ixLoadVersion}
142 sessionId = performGenericPost(connection, sessionsUrl, data)
144 newSessionUrl = '%s/%s' % (sessionsUrl, sessionId)
145 startSessionUrl = '%s/operations/start' % newSessionUrl
149 performGenericOperation(connection, startSessionUrl, {})
151 logger.debug('Created session no %s' % sessionId)
156 def deleteSession(connection, sessionUrl):
158 This method is used to delete an existing session.
162 performGenericDelete(connection, sessionUrl, deleteParams)
165 def uploadFile(connection, url, fileName, uploadPath, overwrite=True):
166 headers = {'Content-Type': 'multipart/form-data'}
167 params = {'overwrite': overwrite, 'uploadPath': uploadPath}
169 logger.debug('Uploading...')
171 with open(fileName, 'rb') as f:
172 resp = requests.post(url, data=f, params=params,
174 except requests.exceptions.ConnectionError, e:
175 raise Exception('Upload file failed. Received connection error. \
176 One common cause for this error is the size of the \
177 file to be uploaded.The web server sets a limit of 1GB\
178 for the uploaded file size. \
179 Received the following error: %s' % str(e))
181 raise Exception('Upload file failed. Received IO error: %s'
184 raise Exception('Upload file failed. Received the following error: %s'
187 logger.debug('Upload file finished.')
188 logger.debug('Response status code %s' % resp.status_code)
189 logger.debug('Response text %s' % resp.text)
192 def loadRepository(connection, sessionUrl, rxfFilePath):
194 This method will perform a POST request to load a repository.
197 loadTestUrl = '%s/ixload/test/operations/loadTest' % sessionUrl
198 data = {'fullPath': rxfFilePath}
200 performGenericOperation(connection, loadTestUrl, data)
203 def saveRxf(connection, sessionUrl, rxfFilePath):
205 This method saves the current rxf to the disk of the machine on
206 which the IxLoad instance is running.
209 saveRxfUrl = '%s/ixload/test/operations/saveAs' % sessionUrl
210 rxfFilePath = rxfFilePath.replace('\\', '\\\\')
211 data = {'fullPath': rxfFilePath, 'overWrite': 1}
213 performGenericOperation(connection, saveRxfUrl, data)
216 def runTest(connection, sessionUrl):
218 This method is used to start the currently loaded test.
219 After starting the 'Start Test' action, wait for the action to complete.
222 startRunUrl = '%s/ixload/test/operations/runTest' % sessionUrl
225 performGenericOperation(connection, startRunUrl, data)
228 def getTestCurrentState(connection, sessionUrl):
230 This method gets the test current state.
231 (for example - running, unconfigured, ..)
234 activeTestUrl = '%s/ixload/test/activeTest' % sessionUrl
235 testObj = connection.httpGet(activeTestUrl)
237 return testObj.currentState
240 def getTestRunError(connection, sessionUrl):
242 This method gets the error that appeared during the last test run.
243 If no error appeared (the test ran successfully),
244 the return value will be 'None'.
247 activeTestUrl = '%s/ixload/test/activeTest' % sessionUrl
248 testObj = connection.httpGet(activeTestUrl)
250 return testObj.testRunError
253 def waitForTestToReachUnconfiguredState(connection, sessionUrl):
255 This method waits for the current test to reach the 'Unconfigured' state.
258 while getTestCurrentState(connection, sessionUrl) \
259 != kTestStateUnconfigured:
263 def pollStats(connection, sessionUrl, watchedStatsDict, pollingInterval=4):
265 This method is used to poll the stats.
266 Polling stats is per request but this method does a continuous poll.
269 statSourceList = watchedStatsDict.keys()
272 collectedTimestamps = {}
277 for statSource in statSourceList[:]:
278 statSourceUrl = '%s/ixload/stats/%s/values' % (sessionUrl, statSource)
279 statSourceReply = connection.httpRequest('GET', statSourceUrl)
280 if statSourceReply.status_code != 200:
281 logger.debug("Warning - Stat source '%s' does not exist. \
282 Will ignore it." % statSource)
283 statSourceList.remove(statSource)
285 # check the test state, and poll stats while the test is still running
289 # the polling interval is configurable.
290 # by default, it's set to 4 seconds
292 time.sleep(pollingInterval)
294 for statSource in statSourceList:
295 valuesUrl = '%s/ixload/stats/%s/values' % (sessionUrl, statSource)
297 valuesObj = connection.httpGet(valuesUrl)
298 valuesDict = valuesObj.getOptions()
300 # get just the new timestamps - that were not previously
301 # retrieved in another stats polling iteration
303 newTimestamps = [int(timestamp) for timestamp in
304 valuesDict.keys() if timestamp
305 not in collectedTimestamps.get(statSource,
309 for timestamp in newTimestamps:
310 timeStampStr = str(timestamp)
312 collectedTimestamps.setdefault(
313 statSource, []).append(timeStampStr)
315 timestampDict = statsDict.setdefault(
316 statSource, {}).setdefault(timestamp, {})
318 # save the values for the current timestamp,
319 # and later print them
322 for (caption, value) in \
323 valuesDict[timeStampStr].getOptions().items():
324 if caption in watchedStatsDict[statSource]:
325 logger.info(' %s -> %s' % (caption, value))
326 timestampDict[caption] = value
328 testIsRunning = getTestCurrentState(connection, sessionUrl) \
331 logger.debug('Stopped receiving stats.')
335 def clearChassisList(connection, sessionUrl):
337 This method is used to clear the chassis list.
338 After execution no chassis should be available in the chassisListself.
341 chassisListUrl = '%s/ixload/chassischain/chassisList' % sessionUrl
343 performGenericDelete(connection, chassisListUrl, deleteParams)
346 def configureLicenseServer(connection, sessionUrl, licenseServerIp):
348 This method is used to clear the chassis list.
349 After execution no chassis should be available in the chassisList.
352 chassisListUrl = '%s/ixload/preferences' % sessionUrl
353 patchParams = {'licenseServer': licenseServerIp}
354 performGenericPatch(connection, chassisListUrl, patchParams)
357 def addChassisList(connection, sessionUrl, chassisList):
359 This method is used to add one or more chassis to the chassis list.
362 chassisListUrl = '%s/ixload/chassisChain/chassisList' % sessionUrl
364 for chassisName in chassisList:
365 data = {'name': chassisName}
366 chassisId = performGenericPost(connection, chassisListUrl, data)
368 # refresh the chassis
370 refreshConnectionUrl = '%s/%s/operations/refreshConnection' \
371 % (chassisListUrl, chassisId)
372 performGenericOperation(connection, refreshConnectionUrl, {})
375 def assignPorts(connection, sessionUrl, portListPerCommunity):
377 This method is used to assign ports from a connected chassis
378 to the required NetTraffics.
381 communtiyListUrl = '%s/ixload/test/activeTest/communityList' \
384 communityList = connection.httpGet(url=communtiyListUrl)
386 for community in communityList:
387 portListForCommunity = portListPerCommunity.get(community.name)
389 portListUrl = '%s/%s/network/portList' % (communtiyListUrl,
392 if portListForCommunity:
393 for portTuple in portListForCommunity:
394 (chassisId, cardId, portId) = portTuple
395 paramDict = {'chassisId': chassisId, 'cardId': cardId,
398 performGenericPost(connection, portListUrl, paramDict)