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:
112 print(e.args[0].encode("utf8"))
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 type(json) in [str, unicode]:
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 type(json) in [str, unicode] and ovs.ovsuuid.is_valid_string(json):
223 name = "#%d#" % len(symtab)
224 sys.stderr.write("%s = %s\n" % (name, json))
226 elif type(json) == list:
228 parse_uuids(element, symtab)
229 elif type(json) == dict:
230 for value in six.itervalues(json):
231 parse_uuids(value, symtab)
234 def idltest_find_simple(idl, i):
235 for row in six.itervalues(idl.tables["simple"].rows):
241 def idl_set(idl, commands, step):
242 txn = ovs.db.idl.Transaction(idl)
246 for command in commands.split(','):
247 words = command.split()
251 if name == "notifytest":
254 old_notify = idl.notify
256 def notify(event, row, updates=None):
258 upcol = list(updates._data.keys())[0]
261 events.append("%s|%s|%s" % (event, row.i, upcol))
262 idl.notify = old_notify
268 sys.stderr.write('"set" command requires 3 arguments\n')
271 s = idltest_find_simple(idl, int(args[0]))
273 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
282 s.u = uuid.UUID(args[2])
286 sys.stderr.write('"set" comamnd asks for unknown column %s\n'
289 elif name == "insert":
291 sys.stderr.write('"set" command requires 1 argument\n')
294 s = txn.insert(idl.tables["simple"])
296 elif name == "delete":
298 sys.stderr.write('"delete" command requires 1 argument\n')
301 s = idltest_find_simple(idl, int(args[0]))
303 sys.stderr.write('"delete" command asks for nonexistent i=%d\n'
307 elif name == "verify":
309 sys.stderr.write('"verify" command requires 2 arguments\n')
312 s = idltest_find_simple(idl, int(args[0]))
314 sys.stderr.write('"verify" command asks for nonexistent i=%d\n'
318 if args[1] in ("i", "b", "s", "u", "r"):
321 sys.stderr.write('"verify" command asks for unknown column '
324 elif name == "fetch":
326 sys.stderr.write('"fetch" command requires 2 argument\n')
329 row = idltest_find_simple(idl, int(args[0]))
331 sys.stderr.write('"fetch" command asks for nonexistent i=%d\n'
337 fetch_cmds.append([row, column])
338 elif name == "increment":
340 sys.stderr.write('"increment" command requires 1 argument\n')
343 s = idltest_find_simple(idl, int(args[0]))
345 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
351 elif name == "abort":
354 elif name == "destroy":
355 print("%03d: destroy" % step)
359 elif name == "linktest":
360 l1_0 = txn.insert(idl.tables["link1"])
364 l1_1 = txn.insert(idl.tables["link1"])
367 l1_1.ka = [l1_0, l1_1]
368 elif name == 'getattrtest':
369 l1 = txn.insert(idl.tables["link1"])
370 i = getattr(l1, 'i', 1)
373 i = getattr(l1, 'i', 1)
377 sys.stderr.write("unknown command %s\n" % name)
380 status = txn.commit_block()
381 sys.stdout.write("%03d: commit, status=%s"
382 % (step, ovs.db.idl.Transaction.status_to_string(status)))
383 if increment and status == ovs.db.idl.Transaction.SUCCESS:
384 sys.stdout.write(", increment=%d" % txn.get_increment_new_value())
386 # Event notifications from operations in a single transaction are
387 # not in a gauranteed order due to update messages being dicts
388 sys.stdout.write(", events=" + ", ".join(sorted(events)))
389 sys.stdout.write("\n")
393 def do_idl(schema_file, remote, *commands):
394 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
395 if commands and commands[0].startswith("?"):
397 for x in commands[0][1:].split("?"):
399 table, columns = x.split(":")
400 columns = columns.split(",")
401 for index, column in enumerate(columns):
402 if column[-1] == '!':
403 columns[index] = columns[index][:-1]
404 readonly.append(columns[index])
405 schema_helper.register_columns(table, columns, readonly)
406 commands = commands[1:]
408 schema_helper.register_all()
409 idl = ovs.db.idl.Idl(remote, schema_helper)
412 error, stream = ovs.stream.Stream.open_block(
413 ovs.stream.Stream.open(remote))
415 sys.stderr.write("failed to connect to \"%s\"" % remote)
417 rpc = ovs.jsonrpc.Connection(stream)
424 for command in commands:
425 if command.startswith("+"):
426 # The previous transaction didn't change anything.
427 command = command[1:]
430 while idl.change_seqno == seqno and not idl.run():
433 poller = ovs.poller.Poller()
441 seqno = idl.change_seqno
443 if command == "reconnect":
444 print("%03d: reconnect" % step)
447 idl.force_reconnect()
448 elif not command.startswith("["):
449 idl_set(idl, command, step)
452 json = ovs.json.from_string(command)
453 if type(json) in [str, unicode]:
454 sys.stderr.write("\"%s\": %s\n" % (command, json))
456 json = substitute_uuids(json, symtab)
457 request = ovs.jsonrpc.Message.create_request("transact", json)
458 error, reply = rpc.transact_block(request)
460 sys.stderr.write("jsonrpc transaction failed: %s"
461 % os.strerror(error))
463 elif reply.error is not None:
464 sys.stderr.write("jsonrpc transaction failed: %s"
468 sys.stdout.write("%03d: " % step)
471 if reply.result is not None:
472 parse_uuids(reply.result, symtab)
474 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
479 while idl.change_seqno == seqno and not idl.run():
480 poller = ovs.poller.Poller()
486 print("%03d: done" % step)
491 %(program_name)s: test utility for Open vSwitch database Python bindings
492 usage: %(program_name)s [OPTIONS] COMMAND ARG...
494 The following commands are supported:
496 test ovsdb_atom_default()
498 test ovsdb_datum_default()
499 parse-atomic-type TYPE
500 parse TYPE as OVSDB atomic type, and re-serialize
502 parse TYPE as OVSDB base type, and re-serialize
504 parse JSON as OVSDB type, and re-serialize
505 parse-atoms TYPE ATOM...
506 parse JSON ATOMs as atoms of TYPE, and re-serialize
507 parse-atom-strings TYPE ATOM...
508 parse string ATOMs as atoms of given TYPE, and re-serialize
509 sort-atoms TYPE ATOM...
510 print JSON ATOMs in sorted order
511 parse-data TYPE DATUM...
512 parse JSON DATUMs as data of given TYPE, and re-serialize
513 parse-column NAME OBJECT
514 parse column NAME with info OBJECT, and re-serialize
515 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
516 parse table NAME with info OBJECT
518 parse JSON as an OVSDB schema, and re-serialize
519 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
520 connect to SERVER (which has the specified SCHEMA) and dump the
521 contents of the database as seen initially by the IDL implementation
522 and after executing each TRANSACTION. (Each TRANSACTION must modify
523 the database or this command will hang.)
524 By default, all columns of all tables are monitored. The "?" option
525 can be used to monitor specific Table:Column(s). The table and their
526 columns are listed as a string of the form starting with "?":
527 ?<table-name>:<column-name>,<column-name>,...
529 ?simple:b - Monitor column "b" in table "simple"
530 Entries for multiple tables are seperated by "?":
531 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
533 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
534 and column "i", "k" in table "link1"
535 Readonly columns: Suffixing a "!" after a column indicates that the
536 column is to be registered "readonly".
538 ?simple:i,b! - Register interest in column "i" (monitoring) and
539 column "b" (readonly).
542 The following options are also available:
543 -t, --timeout=SECS give up after SECS seconds
544 -h, --help display this help message\
545 """ % {'program_name': ovs.util.PROGRAM_NAME})
551 options, args = getopt.gnu_getopt(argv[1:], 't:h',
554 except getopt.GetoptError as geo:
555 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
558 for key, value in options:
559 if key in ['-h', '--help']:
561 elif key in ['-t', '--timeout']:
567 raise error.Error("value %s on -t or --timeout is not at "
569 signal.alarm(timeout)
574 sys.stderr.write("%s: missing command argument "
575 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
578 commands = {"default-atoms": (do_default_atoms, 0),
579 "default-data": (do_default_data, 0),
580 "parse-atomic-type": (do_parse_atomic_type, 1),
581 "parse-base-type": (do_parse_base_type, 1),
582 "parse-type": (do_parse_type, 1),
583 "parse-atoms": (do_parse_atoms, (2,)),
584 "parse-data": (do_parse_data, (2,)),
585 "sort-atoms": (do_sort_atoms, 2),
586 "parse-column": (do_parse_column, 2),
587 "parse-table": (do_parse_table, (2, 3)),
588 "parse-schema": (do_parse_schema, 1),
589 "idl": (do_idl, (2,))}
591 command_name = args[0]
593 if command_name not in commands:
594 sys.stderr.write("%s: unknown command \"%s\" "
595 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
599 func, n_args = commands[command_name]
600 if type(n_args) == tuple:
601 if len(args) < n_args[0]:
602 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
604 % (ovs.util.PROGRAM_NAME, command_name,
607 elif type(n_args) == int:
608 if len(args) != n_args:
609 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
611 % (ovs.util.PROGRAM_NAME, command_name,
620 if __name__ == '__main__':
623 except error.Error as e:
624 sys.stderr.write("%s\n" % e)