Skip to content

Commit 4cc539f

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Support compute service force down/up"
2 parents ca5e8e6 + eccd943 commit 4cc539f

4 files changed

Lines changed: 165 additions & 20 deletions

File tree

doc/source/command-objects/compute-service.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Set service command
5858
os compute service set
5959
[--enable | --disable]
6060
[--disable-reason <reason>]
61+
[--up | --down]
6162
<host> <service>
6263
6364
.. _compute-service-set:
@@ -73,6 +74,14 @@ Set service command
7374

7475
Reason for disabling the service (in quotes). Should be used with --disable option.
7576

77+
.. option:: --up
78+
79+
Force up service
80+
81+
.. option:: --down
82+
83+
Force down service
84+
7685
.. describe:: <host>
7786

7887
Name of host

openstackclient/compute/v2/service.py

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from osc_lib import utils
2121

2222
from openstackclient.i18n import _
23+
from openstackclient.i18n import _LE
2324

2425

2526
class DeleteService(command.Command):
@@ -127,6 +128,17 @@ def get_parser(self, prog_name):
127128
help=_("Reason for disabling the service (in quotas). "
128129
"Should be used with --disable option.")
129130
)
131+
up_down_group = parser.add_mutually_exclusive_group()
132+
up_down_group.add_argument(
133+
'--up',
134+
action='store_true',
135+
help=_('Force up service'),
136+
)
137+
up_down_group.add_argument(
138+
'--down',
139+
action='store_true',
140+
help=_('Force down service'),
141+
)
130142
return parser
131143

132144
def take_action(self, parsed_args):
@@ -139,20 +151,45 @@ def take_action(self, parsed_args):
139151
"--disable specified.")
140152
raise exceptions.CommandError(msg)
141153

154+
result = 0
142155
enabled = None
143-
if parsed_args.enable:
144-
enabled = True
145-
if parsed_args.disable:
146-
enabled = False
147-
148-
if enabled is None:
149-
return
150-
elif enabled:
151-
cs.enable(parsed_args.host, parsed_args.service)
152-
else:
153-
if parsed_args.disable_reason:
154-
cs.disable_log_reason(parsed_args.host,
155-
parsed_args.service,
156-
parsed_args.disable_reason)
157-
else:
158-
cs.disable(parsed_args.host, parsed_args.service)
156+
try:
157+
if parsed_args.enable:
158+
enabled = True
159+
if parsed_args.disable:
160+
enabled = False
161+
162+
if enabled is not None:
163+
if enabled:
164+
cs.enable(parsed_args.host, parsed_args.service)
165+
else:
166+
if parsed_args.disable_reason:
167+
cs.disable_log_reason(parsed_args.host,
168+
parsed_args.service,
169+
parsed_args.disable_reason)
170+
else:
171+
cs.disable(parsed_args.host, parsed_args.service)
172+
except Exception:
173+
status = "enabled" if enabled else "disabled"
174+
self.log.error(_LE("Failed to set service status to %s"), status)
175+
result += 1
176+
177+
force_down = None
178+
try:
179+
if parsed_args.down:
180+
force_down = True
181+
if parsed_args.up:
182+
force_down = False
183+
if force_down is not None:
184+
cs.force_down(parsed_args.host, parsed_args.service,
185+
force_down=force_down)
186+
except Exception:
187+
state = "down" if force_down else "up"
188+
self.log.error(_LE("Failed to set service state to %s"), state)
189+
result += 1
190+
191+
if result > 0:
192+
msg = _("Compute service %(service)s of host %(host)s failed to "
193+
"set.") % {"service": parsed_args.service,
194+
"host": parsed_args.host}
195+
raise exceptions.CommandError(msg)

openstackclient/tests/compute/v2/test_service.py

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# under the License.
1414
#
1515

16+
import mock
17+
1618
from osc_lib import exceptions
1719

