# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 VMware, Inc. All rights reserved.
#
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""
"""
import errno
import netaddr
self.iptables_manager = None
"""Initialize the router on the system.
This differs from __init__ in that this method actually affects the
system creating namespaces, starting processes, etc. The other merely
initializes the python object. This separates in-memory object
initialization from methods that actually go do stuff to the system.
:param process_monitor: The agent's process monitor instance.
"""
# Because of the way how dnsmasq works on Solaris, the length
# of datalink name cannot exceed 16 (includes terminating nul
# character). So, the linkname can only have 15 characters and
# the last two characters are set aside for '_0'. So, we only
# have 13 characters left.
dname += '_0'
# please see the comment above
dname += '_0'
pass
# driver just returns if datalink and IP interface already exists
# Since we support shared router model, we need to block the new
# internal port from reaching other tenant's ports
# If allow_forwarding_between_networks is set, then we need to
# allow forwarding of packets between same tenant's ports.
# walk through the other internal ports and retrieve their
# cidrs and at the same time add the new internal port's
# cidr to them
block_subnets = []
allow_subnets = []
continue
# we need to add the port's subnet to this internal_port's
# allowed_subnet_pool
[port_subnet])
else:
[port_subnet])
# update the new port's pool with other ports' subnet
# now setup the IPF rules
rules = ['block in quick on %s from %s to pool/%d' %
# pass in packets between networks that belong to same tenant
# if the external gateway is already setup for the shared router,
# then we need to add Policy Based Routing (PBR) for this internal
# network
if ex_gw_port else None)
if ex_gw_ip:
rdr_rule = ['rdr %s 169.254.169.254/32 port 80 -> %s port %d tcp' %
# remove all the IP filter rules that we added during
# internal network addition
rules = ['block in quick on %s from %s to pool/%d' %
# remove all the IP filter rules that we added during
# external network addition
if ex_gw_port else None)
if ex_gw_ip:
# remove the ippool
[port_subnet])
else:
[port_subnet])
rdr_rule = ['rdr %s 169.254.169.254/32 port 80 -> %s port %d tcp' %
if p['admin_state_up']])
p['id'] not in current_port_ids]
# updated_ports = self._get_updated_ports(self.internal_ports,
# internal_ports)
for p in new_ports:
for p in old_ports:
# if updated_ports:
# for index, p in enumerate(internal_ports):
# if not updated_ports.get(p['id']):
# continue
# self.internal_ports[index] = updated_ports[p['id']]
# interface_name = self.get_internal_device_name(p['id'])
# ip_cidrs = common_utils.fixed_ip_cidrs(p['fixed_ips'])
# self.driver.init_l3(interface_name, ip_cidrs=ip_cidrs,
# namespace=self.ns_name)
# enable_ra = enable_ra or self._port_has_ipv6_subnet(p)
# Enable RA
if enable_ra:
# remove any internal stale router interfaces (i.e., l3i.. VNICs)
if n.startswith(INTERNAL_DEV_PREFIX))
for port_id in current_port_ids)
for stale_dev in stale_devs:
# Generate a unique-name for ippool(1m) from that last 3
# bytes of mac-address. It is called pool name, but it is
# actually a 32 bit integer
if suffix:
"""Configure IP addresses on router's external gateway interface.
Ensures addresses for existing floating IPs and cleans up
those that should not longer be configured.
"""
fip_statuses = {}
if interface_name is None:
return fip_statuses
new_nat_rules = []
# Loop once to ensure that floating ips are configured.
for fip in floating_ips:
if fip_cidr not in existing_cidrs:
try:
# TODO(gmoodalb): If we fail in add_nat_rules(), then
# we need to remove the fip_cidr address
# any exception occurred here should cause the floating IP
# to be set in error state
continue
else:
# check if existing fip has been reassigned
for rule in existing_nat_rules:
continue
continue
if fixed_cidr not in rule:
break
if fip_reassigned:
# remove the old nat rule and
# add a new one for the new fixed_ip
try:
continue
# remove all the old NAT rules
# Filter out 'bimap' NAT rules as we don't want to remove NAT rules
# that were added for Metadata server
# Clean up addresses that no longer belong on the gateway interface.
return fip_statuses
# Todo(gmoodalb): need to do more work on ipv6 gateway
# determine the network type of the external network
try:
"the external network, and it is required "
"to create an external gateway port: %s") % err)
return
"VLAN based, and it is required to "
"create an external gateway port"))
return
elif (l2type == 'vlan' and
"Juno and will be removed in the next release "
"of Solaris OpenStack. Please use the evsadm "
"set-controlprop subcommand to setup the "
"uplink-port for an external network"))
# proceed with the old-style of doing things
else:
ex_gw_port['network_id'],
if gw_ip:
if 'entry exists' not in stdout:
# for each of the internal ports, add Policy Based
# Routing (PBR) rule
rules = ['pass in on %s to %s:%s from any to !%s' %
ipversion = \
# There is nothing to do on Solaris
pass
if gw_ip:
# remove PBR rules
rules = ['pass in on %s to %s:%s from any to !%s' %
ipversion = \
if self.remove_route:
'default', gw_ip]
# TODO(Carl) Refactor to clarify roles of ex_gw_port vs self.ex_gw_port
interface_name = None
if ex_gw_port_id:
if ex_gw_port:
if k not in ignore)
return port1_filtered == port2_filtered
if not self.ex_gw_port:
# Remove any external stale router interfaces (i.e., l3e.. VNICs)
dev != interface_name]
for stale_dev in stale_devs:
# Process SNAT rules for external gateway
rules = []
ip_cidrs = []
return rules
# Remove all the old SNAT rules
# This is safe because if use_namespaces is set as False
# then the agent can only configure one router, otherwise
# each router's SNAT rules will be in their own namespace
# get only the SNAT rules
# And add them back if the action is add_rules
# NAT rules are added only if ex_gw_port has an IPv4 address
break
try:
# TODO(Carl) Return after setting existing_floating_ips and
# still call update_fip_statuses?
if not ex_gw_port:
return
# Once NAT rules for floating IPs are safely in place
# configure their addresses on the external gateway port
except (n_exc.FloatingIpSetupException,
n_exc.IpTablesApplyException) as e:
# All floating IPs must be put in error state
OPTS = [
"an external network.")),
"networks")),
]
args = []
kwargs = {
'router_id': router_id,
'router': router,
}