]> git.proxmox.com Git - ovs.git/blob - tests/test-ovsdb.py
ovs.ovsuuid: Get rid of ovs.ovsuuid.UUID class.
[ovs.git] / tests / test-ovsdb.py
1 # Copyright (c) 2009, 2010, 2011 Nicira Networks
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
15 import codecs
16 import getopt
17 import re
18 import os
19 import signal
20 import sys
21
22 from ovs.db import error
23 import ovs.db.idl
24 import ovs.db.schema
25 from ovs.db import data
26 from ovs.db import types
27 import ovs.ovsuuid
28 import ovs.poller
29 import ovs.util
30
31 def unbox_json(json):
32 if type(json) == list and len(json) == 1:
33 return json[0]
34 else:
35 return json
36
37 def 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
51 def 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
77 def 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
82 def 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
87 def 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
92 def 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:
101 print unicode(e)
102
103 def 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
111 def 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
119 def 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
124 def do_parse_table(name, table_string, default_is_root_string='false'):
125 default_is_root = default_is_root_string == 'true'
126 table_json = unbox_json(ovs.json.from_string(table_string))
127 table = ovs.db.schema.TableSchema.from_json(table_json, name)
128 print ovs.json.to_string(table.to_json(default_is_root), sort_keys=True)
129
130 def 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
134 def 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
139 def 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
151 def 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
165 def parse_uuids(json, symtab):
166 if type(json) in [str, unicode] and ovs.ovsuuid.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
177 def 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
250 def usage():
251 print """\
252 %(program_name)s: test utility for Open vSwitch database Python bindings
253 usage: %(program_name)s [OPTIONS] COMMAND ARG...
254
255 The following commands are supported:
256 default-atoms
257 test ovsdb_atom_default()
258 default-data
259 test ovsdb_datum_default()
260 parse-atomic-type TYPE
261 parse TYPE as OVSDB atomic type, and re-serialize
262 parse-base-type TYPE
263 parse TYPE as OVSDB base type, and re-serialize
264 parse-type JSON
265 parse JSON as OVSDB type, and re-serialize
266 parse-atoms TYPE ATOM...
267 parse JSON ATOMs as atoms of TYPE, and re-serialize
268 parse-atom-strings TYPE ATOM...
269 parse string ATOMs as atoms of given TYPE, and re-serialize
270 sort-atoms TYPE ATOM...
271 print JSON ATOMs in sorted order
272 parse-data TYPE DATUM...
273 parse JSON DATUMs as data of given TYPE, and re-serialize
274 parse-column NAME OBJECT
275 parse column NAME with info OBJECT, and re-serialize
276 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
277 parse table NAME with info OBJECT
278 parse-schema JSON
279 parse JSON as an OVSDB schema, and re-serialize
280 idl 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
286 The 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
292 def main(argv):
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),
332 "parse-table": (do_parse_table, (2, 3)),
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
364 if __name__ == '__main__':
365 try:
366 main(sys.argv)
367 except error.Error, e:
368 sys.stderr.write("%s\n" % e)
369 sys.exit(1)