Merge "NSXv: add address pair support"
This commit is contained in:
commit
516116f5ac
|
@ -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)
|
||||
|
|
|
@ -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'])
|
||||
|
|
Loading…
Reference in New Issue