Merge ~andreserl/maas:snap_rack_delete into maas:master

Proposed by Andres Rodriguez
Status: Merged
Approved by: Andres Rodriguez
Approved revision: f01b6e6cc65163644d330d6db48fab19d37af45b
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~andreserl/maas:snap_rack_delete
Merge into: maas:master
Diff against target: 109 lines (+57/-11)
2 files modified
src/provisioningserver/rpc/clusterservice.py (+26/-9)
src/provisioningserver/rpc/tests/test_clusterservice.py (+31/-2)
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Mike Pontillo (community) Approve
Review via email: mp+329275@code.launchpad.net

Commit message

LP: #1711414 - Fix deleting a rack when it is installed via the snap

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Can this code ever be reached on a rack+region?

review: Needs Information
Revision history for this message
Mike Pontillo (mpontillo) wrote :

(Also, this branch is missing updates to the unit tests.)

Revision history for this message
Andres Rodriguez (andreserl) wrote :

@Mike, no, this code is only called if the machine is "NODE.RACK_CONTROLLER" so a REGION_AND_RACK won't have this same code path.

Revision history for this message
Mike Pontillo (mpontillo) wrote :

Sounds good. I think you need one more test case for ignoring the CalledProcessError (not raising CannotDisableAndShutoffRackd) if running_in_snap() and e.returncode == -15.

Revision history for this message
Mike Pontillo (mpontillo) wrote :

LGTM!

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Revision history for this message
MAAS Lander (maas-lander) wrote :
Revision history for this message
Andres Rodriguez (andreserl) :
review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Revision history for this message
MAAS Lander (maas-lander) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/provisioningserver/rpc/clusterservice.py b/src/provisioningserver/rpc/clusterservice.py
2index 7157c81..50019d3 100644
3--- a/src/provisioningserver/rpc/clusterservice.py
4+++ b/src/provisioningserver/rpc/clusterservice.py
5@@ -98,6 +98,10 @@ from provisioningserver.utils.shell import (
6 ExternalProcessError,
7 select_c_utf8_bytes_locale,
8 )
9+from provisioningserver.utils.snappy import (
10+ get_snap_path,
11+ running_in_snap,
12+)
13 from provisioningserver.utils.twisted import (
14 call,
15 callOut,
16@@ -676,17 +680,30 @@ class Cluster(RPCProtocol):
17 Implementation of
18 :py:class:`~provisioningserver.rpc.cluster.DisableAndShutoffRackd`.
19 """
20- maaslog.info("Rack deleted, disabling rackd service")
21+ maaslog.info("Attempting to disable the rackd service.")
22 try:
23- # We can't use the --now flag as if the maas-rackd service is on
24- # but not enabled the service won't be stopped
25- call_and_check(
26- ['sudo', 'systemctl', 'disable', 'maas-rackd'])
27- call_and_check(
28- ['sudo', 'systemctl', 'stop', 'maas-rackd'])
29+ if running_in_snap():
30+ cmd = os.path.join(get_snap_path(), 'command-maas.wrapper')
31+ call_and_check(
32+ [cmd, 'config', '--mode', 'none'])
33+ else:
34+ # We can't use the --now flag as if the maas-rackd service is
35+ # on but not enabled the service won't be stopped
36+ call_and_check(
37+ ['sudo', 'systemctl', 'disable', 'maas-rackd'])
38+ call_and_check(
39+ ['sudo', 'systemctl', 'stop', 'maas-rackd'])
40 except ExternalProcessError as e:
41- maaslog.error("Unable to disable and stop maas-rackd service")
42- raise exceptions.CannotDisableAndShutoffRackd(e.output_as_unicode)
43+ # Since the snap sends a SIGTERM to terminate the process, python
44+ # returns -15 as a return code. This indicates the termination
45+ # signal has been performed and the process terminated. However,
46+ # This is not a failure. As such, work around the non-zero return
47+ # (-15) and do not raise an error.
48+ if not (running_in_snap() and e.returncode == -15):
49+ maaslog.error("Unable to disable and stop the rackd service")
50+ raise exceptions.CannotDisableAndShutoffRackd(
51+ e.output_as_unicode)
52+ maaslog.info("Successfully stopped the rackd service.")
53 return {}
54
55
56diff --git a/src/provisioningserver/rpc/tests/test_clusterservice.py b/src/provisioningserver/rpc/tests/test_clusterservice.py
57index 4aea7c2..4b54fc9 100644
58--- a/src/provisioningserver/rpc/tests/test_clusterservice.py
59+++ b/src/provisioningserver/rpc/tests/test_clusterservice.py
60@@ -3127,18 +3127,47 @@ class TestClusterProtocol_DisableAndShutoffRackd(MAASTestCase):
61 cluster.DisableAndShutoffRackd.commandName)
62 self.assertIsNotNone(responder)
63
64- def test_issues_restart(self):
65+ def test_issues_restart_systemd(self):
66 mock_call_and_check = self.patch(clusterservice, 'call_and_check')
67 response = call_responder(
68 Cluster(), cluster.DisableAndShutoffRackd, {})
69 self.assertEquals({}, response.result)
70 self.assertEquals(2, mock_call_and_check.call_count)
71
72+ def test_issues_restart_snap(self):
73+ self.patch(clusterservice, 'running_in_snap').return_value = True
74+ self.patch(clusterservice, 'get_snap_path').return_value = '/'
75+ mock_call_and_check = self.patch(clusterservice, 'call_and_check')
76+ response = call_responder(
77+ Cluster(), cluster.DisableAndShutoffRackd, {})
78+ self.assertEquals({}, response.result)
79+ self.assertEquals(1, mock_call_and_check.call_count)
80+
81 @inlineCallbacks
82- def test_raises_error_on_failure(self):
83+ def test_raises_error_on_failure_systemd(self):
84 mock_call_and_check = self.patch(clusterservice, 'call_and_check')
85 mock_call_and_check.side_effect = ExternalProcessError(
86 1, 'systemctl', 'failure')
87 with ExpectedException(exceptions.CannotDisableAndShutoffRackd):
88 yield call_responder(
89 Cluster(), cluster.DisableAndShutoffRackd, {})
90+
91+ @inlineCallbacks
92+ def test_raises_error_on_failure_snap(self):
93+ mock_call_and_check = self.patch(clusterservice, 'call_and_check')
94+ mock_call_and_check.side_effect = ExternalProcessError(
95+ random.randint(1, 255), 'command-maas.wrapper', 'failure')
96+ with ExpectedException(exceptions.CannotDisableAndShutoffRackd):
97+ yield call_responder(
98+ Cluster(), cluster.DisableAndShutoffRackd, {})
99+
100+ def test_snap_ignores_signal_error_code_on_restart(self):
101+ self.patch(clusterservice, 'running_in_snap').return_value = True
102+ self.patch(clusterservice, 'get_snap_path').return_value = '/'
103+ mock_call_and_check = self.patch(clusterservice, 'call_and_check')
104+ mock_call_and_check.side_effect = ExternalProcessError(
105+ -15, 'command-maas.wrapper', 'failure')
106+ response = call_responder(
107+ Cluster(), cluster.DisableAndShutoffRackd, {})
108+ self.assertEquals({}, response.result)
109+ self.assertEquals(1, mock_call_and_check.call_count)

Subscribers

People subscribed via source and target branches