]>
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.
15 from __future__
import print_function
24 from ovs
.db
import error
27 from ovs
.db
import data
35 if type(json
) == list and len(json
) == 1:
41 def do_default_atoms():
42 for type_
in ovs
.db
.types
.ATOMIC_TYPES
:
43 if type_
== ovs
.db
.types
.VoidType
:
46 sys
.stdout
.write("%s: " % type_
.to_string())
48 atom
= data
.Atom
.default(type_
)
49 if atom
!= data
.Atom
.default(type_
):
50 sys
.stdout
.write("wrong\n")
53 sys
.stdout
.write("OK\n")
56 def do_default_data():
59 for key
in ovs
.db
.types
.ATOMIC_TYPES
:
60 if key
== ovs
.db
.types
.VoidType
:
62 for value
in ovs
.db
.types
.ATOMIC_TYPES
:
63 if value
== ovs
.db
.types
.VoidType
:
66 valueBase
= ovs
.db
.types
.BaseType(value
)
67 type_
= ovs
.db
.types
.Type(ovs
.db
.types
.BaseType(key
),
69 assert type_
.is_valid()
71 sys
.stdout
.write("key %s, value %s, n_min %d: "
72 % (key
.to_string(), value
.to_string(), n_min
))
74 datum
= data
.Datum
.default(type_
)
75 if datum
!= data
.Datum
.default(type_
):
76 sys
.stdout
.write("wrong\n")
79 sys
.stdout
.write("OK\n")
84 def do_parse_atomic_type(type_string
):
85 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
86 atomic_type
= ovs
.db
.types
.AtomicType
.from_json(type_json
)
87 print(ovs
.json
.to_string(atomic_type
.to_json(), sort_keys
=True))
90 def do_parse_base_type(type_string
):
91 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
92 base_type
= ovs
.db
.types
.BaseType
.from_json(type_json
)
93 print(ovs
.json
.to_string(base_type
.to_json(), sort_keys
=True))
96 def do_parse_type(type_string
):
97 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
98 type_
= ovs
.db
.types
.Type
.from_json(type_json
)
99 print(ovs
.json
.to_string(type_
.to_json(), sort_keys
=True))
102 def do_parse_atoms(type_string
, *atom_strings
):
103 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
104 base
= ovs
.db
.types
.BaseType
.from_json(type_json
)
105 for atom_string
in atom_strings
:
106 atom_json
= unbox_json(ovs
.json
.from_string(atom_string
))
108 atom
= data
.Atom
.from_json(base
, atom_json
)
109 print(ovs
.json
.to_string(atom
.to_json()))
110 except error
.Error
as e
:
111 print(e
.args
[0].encode("utf8"))
114 def do_parse_data(type_string
, *data_strings
):
115 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
116 type_
= ovs
.db
.types
.Type
.from_json(type_json
)
117 for datum_string
in data_strings
:
118 datum_json
= unbox_json(ovs
.json
.from_string(datum_string
))
119 datum
= data
.Datum
.from_json(type_
, datum_json
)
120 print(ovs
.json
.to_string(datum
.to_json()))
123 def do_sort_atoms(type_string
, atom_strings
):
124 type_json
= unbox_json(ovs
.json
.from_string(type_string
))
125 base
= ovs
.db
.types
.BaseType
.from_json(type_json
)
126 atoms
= [data
.Atom
.from_json(base
, atom_json
)
127 for atom_json
in unbox_json(ovs
.json
.from_string(atom_strings
))]
128 print(ovs
.json
.to_string([data
.Atom
.to_json(atom
)
129 for atom
in sorted(atoms
)]))
132 def do_parse_column(name
, column_string
):
133 column_json
= unbox_json(ovs
.json
.from_string(column_string
))
134 column
= ovs
.db
.schema
.ColumnSchema
.from_json(column_json
, name
)
135 print(ovs
.json
.to_string(column
.to_json(), sort_keys
=True))
138 def do_parse_table(name
, table_string
, default_is_root_string
='false'):
139 default_is_root
= default_is_root_string
== 'true'
140 table_json
= unbox_json(ovs
.json
.from_string(table_string
))
141 table
= ovs
.db
.schema
.TableSchema
.from_json(table_json
, name
)
142 print(ovs
.json
.to_string(table
.to_json(default_is_root
), sort_keys
=True))
145 def do_parse_schema(schema_string
):
146 schema_json
= unbox_json(ovs
.json
.from_string(schema_string
))
147 schema
= ovs
.db
.schema
.DbSchema
.from_json(schema_json
)
148 print(ovs
.json
.to_string(schema
.to_json(), sort_keys
=True))
151 def print_idl(idl
, step
):
153 if "simple" in idl
.tables
:
154 simple_columns
= ["i", "r", "b", "s", "u", "ia",
155 "ra", "ba", "sa", "ua", "uuid"]
156 simple
= idl
.tables
["simple"].rows
157 for row
in simple
.itervalues():
159 for column
in simple_columns
:
160 if hasattr(row
, column
) and not (type(getattr(row
, column
))
161 is ovs
.db
.data
.Atom
):
162 s
+= " %s=%s" % (column
, getattr(row
, column
))
163 s
= re
.sub('""|,|u?\'', "", s
)
164 s
= re
.sub('UUID\(([^)]+)\)', r
'\1', s
)
165 s
= re
.sub('False', 'false', s
)
166 s
= re
.sub('True', 'true', s
)
167 s
= re
.sub(r
'(ba)=([^[][^ ]*) ', r
'\1=[\2] ', s
)
171 if "link1" in idl
.tables
:
172 l1
= idl
.tables
["link1"].rows
173 for row
in l1
.itervalues():
174 s
= ["%03d: i=%s k=" % (step
, row
.i
)]
175 if hasattr(row
, "k") and row
.k
:
176 s
.append(str(row
.k
.i
))
177 if hasattr(row
, "ka"):
179 s
.append(' '.join(sorted(str(ka
.i
) for ka
in row
.ka
)))
181 if hasattr(row
, "l2") and row
.l2
:
182 s
.append(str(row
.l2
[0].i
))
183 if hasattr(row
, "uuid"):
184 s
.append(" uuid=%s" % row
.uuid
)
188 if "link2" in idl
.tables
:
189 l2
= idl
.tables
["link2"].rows
190 for row
in l2
.itervalues():
192 s
.append(" i=%s l1=" % row
.i
)
193 if hasattr(row
, "l1") and row
.l1
:
194 s
.append(str(row
.l1
[0].i
))
195 if hasattr(row
, "uuid"):
196 s
.append(" uuid=%s" % row
.uuid
)
201 print("%03d: empty" % step
)
205 def substitute_uuids(json
, symtab
):
206 if type(json
) in [str, unicode]:
207 symbol
= symtab
.get(json
)
210 elif type(json
) == list:
211 return [substitute_uuids(element
, symtab
) for element
in json
]
212 elif type(json
) == dict:
214 for key
, value
in json
.iteritems():
215 d
[key
] = substitute_uuids(value
, symtab
)
220 def parse_uuids(json
, symtab
):
221 if type(json
) in [str, unicode] and ovs
.ovsuuid
.is_valid_string(json
):
222 name
= "#%d#" % len(symtab
)
223 sys
.stderr
.write("%s = %s\n" % (name
, json
))
225 elif type(json
) == list:
227 parse_uuids(element
, symtab
)
228 elif type(json
) == dict:
229 for value
in json
.itervalues():
230 parse_uuids(value
, symtab
)
233 def idltest_find_simple(idl
, i
):
234 for row
in idl
.tables
["simple"].rows
.itervalues():
240 def idl_set(idl
, commands
, step
):
241 txn
= ovs
.db
.idl
.Transaction(idl
)
245 for command
in commands
.split(','):
246 words
= command
.split()
250 if name
== "notifytest":
253 old_notify
= idl
.notify
255 def notify(event
, row
, updates
=None):
257 upcol
= updates
._data
.keys()[0]
260 events
.append("%s|%s|%s" % (event
, row
.i
, upcol
))
261 idl
.notify
= old_notify
267 sys
.stderr
.write('"set" command requires 3 arguments\n')
270 s
= idltest_find_simple(idl
, int(args
[0]))
272 sys
.stderr
.write('"set" command asks for nonexistent i=%d\n'
281 s
.u
= uuid
.UUID(args
[2])
285 sys
.stderr
.write('"set" comamnd asks for unknown column %s\n'
288 elif name
== "insert":
290 sys
.stderr
.write('"set" command requires 1 argument\n')
293 s
= txn
.insert(idl
.tables
["simple"])
295 elif name
== "delete":
297 sys
.stderr
.write('"delete" command requires 1 argument\n')
300 s
= idltest_find_simple(idl
, int(args
[0]))
302 sys
.stderr
.write('"delete" command asks for nonexistent i=%d\n'
306 elif name
== "verify":
308 sys
.stderr
.write('"verify" command requires 2 arguments\n')
311 s
= idltest_find_simple(idl
, int(args
[0]))
313 sys
.stderr
.write('"verify" command asks for nonexistent i=%d\n'
317 if args
[1] in ("i", "b", "s", "u", "r"):
320 sys
.stderr
.write('"verify" command asks for unknown column '
323 elif name
== "fetch":
325 sys
.stderr
.write('"fetch" command requires 2 argument\n')
328 row
= idltest_find_simple(idl
, int(args
[0]))
330 sys
.stderr
.write('"fetch" command asks for nonexistent i=%d\n'
336 fetch_cmds
.append([row
, column
])
337 elif name
== "increment":
339 sys
.stderr
.write('"increment" command requires 1 argument\n')
342 s
= idltest_find_simple(idl
, int(args
[0]))
344 sys
.stderr
.write('"set" command asks for nonexistent i=%d\n'
350 elif name
== "abort":
353 elif name
== "destroy":
354 print("%03d: destroy" % step
)
358 elif name
== "linktest":
359 l1_0
= txn
.insert(idl
.tables
["link1"])
363 l1_1
= txn
.insert(idl
.tables
["link1"])
366 l1_1
.ka
= [l1_0
, l1_1
]
367 elif name
== 'getattrtest':
368 l1
= txn
.insert(idl
.tables
["link1"])
369 i
= getattr(l1
, 'i', 1)
372 i
= getattr(l1
, 'i', 1)
376 sys
.stderr
.write("unknown command %s\n" % name
)
379 status
= txn
.commit_block()
380 sys
.stdout
.write("%03d: commit, status=%s"
381 % (step
, ovs
.db
.idl
.Transaction
.status_to_string(status
)))
382 if increment
and status
== ovs
.db
.idl
.Transaction
.SUCCESS
:
383 sys
.stdout
.write(", increment=%d" % txn
.get_increment_new_value())
385 # Event notifications from operations in a single transaction are
386 # not in a gauranteed order due to update messages being dicts
387 sys
.stdout
.write(", events=" + ", ".join(sorted(events
)))
388 sys
.stdout
.write("\n")
392 def do_idl(schema_file
, remote
, *commands
):
393 schema_helper
= ovs
.db
.idl
.SchemaHelper(schema_file
)
394 if commands
and commands
[0].startswith("?"):
396 for x
in commands
[0][1:].split("?"):
398 table
, columns
= x
.split(":")
399 columns
= columns
.split(",")
400 for index
, column
in enumerate(columns
):
401 if column
[-1] == '!':
402 columns
[index
] = columns
[index
][:-1]
403 readonly
.append(columns
[index
])
404 schema_helper
.register_columns(table
, columns
, readonly
)
405 commands
= commands
[1:]
407 schema_helper
.register_all()
408 idl
= ovs
.db
.idl
.Idl(remote
, schema_helper
)
411 error
, stream
= ovs
.stream
.Stream
.open_block(
412 ovs
.stream
.Stream
.open(remote
))
414 sys
.stderr
.write("failed to connect to \"%s\"" % remote
)
416 rpc
= ovs
.jsonrpc
.Connection(stream
)
423 for command
in commands
:
424 if command
.startswith("+"):
425 # The previous transaction didn't change anything.
426 command
= command
[1:]
429 while idl
.change_seqno
== seqno
and not idl
.run():
432 poller
= ovs
.poller
.Poller()
440 seqno
= idl
.change_seqno
442 if command
== "reconnect":
443 print("%03d: reconnect" % step
)
446 idl
.force_reconnect()
447 elif not command
.startswith("["):
448 idl_set(idl
, command
, step
)
451 json
= ovs
.json
.from_string(command
)
452 if type(json
) in [str, unicode]:
453 sys
.stderr
.write("\"%s\": %s\n" % (command
, json
))
455 json
= substitute_uuids(json
, symtab
)
456 request
= ovs
.jsonrpc
.Message
.create_request("transact", json
)
457 error
, reply
= rpc
.transact_block(request
)
459 sys
.stderr
.write("jsonrpc transaction failed: %s"
460 % os
.strerror(error
))
462 elif reply
.error
is not None:
463 sys
.stderr
.write("jsonrpc transaction failed: %s"
467 sys
.stdout
.write("%03d: " % step
)
470 if reply
.result
is not None:
471 parse_uuids(reply
.result
, symtab
)
473 sys
.stdout
.write("%s\n" % ovs
.json
.to_string(reply
.to_json()))
478 while idl
.change_seqno
== seqno
and not idl
.run():
479 poller
= ovs
.poller
.Poller()
485 print("%03d: done" % step
)
490 %(program_name)s: test utility for Open vSwitch database Python bindings
491 usage: %(program_name)s [OPTIONS] COMMAND ARG...
493 The following commands are supported:
495 test ovsdb_atom_default()
497 test ovsdb_datum_default()
498 parse-atomic-type TYPE
499 parse TYPE as OVSDB atomic type, and re-serialize
501 parse TYPE as OVSDB base type, and re-serialize
503 parse JSON as OVSDB type, and re-serialize
504 parse-atoms TYPE ATOM...
505 parse JSON ATOMs as atoms of TYPE, and re-serialize
506 parse-atom-strings TYPE ATOM...
507 parse string ATOMs as atoms of given TYPE, and re-serialize
508 sort-atoms TYPE ATOM...
509 print JSON ATOMs in sorted order
510 parse-data TYPE DATUM...
511 parse JSON DATUMs as data of given TYPE, and re-serialize
512 parse-column NAME OBJECT
513 parse column NAME with info OBJECT, and re-serialize
514 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
515 parse table NAME with info OBJECT
517 parse JSON as an OVSDB schema, and re-serialize
518 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
519 connect to SERVER (which has the specified SCHEMA) and dump the
520 contents of the database as seen initially by the IDL implementation
521 and after executing each TRANSACTION. (Each TRANSACTION must modify
522 the database or this command will hang.)
523 By default, all columns of all tables are monitored. The "?" option
524 can be used to monitor specific Table:Column(s). The table and their
525 columns are listed as a string of the form starting with "?":
526 ?<table-name>:<column-name>,<column-name>,...
528 ?simple:b - Monitor column "b" in table "simple"
529 Entries for multiple tables are seperated by "?":
530 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
532 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
533 and column "i", "k" in table "link1"
534 Readonly columns: Suffixing a "!" after a column indicates that the
535 column is to be registered "readonly".
537 ?simple:i,b! - Register interest in column "i" (monitoring) and
538 column "b" (readonly).
541 The following options are also available:
542 -t, --timeout=SECS give up after SECS seconds
543 -h, --help display this help message\
544 """ % {'program_name': ovs
.util
.PROGRAM_NAME
})
550 options
, args
= getopt
.gnu_getopt(argv
[1:], 't:h',
553 except getopt
.GetoptError
as geo
:
554 sys
.stderr
.write("%s: %s\n" % (ovs
.util
.PROGRAM_NAME
, geo
.msg
))
557 for key
, value
in options
:
558 if key
in ['-h', '--help']:
560 elif key
in ['-t', '--timeout']:
566 raise error
.Error("value %s on -t or --timeout is not at "
568 signal
.alarm(timeout
)
573 sys
.stderr
.write("%s: missing command argument "
574 "(use --help for help)\n" % ovs
.util
.PROGRAM_NAME
)
577 commands
= {"default-atoms": (do_default_atoms
, 0),
578 "default-data": (do_default_data
, 0),
579 "parse-atomic-type": (do_parse_atomic_type
, 1),
580 "parse-base-type": (do_parse_base_type
, 1),
581 "parse-type": (do_parse_type
, 1),
582 "parse-atoms": (do_parse_atoms
, (2,)),
583 "parse-data": (do_parse_data
, (2,)),
584 "sort-atoms": (do_sort_atoms
, 2),
585 "parse-column": (do_parse_column
, 2),
586 "parse-table": (do_parse_table
, (2, 3)),
587 "parse-schema": (do_parse_schema
, 1),
588 "idl": (do_idl
, (2,))}
590 command_name
= args
[0]
592 if command_name
not in commands
:
593 sys
.stderr
.write("%s: unknown command \"%s\" "
594 "(use --help for help)\n" % (ovs
.util
.PROGRAM_NAME
,
598 func
, n_args
= commands
[command_name
]
599 if type(n_args
) == tuple:
600 if len(args
) < n_args
[0]:
601 sys
.stderr
.write("%s: \"%s\" requires at least %d arguments but "
603 % (ovs
.util
.PROGRAM_NAME
, command_name
,
606 elif type(n_args
) == int:
607 if len(args
) != n_args
:
608 sys
.stderr
.write("%s: \"%s\" requires %d arguments but %d "
610 % (ovs
.util
.PROGRAM_NAME
, command_name
,
619 if __name__
== '__main__':
622 except error
.Error
as e
:
623 sys
.stderr
.write("%s\n" % e
)