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):
150 if "simple" in idl.tables:
151 simple_columns = ["i", "r", "b", "s", "u", "ia",
152 "ra", "ba", "sa", "ua", "uuid"]
153 simple = idl.tables["simple"].rows
154 for row in simple.itervalues():
156 for column in simple_columns:
157 if hasattr(row, column) and not (type(getattr(row, column))
158 is ovs.db.data.Atom):
159 s += " %s=%s" % (column, getattr(row, column))
160 s = re.sub('""|,|u?\'', "", s)
161 s = re.sub('UUID\(([^)]+)\)', r'\1', s)
162 s = re.sub('False', 'false', s)
163 s = re.sub('True', 'true', s)
164 s = re.sub(r'(ba)=([^[][^ ]*) ', r'\1=[\2] ', s)
168 if "link1" in idl.tables:
169 l1 = idl.tables["link1"].rows
170 for row in l1.itervalues():
171 s = ["%03d: i=%s k=" % (step, row.i)]
172 if hasattr(row, "k") and row.k:
173 s.append(str(row.k.i))
174 if hasattr(row, "ka"):
176 s.append(' '.join(sorted(str(ka.i) for ka in row.ka)))
178 if hasattr(row, "l2") and row.l2:
179 s.append(str(row.l2[0].i))
180 if hasattr(row, "uuid"):
181 s.append(" uuid=%s" % row.uuid)
185 if "link2" in idl.tables:
186 l2 = idl.tables["link2"].rows
187 for row in l2.itervalues():
189 s.append(" i=%s l1=" % row.i)
190 if hasattr(row, "l1") and row.l1:
191 s.append(str(row.l1[0].i))
192 if hasattr(row, "uuid"):
193 s.append(" uuid=%s" % row.uuid)
198 print("%03d: empty" % step)
202 def substitute_uuids(json, symtab):
203 if type(json) in [str, unicode]:
204 symbol = symtab.get(json)
207 elif type(json) == list:
208 return [substitute_uuids(element, symtab) for element in json]
209 elif type(json) == dict:
211 for key, value in json.iteritems():
212 d[key] = substitute_uuids(value, symtab)
217 def parse_uuids(json, symtab):
218 if type(json) in [str, unicode] and ovs.ovsuuid.is_valid_string(json):
219 name = "#%d#" % len(symtab)
220 sys.stderr.write("%s = %s\n" % (name, json))
222 elif type(json) == list:
224 parse_uuids(element, symtab)
225 elif type(json) == dict:
226 for value in json.itervalues():
227 parse_uuids(value, symtab)
230 def idltest_find_simple(idl, i):
231 for row in idl.tables["simple"].rows.itervalues():
237 def idl_set(idl, commands, step):
238 txn = ovs.db.idl.Transaction(idl)
242 for command in commands.split(','):
243 words = command.split()
247 if name == "notifytest":
250 old_notify = idl.notify
252 def notify(event, row, updates=None):
254 upcol = updates._data.keys()[0]
257 events.append("%s|%s|%s" % (event, row.i, upcol))
258 idl.notify = old_notify
264 sys.stderr.write('"set" command requires 3 arguments\n')
267 s = idltest_find_simple(idl, int(args[0]))
269 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
278 s.u = uuid.UUID(args[2])
282 sys.stderr.write('"set" comamnd asks for unknown column %s\n'
285 elif name == "insert":
287 sys.stderr.write('"set" command requires 1 argument\n')
290 s = txn.insert(idl.tables["simple"])
292 elif name == "delete":
294 sys.stderr.write('"delete" command requires 1 argument\n')
297 s = idltest_find_simple(idl, int(args[0]))
299 sys.stderr.write('"delete" command asks for nonexistent i=%d\n'
303 elif name == "verify":
305 sys.stderr.write('"verify" command requires 2 arguments\n')
308 s = idltest_find_simple(idl, int(args[0]))
310 sys.stderr.write('"verify" command asks for nonexistent i=%d\n'
314 if args[1] in ("i", "b", "s", "u", "r"):
317 sys.stderr.write('"verify" command asks for unknown column '
320 elif name == "fetch":
322 sys.stderr.write('"fetch" command requires 2 argument\n')
325 row = idltest_find_simple(idl, int(args[0]))
327 sys.stderr.write('"fetch" command asks for nonexistent i=%d\n'
333 fetch_cmds.append([row, column])
334 elif name == "increment":
336 sys.stderr.write('"increment" command requires 1 argument\n')
339 s = idltest_find_simple(idl, int(args[0]))
341 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
347 elif name == "abort":
350 elif name == "destroy":
351 print "%03d: destroy" % step
355 elif name == "linktest":
356 l1_0 = txn.insert(idl.tables["link1"])
360 l1_1 = txn.insert(idl.tables["link1"])
363 l1_1.ka = [l1_0, l1_1]
364 elif name == 'getattrtest':
365 l1 = txn.insert(idl.tables["link1"])
366 i = getattr(l1, 'i', 1)
369 i = getattr(l1, 'i', 1)
373 sys.stderr.write("unknown command %s\n" % name)
376 status = txn.commit_block()
377 sys.stdout.write("%03d: commit, status=%s"
378 % (step, ovs.db.idl.Transaction.status_to_string(status)))
379 if increment and status == ovs.db.idl.Transaction.SUCCESS:
380 sys.stdout.write(", increment=%d" % txn.get_increment_new_value())
382 # Event notifications from operations in a single transaction are
383 # not in a gauranteed order due to update messages being dicts
384 sys.stdout.write(", events=" + ", ".join(sorted(events)))
385 sys.stdout.write("\n")
389 def do_idl(schema_file, remote, *commands):
390 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
391 if commands and commands[0].startswith("?"):
393 for x in commands[0][1:].split("?"):
395 table, columns = x.split(":")
396 columns = columns.split(",")
397 for index, column in enumerate(columns):
398 if column[-1] == '!':
399 columns[index] = columns[index][:-1]
400 readonly.append(columns[index])
401 schema_helper.register_columns(table, columns, readonly)
402 commands = commands[1:]
404 schema_helper.register_all()
405 idl = ovs.db.idl.Idl(remote, schema_helper)
408 error, stream = ovs.stream.Stream.open_block(
409 ovs.stream.Stream.open(remote))
411 sys.stderr.write("failed to connect to \"%s\"" % remote)
413 rpc = ovs.jsonrpc.Connection(stream)
420 for command in commands:
421 if command.startswith("+"):
422 # The previous transaction didn't change anything.
423 command = command[1:]
426 while idl.change_seqno == seqno and not idl.run():
429 poller = ovs.poller.Poller()
437 seqno = idl.change_seqno
439 if command == "reconnect":
440 print("%03d: reconnect" % step)
443 idl.force_reconnect()
444 elif not command.startswith("["):
445 idl_set(idl, command, step)
448 json = ovs.json.from_string(command)
449 if type(json) in [str, unicode]:
450 sys.stderr.write("\"%s\": %s\n" % (command, json))
452 json = substitute_uuids(json, symtab)
453 request = ovs.jsonrpc.Message.create_request("transact", json)
454 error, reply = rpc.transact_block(request)
456 sys.stderr.write("jsonrpc transaction failed: %s"
457 % os.strerror(error))
459 elif reply.error is not None:
460 sys.stderr.write("jsonrpc transaction failed: %s"
464 sys.stdout.write("%03d: " % step)
467 if reply.result is not None:
468 parse_uuids(reply.result, symtab)
470 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
475 while idl.change_seqno == seqno and not idl.run():
476 poller = ovs.poller.Poller()
482 print("%03d: done" % step)
487 %(program_name)s: test utility for Open vSwitch database Python bindings
488 usage: %(program_name)s [OPTIONS] COMMAND ARG...
490 The following commands are supported:
492 test ovsdb_atom_default()
494 test ovsdb_datum_default()
495 parse-atomic-type TYPE
496 parse TYPE as OVSDB atomic type, and re-serialize
498 parse TYPE as OVSDB base type, and re-serialize
500 parse JSON as OVSDB type, and re-serialize
501 parse-atoms TYPE ATOM...
502 parse JSON ATOMs as atoms of TYPE, and re-serialize
503 parse-atom-strings TYPE ATOM...
504 parse string ATOMs as atoms of given TYPE, and re-serialize
505 sort-atoms TYPE ATOM...
506 print JSON ATOMs in sorted order
507 parse-data TYPE DATUM...
508 parse JSON DATUMs as data of given TYPE, and re-serialize
509 parse-column NAME OBJECT
510 parse column NAME with info OBJECT, and re-serialize
511 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
512 parse table NAME with info OBJECT
514 parse JSON as an OVSDB schema, and re-serialize
515 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
516 connect to SERVER (which has the specified SCHEMA) and dump the
517 contents of the database as seen initially by the IDL implementation
518 and after executing each TRANSACTION. (Each TRANSACTION must modify
519 the database or this command will hang.)
520 By default, all columns of all tables are monitored. The "?" option
521 can be used to monitor specific Table:Column(s). The table and their
522 columns are listed as a string of the form starting with "?":
523 ?<table-name>:<column-name>,<column-name>,...
525 ?simple:b - Monitor column "b" in table "simple"
526 Entries for multiple tables are seperated by "?":
527 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
529 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
530 and column "i", "k" in table "link1"
531 Readonly columns: Suffixing a "!" after a column indicates that the
532 column is to be registered "readonly".
534 ?simple:i,b! - Register interest in column "i" (monitoring) and
535 column "b" (readonly).
538 The following options are also available:
539 -t, --timeout=SECS give up after SECS seconds
540 -h, --help display this help message\
541 """ % {'program_name': ovs.util.PROGRAM_NAME}
547 options, args = getopt.gnu_getopt(argv[1:], 't:h',
550 except getopt.GetoptError, geo:
551 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
554 for key, value in options:
555 if key in ['-h', '--help']:
557 elif key in ['-t', '--timeout']:
563 raise error.Error("value %s on -t or --timeout is not at "
565 signal.alarm(timeout)
570 sys.stderr.write("%s: missing command argument "
571 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
574 commands = {"default-atoms": (do_default_atoms, 0),
575 "default-data": (do_default_data, 0),
576 "parse-atomic-type": (do_parse_atomic_type, 1),
577 "parse-base-type": (do_parse_base_type, 1),
578 "parse-type": (do_parse_type, 1),
579 "parse-atoms": (do_parse_atoms, (2,)),
580 "parse-data": (do_parse_data, (2,)),
581 "sort-atoms": (do_sort_atoms, 2),
582 "parse-column": (do_parse_column, 2),
583 "parse-table": (do_parse_table, (2, 3)),
584 "parse-schema": (do_parse_schema, 1),
585 "idl": (do_idl, (2,))}
587 command_name = args[0]
589 if not command_name in commands:
590 sys.stderr.write("%s: unknown command \"%s\" "
591 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
595 func, n_args = commands[command_name]
596 if type(n_args) == tuple:
597 if len(args) < n_args[0]:
598 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
600 % (ovs.util.PROGRAM_NAME, command_name,
603 elif type(n_args) == int:
604 if len(args) != n_args:
605 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
607 % (ovs.util.PROGRAM_NAME, command_name,
616 if __name__ == '__main__':
619 except error.Error, e:
620 sys.stderr.write("%s\n" % e)