diff --git a/etc/neutron/plugins/nicira/nvp.ini b/etc/neutron/plugins/nicira/nvp.ini index b22448ec44..f6e928d36b 100644 --- a/etc/neutron/plugins/nicira/nvp.ini +++ b/etc/neutron/plugins/nicira/nvp.ini @@ -133,6 +133,12 @@ # ignored, as new networks will no longer be scheduled to existing dhcp agents. # agent_mode = agent +# Specifies which mode packet replication should be done in. If set to service +# a service node is required in order to perform packet replication. This can +# also be set to source if one wants replication to be performed locally (NOTE: +# usually only useful for testing if one does not want to deploy a service node). +# replication_mode = service + [nsx_sync] # Interval in seconds between runs of the status synchronization task. # The plugin will aim at resynchronizing operational status for all diff --git a/etc/neutron/plugins/vmware/nsx.ini b/etc/neutron/plugins/vmware/nsx.ini index e6add19971..e270df57d6 100644 --- a/etc/neutron/plugins/vmware/nsx.ini +++ b/etc/neutron/plugins/vmware/nsx.ini @@ -128,6 +128,12 @@ # ignored, as new networks will no longer be scheduled to existing dhcp agents. # agent_mode = agent +# Specifies which mode packet replication should be done in. If set to service +# a service node is required in order to perform packet replication. This can +# also be set to source if one wants replication to be performed locally (NOTE: +# usually only useful for testing if one does not want to deploy a service node). +# replication_mode = service + [nsx_sync] # Interval in seconds between runs of the status synchronization task. # The plugin will aim at resynchronizing operational status for all diff --git a/neutron/plugins/vmware/common/config.py b/neutron/plugins/vmware/common/config.py index 8b135da8bc..848d6bded7 100644 --- a/neutron/plugins/vmware/common/config.py +++ b/neutron/plugins/vmware/common/config.py @@ -16,6 +16,8 @@ from oslo.config import cfg +from neutron.plugins.vmware.common import exceptions as nsx_exc + class AgentModes: AGENT = 'agent' @@ -28,6 +30,11 @@ class MetadataModes: INDIRECT = 'dhcp_host_route' +class ReplicationModes: + SERVICE = 'service' + SOURCE = 'source' + + base_opts = [ cfg.IntOpt('max_lp_per_bridged_ls', default=5000, deprecated_group='NVP', @@ -61,7 +68,12 @@ base_opts = [ "bridge, ipsec_gre, or ipsec_stt)")), cfg.StrOpt('agent_mode', default=AgentModes.AGENT, deprecated_group='NVP', - help=_("The mode used to implement DHCP/metadata services.")) + help=_("The mode used to implement DHCP/metadata services.")), + cfg.StrOpt('replication_mode', default=ReplicationModes.SERVICE, + help=_("The default option leverages service nodes to perform" + " packet replication though one could set to this to " + "'source' to perform replication locally. This is useful" + " if one does not want to deploy a service node(s).")) ] sync_opts = [ @@ -176,3 +188,11 @@ cfg.CONF.register_opts(cluster_opts) cfg.CONF.register_opts(vcns_opts, group="vcns") cfg.CONF.register_opts(base_opts, group="NSX") cfg.CONF.register_opts(sync_opts, group="NSX_SYNC") + + +def validate_config_options(): + if cfg.CONF.NSX.replication_mode not in (ReplicationModes.SERVICE, + ReplicationModes.SOURCE): + error = (_("Invalid replication_mode: %s") % + cfg.CONF.NSX.replication_mode) + raise nsx_exc.NsxPluginException(err_msg=error) diff --git a/neutron/plugins/vmware/nsxlib/router.py b/neutron/plugins/vmware/nsxlib/router.py index 75c432911d..35e61da2be 100644 --- a/neutron/plugins/vmware/nsxlib/router.py +++ b/neutron/plugins/vmware/nsxlib/router.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo.config import cfg + from neutron.common import exceptions as exception from neutron.openstack.common import excutils from neutron.openstack.common import jsonutils @@ -54,7 +56,8 @@ def _prepare_lrouter_body(name, neutron_router_id, tenant_id, "routing_config": { "type": router_type }, - "type": "LogicalRouterConfig" + "type": "LogicalRouterConfig", + "replication_mode": cfg.CONF.NSX.replication_mode, } # add the distributed key only if not None (ie: True or False) if distributed is not None: diff --git a/neutron/plugins/vmware/nsxlib/switch.py b/neutron/plugins/vmware/nsxlib/switch.py index a451add2a5..5df050ca43 100644 --- a/neutron/plugins/vmware/nsxlib/switch.py +++ b/neutron/plugins/vmware/nsxlib/switch.py @@ -16,6 +16,8 @@ import json +from oslo.config import cfg + from neutron.common import constants from neutron.common import exceptions as exception from neutron.openstack.common import log @@ -115,6 +117,7 @@ def create_lswitch(cluster, neutron_net_id, tenant_id, display_name, # historical reasons lswitch_obj = {"display_name": utils.check_and_truncate(display_name), "transport_zones": transport_zones_config, + "replication_mode": cfg.CONF.NSX.replication_mode, "tags": utils.get_tags(os_tid=tenant_id, quantum_net_id=neutron_net_id)} # TODO(salv-orlando): Now that we have async status synchronization diff --git a/neutron/plugins/vmware/plugins/base.py b/neutron/plugins/vmware/plugins/base.py index e378d21c76..15f442bd41 100644 --- a/neutron/plugins/vmware/plugins/base.py +++ b/neutron/plugins/vmware/plugins/base.py @@ -123,6 +123,7 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin, def __init__(self): super(NsxPluginV2, self).__init__() + config.validate_config_options() # TODO(salv-orlando): Replace These dicts with # collections.defaultdict for better handling of default values # Routines for managing logical ports in NSX diff --git a/neutron/tests/unit/vmware/nsxlib/test_router.py b/neutron/tests/unit/vmware/nsxlib/test_router.py index c2384400ce..8250efd52b 100644 --- a/neutron/tests/unit/vmware/nsxlib/test_router.py +++ b/neutron/tests/unit/vmware/nsxlib/test_router.py @@ -16,6 +16,8 @@ import mock +from oslo.config import cfg + from neutron.common import exceptions from neutron.openstack.common import uuidutils from neutron.plugins.vmware.api_client import exception as api_exc @@ -115,7 +117,8 @@ class TestExplicitLRouters(base.NsxlibTestCase): 'type': 'SingleDefaultRouteImplicitRoutingConfig'}, 'tags': utils.get_tags(os_tid='fake_tenant_id', q_router_id='pipita_higuain'), - 'type': 'LogicalRouterConfig'} + 'type': 'LogicalRouterConfig', + 'replication_mode': cfg.CONF.NSX.replication_mode} self.assertEqual(expected, body) def test_prepare_body_without_routing_config(self): @@ -129,7 +132,8 @@ class TestExplicitLRouters(base.NsxlibTestCase): 'routing_config': {'type': 'RoutingTableRoutingConfig'}, 'tags': utils.get_tags(os_tid='fake_tenant_id', q_router_id='marekiaro_hamsik'), - 'type': 'LogicalRouterConfig'} + 'type': 'LogicalRouterConfig', + 'replication_mode': cfg.CONF.NSX.replication_mode} self.assertEqual(expected, body) def test_get_lrouter(self): diff --git a/neutron/tests/unit/vmware/test_nsx_opts.py b/neutron/tests/unit/vmware/test_nsx_opts.py index 69d88ca3bb..99b6366a9e 100644 --- a/neutron/tests/unit/vmware/test_nsx_opts.py +++ b/neutron/tests/unit/vmware/test_nsx_opts.py @@ -121,6 +121,7 @@ class ConfigurationTest(base.BaseTestCase): self.assertEqual(10, cfg.CONF.NSX.concurrent_connections) self.assertEqual('access_network', cfg.CONF.NSX.metadata_mode) self.assertEqual('stt', cfg.CONF.NSX.default_transport_type) + self.assertEqual('service', cfg.CONF.NSX.replication_mode) self.assertIsNone(cfg.CONF.default_tz_uuid) self.assertEqual('admin', cfg.CONF.nsx_user)