Skip to content

Commit a9e3049

Browse files
committed
Add block storage log level {list, set} commands
This patch adds the ``block storage log level list`` and ``block storage log level set`` commands that allow operators to list the current log levels of cinder services and also enables them to set a particular log level. Change-Id: I16cd8084fb505a9e68a35a936ef3b8b1f3cdc712
1 parent e7ebf75 commit a9e3049

File tree

7 files changed

+417
-2
lines changed

7 files changed

+417
-2
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=======================
2+
Block Storage Log Level
3+
=======================
4+
5+
Block Storage v3
6+
7+
.. autoprogram-cliff:: openstack.volume.v3
8+
:command: block storage log level *

doc/source/cli/data/cinder.csv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ retype,volume type set --type,Changes the volume type for a volume.
103103
revert-to-snapshot,volume revert,Revert a volume to the specified snapshot. (Supported by API versions 3.40 - 3.latest)
104104
service-disable,volume service set --disable,Disables the service.
105105
service-enable,volume service set --enable,Enables the service.
106-
service-get-log,,(Supported by API versions 3.32 - 3.latest)
106+
service-get-log,block storage log level list,(Supported by API versions 3.32 - 3.latest)
107107
service-list,volume service list,Lists all services. Filter by host and service binary.
108-
service-set-log,,(Supported by API versions 3.32 - 3.latest)
108+
service-set-log,block storage log level set,(Supported by API versions 3.32 - 3.latest)
109109
set-bootable,volume set --bootable / --not-bootable,Update bootable status of a volume.
110110
show,volume show,Shows volume details.
111111
snapshot-create,snapshot create,Creates a snapshot.

openstackclient/tests/unit/volume/v3/fakes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ def __init__(self, **kwargs):
4747
self.volumes.resource_class = fakes.FakeResource(None, {})
4848
self.volume_types = mock.Mock()
4949
self.volume_types.resource_class = fakes.FakeResource(None, {})
50+
self.services = mock.Mock()
51+
self.services.resource_class = fakes.FakeResource(None, {})
5052

5153

5254
class TestVolume(utils.TestCommand):
@@ -436,3 +438,20 @@ def get_volume_attachments(attachments=None, count=2):
436438
attachments = create_volume_attachments(count)
437439

