Policy pass-through api support

Adding basic support and config flag for the passthrough api.
This will use the nsx manager api for handling policy resources
fine tuning when there is no policy apis available.

Change-Id: I29cbbd570b8e3eea4f52fb13d01820fddd7b1cff
This commit is contained in:
Adit Sarfaty 2018-11-28 14:53:02 +02:00
parent e562087ec3
commit 90e97c4390
6 changed files with 160 additions and 44 deletions

View File

@ -126,7 +126,8 @@ def get_default_nsxlib_config():
plugin_tag=PLUGIN_TAG,
plugin_ver=PLUGIN_VER,
dns_nameservers=DNS_NAMESERVERS,
dns_domain=DNS_DOMAIN
dns_domain=DNS_DOMAIN,
allow_passthrough=True
)

View File

@ -33,7 +33,9 @@ class NsxPolicyLibTestCase(policy_testcase.TestPolicyApi):
super(NsxPolicyLibTestCase, self).setUp()
nsxlib_config = nsxlib_testcase.get_default_nsxlib_config()
self.policy_lib = v3.NsxPolicyLib(nsxlib_config)
# Mock the nsx-lib for the passthrough api
with mock.patch('vmware_nsxlib.v3.NsxLib'):
self.policy_lib = v3.NsxPolicyLib(nsxlib_config)
self.policy_api = self.policy_lib.policy_api
self.policy_api.client = self.client
@ -1864,6 +1866,34 @@ class TestPolicyTier1(NsxPolicyLibTestCase):
tier1_id, tenant=TEST_TENANT)
self.assertEqual(info, actual_info)
def test_update_transport_zone(self):
# Test the passthrough api
tier1_id = '111'
logical_router_id = 'realized_111'
tz_uuid = 'dummy_tz'
info = {'state': policy_constants.STATE_REALIZED,
'entity_type': 'RealizedLogicalRouter',
'realization_specific_identifier': logical_router_id}
passthrough_mock = self.resourceApi.nsx_api.logical_router.update
with mock.patch.object(self.resourceApi, "_get_realization_info",
return_value=info) as realization:
self.resourceApi.update_transport_zone(tier1_id, tz_uuid,
tenant=TEST_TENANT)
realization.assert_called_once()
passthrough_mock.assert_called_once_with(
logical_router_id, transport_zone_id=tz_uuid)
def test_wait_until_realized(self):
tier1_id = '111'
logical_router_id = 'realized_111'
info = {'state': policy_constants.STATE_UNREALIZED,
'realization_specific_identifier': logical_router_id}
with mock.patch.object(self.resourceApi, "_get_realization_info",
return_value=info):
self.assertRaises(nsxlib_exc.ManagerError,
self.resourceApi.wait_until_realized,
tier1_id, tenant=TEST_TENANT)
class TestPolicyTier1NatRule(NsxPolicyLibTestCase):
@ -2001,6 +2031,32 @@ class TestPolicyTier0(NsxPolicyLibTestCase):
self.assert_called_with_def(
update_call, expected_def)
def test_get_overlay_transport_zone(self):
# Test the passthrough api
tier0_id = '111'
logical_router_id = 'realized_111'
info = {'state': policy_constants.STATE_REALIZED,
'entity_type': 'RealizedLogicalRouter',
'realization_specific_identifier': logical_router_id}
pt_mock = self.resourceApi.nsx_api.router.get_tier0_router_overlay_tz
with mock.patch.object(self.resourceApi, "_get_realization_info",
return_value=info) as realization:
self.resourceApi.get_overlay_transport_zone(
tier0_id, tenant=TEST_TENANT)
realization.assert_called_once()
pt_mock.assert_called_once_with(logical_router_id)
def test_wait_until_realized(self):
tier1_id = '111'
logical_router_id = 'realized_111'
info = {'state': policy_constants.STATE_UNREALIZED,
'realization_specific_identifier': logical_router_id}
with mock.patch.object(self.resourceApi, "_get_realization_info",
return_value=info):
self.assertRaises(nsxlib_exc.ManagerError,
self.resourceApi.wait_until_realized,
tier1_id, tenant=TEST_TENANT)
class TestPolicySegmentProfileBase(NsxPolicyLibTestCase):

View File

@ -14,11 +14,11 @@
# under the License.
#
from vmware_nsxlib import v3
import mock
from vmware_nsxlib.tests.unit.v3 import nsxlib_testcase
from vmware_nsxlib.tests.unit.v3 import policy_testcase
from vmware_nsxlib import v3
from vmware_nsxlib.v3 import policy_transaction as trans
@ -29,7 +29,9 @@ class TestPolicyTransaction(policy_testcase.TestPolicyApi):
super(TestPolicyTransaction, self).setUp()
nsxlib_config = nsxlib_testcase.get_default_nsxlib_config()
self.policy_lib = v3.NsxPolicyLib(nsxlib_config)
# Mock the nsx-lib for the passthrough api
with mock.patch('vmware_nsxlib.v3.NsxLib'):
self.policy_lib = v3.NsxPolicyLib(nsxlib_config)
self.policy_api = self.policy_lib.policy_api
self.policy_api.client = self.client

