]> git.proxmox.com Git - mirror_ovs.git/blame - tests/test-ovsdb.py
ovs-ctl: Log messages about database upgrade process.
[mirror_ovs.git] / tests / test-ovsdb.py
CommitLineData
c5f341ab 1# Copyright (c) 2009, 2010, 2011 Nicira Networks
99155935
BP
2#
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:
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
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.
14
15import codecs
16import getopt
17import re
18import os
19import signal
20import sys
21
22from ovs.db import error
23import ovs.db.idl
24import ovs.db.schema
25from ovs.db import data
26from ovs.db import types
27import ovs.ovsuuid
28import ovs.poller
29import ovs.util
30
31def unbox_json(json):
32 if type(json) == list and len(json) == 1:
33 return json[0]
34 else:
35 return json
36
37def do_default_atoms():
38 for type in types.ATOMIC_TYPES:
39 if type == types.VoidType:
40 continue
41
42 sys.stdout.write("%s: " % type.to_string())
43
44 atom = data.Atom.default(type)
45 if atom != data.Atom.default(type):
46 sys.stdout.write("wrong\n")
47 sys.exit(1)
48
49 sys.stdout.write("OK\n")
50
51def do_default_data():
52 any_errors = False
53 for n_min in 0, 1:
54 for key in types.ATOMIC_TYPES:
55 if key == types.VoidType:
56 continue
57 for value in types.ATOMIC_TYPES:
58 if value == types.VoidType:
59 valueBase = None
60 else:
61 valueBase = types.BaseType(value)
62 type = types.Type(types.BaseType(key), valueBase, n_min, 1)
63 assert type.is_valid()
64
65 sys.stdout.write("key %s, value %s, n_min %d: "
66 % (key.to_string(), value.to_string(), n_min))
67
68 datum = data.Datum.default(type)
69 if datum != data.Datum.default(type):
70 sys.stdout.write("wrong\n")
71 any_errors = True
72 else:
73 sys.stdout.write("OK\n")
74 if any_errors:
75 sys.exit(1)
76
77def do_parse_atomic_type(type_string):
78 type_json = unbox_json(ovs.json.from_string(type_string))
79 atomic_type = types.AtomicType.from_json(type_json)
80 print ovs.json.to_string(atomic_type.to_json(), sort_keys=True)
81
82def do_parse_base_type(type_string):
83 type_json = unbox_json(ovs.json.from_string(type_string))
84 base_type = types.BaseType.from_json(type_json)
85 print ovs.json.to_string(base_type.to_json(), sort_keys=True)
86
87def do_parse_type(type_string):
88 type_json = unbox_json(ovs.json.from_string(type_string))
89 type = types.Type.from_json(type_json)
90 print ovs.json.to_string(type.to_json(), sort_keys=True)
91
92def do_parse_atoms(type_string, *atom_strings):
93 type_json = unbox_json(ovs.json.from_string(type_string))
94 base = types.BaseType.from_json(type_json)
95 for atom_string in atom_strings:
96 atom_json = unbox_json(ovs.json.from_string(atom_string))
97 try:
98 atom = data.Atom.from_json(base, atom_json)
99 print ovs.json.to_string(atom.to_json())
100 except error.Error, e:
be44585c 101 print unicode(e)
99155935
BP
102
103def do_parse_data(type_string, *data_strings):
104 type_json = unbox_json(ovs.json.from_string(type_string))
105 type = types.Type.from_json(type_json)
106 for datum_string in data_strings:
107 datum_json = unbox_json(ovs.json.from_string(datum_string))
108 datum = data.Datum.from_json(type, datum_json)
109 print ovs.json.to_string(datum.to_json())
110
111def do_sort_atoms(type_string, atom_strings):
112 type_json = unbox_json(ovs.json.from_string(type_string))
113 base = types.BaseType.from_json(type_json)
114 atoms = [data.Atom.from_json(base, atom_json)
115 for atom_json in unbox_json(ovs.json.from_string(atom_strings))]
116 print ovs.json.to_string([data.Atom.to_json(atom)
117 for atom in sorted(atoms)])
118
119def do_parse_column(name, column_string):
120 column_json = unbox_json(ovs.json.from_string(column_string))
121 column = ovs.db.schema.ColumnSchema.from_json(column_json, name)
122 print ovs.json.to_string(column.to_json(), sort_keys=True)
123
c5f341ab
BP
124def do_parse_table(name, table_string, default_is_root_string='false'):
125 default_is_root = default_is_root_string == 'true'
99155935
BP
126 table_json = unbox_json(ovs.json.from_string(table_string))
127 table = ovs.db.schema.TableSchema.from_json(table_json, name)
c5f341ab 128 print ovs.json.to_string(table.to_json(default_is_root), sort_keys=True)
99155935
BP
129
130def do_parse_rows(table_string, *rows):
131 table_json = unbox_json(ovs.json.from_string(table_string))
132 table = ovs.db.schema.TableSchema.from_json(table_json, name)
133
134def do_parse_schema(schema_string):
135 schema_json = unbox_json(ovs.json.from_string(schema_string))
136 schema = ovs.db.schema.DbSchema.from_json(schema_json)
137 print ovs.json.to_string(schema.to_json(), sort_keys=True)
138
139def print_idl(idl, step):
140 n = 0
141 for uuid, row in idl.data["simple"].iteritems():
142 s = ("%03d: i=%s r=%s b=%s s=%s u=%s "
143 "ia=%s ra=%s ba=%s sa=%s ua=%s uuid=%s"
144 % (step, row.i, row.r, row.b, row.s, row.u,
145 row.ia, row.ra, row.ba, row.sa, row.ua, uuid))
146 print(re.sub('""|,', "", s))
147 n += 1
148 if not n:
149 print("%03d: empty" % step)
150
151def substitute_uuids(json, symtab):
152 if type(json) in [str, unicode]:
153 symbol = symtab.get(json)
154 if symbol:
155 return str(symbol)
156 elif type(json) == list:
157 return [substitute_uuids(element, symtab) for element in json]
158 elif type(json) == dict:
159 d = {}
160 for key, value in json.iteritems():
161 d[key] = substitute_uuids(value, symtab)
162 return d
163 return json
164
165def parse_uuids(json, symtab):
166 if type(json) in [str, unicode] and ovs.ovsuuid.UUID.is_valid_string(json):
167 name = "#%d#" % len(symtab)
168 sys.stderr.write("%s = %s\n" % (name, json))
169 symtab[name] = json
170 elif type(json) == list:
171 for element in json:
172 parse_uuids(element, symtab)
173 elif type(json) == dict:
174 for value in json.itervalues():
175 parse_uuids(value, symtab)
176
177def do_idl(remote, *commands):
178 idl = ovs.db.idl.Idl(remote, "idltest")
179
180 if commands:
181 error, stream = ovs.stream.Stream.open_block(
182 ovs.stream.Stream.open(remote))
183 if error:
184 sys.stderr.write("failed to connect to \"%s\"" % remote)
185 sys.exit(1)
186 rpc = ovs.jsonrpc.Connection(stream)
187 else:
188 rpc = None
189
190 symtab = {}
191 seqno = 0
192 step = 0
193 for command in commands:
194 if command.startswith("+"):
195 # The previous transaction didn't change anything.
196 command = command[1:]
197 else:
198 # Wait for update.
199 while idl.get_seqno() == seqno and not idl.run():
200 rpc.run()
201
202 poller = ovs.poller.Poller()
203 idl.wait(poller)
204 rpc.wait(poller)
205 poller.block()
206
207 print_idl(idl, step)
208 step += 1
209
210 seqno = idl.get_seqno()
211
212 if command == "reconnect":
213 print("%03d: reconnect" % step)
214 step += 1
215 idl.force_reconnect()
216 elif not command.startswith("["):
217 idl_set(idl, command, step)
218 step += 1
219 else:
220 json = ovs.json.from_string(command)
221 if type(json) in [str, unicode]:
222 sys.stderr.write("\"%s\": %s\n" % (command, json))
223 sys.exit(1)
224 json = substitute_uuids(json, symtab)
225 request = ovs.jsonrpc.Message.create_request("transact", json)
226 error, reply = rpc.transact_block(request)
227 if error:
228 sys.stderr.write("jsonrpc transaction failed: %s"
229 % os.strerror(error))
230 sys.exit(1)
231 sys.stdout.write("%03d: " % step)
232 sys.stdout.flush()
233 step += 1
234 if reply.result is not None:
235 parse_uuids(reply.result, symtab)
236 reply.id = None
237 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
238
239 if rpc:
240 rpc.close()
241 while idl.get_seqno() == seqno and not idl.run():
242 poller = ovs.poller.Poller()
243 idl.wait(poller)
244 poller.block()
245 print_idl(idl, step)
246 step += 1
247 idl.close()
248 print("%03d: done" % step)
249
250def usage():
251 print """\
252%(program_name)s: test utility for Open vSwitch database Python bindings
253usage: %(program_name)s [OPTIONS] COMMAND ARG...
254
255The following commands are supported:
256default-atoms
257 test ovsdb_atom_default()
258default-data
259 test ovsdb_datum_default()
260parse-atomic-type TYPE
261 parse TYPE as OVSDB atomic type, and re-serialize
262parse-base-type TYPE
263 parse TYPE as OVSDB base type, and re-serialize
264parse-type JSON
265 parse JSON as OVSDB type, and re-serialize
266parse-atoms TYPE ATOM...
267 parse JSON ATOMs as atoms of TYPE, and re-serialize
268parse-atom-strings TYPE ATOM...
269 parse string ATOMs as atoms of given TYPE, and re-serialize
270sort-atoms TYPE ATOM...
271 print JSON ATOMs in sorted order
272parse-data TYPE DATUM...
273 parse JSON DATUMs as data of given TYPE, and re-serialize
274parse-column NAME OBJECT
275 parse column NAME with info OBJECT, and re-serialize
c5f341ab 276parse-table NAME OBJECT [DEFAULT-IS-ROOT]
99155935
BP
277 parse table NAME with info OBJECT
278parse-schema JSON
279 parse JSON as an OVSDB schema, and re-serialize
280idl SERVER [TRANSACTION...]
281 connect to SERVER and dump the contents of the database
282 as seen initially by the IDL implementation and after
283 executing each TRANSACTION. (Each TRANSACTION must modify
284 the database or this command will hang.)
285
286The following options are also available:
287 -t, --timeout=SECS give up after SECS seconds
288 -h, --help display this help message\
289""" % {'program_name': ovs.util.PROGRAM_NAME}
290 sys.exit(0)
291
292def main(argv):
99155935
BP
293 try:
294 options, args = getopt.gnu_getopt(argv[1:], 't:h',
295 ['timeout',
296 'help'])
297 except getopt.GetoptError, geo:
298 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
299 sys.exit(1)
300
301 for key, value in options:
302 if key in ['-h', '--help']:
303 usage()
304 elif key in ['-t', '--timeout']:
305 try:
306 timeout = int(value)
307 if timeout < 1:
308 raise TypeError
309 except TypeError:
310 raise error.Error("value %s on -t or --timeout is not at "
311 "least 1" % value)
312 signal.alarm(timeout)
313 else:
314 sys.exit(0)
315
316 optKeys = [key for key, value in options]
317
318 if not args:
319 sys.stderr.write("%s: missing command argument "
320 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
321 sys.exit(1)
322
323 commands = {"default-atoms": (do_default_atoms, 0),
324 "default-data": (do_default_data, 0),
325 "parse-atomic-type": (do_parse_atomic_type, 1),
326 "parse-base-type": (do_parse_base_type, 1),
327 "parse-type": (do_parse_type, 1),
328 "parse-atoms": (do_parse_atoms, (2,)),
329 "parse-data": (do_parse_data, (2,)),
330 "sort-atoms": (do_sort_atoms, 2),
331 "parse-column": (do_parse_column, 2),
c5f341ab 332 "parse-table": (do_parse_table, (2, 3)),
99155935
BP
333 "parse-schema": (do_parse_schema, 1),
334 "idl": (do_idl, (1,))}
335
336 command_name = args[0]
337 args = args[1:]
338 if not command_name in commands:
339 sys.stderr.write("%s: unknown command \"%s\" "
340 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
341 command_name))
342 sys.exit(1)
343
344 func, n_args = commands[command_name]
345 if type(n_args) == tuple:
346 if len(args) < n_args[0]:
347 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
348 "only %d provided\n"
349 % (ovs.util.PROGRAM_NAME, command_name,
350 n_args, len(args)))
351 sys.exit(1)
352 elif type(n_args) == int:
353 if len(args) != n_args:
354 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
355 "provided\n"
356 % (ovs.util.PROGRAM_NAME, command_name,
357 n_args, len(args)))
358 sys.exit(1)
359 else:
360 assert False
361
362 func(*args)
363
364if __name__ == '__main__':
365 try:
366 main(sys.argv)
367 except error.Error, e:
368 sys.stderr.write("%s\n" % e)
369 sys.exit(1)