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:
parent
2d356098e5
commit
71b8aa1272
59
heatclient/tests/test_service.py
Normal file
59
heatclient/tests/test_service.py
Normal 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)
|
@ -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)
|
||||
|
@ -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
32
heatclient/v1/services.py
Normal 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")
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user