Merge lp:~mpontillo/maas/bug-1451852-remove-legacy-esxi-probe-and-enlist into lp:~maas-committers/maas/trunk
- bug-1451852-remove-legacy-esxi-probe-and-enlist
- Merge into trunk
Proposed by
Mike Pontillo
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Mike Pontillo | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 3895 | ||||
Proposed branch: | lp:~mpontillo/maas/bug-1451852-remove-legacy-esxi-probe-and-enlist | ||||
Merge into: | lp:~maas-committers/maas/trunk | ||||
Prerequisite: | lp:~mpontillo/maas/add-pycharm-project-files | ||||
Diff against target: |
948 lines (+6/-767) 13 files modified
etc/maas/templates/power/esxi.template (+0/-65) src/maasserver/api/nodegroups.py (+1/-26) src/maasserver/api/tests/test_nodegroup.py (+0/-40) src/maasserver/models/nodegroup.py (+0/-27) src/maasserver/models/tests/test_nodegroup.py (+0/-54) src/maasserver/static/js/angular/controllers/add_hardware.js (+1/-39) src/maastesting/tests/test_scss.py (+1/-1) src/provisioningserver/drivers/hardware/esxi.py (+0/-116) src/provisioningserver/drivers/hardware/tests/test_esxi.py (+0/-315) src/provisioningserver/power_schema.py (+1/-11) src/provisioningserver/rpc/clusterservice.py (+1/-15) src/provisioningserver/rpc/power.py (+0/-1) src/provisioningserver/rpc/tests/test_clusterservice.py (+1/-57) |
||||
To merge this branch: | bzr merge lp:~mpontillo/maas/bug-1451852-remove-legacy-esxi-probe-and-enlist | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andres Rodriguez (community) | Approve | ||
Review via email: mp+259075@code.launchpad.net |
Commit message
Remove legacy (never shipped) VMware probe-and-enlist option.
Description of the change
Remove redundant VMware probe-and-enlist option.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed file 'etc/maas/templates/power/esxi.template' |
2 | --- etc/maas/templates/power/esxi.template 2015-02-19 17:31:32 +0000 |
3 | +++ etc/maas/templates/power/esxi.template 1970-01-01 00:00:00 +0000 |
4 | @@ -1,65 +0,0 @@ |
5 | -# -*- mode: shell-script -*- |
6 | -# |
7 | -# Control virtual system's "power" through virsh for ESXi |
8 | -# |
9 | - |
10 | -# Exit with failure message. |
11 | -# Parameters: exit code, and error message. |
12 | -fail() { |
13 | - echo "$2" >&2 |
14 | - exit $1 |
15 | -} |
16 | - |
17 | -issue_virsh_command() { |
18 | -python - << END |
19 | -import sys |
20 | -from provisioningserver.drivers.hardware.esxi import power_control_esxi |
21 | -try: |
22 | - power_control_esxi( |
23 | - {{escape_py_literal(power_address).decode("ascii") | safe}}, |
24 | - {{escape_py_literal(power_id).decode("ascii") | safe}}, |
25 | - {{escape_py_literal(power_change).decode("ascii") | safe}}, |
26 | - {{escape_py_literal(power_user).decode("ascii") | safe}}, |
27 | - {{escape_py_literal(power_pass).decode("ascii") | safe}}, |
28 | - ) |
29 | -except Exception as e: |
30 | - # This gets in the node event log: print the exception's message |
31 | - # and not the stacktrace. |
32 | - print(unicode(e)) |
33 | - sys.exit(1) |
34 | -END |
35 | -} |
36 | - |
37 | -query_state() { |
38 | -python - << END |
39 | -import sys |
40 | -from provisioningserver.drivers.hardware.esxi import power_state_esxi |
41 | -try: |
42 | - print(power_state_esxi( |
43 | - {{escape_py_literal(power_address).decode("ascii") | safe}}, |
44 | - {{escape_py_literal(power_id).decode("ascii") | safe}}, |
45 | - {{escape_py_literal(power_user).decode("ascii") | safe}}, |
46 | - {{escape_py_literal(power_pass).decode("ascii") | safe}}, |
47 | - )) |
48 | -except Exception as e: |
49 | - # This gets in the node event log: print the exception's message |
50 | - # and not the stacktrace. |
51 | - print(unicode(e)) |
52 | - sys.exit(1) |
53 | -END |
54 | -} |
55 | - |
56 | -main() { |
57 | - case $1 in |
58 | - 'on'|'off') |
59 | - issue_virsh_command |
60 | - ;; |
61 | - 'query') |
62 | - query_state |
63 | - ;; |
64 | - *) |
65 | - fail 2 "Unknown power command: '$1'" |
66 | - esac |
67 | -} |
68 | - |
69 | -main "{{power_change}}" |
70 | |
71 | === modified file 'src/maasserver/api/nodegroups.py' |
72 | --- src/maasserver/api/nodegroups.py 2015-05-07 18:14:38 +0000 |
73 | +++ src/maasserver/api/nodegroups.py 2015-05-14 16:27:22 +0000 |
74 | @@ -372,11 +372,10 @@ |
75 | """Add special hardware types. |
76 | |
77 | :param model: The type of hardware. 'seamicro15k', 'virsh', 'vsphere', |
78 | - 'esxi', 'powerkvm', 'mscm', 'msftocs' and 'ucsm' are supported. |
79 | + 'powerkvm', 'mscm', 'msftocs' and 'ucsm' are supported. |
80 | |
81 | seamicro15k is the model for the Seamicro 1500 Chassis. |
82 | virsh is the model for Virtual Machines managed by Virsh. |
83 | - esxi is the model for Virtual Machines managed by ESXi. |
84 | powerkvm is the model for Virtual Machines on Power KVM, |
85 | managed by Virsh. |
86 | mscm is the model for the Moonshot Chassis Manager. |
87 | @@ -419,20 +418,6 @@ |
88 | :param prefix_filter: Filter nodes with supplied prefix. |
89 | :type prefix_filter: unicode |
90 | |
91 | - The following are required if you are probing esxi: |
92 | - |
93 | - :param address: The IP address of the esxi machine. |
94 | - :type address: unicode |
95 | - :param username: esxi username. |
96 | - :type username: unicode |
97 | - :param password: esxi password. |
98 | - :type password: unicode |
99 | - |
100 | - The following are optional if you are probing esxi: |
101 | - |
102 | - :param prefix_filter: Filter nodes with supplied prefix. |
103 | - :type prefix_filter: unicode |
104 | - |
105 | The following are required if you are probing mscm: |
106 | |
107 | :param host: IP Address for the Moonshot Chassis Manager. |
108 | @@ -514,16 +499,6 @@ |
109 | user, host, username, password, port=port, |
110 | protocol=protocol, prefix_filter=prefix_filter, |
111 | accept_all=accept_all) |
112 | - elif model == 'esxi': |
113 | - poweraddr = get_mandatory_param(request.data, 'address') |
114 | - poweruser = get_mandatory_param(request.data, 'username') |
115 | - password = get_mandatory_param(request.data, 'password') |
116 | - prefix_filter = get_optional_param( |
117 | - request.data, 'prefix_filter', default=None) |
118 | - |
119 | - nodegroup.add_esxi( |
120 | - user, poweruser, poweraddr, password=password, |
121 | - prefix_filter=prefix_filter, accept_all=accept_all) |
122 | else: |
123 | return HttpResponse(status=httplib.BAD_REQUEST) |
124 | |
125 | |
126 | === modified file 'src/maasserver/api/tests/test_nodegroup.py' |
127 | --- src/maasserver/api/tests/test_nodegroup.py 2015-05-07 18:14:38 +0000 |
128 | +++ src/maasserver/api/tests/test_nodegroup.py 2015-05-14 16:27:22 +0000 |
129 | @@ -57,7 +57,6 @@ |
130 | ) |
131 | from mock import Mock |
132 | from provisioningserver.rpc.cluster import ( |
133 | - AddESXi, |
134 | AddSeaMicro15k, |
135 | AddVirsh, |
136 | AddVsphere, |
137 | @@ -447,45 +446,6 @@ |
138 | port=None, prefix_filter=prefix_filter, |
139 | accept_all=True)) |
140 | |
141 | - def test_probe_and_enlist_hardware_adds_esxi(self): |
142 | - self.become_admin() |
143 | - user = self.logged_in_user |
144 | - nodegroup = factory.make_NodeGroup() |
145 | - model = 'esxi' |
146 | - poweraddr = factory.make_ipv4_address() |
147 | - password = factory.make_name('password') |
148 | - poweruser = factory.make_name('poweruser') |
149 | - prefix_filter = factory.make_name('filter') |
150 | - accept_all = True |
151 | - |
152 | - getClientFor = self.patch(nodegroup_module, 'getClientFor') |
153 | - client = getClientFor.return_value |
154 | - nodegroup = factory.make_NodeGroup() |
155 | - |
156 | - response = self.client.post( |
157 | - reverse('nodegroup_handler', args=[nodegroup.uuid]), |
158 | - { |
159 | - 'op': 'probe_and_enlist_hardware', |
160 | - 'model': model, |
161 | - 'user': user.username, |
162 | - 'address': poweraddr, |
163 | - 'username': poweruser, |
164 | - 'password': password, |
165 | - 'prefix_filter': prefix_filter, |
166 | - 'accept_all': accept_all, |
167 | - }) |
168 | - |
169 | - self.assertEqual( |
170 | - httplib.OK, response.status_code, |
171 | - explain_unexpected_response(httplib.OK, response)) |
172 | - |
173 | - self.expectThat( |
174 | - client, |
175 | - MockCalledOnceWith( |
176 | - AddESXi, user=user.username, poweruser=poweruser, |
177 | - poweraddr=poweraddr, password=password, |
178 | - prefix_filter=prefix_filter, accept_all=True)) |
179 | - |
180 | def test_probe_and_enlist_hardware_adds_msftocs(self): |
181 | self.become_admin() |
182 | user = self.logged_in_user |
183 | |
184 | === modified file 'src/maasserver/models/nodegroup.py' |
185 | --- src/maasserver/models/nodegroup.py 2015-05-07 18:14:38 +0000 |
186 | +++ src/maasserver/models/nodegroup.py 2015-05-14 16:27:22 +0000 |
187 | @@ -50,7 +50,6 @@ |
188 | ) |
189 | from provisioningserver.dhcp.omshell import generate_omapi_key |
190 | from provisioningserver.rpc.cluster import ( |
191 | - AddESXi, |
192 | AddSeaMicro15k, |
193 | AddVirsh, |
194 | AddVsphere, |
195 | @@ -437,32 +436,6 @@ |
196 | password=password, protocol=protocol, port=port, |
197 | prefix_filter=prefix_filter, accept_all=accept_all) |
198 | |
199 | - def add_esxi(self, user, poweruser, poweraddr, password, |
200 | - prefix_filter=None, accept_all=False): |
201 | - """ Add all of the virtual machines inside a virsh controller. |
202 | - |
203 | - :param user: user for the ESXi host. |
204 | - :param poweraddr: IP address of esxi host string. |
205 | - :param password: password. |
206 | - :param prefix_filter: import based on prefix. |
207 | - :param accept_all: commission enlisted nodes. |
208 | - |
209 | - :raises NoConnectionsAvailable: If no connections to the cluster |
210 | - are available. |
211 | - """ |
212 | - try: |
213 | - client = getClientFor(self.uuid, timeout=1) |
214 | - except NoConnectionsAvailable: |
215 | - # No connection to the cluster so we can't do anything. We |
216 | - # let the caller handle the error, since we don't want to |
217 | - # just drop it. |
218 | - raise |
219 | - else: |
220 | - return client( |
221 | - AddESXi, user=user, poweruser=poweruser, poweraddr=poweraddr, |
222 | - password=password, prefix_filter=prefix_filter, |
223 | - accept_all=accept_all) |
224 | - |
225 | def enlist_nodes_from_ucsm(self, user, url, username, |
226 | password, accept_all=False): |
227 | """ Add the servers from a Cicso UCS Manager. |
228 | |
229 | === modified file 'src/maasserver/models/tests/test_nodegroup.py' |
230 | --- src/maasserver/models/tests/test_nodegroup.py 2015-05-07 18:14:38 +0000 |
231 | +++ src/maasserver/models/tests/test_nodegroup.py 2015-05-14 16:27:22 +0000 |
232 | @@ -54,7 +54,6 @@ |
233 | ) |
234 | from provisioningserver.dhcp.omshell import generate_omapi_key |
235 | from provisioningserver.rpc.cluster import ( |
236 | - AddESXi, |
237 | AddSeaMicro15k, |
238 | AddVirsh, |
239 | AddVsphere, |
240 | @@ -683,59 +682,6 @@ |
241 | username, password, protocol=None, port=None, |
242 | prefix_filter=None, accept_all=True) |
243 | |
244 | - def test_add_esxi_end_to_end(self): |
245 | - nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED) |
246 | - |
247 | - self.useFixture(RegionEventLoopFixture("rpc")) |
248 | - self.useFixture(RunningEventLoopFixture()) |
249 | - fixture = self.useFixture(MockLiveRegionToClusterRPCFixture()) |
250 | - protocol = fixture.makeCluster(nodegroup, AddESXi) |
251 | - protocol.AddESXi.return_value = defer.succeed( |
252 | - {'system_id': factory.make_name('system-id')}) |
253 | - |
254 | - user = factory.make_name('user') |
255 | - poweruser = factory.make_name('poweruser') |
256 | - poweraddr = factory.make_name('poweraddr') |
257 | - password = factory.make_name('password') |
258 | - nodegroup.add_esxi( |
259 | - user, poweruser, poweraddr, password, None, True).wait(10) |
260 | - |
261 | - self.expectThat( |
262 | - protocol.AddESXi, |
263 | - MockCalledOnceWith( |
264 | - ANY, user=user, poweruser=poweruser, poweraddr=poweraddr, |
265 | - password=password, prefix_filter=None, accept_all=True)) |
266 | - |
267 | - def test_add_esxi_calls_client_with_resource_endpoint(self): |
268 | - getClientFor = self.patch(nodegroup_module, 'getClientFor') |
269 | - client = getClientFor.return_value |
270 | - nodegroup = factory.make_NodeGroup() |
271 | - |
272 | - user = factory.make_name('user') |
273 | - poweruser = factory.make_name('poweruser') |
274 | - poweraddr = factory.make_name('poweraddr') |
275 | - password = factory.make_name('password') |
276 | - nodegroup.add_esxi(user, poweruser, poweraddr, password, None, True) |
277 | - |
278 | - self.expectThat( |
279 | - client, |
280 | - MockCalledOnceWith( |
281 | - AddESXi, user=user, poweruser=poweruser, poweraddr=poweraddr, |
282 | - password=password, prefix_filter=None, accept_all=True)) |
283 | - |
284 | - def test_add_esxi_raises_if_no_connection_to_cluster(self): |
285 | - getClientFor = self.patch(nodegroup_module, 'getClientFor') |
286 | - getClientFor.side_effect = NoConnectionsAvailable() |
287 | - nodegroup = factory.make_NodeGroup() |
288 | - |
289 | - user = factory.make_name('user') |
290 | - poweraddr = factory.make_name('poweraddr') |
291 | - password = factory.make_name('password') |
292 | - |
293 | - self.assertRaises( |
294 | - NoConnectionsAvailable, nodegroup.add_esxi, user, |
295 | - poweraddr, password, True) |
296 | - |
297 | def test_add_seamicro15k_end_to_end(self): |
298 | nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED) |
299 | |
300 | |
301 | === modified file 'src/maasserver/static/js/angular/controllers/add_hardware.js' |
302 | --- src/maasserver/static/js/angular/controllers/add_hardware.js 2015-05-07 15:00:36 +0000 |
303 | +++ src/maasserver/static/js/angular/controllers/add_hardware.js 2015-05-14 16:27:22 +0000 |
304 | @@ -172,46 +172,8 @@ |
305 | fields: virshFields |
306 | }, |
307 | { |
308 | - name: 'esxi', |
309 | - description: 'VMWare ESXi (virsh)', |
310 | - fields: [ |
311 | - { |
312 | - name: 'address', |
313 | - label: 'Address', |
314 | - field_type: 'string', |
315 | - "default": '', |
316 | - choices: [], |
317 | - required: true |
318 | - }, |
319 | - { |
320 | - name: 'username', |
321 | - label: 'Username', |
322 | - field_type: 'string', |
323 | - "default": '', |
324 | - choices: [], |
325 | - required: true |
326 | - }, |
327 | - { |
328 | - name: 'password', |
329 | - label: 'Password', |
330 | - field_type: 'string', |
331 | - "default": '', |
332 | - choices: [], |
333 | - required: true |
334 | - }, |
335 | - { |
336 | - name: 'prefix_filter', |
337 | - label: 'Prefix filter', |
338 | - field_type: 'string', |
339 | - "default": '', |
340 | - choices: [], |
341 | - required: false |
342 | - } |
343 | - ] |
344 | - }, |
345 | - { |
346 | name: 'vsphere', |
347 | - description: 'VMWare (python-vmomi)', |
348 | + description: 'VMWare', |
349 | fields: [ |
350 | { |
351 | name: 'host', |
352 | |
353 | === modified file 'src/maastesting/tests/test_scss.py' |
354 | --- src/maastesting/tests/test_scss.py 2015-05-12 12:38:12 +0000 |
355 | +++ src/maastesting/tests/test_scss.py 2015-05-14 16:27:22 +0000 |
356 | @@ -70,4 +70,4 @@ |
357 | tmp_css = self.read_content( |
358 | os.path.join(output_dir, "maas-styles.css")) |
359 | if in_tree_css != tmp_css: |
360 | - self.fail("maas-styles.css is out-of-date.") |
361 | + self.fail("maas-styles.css is out-of-date. (run 'make styles')") |
362 | |
363 | === removed file 'src/provisioningserver/drivers/hardware/esxi.py' |
364 | --- src/provisioningserver/drivers/hardware/esxi.py 2015-05-07 18:14:38 +0000 |
365 | +++ src/provisioningserver/drivers/hardware/esxi.py 1970-01-01 00:00:00 +0000 |
366 | @@ -1,116 +0,0 @@ |
367 | -# Copyright 2015 Canonical Ltd. This software is licensed under the |
368 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
369 | - |
370 | -from __future__ import ( |
371 | - absolute_import, |
372 | - print_function, |
373 | - unicode_literals, |
374 | - ) |
375 | - |
376 | -str = None |
377 | - |
378 | -__metaclass__ = type |
379 | -__all__ = [ |
380 | - 'probe_esxi_and_enlist', |
381 | - ] |
382 | - |
383 | -from provisioningserver.drivers.hardware.virsh import ( |
384 | - VirshSSH, |
385 | - VirshVMState, |
386 | - VM_STATE_TO_POWER_STATE, |
387 | -) |
388 | -from provisioningserver.utils import ( |
389 | - commission_node, |
390 | - create_node, |
391 | -) |
392 | -from provisioningserver.utils.twisted import synchronous |
393 | - |
394 | - |
395 | -class ESXiError(Exception): |
396 | - """Failure communicating to ESXi. """ |
397 | - |
398 | - |
399 | -def compose_esxi_url(poweruser, poweraddr): |
400 | - return "esx://%s@%s/?no_verify=1" % (poweruser, poweraddr) |
401 | - |
402 | - |
403 | -@synchronous |
404 | -def probe_esxi_and_enlist( |
405 | - user, poweruser, poweraddr, password, |
406 | - prefix_filter=None, accept_all=False): |
407 | - """Extracts all of the virtual machines from virsh and enlists them |
408 | - into MAAS. |
409 | - |
410 | - :param user: user for the nodes. |
411 | - :param poweraddr: IP Address of ESXi host. |
412 | - :param password: password connection string. |
413 | - :param prefix_filter: only enlist nodes that have the prefix. |
414 | - :param accept_all: if True, commission enlisted nodes. |
415 | - """ |
416 | - conn = VirshSSH(dom_prefix=prefix_filter) |
417 | - virsh_poweraddr = compose_esxi_url(poweruser, poweraddr) |
418 | - if not conn.login(virsh_poweraddr, password): |
419 | - raise ESXiError('Failed to login to virsh console.') |
420 | - |
421 | - for machine in conn.list(): |
422 | - arch = conn.get_arch(machine) |
423 | - state = conn.get_state(machine) |
424 | - macs = conn.get_mac_addresses(machine) |
425 | - |
426 | - # Force the machine off, as MAAS will control the machine |
427 | - # and it needs to be in a known state of off. |
428 | - if state == VirshVMState.ON: |
429 | - conn.poweroff(machine) |
430 | - |
431 | - params = { |
432 | - 'power_address': poweraddr, |
433 | - 'power_user': poweruser, |
434 | - 'power_id': machine, |
435 | - 'power_pass': password, |
436 | - } |
437 | - system_id = create_node(macs, arch, 'esxi', params).wait(30) |
438 | - |
439 | - if accept_all: |
440 | - commission_node(system_id, user).wait(30) |
441 | - |
442 | - conn.logout() |
443 | - |
444 | - |
445 | -def power_control_esxi(poweraddr, machine, power_change, poweruser, password): |
446 | - """Powers controls a virtual machine using virsh.""" |
447 | - |
448 | - conn = VirshSSH() |
449 | - virsh_poweraddr = compose_esxi_url(poweruser, poweraddr) |
450 | - if not conn.login(virsh_poweraddr, password): |
451 | - raise ESXiError('Failed to login to virsh console.') |
452 | - |
453 | - state = conn.get_state(machine) |
454 | - if state is None: |
455 | - raise ESXiError('Failed to get virtual domain: %s' % machine) |
456 | - |
457 | - if state == VirshVMState.OFF: |
458 | - if power_change == 'on': |
459 | - if not conn.poweron(machine): |
460 | - raise ESXiError('Failed to power on domain: %s' % machine) |
461 | - elif state == VirshVMState.ON: |
462 | - if power_change == 'off': |
463 | - if not conn.poweroff(machine): |
464 | - raise ESXiError('Failed to power off domain: %s' % machine) |
465 | - |
466 | - |
467 | -def power_state_esxi(poweraddr, machine, poweruser, password): |
468 | - """Return the power state for the virtual machine using virsh.""" |
469 | - |
470 | - conn = VirshSSH() |
471 | - virsh_poweraddr = compose_esxi_url(poweruser, poweraddr) |
472 | - if not conn.login(virsh_poweraddr, password): |
473 | - raise ESXiError('Failed to login to virsh console.') |
474 | - |
475 | - state = conn.get_state(machine) |
476 | - if state is None: |
477 | - raise ESXiError('Failed to get domain: %s' % machine) |
478 | - |
479 | - try: |
480 | - return VM_STATE_TO_POWER_STATE[state] |
481 | - except KeyError: |
482 | - raise ESXiError('Unknown power state: %s' % state) |
483 | |
484 | === removed file 'src/provisioningserver/drivers/hardware/tests/test_esxi.py' |
485 | --- src/provisioningserver/drivers/hardware/tests/test_esxi.py 2015-05-07 18:14:38 +0000 |
486 | +++ src/provisioningserver/drivers/hardware/tests/test_esxi.py 1970-01-01 00:00:00 +0000 |
487 | @@ -1,315 +0,0 @@ |
488 | -# Copyright 2015 Canonical Ltd. This software is licensed under the |
489 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
490 | - |
491 | -"""Tests for `provisioningserver.drivers.hardware.esxi`. |
492 | -""" |
493 | - |
494 | -from __future__ import ( |
495 | - absolute_import, |
496 | - print_function, |
497 | - unicode_literals, |
498 | - ) |
499 | - |
500 | -str = None |
501 | - |
502 | -__metaclass__ = type |
503 | -__all__ = [] |
504 | - |
505 | -from textwrap import dedent |
506 | - |
507 | -from maastesting.factory import factory |
508 | -from maastesting.matchers import ( |
509 | - MockCalledOnceWith, |
510 | - MockCalledWith, |
511 | - MockCallsMatch, |
512 | -) |
513 | -from maastesting.testcase import ( |
514 | - MAASTestCase, |
515 | - MAASTwistedRunTest, |
516 | -) |
517 | -from mock import call |
518 | -from provisioningserver.drivers.hardware import esxi as virsh |
519 | -from provisioningserver.utils.twisted import asynchronous |
520 | -from testtools.testcase import ExpectedException |
521 | -from twisted.internet.defer import inlineCallbacks |
522 | -from twisted.internet.threads import deferToThread |
523 | - |
524 | - |
525 | -SAMPLE_IFLIST = dedent(""" |
526 | - Interface Type Source Model MAC |
527 | - ------------------------------------------------------- |
528 | - - bridge br0 e1000 %s |
529 | - - bridge br1 e1000 %s |
530 | - """) |
531 | - |
532 | -SAMPLE_DUMPXML = dedent(""" |
533 | - <domain type='kvm'> |
534 | - <name>test</name> |
535 | - <memory unit='KiB'>4096576</memory> |
536 | - <currentMemory unit='KiB'>4096576</currentMemory> |
537 | - <vcpu placement='static'>1</vcpu> |
538 | - <os> |
539 | - <type arch='%s'>hvm</type> |
540 | - <boot dev='network'/> |
541 | - </os> |
542 | - </domain> |
543 | - """) |
544 | - |
545 | - |
546 | -class TestESXi(MAASTestCase): |
547 | - """Tests for `probe_esxi_and_enlist`.""" |
548 | - |
549 | - run_tests_with = MAASTwistedRunTest.make_factory(timeout=5) |
550 | - |
551 | - @inlineCallbacks |
552 | - def test_probe_and_enlist(self): |
553 | - # Patch VirshSSH list so that some machines are returned |
554 | - # with some fake architectures. |
555 | - user = factory.make_name('user') |
556 | - system_id = factory.make_name('system_id') |
557 | - machines = [factory.make_name('machine') for _ in range(3)] |
558 | - self.patch(virsh.VirshSSH, 'list').return_value = machines |
559 | - fake_arch = factory.make_name('arch') |
560 | - mock_arch = self.patch(virsh.VirshSSH, 'get_arch') |
561 | - mock_arch.return_value = fake_arch |
562 | - |
563 | - # Patch get_state so that one of the machines is on, so we |
564 | - # can check that it will be forced off. |
565 | - fake_states = [ |
566 | - virsh.VirshVMState.ON, |
567 | - virsh.VirshVMState.OFF, |
568 | - virsh.VirshVMState.OFF |
569 | - ] |
570 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
571 | - mock_state.side_effect = fake_states |
572 | - |
573 | - # Setup the power parameters that we should expect to be |
574 | - # the output of the probe_and_enlist |
575 | - fake_password = factory.make_string() |
576 | - poweruser = factory.make_name('poweruser') |
577 | - poweraddr = factory.make_name('poweraddr') |
578 | - esx_poweraddr = "esx://%s@%s/?no_verify=1" % (user, poweraddr) |
579 | - called_params = [] |
580 | - fake_macs = [] |
581 | - for machine in machines: |
582 | - macs = [factory.make_mac_address() for _ in range(3)] |
583 | - fake_macs.append(macs) |
584 | - called_params.append({ |
585 | - 'power_address': poweraddr, |
586 | - 'power_id': machine, |
587 | - 'power_pass': fake_password, |
588 | - 'power_user': poweruser, |
589 | - }) |
590 | - |
591 | - # Patch the get_mac_addresses so we get a known list of |
592 | - # mac addresses for each machine. |
593 | - mock_macs = self.patch(virsh.VirshSSH, 'get_mac_addresses') |
594 | - mock_macs.side_effect = fake_macs |
595 | - |
596 | - # Patch the poweroff and create as we really don't want these |
597 | - # actions to occur, but want to also check that they are called. |
598 | - mock_poweroff = self.patch(virsh.VirshSSH, 'poweroff') |
599 | - mock_create_node = self.patch(virsh, 'create_node') |
600 | - mock_create_node.side_effect = asynchronous(lambda *args: system_id) |
601 | - mock_commission_node = self.patch(virsh, 'commission_node') |
602 | - |
603 | - # Patch login and logout so that we don't really contact |
604 | - # a server at the fake poweraddr |
605 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
606 | - mock_login.return_value = True |
607 | - mock_logout = self.patch(virsh.VirshSSH, 'logout') |
608 | - |
609 | - # Perform the probe and enlist |
610 | - yield deferToThread( |
611 | - virsh.probe_esxi_and_enlist, user, poweruser, poweraddr, |
612 | - password=fake_password, accept_all=True) |
613 | - |
614 | - # Check that login was called with the provided poweraddr and |
615 | - # password. |
616 | - self.expectThat( |
617 | - mock_login, MockCalledOnceWith(esx_poweraddr, fake_password)) |
618 | - |
619 | - # The first machine should have poweroff called on it, as it |
620 | - # was initial in the on state. |
621 | - self.expectThat( |
622 | - mock_poweroff, MockCalledOnceWith(machines[0])) |
623 | - |
624 | - # Check that the create command had the correct parameters for |
625 | - # each machine. |
626 | - self.expectThat( |
627 | - mock_create_node, MockCallsMatch( |
628 | - call( |
629 | - fake_macs[0], fake_arch, 'esxi', called_params[0]), |
630 | - call( |
631 | - fake_macs[1], fake_arch, 'esxi', called_params[1]), |
632 | - call( |
633 | - fake_macs[2], fake_arch, |
634 | - 'esxi', called_params[2]))) |
635 | - mock_logout.assert_called() |
636 | - self.expectThat( |
637 | - mock_commission_node, |
638 | - MockCalledWith(system_id, user)) |
639 | - |
640 | - @inlineCallbacks |
641 | - def test_probe_and_enlist_login_failure(self): |
642 | - user = factory.make_name('user') |
643 | - poweruser = factory.make_name('poweruser') |
644 | - poweraddr = factory.make_name('poweraddr') |
645 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
646 | - mock_login.return_value = False |
647 | - with ExpectedException(virsh.ESXiError): |
648 | - yield deferToThread( |
649 | - virsh.probe_esxi_and_enlist, |
650 | - user, poweruser, poweraddr, password=factory.make_string()) |
651 | - |
652 | - |
653 | -class TestESXiPowerControl(MAASTestCase): |
654 | - """Tests for `power_control_esxi`.""" |
655 | - |
656 | - def test_power_control_login_failure(self): |
657 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
658 | - mock_login.return_value = False |
659 | - self.assertRaises( |
660 | - virsh.ESXiError, virsh.power_control_esxi, |
661 | - factory.make_name('poweraddr'), factory.make_name('machine'), 'on', |
662 | - factory.make_name('username'), password=factory.make_string()) |
663 | - |
664 | - def test_power_control_on(self): |
665 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
666 | - mock_login.return_value = True |
667 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
668 | - mock_state.return_value = virsh.VirshVMState.OFF |
669 | - mock_poweron = self.patch(virsh.VirshSSH, 'poweron') |
670 | - |
671 | - poweraddr = factory.make_name('poweraddr') |
672 | - machine = factory.make_name('machine') |
673 | - username = factory.make_name('user') |
674 | - password = factory.make_string() |
675 | - esx_poweraddr = "esx://%s@%s/?no_verify=1" % (username, poweraddr) |
676 | - virsh.power_control_esxi(poweraddr, machine, 'on', username, password) |
677 | - |
678 | - self.assertThat( |
679 | - mock_login, MockCalledOnceWith(esx_poweraddr, password)) |
680 | - self.assertThat( |
681 | - mock_state, MockCalledOnceWith(machine)) |
682 | - self.assertThat( |
683 | - mock_poweron, MockCalledOnceWith(machine)) |
684 | - |
685 | - def test_power_control_off(self): |
686 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
687 | - mock_login.return_value = True |
688 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
689 | - mock_state.return_value = virsh.VirshVMState.ON |
690 | - mock_poweroff = self.patch(virsh.VirshSSH, 'poweroff') |
691 | - |
692 | - poweraddr = factory.make_name('poweraddr') |
693 | - machine = factory.make_name('machine') |
694 | - username = factory.make_name('user') |
695 | - password = factory.make_string() |
696 | - esx_poweraddr = "esx://%s@%s/?no_verify=1" % (username, poweraddr) |
697 | - virsh.power_control_esxi(poweraddr, machine, 'off', username, password) |
698 | - |
699 | - self.assertThat( |
700 | - mock_login, MockCalledOnceWith(esx_poweraddr, password)) |
701 | - self.assertThat( |
702 | - mock_state, MockCalledOnceWith(machine)) |
703 | - self.assertThat( |
704 | - mock_poweroff, MockCalledOnceWith(machine)) |
705 | - |
706 | - def test_power_control_bad_domain(self): |
707 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
708 | - mock_login.return_value = True |
709 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
710 | - mock_state.return_value = None |
711 | - |
712 | - poweraddr = factory.make_name('poweraddr') |
713 | - machine = factory.make_name('machine') |
714 | - username = factory.make_name('user') |
715 | - password = factory.make_string() |
716 | - self.assertRaises( |
717 | - virsh.ESXiError, virsh.power_control_esxi, |
718 | - poweraddr, machine, 'on', username, password) |
719 | - |
720 | - def test_power_control_power_failure(self): |
721 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
722 | - mock_login.return_value = True |
723 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
724 | - mock_state.return_value = virsh.VirshVMState.ON |
725 | - mock_poweroff = self.patch(virsh.VirshSSH, 'poweroff') |
726 | - mock_poweroff.return_value = False |
727 | - |
728 | - poweraddr = factory.make_name('poweraddr') |
729 | - machine = factory.make_name('machine') |
730 | - username = factory.make_name('user') |
731 | - password = factory.make_string() |
732 | - self.assertRaises( |
733 | - virsh.ESXiError, virsh.power_control_esxi, |
734 | - poweraddr, machine, 'off', username, password) |
735 | - |
736 | - |
737 | -class TestESXiPowerState(MAASTestCase): |
738 | - """Tests for `power_state_esxi`.""" |
739 | - |
740 | - def test_power_state_login_failure(self): |
741 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
742 | - mock_login.return_value = False |
743 | - self.assertRaises( |
744 | - virsh.ESXiError, virsh.power_state_esxi, |
745 | - factory.make_name('poweraddr'), factory.make_name('machine'), |
746 | - factory.make_name('user'), password=factory.make_string()) |
747 | - |
748 | - def test_power_state_get_on(self): |
749 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
750 | - mock_login.return_value = True |
751 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
752 | - mock_state.return_value = virsh.VirshVMState.ON |
753 | - |
754 | - poweraddr = factory.make_name('poweraddr') |
755 | - machine = factory.make_name('machine') |
756 | - username = factory.make_name('user') |
757 | - password = factory.make_string() |
758 | - self.assertEqual( |
759 | - 'on', virsh.power_state_esxi(poweraddr, machine, |
760 | - username, password)) |
761 | - |
762 | - def test_power_state_get_off(self): |
763 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
764 | - mock_login.return_value = True |
765 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
766 | - mock_state.return_value = virsh.VirshVMState.OFF |
767 | - |
768 | - poweraddr = factory.make_name('poweraddr') |
769 | - machine = factory.make_name('machine') |
770 | - username = factory.make_name('user') |
771 | - password = factory.make_string() |
772 | - self.assertEqual( |
773 | - 'off', virsh.power_state_esxi(poweraddr, machine, |
774 | - username, password)) |
775 | - |
776 | - def test_power_control_bad_domain(self): |
777 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
778 | - mock_login.return_value = True |
779 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
780 | - mock_state.return_value = None |
781 | - |
782 | - poweraddr = factory.make_name('poweraddr') |
783 | - machine = factory.make_name('machine') |
784 | - username = factory.make_name('user') |
785 | - password = factory.make_string() |
786 | - self.assertRaises( |
787 | - virsh.ESXiError, virsh.power_state_esxi, |
788 | - poweraddr, machine, username, password) |
789 | - |
790 | - def test_power_state_error_on_unknown_state(self): |
791 | - mock_login = self.patch(virsh.VirshSSH, 'login') |
792 | - mock_login.return_value = True |
793 | - mock_state = self.patch(virsh.VirshSSH, 'get_state') |
794 | - mock_state.return_value = 'unknown' |
795 | - |
796 | - poweraddr = factory.make_name('poweraddr') |
797 | - machine = factory.make_name('machine') |
798 | - username = factory.make_name('user') |
799 | - password = factory.make_string() |
800 | - self.assertRaises( |
801 | - virsh.ESXiError, virsh.power_state_esxi, |
802 | - poweraddr, machine, username, password) |
803 | |
804 | === modified file 'src/provisioningserver/power_schema.py' |
805 | --- src/provisioningserver/power_schema.py 2015-05-07 18:14:38 +0000 |
806 | +++ src/provisioningserver/power_schema.py 2015-05-14 16:27:22 +0000 |
807 | @@ -174,18 +174,8 @@ |
808 | ], |
809 | }, |
810 | { |
811 | - 'name': 'esxi', |
812 | - 'description': 'VMWare ESXi (virsh)', |
813 | - 'fields': [ |
814 | - make_json_field('power_address', "Power address"), |
815 | - make_json_field('power_id', "Power ID"), |
816 | - make_json_field('power_user', "Power user"), |
817 | - make_json_field('power_pass', "Power password"), |
818 | - ], |
819 | - }, |
820 | - { |
821 | 'name': 'vsphere', |
822 | - 'description': 'VMWare (python-pyvmomi)', |
823 | + 'description': 'VMWare', |
824 | 'fields': [ |
825 | make_json_field( |
826 | 'power_vm_name', "VM Name (if UUID unknown)", required=False), |
827 | |
828 | === modified file 'src/provisioningserver/rpc/clusterservice.py' |
829 | --- src/provisioningserver/rpc/clusterservice.py 2015-05-07 18:14:38 +0000 |
830 | +++ src/provisioningserver/rpc/clusterservice.py 2015-05-14 16:27:22 +0000 |
831 | @@ -34,7 +34,6 @@ |
832 | ArchitectureRegistry, |
833 | PowerTypeRegistry, |
834 | ) |
835 | -from provisioningserver.drivers.hardware.esxi import probe_esxi_and_enlist |
836 | from provisioningserver.drivers.hardware.mscm import probe_and_enlist_mscm |
837 | from provisioningserver.drivers.hardware.msftocs import ( |
838 | probe_and_enlist_msftocs, |
839 | @@ -368,19 +367,6 @@ |
840 | d.addErrback(partial(catch_probe_and_enlist_error, "virsh")) |
841 | return {} |
842 | |
843 | - @cluster.AddESXi.responder |
844 | - def add_esxi(self, user, poweruser, poweraddr, |
845 | - password, prefix_filter, accept_all): |
846 | - """add_esxi() |
847 | - |
848 | - Implementation of :py:class:`~provisioningserver.rpc.cluster.AddESXi`. |
849 | - """ |
850 | - d = deferToThread( |
851 | - probe_esxi_and_enlist, |
852 | - user, poweruser, poweraddr, password, prefix_filter, accept_all) |
853 | - d.addErrback(partial(catch_probe_and_enlist_error, "esxi")) |
854 | - return {} |
855 | - |
856 | @cluster.AddSeaMicro15k.responder |
857 | def add_seamicro15k(self, user, mac, username, |
858 | password, power_control, accept_all): |
859 | @@ -417,7 +403,7 @@ |
860 | port=port, protocol=protocol, prefix_filter=prefix_filter, |
861 | accept_all=accept_all) |
862 | d.addErrback( |
863 | - partial(catch_probe_and_enlist_error, "vSphere")) |
864 | + partial(catch_probe_and_enlist_error, "VMware")) |
865 | return {} |
866 | |
867 | @cluster.EnlistNodesFromMSCM.responder |
868 | |
869 | === modified file 'src/provisioningserver/rpc/power.py' |
870 | --- src/provisioningserver/rpc/power.py 2015-05-12 16:12:15 +0000 |
871 | +++ src/provisioningserver/rpc/power.py 2015-05-14 16:27:22 +0000 |
872 | @@ -67,7 +67,6 @@ |
873 | QUERY_POWER_TYPES = [ |
874 | 'amt', |
875 | 'dli', |
876 | - 'esxi', |
877 | 'ipmi', |
878 | 'mscm', |
879 | 'msftocs', |
880 | |
881 | === modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py' |
882 | --- src/provisioningserver/rpc/tests/test_clusterservice.py 2015-05-07 18:14:38 +0000 |
883 | +++ src/provisioningserver/rpc/tests/test_clusterservice.py 2015-05-14 16:27:22 +0000 |
884 | @@ -2082,63 +2082,7 @@ |
885 | clusterservice.maaslog.error, |
886 | MockAnyCall( |
887 | "Failed to probe and enlist %s nodes: %s", |
888 | - "vSphere", fake_error)) |
889 | - |
890 | - |
891 | -class TestClusterProtocol_AddESXi(MAASTestCase): |
892 | - |
893 | - def test__is_registered(self): |
894 | - protocol = Cluster() |
895 | - responder = protocol.locateResponder( |
896 | - cluster.AddESXi.commandName) |
897 | - self.assertIsNotNone(responder) |
898 | - |
899 | - def test__calls_deferToThread_with_probe_esxi_and_enlist(self): |
900 | - mock_deferToThread = self.patch_autospec( |
901 | - clusterservice, 'deferToThread') |
902 | - user = factory.make_name('user') |
903 | - poweruser = factory.make_name('poweruser') |
904 | - poweraddr = factory.make_name('poweraddr') |
905 | - password = factory.make_name('password') |
906 | - prefix_filter = factory.make_name('prefix_filter') |
907 | - call_responder(Cluster(), cluster.AddESXi, { |
908 | - "user": user, |
909 | - "poweruser": poweruser, |
910 | - "poweraddr": poweraddr, |
911 | - "password": password, |
912 | - "prefix_filter": prefix_filter, |
913 | - "accept_all": True, |
914 | - }) |
915 | - self.assertThat( |
916 | - mock_deferToThread, MockCalledOnceWith( |
917 | - clusterservice.probe_esxi_and_enlist, |
918 | - user, poweruser, poweraddr, password, |
919 | - prefix_filter, True)) |
920 | - |
921 | - def test__logs_error_to_maaslog(self): |
922 | - fake_error = factory.make_name('error') |
923 | - self.patch(clusterservice, 'maaslog') |
924 | - mock_deferToThread = self.patch_autospec( |
925 | - clusterservice, 'deferToThread') |
926 | - mock_deferToThread.return_value = fail(Exception(fake_error)) |
927 | - user = factory.make_name('user') |
928 | - poweruser = factory.make_name('poweruser') |
929 | - poweraddr = factory.make_name('poweraddr') |
930 | - password = factory.make_name('password') |
931 | - prefix_filter = factory.make_name('prefix_filter') |
932 | - call_responder(Cluster(), cluster.AddESXi, { |
933 | - "user": user, |
934 | - "poweruser": poweruser, |
935 | - "poweraddr": poweraddr, |
936 | - "password": password, |
937 | - "prefix_filter": prefix_filter, |
938 | - "accept_all": True, |
939 | - }) |
940 | - self.assertThat( |
941 | - clusterservice.maaslog.error, |
942 | - MockAnyCall( |
943 | - "Failed to probe and enlist %s nodes: %s", |
944 | - "esxi", fake_error)) |
945 | + "VMware", fake_error)) |
946 | |
947 | |
948 | class TestClusterProtocol_AddSeaMicro15k(MAASTestCase): |
lgtm!