Add per subnet masquerading

Masquerading for external access for each routed
network, if enabled.

Implements: blueprint tripleo-routed-networks-ironic-inspector
Implements: blueprint tripleo-routed-networks-deployment
Change-Id: I792b516314302e2c290e63c10fb0fe6881ce7236
This commit is contained in:
Harald Jensas 2018-01-13 15:17:57 +01:00
parent 1b83386162
commit 983c2be88e
6 changed files with 89 additions and 19 deletions

View File

@ -11,7 +11,11 @@ $IPTCOMMAND -w -t nat -N BOOTSTACK_MASQ_NEW
# Build the chain we want.
{{#masquerade_networks}}
NETWORK={{.}}
$IPTCOMMAND -w -t nat -A BOOTSTACK_MASQ_NEW -s $NETWORK ! -d $NETWORK -j MASQUERADE
NETWORKS={{#masquerade_networks}}{{.}},{{/masquerade_networks}}
# Shell substitution to remove the traling comma
NETWORKS=${NETWORKS%?}
$IPTCOMMAND -w -t nat -A BOOTSTACK_MASQ_NEW -s $NETWORK -d $NETWORKS -j RETURN
$IPTCOMMAND -w -t nat -A BOOTSTACK_MASQ_NEW -s $NETWORK -j MASQUERADE
{{/masquerade_networks}}
# Link it in.
$IPTCOMMAND -w -t nat -I POSTROUTING -j BOOTSTACK_MASQ_NEW

View File

@ -49,14 +49,16 @@ class BaseTestCase(base.BaseTestCase):
cfg.StrOpt('dhcp_start'),
cfg.StrOpt('dhcp_end'),
cfg.StrOpt('inspection_iprange'),
cfg.StrOpt('gateway')]
cfg.StrOpt('gateway'),
cfg.BoolOpt('masquerade')]
self.conf.register_opts(self.opts, group=self.grp0)
self.grp1 = cfg.OptGroup(name='subnet1', title='subnet1')
self.gtp2 = cfg.OptGroup(name='subnet2', title='subnet2')
self.conf.config(cidr='192.168.24.0/24',
dhcp_start='192.168.24.5', dhcp_end='192.168.24.24',
inspection_iprange='192.168.24.100,192.168.24.120',
gateway='192.168.24.1', group='ctlplane-subnet')
gateway='192.168.24.1', masquerade=True,
group='ctlplane-subnet')
class TestUndercloud(BaseTestCase):
@ -674,11 +676,13 @@ class TestGenerateEnvironment(BaseTestCase):
self.conf.config(cidr='192.168.10.0/24', dhcp_start='192.168.10.10',
dhcp_end='192.168.10.99',
inspection_iprange='192.168.10.100,192.168.10.189',
gateway='192.168.10.254', group='subnet1')
gateway='192.168.10.254', masquerade=True,
group='subnet1')
self.conf.config(cidr='192.168.20.0/24', dhcp_start='192.168.20.10',
dhcp_end='192.168.20.99',
inspection_iprange='192.168.20.100,192.168.20.189',
gateway='192.168.20.254', group='subnet2')
gateway='192.168.20.254', masquerade=True,
group='subnet2')
env = undercloud._generate_environment('.')
reference = [{"tag": "subnet1", "gateway": "192.168.10.254",
"ip_range": "192.168.10.100,192.168.10.189",
@ -696,16 +700,18 @@ class TestGenerateEnvironment(BaseTestCase):
self.conf.config(cidr='192.168.24.0/24',
dhcp_start='192.168.24.5', dhcp_end='192.168.24.24',
inspection_iprange='192.168.24.100,192.168.24.120',
gateway='192.168.24.1', group='ctlplane-subnet')
gateway='192.168.24.1', masquerade=True,
group='ctlplane-subnet')
self.conf.config(cidr='192.168.10.0/24', dhcp_start='192.168.10.10',
dhcp_end='192.168.10.99',
inspection_iprange='192.168.10.100,192.168.10.189',
gateway='192.168.10.254', group='subnet1')
gateway='192.168.10.254', masquerade=True,
group='subnet1')
self.conf.config(cidr='192.168.20.0/24', dhcp_start='192.168.20.10',
dhcp_end='192.168.20.99',
inspection_iprange='192.168.20.100,192.168.20.189',
gateway='192.168.20.254', group='subnet2')
gateway='192.168.20.254', masquerade=True,
group='subnet2')
env = undercloud._generate_environment('.')
reference = [{"ip_netmask": "192.168.10.0/24",
"next_hop": "192.168.24.1"},
@ -741,6 +747,31 @@ class TestGenerateEnvironment(BaseTestCase):
actual = env['SUBNETS_CIDR_NAT_RULES']
self.assertEqual(reference, actual)
def test_masquerade_networks(self):
self.conf.config(subnets=['ctlplane-subnet', 'subnet1', 'subnet2'])
self.conf.register_opts(self.opts, group=self.grp1)
self.conf.register_opts(self.opts, group=self.gtp2)
self.conf.config(cidr='192.168.24.0/24',
dhcp_start='192.168.24.5', dhcp_end='192.168.24.24',
inspection_iprange='192.168.24.100,192.168.24.120',
gateway='192.168.24.1', masquerade=True,
group='ctlplane-subnet')
self.conf.config(cidr='192.168.10.0/24', dhcp_start='192.168.10.10',
dhcp_end='192.168.10.99',
inspection_iprange='192.168.10.100,192.168.10.189',
gateway='192.168.10.254', masquerade=True,
group='subnet1')
self.conf.config(cidr='192.168.20.0/24', dhcp_start='192.168.20.10',
dhcp_end='192.168.20.99',
inspection_iprange='192.168.20.100,192.168.20.189',
gateway='192.168.20.254', masquerade=True,
group='subnet2')
env = undercloud._generate_environment('.')
reference = ['192.168.24.0/24', '192.168.10.0/24', '192.168.20.0/24']
actual = json.loads(env['MASQUERADE_NETWORKS'])
self.assertEqual(reference, actual)
class TestWritePasswordFile(BaseTestCase):
def test_normal(self):

View File

@ -33,12 +33,14 @@ class TestValidator(base.BaseTestCase):
cfg.StrOpt('dhcp_start'),
cfg.StrOpt('dhcp_end'),
cfg.StrOpt('inspection_iprange'),
cfg.StrOpt('gateway')]
cfg.StrOpt('gateway'),
cfg.BoolOpt('masquerade')]
self.conf.register_opts(self.opts, group=self.grp0)
self.conf.config(cidr='192.168.24.0/24',
dhcp_start='192.168.24.5', dhcp_end='192.168.24.24',
inspection_iprange='192.168.24.100,192.168.24.120',
gateway='192.168.24.1', group='ctlplane-subnet')
gateway='192.168.24.1', masquerade=True,
group='ctlplane-subnet')
@mock.patch('netifaces.interfaces')
def test_validation_passes(self, ifaces_mock):

