Merge lp:~ltrager/maas/disable_delete_rack into lp:~maas-committers/maas/trunk
- disable_delete_rack
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Lee Trager |
Approved revision: | no longer in the source branch. |
Merged at revision: | 5011 |
Proposed branch: | lp:~ltrager/maas/disable_delete_rack |
Merge into: | lp:~maas-committers/maas/trunk |
Prerequisite: | lp:~ltrager/maas/delete_rack |
Diff against target: |
215 lines (+106/-14) 6 files modified
src/maasserver/models/node.py (+10/-9) src/maasserver/models/tests/test_node.py (+30/-5) src/provisioningserver/rpc/cluster.py (+12/-0) src/provisioningserver/rpc/clusterservice.py (+24/-0) src/provisioningserver/rpc/exceptions.py (+5/-0) src/provisioningserver/rpc/tests/test_clusterservice.py (+25/-0) |
To merge this branch: | bzr merge lp:~ltrager/maas/disable_delete_rack |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Review via email: mp+293594@code.launchpad.net |
Commit message
Disable and stop the rackd service if running on deletion
Description of the change
Upon deletion of a rack controller if a secondary rack controller is still connected send an RPC call which disables and stops the maas-rackd service. A user can reenable it using systemctl. As maas-dhcpd{
Last Friday when testing this branch the delete failed because there still was a relation between the rack controller and RegionRackRPCCo
For maas-rackd to be able to disable and stop the maas-rackd service I had to add permission to 99-maas-sudoers. Review at https:/
MAAS Lander (maas-lander) wrote : | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~ltrager/maas/disable_delete_rack into lp:maas failed. Below is the output from the failed tests.
Hit:1 http://
Hit:2 http://
Get:3 http://
Hit:4 http://
Fetched 94.5 kB in 0s (179 kB/s)
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu3).
archdetect-deb is already the newest version (1.117ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
bash is already the newest version (4.3-14ubuntu1).
build-essential is already the newest version (12.1ubuntu2).
bzr is already the newest version (2.7.0-2ubuntu1).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubun
distro-info is already the newest version (0.14build1).
freeipmi-tools is already the newest version (1.4.11-1ubuntu1).
git is already the newest version (1:2.7.4-0ubuntu1).
isc-dhcp-common is already the newest version (4.3.3-5ubuntu12).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1ubuntu3).
libpq-dev is already the newest version (9.5.2-1).
make is already the newest version (4.1-6).
postgresql is already the newest version (9.5+173...
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~ltrager/maas/disable_delete_rack into lp:maas failed. Below is the output from the failed tests.
Hit:1 http://
Hit:2 http://
Get:3 http://
Hit:4 http://
Fetched 94.5 kB in 0s (217 kB/s)
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu3).
archdetect-deb is already the newest version (1.117ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
bash is already the newest version (4.3-14ubuntu1).
build-essential is already the newest version (12.1ubuntu2).
bzr is already the newest version (2.7.0-2ubuntu1).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubun
distro-info is already the newest version (0.14build1).
freeipmi-tools is already the newest version (1.4.11-1ubuntu1).
git is already the newest version (1:2.7.4-0ubuntu1).
isc-dhcp-common is already the newest version (4.3.3-5ubuntu12).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1ubuntu3).
libpq-dev is already the newest version (9.5.2-1).
make is already the newest version (4.1-6).
postgresql is already the newest version (9.5+173...
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~ltrager/maas/disable_delete_rack into lp:maas failed. Below is the output from the failed tests.
Hit:1 http://
Get:2 http://
Hit:3 http://
Hit:4 http://
Get:5 http://
Get:6 http://
Fetched 174 kB in 0s (397 kB/s)
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu3).
archdetect-deb is already the newest version (1.117ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
bash is already the newest version (4.3-14ubuntu1).
build-essential is already the newest version (12.1ubuntu2).
bzr is already the newest version (2.7.0-2ubuntu1).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubun
distro-info is already the newest version (0.14build1).
freeipmi-tools is already the newest version (1.4.11-1ubuntu1).
git is already the newest version (1:2.7.4-0ubuntu1).
isc-dhcp-common is already the newest version (4.3.3-5ubuntu12).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
l...
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~ltrager/maas/disable_delete_rack into lp:maas failed. Below is the output from the failed tests.
Hit:1 http://
Get:2 http://
Hit:3 http://
Hit:4 http://
Fetched 94.5 kB in 0s (231 kB/s)
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-2ubuntu3).
archdetect-deb is already the newest version (1.117ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
bash is already the newest version (4.3-14ubuntu1).
build-essential is already the newest version (12.1ubuntu2).
bzr is already the newest version (2.7.0-2ubuntu1).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubun
distro-info is already the newest version (0.14build1).
freeipmi-tools is already the newest version (1.4.11-1ubuntu1).
git is already the newest version (1:2.7.4-0ubuntu1).
isc-dhcp-common is already the newest version (4.3.3-5ubuntu12).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1ubuntu3).
libpq-dev is already the newest version (9.5.2-1).
make is already the newest version (4.1-6).
postgresql is already the newest version (9...
Andres Rodriguez (andreserl) wrote : | # |
ERROR: provisioningser
-------
testtools.
Traceback (most recent call last):
provisioningser
}}}
twisted-log: {{{
2016-05-10 18:30:20+0000 [-] Unhandled error in Deferred:
2016-05-10 18:30:20+0000 [-] Unhandled Error
Traceback (most recent call last):
Failure: provisioningser
}}}
-------
Ran 2369 tests in 44.324s
Preview Diff
1 | === modified file 'src/maasserver/models/node.py' |
2 | --- src/maasserver/models/node.py 2016-05-09 21:18:43 +0000 |
3 | +++ src/maasserver/models/node.py 2016-05-10 23:45:39 +0000 |
4 | @@ -162,6 +162,7 @@ |
5 | from provisioningserver.power import QUERY_POWER_TYPES |
6 | from provisioningserver.rpc.cluster import ( |
7 | AddChassis, |
8 | + DisableAndShutoffRackd, |
9 | IsImportBootImagesRunning, |
10 | RefreshRackControllerInfo, |
11 | ) |
12 | @@ -3658,15 +3659,6 @@ |
13 | |
14 | def delete(self): |
15 | """Delete this rack controller.""" |
16 | - # Avoid circular dependency. |
17 | - from maasserver.models import RegionRackRPCConnection |
18 | - connections = RegionRackRPCConnection.objects.filter( |
19 | - rack_controller=self) |
20 | - if len(connections) != 0: |
21 | - raise ValidationError( |
22 | - "Unable to delete %s as it's currently connected to one or " |
23 | - "more regions." % self.hostname) |
24 | - |
25 | primary_vlans = VLAN.objects.filter(primary_rack=self) |
26 | if len(primary_vlans) != 0: |
27 | raise ValidationError( |
28 | @@ -3675,6 +3667,15 @@ |
29 | (self.hostname, |
30 | ', '.join([str(vlan) for vlan in primary_vlans]))) |
31 | |
32 | + try: |
33 | + client = getClientFor(self.system_id, timeout=1) |
34 | + call = client(DisableAndShutoffRackd) |
35 | + call.wait(30) |
36 | + except NoConnectionsAvailable: |
37 | + # NoConnectionsAvailable is always thrown. Either because the rack |
38 | + # is currently disconnected or rackd was killed |
39 | + pass |
40 | + |
41 | for vlan in VLAN.objects.filter(secondary_rack=self): |
42 | vlan.secondary_rack = None |
43 | vlan.save() |
44 | |
45 | === modified file 'src/maasserver/models/tests/test_node.py' |
46 | --- src/maasserver/models/tests/test_node.py 2016-05-09 23:54:19 +0000 |
47 | +++ src/maasserver/models/tests/test_node.py 2016-05-10 23:45:39 +0000 |
48 | @@ -137,10 +137,12 @@ |
49 | from provisioningserver.power.schema import JSON_POWER_TYPE_PARAMETERS |
50 | from provisioningserver.rpc.cluster import ( |
51 | AddChassis, |
52 | + DisableAndShutoffRackd, |
53 | IsImportBootImagesRunning, |
54 | RefreshRackControllerInfo, |
55 | ) |
56 | from provisioningserver.rpc.exceptions import ( |
57 | + CannotDisableAndShutoffRackd, |
58 | NoConnectionsAvailable, |
59 | UnknownPowerType, |
60 | ) |
61 | @@ -6992,11 +6994,34 @@ |
62 | rackcontroller.delete() |
63 | self.assertIsNone(reload_object(rackcontroller)) |
64 | |
65 | - def test_prevents_delete_when_connected(self): |
66 | - rackcontroller = factory.make_RackController() |
67 | - mock_filter = self.patch(RegionRackRPCConnection.objects, 'filter') |
68 | - mock_filter.return_value = [rackcontroller] |
69 | - self.assertRaises(ValidationError, rackcontroller.delete) |
70 | + def test_disables_and_disconn_when_secondary_connected(self): |
71 | + rackcontroller = factory.make_RackController() |
72 | + factory.make_VLAN(secondary_rack=rackcontroller) |
73 | + |
74 | + self.useFixture(RegionEventLoopFixture("rpc")) |
75 | + self.useFixture(RunningEventLoopFixture()) |
76 | + fixture = self.useFixture(MockLiveRegionToClusterRPCFixture()) |
77 | + protocol = fixture.makeCluster( |
78 | + rackcontroller, DisableAndShutoffRackd) |
79 | + protocol.DisableAndShutoffRackd.return_value = defer.succeed({}) |
80 | + |
81 | + rackcontroller.delete() |
82 | + self.expectThat(protocol.DisableAndShutoffRackd, MockCalledOnce()) |
83 | + |
84 | + def test_disables_and_disconn_when_secondary_connected_fails(self): |
85 | + rackcontroller = factory.make_RackController() |
86 | + factory.make_VLAN(secondary_rack=rackcontroller) |
87 | + |
88 | + self.useFixture(RegionEventLoopFixture("rpc")) |
89 | + self.useFixture(RunningEventLoopFixture()) |
90 | + fixture = self.useFixture(MockLiveRegionToClusterRPCFixture()) |
91 | + protocol = fixture.makeCluster( |
92 | + rackcontroller, DisableAndShutoffRackd) |
93 | + protocol.DisableAndShutoffRackd.return_value = defer.fail( |
94 | + CannotDisableAndShutoffRackd()) |
95 | + |
96 | + self.assertRaises(CannotDisableAndShutoffRackd, rackcontroller.delete) |
97 | + self.expectThat(protocol.DisableAndShutoffRackd, MockCalledOnce()) |
98 | |
99 | def test_prevents_delete_when_primary_rack(self): |
100 | rackcontroller = factory.make_RackController() |
101 | |
102 | === modified file 'src/provisioningserver/rpc/cluster.py' |
103 | --- src/provisioningserver/rpc/cluster.py 2016-04-29 22:12:18 +0000 |
104 | +++ src/provisioningserver/rpc/cluster.py 2016-05-10 23:45:39 +0000 |
105 | @@ -478,3 +478,15 @@ |
106 | (b"protocol", amp.Unicode(optional=True)), |
107 | ] |
108 | errors = {} |
109 | + |
110 | + |
111 | +class DisableAndShutoffRackd(amp.Command): |
112 | + """Disable and shutdown the rackd service. |
113 | + |
114 | + :since: 2.0 |
115 | + """ |
116 | + arguments = [] |
117 | + errors = { |
118 | + exceptions.CannotDisableAndShutoffRackd: ( |
119 | + b"CannotDisableAndShutoffRackd"), |
120 | + } |
121 | |
122 | === modified file 'src/provisioningserver/rpc/clusterservice.py' |
123 | --- src/provisioningserver/rpc/clusterservice.py 2016-04-29 22:12:18 +0000 |
124 | +++ src/provisioningserver/rpc/clusterservice.py 2016-05-10 23:45:39 +0000 |
125 | @@ -72,6 +72,10 @@ |
126 | get_maas_id, |
127 | set_maas_id, |
128 | ) |
129 | +from provisioningserver.utils.shell import ( |
130 | + call_and_check, |
131 | + ExternalProcessError, |
132 | +) |
133 | from provisioningserver.utils.twisted import ( |
134 | DeferredValue, |
135 | synchronous, |
136 | @@ -460,6 +464,26 @@ |
137 | maaslog.error(message) |
138 | return {} |
139 | |
140 | + @cluster.DisableAndShutoffRackd.responder |
141 | + def disable_and_shutoff_rackd(self): |
142 | + """DisableAndShutoffRackd() |
143 | + |
144 | + Implementation of |
145 | + :py:class:`~provisioningserver.rpc.cluster.DisableAndShutoffRackd`. |
146 | + """ |
147 | + maaslog.info("Rack deleted, disabling rackd service") |
148 | + try: |
149 | + # We can't use the --now flag as if the maas-rackd service is on |
150 | + # but not enabled the service won't be stopped |
151 | + call_and_check( |
152 | + ['sudo', 'systemctl', 'disable', 'maas-rackd']) |
153 | + call_and_check( |
154 | + ['sudo', 'systemctl', 'stop', 'maas-rackd']) |
155 | + except ExternalProcessError as e: |
156 | + maaslog.error("Unable to disable and stop maas-rackd service") |
157 | + raise exceptions.CannotDisableAndShutoffRackd(e.output_as_unicode) |
158 | + return {} |
159 | + |
160 | |
161 | @implementer(IConnection) |
162 | class ClusterClient(Cluster): |
163 | |
164 | === modified file 'src/provisioningserver/rpc/exceptions.py' |
165 | --- src/provisioningserver/rpc/exceptions.py 2016-04-11 16:23:26 +0000 |
166 | +++ src/provisioningserver/rpc/exceptions.py 2016-05-10 23:45:39 +0000 |
167 | @@ -7,6 +7,7 @@ |
168 | "AuthenticationFailed", |
169 | "CannotConfigureDHCP", |
170 | "CannotCreateHostMap", |
171 | + "CannotDisableAndShutoffRackd", |
172 | "CannotModifyHostMap", |
173 | "CannotRegisterCluster", |
174 | "CannotRemoveHostMap", |
175 | @@ -146,3 +147,7 @@ |
176 | |
177 | class BootConfigNoResponse(Exception): |
178 | """The region gave no response for the boot configuration.""" |
179 | + |
180 | + |
181 | +class CannotDisableAndShutoffRackd(Exception): |
182 | + """Rackd cannot be disabled and shutoff.""" |
183 | |
184 | === modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py' |
185 | --- src/provisioningserver/rpc/tests/test_clusterservice.py 2016-05-10 11:02:10 +0000 |
186 | +++ src/provisioningserver/rpc/tests/test_clusterservice.py 2016-05-10 23:45:39 +0000 |
187 | @@ -2392,3 +2392,28 @@ |
188 | 'hostname': factory.make_hostname(), |
189 | }) |
190 | self.assertEquals({}, response.result) |
191 | + |
192 | + |
193 | +class TestClusterProtocol_DisableAndShutoffRackd(MAASTestCase): |
194 | + |
195 | + def test__is_registered(self): |
196 | + protocol = Cluster() |
197 | + responder = protocol.locateResponder( |
198 | + cluster.DisableAndShutoffRackd.commandName) |
199 | + self.assertIsNotNone(responder) |
200 | + |
201 | + def test_issues_restart(self): |
202 | + mock_call_and_check = self.patch(clusterservice, 'call_and_check') |
203 | + response = call_responder( |
204 | + Cluster(), cluster.DisableAndShutoffRackd, {}) |
205 | + self.assertEquals({}, response.result) |
206 | + self.assertEquals(2, mock_call_and_check.call_count) |
207 | + |
208 | + @inlineCallbacks |
209 | + def test_raises_error_on_failure(self): |
210 | + mock_call_and_check = self.patch(clusterservice, 'call_and_check') |
211 | + mock_call_and_check.side_effect = ExternalProcessError( |
212 | + 1, 'systemctl', 'failure') |
213 | + with ExpectedException(exceptions.CannotDisableAndShutoffRackd): |
214 | + yield call_responder( |
215 | + Cluster(), cluster.DisableAndShutoffRackd, {}) |
This looks really good. Nice work.