Merge "NSX|V3: ensure that subnet update takes host routes into account"

This commit is contained in:
Jenkins 2017-08-01 06:08:30 +00:00 committed by Gerrit Code Review
commit 39b2821126
2 changed files with 100 additions and 29 deletions

View File

@ -1395,11 +1395,23 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
if (cfg.CONF.nsx_v3.native_dhcp_metadata and
updated_subnet['enable_dhcp']):
kwargs = {}
for key in ('dns_nameservers', 'gateway_ip'):
for key in ('dns_nameservers', 'gateway_ip', 'host_routes'):
if key in subnet['subnet']:
value = subnet['subnet'][key]
if value != orig_subnet[key]:
kwargs[key] = value
if key != 'dns_nameservers':
kwargs['options'] = None
if 'options' in kwargs:
sr, gw_ip = self.nsxlib.native_dhcp.build_static_routes(
updated_subnet.get('gateway_ip'),
updated_subnet.get('cidr'),
updated_subnet.get('host_routes', []))
kwargs['options'] = {'option121': {'static_routes': sr}}
kwargs.pop('host_routes', None)
if (gw_ip is not None and 'gateway_ip' not in kwargs and
gw_ip != updated_subnet['gateway_ip']):
kwargs['gateway_ip'] = gw_ip
if kwargs:
dhcp_service = nsx_db.get_nsx_service_binding(
context.session, orig_subnet['network_id'],
@ -1415,17 +1427,22 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
"%(server)s for network %(network)s",
{'server': dhcp_service['nsx_service_id'],
'network': orig_subnet['network_id']})
if 'gateway_ip' in kwargs:
if 'options' in kwargs:
# Need to update the static binding of every VM in
# this logical DHCP server.
bindings = nsx_db.get_nsx_dhcp_bindings_by_service(
context.session, dhcp_service['nsx_service_id'])
for binding in bindings:
port = self._get_port(context, binding['port_id'])
dhcp_opts = port.get(ext_edo.EXTRADHCPOPTS)
self._update_dhcp_binding_on_server(
context, binding, port['mac_address'],
binding['ip_address'], kwargs['gateway_ip'],
port['network_id'])
binding['ip_address'],
port['network_id'],
gateway_ip=kwargs.get('gateway_ip', False),
dhcp_opts=dhcp_opts,
options=kwargs.get('options'),
subnet=updated_subnet)
if (cfg.CONF.nsx_v3.metadata_on_demand and
not cfg.CONF.nsx_v3.native_dhcp_metadata):
@ -1792,12 +1809,18 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
msg = (_("DHCP option %s is not supported") % opt_name)
raise n_exc.InvalidInput(error_message=msg)
def _get_dhcp_options(self, context, ip, extra_dhcp_opts, net_id):
def _get_dhcp_options(self, context, ip, extra_dhcp_opts, net_id,
subnet):
# Always add option121.
net_az = self.get_network_az_by_net_id(context, net_id)
options = {'option121': {'static_routes': [
{'network': '%s' % net_az.native_metadata_route,
'next_hop': ip}]}}
if subnet:
sr, gateway_ip = self.nsxlib.native_dhcp.build_static_routes(
subnet.get('gateway_ip'), subnet.get('cidr'),
subnet.get('host_routes', []))
options['option121']['static_routes'].extend(sr)
# Adding extra options only if configured on port
if extra_dhcp_opts:
other_opts = []
@ -1829,12 +1852,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
gateway_ip = subnet.get('gateway_ip')
options = self._get_dhcp_options(
context, ip, port.get(ext_edo.EXTRADHCPOPTS),
port['network_id'])
# update static routes
for hr in subnet['host_routes']:
options['option121']['static_routes'].append(
{'network': hr['destination'],
'next_hop': hr['nexthop']})
port['network_id'], subnet)
binding = self.nsxlib.dhcp_server.create_binding(
dhcp_service_id, port['mac_address'], ip, hostname,
cfg.CONF.nsx_v3.dhcp_lease_time, options, gateway_ip)
@ -1969,10 +1987,12 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
binding = self._find_dhcp_binding(subnet_id, ip,
bindings)
if binding:
subnet = self.get_subnet(context,
binding['subnet_id'])
self._update_dhcp_binding_on_server(
context, binding, new_port['mac_address'],
ips_to_add[i][1], old_port['network_id'],
dhcp_opts=dhcp_opts)
dhcp_opts=dhcp_opts, subnet=subnet)
# Update DB IP
nsx_db.update_nsx_dhcp_bindings(context.session,
old_port['id'],
@ -1999,23 +2019,28 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
# If only Mac address/dhcp opts is changed,
# update it in all associated DHCP bindings.
for binding in bindings:
subnet = self.get_subnet(context, binding['subnet_id'])
self._update_dhcp_binding_on_server(
context, binding, new_port['mac_address'],
binding['ip_address'], old_port['network_id'],
dhcp_opts=dhcp_opts if dhcp_opts_changed else None)
dhcp_opts=dhcp_opts, subnet=subnet)
def _update_dhcp_binding_on_server(self, context, binding, mac, ip,
net_id, gateway_ip=False,
dhcp_opts=None):
dhcp_opts=None, options=None,
subnet=None):
try:
data = {'mac_address': mac, 'ip_address': ip}
if ip != binding['ip_address']:
data['host_name'] = 'host-%s' % ip.replace('.', '-')
data['options'] = self._get_dhcp_options(
context, ip, dhcp_opts, net_id)
elif dhcp_opts is not None:
context, ip, dhcp_opts, net_id,
subnet)
elif (dhcp_opts is not None or
options is not None):
data['options'] = self._get_dhcp_options(
context, ip, dhcp_opts, net_id)
context, ip, dhcp_opts, net_id,
subnet)
if gateway_ip is not False:
# Note that None is valid for gateway_ip, means deleting it.
data['gateway_ip'] = gateway_ip

