]> git.proxmox.com Git - ovs.git/blob - tests/test-ovsdb.py
python: make python idl unicode-tolerant
[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 if six.PY2:
338 s.s = args[2].decode('utf-8')
339 else:
340 s.s = args[2].encode('utf-8', 'surrogateescape') \
341 .decode('utf-8', 'replace')
342 elif args[1] == "u":
343 s.u = uuid.UUID(args[2])
344 elif args[1] == "r":
345 s.r = float(args[2])
346 else:
347 sys.stderr.write('"set" comamnd asks for unknown column %s\n'
348 % args[2])
349 sys.stderr.exit(1)
350 elif name == "insert":
351 if len(args) != 1:
352 sys.stderr.write('"set" command requires 1 argument\n')
353 sys.exit(1)
354
355 s = txn.insert(idl.tables["simple"])
356 s.i = int(args[0])
357 elif name == "delete":
358 if len(args) != 1:
359 sys.stderr.write('"delete" command requires 1 argument\n')
360 sys.exit(1)
361
362 s = idltest_find_simple(idl, int(args[0]))
363 if not s:
364 sys.stderr.write('"delete" command asks for nonexistent i=%d\n'
365 % int(args[0]))
366 sys.exit(1)
367 s.delete()
368 elif name == "verify":
369 if len(args) != 2:
370 sys.stderr.write('"verify" command requires 2 arguments\n')
371 sys.exit(1)
372
373 s = idltest_find_simple(idl, int(args[0]))
374 if not s:
375 sys.stderr.write('"verify" command asks for nonexistent i=%d\n'
376 % int(args[0]))
377 sys.exit(1)
378
379 if args[1] in ("i", "b", "s", "u", "r"):
380 s.verify(args[1])
381 else:
382 sys.stderr.write('"verify" command asks for unknown column '
383 '"%s"\n' % args[1])
384 sys.exit(1)
385 elif name == "fetch":
386 if len(args) != 2:
387 sys.stderr.write('"fetch" command requires 2 argument\n')
388 sys.exit(1)
389
390 row = idltest_find_simple(idl, int(args[0]))
391 if not row:
392 sys.stderr.write('"fetch" command asks for nonexistent i=%d\n'
393 % int(args[0]))
394 sys.exit(1)
395
396 column = args[1]
397 row.fetch(column)
398 fetch_cmds.append([row, column])
399 elif name == "increment":
400 if len(args) != 1:
401 sys.stderr.write('"increment" command requires 1 argument\n')
402 sys.exit(1)
403
404 s = idltest_find_simple(idl, int(args[0]))
405 if not s:
406 sys.stderr.write('"set" command asks for nonexistent i=%d\n'
407 % int(args[0]))
408 sys.exit(1)
409
410 s.increment("i")
411 increment = True
412 elif name == "abort":
413 txn.abort()
414 break
415 elif name == "destroy":
416 print("%03d: destroy" % step)
417 sys.stdout.flush()
418 txn.abort()
419 return
420 elif name == "linktest":
421 l1_0 = txn.insert(idl.tables["link1"])
422 l1_0.i = 1
423 l1_0.k = [l1_0]
424 l1_0.ka = [l1_0]
425 l1_1 = txn.insert(idl.tables["link1"])
426 l1_1.i = 2
427 l1_1.k = [l1_0]
428 l1_1.ka = [l1_0, l1_1]
429 elif name == 'getattrtest':
430 l1 = txn.insert(idl.tables["link1"])
431 i = getattr(l1, 'i', 1)
432 assert i == 1
433 l1.i = 2
434 i = getattr(l1, 'i', 1)
435 assert i == 2
436 l1.k = [l1]
437 elif name == 'partialmapinsertelement':
438 row = idltest_find_simple2(idl, 'myString1')
439 len_smap = len(getattr(row, 'smap'))
440 row.setkey('smap', 'key1', 'myList1')
441 len_imap = len(getattr(row, 'imap'))
442 row.setkey('imap', 3, 'myids2')
443 row.__setattr__('name', 'String2')
444 assert len(getattr(row, 'smap')) == len_smap
445 assert len(getattr(row, 'imap')) == len_imap + 1
446 elif name == 'partialmapinsertmultipleelements':
447 row = idltest_find_simple2(idl, 'String2')
448 len_smap = len(getattr(row, 'smap'))
449 row.setkey('smap', 'key2', 'myList2')
450 row.setkey('smap', 'key3', 'myList3')
451 row.setkey('smap', 'key4', 'myList4')
452 assert len(getattr(row, 'smap')) == len_smap + 2
453 elif name == 'partialmapdelelements':
454 row = idltest_find_simple2(idl, 'String2')
455 len_smap = len(getattr(row, 'smap'))
456 row.delkey('smap', 'key1', 'myList1')
457 row.delkey('smap', 'key2', 'wrongvalue')
458 row.delkey('smap', 'key3')
459 row.delkey('smap', 'key4')
460 assert len(getattr(row, 'smap')) == len_smap - 3
461 elif name == 'partialmapmutatenew':
462 new_row2 = txn.insert(idl.tables["simple2"])
463 setattr(new_row2, 'name', 'String2New')
464 new_row2.setkey('smap', 'key1', 'newList1')
465 assert len(getattr(new_row2, 'smap')) == 1
466 new_row2.setkey('smap', 'key2', 'newList2')
467 assert len(getattr(new_row2, 'smap')) == 2
468 elif name == 'partialrenamesetadd':
469 row = idltest_find_simple3(idl, 'mySet1')
470 old_size = len(getattr(row, 'uset', []))
471 row.addvalue('uset',
472 uuid.UUID("001e43d2-dd3f-4616-ab6a-83a490bb0991"))
473 row.__setattr__('name', 'String2')
474 assert len(getattr(row, 'uset', [])) == old_size + 1
475 elif name == 'partialduplicateadd':
476 row = idltest_find_simple3(idl, 'String2')
477 old_size = len(getattr(row, 'uset', []))
478 row.addvalue('uset',
479 uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8"))
480 row.addvalue('uset',
481 uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8"))
482 assert len(getattr(row, 'uset', [])) == old_size + 1
483 elif name == 'partialsetdel':
484 row = idltest_find_simple3(idl, 'String2')
485 old_size = len(getattr(row, 'uset', []))
486 row.delvalue('uset',
487 uuid.UUID("001e43d2-dd3f-4616-ab6a-83a490bb0991"))
488 assert len(getattr(row, 'uset', [])) == old_size - 1
489 elif name == 'partialsetref':
490 new_row = txn.insert(idl.tables["simple4"])
491 new_row.__setattr__('name', 'test')
492 row = idltest_find_simple3(idl, 'String2')
493 old_size = len(getattr(row, 'uref', []))
494 row.addvalue('uref', new_row.uuid)
495 assert len(getattr(row, 'uref', [])) == old_size + 1
496 elif name == 'partialsetoverrideops':
497 row = idltest_find_simple3(idl, 'String2')
498 row.addvalue('uset',
499 uuid.UUID("579e978d-776c-4f19-a225-268e5890e670"))
500 row.delvalue('uset',
501 uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8"))
502 row.__setattr__('uset',
503 [uuid.UUID("0026b3ba-571b-4729-8227-d860a5210ab8")])
504 assert len(getattr(row, 'uset', [])) == 1
505 elif name == 'partialsetadddelete':
506 row = idltest_find_simple3(idl, 'String2')
507 row.addvalue('uset',
508 uuid.UUID('b6272353-af9c-40b7-90fe-32a43e6518a1'))
509 row.addvalue('uset',
510 uuid.UUID('1d6a71a2-dffb-426e-b2fa-b727091f9901'))
511 row.delvalue('uset',
512 uuid.UUID('0026b3ba-571b-4729-8227-d860a5210ab8'))
513 assert len(getattr(row, 'uset', [])) == 2
514 elif name == 'partialsetmutatenew':
515 new_row41 = txn.insert(idl.tables["simple4"])
516 new_row41.__setattr__('name', 'new_row41')
517 new_row3 = txn.insert(idl.tables["simple3"])
518 setattr(new_row3, 'name', 'String3')
519 new_row3.addvalue('uset', new_row41.uuid)
520 assert len(getattr(new_row3, 'uset', [])) == 1
521 else:
522 sys.stderr.write("unknown command %s\n" % name)
523 sys.exit(1)
524
525 status = txn.commit_block()
526 sys.stdout.write("%03d: commit, status=%s"
527 % (step, ovs.db.idl.Transaction.status_to_string(status)))
528 if increment and status == ovs.db.idl.Transaction.SUCCESS:
529 sys.stdout.write(", increment=%d" % txn.get_increment_new_value())
530 if events:
531 # Event notifications from operations in a single transaction are
532 # not in a gauranteed order due to update messages being dicts
533 sys.stdout.write(", events=" + ", ".join(sorted(events)))
534 sys.stdout.write("\n")
535 sys.stdout.flush()
536
537
538 def update_condition(idl, commands):
539 commands = commands[len("condition "):].split(";")
540 for command in commands:
541 command = command.split(" ")
542 if(len(command) != 2):
543 sys.stderr.write("Error parsing condition %s\n" % command)
544 sys.exit(1)
545
546 table = command[0]
547 cond = ovs.json.from_string(command[1])
548
549 idl.cond_change(table, cond)
550
551
552 def do_idl(schema_file, remote, *commands):
553 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
554 track_notify = False
555
556 if remote.startswith("ssl:"):
557 ovs.stream.Stream.ssl_set_private_key_file(commands[0])
558 ovs.stream.Stream.ssl_set_certificate_file(commands[1])
559 ovs.stream.Stream.ssl_set_ca_cert_file(commands[2])
560 commands = commands[3:]
561
562 if commands and commands[0] == "track-notify":
563 commands = commands[1:]
564 track_notify = True
565
566 if commands and commands[0].startswith("?"):
567 readonly = {}
568 for x in commands[0][1:].split("?"):
569 readonly = []
570 table, columns = x.split(":")
571 columns = columns.split(",")
572 for index, column in enumerate(columns):
573 if column[-1] == '!':
574 columns[index] = columns[index][:-1]
575 readonly.append(columns[index])
576 schema_helper.register_columns(table, columns, readonly)
577 commands = commands[1:]
578 else:
579 schema_helper.register_all()
580 idl = ovs.db.idl.Idl(remote, schema_helper)
581
582 if commands:
583 error, stream = ovs.stream.Stream.open_block(
584 ovs.stream.Stream.open(remote))
585 if error:
586 sys.stderr.write("failed to connect to \"%s\"" % remote)
587 sys.exit(1)
588 rpc = ovs.jsonrpc.Connection(stream)
589 else:
590 rpc = None
591
592 symtab = {}
593 seqno = 0
594 step = 0
595
596 def mock_notify(event, row, updates=None):
597 output = "%03d: " % step
598 output += "event:" + str(event) + ", row={"
599 output += get_simple_table_printable_row(row) + "}, updates="
600 if updates is None:
601 output += "None"
602 else:
603 output += "{" + get_simple_table_printable_row(updates) + "}"
604
605 output += '\n'
606 sys.stdout.write(output)
607 sys.stdout.flush()
608
609 if track_notify and "simple" in idl.tables:
610 idl.notify = mock_notify
611
612 commands = list(commands)
613 if len(commands) >= 1 and "condition" in commands[0]:
614 update_condition(idl, commands.pop(0))
615 sys.stdout.write("%03d: change conditions\n" % step)
616 sys.stdout.flush()
617 step += 1
618
619 for command in commands:
620 if command.startswith("+"):
621 # The previous transaction didn't change anything.
622 command = command[1:]
623 else:
624 # Wait for update.
625 while idl.change_seqno == seqno and not idl.run():
626 rpc.run()
627
628 poller = ovs.poller.Poller()
629 idl.wait(poller)
630 rpc.wait(poller)
631 poller.block()
632
633 print_idl(idl, step)
634 step += 1
635
636 seqno = idl.change_seqno
637
638 if command == "reconnect":
639 print("%03d: reconnect" % step)
640 sys.stdout.flush()
641 step += 1
642 idl.force_reconnect()
643 elif "condition" in command:
644 update_condition(idl, command)
645 sys.stdout.write("%03d: change conditions\n" % step)
646 sys.stdout.flush()
647 step += 1
648 elif not command.startswith("["):
649 idl_set(idl, command, step)
650 step += 1
651 else:
652 json = ovs.json.from_string(command)
653 if isinstance(json, six.string_types):
654 sys.stderr.write("\"%s\": %s\n" % (command, json))
655 sys.exit(1)
656 json = substitute_uuids(json, symtab)
657 request = ovs.jsonrpc.Message.create_request("transact", json)
658 error, reply = rpc.transact_block(request)
659 if error:
660 sys.stderr.write("jsonrpc transaction failed: %s"
661 % os.strerror(error))
662 sys.exit(1)
663 elif reply.error is not None:
664 sys.stderr.write("jsonrpc transaction failed: %s"
665 % reply.error)
666 sys.exit(1)
667
668 sys.stdout.write("%03d: " % step)
669 sys.stdout.flush()
670 step += 1
671 if reply.result is not None:
672 parse_uuids(reply.result, symtab)
673 reply.id = None
674 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
675 sys.stdout.flush()
676
677 if rpc:
678 rpc.close()
679 while idl.change_seqno == seqno and not idl.run():
680 poller = ovs.poller.Poller()
681 idl.wait(poller)
682 poller.block()
683 print_idl(idl, step)
684 step += 1
685 idl.close()
686 print("%03d: done" % step)
687
688
689 def do_idl_passive(schema_file, remote, *commands):
690 symtab = {}
691 step = 0
692 schema_helper = ovs.db.idl.SchemaHelper(schema_file)
693 schema_helper.register_all()
694 idl = ovs.db.idl.Idl(remote, schema_helper)
695
696 while idl._session.rpc is None:
697 idl.run()
698
699 rpc = idl._session.rpc
700
701 print_idl(idl, step)
702 step += 1
703
704 for command in commands:
705 json = ovs.json.from_string(command)
706 if isinstance(json, six.string_types):
707 sys.stderr.write("\"%s\": %s\n" % (command, json))
708 sys.exit(1)
709 json = substitute_uuids(json, symtab)
710 request = ovs.jsonrpc.Message.create_request("transact", json)
711 error, reply = rpc.transact_block(request)
712 if error:
713 sys.stderr.write("jsonrpc transaction failed: %s"
714 % os.strerror(error))
715 sys.exit(1)
716 elif reply.error is not None:
717 sys.stderr.write("jsonrpc transaction failed: %s"
718 % reply.error)
719 sys.exit(1)
720
721 sys.stdout.write("%03d: " % step)
722 sys.stdout.flush()
723 step += 1
724 if reply.result is not None:
725 parse_uuids(reply.result, symtab)
726 reply.id = None
727 sys.stdout.write("%s\n" % ovs.json.to_string(reply.to_json()))
728 sys.stdout.flush()
729
730 idl.close()
731 print("%03d: done" % step)
732
733
734 def usage():
735 print("""\
736 %(program_name)s: test utility for Open vSwitch database Python bindings
737 usage: %(program_name)s [OPTIONS] COMMAND ARG...
738
739 The following commands are supported:
740 default-atoms
741 test ovsdb_atom_default()
742 default-data
743 test ovsdb_datum_default()
744 parse-atomic-type TYPE
745 parse TYPE as OVSDB atomic type, and re-serialize
746 parse-base-type TYPE
747 parse TYPE as OVSDB base type, and re-serialize
748 parse-type JSON
749 parse JSON as OVSDB type, and re-serialize
750 parse-atoms TYPE ATOM...
751 parse JSON ATOMs as atoms of TYPE, and re-serialize
752 parse-atom-strings TYPE ATOM...
753 parse string ATOMs as atoms of given TYPE, and re-serialize
754 sort-atoms TYPE ATOM...
755 print JSON ATOMs in sorted order
756 parse-data TYPE DATUM...
757 parse JSON DATUMs as data of given TYPE, and re-serialize
758 parse-column NAME OBJECT
759 parse column NAME with info OBJECT, and re-serialize
760 parse-table NAME OBJECT [DEFAULT-IS-ROOT]
761 parse table NAME with info OBJECT
762 parse-schema JSON
763 parse JSON as an OVSDB schema, and re-serialize
764 idl SCHEMA SERVER [?T1:C1,C2...[?T2:C1,C2,...]...] [TRANSACTION...]
765 connect to SERVER (which has the specified SCHEMA) and dump the
766 contents of the database as seen initially by the IDL implementation
767 and after executing each TRANSACTION. (Each TRANSACTION must modify
768 the database or this command will hang.)
769 By default, all columns of all tables are monitored. The "?" option
770 can be used to monitor specific Table:Column(s). The table and their
771 columns are listed as a string of the form starting with "?":
772 ?<table-name>:<column-name>,<column-name>,...
773 e.g.:
774 ?simple:b - Monitor column "b" in table "simple"
775 Entries for multiple tables are seperated by "?":
776 ?<table-name>:<column-name>,...?<table-name>:<column-name>,...
777 e.g.:
778 ?simple:b?link1:i,k - Monitor column "b" in table "simple",
779 and column "i", "k" in table "link1"
780 Readonly columns: Suffixing a "!" after a column indicates that the
781 column is to be registered "readonly".
782 e.g.:
783 ?simple:i,b! - Register interest in column "i" (monitoring) and
784 column "b" (readonly).
785
786
787 The following options are also available:
788 -t, --timeout=SECS give up after SECS seconds
789 -h, --help display this help message\
790 """ % {'program_name': ovs.util.PROGRAM_NAME})
791 sys.exit(0)
792
793
794 def main(argv):
795 try:
796 options, args = getopt.gnu_getopt(argv[1:], 't:h',
797 ['timeout',
798 'help'])
799 except getopt.GetoptError as geo:
800 sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
801 sys.exit(1)
802
803 for key, value in options:
804 if key in ['-h', '--help']:
805 usage()
806 elif key in ['-t', '--timeout']:
807 try:
808 timeout = int(value)
809 if timeout < 1:
810 raise TypeError
811 except TypeError:
812 raise error.Error("value %s on -t or --timeout is not at "
813 "least 1" % value)
814 signal_alarm(timeout)
815 else:
816 sys.exit(0)
817
818 if not args:
819 sys.stderr.write("%s: missing command argument "
820 "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
821 sys.exit(1)
822
823 commands = {"default-atoms": (do_default_atoms, 0),
824 "default-data": (do_default_data, 0),
825 "parse-atomic-type": (do_parse_atomic_type, 1),
826 "parse-base-type": (do_parse_base_type, 1),
827 "parse-type": (do_parse_type, 1),
828 "parse-atoms": (do_parse_atoms, (2,)),
829 "parse-data": (do_parse_data, (2,)),
830 "sort-atoms": (do_sort_atoms, 2),
831 "parse-column": (do_parse_column, 2),
832 "parse-table": (do_parse_table, (2, 3)),
833 "parse-schema": (do_parse_schema, 1),
834 "idl": (do_idl, (2,)),
835 "idl_passive": (do_idl_passive, (2,))}
836
837 command_name = args[0]
838 args = args[1:]
839 if command_name not in commands:
840 sys.stderr.write("%s: unknown command \"%s\" "
841 "(use --help for help)\n" % (ovs.util.PROGRAM_NAME,
842 command_name))
843 sys.exit(1)
844
845 func, n_args = commands[command_name]
846 if type(n_args) == tuple:
847 if len(args) < n_args[0]:
848 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
849 "only %d provided\n"
850 % (ovs.util.PROGRAM_NAME, command_name,
851 n_args, len(args)))
852 sys.exit(1)
853 elif type(n_args) == int:
854 if len(args) != n_args:
855 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
856 "provided\n"
857 % (ovs.util.PROGRAM_NAME, command_name,
858 n_args, len(args)))
859 sys.exit(1)
860 else:
861 assert False
862
863 func(*args)
864
865
866 if __name__ == '__main__':
867 try:
868 main(sys.argv)
869 except error.Error as e:
870 sys.stderr.write("%s\n" % e)
871 sys.exit(1)