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