OSDN Git Service

add LinuxBridge, OVS, LibVirt agents
authort.moriyama <t.moriyama@users.sourceforge.jp>
Fri, 19 Apr 2013 09:23:03 +0000 (18:23 +0900)
committert.moriyama <t.moriyama@users.sourceforge.jp>
Fri, 19 Apr 2013 09:23:03 +0000 (18:23 +0900)
linkpair/collect/agent/libvirt_agent.py [new file with mode: 0755]
linkpair/collect/agent/linuxbridge_agent.py [new file with mode: 0755]
linkpair/collect/agent/ovs_agent.py [new file with mode: 0755]

diff --git a/linkpair/collect/agent/libvirt_agent.py b/linkpair/collect/agent/libvirt_agent.py
new file mode 100755 (executable)
index 0000000..433594c
--- /dev/null
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+
+__version__ = '1.1'
+
+import sys
+import os
+import re
+from xml.dom import minidom
+from subprocess import Popen, PIPE
+from socket import gethostname
+import shlex
+import libvirt
+from linkpair.device import Device
+from linkpair.port import Port
+from linkpair.linkpair import LinkPair
+from linkpair.collect.utils import CollectUtils
+from linkpair.collect.agent.commandrunner import CommandRunner
+from linkpair.formatter.grapheasy import GraphEasyFormatter
+from linkpair.commonutils import CommonUtils
+
+
+class LibvirtAgent(object):
+    '''
+    Libvirt Collector Agent
+    '''
+
+    def __init__(self, runner, cu, linkpairs, port_to_br, iface_to_nss, remote_desc, formatter=GraphEasyFormatter()):
+        self._runner = runner
+        self._cu = cu
+        self._linkpairs = linkpairs
+        self._port_to_br = port_to_br
+        self._iface_to_nss = iface_to_nss
+        self._remote_desc = remote_desc
+        self._u = CommonUtils()
+
+        ''' set parameters '''
+        self._formatter = formatter
+
+    def run(self):
+        self.pick_libvirt_configuration()
+
+    def pick_libvirt_configuration(self):
+        virt_conn = self.get_libvirt_conn()
+        for id in virt_conn.listDomainsID():
+            vm = virt_conn.lookupByID(id)
+            vmXMLDesc = minidom.parseString(vm.XMLDesc(0))
+            for iface in vmXMLDesc.getElementsByTagName("interface"):
+                [device, bridge] = self.pick_libvirt_iface_configuration(iface)
+                mac = iface.getElementsByTagName(
+                    "mac")[0].getAttribute("address")
+                device = iface.getElementsByTagName(
+                    "target")[0].getAttribute("dev")
+                bridge = self.regist_to_port2br(device, bridge)
+                self._cu.add_linkpair(
+                    Device(str(vm.name()), Device.VM_TYPE),
+                    Device(bridge, Device.BR_TYPE),
+                    Port(device),
+                    Port(""))
+
+    def pick_libvirt_iface_configuration(self, iface):
+        ifaceType = iface.getAttribute("type")
+        bridge = ""
+        device = ""
+        if ifaceType == "network":
+            network = iface.getElementsByTagName(
+                "source")[0].getAttribute("network")
+            netXMLDesc = minidom.parseString(
+                virt_conn.networkLookupByName(network).XMLDesc(0))
+            bridge = netXMLDesc.getElementsByTagName(
+                "bridge")[0].getAttribute("name")
+        elif ifaceType == "bridge":
+            bridge = iface.getElementsByTagName(
+                "source")[0].getAttribute("bridge")
+        return [device, bridge]
+
+    def get_libvirt_conn(self):
+        if self._remote_desc is not None:
+            conn = libvirt.open("qemu+ssh://" + self._remote_desc + "/system")
+        else:
+            conn = libvirt.open("qemu:///system")
+        return conn
diff --git a/linkpair/collect/agent/linuxbridge_agent.py b/linkpair/collect/agent/linuxbridge_agent.py
new file mode 100755 (executable)
index 0000000..92fa2d1
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+
+__version__ = '1.1'
+
+import sys
+import os
+import re
+from xml.dom import minidom
+from subprocess import Popen, PIPE
+from socket import gethostname
+from linkpair.device import Device
+from linkpair.port import Port
+from linkpair.linkpair import LinkPair
+from linkpair.collect.utils import CollectUtils
+from linkpair.collect.agent.commandrunner import CommandRunner
+from linkpair.formatter.grapheasy import GraphEasyFormatter
+from linkpair.commonutils import CommonUtils
+
+
+class LinuxBridgeAgent(object):
+    '''
+    Linux bridge Collector Agent
+    '''
+
+    PEER_FOUND = 1
+
+    def __init__(self, runner, cu, linkpairs, port_to_br, iface_to_nss, formatter=GraphEasyFormatter()):
+        self._runner = runner
+        self._cu = cu
+        self._linkpairs = linkpairs
+        self._port_to_br = port_to_br
+        self._iface_to_nss = iface_to_nss
+        self._u = CommonUtils()
+
+        ''' set parameters '''
+        self._formatter = formatter
+
+    def run(self):
+           self.pick_bridge_configuration()
+    
+    def pick_bridge_configuration(self):
+        br_name = ""
+        result = self._runner.exec_cmd("brctl show")
+        for br_line in result:
+            br_line = br_line.rstrip()
+            if self._u.d_push(re.match(r'^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$', br_line)) is not None:
+                match = self._u.d_pop()
+                br_name = match.group(1)
+                port = match.group(4)
+                if port not in self._port_to_br and br_name != "":
+                    self._port_to_br[port] = br_name
+                    ## for OpenStack quntum...
+                    if self._u.d_push(re.match(r'^qvb(.+)', port)):
+                        quantum_idprefix = self._u.d_pop().group(1)
+                        if "qvo" + quantum_idprefix in self._port_to_br:
+                            self._cu.add_linkpair(
+                                Device(br_name, Device.BR_TYPE),
+                                Device(self._port_to_br[
+                                       "qvo" + quantum_idprefix], Device.BR_TYPE),
+                                Port(port),
+                                Port("qvo" + quantum_idprefix),
+                                self._formatter.VETH_FORMAT)
+                    else:
+                        self._cu.add_linkpair(
+                            Device(br_name),
+                            Device("INTERNAL", Device.OS_ROUTE_TYPE),
+                            Port(port),
+                            Port(""))
+    #            else:
+    #                print self._port_to_br.keys()
+    #                if self._u.d_push(re.match(r'^qvo(.+)', port)):
+    #                    continue
+    #                add_linkpair(self.DEFAULT_FORMAT, br_name, self.DEFAULT_TYPE, port, \
+    #                  "INTERNAL", self.OS_ROUTE_TYPE )
+
+            elif self._u.d_push(re.match(r'^\s+(\S+)$', br_line)) is not None:
+                port = self._u.d_pop().group(1)
+                if port not in self._port_to_br and br_name != "":
+                    self._port_to_br[port] = br_name
+                    ## for OpenStack quntum...
+                    if self._u.d_push(re.match(r'^qvb(.+)', port)):
+                        quantum_idprefix = self._u.d_pop().group(1)
+                        if "qvo" + quantum_idprefix in self._port_to_br:
+                            self._cu.add_linkpair(
+                                Device(br_name, Device.BR_TYPE),
+                                Device(self._port_to_br[
+                                       "qvo" + quantum_idprefix], Device.BR_TYPE),
+                                Port(port),
+                                Port("qvo" + quantum_idprefix),
+                                self._formatter.VETH_FORMAT)
+                    else:
+                        if self._u.d_push(re.match(r'^qvo(.+)', port)):
+                            continue
+                        self._cu.add_linkpair(
+                            Device(br_name),
+                            Device("INTERNAL", Device.OS_ROUTE_TYPE),
+                            Port(port),
+                            Port(""))
+
diff --git a/linkpair/collect/agent/ovs_agent.py b/linkpair/collect/agent/ovs_agent.py
new file mode 100755 (executable)
index 0000000..16c4fb2
--- /dev/null
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+
+__version__ = '1.1'
+
+import sys
+import os
+import re
+from xml.dom import minidom
+from subprocess import Popen, PIPE
+from socket import gethostname
+from linkpair.device import Device
+from linkpair.port import Port
+from linkpair.linkpair import LinkPair
+from linkpair.collect.utils import CollectUtils
+from linkpair.collect.agent.commandrunner import CommandRunner
+from linkpair.formatter.grapheasy import GraphEasyFormatter
+from linkpair.commonutils import CommonUtils
+
+
+class OVSAgent(object):
+    '''
+    Open vSwitch Collector Agent
+    '''
+
+    PEER_FOUND = 1
+
+    def __init__(self, runner, cu, linkpairs, port_to_br, iface_to_nss, formatter=GraphEasyFormatter()):
+        self._runner = runner
+        self._cu = cu
+        self._linkpairs = linkpairs
+        self._port_to_br = port_to_br
+        self._iface_to_nss = iface_to_nss
+        self._u = CommonUtils()
+
+        ''' set parameters '''
+        self._formatter = formatter
+
+    def run(self):
+           self.get_configuration()
+    
+    def get_configuration(self):
+        patch_peers = {}
+
+        result = self._runner.exec_cmd("ovs-vsctl list-br")
+        for br_src in result:
+            br_src = br_src.rstrip()
+            result2 = self._runner.exec_cmd("ovs-dpctl show " + br_src)
+            for port_desc in result2:
+                port_desc = port_desc.rstrip()
+                if self._u.d_push(
+                    re.search(r'port \d+: (.*?) \(patch: peer=(.*?)\)',
+                              port_desc)) is not None:
+                    match = self._u.d_pop()
+                    patch_src = match.group(1)
+                    patch_dst = match.group(2)
+                    patch_peers[patch_src + ":" + patch_dst] = self.PEER_FOUND
+
+                    if patch_dst + ":" + patch_src in patch_peers:
+                        continue
+
+                    result3 = self._runner.exec_cmd(
+                        "ovs-vsctl port-to-br " + patch_dst)
+                    if result3 is not None and len(result3) > 0:
+                        br_dst = result3[0].rstrip()
+                        self._cu.add_linkpair(
+                            Device(br_src, Device.BR_TYPE),
+                            Device(br_dst, Device.BR_TYPE),
+                            Port(patch_src),
+                            Port(patch_dst),
+                            self._formatter.PATCH_FORMAT)
+                    else:
+                        self._cu.add_linkpair(
+                            Device(br_src, Device.BR_TYPE),
+                            Device("NOT CONNECTED", Device.NOT_CONNECTED_TYPE),
+                            Port(patch_src),
+                            Port(patch_dst),
+                            self._formatter.PATCH_FORMAT)
+
+                else:
+                    # Internal OVSPort.
+                    if self._u.d_push(
+                        re.search(
+                            r'port \d+: ' + br_src + ' \(internal\)',
+                            port_desc)) is None:
+                        if self._u.d_push(re.search(r'port \d+: (.*)', port_desc)) is not None:
+                            port = self._u.d_pop().group(1).rstrip()
+                            if self._u.d_push(re.match(r'^eth\d+$', port)) \
+                                or self._u.d_push(re.match(r'^em\d+$', port)) \
+                                    or self._u.d_push(re.match(r'^igb\d+$', port)):
+                                self._cu._port_to_br[port] = br_src
+                                self._cu.add_linkpair(
+                                    Device(br_src, Device.BR_TYPE),
+                                    Device("Physical NW", Device.PHYNET_TYPE),
+                                    Port(port),
+                                    Port(""))
+                            elif self._u.d_push(re.match(r'(vxlan\d+)', port)) \
+                                or self._u.d_push(re.match(r'(gre\d+)', port)) \
+                                    or self._u.d_push(re.match(r'(gre-\d+)', port)):
+                                port2 = self._u.d_pop().group(1)
+                                self._cu._port_to_br[port2] = br_src
+                                self._cu.add_linkpair(
+                                    Device(br_src, Device.BR_TYPE),
+                                    Device("OS Routing", Device.OS_ROUTE_TYPE),
+                                    Port(port),
+                                    Port(""))
+                            elif re.search(r' \(internal\)', port):
+                                port = re.sub(r' \(internal\)', '', port)
+                                if port in self._iface_to_nss:
+                                    self._cu.add_linkpair(
+                                        Device(br_src, Device.BR_TYPE),
+                                        Device(self._iface_to_nss[
+                                               port], Device.NAMESPACE_TYPE),
+                                        Port(port),
+                                        Port(""),
+                                        self._formatter.NAMESPACE_FORMAT)
+                                else:
+                                    self._cu.add_linkpair(
+                                        Device(br_src, Device.BR_TYPE),
+                                        Device(
+                                            "INTERNAL", Device.OS_ROUTE_TYPE),
+                                        Port(port),
+                                        Port(""))
+                            else:
+                                ## Other OVSPort
+                                self._cu._port_to_br[port] = br_src
+                        else:
+                            continue