suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 1 | #! /usr/bin/env python |
| 2 | from time import time, sleep |
| 3 | import time |
| 4 | import json |
| 5 | import requests |
| 6 | import urllib2 |
| 7 | from urllib2 import URLError, HTTPError |
| 8 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 9 | ''' |
| 10 | This script is for Intent Throughput testing. Use linear 7-switch topo. Intents are from S1P1 to/from S7/P1, with incrementing src/dst Mac addresses. |
| 11 | ''' |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 12 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 13 | def setIntentJSN(node_id, intPerGroup, group_id, intent_id): |
| 14 | intents = [None for i in range(intPerGroup)] |
| 15 | oper = {} |
| 16 | index = 0 |
| 17 | for i in range(intPerGroup / 2): |
| 18 | smac = str("%x" %(node_id * 0x100000000000 + 0x010000000000 + (group_id * 0x000001000000) +i + 1)) |
| 19 | dmac = str("%x" %(node_id * 0x100000000000 + 0x070000000000 + (group_id * 0x000001000000) +i + 1)) |
| 20 | srcMac = ':'.join(smac[i:i+2] for i in range(0, len(smac), 2)) |
| 21 | dstMac = ':'.join(dmac[i:i+2] for i in range(0, len(dmac), 2)) |
| 22 | srcSwitch = "00:00:00:00:00:00:00:01" |
| 23 | dstSwitch = "00:00:00:00:00:00:00:07" |
| 24 | srcPort = 1 |
| 25 | dstPort = 1 |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 26 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 27 | oper['intentId'] = intent_id |
| 28 | oper['intentType'] = 'SHORTEST_PATH' # XXX: Hardcode |
| 29 | oper['staticPath'] = False # XXX: Hardcoded |
| 30 | oper['srcSwitchDpid'] = srcSwitch |
| 31 | oper['srcSwitchPort'] = srcPort |
| 32 | oper['dstSwitchDpid'] = dstSwitch |
| 33 | oper['dstSwitchPort'] = dstPort |
| 34 | oper['matchSrcMac'] = srcMac |
| 35 | oper['matchDstMac'] = dstMac |
| 36 | intents[index] = oper |
| 37 | #print ("perGroup Intents-0 are: " + json.dumps(intents) + "\n\n\n" ) |
| 38 | index += 1 |
| 39 | intent_id += 1 |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 40 | oper = {} |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 41 | #print ("ID:" + str(id)) |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 42 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 43 | oper['intentId'] = intent_id |
| 44 | oper['intentType'] = 'SHORTEST_PATH' # XXX: Hardcoded |
| 45 | oper['staticPath'] = False # XXX: Hardcoded |
| 46 | oper['srcSwitchDpid'] = dstSwitch |
| 47 | oper['srcSwitchPort'] = dstPort |
| 48 | oper['dstSwitchDpid'] = srcSwitch |
| 49 | oper['dstSwitchPort'] = srcPort |
| 50 | oper['matchSrcMac'] = dstMac |
| 51 | oper['matchDstMac'] = srcMac |
| 52 | intents[index] = oper |
| 53 | index += 1 |
| 54 | intent_id += 1 |
| 55 | oper = {} |
| 56 | #print ("ID: " + str(id)) |
| 57 | #print ("perGroup Intents-1 are: " + json.dumps(intents) + "\n\n\n" ) |
| 58 | #print ("contructed intents are: " + json.dumps(intents) + "\n\n\n") |
| 59 | return intents, intent_id |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 60 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 61 | def post_json(url, data): |
| 62 | """Make a REST POST call and return the JSON result |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 63 | url: the URL to call |
| 64 | data: the data to POST""" |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 65 | posturl = "http://%s/wm/onos/intent/high" %(url) |
| 66 | #print ("\nPost url is : " + posturl + "\n") |
| 67 | parsed_result = [] |
| 68 | data_json = json.dumps(data) |
| 69 | try: |
| 70 | request = urllib2.Request(posturl, data_json) |
| 71 | request.add_header("Content-Type", "application/json") |
| 72 | response = urllib2.urlopen(request) |
| 73 | result = response.read() |
| 74 | response.close() |
| 75 | if len(result) != 0: |
| 76 | parsed_result = json.loads(result) |
| 77 | except HTTPError as exc: |
| 78 | print "ERROR:" |
| 79 | print " REST POST URL: %s" % posturl |
| 80 | # NOTE: exc.fp contains the object with the response payload |
| 81 | error_payload = json.loads(exc.fp.read()) |
| 82 | print " REST Error Code: %s" % (error_payload['code']) |
| 83 | print " REST Error Summary: %s" % (error_payload['summary']) |
| 84 | print " REST Error Description: %s" % (error_payload['formattedDescription']) |
| 85 | print " HTTP Error Code: %s" % exc.code |
| 86 | print " HTTP Error Reason: %s" % exc.reason |
| 87 | except URLError as exc: |
| 88 | print "ERROR:" |
| 89 | print " REST POST URL: %s" % posturl |
| 90 | print " URL Error Reason: %s" % exc.reason |
| 91 | return parsed_result |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 92 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 93 | def delete_json(self, url, intPerGroup, startID): |
| 94 | """Make a REST DELETE call and return the JSON result |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 95 | url: the URL to call""" |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 96 | #url = "localhost:8080" |
| 97 | for i in range(intPerGroup): |
| 98 | posturl = "http://%s/wm/onos/intent/high/%s" %(url, str(i + startID)) |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 99 | parsed_result = [] |
| 100 | try: |
| 101 | request = urllib2.Request(posturl) |
| 102 | request.get_method = lambda: 'DELETE' |
| 103 | response = urllib2.urlopen(request) |
| 104 | result = response.read() |
| 105 | response.close() |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 106 | #if len(result) != 0: |
| 107 | # parsed_result = json.loads(result) |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 108 | except HTTPError as exc: |
| 109 | print "ERROR:" |
| 110 | print " REST DELETE URL: %s" % posturl |
| 111 | # NOTE: exc.fp contains the object with the response payload |
| 112 | error_payload = json.loads(exc.fp.read()) |
| 113 | print " REST Error Code: %s" % (error_payload['code']) |
| 114 | print " REST Error Summary: %s" % (error_payload['summary']) |
| 115 | print " REST Error Description: %s" % (error_payload['formattedDescription']) |
| 116 | print " HTTP Error Code: %s" % exc.code |
| 117 | print " HTTP Error Reason: %s" % exc.reason |
| 118 | except URLError as exc: |
| 119 | print "ERROR:" |
| 120 | print " REST DELETE URL: %s" % posturl |
| 121 | print " URL Error Reason: %s" % exc.reason |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 122 | return parsed_result |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 123 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 124 | def delete_all_json(url): |
| 125 | """Make a REST DELETE call and return the JSON result |
| 126 | url: the URL to call""" |
| 127 | #url = "localhost:8080" |
| 128 | posturl = "http://%s/wm/onos/intent/high" %(url) |
| 129 | parsed_result = [] |
| 130 | try: |
| 131 | request = urllib2.Request(posturl) |
| 132 | request.get_method = lambda: 'DELETE' |
| 133 | response = urllib2.urlopen(request) |
| 134 | result = response.read() |
| 135 | response.close() |
| 136 | if len(result) != 0: |
| 137 | parsed_result = json.loads(result) |
| 138 | except HTTPError as exc: |
| 139 | print "ERROR:" |
| 140 | print " REST DELETE URL: %s" % posturl |
| 141 | # NOTE: exc.fp contains the object with the response payload |
| 142 | error_payload = json.loads(exc.fp.read()) |
| 143 | print " REST Error Code: %s" % (error_payload['code']) |
| 144 | print " REST Error Summary: %s" % (error_payload['summary']) |
| 145 | print " REST Error Description: %s" % (error_payload['formattedDescription']) |
| 146 | print " HTTP Error Code: %s" % exc.code |
| 147 | print " HTTP Error Reason: %s" % exc.reason |
| 148 | except URLError as exc: |
| 149 | print "ERROR:" |
| 150 | print " REST DELETE URL: %s" % posturl |
| 151 | print " URL Error Reason: %s" % exc.reason |
| 152 | return parsed_result |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 153 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 154 | def loadIntents(node_id, urllist, intPerGroup, addrate, duration): |
| 155 | urlindex = 0 |
| 156 | group = 0 |
| 157 | start_id = 0 |
| 158 | sleeptimer = (1.000/addrate) |
| 159 | tstart = time.time() |
| 160 | while ( (time.time() - tstart) <= duration ): |
| 161 | if urlindex < len(urllist): |
| 162 | realurlind = urlindex |
| 163 | else: |
| 164 | realurlind = 0 |
| 165 | urlindex = 0 |
| 166 | |
| 167 | u = str(urllist[realurlind]) |
| 168 | gstart = time.time() |
| 169 | intents,start_id = setIntentJSN(node_id, intPerGroup, group, start_id) |
| 170 | #print (str(intents)) |
| 171 | #print ("Starting intent id: " + str(start_id)) |
| 172 | result = post_json(u, intents) |
| 173 | #print json.dumps(intents[group]) |
| 174 | #print ("post result: " + str(result)) |
| 175 | gelapse = time.time() - gstart |
| 176 | print ("Group: " + str(group) + " with " + str(intPerGroup) + " intents were added in " + str('%.3f' %gelapse) + " seconds.") |
| 177 | sleep(sleeptimer) |
| 178 | urlindex += 1 |
| 179 | group += 1 |
| 180 | |
| 181 | telapse = time.time() - tstart |
| 182 | #print ( "Number of groups: " + str(group) + "; Totoal " + str(args.groups * args.intPerGroup) + " intents were added in " + str(telapse) + " seconds.") |
| 183 | return telapse, group |
| 184 | |
| 185 | def main(): |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 186 | import argparse |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 187 | |
| 188 | parser = argparse.ArgumentParser(description="less script") |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 189 | parser.add_argument("-n", "--node_id", dest="node_id", default = 1, type=int, help="id of the node generating the intents, this is used to distinguish intents when multiple nodes are use to generate intents") |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 190 | parser.add_argument("-u", "--urls", dest="urls", default="10.128.10.1", type=str, help="a string to show urls to post intents to separated by space, ex. '10.128.10.1:8080 10.128.10.2:80080' ") |
| 191 | parser.add_argument("-i", "--intentsPerGroup", dest="intPerGroup", default=100, type=int, help="number of intents in one restcall group") |
suibin-onlab | 10e128a | 2014-08-07 09:59:16 -0700 | [diff] [blame] | 192 | parser.add_argument("-a", "--addrate", dest="addrate", default=10, type=float, help="rate to add intents groups, groups per second") |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 193 | parser.add_argument("-d", "--delrate", dest="delrate", default=100, type=float, help= "### Not Effective -for now intents are delete as bulk #### rate to delete intents, intents/second") |
| 194 | parser.add_argument("-l", "--length", dest="duration", default=300, type=int, help="duration/length of time the intents are posted") |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 195 | parser.add_argument("-p", "--pause", dest="pause", default=0, type=int, help= "pausing time between add and delete of intents") |
| 196 | args = parser.parse_args() |
| 197 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 198 | node_id = args.node_id |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 199 | urllist = args.urls.split() |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 200 | intPerGroup = args.intPerGroup |
| 201 | addrate = args.addrate |
| 202 | delrate = args.delrate |
| 203 | duration = args.duration |
| 204 | pause = args.pause |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 205 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 206 | print ("Intent posting urls are: " + str(urllist)) |
| 207 | print ("Number of Intents per group: " + str(intPerGroup)) |
| 208 | print ("Intent group add rate: " + str(addrate) ) |
| 209 | print ("Intent delete rate:" + str(delrate) ) |
| 210 | print ("Duration: " + str(duration) ) |
| 211 | print ("Pause between add and delete: " + str(args.pause)) |
| 212 | |
| 213 | telapse, group = loadIntents(node_id, urllist, intPerGroup, addrate, duration) |
| 214 | print ("\n\n#####################") |
| 215 | print ( str(group) + " groups " + " of " + str(intPerGroup) + " Intents per group - Total " + str(group * intPerGroup) + " intents were added in " + str('%.3f' %telapse) + " seconds.") |
| 216 | print ( "Effective intents posting rate is: " + str( '%.1f' %( (group * intPerGroup)/telapse ) ) + " Intents/second." ) |
| 217 | print ("#####################\n\n") |
| 218 | print ("Sleep for " + str(pause) + " seconds before deleting all intents...") |
| 219 | time.sleep(pause) |
| 220 | print ("Cleaning up intents in all nodes...") |
| 221 | for url in urllist: |
| 222 | delete_all_json(url) |
suibin-onlab | bf69cfc | 2014-08-06 11:07:06 -0700 | [diff] [blame] | 223 | |
suibin-onlab | 0a2a886 | 2014-08-08 11:11:46 -0700 | [diff] [blame] | 224 | if __name__ == '__main__': |
| 225 | main() |