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