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 | |
| 9 | |
| 10 | class Loadgen_SB_thread: |
| 11 | ''' |
| 12 | 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''' |
| 13 | |
| 14 | '''response |
| 15 | [{'intent_id':'5','status':'CREATED','log':['created, time:73268214932534']}] |
| 16 | ''' |
| 17 | |
| 18 | def __init__(self, urls, intPerGroup, groups, addrate, delrate, pause): |
| 19 | self.intPerGroup = intPerGroup |
| 20 | self.groups = groups |
| 21 | self.urls = urls |
| 22 | self.addrate = addrate |
| 23 | self.delrate = delrate |
| 24 | self.pause = pause |
| 25 | |
| 26 | intents = [[0 for group in range(self.groups)] for i in range(self.intPerGroup)] |
| 27 | |
| 28 | def setIntJSN(self, node_id, intPerGroup, groups): |
| 29 | intents = [[None for a in range(self.intPerGroup)] for g in range(self.groups)] |
| 30 | id = 0 |
| 31 | oper = {} |
| 32 | for group in range(groups): |
| 33 | index = 0 |
| 34 | for i in range(intPerGroup / 2): |
| 35 | smac = str("%x" %(node_id * 0x100000000000 + 0x010000000000 + (group * 0x000001000000) +i + 1)) |
| 36 | dmac = str("%x" %(node_id * 0x100000000000 + 0x070000000000 + (group * 0x000001000000) +i + 1)) |
| 37 | srcMac = ':'.join(smac[i:i+2] for i in range(0, len(smac), 2)) |
| 38 | dstMac = ':'.join(dmac[i:i+2] for i in range(0, len(dmac), 2)) |
| 39 | srcSwitch = "00:00:00:00:00:00:00:01" |
| 40 | dstSwitch = "00:00:00:00:00:00:00:07" |
| 41 | srcPort = 1 |
| 42 | dstPort = 1 |
| 43 | |
| 44 | oper['intentId'] = id |
| 45 | oper['intentType'] = 'SHORTEST_PATH' # XXX: Hardcoded |
| 46 | oper['staticPath'] = False # XXX: Hardcoded |
| 47 | oper['srcSwitchDpid'] = srcSwitch |
| 48 | oper['srcSwitchPort'] = srcPort |
| 49 | oper['dstSwitchDpid'] = dstSwitch |
| 50 | oper['dstSwitchPort'] = dstPort |
| 51 | oper['matchSrcMac'] = srcMac |
| 52 | oper['matchDstMac'] = dstMac |
| 53 | intents[group][index] = oper |
| 54 | #print ("perGroup Intents-0 are: " + json.dumps(intents) + "\n\n\n" ) |
| 55 | index =index + 1 |
| 56 | id =id+1 |
| 57 | oper = {} |
| 58 | #print ("ID:" + str(id)) |
| 59 | |
| 60 | oper['intentId'] = id |
| 61 | oper['intentType'] = 'SHORTEST_PATH' # XXX: Hardcoded |
| 62 | oper['staticPath'] = False # XXX: Hardcoded |
| 63 | oper['srcSwitchDpid'] = dstSwitch |
| 64 | oper['srcSwitchPort'] = dstPort |
| 65 | oper['dstSwitchDpid'] = srcSwitch |
| 66 | oper['dstSwitchPort'] = srcPort |
| 67 | oper['matchSrcMac'] = dstMac |
| 68 | oper['matchDstMac'] = srcMac |
| 69 | intents[group][index] = oper |
| 70 | index = index + 1 |
| 71 | id = id + 1 |
| 72 | oper = {} |
| 73 | #print ("ID: " + str(id)) |
| 74 | #print ("perGroup Intents-1 are: " + json.dumps(intents) + "\n\n\n" ) |
| 75 | #print ("contructed intents are: " + json.dumps(intents) + "\n\n\n") |
| 76 | return intents, id |
| 77 | |
| 78 | def post_json(self, url, data): |
| 79 | """Make a REST POST call and return the JSON result |
| 80 | url: the URL to call |
| 81 | data: the data to POST""" |
| 82 | posturl = "http://%s/wm/onos/intent/high" %(url) |
| 83 | print ("\nPost url is : " + posturl + "\n") |
| 84 | parsed_result = [] |
| 85 | data_json = json.dumps(data) |
| 86 | try: |
| 87 | request = urllib2.Request(posturl, data_json) |
| 88 | request.add_header("Content-Type", "application/json") |
| 89 | response = urllib2.urlopen(request) |
| 90 | result = response.read() |
| 91 | response.close() |
| 92 | if len(result) != 0: |
| 93 | parsed_result = json.loads(result) |
| 94 | except HTTPError as exc: |
| 95 | print "ERROR:" |
| 96 | print " REST POST URL: %s" % posturl |
| 97 | # NOTE: exc.fp contains the object with the response payload |
| 98 | error_payload = json.loads(exc.fp.read()) |
| 99 | print " REST Error Code: %s" % (error_payload['code']) |
| 100 | print " REST Error Summary: %s" % (error_payload['summary']) |
| 101 | print " REST Error Description: %s" % (error_payload['formattedDescription']) |
| 102 | print " HTTP Error Code: %s" % exc.code |
| 103 | print " HTTP Error Reason: %s" % exc.reason |
| 104 | except URLError as exc: |
| 105 | print "ERROR:" |
| 106 | print " REST POST URL: %s" % posturl |
| 107 | print " URL Error Reason: %s" % exc.reason |
| 108 | return parsed_result |
| 109 | |
| 110 | def delete_json(self, url, startID): |
| 111 | """Make a REST DELETE call and return the JSON result |
| 112 | url: the URL to call""" |
| 113 | #url = "localhost:8080" |
| 114 | for i in range(self.intPerGroup): |
| 115 | posturl = "http://%s/wm/onos/intent/high/%s" %(url, str(i + startID)) |
| 116 | parsed_result = [] |
| 117 | try: |
| 118 | request = urllib2.Request(posturl) |
| 119 | request.get_method = lambda: 'DELETE' |
| 120 | response = urllib2.urlopen(request) |
| 121 | result = response.read() |
| 122 | response.close() |
| 123 | #if len(result) != 0: |
| 124 | # parsed_result = json.loads(result) |
| 125 | except HTTPError as exc: |
| 126 | print "ERROR:" |
| 127 | print " REST DELETE URL: %s" % posturl |
| 128 | # NOTE: exc.fp contains the object with the response payload |
| 129 | error_payload = json.loads(exc.fp.read()) |
| 130 | print " REST Error Code: %s" % (error_payload['code']) |
| 131 | print " REST Error Summary: %s" % (error_payload['summary']) |
| 132 | print " REST Error Description: %s" % (error_payload['formattedDescription']) |
| 133 | print " HTTP Error Code: %s" % exc.code |
| 134 | print " HTTP Error Reason: %s" % exc.reason |
| 135 | except URLError as exc: |
| 136 | print "ERROR:" |
| 137 | print " REST DELETE URL: %s" % posturl |
| 138 | print " URL Error Reason: %s" % exc.reason |
| 139 | return parsed_result |
| 140 | |
| 141 | def delete_all_json(self, url): |
| 142 | """Make a REST DELETE call and return the JSON result |
| 143 | url: the URL to call""" |
| 144 | #url = "localhost:8080" |
| 145 | posturl = "http://%s/wm/onos/intent/high" %(url) |
| 146 | parsed_result = [] |
| 147 | try: |
| 148 | request = urllib2.Request(posturl) |
| 149 | request.get_method = lambda: 'DELETE' |
| 150 | response = urllib2.urlopen(request) |
| 151 | result = response.read() |
| 152 | response.close() |
| 153 | if len(result) != 0: |
| 154 | parsed_result = json.loads(result) |
| 155 | except HTTPError as exc: |
| 156 | print "ERROR:" |
| 157 | print " REST DELETE URL: %s" % posturl |
| 158 | # NOTE: exc.fp contains the object with the response payload |
| 159 | error_payload = json.loads(exc.fp.read()) |
| 160 | print " REST Error Code: %s" % (error_payload['code']) |
| 161 | print " REST Error Summary: %s" % (error_payload['summary']) |
| 162 | print " REST Error Description: %s" % (error_payload['formattedDescription']) |
| 163 | print " HTTP Error Code: %s" % exc.code |
| 164 | print " HTTP Error Reason: %s" % exc.reason |
| 165 | except URLError as exc: |
| 166 | print "ERROR:" |
| 167 | print " REST DELETE URL: %s" % posturl |
| 168 | print " URL Error Reason: %s" % exc.reason |
| 169 | return parsed_result |
| 170 | |
| 171 | |
| 172 | if __name__ == '__main__': |
| 173 | import argparse |
| 174 | import threading |
| 175 | from threading import Thread |
| 176 | |
| 177 | parser = argparse.ArgumentParser(description="less script") |
| 178 | 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' ") |
| 179 | parser.add_argument("-i", "--intentsPerGroup", dest="intPerGroup", default=100, type=int, help="number of intents in one restcall group") |
| 180 | parser.add_argument("-g", "--groups", dest="groups", default=1, type=int, help="number of groups") |
| 181 | parser.add_argument("-a", "--addrate", dest="addrate", default=10, type=int, help="rate to add intents groups, groups per second") |
| 182 | parser.add_argument("-d", "--delrate", dest="delrate", default=100, type=int, help= "rate to delete intents, intents/second") |
| 183 | parser.add_argument("-p", "--pause", dest="pause", default=0, type=int, help= "pausing time between add and delete of intents") |
| 184 | args = parser.parse_args() |
| 185 | |
| 186 | myloadgen = Loadgen_SB_thread(args.urls, args.intPerGroup, args.groups, args.addrate, args.delrate, args.pause) |
| 187 | print ("Intent posting urls are: " + args.urls) |
| 188 | print ("Number of Intents per group: " + str(args.intPerGroup)) |
| 189 | print ("Number of Intent Groups: " + str(args.groups)) |
| 190 | print ("Intent group add rate: " + str(args.addrate) ) |
| 191 | print ("Intent delete rate:" + str(args.delrate) ) |
| 192 | addsleeptimer = (1.000/args.addrate) |
| 193 | print ("Add Sleep timer: " + str(addsleeptimer) ) |
| 194 | delsleeptimer = (1.000/args.delrate) |
| 195 | print ("Del Sleep timer: " + str(delsleeptimer) ) |
| 196 | print ("Pause between add and delete: " + str(args.pause)) |
| 197 | |
| 198 | urllist = args.urls.split() |
| 199 | urlindex = 0 |
| 200 | |
| 201 | intents,id = myloadgen.setIntJSN(7, args.intPerGroup, args.groups) |
| 202 | print json.dumps(intents) |
| 203 | print ("Number of intents: " + str(id) ) |
| 204 | print ("Number of url: " + str(len(urllist)) ) |
| 205 | |
| 206 | tstart = time.time() |
| 207 | for group in range(args.groups): |
| 208 | if urlindex < len(urllist): |
| 209 | realurlind = urlindex |
| 210 | else: |
| 211 | realurlind = 0 |
| 212 | urlindex = 0 |
| 213 | |
| 214 | u = str(urllist[realurlind]) |
| 215 | gstart = time.time() |
| 216 | #print json.dumps(intents[group]) |
| 217 | print ("urlindex is : " + str(urlindex) + "realurlindex is: " + str(realurlind)) |
| 218 | print ("post url is: " + str(urllist[realurlind]) ) |
| 219 | print ("intent group is : " + str(group)) |
| 220 | result = myloadgen.post_json(u,intents[group]) |
| 221 | #print ("post result: " + str(result)) |
| 222 | gelapse = time.time() - gstart |
| 223 | print ("Group: " + str(group) + " of " + str(args.groups) + " with " +str(args.intPerGroup) + " intents were added in " + str(gelapse) + " seconds.") |
| 224 | sleep(1.000/myloadgen.addrate) |
| 225 | urlindex = urlindex + 1 |
| 226 | |
| 227 | telapse = time.time() - tstart |
| 228 | print ( str(args.groups * args.intPerGroup) + " intents were added in " + str(telapse) + " seconds.") |
| 229 | |
| 230 | sleep(myloadgen.pause) |
| 231 | |
| 232 | urlindex = 0 |
| 233 | inID = 0 |
| 234 | tstart = time.time() |
| 235 | for group in range(args.groups): |
| 236 | if urlindex < len(urllist): |
| 237 | realurlind = urlindex |
| 238 | else: |
| 239 | realurlind = 0 |
| 240 | urlindex = 0 |
| 241 | |
| 242 | inID = group * args.intPerGroup |
| 243 | gstart = time.time() |
| 244 | u = str(urllist[realurlind]) |
| 245 | for i in range(args.intPerGroup): |
| 246 | result = myloadgen.delete_json(u, inID) |
| 247 | #print ("post result: " + str(result)) |
| 248 | gelapse = time.time() - gstart |
| 249 | print ("Group: " + str(group) + " of " + str(args.groups) " with " + str(args.intPerGroup) + " intents were deleted in " + str(gelapse) + " seconds.") |
| 250 | sleep(1.000/myloadgen.delrate) |
| 251 | urlindex = urlindex +1 |
| 252 | telapse = time.time() - tstart |
| 253 | print ( str(args.groups * args.intPerGroup) + " intents were deleted in " + str(telapse) + " seconds.") |
| 254 | |
| 255 | print ("Final cleanup to delete all intents on nodes." |
| 256 | for u in urllist: |
| 257 | myloadgen.delete_all(u) |