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.
15 from __future__ import print_function
24 from ovs.db import error
27 from ovs.db import data
36 if type(json) == list and len(json) == 1:
42 def do_default_atoms():
43 for type_ in ovs.db.types.ATOMIC_TYPES:
44 if type_ == ovs.db.types.VoidType:
47 sys.stdout.write("%s: " % type_.to_string())
49 atom = data.Atom.default(type_)
50 if atom != data.Atom.default(type_):
51 sys.stdout.write("wrong\n")
54 sys.stdout.write("OK\n")
57 def do_default_data():
60 for key in ovs.db.types.ATOMIC_TYPES:
61 if key == ovs.db.types.VoidType:
63 for value in ovs.db.types.ATOMIC_TYPES:
64 if value == ovs.db.types.VoidType:
67 valueBase = ovs.db.types.BaseType(value)
68 type_ = ovs.db.types.Type(ovs.db.types.BaseType(key),
70 assert type_.is_valid()
72 sys.stdout.write("key %s, value %s, n_min %d: "
73 % (key.to_string(), value.to_string(), n_min))
75 datum = data.Datum.default(type_)
76 if datum != data.Datum.default(type_):
77 sys.stdout.write("wrong\n")
80 sys.stdout.write("OK\n")
85 def do_parse_atomic_type(type_string):
86 type_json = unbox_json(ovs.json.from_string(type_string))
87 atomic_type = ovs.db.types.AtomicType.from_json(type_json)
88 print(ovs.json.to_string(atomic_type.to_json(), sort_keys=True))
91 def do_parse_base_type(type_string):
92 type_json = unbox_json(ovs.json.from_string(type_string))
93 base_type = ovs.db.types.BaseType.from_json(type_json)
94 print(ovs.json.to_string(base_type.to_json(), sort_keys=True))
97 def do_parse_type(type_string):
98 type_json = unbox_json(ovs.json.from_string(type_string))
99 type_ = ovs.db.types.Type.from_json(type_json)
100 print(ovs.json.to_string(type_.to_json(), sort_keys=True))
103 def do_parse_atoms(type_string, *atom_strings):
104 type_json = unbox_json(ovs.json.from_string(type_string))
105 base = ovs.db.types.BaseType.from_json(type_json)
106 for atom_string in atom_strings:
107 atom_json = unbox_json(ovs.json.from_string(atom_string))
109 atom = data.Atom.from_json(base, atom_json)
110 print(ovs.json.to_string(atom.to_json()))
111 except error.Error as e:
115 def do_parse_data(type_string, *data_strings):
116 type_json = unbox_json(ovs.json.from_string(type_string))
117 type_ = ovs.db.types.Type.from_json(type_json)
118 for datum_string in data_strings:
119 datum_json = unbox_json(ovs.json.from_string(datum_string))
120 datum = data.Datum.from_json(type_, datum_json)
121 print(ovs.json.to_string(datum.to_json()))
124 def do_sort_atoms(type_string, atom_strings):
125 type_json = unbox_json(ovs.json.from_string(type_string))
126 base = ovs.db.types.BaseType.from_json(type_json)
127 atoms = [data.Atom.from_json(base, atom_json)
128 for atom_json in unbox_json(ovs.json.from_string(atom_strings))]
129 print(ovs.json.to_string([data.Atom.to_json(atom)
130 for atom in sorted(atoms)]))
133 def do_parse_column(name, column_string):
134 column_json = unbox_json(ovs.json.from_string(column_string))
135 column = ovs.db.schema.ColumnSchema.from_json(column_json, name)
136 print(ovs.json.to_string(column.to_json(), sort_keys=True))
139 def do_parse_table(name, table_string, default_is_root_string='false'):
140 default_is_root = default_is_root_string == 'true'
141 table_json = unbox_json(ovs.json.from_string(table_string))
142 table = ovs.db.schema.TableSchema.from_json(table_json, name)
143 print(ovs.json.to_string(table.to_json(default_is_root), sort_keys=True))
146 def do_parse_schema(schema_string):
147 schema_json = unbox_json(ovs.json.from_string(schema_string))
148 schema = ovs.db.schema.DbSchema.from_json(schema_json)
149 print(ovs.json.to_string(schema.to_json(), sort_keys=True))
152 def print_idl(idl, step):
154 if "simple" in idl.tables:
155 simple_columns = ["i", "r", "b", "s", "u", "ia",
156 "ra", "ba", "sa", "ua", "uuid"]
157 simple = idl.tables["simple"].rows
158 for row in six.itervalues(simple):
160 for column in simple_columns:
161 if hasattr(row, column) and not (type(getattr(row, column))
162 is ovs.db.data.Atom):
163 s += " %s=%s" % (column, getattr(row, column))
164 s = re.sub('""|,|u?\'', "", s)
165 s = re.sub('UUID\(([^)]+)\)', r'\1', s)
166 s = re.sub('False', 'false', s)
167 s = re.sub('True', 'true', s)
168 s = re.sub(r'(ba)=([^[][^ ]*) ', r'\1=[\2] ', s)
172 if "link1" in idl.tables:
173 l1 = idl.tables["link1"].rows
174 for row in six.itervalues(l1):
175 s = ["%03d: i=%s k=" % (step, row.i)]
176 if hasattr(row, "k") and row.k:
177 s.append(str(row.k.i))
178 if hasattr(row, "ka"):
180 s.append(' '.join(sorted(str(ka.i) for ka in row.ka)))
182 if hasattr(row, "l2") and row.l2:
183 s.append(str(row.l2[0].i))
184 if hasattr(row, "uuid"):
185 s.append(" uuid=%s" % row.uuid)
189 if "link2" in idl.tables:
190 l2 = idl.tables["link2"].rows
191 for row in six.itervalues(l2):
193 s.append(" i=%s l1=" % row.i)
194 if hasattr(row, "l1") and row.l1:
195 s.append(str(row.l1[0].i))
196 if hasattr(row, "uuid"):
197 s.append(" uuid=%s" % row.uuid)
202 print("%03d: empty" % step)
206 def substitute_uuids(json, symtab):
207 if isinstance(json, six.string_types):
208 symbol = symtab.get(json)
211 elif type(json) == list:
212 return [substitute_uuids(element, symtab) for element in json]
213 elif type(json) == dict:
215 for key, value in six.iteritems(json):
216 d[key] = substitute_uuids(value, symtab)
221 def parse_uuids(json, symtab):
222 if (isinstance(json, six.string_types)
223 and ovs.ovsuuid.is_valid_string(json)):
224 name = "#%d#" % len(symtab)
225 sys.stderr.write("%s = %s\n" % (name, json))
227 elif type(json) == list:
229 parse_uuids(element, symtab)
230 elif type(json) == dict:
231 for value in six.itervalues(json):
232 parse_uuids(value, symtab)
235 def idltest_find_simple(idl, i):
236 for row in six.itervalues(idl.tables["simple"].rows):
242 def idl_set(idl, commands, step):
243 txn = ovs.db.idl.Transaction(idl)
247 for command in commands.split(','):
248 words = command.split()
252 if name == "notifytest":
255 old_notify = idl.notify
257 def notify(event, row, updates=None):
259 upcol = list(updates._data.keys())[0]
262 events.append("%s|%s|%s" % (event, row.i, upcol))
263 idl.notify = old_notify
269 sys.stderr.write('"set" command requires 3 arguments\n')
272 s = idltest_find_simple(idl, int(args[0]))
274 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
283 s.u = uuid.UUID(args[2])
287 sys.stderr.write('"set" comamnd asks for unknown column %s\n'
290 elif name == "insert":
292 sys.stderr.write('"set" command requires 1 argument\n')
295 s = txn.insert(idl.tables["simple"])
297 elif name == "delete":
299 sys.stderr.write('"delete" command requires 1 argument\n')
302 s = idltest_find_simple(idl, int(args[0]))
304 sys.stderr.write('"delete" command asks for nonexistent i=%d\n'
308 elif name == "verify":
310 sys.stderr.write('"verify" command requires 2 arguments\n')
313 s = idltest_find_simple(idl, int(args[0]))
315 sys.stderr.write('"verify" command asks for nonexistent i=%d\n'
319 if args[1] in ("i", "b", "s", "u", "r"):
322 sys.stderr.write('"verify" command asks for unknown column '
325 elif name == "fetch":
327 sys.stderr.write('"fetch" command requires 2 argument\n')
330 row = idltest_find_simple(idl, int(args[0]))
332 sys.stderr.write('"fetch" command asks for nonexistent i=%d\n'
338 fetch_cmds.append([row, column])
339 elif name == "increment":
341 sys.stderr.write('"increment" command requires 1 argument\n')
344 s = idltest_find_simple(idl, int(args[0]))
346 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
352 elif name == "abort":
355 elif name == "destroy":
356 print("%03d: destroy" % step)
360 elif name == "linktest":
361 l1_0 = txn.insert(idl.tables["link1"])
365 l1_1 = txn.insert(idl.tables["link1"])
368 l1_1.ka = [l1_0, l1_1]
369 elif name == 'getattrtest':
370 l1 = txn.insert(idl.tables["link1"])
371 i = getattr(l1, 'i', 1)
374 i = getattr(l1, 'i', 1)
378 sys.stderr.write("unknown command %s\n" % name)
381 status = txn.commit_block()
382 sys.stdout.write("%03d: commit, status=%s"
383 % (step, ovs.db.idl.Transaction.status_to_string(status)))
384 if increment and status == ovs.db.idl.Transaction.SUCCESS:
385 sys.stdout.write(", increment=%d" % txn.get_increment_new_value())
387 # Event notifications from operations in a single transaction are
388 # not in a gauranteed order due to update messages being dicts
389 sys.stdout.write(", events=" + ", ".join(sorted(events)))
390 sys.stdout.write("\n")
394 def do_idl(schema_file, remote, *commands):
395 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
396 if commands and commands[0].startswith("?"):
398 for x in commands[0][1:].split("?"):
400 table, columns = x.split(":")
401 columns = columns.split(",")
402 for index, column in enumerate(columns):
403 if column[-1] == '!':
404 columns[index] = columns[index][:-1]
405 readonly.append(columns[index])
406 schema_helper.register_columns(table, columns, readonly)
407 commands = commands[1:]
409 schema_helper.register_all()
410 idl = ovs.db.idl.Idl(remote, schema_helper)
413 error, stream = ovs.stream.Stream.open_block(
414 ovs.stream.Stream.open(remote))
416 sys.stderr.write("failed to connect to \"%s\"" % remote)
418 rpc = ovs.jsonrpc.Connection(stream)
425 for command in commands:
426 if command.startswith("+"):
427 # The previous transaction didn't change anything.
428 command = command[1:]
431 while idl.change_seqno == seqno and not idl.run():
434 poller = ovs.poller.Poller()
442 seqno = idl.change_seqno
444 if command == "reconnect":
445 print("%03d: reconnect" % step)
448 idl.force_reconnect()
449 elif not command.startswith("["):
450 idl_set(idl, command, step)
453 json = ovs.json.from_string(command)
454 if isinstance(json, six.string_types):
455 sys.stderr.write("\"%s\": %s\n" % (command, json))
457 json = substitute_uuids(json, symtab)
458 request = ovs.jsonrpc.Message.create_request("transact", json)
459 error, reply = rpc.transact_block(request)
461 sys.stderr.write("jsonrpc transaction failed: %s"
462 % os.strerror(error))
464 elif reply.error is not None:
465 sys.stderr.write("jsonrpc transaction failed: %s"
469 sys.stdout.write("%03d: " % step)
472 if reply.result is not None:
473 parse_uuids(reply.result, symtab)
475 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
480 while idl.change_seqno == seqno and not idl.run():
481 poller = ovs.poller.Poller()
487 print("%03d: done" % step)
492 %(program_name)s: test utility for Open vSwitch database Python bindings
493 usage: %(program_name)s [OPTIONS] COMMAND ARG...
495 The following commands are supported:
497 test ovsdb_atom_default()
499 test ovsdb_datum_default()
500 parse-atomic-type TYPE
501 parse TYPE as OVSDB atomic type, and re-serialize
503 parse TYPE as OVSDB base type, and re-serialize
505 parse JSON as OVSDB type, and re-serialize
506 parse-atoms TYPE ATOM...
507 parse JSON ATOMs as atoms of TYPE, and re-serialize
508 parse-atom-strings TYPE ATOM...
509 parse string ATOMs as atoms of given TYPE, and re-serialize
510 sort-atoms TYPE ATOM...
511 print JSON ATOMs in sorted order
512 parse-data TYPE DATUM...
513 parse JSON DATUMs as data of given TYPE, and re-serialize
514 parse-column NAME OBJECT
515 parse column NAME with info OBJECT, and re-serialize
516 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
517 parse table NAME with info OBJECT
519 parse JSON as an OVSDB schema, and re-serialize
520 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
521 connect to SERVER (which has the specified SCHEMA) and dump the
522 contents of the database as seen initially by the IDL implementation
523 and after executing each TRANSACTION. (Each TRANSACTION must modify
524 the database or this command will hang.)
525 By default, all columns of all tables are monitored. The "?" option
526 can be used to monitor specific Table:Column(s). The table and their
527 columns are listed as a string of the form starting with "?":
528 ?<table-name>:<column-name>,<column-name>,...
530 ?simple:b - Monitor column "b" in table "simple"
531 Entries for multiple tables are seperated by "?":
532 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
534 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
535 and column "i", "k" in table "link1"
536 Readonly columns: Suffixing a "!" after a column indicates that the
537 column is to be registered "readonly".
539 ?simple:i,b! - Register interest in column "i" (monitoring) and
540 column "b" (readonly).
543 The following options are also available:
544 -t, --timeout=SECS give up after SECS seconds
545 -h, --help display this help message\
546 """ % {'program_name': ovs.util.PROGRAM_NAME})
552 options, args = getopt.gnu_getopt(argv[1:], 't:h',
555 except getopt.GetoptError as geo:
556 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
559 for key, value in options:
560 if key in ['-h', '--help']:
562 elif key in ['-t', '--timeout']:
568 raise error.Error("value %s on -t or --timeout is not at "
570 signal.alarm(timeout)
575 sys.stderr.write("%s: missing command argument "
576 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
579 commands = {"default-atoms": (do_default_atoms, 0),
580 "default-data": (do_default_data, 0),
581 "parse-atomic-type": (do_parse_atomic_type, 1),
582 "parse-base-type": (do_parse_base_type, 1),
583 "parse-type": (do_parse_type, 1),
584 "parse-atoms": (do_parse_atoms, (2,)),
585 "parse-data": (do_parse_data, (2,)),
586 "sort-atoms": (do_sort_atoms, 2),
587 "parse-column": (do_parse_column, 2),
588 "parse-table": (do_parse_table, (2, 3)),
589 "parse-schema": (do_parse_schema, 1),
590 "idl": (do_idl, (2,))}
592 command_name = args[0]
594 if command_name not in commands:
595 sys.stderr.write("%s: unknown command \"%s\" "
596 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
600 func, n_args = commands[command_name]
601 if type(n_args) == tuple:
602 if len(args) < n_args[0]:
603 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
605 % (ovs.util.PROGRAM_NAME, command_name,
608 elif type(n_args) == int:
609 if len(args) != n_args:
610 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
612 % (ovs.util.PROGRAM_NAME, command_name,
621 if __name__ == '__main__':
624 except error.Error as e:
625 sys.stderr.write("%s\n" % e)