3 # Copyright (c) 2017 eBay Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at:
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
24 from ovs.db import idl
25 from ovs import jsonrpc
26 from ovs.poller import Poller
27 from ovs.stream import Stream
29 print("ERROR: Please install the correct Open vSwitch python support")
30 print(" libraries (@VERSION@).")
31 print(" Alternatively, check that your PYTHONPATH is pointing to")
32 print(" the correct location.")
42 usage: %(argv0)s < FILE
43 where FILE is output from ovs-appctl ofproto/trace.
45 The following options are also available:
46 -h, --help display this help message
47 -V, --version display version information
48 --ovnsb=DATABASE use DATABASE as southbound DB
49 --ovnnb=DATABASE use DATABASE as northbound DB\
50 """ % {'argv0': argv0}
56 def wait_for_db_change(idl):
57 seq = idl.change_seqno
58 stop = time.time() + 10
59 while idl.change_seqno == seq and not idl.run():
63 if time.time() >= stop:
64 raise Exception('Retry Timeout')
66 def __init__(self, db_sock, schema_name):
67 self._db_sock = db_sock
69 schema = self._get_schema(schema_name)
71 self._idl_conn = idl.Idl(db_sock, schema)
72 OVSDB.wait_for_db_change(self._idl_conn) # Initial Sync with DB
74 def _get_schema(self, schema_name):
75 error, strm = Stream.open_block(Stream.open(self._db_sock))
77 raise Exception("Unable to connect to %s" % self._db_sock)
78 rpc = jsonrpc.Connection(strm)
79 req = jsonrpc.Message.create_request('get_schema', [schema_name])
80 error, resp = rpc.transact_block(req)
83 if error or resp.error:
84 raise Exception('Unable to retrieve schema.')
85 return idl.SchemaHelper(None, resp.result)
87 def get_table(self, table_name):
88 return self._idl_conn.tables[table_name]
90 def _find_row(self, table_name, find):
92 (row for row in self.get_table(table_name).rows.values()
95 def _find_row_by_name(self, table_name, value):
96 return self._find_row(table_name, lambda row: row.name == value)
98 def find_row_by_partial_uuid(self, table_name, value):
99 return self._find_row(table_name, lambda row: value in str(row.uuid))
102 def get_lflow_from_cookie(ovnsb_db, cookie):
103 return ovnsb_db.find_row_by_partial_uuid('Logical_Flow', cookie)
106 def print_lflow(lflow, prefix):
107 ldp_uuid = lflow.logical_datapath.uuid
108 ldp_name = str(lflow.logical_datapath.external_ids.get('name'))
110 print '%sLogical datapath: "%s" (%s) [%s]' % (prefix,
114 print "%sLogical flow: table=%s (%s), priority=%s, " \
115 "match=(%s), actions=(%s)" % (prefix,
117 lflow.external_ids.get('stage-name'),
119 str(lflow.match).strip('"'),
120 str(lflow.actions).strip('"'))
123 def print_lflow_nb_hint(lflow, prefix, ovnnb_db):
124 external_ids = lflow.external_ids
125 if external_ids.get('stage-name') in ['ls_in_acl',
127 acl_hint = external_ids.get('stage-hint')
130 acl = ovnnb_db.find_row_by_partial_uuid('ACL', acl_hint)
133 output = "%sACL: %s, priority=%s, " \
134 "match=(%s), %s" % (prefix,
137 acl.match.strip('"'),
146 options, args = getopt.gnu_getopt(sys.argv[1:], 'hV',
147 ['help', 'version', 'ovnsb=', 'ovnnb='])
148 except getopt.GetoptError, geo:
149 sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
155 for key, value in options:
156 if key in ['-h', '--help']:
158 elif key in ['-V', '--version']:
159 print "%s (Open vSwitch) @VERSION@" % argv0
160 elif key in ['--ovnsb']:
162 elif key in ['--ovnnb']:
168 sys.stderr.write("%s: non-option argument not supported "
169 "(use --help for help)\n" % argv0)
172 ovs_rundir = os.getenv('OVS_RUNDIR', '@RUNDIR@')
174 ovnsb_db = os.getenv('OVN_SB_DB')
176 ovnsb_db = 'unix:%s/ovnsb_db.sock' % ovs_rundir
179 ovnnb_db = os.getenv('OVN_NB_DB')
181 ovnnb_db = 'unix:%s/ovnnb_db.sock' % ovs_rundir
183 ovsdb_ovnsb = OVSDB(ovnsb_db, 'OVN_Southbound')
184 ovsdb_ovnnb = OVSDB(ovnnb_db, 'OVN_Northbound')
186 regex_cookie = re.compile(r'^.*cookie 0x([0-9a-fA-F]+)')
187 regex_table_id = re.compile(r'^[0-9]+\.')
190 line = sys.stdin.readline()
192 # print lflow info when the current flow block ends
193 if regex_table_id.match(line) or line.strip() == '':
194 lflow = get_lflow_from_cookie(ovsdb_ovnsb, cookie)
195 print_lflow(lflow, " * ")
196 print_lflow_nb_hint(lflow, " * ", ovsdb_ovnnb)
203 m = regex_cookie.match(line)
209 if __name__ == "__main__":