Skip to content

Commit 2792c2a

Browse files
committed
ovs-vsctl: Refactor internals to increase flexibility.
This changes the interface of each of the command implementations, making them take the configuration as an argument and return the output. This will make it easier to support alternate output formats and to execute more than one command per invocation (both happening in upcoming commits).
1 parent 3d1b963 commit 2792c2a

3 files changed

Lines changed: 99 additions & 58 deletions

File tree

tests/ovs-vsctl.at

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,31 @@ dnl specified PARENT and is on the given VLAN.
1515
m4_define([_CHECK_BRIDGE],
1616
[AT_CHECK([RUN_OVS_VSCTL([br-to-parent $1])], [0], [$2
1717
])
18+
19+
# Check br-to-vlan, without --oneline.
1820
AT_CHECK([RUN_OVS_VSCTL([br-to-vlan $1])], [0], [$3
21+
])
22+
# Check br-to-vlan, with --oneline.
23+
# (This particular test is interesting with --oneline because it returns
24+
# an integer instead of a string and that can cause type mismatches inside
25+
# python if not done carefully.)
26+
AT_CHECK([RUN_OVS_VSCTL([--oneline br-to-vlan $1])], [0], [$3
1927
])])
2028
m4_define([CHECK_BRIDGES],
21-
[dnl Check that the bridges appear on list-br.
29+
[dnl Check that the bridges appear on list-br, without --oneline.
2230
AT_CHECK(
2331
[RUN_OVS_VSCTL([list-br])],
2432
[0],
2533
[m4_foreach([brinfo], [$@], [m4_car(brinfo)
2634
])])
2735

36+
dnl Check that the bridges appear on list-br, with --oneline.
37+
AT_CHECK(
38+
[RUN_OVS_VSCTL([--oneline list-br])],
39+
[0],
40+
[m4_join([\n], m4_foreach([brinfo], [$@], [m4_car(brinfo),]))
41+
])
42+
2843
dnl Check that each bridge exists according to br-exists and that
2944
dnl a bridge that should not exist does not.
3045
m4_foreach([brinfo], [$@],
@@ -41,11 +56,19 @@ dnl list of ports, which must be in alphabetical order. Also checks
4156
dnl that "ovs-vsctl port-to-br" reports that each port is
4257
dnl in BRIDGE.
4358
m4_define([CHECK_PORTS],
44-
[AT_CHECK(
59+
[dnl Check ports without --oneline.
60+
AT_CHECK(
4561
[RUN_OVS_VSCTL([list-ports $1])],
4662
[0],
4763
[m4_foreach([port], m4_cdr($@), [port
4864
])])
65+
66+
dnl Check ports with --oneline.
67+
AT_CHECK(
68+
[RUN_OVS_VSCTL([--oneline list-ports $1])],
69+
[0],
70+
[m4_join([\n], m4_shift($@))
71+
])
4972
AT_CHECK([RUN_OVS_VSCTL([port-to-br $1])], [1], [], [ovs-vsctl: no port named $1
5073
])
5174
m4_foreach(
@@ -111,6 +134,22 @@ CHECK_PORTS([b])
111134
CHECK_IFACES([b])
112135
AT_CLEANUP
113136

137+
AT_SETUP([add-br a, add-port a a1, add-port a a2])
138+
AT_KEYWORDS([ovs-vsctl])
139+
AT_CHECK([RUN_OVS_VSCTL(
140+
[add-br a],
141+
[add-port a a1],
142+
[add-port a a2])])
143+
AT_CHECK([cat conf], [0],
144+
[bridge.a.port=a
145+
bridge.a.port=a1
146+
bridge.a.port=a2
147+
])
148+
CHECK_BRIDGES([a, a, 0])
149+
CHECK_PORTS([a], [a1], [a2])
150+
CHECK_IFACES([a], [a1], [a2])
151+
AT_CLEANUP
152+
114153
AT_SETUP([add-br a b, add-port a a1, add-port b b1, del-br a])
115154
AT_KEYWORDS([ovs-vsctl])
116155
AT_CHECK([RUN_OVS_VSCTL(

utilities/ovs-vsctl.8.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ its configuration file.
9898
By default, \fBovs\-vsctl\fR logs its arguments and the details of any
9999
changes that it makes to the system log. This option disables this
100100
logging.
101+
.IP "\fB\-\-oneline\fR"
102+
Modifies the output format so that the output for a command is printed
103+
on a single line. New-line characters that would otherwise separate
104+
lines are printed as \fB\\n\fR, and any instances of \fB\\fR that
105+
would otherwise appear in the output are doubled.
101106
.
102107
.SH COMMANDS
103108
The commands implemented by \fBovs\-vsctl\fR are described in the

utilities/ovs-vsctl.in

Lines changed: 53 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,7 @@ def check_conflicts(cfg, name, op):
373373
if name in get_bridge_ifaces(cfg, parent, vlan):
374374
raise Error("%s because an interface named %s already exists on bridge %s" % (op, name, bridge))
375375

376-
def cmd_add_br(bridge, parent=None, vlan=None):
377-
cfg = cfg_read(VSWITCHD_CONF, True)
378-
376+
def cmd_add_br(cfg, bridge, parent=None, vlan=None):
379377
check_conflicts(cfg, bridge, "cannot create a bridge named %s" % bridge)
380378

381379
if parent and vlan:
@@ -398,57 +396,47 @@ def cmd_add_br(bridge, parent=None, vlan=None):
398396
cfg['bridge.%s.port' % parent].append(bridge)
399397
else:
400398
cfg['bridge.%s.port' % bridge] = [bridge]
401-
cfg_save(cfg, VSWITCHD_CONF)
402399

403-
def cmd_del_br(bridge):
404-
cfg = cfg_read(VSWITCHD_CONF, True)
400+
def cmd_del_br(cfg, bridge):
405401
parent, vlan = find_bridge(cfg, bridge)
406402
if vlan == 0:
407403
vlan = -1
408404
for port in set(get_bridge_ports(cfg, parent, vlan) + [bridge]):
409405
del_port(cfg, port)
410406
if vlan < 0:
411407
del_matching_keys(cfg, 'bridge.%s.[!0-9]*' % bridge)
412-
cfg_save(cfg, VSWITCHD_CONF)
413408

414-
def cmd_list_br():
415-
cfg = cfg_read(VSWITCHD_CONF)
416-
for bridge in get_all_bridges(cfg):
417-
print bridge
409+
def cmd_list_br(cfg):
410+
return get_all_bridges(cfg)
418411

419-
def cmd_br_exists(bridge):
420-
cfg = cfg_read(VSWITCHD_CONF)
412+
def cmd_br_exists(cfg, bridge):
421413
if bridge not in get_all_bridges(cfg):
422414
sys.exit(2)
423415

424-
def cmd_list_ports(bridge):
425-
cfg = cfg_read(VSWITCHD_CONF)
416+
def cmd_list_ports(cfg, bridge):
417+
ports = []
426418
parent, vlan = find_bridge(cfg, bridge)
427419
for port in get_bridge_ports(cfg, parent, vlan):
428420
if port != bridge:
429-
print port
421+
ports.append(port)
422+
return ports
430423

431424
def do_add_port(cfg, bridge, parent, port, vlan):
432425
check_conflicts(cfg, port, "cannot create a port named %s" % port)
433426
cfg['bridge.%s.port' % parent].append(port)
434427
if vlan > 0:
435428
cfg['vlan.%s.tag' % port] = [vlan]
436429

437-
def cmd_add_port(bridge, port):
438-
cfg = cfg_read(VSWITCHD_CONF, True)
430+
def cmd_add_port(cfg, bridge, port):
439431
parent, vlan = find_bridge(cfg, bridge)
440432
do_add_port(cfg, bridge, parent, port, vlan)
441-
cfg_save(cfg, VSWITCHD_CONF)
442433

443-
def cmd_add_bond(bridge, port, *slaves):
444-
cfg = cfg_read(VSWITCHD_CONF, True)
434+
def cmd_add_bond(cfg, bridge, port, *slaves):
445435
parent, vlan = find_bridge(cfg, bridge)
446436
do_add_port(cfg, bridge, parent, port, vlan)
447437
cfg['bonding.%s.slave' % port] = list(slaves)
448-
cfg_save(cfg, VSWITCHD_CONF)
449438

450-
def cmd_del_port(*args):
451-
cfg = cfg_read(VSWITCHD_CONF, True)
439+
def cmd_del_port(cfg, *args):
452440
if len(args) == 2:
453441
bridge, port = args
454442
parent, vlan = find_bridge(cfg, bridge)
@@ -462,40 +450,35 @@ def cmd_del_port(*args):
462450
if not port_to_bridge(cfg, port):
463451
raise Error("no port %s on any bridge" % port)
464452
del_port(cfg, port)
465-
cfg_save(cfg, VSWITCHD_CONF)
466453

467-
def cmd_port_to_br(port):
468-
cfg = cfg_read(VSWITCHD_CONF)
454+
def cmd_port_to_br(cfg, port):
469455
bridge = port_to_bridge(cfg, port)
470456
if bridge:
471-
print bridge
457+
return (bridge,)
472458
else:
473459
raise Error("no port named %s" % port)
474460

475-
def cmd_list_ifaces(bridge):
476-
cfg = cfg_read(VSWITCHD_CONF)
461+
def cmd_list_ifaces(cfg, bridge):
462+
ifaces = []
477463
parent, vlan = find_bridge(cfg, bridge)
478464
for iface in get_bridge_ifaces(cfg, parent, vlan):
479465
if iface != bridge:
480-
print iface
466+
ifaces.append(iface)
467+
return ifaces
481468

482-
def cmd_iface_to_br(iface):
483-
cfg = cfg_read(VSWITCHD_CONF)
469+
def cmd_iface_to_br(cfg, iface):
484470
for bridge, parent, vlan in get_bridge_info(cfg):
485471
if iface != bridge and iface in get_bridge_ifaces(cfg, parent, vlan):
486-
print bridge
487-
return
472+
return (bridge,)
488473
raise Error("no interface named %s" % iface)
489474

490-
def cmd_br_to_vlan(bridge):
491-
cfg = cfg_read(VSWITCHD_CONF)
475+
def cmd_br_to_vlan(cfg, bridge):
492476
parent, vlan = find_bridge(cfg, bridge)
493-
print vlan
477+
return (vlan,)
494478

495-
def cmd_br_to_parent(bridge):
496-
cfg = cfg_read(VSWITCHD_CONF)
479+
def cmd_br_to_parent(cfg, bridge):
497480
parent, vlan = find_bridge(cfg, bridge)
498-
print parent
481+
return (parent,)
499482

500483
def main():
501484
# Parse command line.
@@ -505,13 +488,15 @@ def main():
505488
"target=",
506489
"no-reload",
507490
"no-syslog",
491+
"oneline",
508492
"help",
509493
"version"])
510494
except getopt.GetoptError, msg:
511495
sys.stderr.write("%s: %s (use --help for help)\n" % (argv0, msg))
512496
sys.exit(1)
513497

514498
# Handle options.
499+
oneline = False
515500
for opt, optarg in options:
516501
if opt == "-c" or opt == "--config":
517502
global VSWITCHD_CONF
@@ -531,6 +516,8 @@ def main():
531516
elif opt == "--no-syslog":
532517
global SYSLOG
533518
SYSLOG = False
519+
elif opt == "--oneline":
520+
oneline = True
534521
else:
535522
raise RuntimeError("unhandled option %s" % opt)
536523

@@ -544,35 +531,45 @@ def main():
544531
% argv0)
545532
sys.exit(1)
546533

547-
commands = {'add-br': (cmd_add_br, lambda n: n == 1 or n == 3),
548-
'del-br': (cmd_del_br, 1),
549-
'list-br': (cmd_list_br, 0),
550-
'br-exists': (cmd_br_exists, 1),
551-
'list-ports': (cmd_list_ports, 1),
552-
'add-port': (cmd_add_port, 2),
553-
'add-bond': (cmd_add_bond, lambda n: n >= 4),
554-
'del-port': (cmd_del_port, lambda n: n == 1 or n == 2),
555-
'port-to-br': (cmd_port_to_br, 1),
556-
'br-to-vlan': (cmd_br_to_vlan, 1),
557-
'br-to-parent': (cmd_br_to_parent, 1),
558-
'list-ifaces': (cmd_list_ifaces, 1),
559-
'iface-to-br': (cmd_iface_to_br, 1)}
534+
commands = {'add-br': (cmd_add_br, True, lambda n: n == 1 or n == 3),
535+
'del-br': (cmd_del_br, True, 1),
536+
'list-br': (cmd_list_br, False, 0),
537+
'br-exists': (cmd_br_exists, False, 1),
538+
'list-ports': (cmd_list_ports, False, 1),
539+
'add-port': (cmd_add_port, True, 2),
540+
'add-bond': (cmd_add_bond, True, lambda n: n >= 4),
541+
'del-port': (cmd_del_port, True, lambda n: n == 1 or n == 2),
542+
'port-to-br': (cmd_port_to_br, False, 1),
543+
'br-to-vlan': (cmd_br_to_vlan, False, 1),
544+
'br-to-parent': (cmd_br_to_parent, False, 1),
545+
'list-ifaces': (cmd_list_ifaces, False, 1),
546+
'iface-to-br': (cmd_iface_to_br, False, 1)}
560547
command = args[0]
561548
args = args[1:]
562549
if command not in commands:
563550
sys.stderr.write("%s: unknown command '%s' (use --help for help)\n"
564551
% (argv0, command))
565552
sys.exit(1)
566553

567-
function, nargs = commands[command]
554+
function, is_mutator, nargs = commands[command]
568555
if callable(nargs) and not nargs(len(args)):
569556
sys.stderr.write("%s: '%s' command does not accept %d arguments (use --help for help)\n" % (argv0, command, len(args)))
570557
sys.exit(1)
571558
elif not callable(nargs) and len(args) != nargs:
572559
sys.stderr.write("%s: '%s' command takes %d arguments but %d were supplied (use --help for help)\n" % (argv0, command, nargs, len(args)))
573560
sys.exit(1)
574561
else:
575-
function(*args)
562+
cfg = cfg_read(VSWITCHD_CONF, is_mutator)
563+
output = function(cfg, *args)
564+
if output != None:
565+
if oneline:
566+
print '\\n'.join([str(s).replace('\\', '\\\\')
567+
for s in output])
568+
else:
569+
for line in output:
570+
print line
571+
if is_mutator:
572+
cfg_save(cfg, VSWITCHD_CONF)
576573
sys.exit(0)
577574

578575
if __name__ == "__main__":

0 commit comments

Comments
 (0)