View File

@ -400,7 +400,11 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
options = {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': ip}]}}
'next_hop': ip},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': '0.0.0.0/0',
'next_hop': subnet['subnet']['gateway_ip']}]}}
create_dhcp_binding.assert_called_once_with(
dhcp_service['nsx_service_id'],
port['port']['mac_address'], ip, hostname,
@ -435,8 +439,12 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
options = {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': ip}]},
'others': [{'code': opt_code, 'values': [opt_val]}]}
'next_hop': ip},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': '0.0.0.0/0',
'next_hop': subnet['subnet']['gateway_ip']}]},
'others': [{'code': opt_code, 'values': [opt_val]}]}
create_dhcp_binding.assert_called_once_with(
dhcp_service['nsx_service_id'],
port['port']['mac_address'], ip, hostname,
@ -469,7 +477,12 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': ip},
{'network': '1.0.0.0/24', 'next_hop': '1.2.3.4'}]}}
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': '0.0.0.0/0',
'next_hop': subnet['subnet']['gateway_ip']},
{'network': '1.0.0.0/24',
'next_hop': '1.2.3.4'}]}}
create_dhcp_binding.assert_called_once_with(
dhcp_service['nsx_service_id'],
port['port']['mac_address'], ip, hostname,
@ -595,7 +608,11 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
'options': {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': new_ip}]}}}
'next_hop': new_ip},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': constants.IPv4_ANY,
'next_hop': subnet['subnet']['gateway_ip']}]}}}
self._verify_dhcp_binding(subnet, port_data, update_data,
assert_data)
@ -606,7 +623,15 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
port_data = {'mac_address': '11:22:33:44:55:66'}
new_mac = '22:33:44:55:66:77'
update_data = {'port': {'mac_address': new_mac}}
assert_data = {'mac_address': new_mac}
assert_data = {'mac_address': new_mac,
'options': {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': mock.ANY},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': constants.IPv4_ANY,
'next_hop': subnet['subnet']['gateway_ip']}]}}}
self._verify_dhcp_binding(subnet, port_data, update_data,
assert_data)
@ -627,7 +652,11 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
'options': {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': new_ip}]}}}
'next_hop': new_ip},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': constants.IPv4_ANY,
'next_hop': subnet['subnet']['gateway_ip']}]}}}
self._verify_dhcp_binding(subnet, port_data, update_data,
assert_data)
@ -651,7 +680,11 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
'options': {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': ip_addr}]},
'next_hop': ip_addr},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': constants.IPv4_ANY,
'next_hop': subnet['subnet']['gateway_ip']}]},
'others': [{'code': 26, 'values': ['9002']}]}}
self._verify_dhcp_binding(subnet, port_data, update_data,
assert_data)
@ -676,7 +709,11 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
'options': {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': ip_addr}]},
'next_hop': ip_addr},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': constants.IPv4_ANY,
'next_hop': subnet['subnet']['gateway_ip']}]},
'others': [{'code': 26, 'values': ['9002']},
{'code': 40, 'values': ['abc']}]}}
self._verify_dhcp_binding(subnet, port_data, update_data,
@ -704,7 +741,11 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
'options': {'option121': {'static_routes': [
{'network': '%s' %
cfg.CONF.nsx_v3.native_metadata_route,
'next_hop': ip_addr}]},
'next_hop': ip_addr},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': constants.IPv4_ANY,
'next_hop': subnet['subnet']['gateway_ip']}]},
'others': [{'code': 40, 'values': ['abc']}]}}
self._verify_dhcp_binding(subnet, port_data, update_data,
assert_data)
@ -849,8 +890,13 @@ class NsxNativeDhcpTestCase(test_plugin.NsxV3PluginTestCaseMixin):
ip = port['port']['fixed_ips'][0]['ip_address']
hostname = 'host-%s' % ip.replace('.', '-')
options = {'option121': {'static_routes': [
{'network': '%s' % self.az_metadata_route,
'next_hop': ip}]}}
{'network': '%s' %
self.az_metadata_route,
'next_hop': ip},
{'network': subnet['subnet']['cidr'],
'next_hop': '0.0.0.0'},
{'network': '0.0.0.0/0',
'next_hop': subnet['subnet']['gateway_ip']}]}}
create_dhcp_binding.assert_called_once_with(
dhcp_service['nsx_service_id'],
port['port']['mac_address'], ip, hostname,