Skip to content

Commit

Permalink
Support run individual commands with the -m option.
Browse files Browse the repository at this point in the history
yeasy committed Apr 1, 2014
1 parent e74e8e1 commit 3b85363
Showing 6 changed files with 188 additions and 94 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -101,6 +101,27 @@ EasyOVS: br-int> get
Current default bridge is br-int
```

###sh
`EasyOVS> sh cmd`

Run the system cmd locally, e.g., using ls -l to show local directory's content.
```
EasyOVS> sh ls -l
total 48
drwxr-xr-x. 2 root root 4096 Apr 1 14:34 bin
drwxr-xr-x. 5 root root 4096 Apr 1 14:56 build
drwxr-xr-x. 2 root root 4096 Apr 1 14:56 dist
drwxr-xr-x. 2 root root 4096 Apr 1 14:09 doc
drwxr-xr-x. 4 root root 4096 Apr 1 14:56 easyovs
-rw-r--r--. 1 root root 660 Apr 1 14:56 easyovs.1
drwxr-xr-x. 2 root root 4096 Apr 1 14:56 easyovs.egg-info
-rw-r--r--. 1 root root 2214 Apr 1 14:53 INSTALL
-rw-r--r--. 1 root root 1194 Apr 1 14:53 Makefile
-rw-r--r--. 1 root root 3836 Apr 1 14:53 README.md
-rw-r--r--. 1 root root 1177 Apr 1 14:53 setup.py
drwxr-xr-x. 2 root root 4096 Apr 1 14:09 util
```

###exit|quit
Input `exit` or `quit` to exit it.

@@ -112,6 +133,8 @@ Input `exit` or `quit` to exit it.
* Delete a flow with its id.
* Smart command completion, try tab everywhere.
* Support colorful output.
* Support run local system commands.
* Support run individual command with `-m cmd`

#Installation
Just run `sudo easyOVS/util/install.sh`.
54 changes: 49 additions & 5 deletions bin/easyovs
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import os
import sys
import time

from easyovs.bridge import brDelFlow,brDump,brList,brShow
from easyovs.cli import CLI
from easyovs.clean import cleanup
from easyovs.log import info, debug, error, output, LEVELS, lg
@@ -21,6 +22,11 @@ def version( *_args ):
print "%s" % VERSION
exit()

# optional tests to run
CMDS_ONE = ['cli', 'list']
CMDS_TWO = [ 'dump', 'show']
CMDS_THREE = ['delflow']

class Platform( object ):
"Build, setup, and run the platform."

@@ -42,6 +48,8 @@ class Platform( object ):
opts = OptionParser( description=desc, usage=usage )
opts.add_option( '--clean', '-c', action='store_true',
default=False, help='clean and exit' )
opts.add_option( '--cmd', '-m', type='string', default='cli',
help='Run customized commands for tests.' )
opts.add_option( '--verbosity', '-v', type='choice',
choices=LEVELS.keys(), default = 'info',
help = '|'.join( LEVELS.keys() ) )
@@ -59,20 +67,56 @@ class Platform( object ):
if LEVELS[self.options.verbosity] > LEVELS['output']:
print ( '*** WARNING: selected verbosity level (%s) will hide CLI '
'output!\n'
'Please restart Mininet with -v [debug, info, output].'
'Please restart easyOVS with -v [debug, info, output].'
% self.options.verbosity )
lg.setLogLevel( self.options.verbosity )

def begin( self ):
if self.options.clean:
cleanup()
exit()

start = time.time()
output("***\n Welcome to EasyOVS, type help to see available commands.\n***\n")
CLI()

cmd = self.options.cmd
if len(cmd.split())==1 and cmd in CMDS_ONE:
if cmd == 'cli':
CLI()
elif cmd == 'list':
self.list()
elif len(cmd.split()) == 2:
if cmd.split()[1] in CMDS_TWO: # e.g., br0 show
br,func =cmd.split()[0],cmd.split()[1]
getattr( self, func )(br)
elif cmd.split()[0] in CMDS_TWO: # e.g., show br0
func,br =cmd.split()[0],cmd.split()[1]
getattr( self, func )(br)
else:
output('Wrong command format is given\n')
elif len(cmd.split())==3:
if cmd.split()[1] in CMDS_THREE: # e.g., br0 delflow 9
br,func,arg =cmd.split()[0],cmd.split()[1],cmd.split()[2]
getattr( self, func )(br,arg)
elif cmd.split()[0] in CMDS_THREE: # e.g., delflow br0 9
func,br,arg =cmd.split()[0],cmd.split()[1],cmd.split()[2]
getattr( self, func )(br,arg)
else:
output('Wrong command format is given\n')
else:
output('Wrong command format is given\n')
elapsed = float( time.time() - start )
info( 'completed in %0.3f seconds\n' % elapsed )
info( '\n### Completed in %0.3f seconds ###\n' % elapsed )

def list(self):
brList()

def dump(self,br):
brDump(br)

def show(self,br):
brShow(br)

def delflow(self,br,flow_id):
brDelFlow(br,flow_id)

if __name__ == "__main__":
try:
76 changes: 72 additions & 4 deletions easyovs/bridge.py
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
from flow import Flow
from easyovs.log import output
from easyovs.util import fetchFollowingNum,fetchValueBefore,fetchValueBetween
from neutron import get_neutron_ports

def checkBr(func):
def wrapper(self,*arg):
@@ -35,6 +36,9 @@ def isExisted(self):

@checkBr
def delFlow(self,id):
"""
Return True or False to del the flow.
"""
if not self.flows:
self.updateFlows()
if id < 0 or id >= len(self.flows):
@@ -78,6 +82,7 @@ def delFlow(self,id):
f_new.close()
replace_cmd="ovs-ofctl replace-flows %s %s" %(self.bridge,flows_db_new)
result = Popen(replace_cmd,stdout=subprocess.PIPE,shell=True).stdout.read()
return True

@checkBr
def updateFlows(self,to_file=False):
@@ -161,7 +166,7 @@ def getPorts(self):
except Exception:
return {}
#output('%-8s%-16s%-16s\n' %('PORT','INTF','ADDR'))
br_list = brList()
br_list = getBridges()
for l in cmd_output.split('\n'):
if l.startswith(' ') and l.find('(')>=0 and l.find(')')>=0:
l=l.strip()
@@ -179,10 +184,12 @@ def getPorts(self):
return result

def brDelFlow(bridge,id):
try:
if type(id) == str and id.isdigit():
return Bridge(bridge).delFlow(int(id))
elif type(id) == int:
return Bridge(bridge).delFlow(id)
except Exception:
return None
else:
return False

def brGetFlows(bridge):
try:
@@ -209,6 +216,67 @@ def brGetPorts(bridge):
return {}

def brList():
"""
List available bridges.
"""
bridges = getBridges()
if not bridges:
output('None bridge exists.\n')
return
br_info = ''
for br in sorted(bridges.keys()):
br_info += "%s\n" %(br)
if bridges[br]['Port']:
br_info += " Port:\t\t%s\n" %(' '.join(bridges[br]['Port'].keys()))
if bridges[br]['Controller']:
br_info += " Controller:\t%s\n" %(' '.join(bridges[br]['Controller']))
if bridges[br]['fail_mode']:
br_info += " Fail_Mode:\t%s\n" %(bridges[br]['fail_mode'])
output(br_info)

def brDump(bridge):
"""
Dump the port information of a given bridges.
"""
flows=brGetFlows(bridge)
if flows:
Flow.bannerOutput()
for f in flows:
f.fmtOutput()

def brShow(bridge):
"""
Show information of a given bridges.
"""
ovs_ports = brGetPorts(bridge)
if not ovs_ports:
output('No port is found at bridge %s\n' %bridge)
return
neutron_ports = get_neutron_ports()
output('%-20s%-12s%-8s%-12s' %('Intf','Port','Tag','Type'))
if neutron_ports:
output('%-16s%-24s\n' %('vmIP','vmMAC'))
else:
output('\n')
content=[]
for intf in ovs_ports:
port,tag,type = ovs_ports[intf]['port'],ovs_ports[intf]['tag'],ovs_ports[intf]['type']
if neutron_ports and intf in neutron_ports:
vmIP, vmMac = neutron_ports[intf]['ip_address'],neutron_ports[intf]['mac']
else:
vmIP,vmMac = '', ''
content.append((intf,port,tag,type,vmIP,vmMac))
#output('%-20s%-8s%-16s%-24s%-8s\n' %(intf,port,vmIP,vmMac,tag))
content.sort(key=lambda x:x[0])
content.sort(key=lambda x:x[3])
for _ in content:
output('%-20s%-12s%-8s%-12s' %(_[0],_[1],_[2],_[3]))
if neutron_ports:
output('%-16s%-24s\n' %(_[4],_[5]))
else:
output('\n')

def getBridges():
"""
Return a dict of all available bridges, looks like
{
93 changes: 12 additions & 81 deletions easyovs/cli.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
from subprocess import call,Popen,PIPE
import sys

from easyovs.bridge import brDelFlow,brGetFlows,brIsExisted,brList,brGetPorts
from easyovs.bridge import brDelFlow,brDump,brIsExisted,brList,brShow
from flow import Flow
from easyovs.log import info, output, error
from easyovs.util import colorStr
@@ -39,6 +39,7 @@ def __init__( self, bridge=None, stdin=sys.stdin, script=None ):
self.inPoller = poll()
self.inPoller.register( stdin )
Cmd.__init__( self )
output("***\n Welcome to EasyOVS, type help to see available commands.\n***\n")
info( '*** Starting CLI:\n' )
while True:
try:
@@ -55,9 +56,11 @@ def do_delflow(self,arg):
Del a flow from a bridge.
'''
if len(arg.split())==2:
self._delflow(arg.split()[0],arg.split()[1])
if not brDelFlow(arg.split()[0],arg.split()[1]):
output('Del flow#%s from %s failed.\n' %(arg.split()[1],arg.split()[0]))
elif len(arg.split())==1 and self.bridge:
self._delflow(self.bridge,arg)
if not brDelFlow(self.bridge,arg):
output('Del flow#%s from %s failed.\n' %(arg,self.bridge))
else:
output("Please use [bridge] delflow flow_id.\n")

@@ -67,16 +70,12 @@ def do_dump(self,arg):
Dump the flows from a bridge.
'''
if arg:
flows=brGetFlows(arg)
brDump(arg)
elif self.bridge:
flows=brGetFlows(self.bridge)
brDump(self.bridge)
else:
output("Please give a valid bridge.\n")
return
if flows:
Flow.bannerOutput()
for f in flows:
f.fmtOutput()

def do_EOF( self, arg ):
"Exit"
@@ -104,22 +103,9 @@ def do_help( self, line ):

def do_list(self,_arg):
'''
Show available bridges in the system
List available bridges in the system
'''
bridges = brList()
if not bridges:
output('None bridge exists.\n')
return
br_info = ''
for br in sorted(bridges.keys()):
br_info += "%s\n" %(br)
if bridges[br]['Port']:
br_info += " Port:\t\t%s\n" %(' '.join(bridges[br]['Port'].keys()))
if bridges[br]['Controller']:
br_info += " Controller:\t%s\n" %(' '.join(bridges[br]['Controller']))
if bridges[br]['fail_mode']:
br_info += " Fail_Mode:\t%s\n" %(bridges[br]['fail_mode'])
output(br_info)
brList()

def do_quit( self, line ):
"Exit"
@@ -149,67 +135,12 @@ def do_show(self,arg):
'''
if arg:
br = arg
brShow(arg)
elif self.bridge:
br = self.bridge
brShow(self.bridge)
else:
output("Please give a valid bridge.\n")
return
ovs_ports = brGetPorts(br)
output('%s\n' %br)
neutron_ports = self.get_neutron_ports()
output('%-20s%-12s%-8s%-12s' %('Intf','Port','Tag','Type'))
if neutron_ports:
output('%-16s%-24s\n' %('vmIP','vmMAC'))
else:
output('\n')
content=[]
for intf in ovs_ports:
port,tag,type = ovs_ports[intf]['port'],ovs_ports[intf]['tag'],ovs_ports[intf]['type']
if neutron_ports and intf in neutron_ports:
vmIP, vmMac = neutron_ports[intf]['ip_address'],neutron_ports[intf]['mac']
else:
vmIP,vmMac = '', ''
content.append((intf,port,tag,type,vmIP,vmMac))
#output('%-20s%-8s%-16s%-24s%-8s\n' %(intf,port,vmIP,vmMac,tag))
content.sort(key=lambda x:x[0])
content.sort(key=lambda x:x[3])
for _ in content:
output('%-20s%-12s%-8s%-12s' %(_[0],_[1],_[2],_[3]))
if neutron_ports:
output('%-16s%-24s\n' %(_[4],_[5]))
else:
output('\n')

def get_neutron_ports(self):
"""
Return the neutron port information, each line looks like
qvoxxxx:{'id':id,'name':name,'mac':mac,"subnet_id": subnet_id, "ip_address": ip}
"""
result={}
try:
neutron_port_list= Popen('neutron port-list', stdout=PIPE,stderr=PIPE,shell=True).stdout.read()
except Exception:
return None
neutron_port_list = neutron_port_list.split('\n')
if len(neutron_port_list)>3:
for i in range(3,len(neutron_port_list)-1):
l = neutron_port_list[i]
if l.startswith('| '):
l = l.strip(' |')
l_value=map(lambda x: x.strip(),l.split('|'))
if len(l_value) !=4:
continue
else:
id,name,mac,ips = l_value
result['qvo'+id[:11]] = {'id':id,'name':name,'mac':mac}
result['qvo'+id[:11]].update(eval(ips))
return result

def _delflow(self,bridge,flow_id):
if not flow_id.isdigit():
output('flow_id is not valid.\n')
elif not brDelFlow(bridge,int(flow_id)):
output('Delflow %u from %s failed.\n' %(int(flow_id),bridge))

def emptyline( self ):
"Don't repeat last command when you hit return."
Loading
Oops, something went wrong.

0 comments on commit 3b85363

Please sign in to comment.