Merge "NSX|V3: create dhcp profile at boot time"

This commit is contained in:
Jenkins 2015-10-20 08:40:07 +00:00 committed by Gerrit Code Review
commit f85feb5650
10 changed files with 111 additions and 100 deletions

View File

@ -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 {

View File

@ -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 =

View File

@ -207,12 +207,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

View File

@ -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

View File

@ -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 = []

View File

@ -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(

View File

@ -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])

View File

@ -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)

View File

@ -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)

View File

@ -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)