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
|
#!/usr/bin/python
#
# Copyright 2008, Stone-IT
# Jasper Capel <capel@stone-it.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., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
import func_module
import os
class Bridge(func_module.FuncModule):
version = "0.0.1"
api_version = "0.0.1"
description = "Func module for Bridge management"
# A list of bridge names that should be ignored. You can use this if you
# have bridges that should never be touched by func.
# This should go the the module-specific configuration file in the future.
# Will ignore virbr0 by default, as it's managed by libvirtd, it's probably
# a bad idea to touch it.
ignorebridges = [ "virbr0" ]
brctl = "/usr/sbin/brctl"
ip = "/sbin/ip"
def list(self):
# Returns a dictionary. Elements look like this:
# key: bridgename, value: [ interface1, interface2, ..., interfacen ]
retlist = {}
command = self.brctl + " show"
fp = os.popen(command)
# Read output, discard the first line (header):
# Example output:
# bridge name bridge id STP enabled interfaces
# mgmtbr 8000.feffffffffff no vif12.0
# vif11.0
# netsbr 8000.feffffffffff no pbond1
# vif0.2
lines = fp.readlines()[1:]
fp.close()
curbr = ""
for line in lines:
elements = line.split()
if len(elements) > 1:
# Line containing a new bridge name + interface
curbr = elements[0]
if not curbr in self.ignorebridges:
if len(elements) == 3:
# This is a bridge without connected devices
retlist[elements[0]] = [ ]
elif len(elements) == 4:
# This is a bridge with one or more devices attached to
# it.
retlist[elements[0]] = [ elements[3] ]
elif len(elements) == 1:
# Dictionary key containing interface name should already
# exist, append the interface.
if not curbr in self.ignorebridges:
retlist[curbr].append(elements[0])
return retlist
def add_bridge(self, brname):
# Creates a bridge
if brname not in self.ignorebridges:
exitcode = os.spawnv(os.P_WAIT, self.brctl, [ self.brctl, "addbr", brname ] )
else:
exitcode = -1
return exitcode
def add_interface(self, brname, ifname):
# Adds an interface to a bridge
if brname not in self.ignorebridges:
exitcode = os.spawnv(os.P_WAIT, self.brctl, [ self.brctl, "addif", brname, ifname ] )
else:
exitcode = -1
return exitcode
def delete_bridge(self, brname):
# Deletes a bridge
if brname not in self.ignorebridges:
# This needs some more error checking. :)
exitcode = os.spawnv(os.P_WAIT, self.brctl, [ self.brctl, "delbr", brname ] )
else:
exitcode = -1
return exitcode
def delete_interface(self, brname, ifname):
# Deletes an interface from a bridge
if brname not in self.ignorebridges:
exitcode = os.spawnv(os.P_WAIT, self.brctl, [ self.brctl, "delif", brname, ifname ] )
else:
exitcode = -1
return exitcode
def add_promisc_bridge(self, brname, ifname):
# Creates a new bridge brname, attaches interface ifname to it and sets
# the MAC address of the connected interface to FE:FF:FF:FF:FF:FF so
# traffic can flow freely through the bridge. This is required for use
# with Xen.
addbrret = self.add_bridge(brname)
addifret = self.add_interface(brname,ifname)
# Set the MAC address of the interface we're adding to the bridge to
# FE:FF:FF:FF:FF:FF. This is consistent with the behaviour of the
# Xen network-bridge script.
setaddrret = os.spawnv(os.P_WAIT, self.ip, [ self.ip, "link", "set", ifname, "address", "fe:ff:ff:ff:ff:ff" ])
if addbrret or addifret or setaddrret:
return -1
else:
return 0
def updown_bridge(self, brname, up):
# Marks a bridge and all it's connected interfaces up or down (used
# internally)
if up:
updown = "up"
else:
updown = "down"
bridges = self.list()
if not brname in bridges:
# Bridge doesn't exist, or should be ignored.
return -1
interfaces = [ brname ]
for bridgemember in bridges[brname]:
interfaces.append(bridgemember)
exitcode = 0
for ifname in interfaces:
retcode = os.spawnv(os.P_WAIT, self.ip, [self.ip, "link", "set", ifname, updown ] )
if retcode != 0:
exitcode = retcode
return exitcode
def up_bridge(self, brname):
# Marks a bridge and all it's connected interfaces up
return self.updown_bridge(brname, 1)
def down_bridge(self, brname):
# Marks a bridge and all it's connected interfaces down
return self.updown_bridge(brname, 0)
|