Merge "Refactor keepalive to execute node health check"
This commit is contained in:
commit
0a76d4e3a1
@ -171,7 +171,6 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
|
|||||||
mock_cluster = mock.Mock()
|
mock_cluster = mock.Mock()
|
||||||
mock_cluster.nsxlib_config = mock.Mock()
|
mock_cluster.nsxlib_config = mock.Mock()
|
||||||
mock_cluster.nsxlib_config.url_base = 'abc'
|
mock_cluster.nsxlib_config.url_base = 'abc'
|
||||||
mock_cluster.nsxlib_config.keepalive_section = 'transport-zones'
|
|
||||||
provider = cluster.NSXRequestsHTTPProvider()
|
provider = cluster.NSXRequestsHTTPProvider()
|
||||||
|
|
||||||
with mock.patch.object(client.JSONRESTClient, "get",
|
with mock.patch.object(client.JSONRESTClient, "get",
|
||||||
@ -181,26 +180,10 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
|
|||||||
mock_cluster, mock_ep, mock_conn)
|
mock_cluster, mock_ep, mock_conn)
|
||||||
|
|
||||||
with mock.patch.object(client.JSONRESTClient, "get",
|
with mock.patch.object(client.JSONRESTClient, "get",
|
||||||
return_value={'result_count': 1}):
|
return_value={'healthy': True}):
|
||||||
provider.validate_connection(mock_cluster, mock_ep, mock_conn)
|
provider.validate_connection(mock_cluster, mock_ep, mock_conn)
|
||||||
|
|
||||||
def test_validate_connection_no_keep_alive(self):
|
def _validate_con_mocks(self, nsx_version):
|
||||||
mock_conn = mocks.MockRequestSessionApi()
|
|
||||||
mock_conn.default_headers = {}
|
|
||||||
mock_ep = mock.Mock()
|
|
||||||
mock_ep.provider.url = 'https://1.2.3.4'
|
|
||||||
mock_cluster = mock.Mock()
|
|
||||||
mock_cluster.nsxlib_config = mock.Mock()
|
|
||||||
mock_cluster.nsxlib_config.url_base = 'abc'
|
|
||||||
mock_cluster.nsxlib_config.keepalive_section = None
|
|
||||||
provider = cluster.NSXRequestsHTTPProvider()
|
|
||||||
|
|
||||||
with mock.patch.object(client.JSONRESTClient, "get") as mock_get:
|
|
||||||
provider.validate_connection(mock_cluster, mock_ep, mock_conn)
|
|
||||||
mock_get.assert_not_called()
|
|
||||||
|
|
||||||
def _validate_con_mocks(self, nsx_version,
|
|
||||||
keepalive_section='transport-zones'):
|
|
||||||
nsxlib_config = nsxlib_testcase.get_default_nsxlib_config()
|
nsxlib_config = nsxlib_testcase.get_default_nsxlib_config()
|
||||||
nsxlib = v3.NsxLib(nsxlib_config)
|
nsxlib = v3.NsxLib(nsxlib_config)
|
||||||
nsxlib.nsx_version = nsx_version
|
nsxlib.nsx_version = nsx_version
|
||||||
@ -210,8 +193,6 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
|
|||||||
mock_ep.provider.url = 'https://1.2.3.4'
|
mock_ep.provider.url = 'https://1.2.3.4'
|
||||||
conf = mock.Mock()
|
conf = mock.Mock()
|
||||||
conf.url_base = 'abc'
|
conf.url_base = 'abc'
|
||||||
conf.keepalive_section = keepalive_section
|
|
||||||
conf.validate_connection_method = nsxlib.validate_connection_method
|
|
||||||
mock_cluster = mock.Mock()
|
mock_cluster = mock.Mock()
|
||||||
mock_cluster.nsxlib_config = conf
|
mock_cluster.nsxlib_config = conf
|
||||||
return (mock_cluster, mock_ep, mock_conn)
|
return (mock_cluster, mock_ep, mock_conn)
|
||||||
|
@ -118,10 +118,6 @@ class NsxLib(lib.NsxLibBase):
|
|||||||
self.tag_limits = self.get_tag_limits()
|
self.tag_limits = self.get_tag_limits()
|
||||||
utils.update_tag_limits(self.tag_limits)
|
utils.update_tag_limits(self.tag_limits)
|
||||||
|
|
||||||
@property
|
|
||||||
def keepalive_section(self):
|
|
||||||
return 'transport-zones'
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def validate_connection_method(self):
|
def validate_connection_method(self):
|
||||||
"""Return a method that will validate the NSX manager status"""
|
"""Return a method that will validate the NSX manager status"""
|
||||||
|
@ -67,11 +67,6 @@ class AbstractHTTPProvider(object):
|
|||||||
"""A unique string name for this provider."""
|
"""A unique string name for this provider."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def validate_connection(self, cluster_api, endpoint, conn):
|
|
||||||
"""Validate the said connection for the given endpoint and cluster."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def new_connection(self, cluster_api, provider):
|
def new_connection(self, cluster_api, provider):
|
||||||
"""Create a new http connection.
|
"""Create a new http connection.
|
||||||
@ -191,29 +186,18 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
|
|||||||
# nsxlib 'retries' and 'http_timeout' parameters.
|
# nsxlib 'retries' and 'http_timeout' parameters.
|
||||||
client = nsx_client.NSX3Client(
|
client = nsx_client.NSX3Client(
|
||||||
conn, url_prefix=endpoint.provider.url,
|
conn, url_prefix=endpoint.provider.url,
|
||||||
url_path_base=cluster_api.nsxlib_config.url_base,
|
url_path_base=nsx_client.NSX3Client.NSX_V1_API_PREFIX,
|
||||||
default_headers=conn.default_headers,
|
default_headers=conn.default_headers,
|
||||||
max_attempts=1)
|
max_attempts=1)
|
||||||
|
|
||||||
if cluster_api.nsxlib_config.validate_connection_method:
|
# Try to get the status silently and with no retries
|
||||||
cluster_api.nsxlib_config.validate_connection_method(
|
status = client.get('reverse-proxy/node/health',
|
||||||
client, endpoint.provider.url)
|
silent=True, with_retries=False)
|
||||||
|
if not status or not status.get('healthy', False):
|
||||||
# If keeplive section returns a list, it is assumed to be non-empty
|
msg = _("NSX Node is not healthy, reported status: %s") % status
|
||||||
keepalive_section = cluster_api.nsxlib_config.keepalive_section
|
LOG.warning(msg)
|
||||||
# When validate connection also has the effect of keep-alive,
|
raise exceptions.ResourceNotFound(
|
||||||
# keepalive_section can be disabled by passing in an empty value
|
manager=endpoint.provider.url, operation=msg)
|
||||||
if keepalive_section:
|
|
||||||
result = client.get(keepalive_section,
|
|
||||||
silent=True,
|
|
||||||
with_retries=False)
|
|
||||||
if not result or result.get('result_count', 1) <= 0:
|
|
||||||
msg = _("No %(section)s found "
|
|
||||||
"for '%(url)s'") % {'section': keepalive_section,
|
|
||||||
'url': endpoint.provider.url}
|
|
||||||
LOG.warning(msg)
|
|
||||||
raise exceptions.ResourceNotFound(
|
|
||||||
manager=endpoint.provider.url, operation=msg)
|
|
||||||
|
|
||||||
def new_connection(self, cluster_api, provider):
|
def new_connection(self, cluster_api, provider):
|
||||||
config = cluster_api.nsxlib_config
|
config = cluster_api.nsxlib_config
|
||||||
|
@ -157,9 +157,9 @@ class NsxLibConfig(object):
|
|||||||
self.realization_wait_sec = realization_wait_sec
|
self.realization_wait_sec = realization_wait_sec
|
||||||
|
|
||||||
if len(nsx_api_managers) == 1 and not self.cluster_unavailable_retry:
|
if len(nsx_api_managers) == 1 and not self.cluster_unavailable_retry:
|
||||||
LOG.warning("When only one endpoint is provided, keepalive probes "
|
LOG.warning("When only one endpoint is provided, keepalive probes"
|
||||||
" are disabled. For the system to be able to recover "
|
" are disabled. For the system to be able to recover"
|
||||||
" from DOWN state, cluster_unavailable_retry is set "
|
" from DOWN state, cluster_unavailable_retry is set"
|
||||||
" to True, overriding provided configuration")
|
" to True, overriding provided configuration")
|
||||||
self.cluster_unavailable_retry = True
|
self.cluster_unavailable_retry = True
|
||||||
|
|
||||||
@ -172,9 +172,11 @@ class NsxLibConfig(object):
|
|||||||
|
|
||||||
def extend(self, keepalive_section, validate_connection_method=None,
|
def extend(self, keepalive_section, validate_connection_method=None,
|
||||||
url_base=None):
|
url_base=None):
|
||||||
"""Called by library code to initialize application-specific data"""
|
if keepalive_section or validate_connection_method:
|
||||||
self.keepalive_section = keepalive_section
|
LOG.warning("keepalive_section and validate_connection_method are"
|
||||||
self.validate_connection_method = validate_connection_method
|
" no longer used to conduct keepalive probes. For"
|
||||||
|
" most efficient keepalive roundtrip, proxy health"
|
||||||
|
" API is always used.")
|
||||||
self.url_base = url_base
|
self.url_base = url_base
|
||||||
|
|
||||||
def _attribute_by_index(self, scalar_or_list, index):
|
def _attribute_by_index(self, scalar_or_list, index):
|
||||||
|
@ -61,10 +61,7 @@ class NsxLibBase(object):
|
|||||||
def set_config(self, nsxlib_config):
|
def set_config(self, nsxlib_config):
|
||||||
"""Set config user provided and extend it according to application"""
|
"""Set config user provided and extend it according to application"""
|
||||||
self.nsxlib_config = nsxlib_config
|
self.nsxlib_config = nsxlib_config
|
||||||
self.nsxlib_config.extend(
|
self.nsxlib_config.extend(None, url_base=self.client_url_prefix)
|
||||||
keepalive_section=self.keepalive_section,
|
|
||||||
validate_connection_method=self.validate_connection_method,
|
|
||||||
url_base=self.client_url_prefix)
|
|
||||||
|
|
||||||
def set_default_headers(self, nsxlib_config):
|
def set_default_headers(self, nsxlib_config):
|
||||||
"""Set the default headers with token information"""
|
"""Set the default headers with token information"""
|
||||||
@ -82,14 +79,6 @@ class NsxLibBase(object):
|
|||||||
def client_url_prefix(self):
|
def client_url_prefix(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractproperty
|
|
||||||
def keepalive_section(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractproperty
|
|
||||||
def validate_connection_method(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def init_api(self):
|
def init_api(self):
|
||||||
pass
|
pass
|
||||||
|
@ -132,26 +132,6 @@ class NsxPolicyLib(lib.NsxLibBase):
|
|||||||
self.ipsec_vpn = ipsec_vpn_resources.NsxPolicyIpsecVpnApi(*args)
|
self.ipsec_vpn = ipsec_vpn_resources.NsxPolicyIpsecVpnApi(*args)
|
||||||
self.global_config = core_resources.NsxPolicyGlobalConfig(*args)
|
self.global_config = core_resources.NsxPolicyGlobalConfig(*args)
|
||||||
|
|
||||||
@property
|
|
||||||
def keepalive_section(self):
|
|
||||||
return 'infra'
|
|
||||||
|
|
||||||
@property
|
|
||||||
def validate_connection_method(self):
|
|
||||||
"""Return a method that will validate the NSX policy status"""
|
|
||||||
|
|
||||||
def check_policy_status(client, url):
|
|
||||||
# Try to get the status silently and with no retries
|
|
||||||
infra = client.get('infra',
|
|
||||||
silent=True, with_retries=False)
|
|
||||||
if not infra or not infra.get('id'):
|
|
||||||
msg = _("Policy health check failed")
|
|
||||||
LOG.warning(msg)
|
|
||||||
raise exceptions.ResourceNotFound(
|
|
||||||
manager=url, operation=msg)
|
|
||||||
|
|
||||||
return check_policy_status
|
|
||||||
|
|
||||||
def get_version(self):
|
def get_version(self):
|
||||||
"""Get the NSX Policy manager version
|
"""Get the NSX Policy manager version
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user