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
diff --git a/src/provisioningserver/rpc/clusterservice.py b/src/provisioningserver/rpc/clusterservice.py
index 7157c81..50019d3 100644
--- a/src/provisioningserver/rpc/clusterservice.py
+++ b/src/provisioningserver/rpc/clusterservice.py
@@ -98,6 +98,10 @@ from provisioningserver.utils.shell import (
98 ExternalProcessError,98 ExternalProcessError,
99 select_c_utf8_bytes_locale,99 select_c_utf8_bytes_locale,
100)100)
101from provisioningserver.utils.snappy import (
102 get_snap_path,
103 running_in_snap,
104)
101from provisioningserver.utils.twisted import (105from provisioningserver.utils.twisted import (
102 call,106 call,
103 callOut,107 callOut,
@@ -676,17 +680,30 @@ class Cluster(RPCProtocol):
676 Implementation of680 Implementation of
677 :py:class:`~provisioningserver.rpc.cluster.DisableAndShutoffRackd`.681 :py:class:`~provisioningserver.rpc.cluster.DisableAndShutoffRackd`.
678 """682 """
679 maaslog.info("Rack deleted, disabling rackd service")683 maaslog.info("Attempting to disable the rackd service.")
680 try:684 try:
681 # We can't use the --now flag as if the maas-rackd service is on685 if running_in_snap():
682 # but not enabled the service won't be stopped686 cmd = os.path.join(get_snap_path(), 'command-maas.wrapper')
683 call_and_check(687 call_and_check(
684 ['sudo', 'systemctl', 'disable', 'maas-rackd'])688 [cmd, 'config', '--mode', 'none'])
685 call_and_check(689 else:
686 ['sudo', 'systemctl', 'stop', 'maas-rackd'])690 # We can't use the --now flag as if the maas-rackd service is
691 # on but not enabled the service won't be stopped
692 call_and_check(
693 ['sudo', 'systemctl', 'disable', 'maas-rackd'])
694 call_and_check(
695 ['sudo', 'systemctl', 'stop', 'maas-rackd'])
687 except ExternalProcessError as e:696 except ExternalProcessError as e:
688 maaslog.error("Unable to disable and stop maas-rackd service")697 # Since the snap sends a SIGTERM to terminate the process, python
689 raise exceptions.CannotDisableAndShutoffRackd(e.output_as_unicode)698 # returns -15 as a return code. This indicates the termination
699 # signal has been performed and the process terminated. However,
700 # This is not a failure. As such, work around the non-zero return
701 # (-15) and do not raise an error.
702 if not (running_in_snap() and e.returncode == -15):
703 maaslog.error("Unable to disable and stop the rackd service")
704 raise exceptions.CannotDisableAndShutoffRackd(
705 e.output_as_unicode)
706 maaslog.info("Successfully stopped the rackd service.")
690 return {}707 return {}
691708
692709
diff --git a/src/provisioningserver/rpc/tests/test_clusterservice.py b/src/provisioningserver/rpc/tests/test_clusterservice.py
index 4aea7c2..4b54fc9 100644
--- a/src/provisioningserver/rpc/tests/test_clusterservice.py
+++ b/src/provisioningserver/rpc/tests/test_clusterservice.py
@@ -3127,18 +3127,47 @@ class TestClusterProtocol_DisableAndShutoffRackd(MAASTestCase):
3127 cluster.DisableAndShutoffRackd.commandName)3127 cluster.DisableAndShutoffRackd.commandName)
3128 self.assertIsNotNone(responder)3128 self.assertIsNotNone(responder)
31293129
3130 def test_issues_restart(self):3130 def test_issues_restart_systemd(self):
3131 mock_call_and_check = self.patch(clusterservice, 'call_and_check')3131 mock_call_and_check = self.patch(clusterservice, 'call_and_check')
3132 response = call_responder(3132 response = call_responder(
3133 Cluster(), cluster.DisableAndShutoffRackd, {})3133 Cluster(), cluster.DisableAndShutoffRackd, {})
3134 self.assertEquals({}, response.result)3134 self.assertEquals({}, response.result)
3135 self.assertEquals(2, mock_call_and_check.call_count)3135 self.assertEquals(2, mock_call_and_check.call_count)
31363136
3137 def test_issues_restart_snap(self):
3138 self.patch(clusterservice, 'running_in_snap').return_value = True
3139 self.patch(clusterservice, 'get_snap_path').return_value = '/'
3140 mock_call_and_check = self.patch(clusterservice, 'call_and_check')
3141 response = call_responder(
3142 Cluster(), cluster.DisableAndShutoffRackd, {})
3143 self.assertEquals({}, response.result)
3144 self.assertEquals(1, mock_call_and_check.call_count)
3145
3137 @inlineCallbacks3146 @inlineCallbacks
3138 def test_raises_error_on_failure(self):3147 def test_raises_error_on_failure_systemd(self):
3139 mock_call_and_check = self.patch(clusterservice, 'call_and_check')3148 mock_call_and_check = self.patch(clusterservice, 'call_and_check')
3140 mock_call_and_check.side_effect = ExternalProcessError(3149 mock_call_and_check.side_effect = ExternalProcessError(
3141 1, 'systemctl', 'failure')3150 1, 'systemctl', 'failure')
3142 with ExpectedException(exceptions.CannotDisableAndShutoffRackd):3151 with ExpectedException(exceptions.CannotDisableAndShutoffRackd):
3143 yield call_responder(3152 yield call_responder(
3144 Cluster(), cluster.DisableAndShutoffRackd, {})3153 Cluster(), cluster.DisableAndShutoffRackd, {})
3154
3155 @inlineCallbacks
3156 def test_raises_error_on_failure_snap(self):
3157 mock_call_and_check = self.patch(clusterservice, 'call_and_check')
3158 mock_call_and_check.side_effect = ExternalProcessError(
3159 random.randint(1, 255), 'command-maas.wrapper', 'failure')
3160 with ExpectedException(exceptions.CannotDisableAndShutoffRackd):
3161 yield call_responder(
3162 Cluster(), cluster.DisableAndShutoffRackd, {})
3163
3164 def test_snap_ignores_signal_error_code_on_restart(self):
3165 self.patch(clusterservice, 'running_in_snap').return_value = True
3166 self.patch(clusterservice, 'get_snap_path').return_value = '/'
3167 mock_call_and_check = self.patch(clusterservice, 'call_and_check')
3168 mock_call_and_check.side_effect = ExternalProcessError(
3169 -15, 'command-maas.wrapper', 'failure')
3170 response = call_responder(
3171 Cluster(), cluster.DisableAndShutoffRackd, {})
3172 self.assertEquals({}, response.result)
3173 self.assertEquals(1, mock_call_and_check.call_count)

Subscribers

People subscribed via source and target branches