Merge lp:~blake-rouse/maas/fix-1402109-1.7 into lp:maas/1.7
- fix-1402109-1.7
- Merge into 1.7
Status: | Merged |
---|---|
Merged at revision: | 3333 |
Proposed branch: | lp:~blake-rouse/maas/fix-1402109-1.7 |
Merge into: | lp:maas/1.7 |
Diff against target: |
313 lines (+143/-27) 2 files modified
src/provisioningserver/rpc/clusterservice.py (+25/-4) src/provisioningserver/rpc/tests/test_clusterservice.py (+118/-23) |
To merge this branch: | bzr merge lp:~blake-rouse/maas/fix-1402109-1.7 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christian Reis (community) | Approve | ||
Blake Rouse (community) | Approve | ||
Review via email: mp+245116@code.launchpad.net |
Commit message
deferToThread all probe-and-enlist functions on the cluster.
Description of the change
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~blake-rouse/maas/fix-1402109-1.7 into lp:maas/1.7 failed. Below is the output from the failed tests.
Ign http://
Get:1 http://
Ign http://
Get:2 http://
Ign http://
Hit http://
Get:3 http://
Hit http://
Get:4 http://
Get:5 http://
Hit http://
Get:6 http://
Get:7 http://
Get:8 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:9 http://
Get:10 http://
Get:11 http://
Get:12 http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,315 kB in 2s (448 kB/s)
Reading package lists...
sudo DEBIAN_
--
Preview Diff
1 | === modified file 'src/provisioningserver/rpc/clusterservice.py' |
2 | --- src/provisioningserver/rpc/clusterservice.py 2014-12-08 16:50:57 +0000 |
3 | +++ src/provisioningserver/rpc/clusterservice.py 2014-12-18 15:28:52 +0000 |
4 | @@ -16,6 +16,7 @@ |
5 | "ClusterClientService", |
6 | ] |
7 | |
8 | +from functools import partial |
9 | import json |
10 | import logging |
11 | from os import urandom |
12 | @@ -108,6 +109,14 @@ |
13 | maaslog = get_maas_logger("rpc.cluster") |
14 | |
15 | |
16 | +def catch_probe_and_enlist_error(name, failure): |
17 | + """Logs any errors when trying to probe and enlist a chassis.""" |
18 | + maaslog.error( |
19 | + "Failed to probe and enlist %s nodes: %s", |
20 | + name, failure.getErrorMessage()) |
21 | + return None |
22 | + |
23 | + |
24 | class Cluster(RPCProtocol): |
25 | """The RPC protocol supported by a cluster controller. |
26 | |
27 | @@ -349,7 +358,10 @@ |
28 | |
29 | Implementation of :py:class:`~provisioningserver.rpc.cluster.AddVirsh`. |
30 | """ |
31 | - probe_virsh_and_enlist(poweraddr, password, prefix_filter) |
32 | + d = deferToThread( |
33 | + probe_virsh_and_enlist, |
34 | + poweraddr, password, prefix_filter) |
35 | + d.addErrback(partial(catch_probe_and_enlist_error, "virsh")) |
36 | return {} |
37 | |
38 | @cluster.AddSeaMicro15k.responder |
39 | @@ -361,9 +373,12 @@ |
40 | """ |
41 | ip = find_ip_via_arp(mac) |
42 | if ip is not None: |
43 | - probe_seamicro15k_and_enlist( |
44 | + d = deferToThread( |
45 | + probe_seamicro15k_and_enlist, |
46 | ip, username, password, |
47 | power_control=power_control) |
48 | + d.addErrback( |
49 | + partial(catch_probe_and_enlist_error, "SeaMicro 15000")) |
50 | else: |
51 | message = "Couldn't find IP address for MAC %s" % mac |
52 | maaslog.warning(message) |
53 | @@ -377,7 +392,10 @@ |
54 | Implemention of |
55 | :py:class:`~provisioningserver.rpc.cluster.EnlistNodesFromMSCM`. |
56 | """ |
57 | - probe_and_enlist_mscm(host, username, password) |
58 | + d = deferToThread( |
59 | + probe_and_enlist_mscm, |
60 | + host, username, password) |
61 | + d.addErrback(partial(catch_probe_and_enlist_error, "Moonshot")) |
62 | return {} |
63 | |
64 | @cluster.EnlistNodesFromUCSM.responder |
65 | @@ -387,7 +405,10 @@ |
66 | Implemention of |
67 | :py:class:`~provisioningserver.rpc.cluster.EnlistNodesFromUCSM`. |
68 | """ |
69 | - probe_and_enlist_ucsm(url, username, password) |
70 | + d = deferToThread( |
71 | + probe_and_enlist_ucsm, |
72 | + url, username, password) |
73 | + d.addErrback(partial(catch_probe_and_enlist_error, "UCS")) |
74 | return {} |
75 | |
76 | |
77 | |
78 | === modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py' |
79 | --- src/provisioningserver/rpc/tests/test_clusterservice.py 2014-12-16 19:29:45 +0000 |
80 | +++ src/provisioningserver/rpc/tests/test_clusterservice.py 2014-12-18 15:28:52 +0000 |
81 | @@ -32,6 +32,7 @@ |
82 | from maastesting.factory import factory |
83 | from maastesting.matchers import ( |
84 | IsUnfiredDeferred, |
85 | + MockAnyCall, |
86 | MockCalledOnceWith, |
87 | MockCalledWith, |
88 | MockCallsMatch, |
89 | @@ -1886,9 +1887,9 @@ |
90 | cluster.AddVirsh.commandName) |
91 | self.assertIsNotNone(responder) |
92 | |
93 | - def test__calls_probe_virsh_and_enlist(self): |
94 | - probe_virsh_and_enlist = self.patch_autospec( |
95 | - clusterservice, 'probe_virsh_and_enlist') |
96 | + def test__calls_deferToThread_with_probe_virsh_and_enlist(self): |
97 | + mock_deferToThread = self.patch_autospec( |
98 | + clusterservice, 'deferToThread') |
99 | poweraddr = factory.make_name('poweraddr') |
100 | password = factory.make_name('password') |
101 | prefix_filter = factory.make_name('prefix_filter') |
102 | @@ -1898,32 +1899,55 @@ |
103 | "prefix_filter": prefix_filter, |
104 | }) |
105 | self.assertThat( |
106 | - probe_virsh_and_enlist, MockCalledOnceWith( |
107 | + mock_deferToThread, MockCalledOnceWith( |
108 | + clusterservice.probe_virsh_and_enlist, |
109 | poweraddr, password, prefix_filter)) |
110 | |
111 | def test__password_is_optional(self): |
112 | - probe_virsh_and_enlist = self.patch_autospec( |
113 | - clusterservice, 'probe_virsh_and_enlist') |
114 | + mock_deferToThread = self.patch_autospec( |
115 | + clusterservice, 'deferToThread') |
116 | poweraddr = factory.make_name('poweraddr') |
117 | call_responder(Cluster(), cluster.AddVirsh, { |
118 | "poweraddr": poweraddr, |
119 | "password": None, |
120 | }) |
121 | self.assertThat( |
122 | - probe_virsh_and_enlist, MockCalledOnceWith( |
123 | + mock_deferToThread, MockCalledOnceWith( |
124 | + clusterservice.probe_virsh_and_enlist, |
125 | poweraddr, None, None)) |
126 | |
127 | def test__can_be_called_without_password_key(self): |
128 | - probe_virsh_and_enlist = self.patch_autospec( |
129 | - clusterservice, 'probe_virsh_and_enlist') |
130 | + mock_deferToThread = self.patch_autospec( |
131 | + clusterservice, 'deferToThread') |
132 | poweraddr = factory.make_name('poweraddr') |
133 | call_responder(Cluster(), cluster.AddVirsh, { |
134 | "poweraddr": poweraddr, |
135 | }) |
136 | self.assertThat( |
137 | - probe_virsh_and_enlist, MockCalledOnceWith( |
138 | + mock_deferToThread, MockCalledOnceWith( |
139 | + clusterservice.probe_virsh_and_enlist, |
140 | poweraddr, None, None)) |
141 | |
142 | + def test__logs_error_to_maaslog(self): |
143 | + fake_error = factory.make_name('error') |
144 | + self.patch(clusterservice, 'maaslog') |
145 | + mock_deferToThread = self.patch_autospec( |
146 | + clusterservice, 'deferToThread') |
147 | + mock_deferToThread.return_value = fail(Exception(fake_error)) |
148 | + poweraddr = factory.make_name('poweraddr') |
149 | + password = factory.make_name('password') |
150 | + prefix_filter = factory.make_name('prefix_filter') |
151 | + call_responder(Cluster(), cluster.AddVirsh, { |
152 | + "poweraddr": poweraddr, |
153 | + "password": password, |
154 | + "prefix_filter": prefix_filter, |
155 | + }) |
156 | + self.assertThat( |
157 | + clusterservice.maaslog.error, |
158 | + MockAnyCall( |
159 | + "Failed to probe and enlist %s nodes: %s", |
160 | + "virsh", fake_error)) |
161 | + |
162 | |
163 | class TestClusterProtocol_AddSeaMicro15k(MAASTestCase): |
164 | |
165 | @@ -1936,7 +1960,7 @@ |
166 | def test__calls_find_ip_via_arp(self): |
167 | # Prevent any actual probing from happing. |
168 | self.patch_autospec( |
169 | - clusterservice, 'probe_seamicro15k_and_enlist') |
170 | + clusterservice, 'deferToThread') |
171 | find_ip_via_arp = self.patch_autospec( |
172 | clusterservice, 'find_ip_via_arp') |
173 | find_ip_via_arp.return_value = factory.make_ipv4_address() |
174 | @@ -1980,9 +2004,9 @@ |
175 | MockCalledOnceWith( |
176 | "Couldn't find IP address for MAC %s" % mac)) |
177 | |
178 | - def test__calls_probe_seamicro15k_and_enlist(self): |
179 | - probe_seamicro15k_and_enlist = self.patch_autospec( |
180 | - clusterservice, 'probe_seamicro15k_and_enlist') |
181 | + def test__calls_deferToThread_with_probe_seamicro15k_and_enlist(self): |
182 | + mock_deferToThread = self.patch_autospec( |
183 | + clusterservice, 'deferToThread') |
184 | find_ip_via_arp = self.patch_autospec( |
185 | clusterservice, 'find_ip_via_arp') |
186 | find_ip_via_arp.return_value = factory.make_ipv4_address() |
187 | @@ -1999,10 +2023,37 @@ |
188 | }) |
189 | |
190 | self.assertThat( |
191 | - probe_seamicro15k_and_enlist, MockCalledOnceWith( |
192 | + mock_deferToThread, MockCalledOnceWith( |
193 | + clusterservice.probe_seamicro15k_and_enlist, |
194 | find_ip_via_arp.return_value, username, password, |
195 | power_control=power_control)) |
196 | |
197 | + def test__logs_error_to_maaslog(self): |
198 | + fake_error = factory.make_name('error') |
199 | + self.patch(clusterservice, 'maaslog') |
200 | + mock_deferToThread = self.patch_autospec( |
201 | + clusterservice, 'deferToThread') |
202 | + mock_deferToThread.return_value = fail(Exception(fake_error)) |
203 | + find_ip_via_arp = self.patch_autospec( |
204 | + clusterservice, 'find_ip_via_arp') |
205 | + find_ip_via_arp.return_value = factory.make_ipv4_address() |
206 | + |
207 | + mac = factory.make_mac_address() |
208 | + username = factory.make_name('user') |
209 | + password = factory.make_name('password') |
210 | + power_control = factory.make_name('power_control') |
211 | + call_responder(Cluster(), cluster.AddSeaMicro15k, { |
212 | + "mac": mac, |
213 | + "username": username, |
214 | + "password": password, |
215 | + "power_control": power_control, |
216 | + }) |
217 | + self.assertThat( |
218 | + clusterservice.maaslog.error, |
219 | + MockAnyCall( |
220 | + "Failed to probe and enlist %s nodes: %s", |
221 | + "SeaMicro 15000", fake_error)) |
222 | + |
223 | |
224 | class TestClusterProtocol_EnlistNodesFromMSCM(MAASTestCase): |
225 | |
226 | @@ -2012,9 +2063,9 @@ |
227 | cluster.EnlistNodesFromMSCM.commandName) |
228 | self.assertIsNotNone(responder) |
229 | |
230 | - def test__calls_probe_and_enlist_mscm(self): |
231 | - probe_and_enlist_mscm = self.patch_autospec( |
232 | - clusterservice, 'probe_and_enlist_mscm') |
233 | + def test__deferToThread_with_probe_and_enlist_mscm(self): |
234 | + mock_deferToThread = self.patch_autospec( |
235 | + clusterservice, 'deferToThread') |
236 | |
237 | host = factory.make_name('host') |
238 | username = factory.make_name('user') |
239 | @@ -2027,9 +2078,31 @@ |
240 | }) |
241 | |
242 | self.assertThat( |
243 | - probe_and_enlist_mscm, MockCalledOnceWith( |
244 | + mock_deferToThread, MockCalledOnceWith( |
245 | + clusterservice.probe_and_enlist_mscm, |
246 | host, username, password)) |
247 | |
248 | + def test__logs_error_to_maaslog(self): |
249 | + fake_error = factory.make_name('error') |
250 | + self.patch(clusterservice, 'maaslog') |
251 | + mock_deferToThread = self.patch_autospec( |
252 | + clusterservice, 'deferToThread') |
253 | + mock_deferToThread.return_value = fail(Exception(fake_error)) |
254 | + host = factory.make_name('host') |
255 | + username = factory.make_name('user') |
256 | + password = factory.make_name('password') |
257 | + |
258 | + call_responder(Cluster(), cluster.EnlistNodesFromMSCM, { |
259 | + "host": host, |
260 | + "username": username, |
261 | + "password": password, |
262 | + }) |
263 | + self.assertThat( |
264 | + clusterservice.maaslog.error, |
265 | + MockAnyCall( |
266 | + "Failed to probe and enlist %s nodes: %s", |
267 | + "Moonshot", fake_error)) |
268 | + |
269 | |
270 | class TestClusterProtocol_EnlistNodesFromUCSM(MAASTestCase): |
271 | |
272 | @@ -2039,9 +2112,9 @@ |
273 | cluster.EnlistNodesFromUCSM.commandName) |
274 | self.assertIsNotNone(responder) |
275 | |
276 | - def test__calls_probe_and_enlist_ucsm(self): |
277 | - probe_and_enlist_ucsm = self.patch_autospec( |
278 | - clusterservice, 'probe_and_enlist_ucsm') |
279 | + def test__calls_deferToThread_with_probe_and_enlist_ucsm(self): |
280 | + mock_deferToThread = self.patch_autospec( |
281 | + clusterservice, 'deferToThread') |
282 | |
283 | url = factory.make_url() |
284 | username = factory.make_name('user') |
285 | @@ -2054,5 +2127,27 @@ |
286 | }) |
287 | |
288 | self.assertThat( |
289 | - probe_and_enlist_ucsm, MockCalledOnceWith( |
290 | + mock_deferToThread, MockCalledOnceWith( |
291 | + clusterservice.probe_and_enlist_ucsm, |
292 | url, username, password)) |
293 | + |
294 | + def test__logs_error_to_maaslog(self): |
295 | + fake_error = factory.make_name('error') |
296 | + self.patch(clusterservice, 'maaslog') |
297 | + mock_deferToThread = self.patch_autospec( |
298 | + clusterservice, 'deferToThread') |
299 | + mock_deferToThread.return_value = fail(Exception(fake_error)) |
300 | + url = factory.make_url() |
301 | + username = factory.make_name('user') |
302 | + password = factory.make_name('password') |
303 | + |
304 | + call_responder(Cluster(), cluster.EnlistNodesFromUCSM, { |
305 | + "url": url, |
306 | + "username": username, |
307 | + "password": password, |
308 | + }) |
309 | + self.assertThat( |
310 | + clusterservice.maaslog.error, |
311 | + MockAnyCall( |
312 | + "Failed to probe and enlist %s nodes: %s", |
313 | + "UCS", fake_error)) |
Self-approving backport.