Merge lp:~blake-rouse/maas/read-only-view-node-networking into lp:~maas-committers/maas/trunk
- read-only-view-node-networking
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Blake Rouse |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4447 |
Proposed branch: | lp:~blake-rouse/maas/read-only-view-node-networking |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
451 lines (+227/-13) 12 files modified
src/maasserver/api/interfaces.py (+5/-0) src/maasserver/api/nodes.py (+1/-0) src/maasserver/api/tests/test_interfaces.py (+11/-2) src/maasserver/forms_interface.py (+6/-1) src/maasserver/models/interface.py (+25/-1) src/maasserver/models/tests/test_interface.py (+33/-1) src/maasserver/static/js/angular/controllers/node_details_networking.js (+5/-0) src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js (+14/-0) src/maasserver/static/partials/node-details.html (+15/-5) src/maasserver/tests/test_forms_interface.py (+55/-0) src/maasserver/websockets/handlers/node.py (+16/-1) src/maasserver/websockets/handlers/tests/test_node.py (+41/-2) |
To merge this branch: | bzr merge lp:~blake-rouse/maas/read-only-view-node-networking |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andres Rodriguez (community) | Approve | ||
Review via email: mp+276315@code.launchpad.net |
Commit message
Add the discovered field to the API and websocket for the interface. Use that field in the WebUI to show the current discovered IP address when the node is commissioning. Also update the WebUI to be all in one line once a node is out of edit mode.
Description of the change
Blake Rouse (blake-rouse) wrote : | # |
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~blake-rouse/maas/read-only-view-node-networking into lp:maas failed. Below is the output from the failed tests.
Hit http://
Ign http://
Get:1 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:2 http://
Hit http://
Get:3 http://
Get:4 http://
Get:5 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,415 kB in 3s (376 kB/s)
Reading package lists...
sudo DEBIAN_
--
Andres Rodriguez (andreserl) wrote : | # |
metadataserver.
metadataserver.
metadataserver.
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~blake-rouse/maas/read-only-view-node-networking into lp:maas failed. Below is the output from the failed tests.
Hit http://
Ign http://
Get:1 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:2 http://
Hit http://
Hit http://
Get:3 http://
Get:4 http://
Get:5 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,415 kB in 3s (373 kB/s)
Reading package lists...
sudo DEBIAN_
--
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~blake-rouse/maas/read-only-view-node-networking into lp:maas failed. Below is the output from the failed tests.
Hit http://
Ign http://
Get:1 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:2 http://
Hit http://
Hit http://
Get:3 http://
Get:4 http://
Get:5 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,415 kB in 4s (323 kB/s)
Reading package lists...
sudo DEBIAN_
--
Preview Diff
1 | === modified file 'src/maasserver/api/interfaces.py' |
2 | --- src/maasserver/api/interfaces.py 2015-10-23 21:33:14 +0000 |
3 | +++ src/maasserver/api/interfaces.py 2015-10-31 23:55:40 +0000 |
4 | @@ -63,6 +63,7 @@ |
5 | 'enabled', |
6 | 'links', |
7 | 'params', |
8 | + 'discovered', |
9 | ) |
10 | |
11 | |
12 | @@ -279,6 +280,10 @@ |
13 | def links(cls, interface): |
14 | return interface.get_links() |
15 | |
16 | + @classmethod |
17 | + def discovered(cls, interface): |
18 | + return interface.get_discovered() |
19 | + |
20 | def read(self, request, system_id, interface_id): |
21 | """Read interface on node. |
22 | |
23 | |
24 | === modified file 'src/maasserver/api/nodes.py' |
25 | --- src/maasserver/api/nodes.py 2015-10-26 18:15:08 +0000 |
26 | +++ src/maasserver/api/nodes.py 2015-10-31 23:55:40 +0000 |
27 | @@ -132,6 +132,7 @@ |
28 | 'enabled', |
29 | 'links', |
30 | 'params', |
31 | + 'discovered', |
32 | )), |
33 | 'routers', |
34 | 'zone', |
35 | |
36 | === modified file 'src/maasserver/api/tests/test_interfaces.py' |
37 | --- src/maasserver/api/tests/test_interfaces.py 2015-10-23 21:57:59 +0000 |
38 | +++ src/maasserver/api/tests/test_interfaces.py 2015-10-31 23:55:40 +0000 |
39 | @@ -443,13 +443,19 @@ |
40 | dhcp_ip = factory.make_StaticIPAddress( |
41 | alloc_type=IPADDRESS_TYPE.DHCP, ip="", |
42 | subnet=dhcp_subnet, interface=bond) |
43 | + discovered_ip = factory.pick_ip_in_network( |
44 | + dhcp_subnet.get_ipnetwork()) |
45 | + factory.make_StaticIPAddress( |
46 | + alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=discovered_ip, |
47 | + subnet=dhcp_subnet, interface=bond) |
48 | links.append( |
49 | MatchesDict({ |
50 | "id": Equals(dhcp_ip.id), |
51 | "mode": Equals(INTERFACE_LINK_TYPE.DHCP), |
52 | "subnet": ContainsDict({ |
53 | "id": Equals(dhcp_subnet.id) |
54 | - }) |
55 | + }), |
56 | + "ip_address": Equals(discovered_ip), |
57 | })) |
58 | |
59 | # Second link is a STATIC ip link. |
60 | @@ -506,7 +512,7 @@ |
61 | "tags": Equals(bond.tags), |
62 | "resource_uri": Equals(get_node_interface_uri(bond)), |
63 | "params": Equals(bond.params), |
64 | - })) |
65 | + })) |
66 | self.assertEquals(sorted( |
67 | nic.name |
68 | for nic in parents |
69 | @@ -516,6 +522,9 @@ |
70 | for nic in children |
71 | ), parsed_interface["children"]) |
72 | self.assertThat(parsed_interface["links"], MatchesListwise(links)) |
73 | + json_discovered = parsed_interface["discovered"][0] |
74 | + self.assertEquals(dhcp_subnet.id, json_discovered["subnet"]["id"]) |
75 | + self.assertEquals(discovered_ip, json_discovered["ip_address"]) |
76 | |
77 | def test_read_404_when_invalid_id(self): |
78 | node = factory.make_Node() |
79 | |
80 | === modified file 'src/maasserver/forms_interface.py' |
81 | --- src/maasserver/forms_interface.py 2015-10-04 20:47:36 +0000 |
82 | +++ src/maasserver/forms_interface.py 2015-10-31 23:55:40 +0000 |
83 | @@ -346,7 +346,12 @@ |
84 | ] |
85 | for bond_field in bond_fields: |
86 | value = self.cleaned_data.get(bond_field) |
87 | - if value: |
88 | + if (value is not None and |
89 | + isinstance(value, (bytes, unicode)) and |
90 | + len(value) > 0 and not value.isspace()): |
91 | + interface.params[bond_field] = value |
92 | + elif (value is not None and |
93 | + not isinstance(value, (bytes, unicode))): |
94 | interface.params[bond_field] = value |
95 | elif created: |
96 | interface.params[bond_field] = self.fields[bond_field].initial |
97 | |
98 | === modified file 'src/maasserver/models/interface.py' |
99 | --- src/maasserver/models/interface.py 2015-10-27 17:45:01 +0000 |
100 | +++ src/maasserver/models/interface.py 2015-10-31 23:55:40 +0000 |
101 | @@ -253,7 +253,7 @@ |
102 | { |
103 | "id": 1, |
104 | "mode": "dhcp", |
105 | - "ip": "192.168.1.2", |
106 | + "ip_address": "192.168.1.2", |
107 | "subnet": <Subnet object> |
108 | } |
109 | |
110 | @@ -276,6 +276,30 @@ |
111 | links.append(link) |
112 | return links |
113 | |
114 | + def get_discovered(self): |
115 | + """Return the definition of discovered IP addresses belonging to this |
116 | + interface. |
117 | + |
118 | + Example definition: |
119 | + { |
120 | + "ip_address": "192.168.1.2", |
121 | + "subnet": <Subnet object> |
122 | + } |
123 | + """ |
124 | + discovered_ips = self.ip_addresses.filter( |
125 | + alloc_type=IPADDRESS_TYPE.DISCOVERED) |
126 | + if len(discovered_ips) > 0: |
127 | + discovered = [] |
128 | + for discovered_ip in discovered_ips: |
129 | + if discovered_ip.ip is not None and discovered_ip.ip != "": |
130 | + discovered.append({ |
131 | + "subnet": discovered_ip.subnet, |
132 | + "ip_address": "%s" % discovered_ip.ip, |
133 | + }) |
134 | + return discovered |
135 | + else: |
136 | + return None |
137 | + |
138 | def only_has_link_up(self): |
139 | """Return True if this interface is only set to LINK_UP.""" |
140 | ip_addresses = self.ip_addresses.exclude( |
141 | |
142 | === modified file 'src/maasserver/models/tests/test_interface.py' |
143 | --- src/maasserver/models/tests/test_interface.py 2015-10-30 16:14:33 +0000 |
144 | +++ src/maasserver/models/tests/test_interface.py 2015-10-31 23:55:40 +0000 |
145 | @@ -222,6 +222,38 @@ |
146 | })) |
147 | self.assertThat(interface.get_links(), MatchesListwise(links)) |
148 | |
149 | + def test_get_discovered_returns_None_when_empty(self): |
150 | + interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
151 | + self.assertIsNone(interface.get_discovered()) |
152 | + |
153 | + def test_get_discovered_returns_discovered_address_for_ipv4_and_ipv6(self): |
154 | + interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
155 | + discovered_ips = [] |
156 | + network_v4 = factory.make_ipv4_network() |
157 | + subnet_v4 = factory.make_Subnet(cidr=unicode(network_v4.cidr)) |
158 | + ip_v4 = factory.pick_ip_in_network(network_v4) |
159 | + factory.make_StaticIPAddress( |
160 | + alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip_v4, |
161 | + subnet=subnet_v4, interface=interface) |
162 | + discovered_ips.append( |
163 | + MatchesDict({ |
164 | + "ip_address": Equals(ip_v4), |
165 | + "subnet": Equals(subnet_v4), |
166 | + })) |
167 | + network_v6 = factory.make_ipv6_network() |
168 | + subnet_v6 = factory.make_Subnet(cidr=unicode(network_v6.cidr)) |
169 | + ip_v6 = factory.pick_ip_in_network(network_v6) |
170 | + factory.make_StaticIPAddress( |
171 | + alloc_type=IPADDRESS_TYPE.DISCOVERED, ip=ip_v6, |
172 | + subnet=subnet_v6, interface=interface) |
173 | + discovered_ips.append( |
174 | + MatchesDict({ |
175 | + "ip_address": Equals(ip_v6), |
176 | + "subnet": Equals(subnet_v6), |
177 | + })) |
178 | + self.assertThat( |
179 | + interface.get_discovered(), MatchesListwise(discovered_ips)) |
180 | + |
181 | def test_delete_deletes_related_ip_addresses(self): |
182 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
183 | discovered_ip = factory.make_StaticIPAddress( |
184 | @@ -806,7 +838,7 @@ |
185 | "Unknown interfaces should have been deleted.") |
186 | self.assertEqual(num_connections, interface.ip_addresses.count()) |
187 | for i in range(num_connections): |
188 | - ip = interface.ip_addresses.all()[i] |
189 | + ip = interface.ip_addresses.order_by('id')[i] |
190 | self.assertThat(ip, MatchesStructure.byEquality( |
191 | alloc_type=IPADDRESS_TYPE.DISCOVERED, subnet=subnet_list[i], |
192 | ip=unicode(IPNetwork(cidr_list[i]).ip))) |
193 | |
194 | === modified file 'src/maasserver/static/js/angular/controllers/node_details_networking.js' |
195 | --- src/maasserver/static/js/angular/controllers/node_details_networking.js 2015-10-30 16:35:25 +0000 |
196 | +++ src/maasserver/static/js/angular/controllers/node_details_networking.js 2015-10-31 23:55:40 +0000 |
197 | @@ -557,6 +557,11 @@ |
198 | } |
199 | }; |
200 | |
201 | + // Get the subnet from its ID. |
202 | + $scope.getSubnet = function(subnetId) { |
203 | + return SubnetsManager.getItemFromList(subnetId); |
204 | + }; |
205 | + |
206 | // Toggle showing or hiding the members of the interface. |
207 | $scope.toggleMembers = function(nic) { |
208 | var idx = $scope.showingMembers.indexOf(nic.id); |
209 | |
210 | === modified file 'src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js' |
211 | --- src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js 2015-10-30 16:35:25 +0000 |
212 | +++ src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js 2015-10-31 23:55:40 +0000 |
213 | @@ -1035,6 +1035,20 @@ |
214 | }); |
215 | }); |
216 | |
217 | + describe("getSubnet", function() { |
218 | + |
219 | + it("calls SubnetsManager.getItemFromList", function() { |
220 | + var controller = makeController(); |
221 | + var subnetId = makeInteger(0, 100); |
222 | + var subnet = {}; |
223 | + spyOn(SubnetsManager, "getItemFromList").and.returnValue(subnet); |
224 | + |
225 | + expect($scope.getSubnet(subnetId)).toBe(subnet); |
226 | + expect(SubnetsManager.getItemFromList).toHaveBeenCalledWith( |
227 | + subnetId); |
228 | + }); |
229 | + }); |
230 | + |
231 | describe("toggleMembers", function() { |
232 | |
233 | it("adds interface id to showingMembers", function() { |
234 | |
235 | === modified file 'src/maasserver/static/partials/node-details.html' |
236 | --- src/maasserver/static/partials/node-details.html 2015-10-30 16:43:21 +0000 |
237 | +++ src/maasserver/static/partials/node-details.html 2015-10-31 23:55:40 +0000 |
238 | @@ -415,14 +415,18 @@ |
239 | </div> |
240 | <div class="table__data table__column--18"> |
241 | <select class="table__input" name="subnet" id="subnet" |
242 | + data-ng-hide="isAllNetworkingDisabled() && interface.discovered[0].subnet_id" |
243 | data-ng-model="interface.subnet" |
244 | data-ng-change="subnetChanged(interface)" |
245 | data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets | filterByVLAN:interface.vlan"> |
246 | <option value="" data-ng-hide="interface.links.length > 1">Unconfigured</option> |
247 | </select> |
248 | + <span class="ng-hide" data-ng-show="isAllNetworkingDisabled() && interface.discovered[0].subnet_id"> |
249 | + {$ getSubnetText(getSubnet(interface.discovered[0].subnet_id)) $} |
250 | + </span> |
251 | </div> |
252 | - <div class="table__data table__column--14"> |
253 | - <ul class="no-bullets"> |
254 | + <div class="table__data table__column--21"> |
255 | + <ul class="no-bullets" data-ng-hide="isAllNetworkingDisabled()"> |
256 | <li> |
257 | <select class="table__input" name="link-mode" id="link-mode" |
258 | data-ng-model="interface.mode" |
259 | @@ -441,8 +445,14 @@ |
260 | data-ng-disabled="interface.mode != 'static'"> |
261 | </li> |
262 | </ul> |
263 | + <span class="ng-hide" data-ng-show="isAllNetworkingDisabled() && !interface.discovered[0].ip_address"> |
264 | + {$ interface.ip_address $} ({$ getLinkModeText(interface) $}) |
265 | + </span> |
266 | + <span class="ng-hide" data-ng-show="isAllNetworkingDisabled() && interface.discovered[0].ip_address"> |
267 | + {$ interface.discovered[0].ip_address $} (DHCP) |
268 | + </span> |
269 | </div> |
270 | - <div class="table__data table__column--13"> |
271 | + <div class="table__data table__column--6"> |
272 | <div class="table__controls align-right"> |
273 | <a class="icon add" |
274 | data-ng-click="quickAdd(interface)" |
275 | @@ -500,14 +510,14 @@ |
276 | <option value="" data-ng-hide="newInterface.type === 'alias'">Unconfigured</option> |
277 | </select> |
278 | </div> |
279 | - <div class="table__data table__column--14"> |
280 | + <div class="table__data table__column--21"> |
281 | <select class="table__input" name="link-mode" id="link-mode" |
282 | data-ng-model="newInterface.mode" |
283 | data-ng-disabled="isLinkModeDisabled(newInterface)" |
284 | data-ng-options="mode.mode as mode.text for mode in modes | filterLinkModes:newInterface"> |
285 | </select> |
286 | </div> |
287 | - <div class="table__data table_column--13"></div> |
288 | + <div class="table__data table_column--6"></div> |
289 | </div> |
290 | <div class="table__row table__dropdown-row"> |
291 | <div class="ng-hide" data-ng-show="isShowingInterfaceOptions()"> |
292 | |
293 | === modified file 'src/maasserver/tests/test_forms_interface.py' |
294 | --- src/maasserver/tests/test_forms_interface.py 2015-09-16 20:14:09 +0000 |
295 | +++ src/maasserver/tests/test_forms_interface.py 2015-10-31 23:55:40 +0000 |
296 | @@ -806,3 +806,58 @@ |
297 | "bond_lacp_rate": new_bond_lacp_rate, |
298 | "bond_xmit_hash_policy": new_bond_xmit_hash_policy, |
299 | }, interface.params) |
300 | + |
301 | + def test__edit_allows_zero_params(self): |
302 | + parent1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL) |
303 | + parent2 = factory.make_Interface( |
304 | + INTERFACE_TYPE.PHYSICAL, node=parent1.node) |
305 | + interface = factory.make_Interface( |
306 | + INTERFACE_TYPE.BOND, |
307 | + parents=[parent1, parent2]) |
308 | + bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
309 | + bond_miimon = random.randint(0, 1000) |
310 | + bond_downdelay = random.randint(0, 1000) |
311 | + bond_updelay = random.randint(0, 1000) |
312 | + bond_lacp_rate = factory.pick_choice(BOND_LACP_RATE_CHOICES) |
313 | + bond_xmit_hash_policy = factory.pick_choice( |
314 | + BOND_XMIT_HASH_POLICY_CHOICES) |
315 | + interface.params = { |
316 | + "bond_mode": bond_mode, |
317 | + "bond_miimon": bond_miimon, |
318 | + "bond_downdelay": bond_downdelay, |
319 | + "bond_updelay": bond_updelay, |
320 | + "bond_lacp_rate": bond_lacp_rate, |
321 | + "bond_xmit_hash_policy": bond_xmit_hash_policy, |
322 | + } |
323 | + interface.save() |
324 | + new_vlan = factory.make_VLAN(vid=33) |
325 | + new_name = factory.make_name() |
326 | + new_bond_mode = factory.pick_choice(BOND_MODE_CHOICES) |
327 | + new_bond_miimon = 0 |
328 | + new_bond_downdelay = 0 |
329 | + new_bond_updelay = 0 |
330 | + new_bond_lacp_rate = factory.pick_choice(BOND_LACP_RATE_CHOICES) |
331 | + new_bond_xmit_hash_policy = factory.pick_choice( |
332 | + BOND_XMIT_HASH_POLICY_CHOICES) |
333 | + form = BondInterfaceForm( |
334 | + instance=interface, |
335 | + data={ |
336 | + 'vlan': new_vlan.id, |
337 | + 'name': new_name, |
338 | + 'bond_mode': new_bond_mode, |
339 | + 'bond_miimon': new_bond_miimon, |
340 | + 'bond_downdelay': new_bond_downdelay, |
341 | + 'bond_updelay': new_bond_updelay, |
342 | + 'bond_lacp_rate': new_bond_lacp_rate, |
343 | + 'bond_xmit_hash_policy': new_bond_xmit_hash_policy, |
344 | + }) |
345 | + self.assertTrue(form.is_valid(), form.errors) |
346 | + interface = form.save() |
347 | + self.assertEquals({ |
348 | + "bond_mode": new_bond_mode, |
349 | + "bond_miimon": new_bond_miimon, |
350 | + "bond_downdelay": new_bond_downdelay, |
351 | + "bond_updelay": new_bond_updelay, |
352 | + "bond_lacp_rate": new_bond_lacp_rate, |
353 | + "bond_xmit_hash_policy": new_bond_xmit_hash_policy, |
354 | + }, interface.params) |
355 | |
356 | === modified file 'src/maasserver/websockets/handlers/node.py' |
357 | --- src/maasserver/websockets/handlers/node.py 2015-10-29 20:10:11 +0000 |
358 | +++ src/maasserver/websockets/handlers/node.py 2015-10-31 23:55:40 +0000 |
359 | @@ -498,7 +498,7 @@ |
360 | subnet = link.pop("subnet", None) |
361 | if subnet is not None: |
362 | link["subnet_id"] = subnet.id |
363 | - return { |
364 | + data = { |
365 | "id": interface.id, |
366 | "type": interface.type, |
367 | "name": interface.get_name(), |
368 | @@ -517,6 +517,21 @@ |
369 | "links": links, |
370 | } |
371 | |
372 | + # When the node is commissioning display the discovered IP address for |
373 | + # this interface. This will only be shown on interfaces that are |
374 | + # connected to a MAAS managed subnet. |
375 | + if obj.status == NODE_STATUS.COMMISSIONING: |
376 | + discovereds = interface.get_discovered() |
377 | + if discovereds is not None: |
378 | + for discovered in discovereds: |
379 | + # Replace the subnet object with the subnet_id. The client |
380 | + # will use this information to pull the subnet information |
381 | + # from the websocket. |
382 | + discovered["subnet_id"] = discovered.pop("subnet").id |
383 | + data["discovered"] = discovereds |
384 | + |
385 | + return data |
386 | + |
387 | def dehydrate_summary_output(self, obj, data): |
388 | """Dehydrate the machine summary output.""" |
389 | # Produce a "clean" composite details document. |
390 | |
391 | === modified file 'src/maasserver/websockets/handlers/tests/test_node.py' |
392 | --- src/maasserver/websockets/handlers/tests/test_node.py 2015-10-29 20:10:11 +0000 |
393 | +++ src/maasserver/websockets/handlers/tests/test_node.py 2015-10-31 23:55:40 +0000 |
394 | @@ -557,9 +557,9 @@ |
395 | filesystem.fstype in FILESYSTEM_FORMAT_TYPE_CHOICES_DICT), |
396 | }, handler.dehydrate_filesystem(filesystem)) |
397 | |
398 | - def test_dehydrate_interface(self): |
399 | + def test_dehydrate_interface_for_ready_node(self): |
400 | owner = factory.make_User() |
401 | - node = factory.make_Node(owner=owner) |
402 | + node = factory.make_Node(owner=owner, status=NODE_STATUS.READY) |
403 | handler = NodeHandler(owner, {}) |
404 | interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
405 | factory.make_StaticIPAddress( |
406 | @@ -587,6 +587,45 @@ |
407 | "links": expected_links, |
408 | }, handler.dehydrate_interface(interface, node)) |
409 | |
410 | + def test_dehydrate_interface_for_commissioning_node(self): |
411 | + owner = factory.make_User() |
412 | + node = factory.make_Node(owner=owner, status=NODE_STATUS.COMMISSIONING) |
413 | + handler = NodeHandler(owner, {}) |
414 | + interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL, node=node) |
415 | + factory.make_StaticIPAddress( |
416 | + alloc_type=IPADDRESS_TYPE.AUTO, ip="", |
417 | + subnet=factory.make_Subnet(), interface=interface) |
418 | + expected_links = interface.get_links() |
419 | + for link in expected_links: |
420 | + link["subnet_id"] = link.pop("subnet").id |
421 | + discovered_subnet = factory.make_Subnet() |
422 | + factory.make_StaticIPAddress( |
423 | + alloc_type=IPADDRESS_TYPE.DISCOVERED, |
424 | + ip=factory.pick_ip_in_network(discovered_subnet.get_ipnetwork()), |
425 | + subnet=discovered_subnet, interface=interface) |
426 | + expected_discovered = interface.get_discovered() |
427 | + for discovered in expected_discovered: |
428 | + discovered["subnet_id"] = discovered.pop("subnet").id |
429 | + self.assertEquals({ |
430 | + "id": interface.id, |
431 | + "type": interface.type, |
432 | + "name": interface.get_name(), |
433 | + "enabled": interface.is_enabled(), |
434 | + "is_boot": interface == node.boot_interface, |
435 | + "mac_address": "%s" % interface.mac_address, |
436 | + "vlan_id": interface.vlan_id, |
437 | + "parents": [ |
438 | + nic.id |
439 | + for nic in interface.parents.all() |
440 | + ], |
441 | + "children": [ |
442 | + nic.child.id |
443 | + for nic in interface.children_relationships.all() |
444 | + ], |
445 | + "links": expected_links, |
446 | + "discovered": expected_discovered, |
447 | + }, handler.dehydrate_interface(interface, node)) |
448 | + |
449 | def test_dehydrate_summary_output_returns_None(self): |
450 | owner = factory.make_User() |
451 | node = factory.make_Node(owner=owner) |
Here is an screenshot of what it looks like. This screenshot is a little bit older, as the subnet is also correct now in the branch.
http:// imgur.com/ f3ck2HN