aboutsummaryrefslogtreecommitdiffstats
path: root/sos/plugins/openstack_neutron.py
blob: 36de7cc921077d137800cdc0169e868b82479534 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# Copyright (C) 2013 Red Hat, Inc., Brent Eagles <beagles@redhat.com>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import os
import re

from sos.plugins import Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin

# The Networking plugin includes most of what is needed from a snapshot
# of the networking, so we only need to focus on the parts that are specific
# to OpenStack Networking. The Process plugin should capture the dnsmasq
# command line. The libvirt plugin grabs the instance's XML definition which
# has the interface names for an instance. So what remains is relevant database
# info...


class Neutron(Plugin):
    """OpenStack Networking
    """
    plugin_name = "openstack_neutron"
    profiles = ('openstack',)

    option_list = [("log", "Gathers all Neutron logs", "slow", False),
                   ("quantum", "Overrides checks for newer Neutron components",
                    "fast", False)]

    component_name = "neutron"

    def setup(self):
        if not os.path.exists("/etc/neutron/") or self.get_option("quantum"):
            self.component_name = "quantum"

        self.add_copy_spec([
            "/etc/%s/" % self.component_name,
            "/var/log/%s/" % self.component_name
        ])

        self.netns_dumps()

    def netns_dumps(self):
        # It would've been beautiful if we could get parts of the networking
        # plugin to run in different namespaces. There are a couple of options
        # in the short term: create a local instance and "borrow" some of the
        # functionality, or simply copy some of the functionality.
        prefixes = ["qdhcp", "qrouter"]
        ip_netns_result = self.call_ext_prog("ip netns")
        if not (ip_netns_result['status'] == 0):
            return
        nslist = ip_netns_result['output']
        lease_directories = []
        if nslist:
            for nsname in nslist.splitlines():
                prefix, netid = nsname.split('-', 1)
                if len(netid) > 0 and prefix in prefixes:
                    self.ns_gather_data(nsname)
                    lease_directories.append(
                        "/var/lib/%s/dhcp/%s/" %
                        (self.component_name, netid))
            self.add_copy_spec(lease_directories)

    # TODO: Refactor! Copied from Networking plugin.
    def get_interface_name(self, ip_addr_out):
        """Return a dictionary for which key are interface name according to
        the output of ifconifg-a stored in ifconfig_file.
        """
        out = {}
        for line in ip_addr_out.splitlines():
            match = re.match('.*link/ether', line)
            if match:
                int = match.string.split(':')[1].lstrip()
                out[int] = True
        return out

    def ns_gather_data(self, nsname):
        cmd_prefix = "ip netns exec %s " % nsname
        self.add_cmd_output([
            cmd_prefix + "iptables-save",
            cmd_prefix + "ifconfig -a",
            cmd_prefix + "route -n"
        ])
        # borrowed from networking plugin
        ip_addr_result = self.call_ext_prog(cmd_prefix + "ip -o addr")
        if ip_addr_result['status'] == 0:
            for eth in self.get_interface_name(ip_addr_result['output']):
                # Most, if not all, IFs in the namespaces are going to be
                # virtual. The '-a', '-c' and '-g' options are not likely to be
                # supported so these ops are not copied from the network
                # plugin.
                self.add_cmd_output([
                    cmd_prefix + "ethtool "+eth,
                    cmd_prefix + "ethtool -i "+eth,
                    cmd_prefix + "ethtool -k "+eth,
                    cmd_prefix + "ethtool -S "+eth
                ])

        # As all of the bridges are in the "global namespace", we do not need
        # to gather info on them.

    def gen_pkg_tuple(self, packages):
        names = []
        for p in packages:
            names.append(p % {"comp": self.component_name})
        return tuple(names)


class DebianNeutron(Neutron, DebianPlugin, UbuntuPlugin):
    package_list_template = [
        '%(comp)s-common',
        '%(comp)s-plugin-cisco',
        '%(comp)s-plugin-linuxbridge-agent',
        '%(comp)s-plugin-nicira',
        '%(comp)s-plugin-openvswitch',
        '%(comp)s-plugin-openvswitch-agent',
        '%(comp)s-plugin-ryu',
        '%(comp)s-plugin-ryu-agent',
        '%(comp)s-server',
        'python-%(comp)s',
        'python-%(comp)sclient'
    ]

    def check_enabled(self):
        return self.is_installed("%s-common" % self.component_name)

    def setup(self):
        super(DebianNeutron, self).setup()
        self.packages = self.gen_pkg_tuple(self.package_list_template)
        self.add_copy_spec("/etc/sudoers.d/%s_sudoers" % self.component_name)


class RedHatNeutron(Neutron, RedHatPlugin):

    package_list_template = [
        'openstack-%(comp)s',
        'openstack-%(comp)s-linuxbridge'
        'openstack-%(comp)s-metaplugin',
        'openstack-%(comp)s-openvswitch',
        'openstack-%(comp)s-bigswitch',
        'openstack-%(comp)s-brocade',
        'openstack-%(comp)s-cisco',
        'openstack-%(comp)s-hyperv',
        'openstack-%(comp)s-midonet',
        'openstack-%(comp)s-nec'
        'openstack-%(comp)s-nicira',
        'openstack-%(comp)s-plumgrid',
        'openstack-%(comp)s-ryu',
        'python-%(comp)s',
        'python-%(comp)sclient'
    ]

    def check_enabled(self):
        return self.is_installed("openstack-%s" % self.component_name)

    def setup(self):
        super(RedHatNeutron, self).setup()
        self.packages = self.gen_pkg_tuple(self.package_list_template)
        self.add_copy_spec("/etc/sudoers.d/%s-rootwrap" % self.component_name)

# vim: set et ts=4 sw=4 :