View File

@ -14,6 +14,7 @@
# under the License.
import abc
import copy
from distutils import version
from oslo_log import log
@ -59,12 +60,11 @@ class NsxLibBase(object):
self.general_apis = utils.NsxLibApiBase(
self.client, self.nsxlib_config)
self.nsx_version = None
self.init_api()
super(NsxLibBase, self).__init__()
self.nsx_version = None
def set_config(self, nsxlib_config):
"""Set config user provided and extend it according to application"""
self.nsxlib_config = nsxlib_config
@ -380,46 +380,59 @@ class NsxLib(NsxLibBase):
class NsxPolicyLib(NsxLibBase):
def init_api(self):
# Initialize the policy client
self.policy_api = policy_defs.NsxPolicyApi(self.client)
self.domain = policy_resources.NsxPolicyDomainApi(self.policy_api)
self.group = policy_resources.NsxPolicyGroupApi(self.policy_api)
self.service = policy_resources.NsxPolicyL4ServiceApi(self.policy_api)
# NSX manager api will be used as a pass-through for apis which are
# not implemented by the policy manager yet
if self.nsxlib_config.allow_passthrough:
config = copy.deepcopy(self.nsxlib_config)
# X-Allow-Overwrite must be set for passthrough apis
config.allow_overwrite_header = True
self.nsx_api = NsxLib(config)
else:
self.nsx_api = None
self.nsx_version = self.get_version()
args = (self.policy_api, self.nsx_api, self.nsx_version)
# Initialize all the different resources
self.domain = policy_resources.NsxPolicyDomainApi(*args)
self.group = policy_resources.NsxPolicyGroupApi(*args)
self.service = policy_resources.NsxPolicyL4ServiceApi(*args)
self.icmp_service = policy_resources.NsxPolicyIcmpServiceApi(
self.policy_api)
*args)
self.ip_protocol_service = (
policy_resources.NsxPolicyIPProtocolServiceApi(
self.policy_api))
self.tier0 = policy_resources.NsxPolicyTier0Api(self.policy_api)
self.tier1 = policy_resources.NsxPolicyTier1Api(self.policy_api)
self.tier1_segment = policy_resources.NsxPolicyTier1SegmentApi(
self.policy_api)
policy_resources.NsxPolicyIPProtocolServiceApi(*args))
self.tier0 = policy_resources.NsxPolicyTier0Api(*args)
self.tier1 = policy_resources.NsxPolicyTier1Api(*args)
self.tier1_segment = policy_resources.NsxPolicyTier1SegmentApi(*args)
self.tier1_nat_rule = policy_resources.NsxPolicyTier1NatRuleApi(
self.policy_api)
self.segment = policy_resources.NsxPolicySegmentApi(self.policy_api)
*args)
self.segment = policy_resources.NsxPolicySegmentApi(*args)
self.segment_port = policy_resources.NsxPolicySegmentPortApi(
self.policy_api)
*args)
self.tier1_segment_port = (
policy_resources.NsxPolicyTier1SegmentPortApi(self.policy_api))
policy_resources.NsxPolicyTier1SegmentPortApi(*args))
self.comm_map = policy_resources.NsxPolicyCommunicationMapApi(
self.policy_api)
*args)
self.enforcement_point = policy_resources.NsxPolicyEnforcementPointApi(
self.policy_api)
*args)
self.transport_zone = policy_resources.NsxPolicyTransportZoneApi(
self.policy_api)
*args)
self.deployment_map = policy_resources.NsxPolicyDeploymentMapApi(
self.policy_api)
self.ip_block = policy_resources.NsxPolicyIpBlockApi(self.policy_api)
self.ip_pool = policy_resources.NsxPolicyIpPoolApi(self.policy_api)
*args)
self.ip_block = policy_resources.NsxPolicyIpBlockApi(*args)
self.ip_pool = policy_resources.NsxPolicyIpPoolApi(*args)
self.segment_security_profile = (
policy_resources.NsxSegmentSecurityProfileApi(self.policy_api))
policy_resources.NsxSegmentSecurityProfileApi(*args))
self.qos_profile = (
policy_resources.NsxQosProfileApi(self.policy_api))
policy_resources.NsxQosProfileApi(*args))
self.spoofguard_profile = (
policy_resources.NsxSpoofguardProfileApi(self.policy_api))
policy_resources.NsxSpoofguardProfileApi(*args))
self.ip_discovery_profile = (
policy_resources.NsxIpDiscoveryProfileApi(self.policy_api))
policy_resources.NsxIpDiscoveryProfileApi(*args))
self.mac_discovery_profile = (
policy_resources.NsxMacDiscoveryProfileApi(self.policy_api))
policy_resources.NsxMacDiscoveryProfileApi(*args))
@property
def keepalive_section(self):
@ -429,20 +442,16 @@ class NsxPolicyLib(NsxLibBase):
"""Get the NSX Policy manager version
Currently the backend does not support it, so the nsx-manager api
will be used temporarily.
will be used temporarily as a passthrough.
"""
if self.nsx_version:
return self.nsx_version
manager_client = client.NSX3Client(
self.cluster,
nsx_api_managers=self.nsxlib_config.nsx_api_managers,
max_attempts=self.nsxlib_config.max_attempts,
url_path_base=client.NSX3Client.NSX_V1_API_PREFIX,
rate_limit_retry=self.nsxlib_config.rate_limit_retry)
node = manager_client.get('node')
self.nsx_version = node.get('node_version')
if self.nsx_api:
self.nsx_version = self.nsx_api.get_version()
else:
# return the initial supported version
self.nsx_version = nsx_constants.NSX_VERSION_2_4_0
return self.nsx_version
def feature_supported(self, feature):
@ -454,6 +463,13 @@ class NsxPolicyLib(NsxLibBase):
return (feature == nsx_constants.FEATURE_NSX_POLICY)
def reinitialize_cluster(self, resource, event, trigger, payload=None):
super(NsxPolicyLib, self).reinitialize_cluster(
resource, event, trigger, payload=payload)
if self.nsx_api:
self.nsx_api.reinitialize_cluster(resource, event, trigger,
payload)
@property
def client_url_prefix(self):
return client.NSX3Client.NSX_POLICY_V1_API_PREFIX

