Merge lp:~newell-jensen/maas/2.2-fix-1694759 into lp:maas/2.2
- 2.2-fix-1694759
- Merge into 2.2
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Mike Pontillo | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 6062 | ||||
Proposed branch: | lp:~newell-jensen/maas/2.2-fix-1694759 | ||||
Merge into: | lp:maas/2.2 | ||||
Diff against target: |
235 lines (+85/-72) 2 files modified
src/provisioningserver/drivers/pod/rsd.py (+14/-10) src/provisioningserver/drivers/pod/tests/test_rsd.py (+71/-62) |
||||
To merge this branch: | bzr merge lp:~newell-jensen/maas/2.2-fix-1694759 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Newell Jensen (community) | Approve | ||
Review via email: mp+325260@code.launchpad.net |
Commit message
Backport trunk r6074: Delete newly allocated RSD node if the assembling process fails.
Description of the change
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~newell-jensen/maas/2.2-fix-1694759 into lp:maas/2.2 failed. Below is the output from the failed tests.
Hit:1 http://
Hit:2 http://
Hit:3 http://
Hit:4 http://
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
authbind is already the newest version (2.1.1+nmu1).
avahi-utils is already the newest version (0.6.32~
build-essential is already the newest version (12.1ubuntu2).
debhelper is already the newest version (9.20160115ubun
distro-info is already the newest version (0.14build1).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1ubuntu3).
make is already the newest version (4.1-6).
postgresql is already the newest version (9.5+173).
psmisc is already the newest version (22.21-2.1build1).
pxelinux is already the newest version (3:6.03+
python-formencode is already the newest version (1.3.0-0ubuntu5).
python-lxml is already the newest version (3.5.0-1build1).
python-netaddr is already the newest version (0.7.18-1).
python-netifaces is already the newest version (0.10.4-0.1build2).
python-psycopg2 is already the newest version (2.6.1-1...
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~newell-jensen/maas/2.2-fix-1694759 into lp:maas/2.2 failed. Below is the output from the failed tests.
Hit:1 http://
Get:2 http://
Get:3 http://
Get:4 http://
Fetched 306 kB in 0s (336 kB/s)
Reading package lists...
sudo DEBIAN_
--no-
Reading package lists...
Building dependency tree...
Reading state information...
authbind is already the newest version (2.1.1+nmu1).
avahi-utils is already the newest version (0.6.32~
build-essential is already the newest version (12.1ubuntu2).
debhelper is already the newest version (9.20160115ubun
distro-info is already the newest version (0.14build1).
libjs-angularjs is already the newest version (1.2.28-1ubuntu2).
libjs-jquery is already the newest version (1.11.3+dfsg-4).
libjs-yui3-full is already the newest version (3.5.1-1ubuntu3).
libjs-yui3-min is already the newest version (3.5.1-1ubuntu3).
make is already the newest version (4.1-6).
postgresql is already the newest version (9.5+173).
psmisc is already the newest version (22.21-2.1build1).
pxelinux is already the newest version (3:6.03+
python-formencode is already the newest version (1.3.0-0ubuntu5).
python-lxml is already the newest version (3.5.0-1build1).
python-netaddr is already the newest version (0.7.18-1).
python-netifaces is already the newest version (0.10.4-0.1buil...
Preview Diff
1 | === modified file 'src/provisioningserver/drivers/pod/rsd.py' | |||
2 | --- src/provisioningserver/drivers/pod/rsd.py 2017-05-09 19:10:12 +0000 | |||
3 | +++ src/provisioningserver/drivers/pod/rsd.py 2017-06-07 17:24:55 +0000 | |||
4 | @@ -1046,11 +1046,8 @@ | |||
5 | 1046 | "Unable to allocate machine with requested resources.") | 1046 | "Unable to allocate machine with requested resources.") |
6 | 1047 | 1047 | ||
7 | 1048 | @inlineCallbacks | 1048 | @inlineCallbacks |
13 | 1049 | def decompose(self, pod_id, context): | 1049 | def delete_node(self, url, node_id, headers): |
14 | 1050 | """Decompose machine.""" | 1050 | """Delete node at node_id.""" |
10 | 1051 | url = self.get_url(context) | ||
11 | 1052 | node_id = context.get('node_id').encode('utf-8') | ||
12 | 1053 | headers = self.make_auth_headers(**context) | ||
15 | 1054 | # Delete machine at node_id. | 1051 | # Delete machine at node_id. |
16 | 1055 | endpoint = b"redfish/v1/Nodes/%s" % node_id | 1052 | endpoint = b"redfish/v1/Nodes/%s" % node_id |
17 | 1056 | try: | 1053 | try: |
18 | @@ -1060,12 +1057,17 @@ | |||
19 | 1060 | # XXX newell 2017-02-27 bug=1667754: | 1057 | # XXX newell 2017-02-27 bug=1667754: |
20 | 1061 | # Catch the 404 error when trying to decompose the | 1058 | # Catch the 404 error when trying to decompose the |
21 | 1062 | # resource that has already been decomposed. | 1059 | # resource that has already been decomposed. |
22 | 1063 | # This is a work around and will need to be handled | ||
23 | 1064 | # differently on the region so we don't try to | ||
24 | 1065 | # decompose a machine multiple times. | ||
25 | 1066 | if int(error.status) != HTTPStatus.NOT_FOUND: | 1060 | if int(error.status) != HTTPStatus.NOT_FOUND: |
26 | 1067 | raise | 1061 | raise |
27 | 1068 | 1062 | ||
28 | 1063 | @inlineCallbacks | ||
29 | 1064 | def decompose(self, pod_id, context): | ||
30 | 1065 | """Decompose machine.""" | ||
31 | 1066 | url = self.get_url(context) | ||
32 | 1067 | node_id = context.get('node_id').encode('utf-8') | ||
33 | 1068 | headers = self.make_auth_headers(**context) | ||
34 | 1069 | yield self.delete_node(url, node_id, headers) | ||
35 | 1070 | |||
36 | 1069 | # Retrieve pod resources. | 1071 | # Retrieve pod resources. |
37 | 1070 | discovered_pod = yield self.get_pod_resources(url, headers) | 1072 | discovered_pod = yield self.get_pod_resources(url, headers) |
38 | 1071 | # Retrive pod hints. | 1073 | # Retrive pod hints. |
39 | @@ -1114,7 +1116,8 @@ | |||
40 | 1114 | yield self.redfish_request( | 1116 | yield self.redfish_request( |
41 | 1115 | b"POST", join(url, endpoint), headers) | 1117 | b"POST", join(url, endpoint), headers) |
42 | 1116 | elif node_state == 'Failed': | 1118 | elif node_state == 'Failed': |
44 | 1117 | # Broken system. | 1119 | # Broken system, delete allocated node. |
45 | 1120 | yield self.delete_node(url, node_id, headers) | ||
46 | 1118 | raise PodFatalError( | 1121 | raise PodFatalError( |
47 | 1119 | "Composed machine at node ID %s has a ComposedNodeState" | 1122 | "Composed machine at node ID %s has a ComposedNodeState" |
48 | 1120 | " of Failed." % node_id) | 1123 | " of Failed." % node_id) |
49 | @@ -1131,7 +1134,8 @@ | |||
50 | 1131 | # Check one last time if the state has became `Failed`. | 1134 | # Check one last time if the state has became `Failed`. |
51 | 1132 | 1135 | ||
52 | 1133 | if node_state == 'Failed': | 1136 | if node_state == 'Failed': |
54 | 1134 | # Broken system. | 1137 | # Broken system, delete allocated node. |
55 | 1138 | yield self.delete_node(url, node_id, headers) | ||
56 | 1135 | raise PodFatalError( | 1139 | raise PodFatalError( |
57 | 1136 | "Composed machine at node ID %s has a ComposedNodeState" | 1140 | "Composed machine at node ID %s has a ComposedNodeState" |
58 | 1137 | " of Failed." % node_id) | 1141 | " of Failed." % node_id) |
59 | 1138 | 1142 | ||
60 | === modified file 'src/provisioningserver/drivers/pod/tests/test_rsd.py' | |||
61 | --- src/provisioningserver/drivers/pod/tests/test_rsd.py 2017-05-09 21:53:26 +0000 | |||
62 | +++ src/provisioningserver/drivers/pod/tests/test_rsd.py 2017-06-07 17:24:55 +0000 | |||
63 | @@ -2002,74 +2002,77 @@ | |||
64 | 2002 | factory.make_name('system_id'), context, request) | 2002 | factory.make_name('system_id'), context, request) |
65 | 2003 | 2003 | ||
66 | 2004 | @inlineCallbacks | 2004 | @inlineCallbacks |
67 | 2005 | def test__delete_node(self): | ||
68 | 2006 | driver = RSDPodDriver() | ||
69 | 2007 | context = make_context() | ||
70 | 2008 | url = driver.get_url(context) | ||
71 | 2009 | node_id = context.get('node_id').encode('utf-8') | ||
72 | 2010 | endpoint = b"redfish/v1/Nodes/%s" % node_id | ||
73 | 2011 | headers = driver.make_auth_headers(**context) | ||
74 | 2012 | mock_redfish_request = self.patch(driver, 'redfish_request') | ||
75 | 2013 | |||
76 | 2014 | yield driver.delete_node(url, node_id, headers) | ||
77 | 2015 | self.assertThat(mock_redfish_request, MockCalledOnceWith( | ||
78 | 2016 | b"DELETE", join(url, endpoint), headers)) | ||
79 | 2017 | |||
80 | 2018 | @inlineCallbacks | ||
81 | 2019 | def test_delete_node_continues_on_404_error(self): | ||
82 | 2020 | driver = RSDPodDriver() | ||
83 | 2021 | context = make_context() | ||
84 | 2022 | url = driver.get_url(context) | ||
85 | 2023 | node_id = context.get('node_id').encode('utf-8') | ||
86 | 2024 | endpoint = b"redfish/v1/Nodes/%s" % node_id | ||
87 | 2025 | headers = driver.make_auth_headers(**context) | ||
88 | 2026 | mock_redfish_request = self.patch(driver, 'redfish_request') | ||
89 | 2027 | error = PartialDownloadError( | ||
90 | 2028 | response=json.dumps(SAMPLE_JSON_SYSTEMS).encode('utf-8'), | ||
91 | 2029 | code=HTTPStatus.NOT_FOUND) | ||
92 | 2030 | mock_redfish_request.side_effect = error | ||
93 | 2031 | |||
94 | 2032 | yield driver.delete_node(url, node_id, headers) | ||
95 | 2033 | self.assertThat(mock_redfish_request, MockCalledOnceWith( | ||
96 | 2034 | b"DELETE", join(url, endpoint), headers)) | ||
97 | 2035 | |||
98 | 2036 | @inlineCallbacks | ||
99 | 2037 | def test_delete_node_raises_when_not_404_error(self): | ||
100 | 2038 | driver = RSDPodDriver() | ||
101 | 2039 | context = make_context() | ||
102 | 2040 | url = driver.get_url(context) | ||
103 | 2041 | node_id = context.get('node_id').encode('utf-8') | ||
104 | 2042 | endpoint = b"redfish/v1/Nodes/%s" % node_id | ||
105 | 2043 | headers = driver.make_auth_headers(**context) | ||
106 | 2044 | mock_redfish_request = self.patch(driver, 'redfish_request') | ||
107 | 2045 | error = PartialDownloadError( | ||
108 | 2046 | response=json.dumps(SAMPLE_JSON_SYSTEMS).encode('utf-8'), | ||
109 | 2047 | code=HTTPStatus.BAD_REQUEST) | ||
110 | 2048 | mock_redfish_request.side_effect = error | ||
111 | 2049 | |||
112 | 2050 | with ExpectedException(PartialDownloadError): | ||
113 | 2051 | yield driver.delete_node(url, node_id, headers) | ||
114 | 2052 | self.assertThat(mock_redfish_request, MockCalledOnceWith( | ||
115 | 2053 | b"DELETE", join(url, endpoint), headers)) | ||
116 | 2054 | |||
117 | 2055 | @inlineCallbacks | ||
118 | 2005 | def test__decompose(self): | 2056 | def test__decompose(self): |
119 | 2006 | driver = RSDPodDriver() | 2057 | driver = RSDPodDriver() |
120 | 2007 | context = make_context() | 2058 | context = make_context() |
121 | 2008 | url = driver.get_url(context) | 2059 | url = driver.get_url(context) |
122 | 2009 | node_id = context.get('node_id').encode('utf-8') | 2060 | node_id = context.get('node_id').encode('utf-8') |
123 | 2010 | headers = driver.make_auth_headers(**context) | 2061 | headers = driver.make_auth_headers(**context) |
186 | 2011 | endpoint = b"redfish/v1/Nodes/%s" % node_id | 2062 | mock_delete_node = self.patch(driver, 'delete_node') |
187 | 2012 | mock_redfish_request = self.patch(driver, 'redfish_request') | 2063 | mock_get_pod_resources = self.patch(driver, 'get_pod_resources') |
188 | 2013 | mock_get_pod_resources = self.patch(driver, 'get_pod_resources') | 2064 | discovered_pod = make_discovered_pod() |
189 | 2014 | discovered_pod = make_discovered_pod() | 2065 | mock_get_pod_resources.return_value = discovered_pod |
190 | 2015 | mock_get_pod_resources.return_value = discovered_pod | 2066 | mock_get_pod_hints = self.patch(driver, 'get_pod_hints') |
191 | 2016 | mock_get_pod_hints = self.patch(driver, 'get_pod_hints') | 2067 | |
192 | 2017 | 2068 | yield driver.decompose( | |
193 | 2018 | yield driver.decompose( | 2069 | factory.make_name('system_id'), context) |
194 | 2019 | factory.make_name('system_id'), context) | 2070 | self.assertThat(mock_delete_node, MockCalledOnceWith( |
195 | 2020 | self.assertThat(mock_redfish_request, MockCalledOnceWith( | 2071 | url, node_id, headers)) |
196 | 2021 | b"DELETE", join(url, endpoint), headers)) | 2072 | self.assertThat(mock_get_pod_resources, MockCalledOnceWith( |
197 | 2022 | self.assertThat(mock_get_pod_resources, MockCalledOnceWith( | 2073 | url, headers)) |
198 | 2023 | url, headers)) | 2074 | self.assertThat(mock_get_pod_hints, MockCalledOnceWith( |
199 | 2024 | self.assertThat(mock_get_pod_hints, MockCalledOnceWith( | 2075 | discovered_pod)) |
138 | 2025 | discovered_pod)) | ||
139 | 2026 | |||
140 | 2027 | @inlineCallbacks | ||
141 | 2028 | def test_decompose_continues_on_404_error(self): | ||
142 | 2029 | driver = RSDPodDriver() | ||
143 | 2030 | context = make_context() | ||
144 | 2031 | url = driver.get_url(context) | ||
145 | 2032 | node_id = context.get('node_id').encode('utf-8') | ||
146 | 2033 | headers = driver.make_auth_headers(**context) | ||
147 | 2034 | endpoint = b"redfish/v1/Nodes/%s" % node_id | ||
148 | 2035 | mock_redfish_request = self.patch(driver, 'redfish_request') | ||
149 | 2036 | error = PartialDownloadError( | ||
150 | 2037 | response=json.dumps(SAMPLE_JSON_SYSTEMS).encode('utf-8'), | ||
151 | 2038 | code=HTTPStatus.NOT_FOUND) | ||
152 | 2039 | mock_redfish_request.side_effect = error | ||
153 | 2040 | mock_get_pod_resources = self.patch(driver, 'get_pod_resources') | ||
154 | 2041 | discovered_pod = make_discovered_pod() | ||
155 | 2042 | mock_get_pod_resources.return_value = discovered_pod | ||
156 | 2043 | mock_get_pod_hints = self.patch(driver, 'get_pod_hints') | ||
157 | 2044 | |||
158 | 2045 | yield driver.decompose( | ||
159 | 2046 | factory.make_name('system_id'), context) | ||
160 | 2047 | self.assertThat(mock_redfish_request, MockCalledOnceWith( | ||
161 | 2048 | b"DELETE", join(url, endpoint), headers)) | ||
162 | 2049 | self.assertThat(mock_get_pod_resources, MockCalledOnceWith( | ||
163 | 2050 | url, headers)) | ||
164 | 2051 | self.assertThat(mock_get_pod_hints, MockCalledOnceWith( | ||
165 | 2052 | discovered_pod)) | ||
166 | 2053 | |||
167 | 2054 | @inlineCallbacks | ||
168 | 2055 | def test_decompose_raises_when_not_404_error(self): | ||
169 | 2056 | driver = RSDPodDriver() | ||
170 | 2057 | context = make_context() | ||
171 | 2058 | url = driver.get_url(context) | ||
172 | 2059 | node_id = context.get('node_id').encode('utf-8') | ||
173 | 2060 | headers = driver.make_auth_headers(**context) | ||
174 | 2061 | endpoint = b"redfish/v1/Nodes/%s" % node_id | ||
175 | 2062 | mock_redfish_request = self.patch(driver, 'redfish_request') | ||
176 | 2063 | error = PartialDownloadError( | ||
177 | 2064 | response=json.dumps(SAMPLE_JSON_SYSTEMS).encode('utf-8'), | ||
178 | 2065 | code=HTTPStatus.BAD_REQUEST) | ||
179 | 2066 | mock_redfish_request.side_effect = error | ||
180 | 2067 | |||
181 | 2068 | with ExpectedException(PartialDownloadError): | ||
182 | 2069 | yield driver.decompose( | ||
183 | 2070 | factory.make_name('system_id'), context) | ||
184 | 2071 | self.assertThat(mock_redfish_request, MockCalledOnceWith( | ||
185 | 2072 | b"DELETE", join(url, endpoint), headers)) | ||
200 | 2073 | 2076 | ||
201 | 2074 | @inlineCallbacks | 2077 | @inlineCallbacks |
202 | 2075 | def test__set_pxe_boot(self): | 2078 | def test__set_pxe_boot(self): |
203 | @@ -2164,12 +2167,15 @@ | |||
204 | 2164 | mock_get_composed_node_state = self.patch( | 2167 | mock_get_composed_node_state = self.patch( |
205 | 2165 | driver, 'get_composed_node_state') | 2168 | driver, 'get_composed_node_state') |
206 | 2166 | mock_get_composed_node_state.return_value = "Failed" | 2169 | mock_get_composed_node_state.return_value = "Failed" |
207 | 2170 | mock_delete_node = self.patch(driver, 'delete_node') | ||
208 | 2167 | mock_redfish_request = self.patch(driver, 'redfish_request') | 2171 | mock_redfish_request = self.patch(driver, 'redfish_request') |
209 | 2168 | 2172 | ||
210 | 2169 | with ExpectedException(PodFatalError): | 2173 | with ExpectedException(PodFatalError): |
211 | 2170 | yield driver.assemble_node(url, node_id, headers) | 2174 | yield driver.assemble_node(url, node_id, headers) |
212 | 2171 | self.assertThat(mock_get_composed_node_state, MockCalledOnceWith( | 2175 | self.assertThat(mock_get_composed_node_state, MockCalledOnceWith( |
213 | 2172 | url, node_id, headers)) | 2176 | url, node_id, headers)) |
214 | 2177 | self.assertThat(mock_delete_node, MockCalledOnceWith( | ||
215 | 2178 | url, node_id, headers)) | ||
216 | 2173 | self.assertThat(mock_redfish_request, MockNotCalled()) | 2179 | self.assertThat(mock_redfish_request, MockNotCalled()) |
217 | 2174 | 2180 | ||
218 | 2175 | @inlineCallbacks | 2181 | @inlineCallbacks |
219 | @@ -2183,6 +2189,7 @@ | |||
220 | 2183 | driver, 'get_composed_node_state') | 2189 | driver, 'get_composed_node_state') |
221 | 2184 | mock_get_composed_node_state.side_effect = [ | 2190 | mock_get_composed_node_state.side_effect = [ |
222 | 2185 | "Allocated", "Assembling", "Failed"] | 2191 | "Allocated", "Assembling", "Failed"] |
223 | 2192 | mock_delete_node = self.patch(driver, 'delete_node') | ||
224 | 2186 | mock_redfish_request = self.patch(driver, 'redfish_request') | 2193 | mock_redfish_request = self.patch(driver, 'redfish_request') |
225 | 2187 | endpoint = ( | 2194 | endpoint = ( |
226 | 2188 | b"redfish/v1/Nodes/%s/Actions/ComposedNode.Assemble" % node_id) | 2195 | b"redfish/v1/Nodes/%s/Actions/ComposedNode.Assemble" % node_id) |
227 | @@ -2196,6 +2203,8 @@ | |||
228 | 2196 | call(url, node_id, headers))) | 2203 | call(url, node_id, headers))) |
229 | 2197 | self.assertThat(mock_redfish_request, MockCalledOnceWith( | 2204 | self.assertThat(mock_redfish_request, MockCalledOnceWith( |
230 | 2198 | b"POST", uri, headers)) | 2205 | b"POST", uri, headers)) |
231 | 2206 | self.assertThat(mock_delete_node, MockCalledOnceWith( | ||
232 | 2207 | url, node_id, headers)) | ||
233 | 2199 | 2208 | ||
234 | 2200 | @inlineCallbacks | 2209 | @inlineCallbacks |
235 | 2201 | def test_power_issues_power_reset(self): | 2210 | def test_power_issues_power_reset(self): |
Self review backport.