Merge "NSX|v3: DHCP Relay support"
This commit is contained in:
commit
13fb4d1c93
@ -193,6 +193,7 @@ function neutron_plugin_configure_service {
|
||||
_nsxv3_ini_set native_metadata_route $NATIVE_METADATA_ROUTE
|
||||
_nsxv3_ini_set dhcp_profile $DHCP_PROFILE_UUID
|
||||
_nsxv3_ini_set metadata_proxy $METADATA_PROXY_UUID
|
||||
_nsxv3_ini_set dhcp_relay_service $DHCP_RELAY_SERVICE
|
||||
iniset $NEUTRON_CONF DEFAULT dhcp_agent_notification False
|
||||
fi
|
||||
if [[ "$NSX_USE_CLIENT_CERT_AUTH" == "True" ]]; then
|
||||
|
@ -13,3 +13,4 @@ NSX_MANAGER=<FILL_IN>
|
||||
NSX_CONTROLLERS=<FILL_IN>
|
||||
DHCP_PROFILE_UUID=<FILL_IN>
|
||||
METADATA_PROXY_UUID=<FILL_IN>
|
||||
DHCP_RELAY_SERVICE=<FILL_IN>
|
||||
|
@ -109,6 +109,7 @@ DEFAULT_EDGE_CLUSTER_UUID=<edge-cluster-uuid>
|
||||
|
||||
# Enabled native DHCP support from NSX backend
|
||||
DHCP_PROFILE_UUID=<dhcp-profile-uuid>
|
||||
DHCP_RELAY_SERVICE=<dhcp-relay-service>
|
||||
METADATA_PROXY_UUID=<metadata-proxy-uuid>
|
||||
METADATA_PROXY_SHARED_SECRET=<metadata-proxy-secret>
|
||||
METADATA_PROXY_USE_HTTPS=False
|
||||
|
@ -289,6 +289,10 @@ Routers
|
||||
|
||||
nsxadmin -r routers -o nsx-update-rules
|
||||
|
||||
- Update DHCP relay service on NSX router ports according to the current configuration::
|
||||
|
||||
nsxadmin -r routers -o nsx-update-dhcp-relay
|
||||
|
||||
Orphaned Routers
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
11
releasenotes/notes/nsxv3-dhcp-relay-32cf1ae281e1.yaml
Normal file
11
releasenotes/notes/nsxv3-dhcp-relay-32cf1ae281e1.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
prelude: >
|
||||
The NSX-v3 plugin supports DHCP relay service per network
|
||||
availability zones.
|
||||
features:
|
||||
- The NSX-v3 plugin supports DHCP relay service per network
|
||||
availability zones. When a router interface port is created,
|
||||
the relay service will be added to it.
|
||||
DHCP traffic on the subnet will go through the DHCP server
|
||||
configured in the dhcp relay service on the NSX, if it is
|
||||
connected to the router.
|
@ -399,6 +399,10 @@ nsx_v3_opts = [
|
||||
"that will be used to enable native metadata service. "
|
||||
"It needs to be created in NSX before starting Neutron "
|
||||
"with the NSX plugin.")),
|
||||
cfg.StrOpt('dhcp_relay_service',
|
||||
help=_("(Optional) This is the name or UUID of the NSX dhcp "
|
||||
"relay service that will be used to enable DHCP relay "
|
||||
"on router ports.")),
|
||||
cfg.BoolOpt('log_security_groups_blocked_traffic',
|
||||
default=False,
|
||||
help=_("(Optional) Indicates whether distributed-firewall "
|
||||
@ -793,6 +797,10 @@ nsxv3_az_opts = [
|
||||
cfg.ListOpt('switching_profiles',
|
||||
help=_("(Optional) list switching profiles uuids that will be "
|
||||
"attached to all neutron created nsx ports.")),
|
||||
cfg.StrOpt('dhcp_relay_service',
|
||||
help=_("(Optional) This is the name or UUID of the NSX dhcp "
|
||||
"relay service that will be used to enable DHCP relay "
|
||||
"on router ports.")),
|
||||
]
|
||||
|
||||
# Register the configuration options
|
||||
|
@ -20,6 +20,7 @@ from vmware_nsx.common import availability_zones as common_az
|
||||
from vmware_nsx.common import config
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsxlib.v3 import core_resources
|
||||
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
||||
|
||||
DEFAULT_NAME = common_az.DEFAULT_NAME
|
||||
|
||||
@ -78,6 +79,10 @@ class NsxV3AvailabilityZone(common_az.ConfiguredAvailabilityZone):
|
||||
if self.switching_profiles is None:
|
||||
self.switching_profiles = cfg.CONF.nsx_v3.switching_profiles
|
||||
|
||||
self.dhcp_relay_service = az_info.get('dhcp_relay_service')
|
||||
if self.dhcp_relay_service is None:
|
||||
self.dhcp_relay_service = cfg.CONF.nsx_v3.dhcp_relay_service
|
||||
|
||||
def init_default_az(self):
|
||||
# use the default configuration
|
||||
self.metadata_proxy = cfg.CONF.nsx_v3.metadata_proxy
|
||||
@ -88,6 +93,7 @@ class NsxV3AvailabilityZone(common_az.ConfiguredAvailabilityZone):
|
||||
self.default_overlay_tz = cfg.CONF.nsx_v3.default_overlay_tz
|
||||
self.default_vlan_tz = cfg.CONF.nsx_v3.default_vlan_tz
|
||||
self.switching_profiles = cfg.CONF.nsx_v3.switching_profiles
|
||||
self.dhcp_relay_service = cfg.CONF.nsx_v3.dhcp_relay_service
|
||||
|
||||
def translate_configured_names_to_uuids(self, nsxlib):
|
||||
# Mandatory configurations (in AZ or inherited from global values)
|
||||
@ -171,6 +177,23 @@ class NsxV3AvailabilityZone(common_az.ConfiguredAvailabilityZone):
|
||||
nsx_profile.get('id')))
|
||||
self.switching_profiles_objs = profiles
|
||||
|
||||
if (self.dhcp_relay_service and
|
||||
nsxlib.feature_supported(nsxlib_consts.FEATURE_DHCP_RELAY)):
|
||||
relay_id = None
|
||||
if cfg.CONF.nsx_v3.init_objects_by_tags:
|
||||
# Find the TZ by its tag
|
||||
relay_id = nsxlib.get_id_by_resource_and_tag(
|
||||
nsxlib.relay_service.resource_type,
|
||||
cfg.CONF.nsx_v3.search_objects_scope,
|
||||
self.dhcp_relay_service)
|
||||
if not relay_id:
|
||||
# Find the service by its name or id
|
||||
relay_id = nsxlib.relay_service.get_id_by_name_or_id(
|
||||
self.dhcp_relay_service)
|
||||
self.dhcp_relay_service = relay_id
|
||||
else:
|
||||
self.dhcp_relay_service = None
|
||||
|
||||
|
||||
class NsxV3AvailabilityZones(common_az.ConfiguredAvailabilityZones):
|
||||
|
||||
|
@ -3260,13 +3260,15 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
port, resource_type='os-neutron-rport-id',
|
||||
project_name=context.tenant_name)
|
||||
tags.append({'scope': 'os-subnet-id', 'tag': subnet['id']})
|
||||
net_az = self.get_network_az_by_net_id(context, network_id)
|
||||
self._routerlib.create_logical_router_intf_port_by_ls_id(
|
||||
logical_router_id=nsx_router_id,
|
||||
display_name=display_name,
|
||||
tags=tags,
|
||||
ls_id=nsx_net_id,
|
||||
logical_switch_port_id=nsx_port_id,
|
||||
address_groups=address_groups)
|
||||
address_groups=address_groups,
|
||||
relay_service_uuid=net_az.dhcp_relay_service)
|
||||
|
||||
if router_db.gw_port and not router_db.enable_snat:
|
||||
# TODO(berlin): Announce the subnet on tier0 if enable_snat
|
||||
|
@ -347,6 +347,7 @@ class EdgeFwaasV3Driver(fwaas_base.FwaasDriverBase):
|
||||
nsx_router_id, section_id = self._get_backend_router_and_fw_section(
|
||||
context, router_id)
|
||||
|
||||
#TODO(asarfaty) add dhcp relay allow rules here
|
||||
# Add default drop all rule at the end
|
||||
old_default_rule = self.nsx_firewall.get_default_rule(
|
||||
section_id)
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
import sys
|
||||
|
||||
from vmware_nsx.common import config # noqa
|
||||
from vmware_nsx.common import utils as nsx_utils
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.shell.admin.plugins.common import constants
|
||||
@ -22,11 +23,13 @@ from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
|
||||
from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils
|
||||
from vmware_nsx.shell import resources as shell
|
||||
from vmware_nsxlib.v3 import exceptions as nsx_exc
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
|
||||
from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import l3_db
|
||||
from neutron_lib.callbacks import registry
|
||||
from neutron_lib import context as neutron_context
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -173,6 +176,42 @@ def delete_backend_router(resource, event, trigger, **kwargs):
|
||||
LOG.error("Failed to delete backend router %s.", nsx_id)
|
||||
|
||||
|
||||
@admin_utils.output_header
|
||||
def update_dhcp_relay(resource, event, trigger, **kwargs):
|
||||
"""Update all routers dhcp relay service by the current configuration"""
|
||||
nsxlib = utils.get_connected_nsxlib()
|
||||
if not nsxlib.feature_supported(nsx_constants.FEATURE_DHCP_RELAY):
|
||||
version = nsxlib.get_version()
|
||||
LOG.error("DHCP relay is not supported by NSX version %s", version)
|
||||
return
|
||||
|
||||
# initialize the availability zones and nsxlib
|
||||
config.register_nsxv3_azs(cfg.CONF, cfg.CONF.nsx_v3.availability_zones)
|
||||
|
||||
# get all neutron router interfaces ports
|
||||
admin_cxt = neutron_context.get_admin_context()
|
||||
with utils.NsxV3PluginWrapper() as plugin:
|
||||
filters = {'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF]}
|
||||
ports = plugin.get_ports(admin_cxt, filters=filters)
|
||||
for port in ports:
|
||||
# get the backend router port by the tag
|
||||
nsx_port_id = nsxlib.get_id_by_resource_and_tag(
|
||||
'LogicalRouterDownLinkPort',
|
||||
'os-neutron-rport-id', port['id'])
|
||||
if not nsx_port_id:
|
||||
LOG.warning("Couldn't find nsx router port for interface %s",
|
||||
port['id'])
|
||||
continue
|
||||
# get the network of this port
|
||||
network_id = port['network_id']
|
||||
# check the relay service on the az of the network
|
||||
az = plugin.get_network_az_by_net_id(admin_cxt, network_id)
|
||||
nsxlib.logical_router_port.update(
|
||||
nsx_port_id, relay_service_uuid=az.dhcp_relay_service)
|
||||
#TODO(asarfaty) also update the firewall rules of the routers
|
||||
LOG.info("Done.")
|
||||
|
||||
|
||||
registry.subscribe(list_missing_routers,
|
||||
constants.ROUTERS,
|
||||
shell.Operations.LIST_MISMATCHES.value)
|
||||
@ -188,3 +227,7 @@ registry.subscribe(list_orphaned_routers,
|
||||
registry.subscribe(delete_backend_router,
|
||||
constants.ORPHANED_ROUTERS,
|
||||
shell.Operations.NSX_CLEAN.value)
|
||||
|
||||
registry.subscribe(update_dhcp_relay,
|
||||
constants.ROUTERS,
|
||||
shell.Operations.NSX_UPDATE_DHCP_RELAY.value)
|
||||
|
@ -49,6 +49,7 @@ class Operations(enum.Enum):
|
||||
NSX_UPDATE_ALL = 'nsx-update-all'
|
||||
NSX_UPDATE_SECRET = 'nsx-update-secret'
|
||||
NSX_UPDATE_RULES = 'nsx-update-rules'
|
||||
NSX_UPDATE_DHCP_RELAY = 'nsx-update-dhcp-relay'
|
||||
NSX_UPDATE_IP = 'nsx-update-ip'
|
||||
NSX_RECREATE = 'nsx-recreate'
|
||||
NSX_REORDER = 'nsx-reorder'
|
||||
@ -95,7 +96,8 @@ nsxv3_resources = {
|
||||
Operations.NSX_MIGRATE_EXCLUDE_PORTS.value]),
|
||||
constants.ROUTERS: Resource(constants.ROUTERS,
|
||||
[Operations.LIST_MISMATCHES.value,
|
||||
Operations.NSX_UPDATE_RULES.value]),
|
||||
Operations.NSX_UPDATE_RULES.value,
|
||||
Operations.NSX_UPDATE_DHCP_RELAY.value]),
|
||||
constants.DHCP_BINDING: Resource(constants.DHCP_BINDING,
|
||||
[Operations.LIST.value,
|
||||
Operations.NSX_UPDATE.value]),
|
||||
|
@ -41,6 +41,7 @@ class Nsxv3AvailabilityZonesTestCase(base.BaseTestCase):
|
||||
cfg.CONF.set_override("dns_domain", "xxx.com", group="nsx_v3")
|
||||
cfg.CONF.set_override("nameservers", ["10.1.1.1"], group="nsx_v3")
|
||||
cfg.CONF.set_override("switching_profiles", ["uuid1"], group="nsx_v3")
|
||||
cfg.CONF.set_override("dhcp_relay_service", "service1", group="nsx_v3")
|
||||
|
||||
def _config_az(self,
|
||||
metadata_proxy="metadata_proxy1",
|
||||
@ -50,7 +51,8 @@ class Nsxv3AvailabilityZonesTestCase(base.BaseTestCase):
|
||||
nameservers=["20.1.1.1"],
|
||||
default_overlay_tz='otz',
|
||||
default_vlan_tz='vtz',
|
||||
switching_profiles=["uuid2"]):
|
||||
switching_profiles=["uuid2"],
|
||||
dhcp_relay_service="service2"):
|
||||
if metadata_proxy is not None:
|
||||
cfg.CONF.set_override("metadata_proxy", metadata_proxy,
|
||||
group=self.group_name)
|
||||
@ -76,6 +78,9 @@ class Nsxv3AvailabilityZonesTestCase(base.BaseTestCase):
|
||||
if switching_profiles is not None:
|
||||
cfg.CONF.set_override("switching_profiles", switching_profiles,
|
||||
group=self.group_name)
|
||||
if dhcp_relay_service is not None:
|
||||
cfg.CONF.set_override("dhcp_relay_service", dhcp_relay_service,
|
||||
group=self.group_name)
|
||||
|
||||
def test_simple_availability_zone(self):
|
||||
self._config_az()
|
||||
@ -89,6 +94,7 @@ class Nsxv3AvailabilityZonesTestCase(base.BaseTestCase):
|
||||
self.assertEqual("otz", az.default_overlay_tz)
|
||||
self.assertEqual("vtz", az.default_vlan_tz)
|
||||
self.assertEqual(["uuid2"], az.switching_profiles)
|
||||
self.assertEqual("service2", az.dhcp_relay_service)
|
||||
|
||||
def test_missing_group_section(self):
|
||||
self.assertRaises(
|
||||
|
@ -64,6 +64,7 @@ NSX_TZ_NAME = 'default transport zone'
|
||||
NSX_DHCP_PROFILE_ID = 'default dhcp profile'
|
||||
NSX_METADATA_PROXY_ID = 'default metadata proxy'
|
||||
NSX_SWITCH_PROFILE = 'dummy switch profile'
|
||||
NSX_DHCP_RELAY_SRV = 'dhcp relay srv'
|
||||
|
||||
|
||||
def _mock_create_firewall_rules(*args):
|
||||
@ -134,6 +135,11 @@ def _mock_nsx_backend_calls():
|
||||
"get_id_by_name_or_id",
|
||||
return_value=NSX_DHCP_PROFILE_ID).start()
|
||||
|
||||
mock.patch(
|
||||
"vmware_nsxlib.v3.core_resources.NsxLibDhcpRelayService."
|
||||
"get_id_by_name_or_id",
|
||||
return_value=NSX_DHCP_RELAY_SRV).start()
|
||||
|
||||
mock.patch(
|
||||
"vmware_nsxlib.v3.core_resources.NsxLibMetadataProxy."
|
||||
"get_id_by_name_or_id",
|
||||
@ -1315,6 +1321,29 @@ class TestL3NatTestCase(L3NatTest,
|
||||
{'router': {'admin_state_up': False}},
|
||||
expected_code=exc.HTTPBadRequest.code)
|
||||
|
||||
def test_router_dhcp_relay(self):
|
||||
# Add the relay service to the config and availability zones
|
||||
cfg.CONF.set_override('dhcp_relay_service', NSX_DHCP_RELAY_SRV,
|
||||
'nsx_v3')
|
||||
mock_nsx_version = mock.patch.object(
|
||||
self.plugin.nsxlib, 'feature_supported', return_value=True)
|
||||
mock_nsx_version.start()
|
||||
self.plugin.init_availability_zones()
|
||||
for az in self.plugin.get_azs_list():
|
||||
az.translate_configured_names_to_uuids(self.plugin.nsxlib)
|
||||
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network) as s1,\
|
||||
self.router() as r1,\
|
||||
mock.patch.object(self.plugin.nsxlib.logical_router_port,
|
||||
'update') as mock_update_port:
|
||||
self._router_interface_action('add', r1['router']['id'],
|
||||
s1['subnet']['id'], None)
|
||||
mock_update_port.assert_called_once_with(
|
||||
mock.ANY,
|
||||
relay_service_uuid=NSX_DHCP_RELAY_SRV,
|
||||
subnets=mock.ANY)
|
||||
|
||||
|
||||
class ExtGwModeTestCase(test_ext_gw_mode.ExtGwModeIntTestCase,
|
||||
L3NatTest):
|
||||
|
Loading…
Reference in New Issue
Block a user