OSDN Git Service

f59e3595f9178d7a3050acbfa897676d6c83b15f
[ti2/ti2.git] / linkpair / collect / agent / ovs_agent.py
1 # vim: tabstop=4 shiftwidth=4 softtabstop=4
2 # -*- coding: utf-8 -*-
3 #
4
5 __version__ = '1.1'
6
7 import re
8 from linkpair.device import Device
9 from linkpair.port import Port
10 from linkpair.collect.agent.base_agent import BaseAgent
11
12
13 class OVSAgent(BaseAgent):
14     '''
15     Open vSwitch Collector Agent
16     '''
17
18     PORT_TYPE_UNSPECIFIED = "UNSPECIFIED"
19     PORT_PEER_UNSPECIFIED = "UNSPECIFIED"
20
21     def run(self):
22         self.get_configuration()
23
24     def get_bridge_metadata(self, br):
25         br_meta = {}
26         br_meta["dpid"] = ""
27         br_meta["controller"] = ""
28         br_meta["manager"] = ""
29
30         res_ctl = self._runner.exec_cmd("ovs-vsctl get-controller " + br)
31         for ctl in res_ctl:
32             br_meta["controller"] = self._u.str_join(
33                 br_meta["controller"], ctl.strip(), ", ")
34
35         res_mgr = self._runner.exec_cmd("ovs-vsctl get-manager")
36         for mgr in res_mgr:
37             br_meta["manager"] = self._u.str_join(
38                 br_meta["manager"], mgr.strip(), ", ")
39
40         res_ofsw = self._runner.exec_cmd("ovs-ofctl show " + br)
41         for ofsw_spec in res_ofsw:
42             ofsw_spec = ofsw_spec.strip()
43             if self._u.d_push(re.search(r': dpid:(.*)', ofsw_spec)) is not None:
44                 br_meta["dpid"] = self._u.d_pop().group(1).strip()
45             elif self._u.d_push(re.search(r'n_tables:(.*), n_buffers:(.*)', ofsw_spec)) is not None:
46                 match = self._u.d_pop()
47                 br_meta["tables"] = match.group(1).strip()
48                 br_meta["buffers"] = match.group(2).strip()
49             elif self._u.d_push(re.search(r'capabilities:(.*)', ofsw_spec)) is not None:
50                 br_meta["capabilities"] = self._u.d_pop().group(1).strip()
51             elif self._u.d_push(re.search(r'actions:(.*)', ofsw_spec)) is not None:
52                 br_meta["actions"] = self._u.d_pop().group(1).strip()
53
54         return br_meta
55
56     def get_port_metadata(self, port):
57         port_meta = {}
58         res_ovsport = self._runner.exec_cmd("ovs-vsctl show")
59         for i in range(0, len(res_ovsport)):
60             port_start = res_ovsport[i].strip()
61             if self._u.d_push(re.search(r'Port "?%s"?' % port, port_start)) is not None:
62                 for j in range(i + 1, len(res_ovsport)):
63                     port_spec = res_ovsport[j].strip()
64                     if self._u.d_push(re.search(r'tag: (.*)', port_spec)) is not None:
65                         port_meta["tag"] = self._u.d_pop().group(1).strip()
66                     elif self._u.d_push(re.search(r'type: (.*)', port_spec)) is not None:
67                         port_meta["type"] = self._u.d_pop().group(1).strip()
68                     elif self._u.d_push(re.search(r'options: {(.*)}', port_spec)) is not None:
69                         port_options = self._u.d_pop().group(
70                             1).strip().split(",")
71                         for port_option in port_options:
72                             (opt_name, opt_value) = port_option.split("=")
73                             port_meta[opt_name] = opt_value
74                     elif self._u.d_push(re.search(r'Port "*', port_spec)) is not None:
75                         break
76
77         return port_meta
78
79     def get_port_type(self, port_meta):
80         if "type" in port_meta:
81             return port_meta["type"]
82         else:
83             return self.PORT_TYPE_UNSPECIFIED
84
85     def get_port_peer(self, port_meta):
86         if self.get_port_type(port_meta) == "patch":
87             return port_meta["peer"]
88         else:
89             return self.PORT_TYPE_UNSPECIFIED
90
91     def get_port_veth_peer(self, port_name):
92         port = self._cu.get_port(port_name)
93         if port != self._cu.PORT_NOT_FOUND:
94             port_meta = port.metadata
95             if "veth_peer" in port_meta:
96                 return port_meta["veth_peer"]
97             else:
98                 return self.PORT_PEER_UNSPECIFIED
99         else:
100             return self.PORT_PEER_UNSPECIFIED
101
102     def get_configuration(self):
103         patch_peers = {}
104         veth_peers = {}
105
106         result = self._runner.exec_cmd("ovs-vsctl list-br")
107         for br_src in result:
108             br_src = br_src.rstrip()
109             br_src_meta = self.get_bridge_metadata(br_src)
110             port_names = self._runner.exec_cmd(
111                 "ovs-vsctl list-ports " + br_src)
112             for port_name in port_names:
113                 port_name = port_name.rstrip()
114                 port_meta = self.get_port_metadata(port_name)
115
116                 # patch port
117                 if self.get_port_type(port_meta) == "patch":
118                     patch_src = port_name
119                     patch_dst = self.get_port_peer(port_meta)
120                     patch_peers[patch_src + ":" + patch_dst] = self.PEER_FOUND
121
122                     if patch_dst + ":" + patch_src in patch_peers:
123                         continue
124
125                     patch_src_meta = port_meta
126                     patch_dst_meta = self.get_port_metadata(patch_dst)
127                     result3 = self._runner.exec_cmd(
128                         "ovs-vsctl port-to-br " + patch_dst)
129                     if result3 is not None and len(result3) > 0:
130                         br_dst = result3[0].rstrip()
131                         br_dst_meta = self.get_bridge_metadata(br_dst)
132                         self._cu.add_linkpair(
133                             Device(br_src, Device.BR_TYPE, br_src_meta),
134                             Device(br_dst, Device.BR_TYPE, br_dst_meta),
135                             Port(patch_src, Port.DEFAULT_TYPE, patch_src_meta),
136                             Port(patch_dst, Port.DEFAULT_TYPE, patch_dst_meta),
137                             self._formatter.PATCH_FORMAT)
138                     else:
139                         self._cu.add_linkpair(
140                             Device(br_src, Device.BR_TYPE, br_src_meta),
141                             Device("NOT CONNECTED", Device.NOT_CONNECTED_TYPE),
142                             Port(patch_src, Port.DEFAULT_TYPE, patch_src_meta),
143                             Port(patch_dst, Port.DEFAULT_TYPE, patch_dst_meta),
144                             self._formatter.PATCH_FORMAT)
145
146                 # veth port
147                 elif self.get_port_veth_peer(port_name) != self.PORT_PEER_UNSPECIFIED:
148                     peer_src = port_name
149                     peer_dst = self.get_port_veth_peer(port_name)
150                     veth_peers[peer_src + ":" + peer_dst] = self.PEER_FOUND
151
152                     if peer_dst + ":" + peer_src in veth_peers:
153                         continue
154
155                     peer_src_meta = port_meta
156                     peer_dst_meta = self.get_port_metadata(peer_dst)
157                     result3 = self._runner.exec_cmd(
158                         "ovs-vsctl port-to-br " + peer_dst)
159                     if result3 is not None and len(result3) > 0:
160                         br_dst = result3[0].rstrip()
161                         br_dst_meta = self.get_bridge_metadata(br_dst)
162                         self._cu.add_linkpair(
163                             Device(br_src, Device.BR_TYPE, br_src_meta),
164                             Device(br_dst, Device.BR_TYPE, br_dst_meta),
165                             Port(peer_src, Port.DEFAULT_TYPE, peer_src_meta),
166                             Port(peer_dst, Port.DEFAULT_TYPE, peer_dst_meta),
167                             self._formatter.VETH_FORMAT)
168                     else:
169                         self._cu.add_linkpair(
170                             Device(br_src, Device.BR_TYPE, br_src_meta),
171                             Device("NOT CONNECTED", Device.NOT_CONNECTED_TYPE),
172                             Port(peer_src, Port.DEFAULT_TYPE, peer_src_meta),
173                             Port(peer_dst, Port.DEFAULT_TYPE, peer_dst_meta),
174                             self._formatter.VETH_FORMAT)
175
176                 # none patch port
177                 else:
178                     # NOT Internal Bridge Port.
179                     if self.get_port_type(port_meta) != "internal":
180
181                         # physical interface
182                         if self._u.d_push(re.match(r'^eth\d+$', port_name)) \
183                             or self._u.d_push(re.match(r'^em\d+$', port_name)) \
184                                 or self._u.d_push(re.match(r'^igb\d+$', port_name)) \
185                                 or self._u.d_push(re.match(r'^bond\d+$', port_name)):
186                             self._cu._port_to_br[port_name] = br_src
187                             self._cu.add_linkpair(
188                                 Device(br_src, Device.BR_TYPE, br_src_meta),
189                                 Device("Physical NW", Device.PHYNET_TYPE),
190                                 Port(port_name, Port.DEFAULT_TYPE, port_meta),
191                                 Port(""))
192
193                         # tunnel port
194                         elif self._u.d_push(re.match(r'(vxlan\d+)', port_name)) \
195                             or self._u.d_push(re.match(r'(gre\d+)', port_name)) \
196                                 or self._u.d_push(re.match(r'(gre-\d+)', port_name)):
197                             self._cu._port_to_br[port_name] = br_src
198                             self._cu.add_linkpair(
199                                 Device(br_src, Device.BR_TYPE, br_src_meta),
200                                 Device("OS Routing", Device.OS_ROUTE_TYPE),
201                                 Port(port_name, Port.DEFAULT_TYPE, port_meta),
202                                 Port(""))
203
204                         else:
205                             ## Other OVSPort
206                             self._cu._port_to_br[port_name] = br_src
207
208                     # internal
209                     elif self.get_port_type(port_meta) == "internal":
210                         if port_name in self._iface_to_nss:
211                             self._cu.add_linkpair(
212                                 Device(br_src, Device.BR_TYPE, br_src_meta),
213                                 Device(self._iface_to_nss[
214                                        port], Device.NAMESPACE_TYPE),
215                                 Port(port_name, Port.DEFAULT_TYPE, port_meta),
216                                 Port(""),
217                                 self._formatter.NAMESPACE_FORMAT)
218                         else:
219                             self._cu.add_linkpair(
220                                 Device(br_src, Device.BR_TYPE, br_src_meta),
221                                 Device(
222                                     "INTERNAL", Device.OS_ROUTE_TYPE),
223                                 Port(port_name, Port.DEFAULT_TYPE, port_meta),
224                                 Port(""))
225                     # else:
226                     #        ## Other OVSPort
227                     #        self._cu._port_to_br[port_name] = br_src
228                     else:
229                         continue