Merge lp:~ltrager/maas/lp1637401 into lp:maas/trunk

Proposed by Lee Trager
Status: Merged
Approved by: Lee Trager
Approved revision: 5576
Merged at revision: 5579
Proposed branch: lp:~ltrager/maas/lp1637401
Merge into: lp:maas/trunk
Diff against target: 127 lines (+34/-20)
2 files modified
src/provisioningserver/drivers/hardware/tests/test_virsh.py (+23/-13)
src/provisioningserver/drivers/hardware/virsh.py (+11/-7)
To merge this branch: bzr merge lp:~ltrager/maas/lp1637401
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+312098@code.launchpad.net

Commit message

During probe and enlist of virsh only power off and commission new nodes.

Previously probe_virsh_and_enlist would power off each node before requesting a new node row was created. If the machine already exists or there was some issue creating the new node row the node was still powered off. This meant reprobing a virsh host would power off all known nodes. Power off now only happens if a new row was successfully created, existing nodes are ignored and left untouched.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) :
review: Needs Information
lp:~ltrager/maas/lp1637401 updated
5576. By Lee Trager on 2016-11-30

Fix comment

Revision history for this message
Lee Trager (ltrager) wrote :

create_node is a wrapper around the CreateNode RPC call. If the CreateNode RPC call raises a NodeAlreadyExists, UnhandledCommand, or UnknownRemoteError it returns None. In that case we don't want to proceed as MAAS either already controls the node or an error occurred when creating the new node row. I updated the comment to reflect that most likely we received None because we already control it.

Revision history for this message
Blake Rouse (blake-rouse) wrote :

Looks good. Thanks for the explanation.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/drivers/hardware/tests/test_virsh.py'
2--- src/provisioningserver/drivers/hardware/tests/test_virsh.py 2016-11-17 11:46:08 +0000
3+++ src/provisioningserver/drivers/hardware/tests/test_virsh.py 2016-11-30 17:54:47 +0000
4@@ -13,9 +13,7 @@
5 from lxml import etree
6 from maastesting.factory import factory
7 from maastesting.matchers import (
8- MockAnyCall,
9 MockCalledOnceWith,
10- MockCalledWith,
11 MockCallsMatch,
12 )
13 from maastesting.testcase import (
14@@ -281,7 +279,7 @@
15 # with some fake architectures.
16 user = factory.make_name('user')
17 system_id = factory.make_name('system_id')
18- machines = [factory.make_name('machine') for _ in range(4)]
19+ machines = [factory.make_name('machine') for _ in range(5)]
20 self.patch(virsh.VirshSSH, 'list').return_value = machines
21 fake_arch = factory.make_name('arch')
22 mock_arch = self.patch(virsh.VirshSSH, 'get_arch')
23@@ -295,6 +293,7 @@
24 virsh.VirshVMState.OFF,
25 virsh.VirshVMState.OFF,
26 virsh.VirshVMState.ON,
27+ virsh.VirshVMState.ON,
28 ]
29 mock_state = self.patch(virsh.VirshSSH, 'get_state')
30 mock_state.side_effect = fake_states
31@@ -324,7 +323,7 @@
32 mock_poweroff = self.patch(virsh.VirshSSH, 'poweroff')
33 mock_create_node = self.patch(virsh, 'create_node')
34 mock_create_node.side_effect = asynchronous(
35- lambda *args, **kwargs: system_id)
36+ lambda *args, **kwargs: None if machines[4] in args else system_id)
37 mock_commission_node = self.patch(virsh, 'commission_node')
38
39 # Patch login and logout so that we don't really contact
40@@ -338,6 +337,7 @@
41 SAMPLE_DUMPXML_2,
42 SAMPLE_DUMPXML_3,
43 SAMPLE_DUMPXML_4,
44+ SAMPLE_DUMPXML,
45 ]
46
47 mock_run = self.patch(virsh.VirshSSH, 'run')
48@@ -353,12 +353,6 @@
49 self.expectThat(
50 mock_login, MockCalledOnceWith(poweraddr, fake_password))
51
52- # The first and last machine should have poweroff called on it, as it
53- # was initial in the on state.
54- self.expectThat(mock_poweroff, MockAnyCall(machines[0]))
55-
56- self.expectThat(mock_poweroff, MockAnyCall(machines[3]))
57-
58 # Check that the create command had the correct parameters for
59 # each machine.
60 self.expectThat(
61@@ -375,11 +369,27 @@
62 call(
63 fake_macs[3], fake_arch, 'virsh', called_params[3],
64 domain, machines[3]),
65- ))
66+ call(
67+ fake_macs[4], fake_arch, 'virsh', called_params[4],
68+ domain, machines[4]),
69+ ))
70+
71+ # The first and last machine should have poweroff called on it, as it
72+ # was initial in the on state.
73+ self.expectThat(
74+ mock_poweroff, MockCallsMatch(
75+ call(machines[0]),
76+ call(machines[3]),
77+ ))
78+
79 self.assertThat(mock_logout, MockCalledOnceWith())
80 self.expectThat(
81- mock_commission_node,
82- MockCalledWith(system_id, user))
83+ mock_commission_node, MockCallsMatch(
84+ call(system_id, user),
85+ call(system_id, user),
86+ call(system_id, user),
87+ call(system_id, user),
88+ ))
89
90 @inlineCallbacks
91 def test_probe_and_enlist_login_failure(self):
92
93=== modified file 'src/provisioningserver/drivers/hardware/virsh.py'
94--- src/provisioningserver/drivers/hardware/virsh.py 2016-11-17 11:46:08 +0000
95+++ src/provisioningserver/drivers/hardware/virsh.py 2016-11-30 17:54:47 +0000
96@@ -284,11 +284,6 @@
97 state = conn.get_state(machine)
98 macs = conn.get_mac_addresses(machine)
99
100- # Force the machine off, as MAAS will control the machine
101- # and it needs to be in a known state of off.
102- if state == VirshVMState.ON:
103- conn.poweroff(machine)
104-
105 params = {
106 'power_address': poweraddr,
107 'power_id': machine,
108@@ -298,8 +293,17 @@
109 system_id = create_node(
110 macs, arch, 'virsh', params, domain, machine).wait(30)
111
112- if system_id is not None:
113- conn.configure_pxe_boot(machine)
114+ # If the system_id is None an error occured when creating the machine.
115+ # Most likely the error is the node already exists.
116+ if system_id is None:
117+ continue
118+
119+ # Force the machine off, as MAAS will control the machine
120+ # and it needs to be in a known state of off.
121+ if state == VirshVMState.ON:
122+ conn.poweroff(machine)
123+
124+ conn.configure_pxe_boot(machine)
125
126 if accept_all:
127 commission_node(system_id, user).wait(30)