Merge "NSXv: add address pair support"

This commit is contained in:
Jenkins 2015-11-03 17:29:06 +00:00 committed by Gerrit Code Review
commit 516116f5ac
2 changed files with 145 additions and 1 deletions

View File

@ -29,6 +29,7 @@ from neutron.api.v2 import attributes as attr
from neutron.common import constants
from neutron.common import exceptions as n_exc
from neutron.db import agents_db
from neutron.db import allowedaddresspairs_db as addr_pair_db
from neutron.db import db_base_plugin_v2
from neutron.db import external_net_db
from neutron.db import extraroute_db
@ -39,6 +40,7 @@ from neutron.db import portbindings_db
from neutron.db import portsecurity_db
from neutron.db import quota_db # noqa
from neutron.db import securitygroups_db
from neutron.extensions import allowedaddresspairs as addr_pair
from neutron.extensions import external_net as ext_net_extn
from neutron.extensions import l3
from neutron.extensions import multiprovidernet as mpnet
@ -83,7 +85,8 @@ ROUTER_SIZE = routersize.ROUTER_SIZE
VALID_EDGE_SIZES = routersize.VALID_EDGE_SIZES
class NsxVPluginV2(agents_db.AgentDbMixin,
class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
agents_db.AgentDbMixin,
db_base_plugin_v2.NeutronDbPluginV2,
rt_rtr.RouterType_mixin,
external_net_db.External_net_db_mixin,
@ -95,6 +98,7 @@ class NsxVPluginV2(agents_db.AgentDbMixin,
vnic_index_db.VnicIndexDbMixin):
supported_extension_aliases = ["agent",
"allowed-address-pairs",
"binding",
"dvr",
"ext-gw-mode",
@ -812,6 +816,14 @@ class NsxVPluginV2(agents_db.AgentDbMixin,
context, id, {'network': revert_update})
return net_res
def _validate_address_pairs(self, attrs, db_port):
# Check that the MAC address is the same as the port
for ap in attrs[addr_pair.ADDRESS_PAIRS]:
if ('mac_address' in ap and
ap['mac_address'] != db_port['mac_address']):
msg = _('Address pairs should have same MAC as the port')
raise n_exc.BadRequest(resource='address_pairs', msg=msg)
def create_port(self, context, port):
port_data = port['port']
with context.session.begin(subtransactions=True):
@ -828,6 +840,16 @@ class NsxVPluginV2(agents_db.AgentDbMixin,
port["port"].update(neutron_db)
has_ip = self._ip_on_port(neutron_db)
# allowed address pair checks
attrs = port[attr.PORT]
if self._check_update_has_allowed_address_pairs(port):
if not port_security:
raise addr_pair.AddressPairAndPortSecurityRequired()
self._validate_address_pairs(attrs, neutron_db)
else:
# remove ATTR_NOT_SPECIFIED
attrs[addr_pair.ADDRESS_PAIRS] = []
# security group extension checks
if has_ip:
self._ensure_default_security_group_on_port(context, port)
@ -840,6 +862,11 @@ class NsxVPluginV2(agents_db.AgentDbMixin,
self._process_portbindings_create_and_update(context,
port['port'],
port_data)
neutron_db[addr_pair.ADDRESS_PAIRS] = (
self._process_create_allowed_address_pairs(
context, neutron_db,
attrs.get(addr_pair.ADDRESS_PAIRS)))
try:
# Configure NSX - this should not be done in the DB transaction
# Configure the DHCP Edge service
@ -852,8 +879,11 @@ class NsxVPluginV2(agents_db.AgentDbMixin,
return port_data
def update_port(self, context, id, port):
attrs = port[attr.PORT]
port_data = port['port']
original_port = super(NsxVPluginV2, self).get_port(context, id)
if addr_pair.ADDRESS_PAIRS in attrs:
self._validate_address_pairs(attrs, original_port)
is_compute_port = self._is_compute_port(original_port)
device_id = original_port['device_id']
has_port_security = (cfg.CONF.nsxv.spoofguard_enabled and
@ -928,6 +958,11 @@ class NsxVPluginV2(agents_db.AgentDbMixin,
port['port'],
ret_port)
if addr_pair.ADDRESS_PAIRS in attrs:
self.update_address_pairs_on_port(context, id, port,
original_port,
ret_port)
if comp_owner_update:
# Create dhcp bindings, the port is now owned by an instance
self._create_dhcp_static_binding(context, ret_port)
@ -2045,6 +2080,9 @@ class NsxVPluginV2(agents_db.AgentDbMixin,
session, port['network_id'])
mac_addr = port['mac_address']
approved_addrs = [addr['ip_address'] for addr in port['fixed_ips']]
# add in the address pair
approved_addrs.extend(
addr['ip_address'] for addr in port[addr_pair.ADDRESS_PAIRS])
self.nsx_v.vcns.approve_assigned_addresses(
sg_policy_id, vnic_id, mac_addr, approved_addrs)
self.nsx_v.vcns.publish_assigned_addresses(sg_policy_id, vnic_id)

View File

@ -12,11 +12,14 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from neutron.extensions import allowedaddresspairs as addr_pair
from neutron.extensions import portsecurity as psec
from neutron.tests.unit.db import test_allowedaddresspairs_db as ext_pairs
from vmware_nsx.tests.unit.nsx_mh import test_plugin as test_nsx_plugin
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_nsx_v_plugin
from vmware_nsx.tests.unit.nsx_v3 import test_constants as v3_constants
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_v3_plugin
@ -48,3 +51,106 @@ class TestAllowedAddressPairsNSXv3(test_v3_plugin.NsxV3PluginTestCaseMixin,
def test_create_port_security_false_allowed_address_pairs(self):
self.skipTest('TBD')
class TestAllowedAddressPairsNSXv(test_nsx_v_plugin.NsxVPluginV2TestCase,
ext_pairs.TestAllowedAddressPairs):
def setUp(self, plugin='vmware_nsx.plugin.NsxVPlugin',
ext_mgr=None,
service_plugins=None):
super(TestAllowedAddressPairsNSXv, self).setUp(
plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins)
def test_create_port_security_false_allowed_address_pairs(self):
self.skipTest('TBD')
def test_update_port_security_off_address_pairs(self):
self.skipTest('Not supported')
def test_create_overlap_with_fixed_ip(self):
address_pairs = [{'ip_address': '10.0.0.2'}]
with self.network() as network:
with self.subnet(network=network, cidr='10.0.0.0/24',
enable_dhcp=False) as subnet:
fixed_ips = [{'subnet_id': subnet['subnet']['id'],
'ip_address': '10.0.0.2'}]
res = self._create_port(self.fmt, network['network']['id'],
arg_list=(addr_pair.ADDRESS_PAIRS,
'fixed_ips'),
allowed_address_pairs=address_pairs,
fixed_ips=fixed_ips)
self.assertEqual(res.status_int, 201)
port = self.deserialize(self.fmt, res)
self._delete('ports', port['port']['id'])
def test_create_port_allowed_address_pairs(self):
with self.network() as net:
address_pairs = [{'ip_address': '10.0.0.1'}]
res = self._create_port(self.fmt, net['network']['id'],
arg_list=(addr_pair.ADDRESS_PAIRS,),
allowed_address_pairs=address_pairs)
port = self.deserialize(self.fmt, res)
address_pairs[0]['mac_address'] = port['port']['mac_address']
self.assertEqual(port['port'][addr_pair.ADDRESS_PAIRS],
address_pairs)
self._delete('ports', port['port']['id'])
def test_create_port_remove_allowed_address_pairs(self):
with self.network() as net:
address_pairs = [{'ip_address': '10.0.0.1'}]
res = self._create_port(self.fmt, net['network']['id'],
arg_list=(addr_pair.ADDRESS_PAIRS,),
allowed_address_pairs=address_pairs)
port = self.deserialize(self.fmt, res)
update_port = {'port': {addr_pair.ADDRESS_PAIRS: []}}
req = self.new_update_request('ports', update_port,
port['port']['id'])
port = self.deserialize(self.fmt, req.get_response(self.api))
self.assertEqual(port['port'][addr_pair.ADDRESS_PAIRS], [])
self._delete('ports', port['port']['id'])
def test_update_add_address_pairs(self):
with self.network() as net:
res = self._create_port(self.fmt, net['network']['id'])
port = self.deserialize(self.fmt, res)
address_pairs = [{'ip_address': '10.0.0.1'}]
update_port = {'port': {addr_pair.ADDRESS_PAIRS:
address_pairs}}
req = self.new_update_request('ports', update_port,
port['port']['id'])
port = self.deserialize(self.fmt, req.get_response(self.api))
address_pairs[0]['mac_address'] = port['port']['mac_address']
self.assertEqual(port['port'][addr_pair.ADDRESS_PAIRS],
address_pairs)
self._delete('ports', port['port']['id'])
def test_mac_configuration(self):
address_pairs = [{'mac_address': '00:00:00:00:00:01',
'ip_address': '10.0.0.1'}]
self._create_port_with_address_pairs(address_pairs, 400)
def test_equal_to_max_allowed_address_pair(self):
cfg.CONF.set_default('max_allowed_address_pair', 3)
address_pairs = [{'ip_address': '10.0.0.1'},
{'ip_address': '10.0.0.2'},
{'ip_address': '10.0.0.3'}]
self._create_port_with_address_pairs(address_pairs, 201)
def test_create_port_security_true_allowed_address_pairs(self):
if self._skip_port_security:
self.skipTest("Plugin does not implement port-security extension")
with self.network() as net:
address_pairs = [{'ip_address': '10.0.0.1'}]
res = self._create_port(self.fmt, net['network']['id'],
arg_list=('port_security_enabled',
addr_pair.ADDRESS_PAIRS,),
port_security_enabled=True,
allowed_address_pairs=address_pairs)
port = self.deserialize(self.fmt, res)
self.assertTrue(port['port'][psec.PORTSECURITY])
address_pairs[0]['mac_address'] = port['port']['mac_address']
self.assertEqual(port['port'][addr_pair.ADDRESS_PAIRS],
address_pairs)
self._delete('ports', port['port']['id'])