Support /ping and /health for v2

Now Zaqar supports /ping and /health API, but they're missing
in zaqar client. This patch will fix it.

Change-Id: I34b454c486a7b4c693a540890eee48f162a07605
This commit is contained in:
Fei Long Wang 2016-03-10 09:18:30 +13:00
parent 3152321c7a
commit 15ef3386c0
9 changed files with 203 additions and 16 deletions

View File

@ -94,6 +94,8 @@ openstack.messaging.v2 =
subscription_show = zaqarclient.queues.v2.cli:ShowSubscription subscription_show = zaqarclient.queues.v2.cli:ShowSubscription
subscription_list = zaqarclient.queues.v2.cli:ListSubscriptions subscription_list = zaqarclient.queues.v2.cli:ListSubscriptions
queue_signed_url = zaqarclient.queues.v2.cli:CreateSignedUrl queue_signed_url = zaqarclient.queues.v2.cli:CreateSignedUrl
messaging_ping = zaqarclient.queues.v2.cli:Ping
messaging_health = zaqarclient.queues.v2.cli:Health
openstack.cli.extension = openstack.cli.extension =
messaging = zaqarclient.queues.cli messaging = zaqarclient.queues.cli

View File

@ -0,0 +1,27 @@
# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from zaqarclient.tests.queues import health
from zaqarclient.transport import http
class QueuesV2HealthHttpFunctionalTest(
health.QueuesV2HealthFunctionalTest):
is_functional = True
transport_cls = http.HttpTransport
url = 'http://127.0.0.1:8888'
version = 2

View File

@ -18,15 +18,18 @@ import mock
import ddt import ddt
from zaqarclient.queues import client from zaqarclient.queues import client
from zaqarclient.queues.v1 import core from zaqarclient.tests.queues import base
from zaqarclient.tests import base
from zaqarclient.transport import errors from zaqarclient.transport import errors
from zaqarclient.transport import http
VERSIONS = [2] VERSIONS = [2]
@ddt.ddt @ddt.ddt
class TestClient(base.TestBase): class TestClient(base.QueuesTestBase):
transport_cls = http.HttpTransport
url = 'http://127.0.0.1:8888/v2'
version = VERSIONS[0]
@ddt.data(*VERSIONS) @ddt.data(*VERSIONS)
def test_transport(self, version): def test_transport(self, version):
@ -35,21 +38,18 @@ class TestClient(base.TestBase):
self.assertIsNotNone(cli.transport()) self.assertIsNotNone(cli.transport())
@ddt.data(*VERSIONS) @ddt.data(*VERSIONS)
def test_health_ok(self, version): def test_ping_ok(self, version):
cli = client.Client('http://example.com', with mock.patch.object(self.transport, 'send',
version, {"auth_opts": {'backend': 'noauth'}}) autospec=True) as send_method:
with mock.patch.object(core, 'health', autospec=True) as core_health: send_method.return_value = None
core_health.return_value = None self.assertTrue(self.client.ping())
self.assertTrue(cli.health())
@ddt.data(*VERSIONS) @ddt.data(*VERSIONS)
def test_health_bad(self, version): def test_ping_bad(self, version):
cli = client.Client('http://example.com',
version, {"auth_opts": {'backend': 'noauth'}})
def raise_error(*args, **kwargs): def raise_error(*args, **kwargs):
raise errors.ServiceUnavailableError() raise errors.ServiceUnavailableError()
with mock.patch.object(core, 'health', autospec=True) as core_health: with mock.patch.object(self.transport, 'send',
core_health.side_effect = raise_error autospec=True) as send_method:
self.assertFalse(cli.health()) send_method.side_effect = raise_error
self.assertFalse(self.client.ping())

View File

@ -0,0 +1,24 @@
# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from zaqarclient.tests.queues import health
from zaqarclient.transport import http
class QueuesV2HealthHttpUnitTest(health.QueuesV2HealthUnitTest):
transport_cls = http.HttpTransport
url = 'http://127.0.0.1:8888/v2'
version = 2

