2 # -*- coding: utf-8 -*-
10 from xml.dom import minidom
11 from subprocess import Popen, PIPE
12 from socket import gethostname
15 from linkpair.device import Device
16 from linkpair.port import Port
17 from linkpair.linkpair import LinkPair
18 from linkpair.formatter.grapheasy import GraphEasyFormatter
19 from linkpair.commonutils import CommonUtils
20 from linkpair.dbutils import DBUtils
21 from linkpair.collect.utils import CollectUtils
22 from linkpair.collect.agent.commandrunner import CommandRunner
23 from linkpair.collect.agent.namespace import NamespaceAgent
24 from linkpair.collect.agent.ovs import OVSAgent
27 class Collector(object):
28 '''LinkpPair collector
30 This class gets the LinkPair information from LinuxBridge and Open vSwitch and libvirt
35 def __init__(self, remote_desc, dbu, formatter=GraphEasyFormatter()):
38 self._iface_to_nss = {}
39 self._u = CommonUtils()
41 self._db_enable = False
43 self._remote_desc = remote_desc
44 self._ssh_username = ""
45 self._ssh_hostname = ""
46 self._ssh_hostport = 22
47 self._remote_password = ""
48 self._remote_sshkey = ""
49 self._ssh_keyauth = False
50 self._ssh_passauth = False
52 ''' set parameters '''
53 [self._ssh_username, self._ssh_hostname, self._ssh_hostport] = self._u.parse_remote_desc(remote_desc)
55 self._formatter = formatter
56 self._runner = CommandRunner(self._remote_desc)
59 self._cu = CollectUtils(self._linkpairs, self._port_to_br, self._iface_to_nss, self._dbu, self._formatter)
60 #self.map_port_to_namespace()
61 namespace_agent = NamespaceAgent(self._runner, self._cu, self._iface_to_nss)
63 #self.pick_ovs_configuration()
64 ovs_agent = OVSAgent(self._runner, self._cu, self._linkpairs, self._port_to_br, self._iface_to_nss, self._formatter)
66 self.pick_bridge_configuration()
67 self.pick_libvirt_configuration()
69 def get_linkpairs(self):
70 return self._linkpairs
72 # def add_linkpair(self, dev1, dev2, port1, port2, format=""):
74 # format = self._formatter.DEFAULT_FORMAT
75 # self._linkpairs.append(
76 # LinkPair(dev1, dev2, port1, port2, format))
77 ## if self._dbu.enable_db:
78 ## insert_record(fmt, src, src_style, label, dst, dst_style)
81 # def drop_linkpairs(self):
82 # self._linkpairs = []
84 def pick_libvirt_configuration(self):
85 virt_conn = self.get_libvirt_conn()
86 for id in virt_conn.listDomainsID():
87 vm = virt_conn.lookupByID(id)
88 vmXMLDesc = minidom.parseString(vm.XMLDesc(0))
89 for iface in vmXMLDesc.getElementsByTagName("interface"):
90 [device, bridge] = self.pick_libvirt_iface_configuration(iface)
91 mac = iface.getElementsByTagName(
92 "mac")[0].getAttribute("address")
93 device = iface.getElementsByTagName(
94 "target")[0].getAttribute("dev")
95 bridge = self.regist_to_port2br(device, bridge)
96 self._cu.add_linkpair(
97 Device(str(vm.name()), Device.VM_TYPE),
98 Device(bridge, Device.BR_TYPE),
102 def pick_libvirt_iface_configuration(self, iface):
103 ifaceType = iface.getAttribute("type")
106 if ifaceType == "network":
107 network = iface.getElementsByTagName(
108 "source")[0].getAttribute("network")
109 netXMLDesc = minidom.parseString(
110 virt_conn.networkLookupByName(network).XMLDesc(0))
111 bridge = netXMLDesc.getElementsByTagName(
112 "bridge")[0].getAttribute("name")
113 elif ifaceType == "bridge":
114 bridge = iface.getElementsByTagName(
115 "source")[0].getAttribute("bridge")
116 return [device, bridge]
118 # def regist_to_port2br(self, device, bridge):
119 # if device in self._port_to_br:
121 # return self._port_to_br[device]
125 # self._port_to_br[device] = bridge
128 # def map_port_to_namespace(self):
129 # result = self._runner.exec_cmd("ip netns")
133 # result2 = self._runner.exec_cmd("ip netns exec " + ns + " ip link show")
134 # for linkpair_out in result2:
135 # linkpair_out = linkpair_out.rstrip()
136 # match = re.match(r'\d+: (.*?): ', linkpair_out)
137 # if match is not None and match.group(1) != 'lo':
138 # self._iface_to_nss[match.group(1).rstrip()] = ns
140 def pick_bridge_configuration(self):
142 result = self._runner.exec_cmd("brctl show")
143 for br_line in result:
144 br_line = br_line.rstrip()
145 if self._u.d_push(re.match(r'^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$', br_line)) is not None:
146 match = self._u.d_pop()
147 br_name = match.group(1)
148 port = match.group(4)
149 if port not in self._port_to_br and br_name != "":
150 self._port_to_br[port] = br_name
151 ## for OpenStack quntum...
152 if self._u.d_push(re.match(r'^qvb(.+)', port)):
153 quantum_idprefix = self._u.d_pop().group(1)
154 if "qvo" + quantum_idprefix in self._port_to_br:
155 self._cu.add_linkpair(
156 Device(br_name, Device.BR_TYPE),
157 Device(self._port_to_br[
158 "qvo" + quantum_idprefix], Device.BR_TYPE),
160 Port("qvo" + quantum_idprefix),
161 self._formatter.VETH_FORMAT)
163 self._cu.add_linkpair(
165 Device("INTERNAL", Device.OS_ROUTE_TYPE),
169 # print self._port_to_br.keys()
170 # if self._u.d_push(re.match(r'^qvo(.+)', port)):
172 # add_linkpair(self.DEFAULT_FORMAT, br_name, self.DEFAULT_TYPE, port, \
173 # "INTERNAL", self.OS_ROUTE_TYPE )
175 elif self._u.d_push(re.match(r'^\s+(\S+)$', br_line)) is not None:
176 port = self._u.d_pop().group(1)
177 if port not in self._port_to_br and br_name != "":
178 self._port_to_br[port] = br_name
179 ## for OpenStack quntum...
180 if self._u.d_push(re.match(r'^qvb(.+)', port)):
181 quantum_idprefix = self._u.d_pop().group(1)
182 if "qvo" + quantum_idprefix in self._port_to_br:
183 self._cu.add_linkpair(
184 Device(br_name, Device.BR_TYPE),
185 Device(self._port_to_br[
186 "qvo" + quantum_idprefix], Device.BR_TYPE),
188 Port("qvo" + quantum_idprefix),
189 self._formatter.VETH_FORMAT)
191 if self._u.d_push(re.match(r'^qvo(.+)', port)):
193 self._cu.add_linkpair(
195 Device("INTERNAL", Device.OS_ROUTE_TYPE),
199 def pick_ovs_configuration(self):
202 result = self._runner.exec_cmd("ovs-vsctl list-br")
203 for br_src in result:
204 br_src = br_src.rstrip()
205 result2 = self._runner.exec_cmd("ovs-dpctl show " + br_src)
206 for port_desc in result2:
207 port_desc = port_desc.rstrip()
209 re.search(r'port \d+: (.*?) \(patch: peer=(.*?)\)',
210 port_desc)) is not None:
211 match = self._u.d_pop()
212 patch_src = match.group(1)
213 patch_dst = match.group(2)
214 patch_peers[patch_src + ":" + patch_dst] = self.PEER_FOUND
216 if patch_dst + ":" + patch_src in patch_peers:
219 result3 = self._runner.exec_cmd(
220 "ovs-vsctl port-to-br " + patch_dst)
221 if result3 is not None and len(result3) > 0:
222 br_dst = result3[0].rstrip()
223 self._cu.add_linkpair(
224 Device(br_src, Device.BR_TYPE),
225 Device(br_dst, Device.BR_TYPE),
228 self._formatter.PATCH_FORMAT)
230 self._cu.add_linkpair(
231 Device(br_src, Device.BR_TYPE),
232 Device("NOT CONNECTED", Device.NOT_CONNECTED_TYPE),
235 self._formatter.PATCH_FORMAT)
241 r'port \d+: ' + br_src + ' \(internal\)',
243 if self._u.d_push(re.search(r'port \d+: (.*)', port_desc)) is not None:
244 port = self._u.d_pop().group(1).rstrip()
245 if self._u.d_push(re.match(r'^eth\d+$', port)) \
246 or self._u.d_push(re.match(r'^em\d+$', port)) \
247 or self._u.d_push(re.match(r'^igb\d+$', port)):
248 self._port_to_br[port] = br_src
249 self._cu.add_linkpair(
250 Device(br_src, Device.BR_TYPE),
251 Device("Physical NW", Device.PHYNET_TYPE),
254 elif self._u.d_push(re.match(r'(vxlan\d+)', port)) \
255 or self._u.d_push(re.match(r'(gre\d+)', port)) \
256 or self._u.d_push(re.match(r'(gre-\d+)', port)):
257 port2 = self._u.d_pop().group(1)
258 self._port_to_br[port2] = br_src
259 self._cu.add_linkpair(
260 Device(br_src, Device.BR_TYPE),
261 Device("OS Routing", Device.OS_ROUTE_TYPE),
264 elif re.search(r' \(internal\)', port):
265 port = re.sub(r' \(internal\)', '', port)
266 if port in self._iface_to_nss:
267 self._cu.add_linkpair(
268 Device(br_src, Device.BR_TYPE),
269 Device(self._iface_to_nss[
270 port], Device.NAMESPACE_TYPE),
273 self._formatter.NAMESPACE_FORMAT)
275 self._cu.add_linkpair(
276 Device(br_src, Device.BR_TYPE),
278 "INTERNAL", Device.OS_ROUTE_TYPE),
283 self._port_to_br[port] = br_src
287 def get_libvirt_conn(self):
288 if self._remote_desc is not None:
289 conn = libvirt.open("qemu+ssh://" + self._remote_desc + "/system")
291 conn = libvirt.open("qemu:///system")
294 def set_remote_sshkey(self, remote_sshkey):
295 self._runner.set_remote_sshkey(remote_sshkey)
297 def set_remote_password(self, remote_password):
298 self._runner.set_remote_password(remote_password)