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