Merge lp:~mpontillo/maas/bug-1451852-remove-legacy-esxi-probe-and-enlist into lp:~maas-committers/maas/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
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.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

review: Approve

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):