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