View File

@ -78,6 +78,10 @@ class NsxLibConfig(object):
endpoint in the NSX management cluster is
available to serve a request, and retry
the request instead.
-- Additional parameters which are relevant only for the Policy manager:
:param allow_passthrough: If True, use nsx manager api for cases which are
not supported by the policy manager api.
"""
def __init__(self,
@ -102,7 +106,8 @@ class NsxLibConfig(object):
dhcp_profile_uuid=None,
allow_overwrite_header=False,
rate_limit_retry=True,
cluster_unavailable_retry=False):
cluster_unavailable_retry=False,
allow_passthrough=False):
self.nsx_api_managers = nsx_api_managers
self._username = username
@ -125,6 +130,7 @@ class NsxLibConfig(object):
self.allow_overwrite_header = allow_overwrite_header
self.rate_limit_retry = rate_limit_retry
self.cluster_unavailable_retry = cluster_unavailable_retry
self.allow_passthrough = allow_passthrough
if dhcp_profile_uuid:
# this is deprecated, and never used.

View File

@ -47,8 +47,10 @@ class NsxPolicyResourceBase(object):
"""
SINGLE_ENTRY_ID = 'entry'
def __init__(self, policy_api):
def __init__(self, policy_api, nsx_api, version):
self.policy_api = policy_api
self.nsx_api = nsx_api
self.version = version
@property
def entry_def(self):
@ -761,6 +763,23 @@ class NsxPolicyTier1Api(NsxPolicyResourceBase):
tier1_def = self.entry_def(tier1_id=tier1_id, tenant=tenant)
return self._wait_until_realized(tier1_def, entity_type=entity_type)
def update_transport_zone(self, tier1_id, transport_zone_id,
tenant=policy_constants.POLICY_INFRA_TENANT):
"""Use the pass-through api to update the TZ zone on the NSX router"""
if not self.nsx_api:
LOG.error("Cannot update tier1 %s transport zone as the "
"passthrough api is forbidden", tier1_id)
return
realization_info = self.wait_until_realized(
tier1_id, entity_type='RealizedLogicalRouter', tenant=tenant)
nsx_router_uuid = self.get_realized_id(
tier1_id, tenant=tenant, realization_info=realization_info)
self.nsx_api.logical_router.update(
nsx_router_uuid,
transport_zone_id=transport_zone_id)
class NsxPolicyTier0Api(NsxPolicyResourceBase):
"""NSX Tier0 API """
@ -838,6 +857,22 @@ class NsxPolicyTier0Api(NsxPolicyResourceBase):
if 'edge_cluster_path' in srv:
return srv['edge_cluster_path']
def get_overlay_transport_zone(
self, tier0_id,
tenant=policy_constants.POLICY_INFRA_TENANT):
"""Use the pass-through api to get the TZ zone of the NSX tier0"""
if not self.nsx_api:
LOG.error("Cannot get tier0 %s transport zone as the "
"passthrough api is forbidden", tier0_id)
return
realization_info = self.wait_until_realized(
tier0_id, entity_type='RealizedLogicalRouter', tenant=tenant)
nsx_router_uuid = self.get_realized_id(
tier0_id, tenant=tenant,
realization_info=realization_info)
return self.nsx_api.router.get_tier0_router_overlay_tz(
nsx_router_uuid)
def get_realized_state(self, tier0_id, entity_type=None,
tenant=policy_constants.POLICY_INFRA_TENANT,
realization_info=None):