12
12
# License for the specific language governing permissions and limitations
13
13
# under the License.
18
from oslo_log import log as logging
18
20
from neutron.agent.l3 import link_local_allocator as lla
21
from neutron.agent.l3 import namespaces
19
22
from neutron.agent.linux import ip_lib
20
23
from neutron.agent.linux import iptables_manager
21
24
from neutron.common import utils as common_utils
22
from neutron.i18n import _LE
23
from neutron.openstack.common import log as logging
25
26
LOG = logging.getLogger(__name__)
27
28
FIP_NS_PREFIX = 'fip-'
28
29
FIP_EXT_DEV_PREFIX = 'fg-'
29
30
FIP_2_ROUTER_DEV_PREFIX = 'fpr-'
30
ROUTER_2_FIP_DEV_PREFIX = 'rfp-'
31
ROUTER_2_FIP_DEV_PREFIX = namespaces.ROUTER_2_FIP_DEV_PREFIX
31
32
# Route Table index for FIPs
33
34
FIP_LL_SUBNET = '169.254.30.0/23'
36
37
FIP_PR_END = FIP_PR_START + 40000
39
class FipNamespace(object):
40
def __init__(self, ext_net_id, agent_conf, driver, root_helper, use_ipv6):
40
class FipNamespace(namespaces.Namespace):
42
def __init__(self, ext_net_id, agent_conf, driver, use_ipv6):
43
name = FIP_NS_PREFIX + ext_net_id
44
super(FipNamespace, self).__init__(
45
name, agent_conf, driver, use_ipv6)
41
47
self._ext_net_id = ext_net_id
42
48
self.agent_conf = agent_conf
43
49
self.driver = driver
44
self.root_helper = root_helper
45
50
self.use_ipv6 = use_ipv6
46
51
self.agent_gateway_port = None
47
52
self._subscribers = set()
48
53
self._rule_priorities = set(range(FIP_PR_START, FIP_PR_END))
49
54
self._iptables_manager = iptables_manager.IptablesManager(
50
root_helper=self.root_helper,
51
55
namespace=self.get_name(),
52
56
use_ipv6=self.use_ipv6)
53
57
path = os.path.join(agent_conf.state_path, 'fip-linklocal-networks')
54
58
self.local_subnets = lla.LinkLocalAllocator(path, FIP_LL_SUBNET)
59
self.destroyed = False
56
61
def get_name(self):
57
62
return (FIP_NS_PREFIX + self._ext_net_id)
86
91
def _gateway_added(self, ex_gw_port, interface_name):
87
92
"""Add Floating IP gateway port."""
88
93
ns_name = self.get_name()
89
if not ip_lib.device_exists(interface_name,
90
root_helper=self.root_helper,
94
if not ip_lib.device_exists(interface_name, namespace=ns_name):
92
95
self.driver.plug(ex_gw_port['network_id'],
105
108
ip_lib.send_gratuitous_arp(ns_name,
108
self.agent_conf.send_arp_for_ha,
111
self.agent_conf.send_arp_for_ha)
111
113
gw_ip = ex_gw_port['subnet']['gateway_ip']
113
ipd = ip_lib.IPDevice(interface_name,
115
ipd = ip_lib.IPDevice(interface_name, namespace=ns_name)
116
116
ipd.route.add_gateway(gw_ip)
118
118
cmd = ['sysctl', '-w', 'net.ipv4.conf.%s.proxy_arp=1' % interface_name]
119
119
# TODO(Carl) mlavelle's work has self.ip_wrapper
120
ip_wrapper = ip_lib.IPWrapper(self.root_helper, namespace=ns_name)
120
ip_wrapper = ip_lib.IPWrapper(namespace=ns_name)
121
121
ip_wrapper.netns.execute(cmd, check_exit_code=False)
123
123
def create(self):
124
124
# TODO(Carl) Get this functionality from mlavelle's namespace baseclass
125
ip_wrapper_root = ip_lib.IPWrapper(self.root_helper)
125
ip_wrapper_root = ip_lib.IPWrapper()
126
126
ip_wrapper = ip_wrapper_root.ensure_namespace(self.get_name())
127
127
ip_wrapper.netns.execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'])
128
128
if self.use_ipv6:
134
134
'-j CT --notrack')
135
135
self._iptables_manager.apply()
139
# TODO(carl) Reconcile this with mlavelle's namespace work
140
# TODO(carl) mlavelle's work has self.ip_wrapper
141
ip_wrapper = ip_lib.IPWrapper(self.root_helper, namespace=ns)
138
self.destroyed = True
139
ip_wrapper = ip_lib.IPWrapper(namespace=self.name)
142
140
for d in ip_wrapper.get_devices(exclude_loopback=True):
143
141
if d.name.startswith(FIP_2_ROUTER_DEV_PREFIX):
144
142
# internal link between IRs and FIP NS
150
148
ext_net_bridge = self.agent_conf.external_network_bridge
151
149
self.driver.unplug(d.name,
152
150
bridge=ext_net_bridge,
154
152
prefix=FIP_EXT_DEV_PREFIX)
155
LOG.debug('DVR: destroy fip ns: %s', ns)
153
self.agent_gateway_port = None
156
155
# TODO(mrsmith): add LOG warn if fip count != 0
157
if self.agent_conf.router_delete_namespaces:
159
ip_wrapper.netns.delete(ns)
161
LOG.exception(_LE('Failed trying to delete namespace: %s'), ns)
163
self.agent_gateway_port = None
156
LOG.debug('DVR: destroy fip ns: %s', self.name)
157
super(FipNamespace, self).delete()
165
159
def create_gateway_port(self, agent_gateway_port):
166
160
"""Create Floating IP gateway port.
179
173
def _internal_ns_interface_added(self, ip_cidr,
180
174
interface_name, ns_name):
181
ip_wrapper = ip_lib.IPWrapper(self.root_helper, namespace=ns_name)
175
ip_wrapper = ip_lib.IPWrapper(namespace=ns_name)
182
176
ip_wrapper.netns.execute(['ip', 'addr', 'add',
183
177
ip_cidr, 'dev', interface_name])
192
186
if ri.rtr_fip_subnet is None:
193
187
ri.rtr_fip_subnet = self.local_subnets.allocate(ri.router_id)
194
188
rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair()
195
ip_wrapper = ip_lib.IPWrapper(self.root_helper,
196
namespace=ri.ns_name)
189
ip_wrapper = ip_lib.IPWrapper(namespace=ri.ns_name)
197
190
device_exists = ip_lib.device_exists(rtr_2_fip_name,
199
191
namespace=ri.ns_name)
200
192
if not device_exists:
201
193
int_dev = ip_wrapper.add_veth(rtr_2_fip_name,
211
203
int_dev[1].link.set_up()
213
205
# add default route for the link local interface
214
device = ip_lib.IPDevice(rtr_2_fip_name,
216
namespace=ri.ns_name)
206
device = ip_lib.IPDevice(rtr_2_fip_name, namespace=ri.ns_name)
217
207
device.route.add_gateway(str(fip_2_rtr.ip), table=FIP_RT_TBL)
218
208
#setup the NAT rules and chains
219
209
ri._handle_fip_nat_rules(rtr_2_fip_name, 'add_rules')
226
216
# scan system for any existing fip ports
227
217
ri.dist_fip_count = 0
228
218
rtr_2_fip_interface = self.get_rtr_ext_device_name(ri.router_id)
229
if ip_lib.device_exists(rtr_2_fip_interface,
230
root_helper=self.root_helper,
231
namespace=ri.ns_name):
232
device = ip_lib.IPDevice(rtr_2_fip_interface,
234
namespace=ri.ns_name)
219
if ip_lib.device_exists(rtr_2_fip_interface, namespace=ri.ns_name):
220
device = ip_lib.IPDevice(rtr_2_fip_interface, namespace=ri.ns_name)
235
221
existing_cidrs = [addr['cidr'] for addr in device.addr.list()]
236
222
fip_cidrs = [c for c in existing_cidrs if
237
223
common_utils.is_cidr_host(c)]