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 update_condition(idl, commands):
395 commands = commands.split(";")
396 for command in commands:
397 command = command[len("condition "):]
400 command = command[len("add "):]
403 command = command[len("remove "):]
405 command = command.split(" ")
406 if(len(command) != 2):
407 sys.stderr.write("Error parsong condition %s\n" % command)
411 cond = ovs.json.from_string(command[1])
413 idl.cond_change(table, add_cmd, cond)
416 def do_idl(schema_file, remote, *commands):
417 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
418 if commands and commands[0].startswith("?"):
420 for x in commands[0][1:].split("?"):
422 table, columns = x.split(":")
423 columns = columns.split(",")
424 for index, column in enumerate(columns):
425 if column[-1] == '!':
426 columns[index] = columns[index][:-1]
427 readonly.append(columns[index])
428 schema_helper.register_columns(table, columns, readonly)
429 commands = commands[1:]
431 schema_helper.register_all()
432 idl = ovs.db.idl.Idl(remote, schema_helper)
435 error, stream = ovs.stream.Stream.open_block(
436 ovs.stream.Stream.open(remote))
438 sys.stderr.write("failed to connect to \"%s\"" % remote)
440 rpc = ovs.jsonrpc.Connection(stream)
448 commands = list(commands)
449 if len(commands) >= 1 and "condition" in commands[0]:
450 update_condition(idl, commands.pop(0))
451 sys.stdout.write("%03d: change conditions\n" % step)
455 for command in commands:
456 if command.startswith("+"):
457 # The previous transaction didn't change anything.
458 command = command[1:]
461 while idl.change_seqno == seqno and not idl.run():
464 poller = ovs.poller.Poller()
472 seqno = idl.change_seqno
474 if command == "reconnect":
475 print("%03d: reconnect" % step)
478 idl.force_reconnect()
479 elif "condition" in command:
480 update_condition(idl, command)
481 sys.stdout.write("%03d: change conditions\n" % step)
484 elif not command.startswith("["):
485 idl_set(idl, command, step)
488 json = ovs.json.from_string(command)
489 if isinstance(json, six.string_types):
490 sys.stderr.write("\"%s\": %s\n" % (command, json))
492 json = substitute_uuids(json, symtab)
493 request = ovs.jsonrpc.Message.create_request("transact", json)
494 error, reply = rpc.transact_block(request)
496 sys.stderr.write("jsonrpc transaction failed: %s"
497 % os.strerror(error))
499 elif reply.error is not None:
500 sys.stderr.write("jsonrpc transaction failed: %s"
504 sys.stdout.write("%03d: " % step)
507 if reply.result is not None:
508 parse_uuids(reply.result, symtab)
510 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
515 while idl.change_seqno == seqno and not idl.run():
516 poller = ovs.poller.Poller()
522 print("%03d: done" % step)
525 def do_idl_passive(schema_file, remote, *commands):
528 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
529 schema_helper.register_all()
530 idl = ovs.db.idl.Idl(remote, schema_helper)
532 while idl._session.rpc is None:
535 rpc = idl._session.rpc
540 for command in commands:
541 json = ovs.json.from_string(command)
542 if isinstance(json, six.string_types):
543 sys.stderr.write("\"%s\": %s\n" % (command, json))
545 json = substitute_uuids(json, symtab)
546 request = ovs.jsonrpc.Message.create_request("transact", json)
547 error, reply = rpc.transact_block(request)
549 sys.stderr.write("jsonrpc transaction failed: %s"
550 % os.strerror(error))
552 elif reply.error is not None:
553 sys.stderr.write("jsonrpc transaction failed: %s"
557 sys.stdout.write("%03d: " % step)
560 if reply.result is not None:
561 parse_uuids(reply.result, symtab)
563 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
567 print("%03d: done" % step)
572 %(program_name)s: test utility for Open vSwitch database Python bindings
573 usage: %(program_name)s [OPTIONS] COMMAND ARG...
575 The following commands are supported:
577 test ovsdb_atom_default()
579 test ovsdb_datum_default()
580 parse-atomic-type TYPE
581 parse TYPE as OVSDB atomic type, and re-serialize
583 parse TYPE as OVSDB base type, and re-serialize
585 parse JSON as OVSDB type, and re-serialize
586 parse-atoms TYPE ATOM...
587 parse JSON ATOMs as atoms of TYPE, and re-serialize
588 parse-atom-strings TYPE ATOM...
589 parse string ATOMs as atoms of given TYPE, and re-serialize
590 sort-atoms TYPE ATOM...
591 print JSON ATOMs in sorted order
592 parse-data TYPE DATUM...
593 parse JSON DATUMs as data of given TYPE, and re-serialize
594 parse-column NAME OBJECT
595 parse column NAME with info OBJECT, and re-serialize
596 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
597 parse table NAME with info OBJECT
599 parse JSON as an OVSDB schema, and re-serialize
600 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
601 connect to SERVER (which has the specified SCHEMA) and dump the
602 contents of the database as seen initially by the IDL implementation
603 and after executing each TRANSACTION. (Each TRANSACTION must modify
604 the database or this command will hang.)
605 By default, all columns of all tables are monitored. The "?" option
606 can be used to monitor specific Table:Column(s). The table and their
607 columns are listed as a string of the form starting with "?":
608 ?<table-name>:<column-name>,<column-name>,...
610 ?simple:b - Monitor column "b" in table "simple"
611 Entries for multiple tables are seperated by "?":
612 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
614 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
615 and column "i", "k" in table "link1"
616 Readonly columns: Suffixing a "!" after a column indicates that the
617 column is to be registered "readonly".
619 ?simple:i,b! - Register interest in column "i" (monitoring) and
620 column "b" (readonly).
623 The following options are also available:
624 -t, --timeout=SECS give up after SECS seconds
625 -h, --help display this help message\
626 """ % {'program_name': ovs.util.PROGRAM_NAME})
632 options, args = getopt.gnu_getopt(argv[1:], 't:h',
635 except getopt.GetoptError as geo:
636 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
639 for key, value in options:
640 if key in ['-h', '--help']:
642 elif key in ['-t', '--timeout']:
648 raise error.Error("value %s on -t or --timeout is not at "
650 signal.alarm(timeout)
655 sys.stderr.write("%s: missing command argument "
656 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
659 commands = {"default-atoms": (do_default_atoms, 0),
660 "default-data": (do_default_data, 0),
661 "parse-atomic-type": (do_parse_atomic_type, 1),
662 "parse-base-type": (do_parse_base_type, 1),
663 "parse-type": (do_parse_type, 1),
664 "parse-atoms": (do_parse_atoms, (2,)),
665 "parse-data": (do_parse_data, (2,)),
666 "sort-atoms": (do_sort_atoms, 2),
667 "parse-column": (do_parse_column, 2),
668 "parse-table": (do_parse_table, (2, 3)),
669 "parse-schema": (do_parse_schema, 1),
670 "idl": (do_idl, (2,)),
671 "idl_passive": (do_idl_passive, (2,))}
673 command_name = args[0]
675 if command_name not in commands:
676 sys.stderr.write("%s: unknown command \"%s\" "
677 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
681 func, n_args = commands[command_name]
682 if type(n_args) == tuple:
683 if len(args) < n_args[0]:
684 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
686 % (ovs.util.PROGRAM_NAME, command_name,
689 elif type(n_args) == int:
690 if len(args) != n_args:
691 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
693 % (ovs.util.PROGRAM_NAME, command_name,
702 if __name__ == '__main__':
705 except error.Error as e:
706 sys.stderr.write("%s\n" % e)