Merge lp:~gmb/maas/enlist-uscm-to-RPC into lp:~maas-committers/maas/trunk
- enlist-uscm-to-RPC
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Graham Binns |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2957 |
Proposed branch: | lp:~gmb/maas/enlist-uscm-to-RPC |
Merge into: | lp:~maas-committers/maas/trunk |
Prerequisite: | lp:~gmb/maas/enlist-mscm-to-RPC |
Diff against target: |
291 lines (+126/-33) 8 files modified
src/maasserver/api/tests/test_nodegroup.py (+9/-4) src/maasserver/models/nodegroup.py (+15/-3) src/maasserver/models/tests/test_nodegroup.py (+50/-0) src/provisioningserver/rpc/cluster.py (+14/-0) src/provisioningserver/rpc/clusterservice.py (+11/-0) src/provisioningserver/rpc/tests/test_clusterservice.py (+27/-0) src/provisioningserver/tasks.py (+0/-13) src/provisioningserver/tests/test_tasks.py (+0/-13) |
To merge this branch: | bzr merge lp:~gmb/maas/enlist-uscm-to-RPC |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Raphaël Badin (community) | Approve | ||
Review via email: mp+234285@code.launchpad.net |
This proposal supersedes a proposal from 2014-09-11.
Commit message
Convert the enlist_
Description of the change
Graham Binns (gmb) wrote : | # |
On 11 September 2014 11:35, Raphaël Badin <email address hidden> wrote:
>
>
> When the method is called from the API it will be transformed into a 500 error. This is probably what we want but could you check that the error message in that case is meaningful? (I mean, I'd like to be sure it mentions at least the UUID problematic cluster.)
Yes, I'll check. I'll fix that in a followup branch if necessary;
there are several sites that follow this pattern and they could all do
with the same love :)
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~gmb/maas/enlist-uscm-to-RPC into lp:maas failed. Below is the output from the failed tests.
Ign http://
Hit http://
Hit http://
Ign http://
Ign http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Ign http://
Ign http://
Reading package lists...
sudo DEBIAN_
--
Preview Diff
1 | === modified file 'src/maasserver/api/tests/test_nodegroup.py' | |||
2 | --- src/maasserver/api/tests/test_nodegroup.py 2014-09-11 11:21:49 +0000 | |||
3 | +++ src/maasserver/api/tests/test_nodegroup.py 2014-09-11 12:18:08 +0000 | |||
4 | @@ -57,6 +57,7 @@ | |||
5 | 57 | from provisioningserver.auth import get_recorded_nodegroup_uuid | 57 | from provisioningserver.auth import get_recorded_nodegroup_uuid |
6 | 58 | from provisioningserver.rpc.cluster import ( | 58 | from provisioningserver.rpc.cluster import ( |
7 | 59 | EnlistNodesFromMSCM, | 59 | EnlistNodesFromMSCM, |
8 | 60 | EnlistNodesFromUCSM, | ||
9 | 60 | ImportBootImages, | 61 | ImportBootImages, |
10 | 61 | ) | 62 | ) |
11 | 62 | from testresources import FixtureResource | 63 | from testresources import FixtureResource |
12 | @@ -347,7 +348,9 @@ | |||
13 | 347 | password = factory.make_name('password') | 348 | password = factory.make_name('password') |
14 | 348 | self.become_admin() | 349 | self.become_admin() |
15 | 349 | 350 | ||
17 | 350 | mock = self.patch(nodegroup_module, 'enlist_nodes_from_ucsm') | 351 | getClientFor = self.patch(nodegroup_module, 'getClientFor') |
18 | 352 | client = getClientFor.return_value | ||
19 | 353 | nodegroup = factory.make_NodeGroup() | ||
20 | 351 | 354 | ||
21 | 352 | response = self.client.post( | 355 | response = self.client.post( |
22 | 353 | reverse('nodegroup_handler', args=[nodegroup.uuid]), | 356 | reverse('nodegroup_handler', args=[nodegroup.uuid]), |
23 | @@ -362,9 +365,11 @@ | |||
24 | 362 | httplib.OK, response.status_code, | 365 | httplib.OK, response.status_code, |
25 | 363 | explain_unexpected_response(httplib.OK, response)) | 366 | explain_unexpected_response(httplib.OK, response)) |
26 | 364 | 367 | ||
30 | 365 | args = (url, username, password) | 368 | self.expectThat( |
31 | 366 | matcher = MockCalledOnceWith(queue=nodegroup.uuid, args=args) | 369 | client, |
32 | 367 | self.assertThat(mock.apply_async, matcher) | 370 | MockCalledOnceWith( |
33 | 371 | EnlistNodesFromUCSM, url=url, username=username, | ||
34 | 372 | password=password)) | ||
35 | 368 | 373 | ||
36 | 369 | def test_probe_and_enlist_mscm_adds_mscm(self): | 374 | def test_probe_and_enlist_mscm_adds_mscm(self): |
37 | 370 | nodegroup = factory.make_NodeGroup() | 375 | nodegroup = factory.make_NodeGroup() |
38 | 371 | 376 | ||
39 | === modified file 'src/maasserver/models/nodegroup.py' | |||
40 | --- src/maasserver/models/nodegroup.py 2014-09-11 09:58:18 +0000 | |||
41 | +++ src/maasserver/models/nodegroup.py 2014-09-11 12:18:08 +0000 | |||
42 | @@ -42,10 +42,10 @@ | |||
43 | 42 | AddSeaMicro15k, | 42 | AddSeaMicro15k, |
44 | 43 | AddVirsh, | 43 | AddVirsh, |
45 | 44 | EnlistNodesFromMSCM, | 44 | EnlistNodesFromMSCM, |
46 | 45 | EnlistNodesFromUCSM, | ||
47 | 45 | ImportBootImages, | 46 | ImportBootImages, |
48 | 46 | ) | 47 | ) |
49 | 47 | from provisioningserver.rpc.exceptions import NoConnectionsAvailable | 48 | from provisioningserver.rpc.exceptions import NoConnectionsAvailable |
50 | 48 | from provisioningserver.tasks import enlist_nodes_from_ucsm | ||
51 | 49 | 49 | ||
52 | 50 | 50 | ||
53 | 51 | class NodeGroupManager(Manager): | 51 | class NodeGroupManager(Manager): |
54 | @@ -302,9 +302,21 @@ | |||
55 | 302 | :param URL: URL of the Cisco UCS Manager HTTP-XML API. | 302 | :param URL: URL of the Cisco UCS Manager HTTP-XML API. |
56 | 303 | :param username: username for UCS Manager. | 303 | :param username: username for UCS Manager. |
57 | 304 | :param password: password for UCS Manager. | 304 | :param password: password for UCS Manager. |
58 | 305 | |||
59 | 306 | :raises NoConnectionsAvailable: If no connections to the cluster | ||
60 | 307 | are available. | ||
61 | 305 | """ | 308 | """ |
64 | 306 | args = (url, username, password) | 309 | try: |
65 | 307 | enlist_nodes_from_ucsm.apply_async(queue=self.uuid, args=args) | 310 | client = getClientFor(self.uuid, timeout=1) |
66 | 311 | except NoConnectionsAvailable: | ||
67 | 312 | # No connection to the cluster so we can't do anything. We | ||
68 | 313 | # let the caller handle the error, since we don't want to | ||
69 | 314 | # just drop it. | ||
70 | 315 | raise | ||
71 | 316 | else: | ||
72 | 317 | return client( | ||
73 | 318 | EnlistNodesFromUCSM, url=url, username=username, | ||
74 | 319 | password=password) | ||
75 | 308 | 320 | ||
76 | 309 | def enlist_nodes_from_mscm(self, host, username, password): | 321 | def enlist_nodes_from_mscm(self, host, username, password): |
77 | 310 | """ Add the servers from a Moonshot HP iLO Chassis Manager. | 322 | """ Add the servers from a Moonshot HP iLO Chassis Manager. |
78 | 311 | 323 | ||
79 | === modified file 'src/maasserver/models/tests/test_nodegroup.py' | |||
80 | --- src/maasserver/models/tests/test_nodegroup.py 2014-09-11 09:53:46 +0000 | |||
81 | +++ src/maasserver/models/tests/test_nodegroup.py 2014-09-11 12:18:08 +0000 | |||
82 | @@ -50,6 +50,7 @@ | |||
83 | 50 | AddSeaMicro15k, | 50 | AddSeaMicro15k, |
84 | 51 | AddVirsh, | 51 | AddVirsh, |
85 | 52 | EnlistNodesFromMSCM, | 52 | EnlistNodesFromMSCM, |
86 | 53 | EnlistNodesFromUCSM, | ||
87 | 53 | ImportBootImages, | 54 | ImportBootImages, |
88 | 54 | ) | 55 | ) |
89 | 55 | from provisioningserver.rpc.exceptions import NoConnectionsAvailable | 56 | from provisioningserver.rpc.exceptions import NoConnectionsAvailable |
90 | @@ -563,3 +564,52 @@ | |||
91 | 563 | self.assertRaises( | 564 | self.assertRaises( |
92 | 564 | NoConnectionsAvailable, nodegroup.enlist_nodes_from_mscm, | 565 | NoConnectionsAvailable, nodegroup.enlist_nodes_from_mscm, |
93 | 565 | host, username, password) | 566 | host, username, password) |
94 | 567 | |||
95 | 568 | def test_enlist_nodes_from_ucsm_end_to_end(self): | ||
96 | 569 | nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED) | ||
97 | 570 | |||
98 | 571 | self.useFixture(RegionEventLoopFixture("rpc")) | ||
99 | 572 | self.useFixture(RunningEventLoopFixture()) | ||
100 | 573 | fixture = self.useFixture(MockLiveRegionToClusterRPCFixture()) | ||
101 | 574 | protocol = fixture.makeCluster(nodegroup, EnlistNodesFromUCSM) | ||
102 | 575 | protocol.EnlistNodesFromUCSM.return_value = defer.succeed({}) | ||
103 | 576 | |||
104 | 577 | url = factory.make_url() | ||
105 | 578 | username = factory.make_name('user') | ||
106 | 579 | password = factory.make_name('password') | ||
107 | 580 | nodegroup.enlist_nodes_from_ucsm( | ||
108 | 581 | url, username, password).wait(10) | ||
109 | 582 | |||
110 | 583 | self.expectThat( | ||
111 | 584 | protocol.EnlistNodesFromUCSM, | ||
112 | 585 | MockCalledOnceWith( | ||
113 | 586 | ANY, url=url, username=username, password=password)) | ||
114 | 587 | |||
115 | 588 | def test_enlist_nodes_from_ucsm_calls_client_with_resource_endpoint(self): | ||
116 | 589 | getClientFor = self.patch(nodegroup_module, 'getClientFor') | ||
117 | 590 | client = getClientFor.return_value | ||
118 | 591 | nodegroup = factory.make_NodeGroup() | ||
119 | 592 | |||
120 | 593 | url = factory.make_url() | ||
121 | 594 | username = factory.make_name('user') | ||
122 | 595 | password = factory.make_name('password') | ||
123 | 596 | nodegroup.enlist_nodes_from_ucsm( | ||
124 | 597 | url, username, password).wait(10) | ||
125 | 598 | |||
126 | 599 | self.expectThat( | ||
127 | 600 | client, | ||
128 | 601 | MockCalledOnceWith( | ||
129 | 602 | EnlistNodesFromUCSM, url=url, username=username, | ||
130 | 603 | password=password)) | ||
131 | 604 | |||
132 | 605 | def test_enlist_nodes_from_ucsm_raises_if_no_connection_to_cluster(self): | ||
133 | 606 | getClientFor = self.patch(nodegroup_module, 'getClientFor') | ||
134 | 607 | getClientFor.side_effect = NoConnectionsAvailable() | ||
135 | 608 | nodegroup = factory.make_NodeGroup() | ||
136 | 609 | |||
137 | 610 | url = factory.make_url() | ||
138 | 611 | username = factory.make_name('user') | ||
139 | 612 | password = factory.make_name('password') | ||
140 | 613 | self.assertRaises( | ||
141 | 614 | NoConnectionsAvailable, nodegroup.enlist_nodes_from_ucsm, | ||
142 | 615 | url, username, password) | ||
143 | 566 | 616 | ||
144 | === modified file 'src/provisioningserver/rpc/cluster.py' | |||
145 | --- src/provisioningserver/rpc/cluster.py 2014-09-11 11:16:53 +0000 | |||
146 | +++ src/provisioningserver/rpc/cluster.py 2014-09-11 12:18:08 +0000 | |||
147 | @@ -391,3 +391,17 @@ | |||
148 | 391 | ] | 391 | ] |
149 | 392 | response = [] | 392 | response = [] |
150 | 393 | errors = {} | 393 | errors = {} |
151 | 394 | |||
152 | 395 | |||
153 | 396 | class EnlistNodesFromUCSM(amp.Command): | ||
154 | 397 | """Probe for and enlist ucsm machines attached to the cluster. | ||
155 | 398 | |||
156 | 399 | :since: 1.7 | ||
157 | 400 | """ | ||
158 | 401 | arguments = [ | ||
159 | 402 | (b"url", amp.Unicode()), | ||
160 | 403 | (b"username", amp.Unicode()), | ||
161 | 404 | (b"password", amp.Unicode()), | ||
162 | 405 | ] | ||
163 | 406 | response = [] | ||
164 | 407 | errors = {} | ||
165 | 394 | 408 | ||
166 | === modified file 'src/provisioningserver/rpc/clusterservice.py' | |||
167 | --- src/provisioningserver/rpc/clusterservice.py 2014-09-11 09:58:18 +0000 | |||
168 | +++ src/provisioningserver/rpc/clusterservice.py 2014-09-11 12:18:08 +0000 | |||
169 | @@ -33,6 +33,7 @@ | |||
170 | 33 | from provisioningserver.drivers.hardware.seamicro import ( | 33 | from provisioningserver.drivers.hardware.seamicro import ( |
171 | 34 | probe_seamicro15k_and_enlist, | 34 | probe_seamicro15k_and_enlist, |
172 | 35 | ) | 35 | ) |
173 | 36 | from provisioningserver.drivers.hardware.ucsm import probe_and_enlist_ucsm | ||
174 | 36 | from provisioningserver.drivers.hardware.virsh import probe_virsh_and_enlist | 37 | from provisioningserver.drivers.hardware.virsh import probe_virsh_and_enlist |
175 | 37 | from provisioningserver.logger.log import get_maas_logger | 38 | from provisioningserver.logger.log import get_maas_logger |
176 | 38 | from provisioningserver.rpc import ( | 39 | from provisioningserver.rpc import ( |
177 | @@ -277,6 +278,16 @@ | |||
178 | 277 | probe_and_enlist_mscm(host, username, password) | 278 | probe_and_enlist_mscm(host, username, password) |
179 | 278 | return {} | 279 | return {} |
180 | 279 | 280 | ||
181 | 281 | @cluster.EnlistNodesFromUCSM.responder | ||
182 | 282 | def enlist_nodes_from_ucsm(self, url, username, password): | ||
183 | 283 | """enlist_nodes_from_ucsm() | ||
184 | 284 | |||
185 | 285 | Implemention of | ||
186 | 286 | :py:class:`~provisioningserver.rpc.cluster.EnlistNodesFromUCSM`. | ||
187 | 287 | """ | ||
188 | 288 | probe_and_enlist_ucsm(url, username, password) | ||
189 | 289 | return {} | ||
190 | 290 | |||
191 | 280 | 291 | ||
192 | 281 | @implementer(IConnection) | 292 | @implementer(IConnection) |
193 | 282 | class ClusterClient(Cluster): | 293 | class ClusterClient(Cluster): |
194 | 283 | 294 | ||
195 | === modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py' | |||
196 | --- src/provisioningserver/rpc/tests/test_clusterservice.py 2014-09-11 09:53:18 +0000 | |||
197 | +++ src/provisioningserver/rpc/tests/test_clusterservice.py 2014-09-11 12:18:08 +0000 | |||
198 | @@ -1283,3 +1283,30 @@ | |||
199 | 1283 | self.assertThat( | 1283 | self.assertThat( |
200 | 1284 | probe_and_enlist_mscm, MockCalledOnceWith( | 1284 | probe_and_enlist_mscm, MockCalledOnceWith( |
201 | 1285 | host, username, password)) | 1285 | host, username, password)) |
202 | 1286 | |||
203 | 1287 | |||
204 | 1288 | class TestClusterProtocol_EnlistNodesFromUCSM(MAASTestCase): | ||
205 | 1289 | |||
206 | 1290 | def test__is_registered(self): | ||
207 | 1291 | protocol = Cluster() | ||
208 | 1292 | responder = protocol.locateResponder( | ||
209 | 1293 | cluster.EnlistNodesFromUCSM.commandName) | ||
210 | 1294 | self.assertIsNot(responder, None) | ||
211 | 1295 | |||
212 | 1296 | def test__calls_probe_and_enlist_ucsm(self): | ||
213 | 1297 | probe_and_enlist_ucsm = self.patch_autospec( | ||
214 | 1298 | clusterservice, 'probe_and_enlist_ucsm') | ||
215 | 1299 | |||
216 | 1300 | url = factory.make_url() | ||
217 | 1301 | username = factory.make_name('user') | ||
218 | 1302 | password = factory.make_name('password') | ||
219 | 1303 | |||
220 | 1304 | call_responder(Cluster(), cluster.EnlistNodesFromUCSM, { | ||
221 | 1305 | 'url': url, | ||
222 | 1306 | 'username': username, | ||
223 | 1307 | 'password': password, | ||
224 | 1308 | }) | ||
225 | 1309 | |||
226 | 1310 | self.assertThat( | ||
227 | 1311 | probe_and_enlist_ucsm, MockCalledOnceWith( | ||
228 | 1312 | url, username, password)) | ||
229 | 1286 | 1313 | ||
230 | === modified file 'src/provisioningserver/tasks.py' | |||
231 | --- src/provisioningserver/tasks.py 2014-09-11 09:54:13 +0000 | |||
232 | +++ src/provisioningserver/tasks.py 2014-09-11 12:18:08 +0000 | |||
233 | @@ -42,7 +42,6 @@ | |||
234 | 42 | set_up_options_conf, | 42 | set_up_options_conf, |
235 | 43 | setup_rndc, | 43 | setup_rndc, |
236 | 44 | ) | 44 | ) |
237 | 45 | from provisioningserver.drivers.hardware.ucsm import probe_and_enlist_ucsm | ||
238 | 46 | from provisioningserver.logger import get_maas_logger | 45 | from provisioningserver.logger import get_maas_logger |
239 | 47 | 46 | ||
240 | 48 | # For each item passed to refresh_secrets, a refresh function to give it to. | 47 | # For each item passed to refresh_secrets, a refresh function to give it to. |
241 | @@ -296,15 +295,3 @@ | |||
242 | 296 | exc=exc, countdown=UPDATE_NODE_TAGS_RETRY_DELAY) | 295 | exc=exc, countdown=UPDATE_NODE_TAGS_RETRY_DELAY) |
243 | 297 | else: | 296 | else: |
244 | 298 | raise | 297 | raise |
245 | 299 | |||
246 | 300 | |||
247 | 301 | # ===================================================================== | ||
248 | 302 | # Custom hardware tasks | ||
249 | 303 | # ===================================================================== | ||
250 | 304 | |||
251 | 305 | @task | ||
252 | 306 | @log_task_events() | ||
253 | 307 | @log_exception_text | ||
254 | 308 | def enlist_nodes_from_ucsm(url, username, password): | ||
255 | 309 | """ See `maasserver.api.NodeGroupHandler.enlist_nodes_from_ucsm`. """ | ||
256 | 310 | probe_and_enlist_ucsm(url, username, password) | ||
257 | 311 | 298 | ||
258 | === modified file 'src/provisioningserver/tests/test_tasks.py' | |||
259 | --- src/provisioningserver/tests/test_tasks.py 2014-09-11 10:56:06 +0000 | |||
260 | +++ src/provisioningserver/tests/test_tasks.py 2014-09-11 12:18:08 +0000 | |||
261 | @@ -31,7 +31,6 @@ | |||
262 | 31 | FakeMethod, | 31 | FakeMethod, |
263 | 32 | MultiFakeMethod, | 32 | MultiFakeMethod, |
264 | 33 | ) | 33 | ) |
265 | 34 | from maastesting.matchers import MockCalledOnceWith | ||
266 | 35 | from mock import Mock | 34 | from mock import Mock |
267 | 36 | from netaddr import IPNetwork | 35 | from netaddr import IPNetwork |
268 | 37 | from provisioningserver import ( | 36 | from provisioningserver import ( |
269 | @@ -55,7 +54,6 @@ | |||
270 | 55 | ) | 54 | ) |
271 | 56 | from provisioningserver.tags import MissingCredentials | 55 | from provisioningserver.tags import MissingCredentials |
272 | 57 | from provisioningserver.tasks import ( | 56 | from provisioningserver.tasks import ( |
273 | 58 | enlist_nodes_from_ucsm, | ||
274 | 59 | refresh_secrets, | 57 | refresh_secrets, |
275 | 60 | report_boot_images, | 58 | report_boot_images, |
276 | 61 | rndc_command, | 59 | rndc_command, |
277 | @@ -391,14 +389,3 @@ | |||
278 | 391 | self.assertRaises( | 389 | self.assertRaises( |
279 | 392 | MissingCredentials, update_node_tags.delay, tag, | 390 | MissingCredentials, update_node_tags.delay, tag, |
280 | 393 | '//node', tag_nsmap=None, retry=True) | 391 | '//node', tag_nsmap=None, retry=True) |
281 | 394 | |||
282 | 395 | |||
283 | 396 | class TestAddUCSM(PservTestCase): | ||
284 | 397 | |||
285 | 398 | def test_enlist_nodes_from_ucsm(self): | ||
286 | 399 | url = 'url' | ||
287 | 400 | username = 'username' | ||
288 | 401 | password = 'password' | ||
289 | 402 | mock = self.patch(tasks, 'probe_and_enlist_ucsm') | ||
290 | 403 | enlist_nodes_from_ucsm(url, username, password) | ||
291 | 404 | self.assertThat(mock, MockCalledOnceWith(url, username, password)) |
Looks good. (These branches are a bit boring aren't they?)