]> git.proxmox.com Git - ovs.git/blame - tests/test-ovsdb.py
Remove dependency on python3-six
[ovs.git] / tests / test-ovsdb.py
CommitLineData
0164e367 1# Copyright (c) 2009, 2010, 2011, 2012, 2016 Nicira, Inc.
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
99155935 15import getopt
99155935 16import os
6c7050b5 17import re
99155935 18import sys
8cdf0349 19import uuid
99155935 20
99155935
BP
21import ovs.db.idl
22import ovs.db.schema
3c057118 23import ovs.db.types
99155935
BP
24import ovs.ovsuuid
25import ovs.poller
d90ed7d6 26import ovs.stream
99155935 27import ovs.util
244413ee 28import ovs.vlog
6c7050b5 29from ovs.db import data
30from ovs.db import error
36d51634 31from ovs.fatal_signal import signal_alarm
6c7050b5 32
244413ee
IM
33vlog = ovs.vlog.Vlog("test-ovsdb")
34vlog.set_levels_from_string("console:dbg")
35vlog.init(None)
36
26bb0f31 37
99155935
BP
38def unbox_json(json):
39 if type(json) == list and len(json) == 1:
40 return json[0]
41 else:
42 return json
43
26bb0f31 44
99155935 45def do_default_atoms():
3c057118
RB
46 for type_ in ovs.db.types.ATOMIC_TYPES:
47 if type_ == ovs.db.types.VoidType:
99155935
BP
48 continue
49
8cdf0349 50 sys.stdout.write("%s: " % type_.to_string())
99155935 51
8cdf0349
BP
52 atom = data.Atom.default(type_)
53 if atom != data.Atom.default(type_):
99155935
BP
54 sys.stdout.write("wrong\n")
55 sys.exit(1)
56
57 sys.stdout.write("OK\n")
58
26bb0f31 59
99155935
BP
60def do_default_data():
61 any_errors = False
62 for n_min in 0, 1:
3c057118
RB
63 for key in ovs.db.types.ATOMIC_TYPES:
64 if key == ovs.db.types.VoidType:
99155935 65 continue
3c057118
RB
66 for value in ovs.db.types.ATOMIC_TYPES:
67 if value == ovs.db.types.VoidType:
99155935
BP
68 valueBase = None
69 else:
3c057118
RB
70 valueBase = ovs.db.types.BaseType(value)
71 type_ = ovs.db.types.Type(ovs.db.types.BaseType(key),
72 valueBase, n_min, 1)
8cdf0349 73 assert type_.is_valid()
99155935
BP
74
75 sys.stdout.write("key %s, value %s, n_min %d: "
76 % (key.to_string(), value.to_string(), n_min))
77
8cdf0349
BP
78 datum = data.Datum.default(type_)
79 if datum != data.Datum.default(type_):
99155935
BP
80 sys.stdout.write("wrong\n")
81 any_errors = True
82 else:
83 sys.stdout.write("OK\n")
84 if any_errors:
85 sys.exit(1)
86
26bb0f31 87
99155935
BP
88def do_parse_atomic_type(type_string):
89 type_json = unbox_json(ovs.json.from_string(type_string))
3c057118 90 atomic_type = ovs.db.types.AtomicType.from_json(type_json)
8ea171ab 91 print(ovs.json.to_string(atomic_type.to_json(), sort_keys=True))
99155935 92
26bb0f31 93
99155935
BP
94def do_parse_base_type(type_string):
95 type_json = unbox_json(ovs.json.from_string(type_string))
3c057118 96 base_type = ovs.db.types.BaseType.from_json(type_json)
8ea171ab 97 print(ovs.json.to_string(base_type.to_json(), sort_keys=True))
99155935 98
26bb0f31 99
99155935
BP
100def do_parse_type(type_string):
101 type_json = unbox_json(ovs.json.from_string(type_string))
3c057118 102 type_ = ovs.db.types.Type.from_json(type_json)
8ea171ab 103 print(ovs.json.to_string(type_.to_json(), sort_keys=True))
99155935 104
26bb0f31 105
99155935
BP
106def do_parse_atoms(type_string, *atom_strings):
107 type_json = unbox_json(ovs.json.from_string(type_string))
3c057118 108 base = ovs.db.types.BaseType.from_json(type_json)
99155935
BP
109 for atom_string in atom_strings:
110 atom_json = unbox_json(ovs.json.from_string(atom_string))
111 try:
112 atom = data.Atom.from_json(base, atom_json)
8ea171ab 113 print(ovs.json.to_string(atom.to_json()))
f3068bff 114 except error.Error as e:
64eb96a9 115 print(e.args[0])
99155935 116
26bb0f31 117
99155935
BP
118def do_parse_data(type_string, *data_strings):
119 type_json = unbox_json(ovs.json.from_string(type_string))
3c057118 120 type_ = ovs.db.types.Type.from_json(type_json)
99155935
BP
121 for datum_string in data_strings:
122 datum_json = unbox_json(ovs.json.from_string(datum_string))
8cdf0349 123 datum = data.Datum.from_json(type_, datum_json)
8ea171ab 124 print(ovs.json.to_string(datum.to_json()))
99155935 125
26bb0f31 126
99155935
BP
127def do_sort_atoms(type_string, atom_strings):
128 type_json = unbox_json(ovs.json.from_string(type_string))
3c057118 129 base = ovs.db.types.BaseType.from_json(type_json)
99155935
BP
130 atoms = [data.Atom.from_json(base, atom_json)
131 for atom_json in unbox_json(ovs.json.from_string(atom_strings))]
8ea171ab
RB
132 print(ovs.json.to_string([data.Atom.to_json(atom)
133 for atom in sorted(atoms)]))
99155935 134
26bb0f31 135
99155935
BP
136def do_parse_column(name, column_string):
137 column_json = unbox_json(ovs.json.from_string(column_string))
138 column = ovs.db.schema.ColumnSchema.from_json(column_json, name)
8ea171ab 139 print(ovs.json.to_string(column.to_json(), sort_keys=True))
99155935 140
26bb0f31 141
c5f341ab
BP
142def do_parse_table(name, table_string, default_is_root_string='false'):
143 default_is_root = default_is_root_string == 'true'
99155935
BP
144 table_json = unbox_json(ovs.json.from_string(table_string))
145 table = ovs.db.schema.TableSchema.from_json(table_json, name)
8ea171ab 146 print(ovs.json.to_string(table.to_json(default_is_root), sort_keys=True))
99155935 147
26bb0f31 148
99155935
BP
149def do_parse_schema(schema_string):
150 schema_json = unbox_json(ovs.json.from_string(schema_string))
151 schema = ovs.db.schema.DbSchema.from_json(schema_json)
8ea171ab 152 print(ovs.json.to_string(schema.to_json(), sort_keys=True))
99155935 153
26bb0f31 154
330b9c9c 155def get_simple_printable_row_string(row, columns):
a7261bf7 156 s = ""
330b9c9c 157 for column in columns:
a7261bf7
NS
158 if hasattr(row, column) and not (type(getattr(row, column))
159 is ovs.db.data.Atom):
330b9c9c
AB
160 value = getattr(row, column)
161 if isinstance(value, dict):
162 value = sorted(value.items())
163 s += "%s=%s " % (column, value)
a7261bf7
NS
164 s = s.strip()
165 s = re.sub('""|,|u?\'', "", s)
145a7e88 166 s = re.sub(r'UUID\(([^)]+)\)', r'\1', s)
a7261bf7
NS
167 s = re.sub('False', 'false', s)
168 s = re.sub('True', 'true', s)
169 s = re.sub(r'(ba)=([^[][^ ]*) ', r'\1=[\2] ', s)
170 return s
171
172
330b9c9c
AB
173def get_simple_table_printable_row(row):
174 simple_columns = ["i", "r", "b", "s", "u", "ia",
175 "ra", "ba", "sa", "ua", "uuid"]
176 return get_simple_printable_row_string(row, simple_columns)
177
178
a59912a0
RM
179def get_simple2_table_printable_row(row):
180 simple2_columns = ["name", "smap", "imap"]
330b9c9c 181 return get_simple_printable_row_string(row, simple2_columns)
a59912a0
RM
182
183
184def get_simple3_table_printable_row(row):
185 simple3_columns = ["name", "uset"]
330b9c9c 186 return get_simple_printable_row_string(row, simple3_columns)
a59912a0
RM
187
188
99155935
BP
189def print_idl(idl, step):
190 n = 0
80c12152 191 if "simple" in idl.tables:
80c12152 192 simple = idl.tables["simple"].rows
0c4d144a 193 for row in simple.values():
a7261bf7
NS
194 s = "%03d: " % step
195 s += get_simple_table_printable_row(row)
80c12152
SA
196 print(s)
197 n += 1
198
a59912a0
RM
199 if "simple2" in idl.tables:
200 simple2 = idl.tables["simple2"].rows
0c4d144a 201 for row in simple2.values():
a59912a0
RM
202 s = "%03d: " % step
203 s += get_simple2_table_printable_row(row)
204 print(s)
205 n += 1
206
207 if "simple3" in idl.tables:
208 simple3 = idl.tables["simple3"].rows
0c4d144a 209 for row in simple3.values():
a59912a0
RM
210 s = "%03d: " % step
211 s += get_simple3_table_printable_row(row)
212 print(s)
213 n += 1
214
80c12152
SA
215 if "link1" in idl.tables:
216 l1 = idl.tables["link1"].rows
0c4d144a 217 for row in l1.values():
80c12152
SA
218 s = ["%03d: i=%s k=" % (step, row.i)]
219 if hasattr(row, "k") and row.k:
220 s.append(str(row.k.i))
221 if hasattr(row, "ka"):
222 s.append(" ka=[")
223 s.append(' '.join(sorted(str(ka.i) for ka in row.ka)))
224 s.append("] l2=")
225 if hasattr(row, "l2") and row.l2:
226 s.append(str(row.l2[0].i))
227 if hasattr(row, "uuid"):
228 s.append(" uuid=%s" % row.uuid)
229 print(''.join(s))
230 n += 1
231
232 if "link2" in idl.tables:
233 l2 = idl.tables["link2"].rows
0c4d144a 234 for row in l2.values():
80c12152
SA
235 s = ["%03d:" % step]
236 s.append(" i=%s l1=" % row.i)
237 if hasattr(row, "l1") and row.l1:
238 s.append(str(row.l1[0].i))
239 if hasattr(row, "uuid"):
240 s.append(" uuid=%s" % row.uuid)
241 print(''.join(s))
242 n += 1
8cdf0349 243
079ace1f
MM
244 if "singleton" in idl.tables:
245 sng = idl.tables["singleton"].rows
0c4d144a 246 for row in sng.values():
079ace1f
MM
247 s = ["%03d:" % step]
248 s.append(" name=%s" % row.name)
249 if hasattr(row, "uuid"):
250 s.append(" uuid=%s" % row.uuid)
251 print(''.join(s))
252 n += 1
253
99155935
BP
254 if not n:
255 print("%03d: empty" % step)
8cdf0349 256 sys.stdout.flush()
99155935 257
26bb0f31 258
99155935 259def substitute_uuids(json, symtab):
0c4d144a 260 if isinstance(json, str):
99155935
BP
261 symbol = symtab.get(json)
262 if symbol:
263 return str(symbol)
264 elif type(json) == list:
265 return [substitute_uuids(element, symtab) for element in json]
266 elif type(json) == dict:
267 d = {}
0c4d144a 268 for key, value in json.items():
99155935
BP
269 d[key] = substitute_uuids(value, symtab)
270 return d
271 return json
272
26bb0f31 273
99155935 274def parse_uuids(json, symtab):
0c4d144a 275 if (isinstance(json, str)
25f599fb 276 and ovs.ovsuuid.is_valid_string(json)):
99155935
BP
277 name = "#%d#" % len(symtab)
278 sys.stderr.write("%s = %s\n" % (name, json))
279 symtab[name] = json
280 elif type(json) == list:
281 for element in json:
282 parse_uuids(element, symtab)
283 elif type(json) == dict:
0c4d144a 284 for value in json.values():
99155935
BP
285 parse_uuids(value, symtab)
286
26bb0f31 287
8cdf0349 288def idltest_find_simple(idl, i):
0c4d144a 289 for row in idl.tables["simple"].rows.values():
8cdf0349
BP
290 if row.i == i:
291 return row
292 return None
293
26bb0f31 294
a59912a0 295def idltest_find_simple2(idl, i):
0c4d144a 296 for row in idl.tables["simple2"].rows.values():
a59912a0
RM
297 if row.name == i:
298 return row
299 return None
300
301
302def idltest_find_simple3(idl, i):
13973bc4 303 return next(idl.index_equal("simple3", "simple3_by_name", i), None)
a59912a0
RM
304
305
8cdf0349
BP
306def idl_set(idl, commands, step):
307 txn = ovs.db.idl.Transaction(idl)
308 increment = False
80c12152 309 fetch_cmds = []
d7d417fc 310 events = []
8cdf0349
BP
311 for command in commands.split(','):
312 words = command.split()
313 name = words[0]
314 args = words[1:]
315
d7d417fc
TW
316 if name == "notifytest":
317 name = args[0]
318 args = args[1:]
319 old_notify = idl.notify
320
321 def notify(event, row, updates=None):
1aa2bf92 322 if updates:
cb96c1b2 323 upcol = list(updates._data.keys())[0]
1aa2bf92
AW
324 else:
325 upcol = None
d7d417fc
TW
326 events.append("%s|%s|%s" % (event, row.i, upcol))
327 idl.notify = old_notify
328
329 idl.notify = notify
330
8cdf0349
BP
331 if name == "set":
332 if len(args) != 3:
333 sys.stderr.write('"set" command requires 3 arguments\n')
334 sys.exit(1)
335
336 s = idltest_find_simple(idl, int(args[0]))
337 if not s:
338 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
339 % int(args[0]))
340 sys.exit(1)
341
342 if args[1] == "b":
343 s.b = args[2] == "1"
344 elif args[1] == "s":
0c4d144a
TR
345 s.s = args[2].encode(sys.getfilesystemencoding(),
346 'surrogateescape') \
347 .decode('utf-8', 'replace')
8cdf0349
BP
348 elif args[1] == "u":
349 s.u = uuid.UUID(args[2])
350 elif args[1] == "r":
351 s.r = float(args[2])
352 else:
353 sys.stderr.write('"set" comamnd asks for unknown column %s\n'
354 % args[2])
355 sys.stderr.exit(1)
356 elif name == "insert":
357 if len(args) != 1:
358 sys.stderr.write('"set" command requires 1 argument\n')
359 sys.exit(1)
360
361 s = txn.insert(idl.tables["simple"])
362 s.i = int(args[0])
363 elif name == "delete":
364 if len(args) != 1:
365 sys.stderr.write('"delete" command requires 1 argument\n')
366 sys.exit(1)
367
368 s = idltest_find_simple(idl, int(args[0]))
369 if not s:
370 sys.stderr.write('"delete" command asks for nonexistent i=%d\n'
371 % int(args[0]))
372 sys.exit(1)
373 s.delete()
374 elif name == "verify":
375 if len(args) != 2:
376 sys.stderr.write('"verify" command requires 2 arguments\n')
377 sys.exit(1)
378
379 s = idltest_find_simple(idl, int(args[0]))
380 if not s:
381 sys.stderr.write('"verify" command asks for nonexistent i=%d\n'
382 % int(args[0]))
383 sys.exit(1)
384
385 if args[1] in ("i", "b", "s", "u", "r"):
386 s.verify(args[1])
387 else:
388 sys.stderr.write('"verify" command asks for unknown column '
389 '"%s"\n' % args[1])
390 sys.exit(1)
80c12152
SA
391 elif name == "fetch":
392 if len(args) != 2:
393 sys.stderr.write('"fetch" command requires 2 argument\n')
394 sys.exit(1)
395
396 row = idltest_find_simple(idl, int(args[0]))
397 if not row:
398 sys.stderr.write('"fetch" command asks for nonexistent i=%d\n'
399 % int(args[0]))
400 sys.exit(1)
401
402 column = args[1]
403 row.fetch(column)
404 fetch_cmds.append([row, column])
8cdf0349 405 elif name == "increment":
94fbe1aa
BP
406 if len(args) != 1:
407 sys.stderr.write('"increment" command requires 1 argument\n')
408 sys.exit(1)
409
410 s = idltest_find_simple(idl, int(args[0]))
411 if not s:
412 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
413 % int(args[0]))
8cdf0349
BP
414 sys.exit(1)
415
94fbe1aa 416 s.increment("i")
8cdf0349
BP
417 increment = True
418 elif name == "abort":
419 txn.abort()
420 break
421 elif name == "destroy":
8ea171ab 422 print("%03d: destroy" % step)
8cdf0349
BP
423 sys.stdout.flush()
424 txn.abort()
425 return
225b582a
IY
426 elif name == "linktest":
427 l1_0 = txn.insert(idl.tables["link1"])
428 l1_0.i = 1
429 l1_0.k = [l1_0]
430 l1_0.ka = [l1_0]
431 l1_1 = txn.insert(idl.tables["link1"])
432 l1_1.i = 2
433 l1_1.k = [l1_0]
434 l1_1.ka = [l1_0, l1_1]
3b4c362f
IY
435 elif name == 'getattrtest':
436 l1 = txn.insert(idl.tables["link1"])
437 i = getattr(l1, 'i', 1)
438 assert i == 1
439 l1.i = 2
440 i = getattr(l1, 'i', 1)
441 assert i == 2
442 l1.k = [l1]
a59912a0
RM
443 elif name == 'partialmapinsertelement':
444 row = idltest_find_simple2(idl, 'myString1')
2d54d801 445 len_smap = len(getattr(row, 'smap'))
a59912a0 446 row.setkey('smap', 'key1', 'myList1')
2d54d801 447 len_imap = len(getattr(row, 'imap'))
a59912a0
RM
448 row.setkey('imap', 3, 'myids2')
449 row.__setattr__('name', 'String2')
2d54d801
AB
450 assert len(getattr(row, 'smap')) == len_smap
451 assert len(getattr(row, 'imap')) == len_imap + 1
330b9c9c
AB
452 elif name == 'partialmapinsertmultipleelements':
453 row = idltest_find_simple2(idl, 'String2')
2d54d801 454 len_smap = len(getattr(row, 'smap'))
330b9c9c
AB
455 row.setkey('smap', 'key2', 'myList2')
456 row.setkey('smap', 'key3', 'myList3')
2d54d801
AB
457 row.setkey('smap', 'key4', 'myList4')
458 assert len(getattr(row, 'smap')) == len_smap + 2
330b9c9c 459 elif name == 'partialmapdelelements':
a59912a0 460 row = idltest_find_simple2(idl, 'String2')
2d54d801 461 len_smap = len(getattr(row, 'smap'))
884d9bad 462 row.delkey('smap', 'key1', 'myList1')
330b9c9c
AB
463 row.delkey('smap', 'key2', 'wrongvalue')
464 row.delkey('smap', 'key3')
2d54d801
AB
465 row.delkey('smap', 'key4')
466 assert len(getattr(row, 'smap')) == len_smap - 3
467 elif name == 'partialmapmutatenew':
468 new_row2 = txn.insert(idl.tables["simple2"])
469 setattr(new_row2, 'name', 'String2New')
470 new_row2.setkey('smap', 'key1', 'newList1')
471 assert len(getattr(new_row2, 'smap')) == 1
472 new_row2.setkey('smap', 'key2', 'newList2')
473 assert len(getattr(new_row2, 'smap')) == 2
a59912a0
RM
474 elif name == 'partialrenamesetadd':
475 row = idltest_find_simple3(idl, 'mySet1')
2d54d801 476 old_size = len(getattr(row, 'uset', []))
a59912a0
RM
477 row.addvalue('uset',
478 uuid.UUID("001e43d2-dd3f-4616-ab6a-83a490bb0991"))
479 row.__setattr__('name', 'String2')
2d54d801 480 assert len(getattr(row, 'uset', [])) == old_size + 1
330b9c9c 481 elif name == 'partialduplicateadd':
a59912a0 482 row = idltest_find_simple3(idl, 'String2')
2d54d801 483 old_size = len(getattr(row, 'uset', []))
a59912a0
RM
484 row.addvalue('uset',
485 uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8"))
330b9c9c
AB
486 row.addvalue('uset',
487 uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8"))
2d54d801 488 assert len(getattr(row, 'uset', [])) == old_size + 1
a59912a0
RM
489 elif name == 'partialsetdel':
490 row = idltest_find_simple3(idl, 'String2')
2d54d801 491 old_size = len(getattr(row, 'uset', []))
a59912a0
RM
492 row.delvalue('uset',
493 uuid.UUID("001e43d2-dd3f-4616-ab6a-83a490bb0991"))
2d54d801 494 assert len(getattr(row, 'uset', [])) == old_size - 1
a59912a0
RM
495 elif name == 'partialsetref':
496 new_row = txn.insert(idl.tables["simple4"])
497 new_row.__setattr__('name', 'test')
498 row = idltest_find_simple3(idl, 'String2')
2d54d801 499 old_size = len(getattr(row, 'uref', []))
a59912a0 500 row.addvalue('uref', new_row.uuid)
2d54d801 501 assert len(getattr(row, 'uref', [])) == old_size + 1
330b9c9c
AB
502 elif name == 'partialsetoverrideops':
503 row = idltest_find_simple3(idl, 'String2')
504 row.addvalue('uset',
505 uuid.UUID("579e978d-776c-4f19-a225-268e5890e670"))
506 row.delvalue('uset',
507 uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8"))
508 row.__setattr__('uset',
509 [uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8")])
2d54d801
AB
510 assert len(getattr(row, 'uset', [])) == 1
511 elif name == 'partialsetadddelete':
512 row = idltest_find_simple3(idl, 'String2')
513 row.addvalue('uset',
514 uuid.UUID('b6272353-af9c-40b7-90fe-32a43e6518a1'))
515 row.addvalue('uset',
516 uuid.UUID('1d6a71a2-dffb-426e-b2fa-b727091f9901'))
517 row.delvalue('uset',
518 uuid.UUID('0026b3ba-571b-4729-8227-d860a5210ab8'))
519 assert len(getattr(row, 'uset', [])) == 2
b3220c67
AB
520 elif name == 'partialsetmutatenew':
521 new_row41 = txn.insert(idl.tables["simple4"])
522 new_row41.__setattr__('name', 'new_row41')
523 new_row3 = txn.insert(idl.tables["simple3"])
524 setattr(new_row3, 'name', 'String3')
525 new_row3.addvalue('uset', new_row41.uuid)
2d54d801 526 assert len(getattr(new_row3, 'uset', [])) == 1
8cdf0349
BP
527 else:
528 sys.stderr.write("unknown command %s\n" % name)
529 sys.exit(1)
530
531 status = txn.commit_block()
532 sys.stdout.write("%03d: commit, status=%s"
533 % (step, ovs.db.idl.Transaction.status_to_string(status)))
534 if increment and status == ovs.db.idl.Transaction.SUCCESS:
535 sys.stdout.write(", increment=%d" % txn.get_increment_new_value())
d7d417fc
TW
536 if events:
537 # Event notifications from operations in a single transaction are
538 # not in a gauranteed order due to update messages being dicts
539 sys.stdout.write(", events=" + ", ".join(sorted(events)))
8cdf0349
BP
540 sys.stdout.write("\n")
541 sys.stdout.flush()
542
26bb0f31 543
16ebb90e 544def update_condition(idl, commands):
0164e367 545 commands = commands[len("condition "):].split(";")
16ebb90e 546 for command in commands:
16ebb90e
LS
547 command = command.split(" ")
548 if(len(command) != 2):
0164e367 549 sys.stderr.write("Error parsing condition %s\n" % command)
16ebb90e
LS
550 sys.exit(1)
551
552 table = command[0]
553 cond = ovs.json.from_string(command[1])
554
0164e367 555 idl.cond_change(table, cond)
16ebb90e
LS
556
557
8cdf0349 558def do_idl(schema_file, remote, *commands):
bf42f674 559 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
a7261bf7
NS
560 track_notify = False
561
d90ed7d6 562 if remote.startswith("ssl:"):
6612648d
JS
563 if len(commands) < 3:
564 sys.stderr.write("SSL connection requires private key, "
565 "certificate for private key, and peer CA "
566 "certificate as arguments\n")
567 sys.exit(1)
d90ed7d6
NS
568 ovs.stream.Stream.ssl_set_private_key_file(commands[0])
569 ovs.stream.Stream.ssl_set_certificate_file(commands[1])
570 ovs.stream.Stream.ssl_set_ca_cert_file(commands[2])
571 commands = commands[3:]
572
a7261bf7
NS
573 if commands and commands[0] == "track-notify":
574 commands = commands[1:]
575 track_notify = True
576
01dc1516 577 if commands and commands[0].startswith("?"):
80c12152 578 readonly = {}
01dc1516 579 for x in commands[0][1:].split("?"):
80c12152 580 readonly = []
01dc1516 581 table, columns = x.split(":")
80c12152
SA
582 columns = columns.split(",")
583 for index, column in enumerate(columns):
584 if column[-1] == '!':
585 columns[index] = columns[index][:-1]
586 readonly.append(columns[index])
587 schema_helper.register_columns(table, columns, readonly)
01dc1516
SA
588 commands = commands[1:]
589 else:
590 schema_helper.register_all()
bf42f674 591 idl = ovs.db.idl.Idl(remote, schema_helper)
13973bc4
TW
592 if "simple3" in idl.tables:
593 idl.index_create("simple3", "simple3_by_name")
99155935
BP
594
595 if commands:
31e434fc
NS
596 remotes = remote.split(',')
597 stream = None
598 for r in remotes:
599 error, stream = ovs.stream.Stream.open_block(
77f42ca5 600 ovs.stream.Stream.open(r), 2000)
31e434fc
NS
601 if not error and stream:
602 break
603 stream = None
604
605 if not stream:
99155935
BP
606 sys.stderr.write("failed to connect to \"%s\"" % remote)
607 sys.exit(1)
608 rpc = ovs.jsonrpc.Connection(stream)
609 else:
610 rpc = None
611
612 symtab = {}
613 seqno = 0
614 step = 0
16ebb90e 615
a7261bf7
NS
616 def mock_notify(event, row, updates=None):
617 output = "%03d: " % step
618 output += "event:" + str(event) + ", row={"
619 output += get_simple_table_printable_row(row) + "}, updates="
620 if updates is None:
621 output += "None"
622 else:
623 output += "{" + get_simple_table_printable_row(updates) + "}"
624
625 output += '\n'
626 sys.stdout.write(output)
627 sys.stdout.flush()
628
629 if track_notify and "simple" in idl.tables:
630 idl.notify = mock_notify
631
16ebb90e
LS
632 commands = list(commands)
633 if len(commands) >= 1 and "condition" in commands[0]:
634 update_condition(idl, commands.pop(0))
635 sys.stdout.write("%03d: change conditions\n" % step)
636 sys.stdout.flush()
637 step += 1
638
99155935
BP
639 for command in commands:
640 if command.startswith("+"):
641 # The previous transaction didn't change anything.
642 command = command[1:]
643 else:
644 # Wait for update.
8cdf0349 645 while idl.change_seqno == seqno and not idl.run():
99155935
BP
646 rpc.run()
647
648 poller = ovs.poller.Poller()
649 idl.wait(poller)
650 rpc.wait(poller)
651 poller.block()
26bb0f31 652
99155935
BP
653 print_idl(idl, step)
654 step += 1
655
8cdf0349 656 seqno = idl.change_seqno
99155935
BP
657
658 if command == "reconnect":
659 print("%03d: reconnect" % step)
8cdf0349 660 sys.stdout.flush()
99155935
BP
661 step += 1
662 idl.force_reconnect()
16ebb90e
LS
663 elif "condition" in command:
664 update_condition(idl, command)
665 sys.stdout.write("%03d: change conditions\n" % step)
666 sys.stdout.flush()
667 step += 1
99155935
BP
668 elif not command.startswith("["):
669 idl_set(idl, command, step)
670 step += 1
671 else:
672 json = ovs.json.from_string(command)
0c4d144a 673 if isinstance(json, str):
99155935
BP
674 sys.stderr.write("\"%s\": %s\n" % (command, json))
675 sys.exit(1)
676 json = substitute_uuids(json, symtab)
677 request = ovs.jsonrpc.Message.create_request("transact", json)
678 error, reply = rpc.transact_block(request)
679 if error:
217ac094 680 sys.stderr.write("jsonrpc transaction failed: %s\n"
99155935
BP
681 % os.strerror(error))
682 sys.exit(1)
66eb76d0 683 elif reply.error is not None:
217ac094 684 sys.stderr.write("jsonrpc transaction failed: %s\n"
66eb76d0
EJ
685 % reply.error)
686 sys.exit(1)
687
99155935
BP
688 sys.stdout.write("%03d: " % step)
689 sys.stdout.flush()
690 step += 1
691 if reply.result is not None:
692 parse_uuids(reply.result, symtab)
693 reply.id = None
694 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
8cdf0349 695 sys.stdout.flush()
99155935
BP
696
697 if rpc:
698 rpc.close()
8cdf0349 699 while idl.change_seqno == seqno and not idl.run():
99155935
BP
700 poller = ovs.poller.Poller()
701 idl.wait(poller)
702 poller.block()
703 print_idl(idl, step)
704 step += 1
705 idl.close()
706 print("%03d: done" % step)
707
26bb0f31 708
af358237
OBY
709def do_idl_passive(schema_file, remote, *commands):
710 symtab = {}
711 step = 0
712 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
713 schema_helper.register_all()
714 idl = ovs.db.idl.Idl(remote, schema_helper)
715
716 while idl._session.rpc is None:
717 idl.run()
718
719 rpc = idl._session.rpc
720
721 print_idl(idl, step)
722 step += 1
723
724 for command in commands:
725 json = ovs.json.from_string(command)
0c4d144a 726 if isinstance(json, str):
af358237
OBY
727 sys.stderr.write("\"%s\": %s\n" % (command, json))
728 sys.exit(1)
729 json = substitute_uuids(json, symtab)
730 request = ovs.jsonrpc.Message.create_request("transact", json)
731 error, reply = rpc.transact_block(request)
732 if error:
217ac094 733 sys.stderr.write("jsonrpc transaction failed: %s\n"
af358237
OBY
734 % os.strerror(error))
735 sys.exit(1)
736 elif reply.error is not None:
217ac094 737 sys.stderr.write("jsonrpc transaction failed: %s\n"
af358237
OBY
738 % reply.error)
739 sys.exit(1)
740
741 sys.stdout.write("%03d: " % step)
742 sys.stdout.flush()
743 step += 1
744 if reply.result is not None:
745 parse_uuids(reply.result, symtab)
746 reply.id = None
747 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
748 sys.stdout.flush()
749
750 idl.close()
751 print("%03d: done" % step)
752
753
c39751e4
TE
754def do_idl_cluster(schema_file, remote, pid, *commands):
755 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
756
757 if remote.startswith("ssl:"):
758 if len(commands) < 3:
759 sys.stderr.write("SSL connection requires private key, "
760 "certificate for private key, and peer CA "
761 "certificate as arguments\n")
762 sys.exit(1)
763 ovs.stream.Stream.ssl_set_private_key_file(commands[0])
764 ovs.stream.Stream.ssl_set_certificate_file(commands[1])
765 ovs.stream.Stream.ssl_set_ca_cert_file(commands[2])
766 commands = commands[3:]
767
768 schema_helper.register_all()
769 idl = ovs.db.idl.Idl(remote, schema_helper)
770
771 step = 0
772 seqno = 0
773 commands = list(commands)
774 for command in commands:
775 if command.startswith("+"):
776 # The previous transaction didn't change anything.
777 command = command[1:]
778 else:
779 # Wait for update.
780 while idl.change_seqno == seqno and not idl.run():
781 poller = ovs.poller.Poller()
782 idl.wait(poller)
783 poller.block()
784 step += 1
785
786 seqno = idl.change_seqno
787
788 if command == "reconnect":
789 print("%03d: reconnect" % step)
790 sys.stdout.flush()
791 step += 1
792 idl.force_reconnect()
793 elif command == "remote":
794 print("%03d: %s" % (step, idl.session_name()))
795 sys.stdout.flush()
796 step += 1
797 elif command == "remotestop":
798 r = idl.session_name()
799 remotes = remote.split(',')
800 i = remotes.index(r)
801 pids = pid.split(',')
802 command = None
803 try:
804 command = "kill %s" % pids[i]
805 except ValueError as error:
806 sys.stderr.write("Cannot find pid of remote: %s\n"
807 % os.strerror(error))
808 sys.exit(1)
809 os.popen(command)
810 print("%03d: stop %s" % (step, pids[i]))
811 sys.stdout.flush()
812 step += 1
813
814 idl.close()
815 print("%03d: done" % step)
816
817
99155935 818def usage():
8ea171ab 819 print("""\
99155935
BP
820%(program_name)s: test utility for Open vSwitch database Python bindings
821usage: %(program_name)s [OPTIONS] COMMAND ARG...
822
823The following commands are supported:
824default-atoms
825 test ovsdb_atom_default()
826default-data
827 test ovsdb_datum_default()
828parse-atomic-type TYPE
829 parse TYPE as OVSDB atomic type, and re-serialize
830parse-base-type TYPE
831 parse TYPE as OVSDB base type, and re-serialize
832parse-type JSON
833 parse JSON as OVSDB type, and re-serialize
834parse-atoms TYPE ATOM...
835 parse JSON ATOMs as atoms of TYPE, and re-serialize
836parse-atom-strings TYPE ATOM...
837 parse string ATOMs as atoms of given TYPE, and re-serialize
838sort-atoms TYPE ATOM...
839 print JSON ATOMs in sorted order
840parse-data TYPE DATUM...
841 parse JSON DATUMs as data of given TYPE, and re-serialize
842parse-column NAME OBJECT
843 parse column NAME with info OBJECT, and re-serialize
c5f341ab 844parse-table NAME OBJECT [DEFAULT-IS-ROOT]
99155935
BP
845 parse table NAME with info OBJECT
846parse-schema JSON
847 parse JSON as an OVSDB schema, and re-serialize
01dc1516 848idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
8cdf0349
BP
849 connect to SERVER (which has the specified SCHEMA) and dump the
850 contents of the database as seen initially by the IDL implementation
851 and after executing each TRANSACTION. (Each TRANSACTION must modify
99155935 852 the database or this command will hang.)
01dc1516
SA
853 By default, all columns of all tables are monitored. The "?" option
854 can be used to monitor specific Table:Column(s). The table and their
855 columns are listed as a string of the form starting with "?":
856 ?<table-name>:<column-name>,<column-name>,...
857 e.g.:
858 ?simple:b - Monitor column "b" in table "simple"
859 Entries for multiple tables are seperated by "?":
860 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
861 e.g.:
862 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
863 and column "i", "k" in table "link1"
80c12152
SA
864 Readonly columns: Suffixing a "!" after a column indicates that the
865 column is to be registered "readonly".
866 e.g.:
867 ?simple:i,b! - Register interest in column "i" (monitoring) and
868 column "b" (readonly).
869
99155935
BP
870
871The following options are also available:
872 -t, --timeout=SECS give up after SECS seconds
873 -h, --help display this help message\
8ea171ab 874""" % {'program_name': ovs.util.PROGRAM_NAME})
99155935
BP
875 sys.exit(0)
876
26bb0f31 877
99155935 878def main(argv):
99155935 879 try:
e6703555 880 options, args = getopt.gnu_getopt(argv[1:], 't:h',
99155935 881 ['timeout',
e6703555 882 'help'])
f3068bff 883 except getopt.GetoptError as geo:
99155935
BP
884 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
885 sys.exit(1)
886
9551e80b 887 timeout = None
99155935
BP
888 for key, value in options:
889 if key in ['-h', '--help']:
890 usage()
891 elif key in ['-t', '--timeout']:
892 try:
893 timeout = int(value)
894 if timeout < 1:
895 raise TypeError
896 except TypeError:
897 raise error.Error("value %s on -t or --timeout is not at "
898 "least 1" % value)
99155935
BP
899 else:
900 sys.exit(0)
901
9551e80b
IM
902 signal_alarm(timeout)
903
99155935
BP
904 if not args:
905 sys.stderr.write("%s: missing command argument "
906 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
907 sys.exit(1)
908
909 commands = {"default-atoms": (do_default_atoms, 0),
910 "default-data": (do_default_data, 0),
911 "parse-atomic-type": (do_parse_atomic_type, 1),
912 "parse-base-type": (do_parse_base_type, 1),
913 "parse-type": (do_parse_type, 1),
914 "parse-atoms": (do_parse_atoms, (2,)),
915 "parse-data": (do_parse_data, (2,)),
916 "sort-atoms": (do_sort_atoms, 2),
917 "parse-column": (do_parse_column, 2),
c5f341ab 918 "parse-table": (do_parse_table, (2, 3)),
99155935 919 "parse-schema": (do_parse_schema, 1),
af358237 920 "idl": (do_idl, (2,)),
c39751e4
TE
921 "idl_passive": (do_idl_passive, (2,)),
922 "idl-cluster": (do_idl_cluster, (3,))}
99155935
BP
923
924 command_name = args[0]
925 args = args[1:]
603e325f 926 if command_name not in commands:
99155935
BP
927 sys.stderr.write("%s: unknown command \"%s\" "
928 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
929 command_name))
930 sys.exit(1)
931
932 func, n_args = commands[command_name]
933 if type(n_args) == tuple:
934 if len(args) < n_args[0]:
935 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
936 "only %d provided\n"
937 % (ovs.util.PROGRAM_NAME, command_name,
117637b7 938 n_args[0], len(args)))
99155935
BP
939 sys.exit(1)
940 elif type(n_args) == int:
941 if len(args) != n_args:
942 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
943 "provided\n"
944 % (ovs.util.PROGRAM_NAME, command_name,
945 n_args, len(args)))
946 sys.exit(1)
947 else:
948 assert False
949
950 func(*args)
951
26bb0f31 952
99155935
BP
953if __name__ == '__main__':
954 try:
955 main(sys.argv)
f3068bff 956 except error.Error as e:
99155935
BP
957 sys.stderr.write("%s\n" % e)
958 sys.exit(1)