438440
return mock.Mock(side_effect=attachments)
441+
442+
443+
def create_service_log_level_entry(attrs=None):
444+
service_log_level_info = {
445+
'host': 'host_test',
446+
'binary': 'cinder-api',
447+
'prefix': 'cinder.api.common',
448+
'level': 'DEBUG',
449+
}
450+
# Overwrite default attributes if there are some attributes set
451+
attrs = attrs or {}
452+
453+
service_log_level_info.update(attrs)
454+
455+
service_log_level = fakes.FakeResource(
456+
None, service_log_level_info, loaded=True)
457+
return service_log_level
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
#
14+
15+
from cinderclient import api_versions
16+
import ddt
17+
from osc_lib import exceptions
18+
19+
from openstackclient.tests.unit import utils as tests_utils
20+
from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
21+
from openstackclient.volume.v3 import block_storage_log_level as service
22+
23+
24+
class TestService(volume_fakes.TestVolume):
25+
26+
def setUp(self):
27+
super().setUp()
28+
29+
# Get a shortcut to the ServiceManager Mock
30+
self.service_mock = self.app.client_manager.volume.services
31+
self.service_mock.reset_mock()
32+
33+
34+
class TestBlockStorageLogLevelList(TestService):
35+
36+
service_log = volume_fakes.create_service_log_level_entry()
37+
38+
def setUp(self):
39+
super().setUp()
40+
41+
self.service_mock.get_log_levels.return_value = [self.service_log]
42+
43+
# Get the command object to test
44+
self.cmd = service.BlockStorageLogLevelList(self.app, None)
45+
46+
def test_block_storage_log_level_list(self):
47+
self.app.client_manager.volume.api_version = \
48+
api_versions.APIVersion('3.32')
49+
arglist = [
50+
'--host', self.service_log.host,
51+
'--service', self.service_log.binary,
52+
'--log-prefix', self.service_log.prefix,
53+
]
54+
verifylist = [
55+
('host', self.service_log.host),
56+
('service', self.service_log.binary),
57+
('log_prefix', self.service_log.prefix),
58+
]
59+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
60+
61+
columns, data = self.cmd.take_action(parsed_args)
62+
63+
expected_columns = [
64+
'Binary',
65+
'Host',
66+
'Prefix',
67+
'Level',
68+
]
69+
70+
# confirming if all expected columns are present in the result.
71+
self.assertEqual(expected_columns, columns)
72+
73+
datalist = ((
74+
self.service_log.binary,
75+
self.service_log.host,
76+
self.service_log.prefix,
77+
self.service_log.level,
78+
), )
79+
80+
# confirming if all expected values are present in the result.
81+
self.assertEqual(datalist, tuple(data))
82+
83+
# checking if proper call was made to get log level of services
84+
self.service_mock.get_log_levels.assert_called_with(
85+
server=self.service_log.host,
86+
binary=self.service_log.binary,
87+
prefix=self.service_log.prefix,
88+
)
89+
90+
def test_block_storage_log_level_list_pre_332(self):
91+
arglist = [
92+
'--host', self.service_log.host,
93+
'--service', 'cinder-api',
94+
'--log-prefix', 'cinder_test.api.common',
95+
]
96+
verifylist = [
97+
('host', self.service_log.host),
98+
('service', 'cinder-api'),
99+
('log_prefix', 'cinder_test.api.common'),
100+
]
101+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
102+
103+
exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
104+
parsed_args)
105+
self.assertIn(
106+
'--os-volume-api-version 3.32 or greater is required', str(exc))
107+
108+
def test_block_storage_log_level_list_invalid_service_name(self):
109+
self.app.client_manager.volume.api_version = \
110+
api_versions.APIVersion('3.32')
111+
arglist = [
112+
'--host', self.service_log.host,
113+
'--service', 'nova-api',
114+
'--log-prefix', 'cinder_test.api.common',
115+
]
116+
verifylist = [
117+
('host', self.service_log.host),
118+
('service', 'nova-api'),
119+
('log_prefix', 'cinder_test.api.common'),
120+
]
121+
122+
self.assertRaises(tests_utils.ParserException, self.check_parser,
123+
self.cmd, arglist, verifylist)
124+
125+
126+
@ddt.ddt
127+
class TestBlockStorageLogLevelSet(TestService):
128+
129+
service_log = volume_fakes.create_service_log_level_entry()
130+
131+
def setUp(self):
132+
super().setUp()
133+
134+
# Get the command object to test
135+
self.cmd = service.BlockStorageLogLevelSet(self.app, None)
136+
137+
def test_block_storage_log_level_set(self):
138+
self.app.client_manager.volume.api_version = \
139+
api_versions.APIVersion('3.32')
140+
arglist = [
141+
'ERROR',
142+
'--host', self.service_log.host,
143+
'--service', self.service_log.binary,
144+
'--log-prefix', self.service_log.prefix,
145+
]
146+
verifylist = [
147+
('level', 'ERROR'),
148+
('host', self.service_log.host),
149+
('service', self.service_log.binary),
150+
('log_prefix', self.service_log.prefix),
151+
]
152+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
153+
154+
self.cmd.take_action(parsed_args)
155+
156+
# checking if proper call was made to set log level of services
157+
self.service_mock.set_log_levels.assert_called_with(
158+
level='ERROR',
159+
server=self.service_log.host,
160+
binary=self.service_log.binary,
161+
prefix=self.service_log.prefix,
162+
)
163+
164+
def test_block_storage_log_level_set_pre_332(self):
165+
arglist = [
166+
'ERROR',
167+
'--host', self.service_log.host,
168+
'--service', 'cinder-api',
169+
'--log-prefix', 'cinder_test.api.common',
170+
]
171+
verifylist = [
172+
('level', 'ERROR'),
173+
('host', self.service_log.host),
174+
('service', 'cinder-api'),
175+
('log_prefix', 'cinder_test.api.common'),
176+
]
177+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
178+
179+
exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
180+
parsed_args)
181+
self.assertIn(
182+
'--os-volume-api-version 3.32 or greater is required', str(exc))
183+
184+
def test_block_storage_log_level_set_invalid_service_name(self):
185+
self.app.client_manager.volume.api_version = \
186+
api_versions.APIVersion('3.32')
187+
arglist = [
188+
'ERROR',
189+
'--host', self.service_log.host,
190+
'--service', 'nova-api',
191+
'--log-prefix', 'cinder.api.common',
192+
]
193+
verifylist = [
194+
('level', 'ERROR'),
195+
('host', self.service_log.host),
196+
('service', 'nova-api'),
197+
('log_prefix', 'cinder.api.common'),
198+
]
199+
200+
self.assertRaises(tests_utils.ParserException, self.check_parser,
201+
self.cmd, arglist, verifylist)
202+
203+
@ddt.data('WARNING', 'info', 'Error', 'debuG', 'fake-log-level')
204+
def test_block_storage_log_level_set_log_level(self, log_level):
205+
self.app.client_manager.volume.api_version = \
206+
api_versions.APIVersion('3.32')
207+
arglist = [
208+
log_level,
209+
'--host', self.service_log.host,
210+
'--service', 'cinder-api',
211+
'--log-prefix', 'cinder.api.common',
212+
]
213+
verifylist = [
214+
('level', log_level.upper()),
215+
('host', self.service_log.host),
216+
('service', 'cinder-api'),
217+
('log_prefix', 'cinder.api.common'),
218+
]
219+
220+
if log_level == 'fake-log-level':
221+
self.assertRaises(tests_utils.ParserException, self.check_parser,
222+
self.cmd, arglist, verifylist)
223+
else:
224+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
225+
226+
self.cmd.take_action(parsed_args)
227+
228+
# checking if proper call was made to set log level of services
229+
self.service_mock.set_log_levels.assert_called_with(
230+
level=log_level.upper(),
231+
server=self.service_log.host,
232+
binary=self.service_log.binary,
233+
prefix=self.service_log.prefix)

0 commit comments

Comments
 (0)