1 # Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
22 from ovs.db import error
25 from ovs.db import data
26 from ovs.db import types
33 if type(json) == list and len(json) == 1:
39 def do_default_atoms():
40 for type_ in types.ATOMIC_TYPES:
41 if type_ == types.VoidType:
44 sys.stdout.write("%s: " % type_.to_string())
46 atom = data.Atom.default(type_)
47 if atom != data.Atom.default(type_):
48 sys.stdout.write("wrong\n")
51 sys.stdout.write("OK\n")
54 def do_default_data():
57 for key in types.ATOMIC_TYPES:
58 if key == types.VoidType:
60 for value in types.ATOMIC_TYPES:
61 if value == types.VoidType:
64 valueBase = types.BaseType(value)
65 type_ = types.Type(types.BaseType(key), valueBase, n_min, 1)
66 assert type_.is_valid()
68 sys.stdout.write("key %s, value %s, n_min %d: "
69 % (key.to_string(), value.to_string(), n_min))
71 datum = data.Datum.default(type_)
72 if datum != data.Datum.default(type_):
73 sys.stdout.write("wrong\n")
76 sys.stdout.write("OK\n")
81 def do_parse_atomic_type(type_string):
82 type_json = unbox_json(ovs.json.from_string(type_string))
83 atomic_type = types.AtomicType.from_json(type_json)
84 print ovs.json.to_string(atomic_type.to_json(), sort_keys=True)
87 def do_parse_base_type(type_string):
88 type_json = unbox_json(ovs.json.from_string(type_string))
89 base_type = types.BaseType.from_json(type_json)
90 print ovs.json.to_string(base_type.to_json(), sort_keys=True)
93 def do_parse_type(type_string):
94 type_json = unbox_json(ovs.json.from_string(type_string))
95 type_ = types.Type.from_json(type_json)
96 print ovs.json.to_string(type_.to_json(), sort_keys=True)
99 def do_parse_atoms(type_string, *atom_strings):
100 type_json = unbox_json(ovs.json.from_string(type_string))
101 base = types.BaseType.from_json(type_json)
102 for atom_string in atom_strings:
103 atom_json = unbox_json(ovs.json.from_string(atom_string))
105 atom = data.Atom.from_json(base, atom_json)
106 print ovs.json.to_string(atom.to_json())
107 except error.Error, e:
108 print e.args[0].encode("utf8")
111 def do_parse_data(type_string, *data_strings):
112 type_json = unbox_json(ovs.json.from_string(type_string))
113 type_ = types.Type.from_json(type_json)
114 for datum_string in data_strings:
115 datum_json = unbox_json(ovs.json.from_string(datum_string))
116 datum = data.Datum.from_json(type_, datum_json)
117 print ovs.json.to_string(datum.to_json())
120 def do_sort_atoms(type_string, atom_strings):
121 type_json = unbox_json(ovs.json.from_string(type_string))
122 base = types.BaseType.from_json(type_json)
123 atoms = [data.Atom.from_json(base, atom_json)
124 for atom_json in unbox_json(ovs.json.from_string(atom_strings))]
125 print ovs.json.to_string([data.Atom.to_json(atom)
126 for atom in sorted(atoms)])
129 def do_parse_column(name, column_string):
130 column_json = unbox_json(ovs.json.from_string(column_string))
131 column = ovs.db.schema.ColumnSchema.from_json(column_json, name)
132 print ovs.json.to_string(column.to_json(), sort_keys=True)
135 def do_parse_table(name, table_string, default_is_root_string='false'):
136 default_is_root = default_is_root_string == 'true'
137 table_json = unbox_json(ovs.json.from_string(table_string))
138 table = ovs.db.schema.TableSchema.from_json(table_json, name)
139 print ovs.json.to_string(table.to_json(default_is_root), sort_keys=True)
142 def do_parse_schema(schema_string):
143 schema_json = unbox_json(ovs.json.from_string(schema_string))
144 schema = ovs.db.schema.DbSchema.from_json(schema_json)
145 print ovs.json.to_string(schema.to_json(), sort_keys=True)
148 def print_idl(idl, step):
149 simple = idl.tables["simple"].rows
150 l1 = idl.tables["link1"].rows
151 l2 = idl.tables["link2"].rows
154 for row in simple.itervalues():
155 s = ("%03d: i=%s r=%s b=%s s=%s u=%s "
156 "ia=%s ra=%s ba=%s sa=%s ua=%s uuid=%s"
157 % (step, row.i, row.r, row.b, row.s, row.u,
158 row.ia, row.ra, row.ba, row.sa, row.ua, row.uuid))
159 s = re.sub('""|,|u?\'', "", s)
160 s = re.sub('UUID\(([^)]+)\)', r'\1', s)
161 s = re.sub('False', 'false', s)
162 s = re.sub('True', 'true', s)
163 s = re.sub(r'(ba)=([^[][^ ]*) ', r'\1=[\2] ', s)
167 for row in l1.itervalues():
168 s = ["%03d: i=%s k=" % (step, row.i)]
170 s.append(str(row.k.i))
172 s.append(' '.join(sorted(str(ka.i) for ka in row.ka)))
175 s.append(str(row.l2[0].i))
176 s.append(" uuid=%s" % row.uuid)
180 for row in l2.itervalues():
181 s = ["%03d: i=%s l1=" % (step, row.i)]
183 s.append(str(row.l1[0].i))
184 s.append(" uuid=%s" % row.uuid)
189 print("%03d: empty" % step)
193 def substitute_uuids(json, symtab):
194 if type(json) in [str, unicode]:
195 symbol = symtab.get(json)
198 elif type(json) == list:
199 return [substitute_uuids(element, symtab) for element in json]
200 elif type(json) == dict:
202 for key, value in json.iteritems():
203 d[key] = substitute_uuids(value, symtab)
208 def parse_uuids(json, symtab):
209 if type(json) in [str, unicode] and ovs.ovsuuid.is_valid_string(json):
210 name = "#%d#" % len(symtab)
211 sys.stderr.write("%s = %s\n" % (name, json))
213 elif type(json) == list:
215 parse_uuids(element, symtab)
216 elif type(json) == dict:
217 for value in json.itervalues():
218 parse_uuids(value, symtab)
221 def idltest_find_simple(idl, i):
222 for row in idl.tables["simple"].rows.itervalues():
228 def idl_set(idl, commands, step):
229 txn = ovs.db.idl.Transaction(idl)
232 for command in commands.split(','):
233 words = command.split()
237 if name == "notifytest":
240 old_notify = idl.notify
242 def notify(event, row, updates=None):
244 upcol = updates._data.keys()[0]
247 events.append("%s|%s|%s" % (event, row.i, upcol))
248 idl.notify = old_notify
254 sys.stderr.write('"set" command requires 3 arguments\n')
257 s = idltest_find_simple(idl, int(args[0]))
259 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
268 s.u = uuid.UUID(args[2])
272 sys.stderr.write('"set" comamnd asks for unknown column %s\n'
275 elif name == "insert":
277 sys.stderr.write('"set" command requires 1 argument\n')
280 s = txn.insert(idl.tables["simple"])
282 elif name == "delete":
284 sys.stderr.write('"delete" command requires 1 argument\n')
287 s = idltest_find_simple(idl, int(args[0]))
289 sys.stderr.write('"delete" command asks for nonexistent i=%d\n'
293 elif name == "verify":
295 sys.stderr.write('"verify" command requires 2 arguments\n')
298 s = idltest_find_simple(idl, int(args[0]))
300 sys.stderr.write('"verify" command asks for nonexistent i=%d\n'
304 if args[1] in ("i", "b", "s", "u", "r"):
307 sys.stderr.write('"verify" command asks for unknown column '
310 elif name == "increment":
312 sys.stderr.write('"increment" command requires 1 argument\n')
315 s = idltest_find_simple(idl, int(args[0]))
317 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
323 elif name == "abort":
326 elif name == "destroy":
327 print "%03d: destroy" % step
331 elif name == "linktest":
332 l1_0 = txn.insert(idl.tables["link1"])
336 l1_1 = txn.insert(idl.tables["link1"])
339 l1_1.ka = [l1_0, l1_1]
340 elif name == 'getattrtest':
341 l1 = txn.insert(idl.tables["link1"])
342 i = getattr(l1, 'i', 1)
345 i = getattr(l1, 'i', 1)
349 sys.stderr.write("unknown command %s\n" % name)
352 status = txn.commit_block()
353 sys.stdout.write("%03d: commit, status=%s"
354 % (step, ovs.db.idl.Transaction.status_to_string(status)))
355 if increment and status == ovs.db.idl.Transaction.SUCCESS:
356 sys.stdout.write(", increment=%d" % txn.get_increment_new_value())
358 # Event notifications from operations in a single transaction are
359 # not in a gauranteed order due to update messages being dicts
360 sys.stdout.write(", events=" + ", ".join(sorted(events)))
361 sys.stdout.write("\n")
365 def do_idl(schema_file, remote, *commands):
366 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
367 if commands and commands[0].startswith("?"):
369 for x in commands[0][1:].split("?"):
370 table, columns = x.split(":")
371 monitor[table] = columns.split(",")
372 schema_helper.register_columns(table, monitor[table])
373 commands = commands[1:]
375 schema_helper.register_all()
376 idl = ovs.db.idl.Idl(remote, schema_helper)
379 error, stream = ovs.stream.Stream.open_block(
380 ovs.stream.Stream.open(remote))
382 sys.stderr.write("failed to connect to \"%s\"" % remote)
384 rpc = ovs.jsonrpc.Connection(stream)
391 for command in commands:
392 if command.startswith("+"):
393 # The previous transaction didn't change anything.
394 command = command[1:]
397 while idl.change_seqno == seqno and not idl.run():
400 poller = ovs.poller.Poller()
408 seqno = idl.change_seqno
410 if command == "reconnect":
411 print("%03d: reconnect" % step)
414 idl.force_reconnect()
415 elif not command.startswith("["):
416 idl_set(idl, command, step)
419 json = ovs.json.from_string(command)
420 if type(json) in [str, unicode]:
421 sys.stderr.write("\"%s\": %s\n" % (command, json))
423 json = substitute_uuids(json, symtab)
424 request = ovs.jsonrpc.Message.create_request("transact", json)
425 error, reply = rpc.transact_block(request)
427 sys.stderr.write("jsonrpc transaction failed: %s"
428 % os.strerror(error))
430 elif reply.error is not None:
431 sys.stderr.write("jsonrpc transaction failed: %s"
435 sys.stdout.write("%03d: " % step)
438 if reply.result is not None:
439 parse_uuids(reply.result, symtab)
441 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
446 while idl.change_seqno == seqno and not idl.run():
447 poller = ovs.poller.Poller()
453 print("%03d: done" % step)
458 %(program_name)s: test utility for Open vSwitch database Python bindings
459 usage: %(program_name)s [OPTIONS] COMMAND ARG...
461 The following commands are supported:
463 test ovsdb_atom_default()
465 test ovsdb_datum_default()
466 parse-atomic-type TYPE
467 parse TYPE as OVSDB atomic type, and re-serialize
469 parse TYPE as OVSDB base type, and re-serialize
471 parse JSON as OVSDB type, and re-serialize
472 parse-atoms TYPE ATOM...
473 parse JSON ATOMs as atoms of TYPE, and re-serialize
474 parse-atom-strings TYPE ATOM...
475 parse string ATOMs as atoms of given TYPE, and re-serialize
476 sort-atoms TYPE ATOM...
477 print JSON ATOMs in sorted order
478 parse-data TYPE DATUM...
479 parse JSON DATUMs as data of given TYPE, and re-serialize
480 parse-column NAME OBJECT
481 parse column NAME with info OBJECT, and re-serialize
482 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
483 parse table NAME with info OBJECT
485 parse JSON as an OVSDB schema, and re-serialize
486 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
487 connect to SERVER (which has the specified SCHEMA) and dump the
488 contents of the database as seen initially by the IDL implementation
489 and after executing each TRANSACTION. (Each TRANSACTION must modify
490 the database or this command will hang.)
491 By default, all columns of all tables are monitored. The "?" option
492 can be used to monitor specific Table:Column(s). The table and their
493 columns are listed as a string of the form starting with "?":
494 ?<table-name>:<column-name>,<column-name>,...
496 ?simple:b - Monitor column "b" in table "simple"
497 Entries for multiple tables are seperated by "?":
498 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
500 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
501 and column "i", "k" in table "link1"
503 The following options are also available:
504 -t, --timeout=SECS give up after SECS seconds
505 -h, --help display this help message\
506 """ % {'program_name': ovs.util.PROGRAM_NAME}
512 options, args = getopt.gnu_getopt(argv[1:], 't:h',
515 except getopt.GetoptError, geo:
516 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
519 for key, value in options:
520 if key in ['-h', '--help']:
522 elif key in ['-t', '--timeout']:
528 raise error.Error("value %s on -t or --timeout is not at "
530 signal.alarm(timeout)
535 sys.stderr.write("%s: missing command argument "
536 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
539 commands = {"default-atoms": (do_default_atoms, 0),
540 "default-data": (do_default_data, 0),
541 "parse-atomic-type": (do_parse_atomic_type, 1),
542 "parse-base-type": (do_parse_base_type, 1),
543 "parse-type": (do_parse_type, 1),
544 "parse-atoms": (do_parse_atoms, (2,)),
545 "parse-data": (do_parse_data, (2,)),
546 "sort-atoms": (do_sort_atoms, 2),
547 "parse-column": (do_parse_column, 2),
548 "parse-table": (do_parse_table, (2, 3)),
549 "parse-schema": (do_parse_schema, 1),
550 "idl": (do_idl, (2,))}
552 command_name = args[0]
554 if not command_name in commands:
555 sys.stderr.write("%s: unknown command \"%s\" "
556 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
560 func, n_args = commands[command_name]
561 if type(n_args) == tuple:
562 if len(args) < n_args[0]:
563 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
565 % (ovs.util.PROGRAM_NAME, command_name,
568 elif type(n_args) == int:
569 if len(args) != n_args:
570 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
572 % (ovs.util.PROGRAM_NAME, command_name,
581 if __name__ == '__main__':
584 except error.Error, e:
585 sys.stderr.write("%s\n" % e)