Merge "NSX|P: support policy MDproxy"
This commit is contained in:
commit
12d9382870
@ -961,10 +961,7 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
def _default_physical_net(self, physical_net):
|
||||
return physical_net is None or physical_net == 'default'
|
||||
|
||||
def _validate_provider_create(self, context, network_data,
|
||||
default_vlan_tz_uuid,
|
||||
default_overlay_tz_uuid,
|
||||
mdproxy_uuid,
|
||||
def _validate_provider_create(self, context, network_data, az,
|
||||
nsxlib_tz, nsxlib_network,
|
||||
transparent_vlan=False):
|
||||
"""Validate the parameters of a new provider network
|
||||
@ -977,6 +974,11 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
- vlan_id: vlan tag, 0 or None
|
||||
- switch_mode: standard or ENS
|
||||
"""
|
||||
# initialize the relevant parameters from the AZ
|
||||
default_vlan_tz_uuid = az._default_vlan_tz_uuid
|
||||
default_overlay_tz_uuid = az._default_overlay_tz_uuid
|
||||
mdproxy_uuid = az._native_md_proxy_uuid
|
||||
|
||||
is_provider_net = any(
|
||||
validators.is_attr_set(network_data.get(f))
|
||||
for f in (pnet.NETWORK_TYPE,
|
||||
@ -1107,9 +1109,10 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
switch_mode = nsxlib_tz.get_host_switch_mode(physical_net)
|
||||
|
||||
# validate the mdproxy TZ matches this one.
|
||||
if (not err_msg and physical_net and self.nsxlib and
|
||||
if (not err_msg and physical_net and
|
||||
self._has_native_dhcp_metadata()):
|
||||
if not self._validate_net_mdproxy_tz(physical_net, mdproxy_uuid):
|
||||
if not self._validate_net_mdproxy_tz(
|
||||
az, physical_net, mdproxy_uuid):
|
||||
err_msg = (_('Network TZ %(tz)s does not match MD proxy '
|
||||
'%(md)s edge cluster') %
|
||||
{'tz': physical_net, 'md': mdproxy_uuid})
|
||||
@ -1129,19 +1132,11 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
'vlan_id': vlan_id,
|
||||
'switch_mode': switch_mode}
|
||||
|
||||
def _validate_net_mdproxy_tz(self, tz_uuid, mdproxy_uuid):
|
||||
"""Validate that the network TZ matches the mdproxy edge cluster"""
|
||||
# TODO(asarfaty): separate the validation when using policy mdproxy
|
||||
mdproxy_obj = self.nsxlib.native_md_proxy.get(mdproxy_uuid)
|
||||
ec_id = mdproxy_obj['edge_cluster_id']
|
||||
ec_nodes = self.nsxlib.edge_cluster.get_transport_nodes(ec_id)
|
||||
ec_tzs = []
|
||||
for tn_uuid in ec_nodes:
|
||||
ec_tzs.extend(self.nsxlib.transport_node.get_transport_zones(
|
||||
tn_uuid))
|
||||
if tz_uuid not in ec_tzs:
|
||||
return False
|
||||
return True
|
||||
def _validate_net_mdproxy_tz(self, az, tz_uuid, mdproxy_uuid):
|
||||
"""Validate that the network TZ matches the mdproxy edge cluster
|
||||
Should be implemented by each plugin.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _network_is_nsx_net(self, context, network_id):
|
||||
bindings = nsx_db.get_network_bindings(context.session, network_id)
|
||||
@ -1944,18 +1939,15 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
{'router': {az_def.AZ_HINTS: az_hints}})
|
||||
|
||||
def get_network_availability_zones(self, net_db):
|
||||
if self._has_native_dhcp_metadata():
|
||||
hints = az_validator.convert_az_string_to_list(
|
||||
net_db[az_def.AZ_HINTS])
|
||||
# When using the configured AZs, the az will always be the same
|
||||
# as the hint (or default if none)
|
||||
if hints:
|
||||
az_name = hints[0]
|
||||
else:
|
||||
az_name = self.get_default_az().name
|
||||
return [az_name]
|
||||
hints = az_validator.convert_az_string_to_list(
|
||||
net_db[az_def.AZ_HINTS])
|
||||
# When using the configured AZs, the az will always be the same
|
||||
# as the hint (or default if none)
|
||||
if hints:
|
||||
az_name = hints[0]
|
||||
else:
|
||||
return []
|
||||
az_name = self.get_default_az().name
|
||||
return [az_name]
|
||||
|
||||
def _get_router_az_obj(self, router):
|
||||
l3_attrs_db.ExtraAttributesMixin._extend_extra_router_dict(
|
||||
@ -1973,11 +1965,6 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
force=True)
|
||||
|
||||
def _list_availability_zones(self, context, filters=None):
|
||||
# If no native_dhcp_metadata - use neutron AZs
|
||||
if not self._has_native_dhcp_metadata():
|
||||
return super(NsxPluginV3Base, self)._list_availability_zones(
|
||||
context, filters=filters)
|
||||
|
||||
result = {}
|
||||
for az in self._availability_zones_data.list_availability_zones():
|
||||
# Add this availability zone as a network & router resource
|
||||
@ -1996,10 +1983,6 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
if self._is_sub_plugin and not force:
|
||||
# validation should be done together for both plugins
|
||||
return
|
||||
# If no native_dhcp_metadata - use neutron AZs
|
||||
if not self._has_native_dhcp_metadata():
|
||||
return super(NsxPluginV3Base, self).validate_availability_zones(
|
||||
context, resource_type, availability_zones)
|
||||
# Validate against the configured AZs
|
||||
return self.validate_obj_azs(availability_zones)
|
||||
|
||||
@ -2692,7 +2675,8 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
net_name or 'network'),
|
||||
net_id)
|
||||
|
||||
def _create_net_mdproxy_port(self, context, network, az, nsx_net_id):
|
||||
def _create_net_mp_mdproxy_port(self, context, network, az, nsx_net_id):
|
||||
"""Add MD proxy on the MP logical-switch by creating a logical port"""
|
||||
if (not self.nsxlib or
|
||||
not self._has_native_dhcp_metadata()):
|
||||
return
|
||||
|
@ -21,6 +21,7 @@ from vmware_nsx.common import config
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.plugins.common_v3 import availability_zones as v3_az
|
||||
from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
from vmware_nsxlib.v3.policy import utils as p_utils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
@ -136,13 +137,37 @@ class NsxPAvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
||||
auto_config=True, is_mandatory=False,
|
||||
search_scope=search_scope)
|
||||
|
||||
self.use_policy_md = False
|
||||
if (nsxpolicy.feature_supported(
|
||||
nsx_constants.FEATURE_NSX_POLICY_MDPROXY)):
|
||||
# Try to initialize md-proxy from the policy
|
||||
try:
|
||||
self._native_md_proxy_uuid = self._init_default_resource(
|
||||
nsxpolicy, nsxpolicy.md_proxy, 'metadata_proxy',
|
||||
auto_config=True, is_mandatory=True,
|
||||
search_scope=search_scope)
|
||||
LOG.info("NSX-P az using policy MD proxy: %s",
|
||||
self._native_md_proxy_uuid)
|
||||
self.use_policy_md = True
|
||||
except Exception:
|
||||
LOG.info("NSX-P az could not use policy MD proxy. Using MP "
|
||||
"one instead")
|
||||
|
||||
if not self.use_policy_md:
|
||||
# Try to initialize md-proxy from the MP
|
||||
if nsxlib:
|
||||
self._translate_metadata_proxy(
|
||||
nsxlib, search_scope=search_scope)
|
||||
LOG.info("NSX-P az using MP MD proxy: %s",
|
||||
self._native_md_proxy_uuid)
|
||||
else:
|
||||
self._native_md_proxy_uuid = None
|
||||
|
||||
# If passthrough api is supported, also initialize those NSX objects
|
||||
if nsxlib:
|
||||
self._translate_dhcp_profile(nsxlib, search_scope=search_scope)
|
||||
self._translate_metadata_proxy(nsxlib, search_scope=search_scope)
|
||||
else:
|
||||
self._native_dhcp_profile_uuid = None
|
||||
self._native_md_proxy_uuid = None
|
||||
|
||||
def _get_edge_cluster_tzs(self, nsxpolicy, nsxlib, ec_uuid):
|
||||
ec_nodes = nsxpolicy.edge_cluster.get_edge_node_ids(ec_uuid)
|
||||
@ -207,8 +232,15 @@ class NsxPAvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
||||
dhcp_ec)
|
||||
|
||||
if self._native_md_proxy_uuid:
|
||||
md_ec = nsxlib.native_md_proxy.get(
|
||||
self._native_md_proxy_uuid).get('edge_cluster_id')
|
||||
# Validate that the edge cluster of the MD proxy (MP or policy one)
|
||||
# match the configured TZs
|
||||
if self.use_policy_md:
|
||||
md_ec_path = nsxpolicy.md_proxy.get(
|
||||
self._native_md_proxy_uuid).get('edge_cluster_path')
|
||||
md_ec = p_utils.path_to_id(md_ec_path)
|
||||
else:
|
||||
md_ec = nsxlib.native_md_proxy.get(
|
||||
self._native_md_proxy_uuid).get('edge_cluster_id')
|
||||
if md_ec != tier0_ec_uuid:
|
||||
self._validate_tz(nsxpolicy, nsxlib, 'MD Proxy',
|
||||
self._native_md_proxy_uuid,
|
||||
|
@ -98,6 +98,7 @@ from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
|
||||
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
||||
from vmware_nsxlib.v3.policy import constants as policy_constants
|
||||
from vmware_nsxlib.v3.policy import core_defs as policy_defs
|
||||
from vmware_nsxlib.v3.policy import utils as p_utils
|
||||
from vmware_nsxlib.v3 import security
|
||||
from vmware_nsxlib.v3 import utils as nsxlib_utils
|
||||
|
||||
@ -586,7 +587,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
|
||||
def _create_network_on_backend(self, context, net_data,
|
||||
transparent_vlan,
|
||||
provider_data):
|
||||
provider_data, az):
|
||||
net_data['id'] = net_data.get('id') or uuidutils.generate_uuid()
|
||||
|
||||
# update the network name to indicate the neutron id too.
|
||||
@ -612,13 +613,18 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
else:
|
||||
vlan_ids = None
|
||||
|
||||
kwargs = {
|
||||
'segment_id': net_data['id'],
|
||||
'description': net_data.get('description'),
|
||||
'vlan_ids': vlan_ids,
|
||||
'transport_zone_id': provider_data['physical_net'],
|
||||
'tags': tags}
|
||||
|
||||
if az.use_policy_md:
|
||||
kwargs['metadata_proxy_id'] = az._native_md_proxy_uuid
|
||||
|
||||
self.nsxpolicy.segment.create_or_overwrite(
|
||||
net_name,
|
||||
segment_id=net_data['id'],
|
||||
description=net_data.get('description'),
|
||||
vlan_ids=vlan_ids,
|
||||
transport_zone_id=provider_data['physical_net'],
|
||||
tags=tags)
|
||||
net_name, **kwargs)
|
||||
|
||||
if not admin_state and cfg.CONF.nsx_p.allow_passthrough:
|
||||
# This api uses the passthrough api
|
||||
@ -691,10 +697,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
is_backend_network = False
|
||||
else:
|
||||
provider_data = self._validate_provider_create(
|
||||
context, net_data,
|
||||
az._default_vlan_tz_uuid,
|
||||
az._default_overlay_tz_uuid,
|
||||
az._native_md_proxy_uuid,
|
||||
context, net_data, az,
|
||||
self.nsxpolicy.transport_zone,
|
||||
self.nsxpolicy.segment,
|
||||
transparent_vlan=vlt)
|
||||
@ -739,7 +742,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
if is_backend_network:
|
||||
try:
|
||||
self._create_network_on_backend(
|
||||
context, created_net, vlt, provider_data)
|
||||
context, created_net, vlt, provider_data, az)
|
||||
except Exception as e:
|
||||
LOG.exception("Failed to create NSX network network: %s", e)
|
||||
with excutils.save_and_reraise_exception():
|
||||
@ -752,12 +755,13 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
resource_extend.apply_funcs('networks', created_net, net_model)
|
||||
|
||||
# MD Proxy is currently supported by the passthrough api only
|
||||
if is_backend_network and cfg.CONF.nsx_p.allow_passthrough:
|
||||
if (is_backend_network and not az.use_policy_md and
|
||||
cfg.CONF.nsx_p.allow_passthrough):
|
||||
try:
|
||||
# The new segment was not realized yet. Waiting for a bit.
|
||||
time.sleep(cfg.CONF.nsx_p.realization_wait_sec)
|
||||
nsx_net_id = self._get_network_nsx_id(context, net_id)
|
||||
self._create_net_mdproxy_port(
|
||||
self._create_net_mp_mdproxy_port(
|
||||
context, created_net, az, nsx_net_id)
|
||||
except Exception as e:
|
||||
LOG.exception("Failed to create mdproxy port for network %s: "
|
||||
@ -787,9 +791,13 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
# checks on active ports
|
||||
self._retry_delete_network(context, network_id)
|
||||
|
||||
# MD Proxy is currently supported by the passthrough api only.
|
||||
# Use it to delete mdproxy ports
|
||||
if not is_external_net and cfg.CONF.nsx_p.allow_passthrough:
|
||||
# Delete MD proxy port. This is relevant only if the plugin used
|
||||
# MP MD proxy when this network is created.
|
||||
# If not - the port will not be found, and it is ok.
|
||||
# Note(asarfaty): In the future this code can be removed.
|
||||
if (not is_external_net and cfg.CONF.nsx_p.allow_passthrough and
|
||||
not self.nsxpolicy.feature_supported(
|
||||
nsxlib_consts.FEATURE_NSX_POLICY_MDPROXY)):
|
||||
self._delete_nsx_port_by_network(network_id)
|
||||
|
||||
# Delete the network segment from the backend
|
||||
@ -3116,3 +3124,28 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
extra_rules.extend(vpn_rules)
|
||||
|
||||
return extra_rules
|
||||
|
||||
def _validate_net_mdproxy_tz(self, az, tz_uuid, mdproxy_uuid):
|
||||
"""Validate that the network TZ matches the mdproxy edge cluster"""
|
||||
if not self.nsxlib:
|
||||
# No passthrough api support
|
||||
return True
|
||||
|
||||
if az.use_policy_md:
|
||||
# Policy obj
|
||||
md_ec_path = self.nsxpolicy.md_proxy.get(
|
||||
mdproxy_uuid).get('edge_cluster_path')
|
||||
md_ec = p_utils.path_to_id(md_ec_path)
|
||||
else:
|
||||
# MP obj
|
||||
md_ec = self.nsxlib.native_md_proxy.get(
|
||||
mdproxy_uuid).get('edge_cluster_id')
|
||||
|
||||
ec_nodes = self.nsxlib.edge_cluster.get_transport_nodes(md_ec)
|
||||
ec_tzs = []
|
||||
for tn_uuid in ec_nodes:
|
||||
ec_tzs.extend(self.nsxlib.transport_node.get_transport_zones(
|
||||
tn_uuid))
|
||||
if tz_uuid not in ec_tzs:
|
||||
return False
|
||||
return True
|
||||
|
@ -815,10 +815,7 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
def _create_network_at_the_backend(self, context, net_data, az,
|
||||
transparent_vlan):
|
||||
provider_data = self._validate_provider_create(
|
||||
context, net_data,
|
||||
az._default_vlan_tz_uuid,
|
||||
az._default_overlay_tz_uuid,
|
||||
az._native_md_proxy_uuid,
|
||||
context, net_data, az,
|
||||
self.nsxlib.transport_zone,
|
||||
self.nsxlib.logical_switch,
|
||||
transparent_vlan=transparent_vlan)
|
||||
@ -978,7 +975,7 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
resource_extend.apply_funcs('networks', created_net, net_model)
|
||||
|
||||
if is_backend_network:
|
||||
self._create_net_mdproxy_port(
|
||||
self._create_net_mp_mdproxy_port(
|
||||
context, created_net, az, nsx_net_id)
|
||||
|
||||
except Exception:
|
||||
@ -3442,3 +3439,16 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
if len(port_tags) != orig_len:
|
||||
self.nsxlib.logical_port.update(
|
||||
nsx_lport_id, False, tags=port_tags)
|
||||
|
||||
def _validate_net_mdproxy_tz(self, az, tz_uuid, mdproxy_uuid):
|
||||
"""Validate that the network TZ matches the mdproxy edge cluster"""
|
||||
mdproxy_obj = self.nsxlib.native_md_proxy.get(mdproxy_uuid)
|
||||
ec_id = mdproxy_obj['edge_cluster_id']
|
||||
ec_nodes = self.nsxlib.edge_cluster.get_transport_nodes(ec_id)
|
||||
ec_tzs = []
|
||||
for tn_uuid in ec_nodes:
|
||||
ec_tzs.extend(self.nsxlib.transport_node.get_transport_zones(
|
||||
tn_uuid))
|
||||
if tz_uuid not in ec_tzs:
|
||||
return False
|
||||
return True
|
||||
|
@ -919,7 +919,8 @@ class NsxNativeMetadataTestCase(test_plugin.NsxPPluginTestCaseMixin):
|
||||
|
||||
def test_metadata_proxy_with_create_network(self):
|
||||
# Test if native metadata proxy is enabled on a network when it is
|
||||
# created.
|
||||
# created (Using MP MDproxy).
|
||||
self.plugin._availability_zones_data._default_az.use_policy_md = False
|
||||
with mock.patch.object(nsx_resources.LogicalPort,
|
||||
'create') as create_logical_port:
|
||||
with self.network() as network:
|
||||
@ -938,7 +939,9 @@ class NsxNativeMetadataTestCase(test_plugin.NsxPPluginTestCaseMixin):
|
||||
|
||||
def test_metadata_proxy_with_create_az_network(self):
|
||||
# Test if native metadata proxy is enabled on a network when it is
|
||||
# created.
|
||||
# created (Using MP MDproxy).
|
||||
azs = self.plugin._availability_zones_data.availability_zones
|
||||
azs[self._az_name].use_policy_md = False
|
||||
with mock.patch.object(nsx_resources.LogicalPort,
|
||||
'create') as create_logical_port:
|
||||
with self.network(
|
||||
|
@ -100,7 +100,7 @@ class NsxPPluginTestCaseMixin(
|
||||
'display_name': 'test'}]}
|
||||
mock.patch(
|
||||
"vmware_nsxlib.v3.policy.NsxPolicyLib.get_version",
|
||||
return_value=nsx_constants.NSX_VERSION_2_5_0).start()
|
||||
return_value=nsx_constants.NSX_VERSION_3_0_0).start()
|
||||
mock.patch(
|
||||
"vmware_nsxlib.v3.client.RESTClient.get").start()
|
||||
mock.patch(
|
||||
@ -142,7 +142,7 @@ class NsxPPluginTestCaseMixin(
|
||||
return_value=nsxlib_utils.TagLimits(20, 40, 15)).start()
|
||||
# Add some nsxlib mocks for the passthrough apis
|
||||
mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
|
||||
return_value=nsx_constants.NSX_VERSION_2_5_0).start()
|
||||
return_value=nsx_constants.NSX_VERSION_3_0_0).start()
|
||||
mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter."
|
||||
"update").start()
|
||||
mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportNode."
|
||||
|
Loading…
Reference in New Issue
Block a user