-# Copyright (c) 2009, 2010, 2011 Nicira Networks
+# Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# See the License for the specific language governing permissions and
# limitations under the License.
-import codecs
+from __future__ import print_function
+
import getopt
import re
import os
import signal
import sys
+import uuid
from ovs.db import error
import ovs.db.idl
import ovs.db.schema
from ovs.db import data
-from ovs.db import types
+import ovs.db.types
import ovs.ovsuuid
import ovs.poller
import ovs.util
+
def unbox_json(json):
if type(json) == list and len(json) == 1:
return json[0]
else:
return json
+
def do_default_atoms():
- for type in types.ATOMIC_TYPES:
- if type == types.VoidType:
+ for type_ in ovs.db.types.ATOMIC_TYPES:
+ if type_ == ovs.db.types.VoidType:
continue
- sys.stdout.write("%s: " % type.to_string())
+ sys.stdout.write("%s: " % type_.to_string())
- atom = data.Atom.default(type)
- if atom != data.Atom.default(type):
+ atom = data.Atom.default(type_)
+ if atom != data.Atom.default(type_):
sys.stdout.write("wrong\n")
sys.exit(1)
sys.stdout.write("OK\n")
+
def do_default_data():
any_errors = False
for n_min in 0, 1:
- for key in types.ATOMIC_TYPES:
- if key == types.VoidType:
+ for key in ovs.db.types.ATOMIC_TYPES:
+ if key == ovs.db.types.VoidType:
continue
- for value in types.ATOMIC_TYPES:
- if value == types.VoidType:
+ for value in ovs.db.types.ATOMIC_TYPES:
+ if value == ovs.db.types.VoidType:
valueBase = None
else:
- valueBase = types.BaseType(value)
- type = types.Type(types.BaseType(key), valueBase, n_min, 1)
- assert type.is_valid()
+ valueBase = ovs.db.types.BaseType(value)
+ type_ = ovs.db.types.Type(ovs.db.types.BaseType(key),
+ valueBase, n_min, 1)
+ assert type_.is_valid()
sys.stdout.write("key %s, value %s, n_min %d: "
% (key.to_string(), value.to_string(), n_min))
- datum = data.Datum.default(type)
- if datum != data.Datum.default(type):
+ datum = data.Datum.default(type_)
+ if datum != data.Datum.default(type_):
sys.stdout.write("wrong\n")
any_errors = True
else:
if any_errors:
sys.exit(1)
+
def do_parse_atomic_type(type_string):
type_json = unbox_json(ovs.json.from_string(type_string))
- atomic_type = types.AtomicType.from_json(type_json)
- print ovs.json.to_string(atomic_type.to_json(), sort_keys=True)
+ atomic_type = ovs.db.types.AtomicType.from_json(type_json)
+ print(ovs.json.to_string(atomic_type.to_json(), sort_keys=True))
+
def do_parse_base_type(type_string):
type_json = unbox_json(ovs.json.from_string(type_string))
- base_type = types.BaseType.from_json(type_json)
- print ovs.json.to_string(base_type.to_json(), sort_keys=True)
+ base_type = ovs.db.types.BaseType.from_json(type_json)
+ print(ovs.json.to_string(base_type.to_json(), sort_keys=True))
+
def do_parse_type(type_string):
type_json = unbox_json(ovs.json.from_string(type_string))
- type = types.Type.from_json(type_json)
- print ovs.json.to_string(type.to_json(), sort_keys=True)
+ type_ = ovs.db.types.Type.from_json(type_json)
+ print(ovs.json.to_string(type_.to_json(), sort_keys=True))
+
def do_parse_atoms(type_string, *atom_strings):
type_json = unbox_json(ovs.json.from_string(type_string))
- base = types.BaseType.from_json(type_json)
+ base = ovs.db.types.BaseType.from_json(type_json)
for atom_string in atom_strings:
atom_json = unbox_json(ovs.json.from_string(atom_string))
try:
atom = data.Atom.from_json(base, atom_json)
- print ovs.json.to_string(atom.to_json())
- except error.Error, e:
- print unicode(e)
+ print(ovs.json.to_string(atom.to_json()))
+ except error.Error as e:
+ print(e.args[0].encode("utf8"))
+
def do_parse_data(type_string, *data_strings):
type_json = unbox_json(ovs.json.from_string(type_string))
- type = types.Type.from_json(type_json)
+ type_ = ovs.db.types.Type.from_json(type_json)
for datum_string in data_strings:
datum_json = unbox_json(ovs.json.from_string(datum_string))
- datum = data.Datum.from_json(type, datum_json)
- print ovs.json.to_string(datum.to_json())
+ datum = data.Datum.from_json(type_, datum_json)
+ print(ovs.json.to_string(datum.to_json()))
+
def do_sort_atoms(type_string, atom_strings):
type_json = unbox_json(ovs.json.from_string(type_string))
- base = types.BaseType.from_json(type_json)
+ base = ovs.db.types.BaseType.from_json(type_json)
atoms = [data.Atom.from_json(base, atom_json)
for atom_json in unbox_json(ovs.json.from_string(atom_strings))]
- print ovs.json.to_string([data.Atom.to_json(atom)
- for atom in sorted(atoms)])
+ print(ovs.json.to_string([data.Atom.to_json(atom)
+ for atom in sorted(atoms)]))
+
def do_parse_column(name, column_string):
column_json = unbox_json(ovs.json.from_string(column_string))
column = ovs.db.schema.ColumnSchema.from_json(column_json, name)
- print ovs.json.to_string(column.to_json(), sort_keys=True)
+ print(ovs.json.to_string(column.to_json(), sort_keys=True))
+
def do_parse_table(name, table_string, default_is_root_string='false'):
default_is_root = default_is_root_string == 'true'
table_json = unbox_json(ovs.json.from_string(table_string))
table = ovs.db.schema.TableSchema.from_json(table_json, name)
- print ovs.json.to_string(table.to_json(default_is_root), sort_keys=True)
+ print(ovs.json.to_string(table.to_json(default_is_root), sort_keys=True))
-def do_parse_rows(table_string, *rows):
- table_json = unbox_json(ovs.json.from_string(table_string))
- table = ovs.db.schema.TableSchema.from_json(table_json, name)
def do_parse_schema(schema_string):
schema_json = unbox_json(ovs.json.from_string(schema_string))
schema = ovs.db.schema.DbSchema.from_json(schema_json)
- print ovs.json.to_string(schema.to_json(), sort_keys=True)
+ print(ovs.json.to_string(schema.to_json(), sort_keys=True))
+
def print_idl(idl, step):
n = 0
- for uuid, row in idl.data["simple"].iteritems():
- s = ("%03d: i=%s r=%s b=%s s=%s u=%s "
- "ia=%s ra=%s ba=%s sa=%s ua=%s uuid=%s"
- % (step, row.i, row.r, row.b, row.s, row.u,
- row.ia, row.ra, row.ba, row.sa, row.ua, uuid))
- print(re.sub('""|,', "", s))
- n += 1
+ if "simple" in idl.tables:
+ simple_columns = ["i", "r", "b", "s", "u", "ia",
+ "ra", "ba", "sa", "ua", "uuid"]
+ simple = idl.tables["simple"].rows
+ for row in simple.itervalues():
+ s = "%03d:" % step
+ for column in simple_columns:
+ if hasattr(row, column) and not (type(getattr(row, column))
+ is ovs.db.data.Atom):
+ s += " %s=%s" % (column, getattr(row, column))
+ s = re.sub('""|,|u?\'', "", s)
+ s = re.sub('UUID\(([^)]+)\)', r'\1', s)
+ s = re.sub('False', 'false', s)
+ s = re.sub('True', 'true', s)
+ s = re.sub(r'(ba)=([^[][^ ]*) ', r'\1=[\2] ', s)
+ print(s)
+ n += 1
+
+ if "link1" in idl.tables:
+ l1 = idl.tables["link1"].rows
+ for row in l1.itervalues():
+ s = ["%03d: i=%s k=" % (step, row.i)]
+ if hasattr(row, "k") and row.k:
+ s.append(str(row.k.i))
+ if hasattr(row, "ka"):
+ s.append(" ka=[")
+ s.append(' '.join(sorted(str(ka.i) for ka in row.ka)))
+ s.append("] l2=")
+ if hasattr(row, "l2") and row.l2:
+ s.append(str(row.l2[0].i))
+ if hasattr(row, "uuid"):
+ s.append(" uuid=%s" % row.uuid)
+ print(''.join(s))
+ n += 1
+
+ if "link2" in idl.tables:
+ l2 = idl.tables["link2"].rows
+ for row in l2.itervalues():
+ s = ["%03d:" % step]
+ s.append(" i=%s l1=" % row.i)
+ if hasattr(row, "l1") and row.l1:
+ s.append(str(row.l1[0].i))
+ if hasattr(row, "uuid"):
+ s.append(" uuid=%s" % row.uuid)
+ print(''.join(s))
+ n += 1
+
if not n:
print("%03d: empty" % step)
+ sys.stdout.flush()
+
def substitute_uuids(json, symtab):
if type(json) in [str, unicode]:
return d
return json
+
def parse_uuids(json, symtab):
- if type(json) in [str, unicode] and ovs.ovsuuid.UUID.is_valid_string(json):
+ if type(json) in [str, unicode] and ovs.ovsuuid.is_valid_string(json):
name = "#%d#" % len(symtab)
sys.stderr.write("%s = %s\n" % (name, json))
symtab[name] = json
for value in json.itervalues():
parse_uuids(value, symtab)
-def do_idl(remote, *commands):
- idl = ovs.db.idl.Idl(remote, "idltest")
+
+def idltest_find_simple(idl, i):
+ for row in idl.tables["simple"].rows.itervalues():
+ if row.i == i:
+ return row
+ return None
+
+
+def idl_set(idl, commands, step):
+ txn = ovs.db.idl.Transaction(idl)
+ increment = False
+ fetch_cmds = []
+ events = []
+ for command in commands.split(','):
+ words = command.split()
+ name = words[0]
+ args = words[1:]
+
+ if name == "notifytest":
+ name = args[0]
+ args = args[1:]
+ old_notify = idl.notify
+
+ def notify(event, row, updates=None):
+ if updates:
+ upcol = updates._data.keys()[0]
+ else:
+ upcol = None
+ events.append("%s|%s|%s" % (event, row.i, upcol))
+ idl.notify = old_notify
+
+ idl.notify = notify
+
+ if name == "set":
+ if len(args) != 3:
+ sys.stderr.write('"set" command requires 3 arguments\n')
+ sys.exit(1)
+
+ s = idltest_find_simple(idl, int(args[0]))
+ if not s:
+ sys.stderr.write('"set" command asks for nonexistent i=%d\n'
+ % int(args[0]))
+ sys.exit(1)
+
+ if args[1] == "b":
+ s.b = args[2] == "1"
+ elif args[1] == "s":
+ s.s = args[2]
+ elif args[1] == "u":
+ s.u = uuid.UUID(args[2])
+ elif args[1] == "r":
+ s.r = float(args[2])
+ else:
+ sys.stderr.write('"set" comamnd asks for unknown column %s\n'
+ % args[2])
+ sys.stderr.exit(1)
+ elif name == "insert":
+ if len(args) != 1:
+ sys.stderr.write('"set" command requires 1 argument\n')
+ sys.exit(1)
+
+ s = txn.insert(idl.tables["simple"])
+ s.i = int(args[0])
+ elif name == "delete":
+ if len(args) != 1:
+ sys.stderr.write('"delete" command requires 1 argument\n')
+ sys.exit(1)
+
+ s = idltest_find_simple(idl, int(args[0]))
+ if not s:
+ sys.stderr.write('"delete" command asks for nonexistent i=%d\n'
+ % int(args[0]))
+ sys.exit(1)
+ s.delete()
+ elif name == "verify":
+ if len(args) != 2:
+ sys.stderr.write('"verify" command requires 2 arguments\n')
+ sys.exit(1)
+
+ s = idltest_find_simple(idl, int(args[0]))
+ if not s:
+ sys.stderr.write('"verify" command asks for nonexistent i=%d\n'
+ % int(args[0]))
+ sys.exit(1)
+
+ if args[1] in ("i", "b", "s", "u", "r"):
+ s.verify(args[1])
+ else:
+ sys.stderr.write('"verify" command asks for unknown column '
+ '"%s"\n' % args[1])
+ sys.exit(1)
+ elif name == "fetch":
+ if len(args) != 2:
+ sys.stderr.write('"fetch" command requires 2 argument\n')
+ sys.exit(1)
+
+ row = idltest_find_simple(idl, int(args[0]))
+ if not row:
+ sys.stderr.write('"fetch" command asks for nonexistent i=%d\n'
+ % int(args[0]))
+ sys.exit(1)
+
+ column = args[1]
+ row.fetch(column)
+ fetch_cmds.append([row, column])
+ elif name == "increment":
+ if len(args) != 1:
+ sys.stderr.write('"increment" command requires 1 argument\n')
+ sys.exit(1)
+
+ s = idltest_find_simple(idl, int(args[0]))
+ if not s:
+ sys.stderr.write('"set" command asks for nonexistent i=%d\n'
+ % int(args[0]))
+ sys.exit(1)
+
+ s.increment("i")
+ increment = True
+ elif name == "abort":
+ txn.abort()
+ break
+ elif name == "destroy":
+ print("%03d: destroy" % step)
+ sys.stdout.flush()
+ txn.abort()
+ return
+ elif name == "linktest":
+ l1_0 = txn.insert(idl.tables["link1"])
+ l1_0.i = 1
+ l1_0.k = [l1_0]
+ l1_0.ka = [l1_0]
+ l1_1 = txn.insert(idl.tables["link1"])
+ l1_1.i = 2
+ l1_1.k = [l1_0]
+ l1_1.ka = [l1_0, l1_1]
+ elif name == 'getattrtest':
+ l1 = txn.insert(idl.tables["link1"])
+ i = getattr(l1, 'i', 1)
+ assert i == 1
+ l1.i = 2
+ i = getattr(l1, 'i', 1)
+ assert i == 2
+ l1.k = [l1]
+ else:
+ sys.stderr.write("unknown command %s\n" % name)
+ sys.exit(1)
+
+ status = txn.commit_block()
+ sys.stdout.write("%03d: commit, status=%s"
+ % (step, ovs.db.idl.Transaction.status_to_string(status)))
+ if increment and status == ovs.db.idl.Transaction.SUCCESS:
+ sys.stdout.write(", increment=%d" % txn.get_increment_new_value())
+ if events:
+ # Event notifications from operations in a single transaction are
+ # not in a gauranteed order due to update messages being dicts
+ sys.stdout.write(", events=" + ", ".join(sorted(events)))
+ sys.stdout.write("\n")
+ sys.stdout.flush()
+
+
+def do_idl(schema_file, remote, *commands):
+ schema_helper = ovs.db.idl.SchemaHelper(schema_file)
+ if commands and commands[0].startswith("?"):
+ readonly = {}
+ for x in commands[0][1:].split("?"):
+ readonly = []
+ table, columns = x.split(":")
+ columns = columns.split(",")
+ for index, column in enumerate(columns):
+ if column[-1] == '!':
+ columns[index] = columns[index][:-1]
+ readonly.append(columns[index])
+ schema_helper.register_columns(table, columns, readonly)
+ commands = commands[1:]
+ else:
+ schema_helper.register_all()
+ idl = ovs.db.idl.Idl(remote, schema_helper)
if commands:
error, stream = ovs.stream.Stream.open_block(
command = command[1:]
else:
# Wait for update.
- while idl.get_seqno() == seqno and not idl.run():
+ while idl.change_seqno == seqno and not idl.run():
rpc.run()
poller = ovs.poller.Poller()
idl.wait(poller)
rpc.wait(poller)
poller.block()
-
+
print_idl(idl, step)
step += 1
- seqno = idl.get_seqno()
+ seqno = idl.change_seqno
if command == "reconnect":
print("%03d: reconnect" % step)
+ sys.stdout.flush()
step += 1
idl.force_reconnect()
elif not command.startswith("["):
sys.stderr.write("jsonrpc transaction failed: %s"
% os.strerror(error))
sys.exit(1)
+ elif reply.error is not None:
+ sys.stderr.write("jsonrpc transaction failed: %s"
+ % reply.error)
+ sys.exit(1)
+
sys.stdout.write("%03d: " % step)
sys.stdout.flush()
step += 1
parse_uuids(reply.result, symtab)
reply.id = None
sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
+ sys.stdout.flush()
if rpc:
rpc.close()
- while idl.get_seqno() == seqno and not idl.run():
+ while idl.change_seqno == seqno and not idl.run():
poller = ovs.poller.Poller()
idl.wait(poller)
poller.block()
idl.close()
print("%03d: done" % step)
+
def usage():
- print """\
+ print("""\
%(program_name)s: test utility for Open vSwitch database Python bindings
usage: %(program_name)s [OPTIONS] COMMAND ARG...
parse table NAME with info OBJECT
parse-schema JSON
parse JSON as an OVSDB schema, and re-serialize
-idl SERVER [TRANSACTION...]
- connect to SERVER and dump the contents of the database
- as seen initially by the IDL implementation and after
- executing each TRANSACTION. (Each TRANSACTION must modify
+idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
+ connect to SERVER (which has the specified SCHEMA) and dump the
+ contents of the database as seen initially by the IDL implementation
+ and after executing each TRANSACTION. (Each TRANSACTION must modify
the database or this command will hang.)
+ By default, all columns of all tables are monitored. The "?" option
+ can be used to monitor specific Table:Column(s). The table and their
+ columns are listed as a string of the form starting with "?":
+ ?<table-name>:<column-name>,<column-name>,...
+ e.g.:
+ ?simple:b - Monitor column "b" in table "simple"
+ Entries for multiple tables are seperated by "?":
+ ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
+ e.g.:
+ ?simple:b?link1:i,k - Monitor column "b" in table "simple",
+ and column "i", "k" in table "link1"
+ Readonly columns: Suffixing a "!" after a column indicates that the
+ column is to be registered "readonly".
+ e.g.:
+ ?simple:i,b! - Register interest in column "i" (monitoring) and
+ column "b" (readonly).
+
The following options are also available:
-t, --timeout=SECS give up after SECS seconds
-h, --help display this help message\
-""" % {'program_name': ovs.util.PROGRAM_NAME}
+""" % {'program_name': ovs.util.PROGRAM_NAME})
sys.exit(0)
+
def main(argv):
try:
options, args = getopt.gnu_getopt(argv[1:], 't:h',
['timeout',
'help'])
- except getopt.GetoptError, geo:
+ except getopt.GetoptError as geo:
sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
sys.exit(1)
else:
sys.exit(0)
- optKeys = [key for key, value in options]
-
if not args:
sys.stderr.write("%s: missing command argument "
"(use --help for help)\n" % ovs.util.PROGRAM_NAME)
"parse-column": (do_parse_column, 2),
"parse-table": (do_parse_table, (2, 3)),
"parse-schema": (do_parse_schema, 1),
- "idl": (do_idl, (1,))}
+ "idl": (do_idl, (2,))}
command_name = args[0]
args = args[1:]
- if not command_name in commands:
+ if command_name not in commands:
sys.stderr.write("%s: unknown command \"%s\" "
"(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
command_name))
func(*args)
+
if __name__ == '__main__':
try:
main(sys.argv)
- except error.Error, e:
+ except error.Error as e:
sys.stderr.write("%s\n" % e)
sys.exit(1)