NSX|V3: create dhcp profile at boot time
This profile will be applied to the DHCP ports if the DHCP service is enabled. The change remove the requirement that the admin create this out of band. This is now possible due to the fact that we are using a distributed locking mechanism. Change-Id: I12538af5849226ae3d8aeaea94bdd80be6ed0605
This commit is contained in:
parent
5b8e132cfb
commit
dd7dd97bed
@ -114,7 +114,6 @@ function neutron_plugin_configure_service {
|
||||
_nsxv3_ini_set insecure $NSX_INSECURE
|
||||
_nsxv3_ini_set ca_file $NSX_CA_FILE
|
||||
_nsxv3_ini_set default_bridge_cluster_uuid $DEFAULT_BRIDGE_CLUSTER_UUID
|
||||
_nsxv3_ini_set default_switching_profile_dhcp_uuid $DEFAULT_SWITCHING_PROFILE_DHCP_UUID
|
||||
}
|
||||
|
||||
function neutron_plugin_setup_interface_driver {
|
||||
|
@ -346,12 +346,3 @@
|
||||
# L2 gateway APIs.
|
||||
# This field must be specified on one of the active neutron servers only.
|
||||
# default_bridge_cluster_uuid =
|
||||
|
||||
# UUID of the default NSX switching profile to allow DHCP traffic. This will be
|
||||
# applied on the DHCP ports, if neutron's DHCP service is enabled.
|
||||
# In order to create the DHCP switching profile, go the NSX manager and perform
|
||||
# the following steps:
|
||||
# Create a new Switching Profile of type 'Switch Security'.
|
||||
# Disable DHCP Client Block and DHCP Server Block options for this profile.
|
||||
# Save the profile and copy the Switching Profile's UUID below.
|
||||
# default_switching_profile_dhcp_uuid =
|
||||
|
@ -204,12 +204,6 @@ nsx_v3_opts = [
|
||||
'"ca_file" is set.')),
|
||||
cfg.StrOpt('default_tier0_router_uuid',
|
||||
help=_("Default tier0 router identifier")),
|
||||
cfg.StrOpt('default_switching_profile_dhcp_uuid',
|
||||
help=_("UUID of the default NSX switching profile to allow "
|
||||
"DHCP traffic. This will be applied on the DHCP ports, "
|
||||
"if neutron's DHCP service is enabled. This profile "
|
||||
"must be created on the backend, out of band, with DHCP "
|
||||
"Server/Client Block disabled.")),
|
||||
]
|
||||
|
||||
DEFAULT_STATUS_CHECK_INTERVAL = 2000
|
||||
|
@ -170,7 +170,7 @@ class JSONRESTClient(RESTClient):
|
||||
|
||||
def _rest_call(self, *args, **kwargs):
|
||||
if kwargs.get('body') is not None:
|
||||
kwargs['body'] = jsonutils.dumps(kwargs['body'])
|
||||
kwargs['body'] = jsonutils.dumps(kwargs['body'], sort_keys=True)
|
||||
result = super(JSONRESTClient, self)._rest_call(*args, **kwargs)
|
||||
return result.json() if result.content else result
|
||||
|
||||
|
@ -122,6 +122,30 @@ class SwitchingProfile(AbstractRESTResource):
|
||||
white_list_providers=whitelist_providers,
|
||||
tags=tags or [])
|
||||
|
||||
def create_dhcp_profile(self, display_name,
|
||||
description, tags=None):
|
||||
dhcp_filter = {
|
||||
'client_block_enabled': False,
|
||||
'server_block_enabled': False
|
||||
}
|
||||
rate_limits = {
|
||||
'rx_broadcast': 0,
|
||||
'tx_broadcast': 0,
|
||||
'rx_multicast': 0,
|
||||
'tx_multicast': 0
|
||||
}
|
||||
bpdu_filter = {
|
||||
'enabled': False,
|
||||
'white_list': []
|
||||
}
|
||||
return self.create(SwitchingProfileTypes.SWITCH_SECURITY,
|
||||
display_name=display_name,
|
||||
description=description,
|
||||
tags=tags or [],
|
||||
dhcp_filter=dhcp_filter,
|
||||
rate_limits=rate_limits,
|
||||
bpdu_filter=bpdu_filter)
|
||||
|
||||
@classmethod
|
||||
def build_switch_profile_ids(cls, client, *profiles):
|
||||
ids = []
|
||||
|
@ -73,6 +73,7 @@ from vmware_nsx.nsxlib.v3 import security
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
NSX_V3_PSEC_PROFILE_NAME = 'neutron_port_spoof_guard_profile'
|
||||
NSX_V3_DHCP_PROFILE_NAME = 'neutron_port_dhcp_profile'
|
||||
|
||||
|
||||
class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
|
||||
@ -133,11 +134,16 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
|
||||
self._psec_profile = None
|
||||
self._psec_profile = self._init_port_security_profile()
|
||||
if not self._psec_profile:
|
||||
msg = (_("Unable to initialize NSX v3 port spoofguard "
|
||||
"switching profile: %s") % NSX_V3_PSEC_PROFILE_NAME)
|
||||
msg = _("Unable to initialize NSX v3 port spoofguard "
|
||||
"switching profile: %s") % NSX_V3_PSEC_PROFILE_NAME
|
||||
raise nsx_exc.NsxPluginException(msg)
|
||||
LOG.debug("Initializing NSX v3 DHCP switching profile")
|
||||
self._dhcp_profile = None
|
||||
self._dhcp_profile = self._init_dhcp_switching_profile()
|
||||
if not self._dhcp_profile:
|
||||
msg = _("Unable to initialize NSX v3 DHCP "
|
||||
"switching profile: %s") % NSX_V3_DHCP_PROFILE_NAME
|
||||
raise nsx_exc.NsxPluginException(msg)
|
||||
self._unsubscribe_callback_events()
|
||||
|
||||
def _unsubscribe_callback_events(self):
|
||||
@ -165,22 +171,27 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin,
|
||||
"must be disabled") % dhcp_profile_uuid
|
||||
raise n_exc.InvalidInput(error_message=msg)
|
||||
|
||||
@utils.retry_upon_exception_nsxv3(Exception)
|
||||
def _init_dhcp_switching_profile(self):
|
||||
dhcp_profile_uuid = cfg.CONF.nsx_v3.default_switching_profile_dhcp_uuid
|
||||
if not dhcp_profile_uuid:
|
||||
LOG.warning(_LW("Switching profile for DHCP ports not configured "
|
||||
"in the config file."))
|
||||
return
|
||||
if not uuidutils.is_uuid_like(dhcp_profile_uuid):
|
||||
LOG.warning(_LW("default_switching_profile_dhcp_uuid: %s. DHCP "
|
||||
"profile must be configured with a UUID"),
|
||||
dhcp_profile_uuid)
|
||||
return
|
||||
self._validate_dhcp_profile(dhcp_profile_uuid)
|
||||
with locking.LockManager.get_lock('nsxv3_dhcp_profile_init'):
|
||||
profile = self._get_dhcp_security_profile()
|
||||
if not profile:
|
||||
self._switching_profiles.create_dhcp_profile(
|
||||
NSX_V3_DHCP_PROFILE_NAME, 'Neutron DHCP Security Profile',
|
||||
tags=utils.build_v3_tags_payload({
|
||||
'id': NSX_V3_DHCP_PROFILE_NAME,
|
||||
'tenant_id': 'neutron-nsx-plugin'}))
|
||||
return self._get_dhcp_security_profile()
|
||||
|
||||
def _get_dhcp_security_profile(self):
|
||||
if self._dhcp_profile:
|
||||
return self._dhcp_profile
|
||||
profile = self._switching_profiles.find_by_display_name(
|
||||
NSX_V3_DHCP_PROFILE_NAME)
|
||||
return nsx_resources.SwitchingProfileTypeId(
|
||||
profile_type=(nsx_resources.SwitchingProfileTypes.
|
||||
SWITCH_SECURITY),
|
||||
profile_id=dhcp_profile_uuid)
|
||||
profile_id=profile[0]['id']) if profile else None
|
||||
|
||||
def _get_port_security_profile_id(self):
|
||||
return nsx_resources.SwitchingProfile.build_switch_profile_ids(
|
||||
|
@ -12,7 +12,6 @@
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import mock
|
||||
import six
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
@ -41,7 +40,6 @@ from oslo_utils import uuidutils
|
||||
|
||||
from vmware_nsx.common import utils
|
||||
from vmware_nsx.nsxlib.v3 import client as nsx_client
|
||||
from vmware_nsx.nsxlib.v3 import resources as nsx_resources
|
||||
from vmware_nsx.plugins.nsx_v3 import plugin as nsx_plugin
|
||||
from vmware_nsx.tests import unit as vmware
|
||||
from vmware_nsx.tests.unit.nsx_v3 import mocks as nsx_v3_mocks
|
||||
@ -80,11 +78,6 @@ class NsxV3PluginTestCaseMixin(test_plugin.NeutronDbPluginV2TestCase,
|
||||
if getattr(self.plugin, '_port_client', None):
|
||||
self.plugin._port_client._client._session = self.mock_api
|
||||
|
||||
mocked_locking = mock.patch.object(
|
||||
nsx_plugin, 'locking', new=mock.Mock())
|
||||
mocked_locking.start()
|
||||
self._patchers.append(mocked_locking)
|
||||
|
||||
self.maxDiff = None
|
||||
|
||||
def tearDown(self):
|
||||
@ -354,54 +347,3 @@ class TestNsxV3Utils(NsxV3PluginTestCaseMixin):
|
||||
{'scope': 'os-api-version',
|
||||
'tag': version.version_info.release_string()}]
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
|
||||
class TestNsxV3DHCPSwitchingProfile(TestPortsV2):
|
||||
|
||||
def setUp(self, plugin=PLUGIN_NAME,
|
||||
ext_mgr=None,
|
||||
service_plugins=None):
|
||||
super(TestNsxV3DHCPSwitchingProfile, self).setUp(plugin=plugin,
|
||||
ext_mgr=ext_mgr)
|
||||
dhcp_profile_uuid = uuidutils.generate_uuid()
|
||||
cfg.CONF.set_override('default_switching_profile_dhcp_uuid',
|
||||
dhcp_profile_uuid, 'nsx_v3')
|
||||
self.plugin._dhcp_profile = nsx_resources.SwitchingProfileTypeId(
|
||||
profile_type=(nsx_resources.SwitchingProfileTypes.
|
||||
SWITCH_SECURITY),
|
||||
profile_id=dhcp_profile_uuid)
|
||||
|
||||
def test_create_port_dhcp_profile(self):
|
||||
with mock.patch.object(self.plugin._port_client,
|
||||
'create') as port_create:
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network):
|
||||
data = {'port': {'network_id': network['network']['id'],
|
||||
'tenant_id':
|
||||
network['network']['tenant_id'],
|
||||
'name': 'port1',
|
||||
'admin_state_up': True,
|
||||
'device_owner':
|
||||
constants.DEVICE_OWNER_DHCP}}
|
||||
port_req = self.new_create_request('ports', data)
|
||||
port_req.get_response(self.api)
|
||||
args, kwargs = port_create.call_args
|
||||
self.assertEqual(kwargs['switch_profile_ids'],
|
||||
[self.plugin._dhcp_profile])
|
||||
|
||||
def test_create_non_dhcp_port_with_dhcp_profile(self):
|
||||
with mock.patch.object(self.plugin._port_client,
|
||||
'create') as port_create:
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network):
|
||||
data = {'port': {'network_id': network['network']['id'],
|
||||
'tenant_id':
|
||||
network['network']['tenant_id'],
|
||||
'name': 'port1',
|
||||
'admin_state_up': True,
|
||||
'device_owner': 'not-dhcp'}}
|
||||
port_req = self.new_create_request('ports', data)
|
||||
port_req.get_response(self.api)
|
||||
args, kwargs = port_create.call_args
|
||||
self.assertNotEqual(kwargs['switch_profile_ids'],
|
||||
[self.plugin._dhcp_profile])
|
||||
|
@ -58,7 +58,8 @@ class NsxLibQosTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/switching-profiles',
|
||||
False,
|
||||
jsonutils.dumps(self._body(qos_marking='UNTRUSTED', dscp=25)),
|
||||
jsonutils.dumps(self._body(qos_marking='UNTRUSTED', dscp=25),
|
||||
sort_keys=True),
|
||||
_JSON_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -77,7 +78,8 @@ class NsxLibQosTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/switching-profiles',
|
||||
False,
|
||||
jsonutils.dumps(self._body(qos_marking='trusted', dscp=0)),
|
||||
jsonutils.dumps(self._body(qos_marking='trusted', dscp=0),
|
||||
sort_keys=True),
|
||||
_JSON_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
|
@ -44,7 +44,7 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
'resource_type': profile_types.PORT_MIRRORING,
|
||||
'display_name': 'pm-profile',
|
||||
'description': 'port mirror prof'
|
||||
}),
|
||||
}, sort_keys=True),
|
||||
client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -71,7 +71,7 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
False, jsonutils.dumps({
|
||||
'resource_type': profile_types.PORT_MIRRORING,
|
||||
'tags': tags
|
||||
}),
|
||||
}, sort_keys=True),
|
||||
client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -104,7 +104,53 @@ class TestSwitchingProfileTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
'description': 'spoofguard-for-neutron',
|
||||
'white_list_providers': ['LPORT_BINDINGS'],
|
||||
'tags': tags
|
||||
}),
|
||||
}, sort_keys=True),
|
||||
client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
def test_create_dhcp_profile(self):
|
||||
|
||||
tags = [
|
||||
{
|
||||
'scope': 'os-tid',
|
||||
'tag': 'tenant-1'
|
||||
},
|
||||
{
|
||||
'scope': 'os-api-version',
|
||||
'tag': '2.1.1.0'
|
||||
}
|
||||
]
|
||||
|
||||
api = resources.SwitchingProfile(client.NSX3Client())
|
||||
with self.mocked_resource(api) as mocked:
|
||||
api.create_dhcp_profile(
|
||||
'neutron-dhcp', 'dhcp-for-neutron',
|
||||
tags=tags)
|
||||
|
||||
test_client.assert_session_call(
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/switching-profiles',
|
||||
False,
|
||||
jsonutils.dumps({
|
||||
'bpdu_filter': {
|
||||
'enabled': False,
|
||||
'white_list': []
|
||||
},
|
||||
'resource_type': profile_types.SWITCH_SECURITY,
|
||||
'display_name': 'neutron-dhcp',
|
||||
'description': 'dhcp-for-neutron',
|
||||
'tags': tags,
|
||||
'dhcp_filter': {
|
||||
'client_block_enabled': False,
|
||||
'server_block_enabled': False
|
||||
},
|
||||
'rate_limits': {
|
||||
'rx_broadcast': 0,
|
||||
'tx_broadcast': 0,
|
||||
'rx_multicast': 0,
|
||||
'tx_multicast': 0
|
||||
}
|
||||
}, sort_keys=True),
|
||||
client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -200,7 +246,7 @@ class LogicalPortTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/logical-ports',
|
||||
False,
|
||||
jsonutils.dumps(resp_body),
|
||||
jsonutils.dumps(resp_body, sort_keys=True),
|
||||
client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -271,7 +317,7 @@ class LogicalRouterTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/logical-routers',
|
||||
False,
|
||||
jsonutils.dumps(data),
|
||||
jsonutils.dumps(data, sort_keys=True),
|
||||
client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -325,7 +371,7 @@ class LogicalRouterPortTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/logical-router-ports',
|
||||
False,
|
||||
jsonutils.dumps(data),
|
||||
jsonutils.dumps(data, sort_keys=True),
|
||||
client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
|
@ -53,7 +53,7 @@ class NsxLibSwitchTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
test_client.assert_session_call(
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/logical-switches',
|
||||
False, jsonutils.dumps(self._create_body()),
|
||||
False, jsonutils.dumps(self._create_body(), sort_keys=True),
|
||||
nsxlib.client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -71,7 +71,8 @@ class NsxLibSwitchTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
'https://1.2.3.4/api/v1/logical-switches',
|
||||
False,
|
||||
jsonutils.dumps(self._create_body(
|
||||
admin_state=nsx_constants.ADMIN_STATE_DOWN)),
|
||||
admin_state=nsx_constants.ADMIN_STATE_DOWN),
|
||||
sort_keys=True),
|
||||
nsxlib.client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
@ -87,7 +88,8 @@ class NsxLibSwitchTestCase(nsxlib_testcase.NsxClientTestCase):
|
||||
test_client.assert_session_call(
|
||||
mocked.get('post'),
|
||||
'https://1.2.3.4/api/v1/logical-switches',
|
||||
False, jsonutils.dumps(self._create_body(vlan_id='123')),
|
||||
False, jsonutils.dumps(self._create_body(vlan_id='123'),
|
||||
sort_keys=True),
|
||||
nsxlib.client.JSONRESTClient._DEFAULT_HEADERS,
|
||||
nsxlib_testcase.NSX_CERT)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user