View File

@ -178,8 +178,8 @@ _opts = [
'and introspection. Comma separated list of names/tags. '
'For each network a section/group needs to be added to '
'the configuration file with these parameters set: '
'cidr, dhcp_start, dhcp_end, inspection_iprange and '
'gateway.'
'cidr, dhcp_start, dhcp_end, inspection_iprange, '
'gateway and masquerade_network.'
'\n\n'
'Example:\n\n'
'subnets = subnet1,subnet2\n'
@ -192,6 +192,7 @@ _opts = [
'dhcp_end = 192.168.10.200\n'
'inspection_iprange = 192.168.10.20,192.168.10.90\n'
'gateway = 192.168.10.254\n'
'masquerade_network = True'
'\n'
'[subnet2]\n'
'. . .\n')),
@ -247,6 +248,11 @@ _opts = [
),
cfg.StrOpt('masquerade_network',
default='192.168.24.0/24',
deprecated_for_removal=True,
deprecated_reason=('With support for routed networks, '
'masquerading of the provisioning networks '
'is moved to a boolean option for each '
'subnet.'),
help=('Network that will be masqueraded for external access, '
'if required. This should be the subnet used for PXE '
'booting.')
@ -424,6 +430,9 @@ _subnets_opts = [
deprecated_opts=_deprecated_opt_network_gateway,
help=('Network gateway for the Neutron-managed network for '
'Overcloud instances on this network.')),
cfg.BoolOpt('masquerade',
default=False,
help=('The network will be masqueraded for external access.')),
]
# Passwords, tokens, hashes
@ -1158,7 +1167,7 @@ class InstackEnvironment(dict):
'ENABLED_MANAGEMENT_INTERFACES', 'SYSCTL_SETTINGS',
'LOCAL_IP_WRAPPED', 'ENABLE_ARCHITECTURE_PPC64LE',
'INSPECTION_SUBNETS', 'SUBNETS_CIDR_NAT_RULES',
'SUBNETS_STATIC_ROUTES'}
'SUBNETS_STATIC_ROUTES', 'MASQUERADE_NETWORKS'}
"""The variables we calculate in _generate_environment call."""
PUPPET_KEYS = DYNAMIC_KEYS | {opt.name.upper() for _, group in list_opts()
@ -1261,6 +1270,20 @@ def _process_drivers_and_hardware_types(instack_env):
instack_env['ENABLED_POWER_INTERFACES'] = _make_list(mgmt_interfaces)
def _generate_masquerade_networks():
env_list = []
for subnet in CONF.subnets:
s = CONF.get(subnet)
if s.masquerade:
env_list.append(s.cidr)
# NOTE(hjensas): Remove once deprecated masquerade_network option is gone
if CONF.masquerade_network and (CONF.masquerade_network not in env_list):
env_list.append(CONF.masquerade_network)
return json.dumps(env_list)
def _generate_inspection_subnets():
env_list = []
for subnet in CONF.subnets:
@ -1391,6 +1414,7 @@ def _generate_environment(instack_root):
_process_drivers_and_hardware_types(instack_env)
instack_env['INSPECTION_SUBNETS'] = _generate_inspection_subnets()
instack_env['SUBNETS_CIDR_NAT_RULES'] = _generate_subnets_cidr_nat_rules()
instack_env['MASQUERADE_NETWORKS'] = _generate_masquerade_networks()
instack_env['SUBNETS_STATIC_ROUTES'] = _generate_subnets_static_routes()
instack_env['SYSCTL_SETTINGS'] = _generate_sysctl_settings()

View File

@ -10,7 +10,7 @@
]},
"local-ip": "{{LOCAL_IP}}",
"local-ip-wrapped": "{{LOCAL_IP_WRAPPED}}",
"masquerade_networks": ["{{MASQUERADE_NETWORK}}"],
"masquerade_networks": {{MASQUERADE_NETWORKS}},
"service_certificate": "{{UNDERCLOUD_SERVICE_CERTIFICATE}}",
"public_host": "{{UNDERCLOUD_PUBLIC_HOST}}",
"admin_password": "{{UNDERCLOUD_ADMIN_PASSWORD}}",

