Merge "misc L3 fixes."
This commit is contained in:
commit
27943f7a67
@ -76,7 +76,7 @@ class L3NATAgent(object):
|
||||
cfg.IntOpt('polling_interval',
|
||||
default=3,
|
||||
help="The time in seconds between state poll requests."),
|
||||
cfg.StrOpt('metadata_ip', default='127.0.0.1',
|
||||
cfg.StrOpt('metadata_ip', default='',
|
||||
help="IP address used by Nova metadata server."),
|
||||
cfg.IntOpt('metadata_port',
|
||||
default=8775,
|
||||
@ -117,16 +117,8 @@ class L3NATAgent(object):
|
||||
auth_region=self.conf.auth_region
|
||||
)
|
||||
|
||||
# disable forwarding
|
||||
linux_utils.execute(['sysctl', '-w', 'net.ipv4.ip_forward=0'],
|
||||
self.conf.root_helper, check_exit_code=False)
|
||||
|
||||
self._destroy_all_router_namespaces()
|
||||
|
||||
# enable forwarding
|
||||
linux_utils.execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'],
|
||||
self.conf.root_helper, check_exit_code=False)
|
||||
|
||||
def _destroy_all_router_namespaces(self):
|
||||
"""Destroy all router namespaces on the host to eliminate
|
||||
all stale linux devices, iptables rules, and namespaces.
|
||||
@ -151,13 +143,18 @@ class L3NATAgent(object):
|
||||
bridge=self.conf.external_network_bridge)
|
||||
ns_ip.netns.delete(namespace)
|
||||
|
||||
def daemon_loop(self):
|
||||
def _create_router_namespace(self, ri):
|
||||
ip_wrapper_root = ip_lib.IPWrapper(self.conf.root_helper)
|
||||
ip_wrapper_root.netns.add(ri.ns_name())
|
||||
|
||||
#TODO(danwent): this simple diff logic does not handle if a
|
||||
# resource is modified (i.e., ip change on port, or floating ip
|
||||
# mapped from one IP to another). Will fix this properly with
|
||||
# update notifications.
|
||||
# Likewise, it does not handle removing routers
|
||||
ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
|
||||
namespace=ri.ns_name())
|
||||
ip_wrapper.netns.execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'])
|
||||
|
||||
def daemon_loop(self):
|
||||
#TODO(danwent): this simple diff logic does not handle if
|
||||
# details of a router port (e.g., IP, mac) are changed behind
|
||||
# our back. Will fix this properly with update notifications.
|
||||
|
||||
while True:
|
||||
try:
|
||||
@ -173,10 +170,14 @@ class L3NATAgent(object):
|
||||
|
||||
# identify and update new or modified routers
|
||||
for r in self.qclient.list_routers()['routers']:
|
||||
#FIXME(danwent): handle admin state
|
||||
|
||||
cur_router_ids.add(r['id'])
|
||||
if r['id'] not in self.router_info:
|
||||
self.router_info[r['id']] = RouterInfo(r['id'],
|
||||
self.conf.root_helper)
|
||||
self._create_router_namespace(self.router_info[r['id']])
|
||||
|
||||
ri = self.router_info[r['id']]
|
||||
self.process_router(ri)
|
||||
|
||||
@ -246,6 +247,8 @@ class L3NATAgent(object):
|
||||
existing_floating_ip_ids = set([fip['id'] for fip in ri.floating_ips])
|
||||
cur_floating_ip_ids = set([fip['id'] for fip in floating_ips])
|
||||
|
||||
id_to_fixed_map = {}
|
||||
|
||||
for fip in floating_ips:
|
||||
if fip['port_id']:
|
||||
if fip['id'] not in existing_floating_ip_ids:
|
||||
@ -254,6 +257,9 @@ class L3NATAgent(object):
|
||||
fip['floating_ip_address'],
|
||||
fip['fixed_ip_address'])
|
||||
|
||||
# store to see if floatingip was remapped
|
||||
id_to_fixed_map[fip['id']] = fip['fixed_ip_address']
|
||||
|
||||
floating_ip_ids_to_remove = (existing_floating_ip_ids -
|
||||
cur_floating_ip_ids)
|
||||
for fip in ri.floating_ips:
|
||||
@ -262,6 +268,17 @@ class L3NATAgent(object):
|
||||
self.floating_ip_removed(ri, ri.ex_gw_port,
|
||||
fip['floating_ip_address'],
|
||||
fip['fixed_ip_address'])
|
||||
else:
|
||||
# handle remapping of a floating IP
|
||||
cur_fixed_ip = id_to_fixed_map[fip['id']]
|
||||
existing_fixed_ip = fip['fixed_ip_address']
|
||||
if (cur_fixed_ip and existing_fixed_ip and
|
||||
cur_fixed_ip != existing_fixed_ip):
|
||||
floating_ip = fip['floating_ip_address']
|
||||
self.floating_ip_removed(ri, ri.ex_gw_port,
|
||||
floating_ip, existing_fixed_ip)
|
||||
self.floating_ip_added(ri, ri.ex_gw_port,
|
||||
floating_ip, cur_fixed_ip)
|
||||
|
||||
def _get_ex_gw_port(self, ri):
|
||||
ports = self.qclient.list_ports(
|
||||
@ -306,7 +323,8 @@ class L3NATAgent(object):
|
||||
for (c, r) in self.external_gateway_filter_rules():
|
||||
ri.iptables_manager.ipv4['filter'].add_rule(c, r)
|
||||
for (c, r) in self.external_gateway_nat_rules(ex_gw_ip,
|
||||
internal_cidrs):
|
||||
internal_cidrs,
|
||||
interface_name):
|
||||
ri.iptables_manager.ipv4['nat'].add_rule(c, r)
|
||||
ri.iptables_manager.apply()
|
||||
|
||||
@ -321,21 +339,30 @@ class L3NATAgent(object):
|
||||
ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
|
||||
for c, r in self.external_gateway_filter_rules():
|
||||
ri.iptables_manager.ipv4['filter'].remove_rule(c, r)
|
||||
for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs):
|
||||
for c, r in self.external_gateway_nat_rules(ex_gw_ip, internal_cidrs,
|
||||
interface_name):
|
||||
ri.iptables_manager.ipv4['nat'].remove_rule(c, r)
|
||||
ri.iptables_manager.apply()
|
||||
|
||||
def external_gateway_filter_rules(self):
|
||||
return [('INPUT', '-s 0.0.0.0/0 -d %s '
|
||||
rules = []
|
||||
if self.conf.metadata_ip:
|
||||
rules.append(('INPUT', '-s 0.0.0.0/0 -d %s '
|
||||
'-p tcp -m tcp --dport %s '
|
||||
'-j ACCEPT' %
|
||||
(self.conf.metadata_ip, self.conf.metadata_port))]
|
||||
(self.conf.metadata_ip, self.conf.metadata_port)))
|
||||
return rules
|
||||
|
||||
def external_gateway_nat_rules(self, ex_gw_ip, internal_cidrs):
|
||||
rules = [('PREROUTING', '-s 0.0.0.0/0 -d 169.254.169.254/32 '
|
||||
'-p tcp -m tcp --dport 80 -j DNAT '
|
||||
'--to-destination %s:%s' %
|
||||
(self.conf.metadata_ip, self.conf.metadata_port))]
|
||||
def external_gateway_nat_rules(self, ex_gw_ip, internal_cidrs,
|
||||
interface_name):
|
||||
rules = [('POSTROUTING', '! -i %(interface_name)s '
|
||||
'! -o %(interface_name)s -m conntrack ! '
|
||||
'--ctstate DNAT -j ACCEPT' % locals())]
|
||||
if self.conf.metadata_ip:
|
||||
rules.append('PREROUTING', '-s 0.0.0.0/0 -d 169.254.169.254/32 '
|
||||
'-p tcp -m tcp --dport 80 -j DNAT '
|
||||
'--to-destination %s:%s' %
|
||||
(self.conf.metadata_ip, self.conf.metadata_port))
|
||||
for cidr in internal_cidrs:
|
||||
rules.extend(self.internal_network_nat_rules(ex_gw_ip, cidr))
|
||||
return rules
|
||||
@ -375,10 +402,12 @@ class L3NATAgent(object):
|
||||
ri.iptables_manager.apply()
|
||||
|
||||
def internal_network_nat_rules(self, ex_gw_ip, internal_cidr):
|
||||
return [('snat', '-s %s -j SNAT --to-source %s' %
|
||||
(internal_cidr, ex_gw_ip)),
|
||||
('POSTROUTING', '-s %s -d %s/32 -j ACCEPT' %
|
||||
(internal_cidr, self.conf.metadata_ip))]
|
||||
rules = [('snat', '-s %s -j SNAT --to-source %s' %
|
||||
(internal_cidr, ex_gw_ip))]
|
||||
if self.conf.metadata_ip:
|
||||
rules.append(('POSTROUTING', '-s %s -d %s/32 -j ACCEPT' %
|
||||
(internal_cidr, self.conf.metadata_ip)))
|
||||
return rules
|
||||
|
||||
def floating_ip_added(self, ri, ex_gw_port, floating_ip, fixed_ip):
|
||||
ip_cidr = str(floating_ip) + '/32'
|
||||
|
@ -14,6 +14,7 @@
|
||||
# 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 copy
|
||||
import time
|
||||
import unittest
|
||||
|
||||
@ -79,13 +80,6 @@ class TestBasicRouterOperations(unittest.TestCase):
|
||||
def testAgentCreate(self):
|
||||
agent = l3_agent.L3NATAgent(self.conf)
|
||||
|
||||
# calls to disable/enable routing
|
||||
self.utils_exec.assert_has_calls([
|
||||
mock.call(mock.ANY, self.conf.root_helper,
|
||||
check_exit_code=mock.ANY),
|
||||
mock.call(mock.ANY, self.conf.root_helper,
|
||||
check_exit_code=mock.ANY)])
|
||||
|
||||
self.device_exists.assert_has_calls(
|
||||
[mock.call(self.conf.external_network_bridge)])
|
||||
|
||||
@ -203,7 +197,7 @@ class TestBasicRouterOperations(unittest.TestCase):
|
||||
fake_subnet = {'subnet': {'cidr': '19.4.4.0/24',
|
||||
'gateway_ip': '19.4.4.1'}}
|
||||
|
||||
fake_floatingips = {'floatingips': [
|
||||
fake_floatingips1 = {'floatingips': [
|
||||
{'id': _uuid(),
|
||||
'floating_ip_address': '8.8.8.8',
|
||||
'fixed_ip_address': '7.7.7.7',
|
||||
@ -211,7 +205,13 @@ class TestBasicRouterOperations(unittest.TestCase):
|
||||
|
||||
self.client_inst.list_ports.side_effect = fake_list_ports1
|
||||
self.client_inst.show_subnet.return_value = fake_subnet
|
||||
self.client_inst.list_floatingips.return_value = fake_floatingips
|
||||
self.client_inst.list_floatingips.return_value = fake_floatingips1
|
||||
agent.process_router(ri)
|
||||
|
||||
# remap floating IP to a new fixed ip
|
||||
fake_floatingips2 = copy.deepcopy(fake_floatingips1)
|
||||
fake_floatingips2['floatingips'][0]['fixed_ip_address'] = '7.7.7.8'
|
||||
self.client_inst.list_floatingips.return_value = fake_floatingips2
|
||||
agent.process_router(ri)
|
||||
|
||||
# remove just the floating ips
|
||||
|
Loading…
Reference in New Issue
Block a user