NSX|P: Validate availability zones

At plugin init, validate that tier0, default TZs, and dhcp conf
are all connected to the same transport zones.

Change-Id: I240c527ac53ea42680bf8810762f708a330f9b3e
This commit is contained in:
Adit Sarfaty 2019-07-15 13:40:06 +03:00
parent d37be7b5c2
commit 3a6a78046b
3 changed files with 81 additions and 0 deletions

View File

@ -21,6 +21,7 @@ from vmware_nsx.common import config
from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.common import exceptions as nsx_exc
from vmware_nsx.plugins.common_v3 import availability_zones as v3_az 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 exceptions as nsx_lib_exc
from vmware_nsxlib.v3.policy import utils as p_utils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -143,6 +144,76 @@ class NsxPAvailabilityZone(v3_az.NsxV3AvailabilityZone):
self._native_dhcp_profile_uuid = None self._native_dhcp_profile_uuid = None
self._native_md_proxy_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)
ec_tzs = []
for tn_uuid in ec_nodes:
ec_tzs.extend(nsxlib.transport_node.get_transport_zones(
tn_uuid))
return ec_tzs
def _validate_tz(self, nsxpolicy, nsxlib, obj_type, obj_id, ec_uuid):
obj_tzs = self._get_edge_cluster_tzs(nsxpolicy, nsxlib, ec_uuid)
if self._default_overlay_tz_uuid not in obj_tzs:
msg = (_("%(type)s %(id)s of availability zone %(az)s with edge "
"cluster %(ec)s does not match the default overlay tz "
"%(tz)s") % {
'type': obj_type,
'id': obj_id,
'ec': ec_uuid,
'tz': self._default_overlay_tz_uuid,
'az': self.name})
raise nsx_exc.NsxPluginException(err_msg=msg)
if (self._default_vlan_tz_uuid and
self._default_vlan_tz_uuid not in obj_tzs):
msg = (_("%(type)s %(id)s of availability zone %(az)s with edge "
"cluster %(ec)s does not match the default vlan tz "
"%(tz)s") % {
'id': obj_id,
'ec': ec_uuid,
'tz': self._default_vlan_tz_uuid,
'az': self.name})
raise nsx_exc.NsxPluginException(err_msg=msg)
def validate_availability_zone(self, nsxpolicy, nsxlib=None):
"""Validate that all the components of this AZ are connected"""
if not nsxlib:
LOG.warning("Cannot validate availability zone %s without "
"passthrough api", self.name)
return
# Validate tier0 TZ match the default ones
tier0_ec_path = nsxpolicy.tier0.get_edge_cluster_path(
self._default_tier0_router)
if not tier0_ec_path:
msg = (_("Tier0 %(id)s of availability zone %(az)s does not have "
"an edge cluster") % {
'id': self._default_tier0_router,
'az': self.name})
raise nsx_exc.NsxPluginException(err_msg=msg)
tier0_ec_uuid = p_utils.path_to_id(tier0_ec_path)
self._validate_tz(nsxpolicy, nsxlib, 'Tier0',
self._default_tier0_router,
tier0_ec_uuid)
if self._native_dhcp_profile_uuid:
dhcp_ec = nsxlib.native_dhcp_profile.get(
self._native_dhcp_profile_uuid).get('edge_cluster_id')
if dhcp_ec != tier0_ec_uuid:
self._validate_tz(nsxpolicy, nsxlib, 'DHCP profile',
self._native_dhcp_profile_uuid,
dhcp_ec)
if self._native_md_proxy_uuid:
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,
md_ec)
class NsxPAvailabilityZones(common_az.ConfiguredAvailabilityZones): class NsxPAvailabilityZones(common_az.ConfiguredAvailabilityZones):

View File

@ -280,6 +280,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
for az in self.get_azs_list(): for az in self.get_azs_list():
az.translate_configured_names_to_uuids( az.translate_configured_names_to_uuids(
self.nsxpolicy, nsxlib=self.nsxlib, search_scope=search_scope) self.nsxpolicy, nsxlib=self.nsxlib, search_scope=search_scope)
az.validate_availability_zone(self.nsxpolicy, nsxlib=self.nsxlib)
# WAF is currently not supported by the NSX # WAF is currently not supported by the NSX
self._waf_profile_uuid = None self._waf_profile_uuid = None

View File

@ -133,6 +133,11 @@ class NsxPPluginTestCaseMixin(
"NsxPolicySegmentApi.set_admin_state").start() "NsxPolicySegmentApi.set_admin_state").start()
mock.patch("vmware_nsxlib.v3.policy.core_resources." mock.patch("vmware_nsxlib.v3.policy.core_resources."
"NsxPolicySegmentPortApi.set_admin_state").start() "NsxPolicySegmentPortApi.set_admin_state").start()
mock.patch("vmware_nsxlib.v3.policy.core_resources.NsxPolicyTier0Api."
"get_edge_cluster_path", return_value="x/1").start()
mock.patch("vmware_nsxlib.v3.policy.core_resources."
"NsxPolicyEdgeClusterApi.get_edge_node_ids",
return_value=["node1"]).start()
mock.patch("vmware_nsxlib.v3.NsxLib.get_tag_limits", mock.patch("vmware_nsxlib.v3.NsxLib.get_tag_limits",
return_value=nsxlib_utils.TagLimits(20, 40, 15)).start() return_value=nsxlib_utils.TagLimits(20, 40, 15)).start()
# Add some nsxlib mocks for the passthrough apis # Add some nsxlib mocks for the passthrough apis
@ -140,6 +145,10 @@ class NsxPPluginTestCaseMixin(
return_value=nsx_constants.NSX_VERSION_2_5_0).start() return_value=nsx_constants.NSX_VERSION_2_5_0).start()
mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter." mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter."
"update").start() "update").start()
mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportNode."
"get_transport_zones",
return_value=[NSX_OVERLAY_TZ_NAME,
NSX_VLAN_TZ_NAME]).start()
def _mock_nsxlib_backend_calls(self): def _mock_nsxlib_backend_calls(self):
"""Mock nsxlib backend calls used as passthrough """Mock nsxlib backend calls used as passthrough