View File

@ -42,7 +42,8 @@
# List of routed network subnets for provisioning and introspection.
# Comma separated list of names/tags. For each network a section/group
# needs to be added to the configuration file with these parameters
# set: cidr, dhcp_start, dhcp_end, inspection_iprange and gateway.
# set: cidr, dhcp_start, dhcp_end, inspection_iprange, gateway and
# masquerade_network.
#
# Example:
#
@ -56,7 +57,7 @@
# dhcp_end = 192.168.10.200
# inspection_iprange = 192.168.10.20,192.168.10.90
# gateway = 192.168.10.254
#
# masquerade_network = True
# [subnet2]
# . . .
# (list value)
@ -102,8 +103,13 @@
# MTU to use for the local_interface. (integer value)
#local_mtu = 1500
# Network that will be masqueraded for external access, if required.
# This should be the subnet used for PXE booting. (string value)
# DEPRECATED: Network that will be masqueraded for external access, if
# required. This should be the subnet used for PXE booting. (string
# value)
# This option is deprecated for removal.
# Its value may be silently ignored in the future.
# Reason: With support for routed networks, masquerading of the
# provisioning networks is moved to a boolean option for each subnet.
#masquerade_network = 192.168.24.0/24
# Path to hieradata override file. If set, the file will be copied
@ -382,3 +388,6 @@
# instances on this network. (string value)
# Deprecated group/name - [DEFAULT]/network_gateway
#gateway = 192.168.24.1
# The network will be masqueraded for external access. (boolean value)
#masquerade = false