View File

@ -74,4 +74,14 @@ V2.schema.update({
'detailed': {'type': 'boolean'} 'detailed': {'type': 'boolean'}
} }
}, },
'ping': {
'ref': 'ping',
'method': 'GET',
},
'health': {
'ref': 'health',
'method': 'GET',
},
}) })

View File

@ -393,3 +393,26 @@ class CreateSignedUrl(show.ShowOne):
data['signature'], data['signature'],
data['project'] data['project']
) )
class Ping(show.ShowOne):
"""Check if Zaqar server is alive or not"""
log = logging.getLogger(__name__ + ".Ping")
def take_action(self, parsed_args):
client = _get_client(self, parsed_args)
columns = ('Pingable', )
return columns, utils.get_dict_properties({'pingable': client.ping()},
columns)
class Health(command.Command):
"""Display detailed health status of Zaqar server"""
log = logging.getLogger(__name__ + ".Health")
def take_action(self, parsed_args):
client = _get_client(self, parsed_args)
health = client.health()
print(json.dumps(health, indent=4, sort_keys=True))

View File

@ -92,3 +92,14 @@ class Client(client.Client):
subscription_list, subscription_list,
'subscriptions', 'subscriptions',
subscription.create_object(self)) subscription.create_object(self))
def ping(self):
"""Gets the health status of Zaqar server."""
req, trans = self._request_and_transport()
return core.ping(trans, req)
@decorators.version(min_version=1.1)
def health(self):
"""Gets the detailed health status of Zaqar server."""
req, trans = self._request_and_transport()
return core.health(trans, req)

View File

@ -220,3 +220,42 @@ def subscription_list(transport, request, queue_name, **kwargs):
return {'links': [], 'subscriptions': []} return {'links': [], 'subscriptions': []}
return resp.deserialized_content return resp.deserialized_content
def ping(transport, request, callback=None):
"""Check the health of web head for load balancing
:param transport: Transport instance to use
:type transport: `transport.base.Transport`
:param request: Request instance ready to be sent.
:type request: `transport.request.Request`
:param callback: Optional callable to use as callback.
If specified, this request will be sent asynchronously.
(IGNORED UNTIL ASYNC SUPPORT IS COMPLETE)
:type callback: Callable object.
"""
request.operation = 'ping'
try:
transport.send(request)
return True
except Exception:
return False
def health(transport, request, callback=None):
"""Get detailed health status of Zaqar server
:param transport: Transport instance to use
:type transport: `transport.base.Transport`
:param request: Request instance ready to be sent.
:type request: `transport.request.Request`
:param callback: Optional callable to use as callback.
If specified, this request will be sent asynchronously.
(IGNORED UNTIL ASYNC SUPPORT IS COMPLETE)
:type callback: Callable object.
"""
request.operation = 'health'
resp = transport.send(request)
return resp.deserialized_content

View File

@ -0,0 +1,51 @@
# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import mock
from zaqarclient.tests.queues import base
from zaqarclient.transport import response
class QueuesV2HealthUnitTest(base.QueuesTestBase):
def test_health(self):
expect_health = {u'catalog_reachable': True,
u'redis': {u'operation_status': {},
u'storage_reachable': True}
}
with mock.patch.object(self.transport, 'send',
autospec=True) as send_method:
health_content = json.dumps(expect_health)
health_resp = response.Response(None, health_content)
send_method.side_effect = iter([health_resp])
health = self.client.health()
self.assertEqual(expect_health, health)
class QueuesV2HealthFunctionalTest(base.QueuesTestBase):
def test_ping(self):
# NOTE(flwang): If test env is not pingable, then the test should fail
self.assertTrue(self.client.ping())
def test_health(self):
health = self.client.health()
# NOTE(flwang): If everything is ok, then zaqar server will return a
# JSON(dict).
self.assertTrue(isinstance(health, dict))