Open Kilda Java Documentation
rest.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 # Copyright 2017 Telstra Open Source
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 
17 from __future__ import absolute_import
18 
19 from bottle import get, post, request, run, Bottle, response, request, install
20 from mininet.net import Mininet
21 from mininet.node import RemoteController, OVSKernelSwitch, Host, OVSSwitch
22 from mininet.clean import cleanup
23 from mininet.link import TCLink
24 from mininet.util import errRun
25 
26 from jsonschema import validate
27 import logging
28 from logging.config import dictConfig
29 import json
30 import socket
31 import Queue
32 import threading
33 import time
34 import subprocess
35 from functools import wraps
36 
37 
40 
41 net = None # mininet object
42 
43 class KildaSwitch( OVSSwitch ):
44  "Add the OpenFlow13 Protocol"
45  def __init__(self,name,**params):
46  params['protocols'] = 'OpenFlow13'
47  OVSSwitch.__init__(self, name, **params)
48 
49  @classmethod
50  def batchStartup( cls, switches, run=errRun ):
51  """
52  Mininet looks for this during stop(). It exists in OVSSwitch. Kilda, at the moment,
53  doesn't like this batch operation (and it shouldn't be done in batch)
54  """
55  logger.info ("IGNORE batchStartup()")
56  for switch in switches:
57  if switch.batch:
58  logger.warn (" .... BATCH = TRUE !!!!!!")
59  return switches
60 
61  @classmethod
62  def batchShutdown( cls, switches, run=errRun ):
63  """
64  Mininet looks for this during stop(). It exists in OVSSwitch. Kilda, at the moment,
65  doesn't like this batch operation (and it shouldn't be done in batch)
66  """
67  logger.info ("IGNORE batchShutdown()")
68  for switch in switches:
69  if switch.batch:
70  logger.warn (" .... BATCH = TRUE !!!!!!")
71  return switches
72 
73 
74 def log_to_logger(fn):
75  '''
76  Wrap a Bottle request so that a log line is emitted after it's handled.
77  (This decorator can be extended to take the desired logger as a param.)
78  '''
79  @wraps(fn)
80  def _log_to_logger(*args, **kwargs):
81  actual_response = fn(*args, **kwargs)
82  logger.info('%s %s %s %s' % (request.remote_addr,
83  request.method,
84  request.url,
85  response.status))
86  return actual_response
87  return _log_to_logger
88 
89 
91  def _hatch(__):
92  def _hatchet():
93  for _ in pars:
94  if request.query.get(_) is None:
95  response.status = 500
96  return "%s: %s must be specified\n" % (request.path, _)
97  return __(dict([(_, request.query.get(_)) for _ in pars]))
98  return _hatchet
99  return _hatch
100 
101 
102 install(log_to_logger)
103 
104 topology_schema = {
105  "$schema": "http://json-schema.org/draft-04/schema#",
106  "type": "object",
107  "properties": {
108  "controllers": {
109  "type": "array",
110  "items": {
111  "type": "object",
112  "properties": {
113  "name": {
114  "type": "string"
115  },
116  "host": {
117  "type": "string"
118  },
119  "port": {
120  "type": "integer"
121  }
122  },
123  "required": [
124  "name",
125  "host",
126  "port"
127  ]
128  }
129  },
130  "links": {
131  "type": "array",
132  "items": {
133  "type": "object",
134  "properties": {
135  "node1": {
136  "type": "string"
137  },
138  "node2": {
139  "type": "string"
140  }
141  },
142  "required": [
143  "node1",
144  "node2"
145  ]
146  }
147  },
148  "switches": {
149  "type": "array",
150  "items": {
151  "type": "object",
152  "properties": {
153  "name": {
154  "type": "string"
155  },
156  "dpid": {
157  "type": "string"
158  }
159  },
160  "required": [
161  "name",
162  "dpid"
163  ]
164  }
165  }
166  },
167  "required": [
168  "controllers",
169  "links",
170  "switches"
171  ]
172 }
173 
174 switches_schema = {
175  "$schema": "http://json-schema.org/draft-04/schema#",
176  "type": "object",
177  "properties": {
178  "switches": {
179  "type": "array",
180  "items": {
181  "type": "object",
182  "properties": {
183  "name": {
184  "type": "string"
185  },
186  "dpid": {
187  "type": "string"
188  }
189  },
190  "required": [
191  "name",
192  "dpid"
193  ]
194  }
195  }
196  },
197  "required": [
198  "switches"
199  ]
200 }
201 
202 links_schema = {
203  "$schema": "http://json-schema.org/draft-04/schema#",
204  "type": "object",
205  "properties": {
206  "links": {
207  "type": "array",
208  "items": {
209  "type": "object",
210  "properties": {
211  "node1": {
212  "type": "string"
213  },
214  "node2": {
215  "type": "string"
216  }
217  },
218  "required": [
219  "node1",
220  "node2"
221  ]
222  }
223  }
224  },
225  "required": [
226  "links"
227  ]
228 }
229 
230 controllers_schema = {
231  "$schema": "http://json-schema.org/draft-04/schema#",
232  "type": "object",
233  "properties": {
234  "controllers": {
235  "type": "array",
236  "items": {
237  "type": "object",
238  "properties": {
239  "name": {
240  "type": "string"
241  },
242  "host": {
243  "type": "string"
244  },
245  "port": {
246  "type": "integer"
247  }
248  },
249  "required": [
250  "name",
251  "host",
252  "port"
253  ]
254  }
255  }
256  },
257  "required": [
258  "controllers"
259  ]
260 }
261 
262 
263 def controller_info(controller):
264  return {"name": controller.name,
265  "host": controller.ip,
266  "port": controller.port}
267 
268 
270  return [controller_info(x) for x in net.controllers]
271 
272 
273 def switch_info(switch):
274  intfs = []
275  if len(switch.intfs) > 0:
276  for i in switch.intfs:
277  intf = switch.intfs[i]
278  intfs.append({'name': intf.name,
279  'mac': intf.mac,
280  'status': intf.status()})
281  return {'name': switch.name,
282  'dpid': switch.dpid,
283  'connected': switch.connected(),
284  'interface': intfs}
285 
286 
287 def list_switch(name):
288  return (switch_info(net.switches[name]))
289 
290 
292  return [switch_info(x) for x in net.switches]
293 
294 
295 def link_name(link):
296  name = "{}:{}".format(link.intf1.name, link.intf2.name)
297  if link.intf1.name < link.intf2.name:
298  name = "{}:{}".format(link.intf2.name, link.intf1.name)
299  return name
300 
301 
302 def link_info(link):
303  return {'name': link_name(link), 'status': link.status()}
304 
305 
307  return [link_info(x) for x in net.links]
308 
309 
310 @post('/topology')
312  global net
313 
314  logger.info( "*** Creating Topology" )
315  validate(request.json, topology_schema)
316  net = Mininet( controller=RemoteController, switch=KildaSwitch, build=False )
317 
318  logger.info( "" )
319  logger.info( "*** Creating (Remote) controllers" )
320  for controller in request.json['controllers']:
321  name = controller['name']
322  host = controller['host']
323  port = controller['port']
324  logger.info("===> adding controller name={}, host={}, port={}".format(name, host, port))
325  ip = socket.gethostbyname(host)
326  net.addController (name, ip=ip, port=port)
327 
328  logger.info( "" )
329  logger.info( "*** Creating switches" )
330  for switch in request.json['switches']:
331  name = switch['name']
332  dpid = switch['dpid']
333  if type(dpid) is unicode:
334  dpid = dpid.encode('ascii','ignore')
335  logger.info("===> adding switch name={}, dpid={}".format(name, dpid))
336  net.addSwitch( name=name, dpid=dpid )
337 
338  logger.info( "" )
339  logger.info( "*** Creating Switch:Switch links" )
340  for link in request.json['links']:
341  node1 = link['node1']
342  node2 = link['node2']
343  logger.info("===> adding link {} -> {}".format(node1, node2))
344  net.addLink( node1, node2 )
345 
346  logger.info( "" )
347  logger.info( "*** Creating hosts\n" )
348  for switch in net.switches:
349  # add single host per switch .. sufficient for our strategy of testing flows
350  h = net.addHost( 'h%s' % switch.name)
351  net.addLink(h, switch)
352 
353  logger.info( "" )
354  logger.info( "*** Starting network" )
355  net.configHosts()
356  net.start()
357 
358  response.content_type = 'application/json'
359  result = json.dumps({'controllers': [controller_info(x) for x in net.controllers],
360  'switches': [switch_info(x) for x in net.switches],
361  'links': [link_info(x) for x in net.links]})
362  logger.info( "" )
363  logger.info ("*** returning {}".format(result))
364  logger.info( "" )
365  return result
366 
367 
368 #
369 # Create a linear topology with random links between the switches.
370 # - create N switches
371 # - create a random set of M links amongst the switches
372 #
373 @post('/create_random_linear_topology')
375 
376  #
377  # This code needs to be refactored to match the rest of this class.
378  # What changed? We moved off of local collections of controllers / switches / links and
379  # onto the Mininet way of doing things. This method used threading to add a bunch of
380  # switches and links in parallel .. we could look at Mininet's batch mechanism (I don't
381  # think it is any faster - it may just loop through things - so we'd need to figure out
382  # how to accelerate, if at all.
383  #
384  # Another possibility is to just delete this method, rely on the code above.
385  # In addition, we've implemented a simulator .. so as to remove the need for mininet/floodlight
386  # completely for scale tests (scale testing of everything except floodlight)
387  #
388  needs_to_be_refactored = True
389  if needs_to_be_refactored:
390  return json.dumps({'status': 'refactor me'})
391 
392  _switch_threads=[]
393  _link_threads=[]
394 
395  switch_count = request.json['switches']
396  link_count = request.json['links']
397  num_worker_threads = request.json.get('threads', 10)
398  logger.debug("==> switch count={}; link count={}; num threads = {}".
399  format(switch_count,link_count, num_worker_threads))
400 
401  add_controllers(request.json['controllers'])
402 
403 
406  names = Queue.Queue()
407  for i in range(switch_count):
408  name = "s" + str(i+1)
409  names.put(name)
410 
411  def add_switch_worker():
412  while True:
413  name = names.get()
414  switch = OVSKernelSwitch(name, protocols='OpenFlow13', inNamespace=False)
415  switches[name] = switch
416  switch.start(controllers)
417  # time to here, 5 switches : 0.88s, 50sw : 2.8 (15), 200 : 22s (33)
418  logger.debug("==> added switch name={}".format(name))
419  names.task_done()
420 
421  if num_worker_threads > len(_switch_threads):
422  logger.debug("==> Starting Switch Threads {} .. {}".
423  format(len(_switch_threads),num_worker_threads))
424  for i in range(len(_switch_threads), num_worker_threads):
425  t = threading.Thread(target=add_switch_worker)
426  t.daemon = True
427  _switch_threads.append(t)
428  t.start()
429  else:
430  logger.debug("==> Num Switch Threads is >= num_worker_threads {},{}".
431  format(len(_switch_threads),num_worker_threads))
432 
433  names.join() # block until all tasks are done
434 
435 
436 
439  ep_tuples = Queue.Queue()
440  # for i in range(link_count):
441  # ep1 = "s" + str(random.randint(1,switch_count));
442  # ep2 = "s" + str(random.randint(1,switch_count));
443  # ept = (ep1,ep2) # end point tuple
444  # ep_tuples.put(ept)
445 
446  for i in range(switch_count-1):
447  ep1 = "s" + str(i+1);
448  ep2 = "s" + str(i+2);
449  ept = (ep1,ep2) # end point tuple
450  ep_tuples.put(ept)
451 
452  lock = threading.Lock()
453  switch_locks = {}
454  for i in range(switch_count):
455  sid = "s" + str(i+1);
456  switch_locks[sid] = threading.Lock()
457 
458  def add_link_worker():
459  while True:
460  if ep_tuples.qsize() == 0:
461  time.sleep(5)
462  break
463 
464  success1 = success2 = False
465  ept = None
466  lock.acquire()
467  logger.debug("==> ++++ lock {}".format(threading.current_thread().getName()))
468  for _ in range (ep_tuples.qsize()):
469  ept = ep_tuples.get()
470  if ept:
471  success1 = switch_locks[ept[0]].acquire(False)
472  success2 = switch_locks[ept[1]].acquire(False)
473  logger.debug("==> switches ???? {} {} {} {}".format(ept[0],ept[1],success1, success2))
474  # if successful, process the tuple. Otherwise release the locks
475  if success1 and success2:
476  break
477  if success1: switch_locks[ept[0]].release()
478  if success2: switch_locks[ept[1]].release()
479  ep_tuples.put(ept) # put it back
480  ep_tuples.task_done() # since put increases the count; this round is "done"
481 
482  lock.release()
483  logger.debug("==> ---- lock {}".format(threading.current_thread().getName()))
484 
485  # if both are true, then we'll need to release locks at the end.
486  # if either aren't true, the resources will have already been released
487 
488  if success1 and success2:
489  placed = False
490  try:
491  link = TCLink(switches[ept[0]], switches[ept[1]])
492  link.intf1.node.attach(link.intf1)
493  link.intf2.node.attach(link.intf2)
494  links[link_name(link)] = link
495  placed = True
496  logger.debug("==> switches ++++ {} {}".format(ept[0],ept[1]))
497  except:
498  # Release the locks on the switches
499  logger.debug("==>==> ## ERROR adding link, putting back on queue={}".format(
500  ept))
501 
502  if not placed:
503  ep_tuples.put(ept)
504 
505  switch_locks[ept[0]].release()
506  switch_locks[ept[1]].release()
507  ep_tuples.task_done()
508  time.sleep(1)
509 
510  if num_worker_threads > len(_link_threads):
511  logger.debug("==> Starting Link Threads {} .. {}".
512  format(len(_link_threads),num_worker_threads))
513  for i in range(len(_link_threads),num_worker_threads):
514  t = threading.Thread(target=add_link_worker)
515  t.daemon = True
516  _link_threads.append(t)
517  t.start()
518  else:
519  logger.debug("==> Num Link Threads is >= num_worker_threads {},{}".
520  format(len(_link_threads),num_worker_threads))
521 
522 
523  while not ep_tuples.empty():
524  ep_tuples.join() # block until all tasks are done
525  logger.debug("==> LINKS: {} ".format(len(links)))
526  logger.debug("==> QUEUE: {} {}".format(ep_tuples.qsize(), ep_tuples.empty()))
527 
528  response.content_type = 'application/json'
529  return json.dumps({'status': 'ok'})
530 
531 
532 @get('/switch/<name>')
533 def get_switch(name):
534  response.content_type = 'application/json'
535  return json.dumps(list_switch(name))
536 
537 
538 @get('/switch')
540  response.content_type = 'appliation/json'
541  return json.dumps({'switches': list_switches()})
542 
543 
544 @post('/switch')
546  validate(request.json, switches_schema)
547  add_switches(request.json['switches'])
548  response.content_type = 'application/json'
549  return json.dumps(list_switches())
550 
551 
552 @get('/links')
553 def get_links():
554  response.content_type = 'application/json'
555  return json.dumps({"links": list_links()})
556 
557 
558 @post('/links')
560  validate(request.json, links_schema)
561  add_links(request.json['links'])
562  response.content_type = 'application/json'
563  return json.dumps({"links": list_links()})
564 
565 
566 @get('/controllers')
568  response.content_type = 'application/json'
569  return json.dumps(list_controllers())
570 
571 
572 @post('/controller')
574  validate(request.json, controllers_schema)
575  add_controllers(request.json['controllers'])
576  response.content_type = 'application/json'
577  return json.dumps(list_controllers())
578 
579 
580 @post('/cleanup')
582  global net
583  logger.info( "*** Clean Topology" )
584  if net is not None:
585  logger.info( "--> calling mininet.stop()" )
586  net.stop()
587  net = None
588  cleanup()
589  return {'status': 'ok'}
590 
591 
592 @get('/status')
593 def status():
594  return {'status': 'ok'}
595 
596 
597 def start_server(interface, port):
598  run(host='0.0.0.0', port=port, debug=True)
599 
600 
601 
610 
611 def get_output_actions(in_vlan,out_vlan):
612  """
613  This is to setup rules for host to switch / switch to host.
614  It honors what we are trying to accomlish with testing Kilda:
615  1) Kilda will put rules on one or more switches
616  2) This code will put rules on the switches outside that set. For instance, if we are
617  testing Kilda in a single switch scenario (s3), then this code will be used
618  to put rules on s2 and s4 so that s3 can be tested properly.
619  3) To keep things simple, we leverage the host attached to s2 and s4 to do a ping
620  4) These rules setup the host to switch port as in, and then the switch to be tested as the
621  out port.
622  """
623  result = ""
624  if out_vlan == 0:
625  if in_vlan != 0:
626  result = "strip_vlan,"
627  else:
628  if in_vlan == 0:
629  result = "push_vlan:0x8100,mod_vlan_vid:{},".format(out_vlan)
630  else:
631  result = "mod_vlan_vid:{},".format(out_vlan)
632  return result
633 
634 
635 def add_single_switch_rules(switch_id,in_port,out_port,in_vlan=0,out_vlan=0):
636  """add reciprocal rules to a switch to emulate kilda rules"""
637 
638  logger.info("** Adding flows to {}".format(switch_id))
639 
640  in_match = "" if in_vlan == 0 else ",dl_vlan={}".format(in_vlan)
641  out_match = "" if out_vlan == 0 else ",dl_vlan={}".format(out_vlan)
642 
643  in_action = get_output_actions(in_vlan,out_vlan)
644  out_action = get_output_actions(out_vlan,in_vlan)
645 
646  noise = "idle_timeout=0,priority=1000"
647  in_rule = "{},in_port={}{},actions={}output:{}".format(noise, in_port, in_match, in_action, out_port)
648  out_rule = "{},in_port={}{},actions={}output:{}".format(noise, out_port, out_match, out_action, in_port)
649  print("ingress rule: {}".format(in_rule))
650  print("egress rule: {}".format(out_rule))
651  # Ingress
652  subprocess.Popen(["ovs-ofctl","-O","OpenFlow13","add-flow",switch_id,in_rule],
653  stdout=subprocess.PIPE).wait()
654  # Egress
655  subprocess.Popen(["ovs-ofctl","-O","OpenFlow13","add-flow",switch_id,out_rule],
656  stdout=subprocess.PIPE).wait()
657 
658  # ## If debugging, remove the comments below to see what the flow rules are
659  # result = subprocess.Popen(["ovs-ofctl","-O","OpenFlow13","dump-flows",switch_id],
660  # stdout=subprocess.PIPE).communicate()[0]
661  # logger.info(result)
662 
663 
664 def clear_single_switch_rules(switch_id,in_port,out_port):
665  """remove rules from switch 3 to emulate kilda clear rules"""
666  print("** Remove flows from {}".format(switch_id))
667  in_rule = "in_port={}".format(in_port)
668  out_rule = "in_port={}".format(out_port)
669  subprocess.Popen(["ovs-ofctl","-O","OpenFlow13","del-flows",switch_id,in_rule],
670  stdout=subprocess.PIPE).wait()
671  subprocess.Popen(["ovs-ofctl","-O","OpenFlow13","del-flows",switch_id,out_rule],
672  stdout=subprocess.PIPE).wait()
673 
674 
678 
679 
680 def pingable(host1, host2):
681  result = host1.cmd( 'ping -c1 -w1 %s' % (host2.IP()) )
682  lines = result.split("\n")
683  if "1 packets received" in lines[3]:
684  print "CONNECTION BETWEEN ", host1.IP(), "and", host2.IP()
685  return True
686  else:
687  print "NO CONNECTION BETWEEN ", host1.IP(), "and", host2.IP()
688  return False
689 
690 
691 @get('/checkpingtraffic')
692 @required_parameters("srcswitch", "dstswitch", "srcport", "dstport", "srcvlan",
693  "dstvlan")
695  """
696  Algorithm:
697  1) add host/switch ingress/egress rules on Src and Dst
698  2) do the ping
699  3) remove host/switch ingress/egress rules on Src and Dst
700  """
701  # initial example:
702  #
703  # - test switch 3, using switches 2 and 4. s2 and s4 are sent in.
704  # - single switch "3" inport 1, outport 2
705  # - switch 2 needs to push packet from port 3 (h) to port 2 (s3), matching switch 3 rules
706  # - switch 2 needs to push packet from port 2 (s3) to port 3 (h) , should strip
707  # - switch 4 needs to push packet from port 3 (h) to port 1 (s3), matching switch 3 rules
708  # - switch 4 needs to push packet from port 1 (s3) to port 3 (h) , should strip
709  src_switch = p['srcswitch']
710  src_port = p['srcport']
711  src_vlan = int(p['srcvlan'])
712  dst_switch = p['dstswitch']
713  dst_port = p['dstport']
714  dst_vlan = int(p['dstvlan'])
715 
716  logger.info( "** PING request received: src={}:{}x{} dst={}:{}x{}".format(
717  src_switch,src_port,src_vlan,dst_switch,dst_port,dst_vlan
718  ))
719 
720  # TODO: better to find the host port, vs encoding the heuristic
721  src_host_port = 2 if src_switch == "00000001" else 3 # all hosts are on port 3, except first switch
722  dst_host_port = 3
723 
724  logger.info ( "--> adding host/switch rules" )
725  # for src port (ingress): inport = 2 or 3, no vlan ... send to srcport,srcvlan
726  # for src port (egress): Opposite of ingress .. inport = srcport,srcvlan ... 2 or 3, no vlan
727  # for dst port .. same strategy
728  add_single_switch_rules( src_switch, src_host_port, src_port, 0, src_vlan )
729  add_single_switch_rules( dst_switch, dst_host_port, dst_port, 0, dst_vlan )
730 
731  logger.info ( "--> ping" )
732  src_host = net.nameToNode["h%s" % src_switch]
733  dst_host = net.nameToNode["h%s" % dst_switch]
734  successful_ping = pingable(src_host, dst_host)
735 
736  logger.info ( "--> remove host/switch rules" )
737  clear_single_switch_rules( src_switch, src_host_port, src_port )
738  clear_single_switch_rules( dst_switch, dst_host_port, dst_port )
739 
740  if successful_ping:
741  response.status = 200
742  return "True"
743  else:
744  response.status = 503
745  return "False"
746 
747 
748 ofctl_start='ovs-ofctl -O OpenFlow13 add-flow'
749 
750 @get("/add_default_flows")
751 @required_parameters("switch")
753  switch = p['switch']
754  cmd1 = "%s %s idle_timeout=0,priority=1,actions=drop" % (ofctl_start, switch)
755  cmd2 = "%s %s idle_timeout=0,priority=2,dl_type=0x88cc,action=output:controller" % (ofctl_start, switch)
756  result1 = os.system(cmd1)
757  result2 = os.system(cmd2)
758  return {'result1': result1, 'result2': result2}
759 
760 
761 @get("/add_ingress_flow")
762 @required_parameters("switch","inport","vlan","outport","priority")
764  switch = p['switch']
765  inport = p['inport']
766  vlan = p['vlan']
767  outport = p['outport']
768  priority = p['priority']
769 
770  cmd1 = "%s %s idle_timeout=0,priority=%s,in_port=%s,actions=push_vlan:0x8100,mod_vlan_vid:%s,output:%s" % \
771  (ofctl_start, switch,priority,inport,vlan,outport)
772  result1 = os.system(cmd1)
773  return {'result1': result1}
774 
775 
776 @get("/add_egress_flow")
777 @required_parameters("switch","inport","vlan","outport","priority")
779  switch = p['switch']
780  inport = p['inport']
781  vlan = p['vlan']
782  outport = p['outport']
783  priority = p['priority']
784 
785  cmd1 = "%s %s idle_timeout=0,priority=%s,in_port=%s,dl_vlan=%s,actions=strip_vlan,output:%s" % \
786  (ofctl_start, switch,priority,inport,vlan,outport)
787  result1 = os.system(cmd1)
788  return {'result1': result1}
789 
790 
791 @get("/add_transit_flow")
792 @required_parameters("switch","inport","vlan","outport","priority")
794  switch = p['switch']
795  inport = p['inport']
796  vlan = p['vlan']
797  outport = p['outport']
798  priority = p['priority']
799 
800  cmd1 = "%s %s idle_timeout=0,priority=%s,in_port=%s,dl_vlan=%s,actions=output:%s" % \
801  (ofctl_start, switch,priority,inport,vlan,outport)
802  result1 = os.system(cmd1)
803  return {'result1': result1}
804 
805 # Declare the variables before the init
806 def init():
807  """Get the global variables defined and initialized"""
808  global logger
809 
810  with open("/app/log.json", "r") as fd:
811  logging.config.dictConfig(json.load(fd))
812 
813  logger = logging.getLogger()
814 
815 
816 def main():
817  init()
818  start_server('0.0.0.0', 38080)
819 
820 
821 if __name__ == '__main__':
822  main()
def add_transit_flow(p)
Definition: rest.py:793
def new_topology()
Definition: rest.py:311
def add_default_flows(p)
Definition: rest.py:752
def switch_info(switch)
Definition: rest.py:273
def log_to_logger(fn)
Definition: rest.py:74
def get(section, option)
Definition: config.py:43
def list_switches()
Definition: rest.py:291
def batchStartup(cls, switches, run=errRun)
Definition: rest.py:50
def list_links()
Definition: rest.py:306
def start_server(interface, port)
Definition: rest.py:597
def add_egress_flow(p)
Definition: rest.py:778
def get_switch(name)
Definition: rest.py:533
def mininet_cleanup()
Definition: rest.py:581
def check_ping_traffic(p)
Definition: rest.py:694
def status()
Definition: rest.py:593
def controller_info(controller)
Definition: rest.py:263
def list_controllers()
Definition: rest.py:269
def required_parameters(pars)
Definition: rest.py:90
def pingable(host1, host2)
Definition: rest.py:680
def get_switches()
Definition: rest.py:539
def create_links()
Definition: rest.py:559
def link_name(link)
Definition: rest.py:295
def get_output_actions(in_vlan, out_vlan)
Flow Debugging Section.
Definition: rest.py:611
def create_controller()
Definition: rest.py:573
def list_switch(name)
Definition: rest.py:287
def add_ingress_flow(p)
Definition: rest.py:763
def get_controllers()
Definition: rest.py:567
def clear_single_switch_rules(switch_id, in_port, out_port)
Definition: rest.py:664
def get_links()
Definition: rest.py:553
def create_topology()
Definition: rest.py:374
def __init__(self, name, params)
Definition: rest.py:45
def add_single_switch_rules(switch_id, in_port, out_port, in_vlan=0, out_vlan=0)
Definition: rest.py:635
def link_info(link)
Definition: rest.py:302
def batchShutdown(cls, switches, run=errRun)
Definition: rest.py:62
def create_switches()
Definition: rest.py:545