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