NSX-V: add support for mac learning extension
Enable a port to set the mac learning property. This will configure the port group to be in 'forget transmit' and 'promiscuous'. This will enable an embedded hypervisor to be run with the NSX-V Mac learning can only be configured if there is no port security and security groups configured Change-Id: I9cb36d877669fbd682cb7a9c0a88a172a31aeebb
This commit is contained in:
parent
54a809c4fa
commit
006231cf7d
@ -66,3 +66,13 @@ class MacLearningDbMixin(object):
|
||||
mac_learning_enabled=enabled)
|
||||
context.session.add(state)
|
||||
return self._make_mac_learning_state_dict(state)
|
||||
|
||||
def get_mac_learning_state(self, context, port_id):
|
||||
try:
|
||||
query = model_query.query_with_hooks(
|
||||
context, nsx_models.MacLearningState)
|
||||
state = query.filter(
|
||||
nsx_models.MacLearningState.port_id == port_id).one()
|
||||
return state.mac_learning_enabled
|
||||
except exc.NoResultFound:
|
||||
return None
|
||||
|
@ -444,6 +444,36 @@ class DvsManager(VCManagerBase):
|
||||
port_conf = pg_spec.defaultPortConfig
|
||||
port_conf.vlan = self._get_trunk_vlan_spec()
|
||||
|
||||
def update_port_group_security_policy(self, pg_spec, status):
|
||||
policy = pg_spec.policy
|
||||
policy.securityPolicyOverrideAllowed = status
|
||||
|
||||
def _update_port_security_policy(self, dvs_moref, port, status):
|
||||
client_factory = self._session.vim.client.factory
|
||||
ps = client_factory.create('ns0:DVPortConfigSpec')
|
||||
ps.key = port.portKey
|
||||
ps.operation = 'edit'
|
||||
policy = client_factory.create('ns0:DVSSecurityPolicy')
|
||||
bp = client_factory.create('ns0:BoolPolicy')
|
||||
bp.inherited = False
|
||||
bp.value = status
|
||||
policy.allowPromiscuous = bp
|
||||
policy.forgedTransmits = bp
|
||||
policy.inherited = False
|
||||
setting = client_factory.create('ns0:VMwareDVSPortSetting')
|
||||
setting.securityPolicy = policy
|
||||
ps.setting = setting
|
||||
task = self._session.invoke_api(self._session.vim,
|
||||
'ReconfigureDVPort_Task',
|
||||
dvs_moref,
|
||||
port=ps)
|
||||
try:
|
||||
self._session.wait_for_task(task)
|
||||
LOG.info("Updated port security status")
|
||||
except Exception as e:
|
||||
LOG.error("Failed to update port %s. Reason: %s",
|
||||
port.key, e)
|
||||
|
||||
|
||||
class VMManager(VCManagerBase):
|
||||
"""Management class for VMs related VC tasks."""
|
||||
@ -567,6 +597,25 @@ class VMManager(VCManagerBase):
|
||||
"config.hardware.device")
|
||||
return hardware_devices
|
||||
|
||||
def _get_device_port(self, device_id, mac_address):
|
||||
vm_moref = self.get_vm_moref_obj(device_id)
|
||||
hardware_devices = self.get_vm_interfaces_info(vm_moref)
|
||||
if not hardware_devices:
|
||||
return
|
||||
if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
|
||||
hardware_devices = hardware_devices.VirtualDevice
|
||||
for device in hardware_devices:
|
||||
if hasattr(device, 'macAddress'):
|
||||
if device.macAddress == mac_address:
|
||||
return device.backing.port
|
||||
|
||||
def update_port_security_policy(self, dvs_id, net_id, net_moref,
|
||||
device_id, mac_address, status):
|
||||
dvs_moref = self._get_dvs_moref_by_id(dvs_id)
|
||||
port = self._get_device_port(device_id, mac_address)
|
||||
if port:
|
||||
self._update_port_security_policy(dvs_moref, port, status)
|
||||
|
||||
|
||||
class ClusterManager(VCManagerBase):
|
||||
"""Management class for Cluster related VC tasks."""
|
||||
|
@ -104,6 +104,7 @@ from vmware_nsx.db import (
|
||||
routertype as rt_rtr)
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.db import extended_security_group as extended_secgroup
|
||||
from vmware_nsx.db import maclearning as mac_db
|
||||
from vmware_nsx.db import nsx_portbindings_db as pbin_db
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.db import vnic_index_db
|
||||
@ -113,6 +114,7 @@ from vmware_nsx.extensions import (
|
||||
vnicindex as ext_vnic_idx)
|
||||
from vmware_nsx.extensions import dhcp_mtu as ext_dhcp_mtu
|
||||
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain
|
||||
from vmware_nsx.extensions import maclearning as mac_ext
|
||||
from vmware_nsx.extensions import nsxpolicy
|
||||
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
||||
from vmware_nsx.extensions import routersize
|
||||
@ -163,7 +165,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
vnic_index_db.VnicIndexDbMixin,
|
||||
dns_db.DNSDbMixin, nsxpolicy.NsxPolicyPluginBase,
|
||||
vlantransparent_db.Vlantransparent_db_mixin,
|
||||
nsx_com_az.NSXAvailabilityZonesPluginCommon):
|
||||
nsx_com_az.NSXAvailabilityZonesPluginCommon,
|
||||
mac_db.MacLearningDbMixin):
|
||||
|
||||
supported_extension_aliases = ["agent",
|
||||
"allowed-address-pairs",
|
||||
@ -193,7 +196,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
"router_availability_zone",
|
||||
"l3-flavors",
|
||||
"flavors",
|
||||
"dhcp-mtu"]
|
||||
"dhcp-mtu",
|
||||
"mac-learning"]
|
||||
|
||||
__native_bulk_support = True
|
||||
__native_pagination_support = True
|
||||
@ -1778,6 +1782,20 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
|
||||
self._process_port_create_extra_dhcp_opts(
|
||||
context, port_data, dhcp_opts)
|
||||
# MAC learning - only update DB. Can only update NSX when the port
|
||||
# exists - this is done via update
|
||||
if validators.is_attr_set(port_data.get(mac_ext.MAC_LEARNING)):
|
||||
if (((has_ip and port_security) or
|
||||
has_security_groups or provider_sg_specified) and
|
||||
port_data.get(mac_ext.MAC_LEARNING) is True):
|
||||
err_msg = _("Security features are not supported for "
|
||||
"mac learning.")
|
||||
raise n_exc.InvalidInput(error_message=err_msg)
|
||||
self._create_mac_learning_state(context, port_data)
|
||||
elif mac_ext.MAC_LEARNING in port_data:
|
||||
# This is due to the fact that the default is
|
||||
# ATTR_NOT_SPECIFIED
|
||||
port_data.pop(mac_ext.MAC_LEARNING)
|
||||
|
||||
try:
|
||||
# Configure NSX - this should not be done in the DB transaction
|
||||
@ -1909,6 +1927,30 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
self.edge_manager.update_dhcp_edge_service(
|
||||
context, network_id, address_groups=address_groups)
|
||||
|
||||
def _nsx_update_mac_learning(self, context, port):
|
||||
net_id = port['network_id']
|
||||
# default dvs for this network
|
||||
az = self.get_network_az_by_net_id(context, net_id)
|
||||
az_dvs_id = az.dvs_id
|
||||
|
||||
# get the network moref/s from the db
|
||||
net_mappings = nsx_db.get_nsx_network_mappings(
|
||||
context.session, net_id)
|
||||
for mapping in net_mappings:
|
||||
dvs_id = mapping.dvs_id or az_dvs_id
|
||||
try:
|
||||
self._vcm.update_port_groups_config(
|
||||
dvs_id, net_id, mapping.nsx_id,
|
||||
self._vcm.update_port_group_security_policy, True)
|
||||
except Exception as e:
|
||||
LOG.error("Unable to update network security override "
|
||||
"policy: %s", e)
|
||||
return
|
||||
self._vcm.update_port_security_policy(
|
||||
dvs_id, net_id, mapping.nsx_id,
|
||||
port['device_id'], port['mac_address'],
|
||||
port[mac_ext.MAC_LEARNING])
|
||||
|
||||
def _update_port(self, context, id, port, original_port, is_compute_port,
|
||||
device_id):
|
||||
attrs = port[port_def.RESOURCE_NAME]
|
||||
@ -1995,6 +2037,13 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
err_msg = _("Security features are not supported for "
|
||||
"ports with direct/direct-physical VNIC type.")
|
||||
raise n_exc.InvalidInput(error_message=err_msg)
|
||||
if (mac_ext.MAC_LEARNING in port_data and
|
||||
port_data[mac_ext.MAC_LEARNING] is True and
|
||||
has_port_security):
|
||||
err_msg = _("Security features are not supported for "
|
||||
"mac_learning.")
|
||||
raise n_exc.InvalidInput(error_message=err_msg)
|
||||
old_mac_learning_state = original_port.get(mac_ext.MAC_LEARNING)
|
||||
|
||||
with db_api.context_manager.writer.using(context):
|
||||
ret_port = super(NsxVPluginV2, self).update_port(
|
||||
@ -2037,6 +2086,11 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
|
||||
self._update_extra_dhcp_opts_on_port(context, id, port,
|
||||
ret_port)
|
||||
new_mac_learning_state = ret_port.get(mac_ext.MAC_LEARNING)
|
||||
if (new_mac_learning_state is not None and
|
||||
old_mac_learning_state != new_mac_learning_state):
|
||||
self._update_mac_learning_state(context, id,
|
||||
new_mac_learning_state)
|
||||
|
||||
if comp_owner_update:
|
||||
# Create dhcp bindings, the port is now owned by an instance
|
||||
@ -2180,6 +2234,15 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
self._update_security_groups_port_mapping(
|
||||
context.session, id, vnic_id, curr_sgids, new_sgids)
|
||||
|
||||
# update mac learning on NSX
|
||||
if self._vcm:
|
||||
mac_learning = self.get_mac_learning_state(context, id)
|
||||
if mac_learning is not None:
|
||||
try:
|
||||
self._nsx_update_mac_learning(context, ret_port)
|
||||
except Exception as e:
|
||||
LOG.error("Unable to update mac learning for port %s, "
|
||||
"reason: %s", id, e)
|
||||
return ret_port
|
||||
|
||||
def delete_port(self, context, id, l3_port_check=True,
|
||||
|
Loading…
Reference in New Issue
Block a user