1820
from openstackclient.compute.v2 import service
@@ -225,8 +227,12 @@ def test_service_set_only_with_disable_reason(self):
225227
('service', self.service.binary),
226228
]
227229
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
228-
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
229-
parsed_args)
230+
try:
231+
self.cmd.take_action(parsed_args)
232+
self.fail("CommandError should be raised.")
233+
except exceptions.CommandError as e:
234+
self.assertEqual("Cannot specify option --disable-reason without "
235+
"--disable specified.", str(e))
230236

231237
def test_service_set_enable_with_disable_reason(self):
232238
reason = 'earthquake'
@@ -243,5 +249,93 @@ def test_service_set_enable_with_disable_reason(self):
243249
('service', self.service.binary),
244250
]
245251
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
246-
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
247-
parsed_args)
252+
try:
253+
self.cmd.take_action(parsed_args)
254+
self.fail("CommandError should be raised.")
255+
except exceptions.CommandError as e:
256+
self.assertEqual("Cannot specify option --disable-reason without "
257+
"--disable specified.", str(e))
258+
259+
def test_service_set_state_up(self):
260+
arglist = [
261+
'--up',
262+
self.service.host,
263+
self.service.binary,
264+
]
265+
verifylist = [
266+
('up', True),
267+
('host', self.service.host),
268+
('service', self.service.binary),
269+
]
270+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
271+
result = self.cmd.take_action(parsed_args)
272+
self.service_mock.force_down.assert_called_once_with(
273+
self.service.host, self.service.binary, force_down=False)
274+
self.assertNotCalled(self.service_mock.enable)
275+
self.assertNotCalled(self.service_mock.disable)
276+
self.assertIsNone(result)
277+
278+
def test_service_set_state_down(self):
279+
arglist = [
280+
'--down',
281+
self.service.host,
282+
self.service.binary,
283+
]
284+
verifylist = [
285+
('down', True),
286+
('host', self.service.host),
287+
('service', self.service.binary),
288+
]
289+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
290+
result = self.cmd.take_action(parsed_args)
291+
self.service_mock.force_down.assert_called_once_with(
292+
self.service.host, self.service.binary, force_down=True)
293+
self.assertNotCalled(self.service_mock.enable)
294+
self.assertNotCalled(self.service_mock.disable)
295+
self.assertIsNone(result)
296+
297+
def test_service_set_enable_and_state_down(self):
298+
arglist = [
299+
'--enable',
300+
'--down',
301+
self.service.host,
302+
self.service.binary,
303+
]
304+
verifylist = [
305+
('enable', True),
306+
('down', True),
307+
('host', self.service.host),
308+
('service', self.service.binary),
309+
]
310+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
311+
result = self.cmd.take_action(parsed_args)
312+
self.service_mock.enable.assert_called_once_with(
313+
self.service.host, self.service.binary)
314+
self.service_mock.force_down.assert_called_once_with(
315+
self.service.host, self.service.binary, force_down=True)
316+
self.assertIsNone(result)
317+
318+
def test_service_set_enable_and_state_down_with_exception(self):
319+
arglist = [
320+
'--enable',
321+
'--down',
322+
self.service.host,
323+
self.service.binary,
324+
]
325+
verifylist = [
326+
('enable', True),
327+
('down', True),
328+
('host', self.service.host),
329+
('service', self.service.binary),
330+
]
331+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
332+
333+
with mock.patch.object(self.cmd.log, 'error') as mock_log:
334+
with mock.patch.object(self.service_mock, 'enable',
335+
side_effect=Exception()):
336+
self.assertRaises(exceptions.CommandError,
337+
self.cmd.take_action, parsed_args)
338+
mock_log.assert_called_once_with(
339+
"Failed to set service status to %s", "enabled")
340+
self.service_mock.force_down.assert_called_once_with(
341+
self.service.host, self.service.binary, force_down=True)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- Add options ``--up`` and ``--down`` for compute v2 ``compute service set``
4+
command to support force up/down compute service.
5+
[Bug `1589348 <https://bugs.launchpad.net/python-openstackclient/+bug/1589348>`_]

0 commit comments

Comments
 (0)