Adds CLI heat service-list

Adds 'service-list' to heat CLI for reporting the status
of all running engines in given cloud environment

"DocImpact"
Implements: blueprint heat-manage-service-list

Change-Id: Ief8b6e9bdd1a9b7428e0c8f58b65e9bff607c592
This commit is contained in:
Kanagaraj Manickam 2014-12-18 16:18:56 +05:30
parent 2d356098e5
commit 71b8aa1272
5 changed files with 185 additions and 0 deletions

View File

@ -0,0 +1,59 @@
# Copyright 2012 OpenStack Foundation
# All Rights Reserved.
#
# 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 heatclient import exc
import testtools
from heatclient.v1 import services
class ManageServiceTest(testtools.TestCase):
def setUp(self):
super(ManageServiceTest, self).setUp()
def test_service_list(self):
class FakeResponse(object):
def json(self):
return {'services': []}
class FakeClient(object):
def get(self, *args, **kwargs):
assert args[0] == ('/services')
return FakeResponse()
manager = services.ServiceManager(FakeClient())
self.assertEqual(manager.list(), [])
def test_service_list_403(self):
class FakeClient403(object):
def get(self, *args, **kwargs):
assert args[0] == ('/services')
raise exc.HTTPForbidden()
manager = services.ServiceManager(FakeClient403())
self.assertRaises(exc.HTTPForbidden,
manager.list)
def test_service_list_503(self):
class FakeClient503(object):
def get(self, *args, **kwargs):
assert args[0] == ('/services')
raise exc.HTTPServiceUnavailable()
manager = services.ServiceManager(FakeClient503())
self.assertRaises(exc.HTTPServiceUnavailable,
manager.list)

View File

@ -2958,3 +2958,87 @@ class MockShellTestStandaloneToken(MockShellTestUserPass):
'OS_PASSWORD': 'password'
}
self.set_fake_env(fake_env)
class ShellTestManageService(ShellBase):
def setUp(self):
super(ShellTestManageService, self).setUp()
self.set_fake_env(FAKE_ENV_KEYSTONE_V2)
def _set_fake_env(self):
'''Patch os.environ to avoid required auth info.'''
self.set_fake_env(FAKE_ENV_KEYSTONE_V2)
def _test_error_case(self, code, message):
self.register_keystone_auth_fixture()
resp_dict = {
'explanation': '',
'code': code,
'error': {
'message': message,
'type': '',
'traceback': '',
},
'title': 'test title'
}
resp_string = jsonutils.dumps(resp_dict)
resp = fakes.FakeHTTPResponse(
code,
'test reason',
{'content-type': 'application/json'},
resp_string)
(http.HTTPClient.json_request('GET', '/services').
AndRaise(exc.from_response(resp)))
exc.verbose = 1
self.m.ReplayAll()
e = self.assertRaises(exc.HTTPException,
self.shell, "service-list")
self.m.VerifyAll()
self.assertIn(message, str(e))
def test_service_list(self):
self.register_keystone_auth_fixture()
resp_dict = {
'services': [
{
"status": "up",
"binary": "heat-engine",
"engine_id": "9d9242c3-4b9e-45e1-9e74-7615fbf20e5d",
"hostname": "mrkanag",
"updated_at": "2015-02-03T05:57:59.000000",
"topic": "engine",
"host": "engine-1"
}
]
}
resp_string = jsonutils.dumps(resp_dict)
headers = {}
http_resp = fakes.FakeHTTPResponse(200, 'OK', headers, resp_string)
response = (http_resp, resp_dict)
http.HTTPClient.json_request('GET', '/services').AndReturn(response)
self.m.ReplayAll()
services_text = self.shell('service-list')
self.m.VerifyAll()
required = [
'hostname', 'binary', 'engine_id', 'host',
'topic', 'updated_at', 'status'
]
for r in required:
self.assertRegexpMatches(services_text, r)
def test_service_list_503(self):
self._test_error_case(
message='All heat engines are down',
code=503)
def test_service_list_403(self):
self._test_error_case(
message=('You are not authorized to '
'complete this action'),
code=403)

View File

@ -19,6 +19,7 @@ from heatclient.v1 import build_info
from heatclient.v1 import events
from heatclient.v1 import resource_types
from heatclient.v1 import resources
from heatclient.v1 import services
from heatclient.v1 import software_configs
from heatclient.v1 import software_deployments
from heatclient.v1 import stacks
@ -49,3 +50,4 @@ class Client(object):
self.http_client)
self.software_configs = software_configs.SoftwareConfigManager(
self.http_client)
self.services = services.ServiceManager(self.http_client)

32
heatclient/v1/services.py Normal file
View File

@ -0,0 +1,32 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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 heatclient.openstack.common.apiclient import base
class Service(base.Resource):
def __repr__(self):
return "<Service %s>" % self._info
class ServiceManager(base.BaseManager):
resource_class = Service
def list(self):
"""Get a list of services.
:rtype: list of :class:`Service`
"""
url = '/services'
return self._list(url, "services")

View File

@ -1169,3 +1169,11 @@ def do_snapshot_list(hc, args):
'creation_time': lambda x: x['creation_time'],
}
utils.print_list(snapshots["snapshots"], fields, formatters=formatters)
def do_service_list(hc, args=None):
'''List the Heat engines.'''
fields = ['hostname', 'binary', 'engine_id', 'host',
'topic', 'updated_at', 'status']
services = hc.services.list()
utils.print_list(services, fields, sortby_index=1)