]> git.proxmox.com Git - mirror_ovs.git/blob - ovn/utilities/ovn-detrace.in
treewide: Convert leading tabs to spaces.
[mirror_ovs.git] / ovn / utilities / ovn-detrace.in
1 #! @PYTHON@
2 #
3 # Copyright (c) 2017 eBay Inc.
4 #
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:
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 import getopt
18 import os
19 import re
20 import sys
21 import time
22
23 try:
24 from ovs.db import idl
25 from ovs import jsonrpc
26 from ovs.poller import Poller
27 from ovs.stream import Stream
28 except Exception:
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.")
33 sys.exit(1)
34
35
36 argv0 = sys.argv[0]
37
38
39 def usage():
40 print """\
41 %(argv0)s:
42 usage: %(argv0)s < FILE
43 where FILE is output from ovs-appctl ofproto/trace.
44
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}
51 sys.exit(0)
52
53
54 class OVSDB(object):
55 @staticmethod
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():
60 poller = Poller()
61 idl.wait(poller)
62 poller.block()
63 if time.time() >= stop:
64 raise Exception('Retry Timeout')
65
66 def __init__(self, db_sock, schema_name):
67 self._db_sock = db_sock
68 self._txn = None
69 schema = self._get_schema(schema_name)
70 schema.register_all()
71 self._idl_conn = idl.Idl(db_sock, schema)
72 OVSDB.wait_for_db_change(self._idl_conn) # Initial Sync with DB
73
74 def _get_schema(self, schema_name):
75 error, strm = Stream.open_block(Stream.open(self._db_sock))
76 if error:
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)
81 rpc.close()
82
83 if error or resp.error:
84 raise Exception('Unable to retrieve schema.')
85 return idl.SchemaHelper(None, resp.result)
86
87 def get_table(self, table_name):
88 return self._idl_conn.tables[table_name]
89
90 def _find_row(self, table_name, find):
91 return next(
92 (row for row in self.get_table(table_name).rows.values()
93 if find(row)), None)
94
95 def _find_row_by_name(self, table_name, value):
96 return self._find_row(table_name, lambda row: row.name == value)
97
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))
100
101
102 def get_lflow_from_cookie(ovnsb_db, cookie):
103 return ovnsb_db.find_row_by_partial_uuid('Logical_Flow', cookie)
104
105
106 def print_lflow(lflow, prefix):
107 ldp_uuid = lflow.logical_datapath.uuid
108 ldp_name = str(lflow.logical_datapath.external_ids.get('name'))
109
110 print '%sLogical datapath: "%s" (%s) [%s]' % (prefix,
111 ldp_name,
112 ldp_uuid,
113 lflow.pipeline)
114 print "%sLogical flow: table=%s (%s), priority=%s, " \
115 "match=(%s), actions=(%s)" % (prefix,
116 lflow.table_id,
117 lflow.external_ids.get('stage-name'),
118 lflow.priority,
119 str(lflow.match).strip('"'),
120 str(lflow.actions).strip('"'))
121
122
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',
126 'ls_out_acl']:
127 acl_hint = external_ids.get('stage-hint')
128 if not acl_hint:
129 return
130 acl = ovnnb_db.find_row_by_partial_uuid('ACL', acl_hint)
131 if not acl:
132 return
133 output = "%sACL: %s, priority=%s, " \
134 "match=(%s), %s" % (prefix,
135 acl.direction,
136 acl.priority,
137 acl.match.strip('"'),
138 acl.action)
139 if acl.log:
140 output += ' (log)'
141 print output
142
143
144 def main():
145 try:
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))
150 sys.exit(1)
151
152 ovnsb_db = None
153 ovnnb_db = None
154
155 for key, value in options:
156 if key in ['-h', '--help']:
157 usage()
158 elif key in ['-V', '--version']:
159 print "%s (Open vSwitch) @VERSION@" % argv0
160 elif key in ['--ovnsb']:
161 ovnsb_db = value
162 elif key in ['--ovnnb']:
163 ovnnb_db = value
164 else:
165 sys.exit(0)
166
167 if len(args) != 0:
168 sys.stderr.write("%s: non-option argument not supported "
169 "(use --help for help)\n" % argv0)
170 sys.exit(1)
171
172 ovs_rundir = os.getenv('OVS_RUNDIR', '@RUNDIR@')
173 if not ovnsb_db:
174 ovnsb_db = os.getenv('OVN_SB_DB')
175 if not ovnsb_db:
176 ovnsb_db = 'unix:%s/ovnsb_db.sock' % ovs_rundir
177
178 if not ovnnb_db:
179 ovnnb_db = os.getenv('OVN_NB_DB')
180 if not ovnnb_db:
181 ovnnb_db = 'unix:%s/ovnnb_db.sock' % ovs_rundir
182
183 ovsdb_ovnsb = OVSDB(ovnsb_db, 'OVN_Southbound')
184 ovsdb_ovnnb = OVSDB(ovnnb_db, 'OVN_Northbound')
185
186 regex_cookie = re.compile(r'^.*cookie 0x([0-9a-fA-F]+)')
187 regex_table_id = re.compile(r'^[0-9]+\.')
188 cookie = None
189 while True:
190 line = sys.stdin.readline()
191 if cookie:
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)
197 cookie = None
198
199 print line.strip()
200 if line == "":
201 break
202
203 m = regex_cookie.match(line)
204 if not m:
205 continue
206 cookie = m.group(1)
207
208
209 if __name__ == "__main__":
210 main()
211
212
213 # Local variables:
214 # mode: python
215 # End: