]>
git.proxmox.com Git - ovs.git/blob - tests/test-ovsdb.py
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
33 if type(json
) == list and len(json
) == 1:
39 def do_default_atoms():
40 for type_
in ovs
.db
.types
.ATOMIC_TYPES
:
41 if type_
== ovs
.db
.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 ovs
.db
.types
.ATOMIC_TYPES
:
58 if key
== ovs
.db
.types
.VoidType
:
60 for value
in ovs
.db
.types
.ATOMIC_TYPES
:
61 if value
== ovs
.db
.types
.VoidType
:
64 valueBase
= ovs
.db
.types
.BaseType(value
)
65 type_
= ovs
.db
.types
.Type(ovs
.db
.types
.BaseType(key
),
67 assert type_
.is_valid()
69 sys
.stdout
.write("key %s, value %s, n_min %d: "
70 % (key
.to_string(), value
.to_string(), n_min
))
72 datum
= data
.Datum
.default(type_
)
73 if datum
!= data
.Datum
.default(type_
):
74 sys
.stdout
.write("wrong\n")
77 sys
.stdout
.write("OK\n")
82 def do_parse_atomic_type(type_string
):
83 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
84 atomic_type
= ovs
.db
.types
.AtomicType
.from_json(type_json
)
85 print ovs
.json
.to_string(atomic_type
.to_json(), sort_keys
=True)
88 def do_parse_base_type(type_string
):
89 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
90 base_type
= ovs
.db
.types
.BaseType
.from_json(type_json
)
91 print ovs
.json
.to_string(base_type
.to_json(), sort_keys
=True)
94 def do_parse_type(type_string
):
95 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
96 type_
= ovs
.db
.types
.Type
.from_json(type_json
)
97 print ovs
.json
.to_string(type_
.to_json(), sort_keys
=True)
100 def do_parse_atoms(type_string
, *atom_strings
):
101 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
102 base
= ovs
.db
.types
.BaseType
.from_json(type_json
)
103 for atom_string
in atom_strings
:
104 atom_json
= unbox_json(ovs
.json
.from_string(atom_string
))
106 atom
= data
.Atom
.from_json(base
, atom_json
)
107 print ovs
.json
.to_string(atom
.to_json())
108 except error
.Error
as e
:
109 print e
.args
[0].encode("utf8")
112 def do_parse_data(type_string
, *data_strings
):
113 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
114 type_
= ovs
.db
.types
.Type
.from_json(type_json
)
115 for datum_string
in data_strings
:
116 datum_json
= unbox_json(ovs
.json
.from_string(datum_string
))
117 datum
= data
.Datum
.from_json(type_
, datum_json
)
118 print ovs
.json
.to_string(datum
.to_json())
121 def do_sort_atoms(type_string
, atom_strings
):
122 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
123 base
= ovs
.db
.types
.BaseType
.from_json(type_json
)
124 atoms
= [data
.Atom
.from_json(base
, atom_json
)
125 for atom_json
in unbox_json(ovs
.json
.from_string(atom_strings
))]
126 print ovs
.json
.to_string([data
.Atom
.to_json(atom
)
127 for atom
in sorted(atoms
)])
130 def do_parse_column(name
, column_string
):
131 column_json
= unbox_json(ovs
.json
.from_string(column_string
))
132 column
= ovs
.db
.schema
.ColumnSchema
.from_json(column_json
, name
)
133 print ovs
.json
.to_string(column
.to_json(), sort_keys
=True)
136 def do_parse_table(name
, table_string
, default_is_root_string
='false'):
137 default_is_root
= default_is_root_string
== 'true'
138 table_json
= unbox_json(ovs
.json
.from_string(table_string
))
139 table
= ovs
.db
.schema
.TableSchema
.from_json(table_json
, name
)
140 print ovs
.json
.to_string(table
.to_json(default_is_root
), sort_keys
=True)
143 def do_parse_schema(schema_string
):
144 schema_json
= unbox_json(ovs
.json
.from_string(schema_string
))
145 schema
= ovs
.db
.schema
.DbSchema
.from_json(schema_json
)
146 print ovs
.json
.to_string(schema
.to_json(), sort_keys
=True)
149 def print_idl(idl
, step
):
151 if "simple" in idl
.tables
:
152 simple_columns
= ["i", "r", "b", "s", "u", "ia",
153 "ra", "ba", "sa", "ua", "uuid"]
154 simple
= idl
.tables
["simple"].rows
155 for row
in simple
.itervalues():
157 for column
in simple_columns
:
158 if hasattr(row
, column
) and not (type(getattr(row
, column
))
159 is ovs
.db
.data
.Atom
):
160 s
+= " %s=%s" % (column
, getattr(row
, column
))
161 s
= re
.sub('""|,|u?\'', "", s
)
162 s
= re
.sub('UUID\(([^)]+)\)', r
'\1', s
)
163 s
= re
.sub('False', 'false', s
)
164 s
= re
.sub('True', 'true', s
)
165 s
= re
.sub(r
'(ba)=([^[][^ ]*) ', r
'\1=[\2] ', s
)
169 if "link1" in idl
.tables
:
170 l1
= idl
.tables
["link1"].rows
171 for row
in l1
.itervalues():
172 s
= ["%03d: i=%s k=" % (step
, row
.i
)]
173 if hasattr(row
, "k") and row
.k
:
174 s
.append(str(row
.k
.i
))
175 if hasattr(row
, "ka"):
177 s
.append(' '.join(sorted(str(ka
.i
) for ka
in row
.ka
)))
179 if hasattr(row
, "l2") and row
.l2
:
180 s
.append(str(row
.l2
[0].i
))
181 if hasattr(row
, "uuid"):
182 s
.append(" uuid=%s" % row
.uuid
)
186 if "link2" in idl
.tables
:
187 l2
= idl
.tables
["link2"].rows
188 for row
in l2
.itervalues():
190 s
.append(" i=%s l1=" % row
.i
)
191 if hasattr(row
, "l1") and row
.l1
:
192 s
.append(str(row
.l1
[0].i
))
193 if hasattr(row
, "uuid"):
194 s
.append(" uuid=%s" % row
.uuid
)
199 print("%03d: empty" % step
)
203 def substitute_uuids(json
, symtab
):
204 if type(json
) in [str, unicode]:
205 symbol
= symtab
.get(json
)
208 elif type(json
) == list:
209 return [substitute_uuids(element
, symtab
) for element
in json
]
210 elif type(json
) == dict:
212 for key
, value
in json
.iteritems():
213 d
[key
] = substitute_uuids(value
, symtab
)
218 def parse_uuids(json
, symtab
):
219 if type(json
) in [str, unicode] and ovs
.ovsuuid
.is_valid_string(json
):
220 name
= "#%d#" % len(symtab
)
221 sys
.stderr
.write("%s = %s\n" % (name
, json
))
223 elif type(json
) == list:
225 parse_uuids(element
, symtab
)
226 elif type(json
) == dict:
227 for value
in json
.itervalues():
228 parse_uuids(value
, symtab
)
231 def idltest_find_simple(idl
, i
):
232 for row
in idl
.tables
["simple"].rows
.itervalues():
238 def idl_set(idl
, commands
, step
):
239 txn
= ovs
.db
.idl
.Transaction(idl
)
243 for command
in commands
.split(','):
244 words
= command
.split()
248 if name
== "notifytest":
251 old_notify
= idl
.notify
253 def notify(event
, row
, updates
=None):
255 upcol
= updates
._data
.keys()[0]
258 events
.append("%s|%s|%s" % (event
, row
.i
, upcol
))
259 idl
.notify
= old_notify
265 sys
.stderr
.write('"set" command requires 3 arguments\n')
268 s
= idltest_find_simple(idl
, int(args
[0]))
270 sys
.stderr
.write('"set" command asks for nonexistent i=%d\n'
279 s
.u
= uuid
.UUID(args
[2])
283 sys
.stderr
.write('"set" comamnd asks for unknown column %s\n'
286 elif name
== "insert":
288 sys
.stderr
.write('"set" command requires 1 argument\n')
291 s
= txn
.insert(idl
.tables
["simple"])
293 elif name
== "delete":
295 sys
.stderr
.write('"delete" command requires 1 argument\n')
298 s
= idltest_find_simple(idl
, int(args
[0]))
300 sys
.stderr
.write('"delete" command asks for nonexistent i=%d\n'
304 elif name
== "verify":
306 sys
.stderr
.write('"verify" command requires 2 arguments\n')
309 s
= idltest_find_simple(idl
, int(args
[0]))
311 sys
.stderr
.write('"verify" command asks for nonexistent i=%d\n'
315 if args
[1] in ("i", "b", "s", "u", "r"):
318 sys
.stderr
.write('"verify" command asks for unknown column '
321 elif name
== "fetch":
323 sys
.stderr
.write('"fetch" command requires 2 argument\n')
326 row
= idltest_find_simple(idl
, int(args
[0]))
328 sys
.stderr
.write('"fetch" command asks for nonexistent i=%d\n'
334 fetch_cmds
.append([row
, column
])
335 elif name
== "increment":
337 sys
.stderr
.write('"increment" command requires 1 argument\n')
340 s
= idltest_find_simple(idl
, int(args
[0]))
342 sys
.stderr
.write('"set" command asks for nonexistent i=%d\n'
348 elif name
== "abort":
351 elif name
== "destroy":
352 print "%03d: destroy" % step
356 elif name
== "linktest":
357 l1_0
= txn
.insert(idl
.tables
["link1"])
361 l1_1
= txn
.insert(idl
.tables
["link1"])
364 l1_1
.ka
= [l1_0
, l1_1
]
365 elif name
== 'getattrtest':
366 l1
= txn
.insert(idl
.tables
["link1"])
367 i
= getattr(l1
, 'i', 1)
370 i
= getattr(l1
, 'i', 1)
374 sys
.stderr
.write("unknown command %s\n" % name
)
377 status
= txn
.commit_block()
378 sys
.stdout
.write("%03d: commit, status=%s"
379 % (step
, ovs
.db
.idl
.Transaction
.status_to_string(status
)))
380 if increment
and status
== ovs
.db
.idl
.Transaction
.SUCCESS
:
381 sys
.stdout
.write(", increment=%d" % txn
.get_increment_new_value())
383 # Event notifications from operations in a single transaction are
384 # not in a gauranteed order due to update messages being dicts
385 sys
.stdout
.write(", events=" + ", ".join(sorted(events
)))
386 sys
.stdout
.write("\n")
390 def do_idl(schema_file
, remote
, *commands
):
391 schema_helper
= ovs
.db
.idl
.SchemaHelper(schema_file
)
392 if commands
and commands
[0].startswith("?"):
394 for x
in commands
[0][1:].split("?"):
396 table
, columns
= x
.split(":")
397 columns
= columns
.split(",")
398 for index
, column
in enumerate(columns
):
399 if column
[-1] == '!':
400 columns
[index
] = columns
[index
][:-1]
401 readonly
.append(columns
[index
])
402 schema_helper
.register_columns(table
, columns
, readonly
)
403 commands
= commands
[1:]
405 schema_helper
.register_all()
406 idl
= ovs
.db
.idl
.Idl(remote
, schema_helper
)
409 error
, stream
= ovs
.stream
.Stream
.open_block(
410 ovs
.stream
.Stream
.open(remote
))
412 sys
.stderr
.write("failed to connect to \"%s\"" % remote
)
414 rpc
= ovs
.jsonrpc
.Connection(stream
)
421 for command
in commands
:
422 if command
.startswith("+"):
423 # The previous transaction didn't change anything.
424 command
= command
[1:]
427 while idl
.change_seqno
== seqno
and not idl
.run():
430 poller
= ovs
.poller
.Poller()
438 seqno
= idl
.change_seqno
440 if command
== "reconnect":
441 print("%03d: reconnect" % step
)
444 idl
.force_reconnect()
445 elif not command
.startswith("["):
446 idl_set(idl
, command
, step
)
449 json
= ovs
.json
.from_string(command
)
450 if type(json
) in [str, unicode]:
451 sys
.stderr
.write("\"%s\": %s\n" % (command
, json
))
453 json
= substitute_uuids(json
, symtab
)
454 request
= ovs
.jsonrpc
.Message
.create_request("transact", json
)
455 error
, reply
= rpc
.transact_block(request
)
457 sys
.stderr
.write("jsonrpc transaction failed: %s"
458 % os
.strerror(error
))
460 elif reply
.error
is not None:
461 sys
.stderr
.write("jsonrpc transaction failed: %s"
465 sys
.stdout
.write("%03d: " % step
)
468 if reply
.result
is not None:
469 parse_uuids(reply
.result
, symtab
)
471 sys
.stdout
.write("%s\n" % ovs
.json
.to_string(reply
.to_json()))
476 while idl
.change_seqno
== seqno
and not idl
.run():
477 poller
= ovs
.poller
.Poller()
483 print("%03d: done" % step
)
488 %(program_name)s: test utility for Open vSwitch database Python bindings
489 usage: %(program_name)s [OPTIONS] COMMAND ARG...
491 The following commands are supported:
493 test ovsdb_atom_default()
495 test ovsdb_datum_default()
496 parse-atomic-type TYPE
497 parse TYPE as OVSDB atomic type, and re-serialize
499 parse TYPE as OVSDB base type, and re-serialize
501 parse JSON as OVSDB type, and re-serialize
502 parse-atoms TYPE ATOM...
503 parse JSON ATOMs as atoms of TYPE, and re-serialize
504 parse-atom-strings TYPE ATOM...
505 parse string ATOMs as atoms of given TYPE, and re-serialize
506 sort-atoms TYPE ATOM...
507 print JSON ATOMs in sorted order
508 parse-data TYPE DATUM...
509 parse JSON DATUMs as data of given TYPE, and re-serialize
510 parse-column NAME OBJECT
511 parse column NAME with info OBJECT, and re-serialize
512 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
513 parse table NAME with info OBJECT
515 parse JSON as an OVSDB schema, and re-serialize
516 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
517 connect to SERVER (which has the specified SCHEMA) and dump the
518 contents of the database as seen initially by the IDL implementation
519 and after executing each TRANSACTION. (Each TRANSACTION must modify
520 the database or this command will hang.)
521 By default, all columns of all tables are monitored. The "?" option
522 can be used to monitor specific Table:Column(s). The table and their
523 columns are listed as a string of the form starting with "?":
524 ?<table-name>:<column-name>,<column-name>,...
526 ?simple:b - Monitor column "b" in table "simple"
527 Entries for multiple tables are seperated by "?":
528 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
530 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
531 and column "i", "k" in table "link1"
532 Readonly columns: Suffixing a "!" after a column indicates that the
533 column is to be registered "readonly".
535 ?simple:i,b! - Register interest in column "i" (monitoring) and
536 column "b" (readonly).
539 The following options are also available:
540 -t, --timeout=SECS give up after SECS seconds
541 -h, --help display this help message\
542 """ % {'program_name': ovs
.util
.PROGRAM_NAME
}
548 options
, args
= getopt
.gnu_getopt(argv
[1:], 't:h',
551 except getopt
.GetoptError
as geo
:
552 sys
.stderr
.write("%s: %s\n" % (ovs
.util
.PROGRAM_NAME
, geo
.msg
))
555 for key
, value
in options
:
556 if key
in ['-h', '--help']:
558 elif key
in ['-t', '--timeout']:
564 raise error
.Error("value %s on -t or --timeout is not at "
566 signal
.alarm(timeout
)
571 sys
.stderr
.write("%s: missing command argument "
572 "(use --help for help)\n" % ovs
.util
.PROGRAM_NAME
)
575 commands
= {"default-atoms": (do_default_atoms
, 0),
576 "default-data": (do_default_data
, 0),
577 "parse-atomic-type": (do_parse_atomic_type
, 1),
578 "parse-base-type": (do_parse_base_type
, 1),
579 "parse-type": (do_parse_type
, 1),
580 "parse-atoms": (do_parse_atoms
, (2,)),
581 "parse-data": (do_parse_data
, (2,)),
582 "sort-atoms": (do_sort_atoms
, 2),
583 "parse-column": (do_parse_column
, 2),
584 "parse-table": (do_parse_table
, (2, 3)),
585 "parse-schema": (do_parse_schema
, 1),
586 "idl": (do_idl
, (2,))}
588 command_name
= args
[0]
590 if command_name
not in commands
:
591 sys
.stderr
.write("%s: unknown command \"%s\" "
592 "(use --help for help)\n" % (ovs
.util
.PROGRAM_NAME
,
596 func
, n_args
= commands
[command_name
]
597 if type(n_args
) == tuple:
598 if len(args
) < n_args
[0]:
599 sys
.stderr
.write("%s: \"%s\" requires at least %d arguments but "
601 % (ovs
.util
.PROGRAM_NAME
, command_name
,
604 elif type(n_args
) == int:
605 if len(args
) != n_args
:
606 sys
.stderr
.write("%s: \"%s\" requires %d arguments but %d "
608 % (ovs
.util
.PROGRAM_NAME
, command_name
,
617 if __name__
== '__main__':
620 except error
.Error
as e
:
621 sys
.stderr
.write("%s\n" % e
)