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)
490 def do_idl_passive(schema_file, remote, *commands):
493 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
494 schema_helper.register_all()
495 idl = ovs.db.idl.Idl(remote, schema_helper)
497 while idl._session.rpc is None:
500 rpc = idl._session.rpc
505 for command in commands:
506 json = ovs.json.from_string(command)
507 if isinstance(json, six.string_types):
508 sys.stderr.write("\"%s\": %s\n" % (command, json))
510 json = substitute_uuids(json, symtab)
511 request = ovs.jsonrpc.Message.create_request("transact", json)
512 error, reply = rpc.transact_block(request)
514 sys.stderr.write("jsonrpc transaction failed: %s"
515 % os.strerror(error))
517 elif reply.error is not None:
518 sys.stderr.write("jsonrpc transaction failed: %s"
522 sys.stdout.write("%03d: " % step)
525 if reply.result is not None:
526 parse_uuids(reply.result, symtab)
528 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
532 print("%03d: done" % step)
537 %(program_name)s: test utility for Open vSwitch database Python bindings
538 usage: %(program_name)s [OPTIONS] COMMAND ARG...
540 The following commands are supported:
542 test ovsdb_atom_default()
544 test ovsdb_datum_default()
545 parse-atomic-type TYPE
546 parse TYPE as OVSDB atomic type, and re-serialize
548 parse TYPE as OVSDB base type, and re-serialize
550 parse JSON as OVSDB type, and re-serialize
551 parse-atoms TYPE ATOM...
552 parse JSON ATOMs as atoms of TYPE, and re-serialize
553 parse-atom-strings TYPE ATOM...
554 parse string ATOMs as atoms of given TYPE, and re-serialize
555 sort-atoms TYPE ATOM...
556 print JSON ATOMs in sorted order
557 parse-data TYPE DATUM...
558 parse JSON DATUMs as data of given TYPE, and re-serialize
559 parse-column NAME OBJECT
560 parse column NAME with info OBJECT, and re-serialize
561 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
562 parse table NAME with info OBJECT
564 parse JSON as an OVSDB schema, and re-serialize
565 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
566 connect to SERVER (which has the specified SCHEMA) and dump the
567 contents of the database as seen initially by the IDL implementation
568 and after executing each TRANSACTION. (Each TRANSACTION must modify
569 the database or this command will hang.)
570 By default, all columns of all tables are monitored. The "?" option
571 can be used to monitor specific Table:Column(s). The table and their
572 columns are listed as a string of the form starting with "?":
573 ?<table-name>:<column-name>,<column-name>,...
575 ?simple:b - Monitor column "b" in table "simple"
576 Entries for multiple tables are seperated by "?":
577 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
579 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
580 and column "i", "k" in table "link1"
581 Readonly columns: Suffixing a "!" after a column indicates that the
582 column is to be registered "readonly".
584 ?simple:i,b! - Register interest in column "i" (monitoring) and
585 column "b" (readonly).
588 The following options are also available:
589 -t, --timeout=SECS give up after SECS seconds
590 -h, --help display this help message\
591 """ % {'program_name': ovs.util.PROGRAM_NAME})
597 options, args = getopt.gnu_getopt(argv[1:], 't:h',
600 except getopt.GetoptError as geo:
601 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
604 for key, value in options:
605 if key in ['-h', '--help']:
607 elif key in ['-t', '--timeout']:
613 raise error.Error("value %s on -t or --timeout is not at "
615 signal.alarm(timeout)
620 sys.stderr.write("%s: missing command argument "
621 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
624 commands = {"default-atoms": (do_default_atoms, 0),
625 "default-data": (do_default_data, 0),
626 "parse-atomic-type": (do_parse_atomic_type, 1),
627 "parse-base-type": (do_parse_base_type, 1),
628 "parse-type": (do_parse_type, 1),
629 "parse-atoms": (do_parse_atoms, (2,)),
630 "parse-data": (do_parse_data, (2,)),
631 "sort-atoms": (do_sort_atoms, 2),
632 "parse-column": (do_parse_column, 2),
633 "parse-table": (do_parse_table, (2, 3)),
634 "parse-schema": (do_parse_schema, 1),
635 "idl": (do_idl, (2,)),
636 "idl_passive": (do_idl_passive, (2,))}
638 command_name = args[0]
640 if command_name not in commands:
641 sys.stderr.write("%s: unknown command \"%s\" "
642 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
646 func, n_args = commands[command_name]
647 if type(n_args) == tuple:
648 if len(args) < n_args[0]:
649 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
651 % (ovs.util.PROGRAM_NAME, command_name,
654 elif type(n_args) == int:
655 if len(args) != n_args:
656 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
658 % (ovs.util.PROGRAM_NAME, command_name,
667 if __name__ == '__main__':
670 except error.Error as e:
671 sys.stderr.write("%s\n" % e)