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