blob: 7cd73759a855de25231d036cd6ad23d367294806 [file] [log] [blame]
Gabe Black90623222017-01-18 19:52:28 +00001#!/usr/bin/env python
2import requests, sys, getopt, json
3
4COMMANDS = [ 'show','reset', 'add','delete','deploy',"V_BUFS","NUM_BUFS", "INPUT_MODE", "TX_MODE", "QUEUE_TYPE" ]
5trafficTypes = ['TSA_CP','TSA_UP', 'TAA_CP', 'TAA_UP']
6INPUT_MODES=["mmap","pfring","pfring_zc","dpdk"]
7TX_MODES=["frp_udp","frp_tcp","viv"]
8QUEUE_TYPES=["CLFFIFO","dpdk"]
9RESOURCE_NAMES = [ 'V_BUFS', 'NUM_BUFS', 'INPUT_MODE', 'TX_MODE', 'QUEUE_TYPE']
10
11settings = {
12 'ipAddress':'127.0.0.1',
13 'port':'8080',
14 'api_version':'v1.0',
15 'resource': 'vivs/1',
16 'operation':'GET',
17 'verbose': False,
18 'data': None
19 }
20
21class restClient:
22
23 def doIt( self, settings ):
24 try:
25 hdrs = { 'Accept':'application/json','content-type':'application/json' }
26 url = "http://%s:%s/%s" % ( settings['ipAddress'], settings['port'], settings['api_version'] )
27 if settings['resource']:
28 url = "%s/%s" % (url, settings['resource'])
29
30 if settings['operation'] == 'GET':
31 r = requests.get( url, headers = hdrs )
32 elif settings['operation'] == 'POST':
33 data = json.loads(settings['data'])
34 r = requests.post( url, data=json.dumps(data), headers = hdrs )
35
36 if r.status_code == requests.codes.ok:
37 if r.headers['content-type'] == 'application/json':
38 print json.dumps( r.json(), indent=4 )
39 else:
40 print "Received unexpected content type: %s" % r.headers['content-type']
41 if settings['verbose']:
42 print r.text
43
44 if settings['verbose']:
45 print "\nOperation:\n %s" % settings['operation']
46 print "\nURL:\n %s" % r.url
47 print "\nHeaders sent:\n %s" % r.request.headers
48 print "\nResponse status code:\n %s" % r.status_code
49
50 except requests.ConnectionError as e:
51 print e
52 raise # re-raise exception
53 except ValueError as e:
54 print "Invalid JSON: %s" % e
55 raise # re-raise exception
56
57
58def stringFromList( p ):
59 """
60 e.g. ['a', 'b', 'c' ] becomes "[a|b|c]"
61 """
62 return str( p ).replace("'","").replace(", ","|")
63
64def usage():
65 print "Usage:"
66 print " $ %s [-i ip][-p port][-a version][-v] command" % sys.argv[0]
67 print ""
68 print "optional arguments:"
69 print " -i <ip> IP address of server. (Default: 127.0.0.1)"
70 print " -p <port> Port on server. (Default: 8080)"
71 print " -a <version> API version to use. (Default: v1.0)"
72 print " -v Be verbose"
73 print ""
74 print "command"
75 print "-------"
76 print " show [<path>]"
77 print " add input <device> <type> [<type> [...]]"
78 print " add output <ip_address> <port> <type>"
79 print " delete input <device> [<type> [<type> [...]]]"
80 print " delete output <ip_address>[:<port>] [<type> [<type> [...]]]"
81 print " reset"
82 print " deploy"
83 print ""
84 print " V_BUFS <value>"
85 print " NUM_BUFS <value>"
86 print " INPUT_MODE <input-mode>"
87 print " TX_MODE <tx-mode>"
88 print " QUEUE_TYPE <queue-type>"
89 print ""
90 print ""
91 print " Where:"
92 print " <type> = %s" % stringFromList( trafficTypes )
93 print " <input_mode> = %s" % stringFromList(INPUT_MODES )
94 print " <tx-mode> = %s" % stringFromList( QUEUE_TYPES )
95 print ""
96
97
98def getTrafficTypes( args ):
99 traffic_types=[]
100 while len(args) > 0:
101 t = args.pop(0)
102 if t not in trafficTypes:
103 raise ValueError("Invalid traffic type '%s'" % t )
104 traffic_types.append( t )
105 return traffic_types
106
107def parseAddInputCommand( args ):
108 if len( args ) < 2:
109 raise ValueError("Usage: %s add input <device> <traffic_type> [<traffic_type> [...]]" % sys.argv[0] )
110
111 device = args.pop(0)
112 tt = getTrafficTypes( args )
113 data = { "inputs":[{"device":device,"traffic_types":tt}]}
114 settings['resource']='vivs/1/add'
115 settings['operation']='POST'
116 settings['data'] = json.dumps( data )
117
118def parseAddOutputCommand( args ):
119 if len( args ) != 3:
120 raise ValueError("Usage: %s add output <ip_address> <port> <traffic_type>" % sys.argv[0] )
121
122 ip_address = args.pop(0)
123 port = args.pop(0)
124 traffic_type = args.pop(0)
125 if traffic_type not in trafficTypes:
126 raise ValueError("Invalid traffic type '%s'" % traffic_type )
127
128 data = {"outputs":[{"ip_address":ip_address,"type":traffic_type,"port":port}]}
129 settings['resource']='vivs/1/add'
130 settings['operation']='POST'
131 settings['data'] = json.dumps( data )
132
133def parseDeleteInputCommand( args ):
134 if len( args ) < 1:
135 raise ValueError( "Usage: %s delete input <device> [<traffic_type> [<traffic_type> [...]]]" % sys.argv[0] )
136
137 device = args.pop(0)
138 tt = getTrafficTypes( args )
139 data = {"inputs":[{"device":device,"traffic_types":tt}]}
140 settings['resource']='vivs/1/delete'
141 settings['operation']='POST'
142 settings['data'] = json.dumps( data )
143
144def parseDeleteOutputCommand( args ):
145 if len(args) == 0:
146 raise ValueError( "Usage: %s delete output <ip_address>[:<port>] [<traffic_type> [<traffic_type> [...]]]" % sys.argv[0] )
147
148 ipp = args.pop(0).split(':')
149 ip_address = ipp[0]
150 try:
151 port = ipp[1]
152 except IndexError:
153 # No port was specified
154 # All ports with spec'd traffic types will be removed for
155 # the IP given.
156 port = None
157
158 tt = getTrafficTypes( args )
159 data = {"outputs":[{"ip_address":ip_address,"port":port, "traffic_types":tt}]}
160 settings['resource']='vivs/1/delete'
161 settings['operation']='POST'
162 settings['data'] = json.dumps( data )
163
164def parseArgs( argv ):
165 try:
166 opts,args = getopt.getopt( argv,
167 "i:p:a:vh", ["ip=","port=","api_version="])
168 except getopt.GetoptError as e:
169 print e
170 raise # re-raise exception
171 for opt,arg in opts:
172 if opt == '-h':
173 usage()
174 sys.exit()
175 elif opt == '-v':
176 settings['verbose'] = True
177 elif opt in ("-i","--ip"):
178 settings['ipAddress'] = arg
179 elif opt in ("-p","--port"):
180 settings['port'] = arg
181 elif opt in ("-a","--api_version"):
182 settings['api_version'] = arg
183
184 # process residual non option args
185 if len(args) == 0:
186 raise ValueError( "Expected one of: %s" % str( COMMANDS ) )
187
188 cmd = args.pop(0)
189 if cmd not in COMMANDS:
190 print 'Unknown command', cmd
191 sys.exit(1)
192
193 if cmd in ['show']:
194 if len(args) != 0:
195 settings['resource'] = args.pop(0)
196
197 elif cmd in ['reset']:
198 settings['resource']='vivs/1/reset'
199 settings['operation'] = 'POST'
200 settings['data'] = json.dumps( {} )
201
202 elif cmd in ['add']:
203
204 if len(args) == 0:
205 raise ValueError("Expected 'input' or 'output'")
206
207 direction = args.pop(0)
208 if direction not in ['input','output']:
209 raise ValueError( "expected 'input' or 'output', found '%s'" % direction )
210
211 if direction == 'input':
212 parseAddInputCommand( args )
213 else:
214 parseAddOutputCommand( args )
215
216 elif cmd in ['delete']:
217 if len(args) == 0:
218 raise ValueError("Expected 'input' or 'output'" )
219
220 direction = args.pop(0)
221 if direction not in ['input','output']:
222 raise ValueError("expected 'input' or 'output', found '%s'" % direction )
223
224 if direction == 'input':
225 parseDeleteInputCommand( args )
226 else:
227 parseDeleteOutputCommand( args )
228
229 elif cmd in ['deploy']:
230 settings['resource']='vivs/1/deploy'
231 settings['operation'] = 'POST'
232 settings['data'] = '{}'
233
234 else:
235
236 if cmd in RESOURCE_NAMES:
237 if len( args ) == 0 :
238 raise ValueError( 'No value supplied' )
239
240 val = args.pop(0)
241 # The server will complain if it does not like the value.
242 settings['resource']='vivs/1/%s' % cmd
243 settings['operation'] = 'POST'
244 settings['data'] = json.dumps( { cmd : val } )
245
246
247 return settings
248
249
250def RestClient(argv):
251 settings = parseArgs( argv )
252 client = restClient()
253 client.doIt( settings )
254
255
256if __name__ == '__main__':
257 try:
258 RestClient(sys.argv[1:])
259 except ValueError as e:
260 print e
261 sys.exit(2)
262 except getopt.GetoptError as e:
263 print e
264 sys.exit(3)
265 except requests.ConnectionError as e:
266 print e
267 sys.exit(4)
268