Merge ~jsseidel/maas:jsseidel-load-nodes-examples-by-default into maas:master

Proposed by Spencer Seidel
Status: Merged
Approved by: Newell Jensen
Approved revision: 0c2b1dab0c5a4ef476666d1e11a041d776244d98
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~jsseidel/maas:jsseidel-load-nodes-examples-by-default
Merge into: maas:master
Diff against target: 3358 lines (+2970/-168)
4 files modified
src/maasserver/api/annotations.py (+31/-10)
src/maasserver/api/examples/nodes.json (+2605/-0)
src/maasserver/api/nodes.py (+308/-157)
src/maasserver/api/tests/test_annotations.py (+26/-1)
Reviewer Review Type Date Requested Status
Newell Jensen (community) Approve
MAAS Lander unittests Pending
Review via email: mp+359556@code.launchpad.net

Commit message

Added nodes api annotations, updated annotations to load nodes by default, added tests to make sure that nodes examples are loaded by default.

Description of the change

Updated annotations.py so that it always loads examples/nodes.json by default since other API operations like machines and devices inherit from nodes. Added a unit test to make sure that this is in fact being loaded by default. The unit test creates a operation URI unrelated to nodes (.../for-test/{foobar}) and then makes sure that an example specific to nodes is loaded for a key known to be in examples/nodes.json.

To post a comment you must log in.
bf2caf3... by Spencer Seidel

Formatted nodes examples correctly.

Revision history for this message
Newell Jensen (newell-jensen) wrote :

Looks good. Couple nits inline.

review: Approve
0c2b1da... by Spencer Seidel

Removed unneeded parens and changed confusing comment

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/annotations.py b/src/maasserver/api/annotations.py
2index 79da0f3..c8bac9f 100644
3--- a/src/maasserver/api/annotations.py
4+++ b/src/maasserver/api/annotations.py
5@@ -627,8 +627,30 @@ class APIDocstringParser:
6
7 return ""
8
9+ def _load_nodes_examples_dict(self):
10+ """Returns a dictionary containing 'nodes' examples data.
11+
12+ Since many API objects inherit from nodes (e.g. machines, devices) we
13+ always load nodes examples to prevent duplicating data.
14+
15+ If examples/nodes.json cannot be found, we warn, which will prevent
16+ the unit tests from completing normally, but we return an empty
17+ dictionary so the code can continue.
18+ """
19+ nodes_examples = {}
20+
21+ json_file = ("%s/examples/nodes.json" % os.path.dirname(__file__))
22+
23+ if not os.path.isfile(json_file):
24+ self._warn("examples/nodes.json not found.")
25+ else:
26+ with open(json_file, "r") as ex_db_file:
27+ nodes_examples = json.load(ex_db_file)
28+
29+ return nodes_examples
30+
31 def _get_examples_dict(self, uri):
32- """Returns a dictionary containing examples data or None
33+ """Returns a dictionary containing examples data
34
35 Given an operation string like "zone" or "zones", this function tries
36 to open and slurp in the JSON of a matching file in the api/examples
37@@ -638,15 +660,13 @@ class APIDocstringParser:
38 ... any JSON object ...
39 }
40
41- If no database is associated with the operation, the function
42- returns None.
43+ This function will always return at least nodes examples data.
44 """
45- examples = {}
46+ examples = self._load_nodes_examples_dict()
47
48 operation = self._get_operation_from_uri(uri)
49-
50- if operation == "":
51- return None
52+ if operation == "" or operation == "nodes" or operation == "node":
53+ return examples
54
55 # First, try the operation string as is:
56 json_file = ("%s/examples/%s.json" %
57@@ -658,11 +678,12 @@ class APIDocstringParser:
58 (os.path.dirname(__file__), operation))
59
60 if not os.path.isfile(json_file):
61- # Give up
62- return None
63+ # No examples found so return base set
64+ return examples
65
66 with open(json_file, "r") as ex_db_file:
67- examples = json.load(ex_db_file)
68+ operation_examples = json.load(ex_db_file)
69+ examples.update(operation_examples)
70
71 return examples
72
73diff --git a/src/maasserver/api/examples/nodes.json b/src/maasserver/api/examples/nodes.json
74new file mode 100644
75index 0000000..9ba7ecc
76--- /dev/null
77+++ b/src/maasserver/api/examples/nodes.json
78@@ -0,0 +1,2605 @@
79+{
80+ "read-node": {
81+ "boot_interface": {
82+ "system_id": "g8xyqs",
83+ "name": "eth-jJ5ZwN",
84+ "vlan": {
85+ "vid": 0,
86+ "mtu": 1500,
87+ "dhcp_on": false,
88+ "external_dhcp": null,
89+ "relay_vlan": null,
90+ "name": "untagged",
91+ "fabric_id": 2,
92+ "id": 5005,
93+ "secondary_rack": null,
94+ "space": "undefined",
95+ "primary_rack": null,
96+ "fabric": "fabric-2",
97+ "resource_uri": "/MAAS/api/2.0/vlans/5005/"
98+ },
99+ "vendor": null,
100+ "enabled": true,
101+ "children": [
102+ "bond-VpkNvO"
103+ ],
104+ "discovered": null,
105+ "id": 112,
106+ "params": "",
107+ "type": "physical",
108+ "firmware_version": null,
109+ "mac_address": "3d:fd:40:ef:70:e8",
110+ "parents": [],
111+ "tags": [
112+ "tag-M21kgB",
113+ "tag-CpnGzQ",
114+ "tag-Wgd7Eu"
115+ ],
116+ "links": [],
117+ "effective_mtu": 1500,
118+ "product": null,
119+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/interfaces/112/"
120+ },
121+ "memory": 8192,
122+ "tag_names": [],
123+ "current_installation_result_id": null,
124+ "fqdn": "causal-quagga.maas",
125+ "disable_ipv4": false,
126+ "distro_series": "",
127+ "ip_addresses": [],
128+ "pool": {
129+ "name": "default",
130+ "description": "Default pool",
131+ "id": 0,
132+ "resource_uri": "/MAAS/api/2.0/resourcepool/0/"
133+ },
134+ "node_type": 0,
135+ "min_hwe_kernel": null,
136+ "commissioning_status_name": "Passed",
137+ "domain": {
138+ "authoritative": true,
139+ "ttl": null,
140+ "name": "maas",
141+ "resource_record_count": 0,
142+ "id": 0,
143+ "is_default": true,
144+ "resource_uri": "/MAAS/api/2.0/domains/0/"
145+ },
146+ "boot_disk": {
147+ "firmware_version": "firmware_version-tnhqNO",
148+ "partitions": [],
149+ "system_id": "g8xyqs",
150+ "name": "name-rcEM1G",
151+ "id_path": null,
152+ "block_size": 512,
153+ "model": "model-RAViIE",
154+ "available_size": 2250362368,
155+ "id": 75,
156+ "filesystem": null,
157+ "size": 2250362368,
158+ "type": "physical",
159+ "used_size": 0,
160+ "partition_table_type": null,
161+ "serial": "serial-qlOilQ",
162+ "path": "/dev/disk/by-dname/name-rcEM1G",
163+ "tags": [
164+ "tag-OKbSzN",
165+ "tag-IExJAF",
166+ "tag-p2t26t"
167+ ],
168+ "storage_pool": "pool_id-ry2OnY",
169+ "uuid": null,
170+ "used_for": "Unused",
171+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/blockdevices/75/"
172+ },
173+ "system_id": "g8xyqs",
174+ "zone": {
175+ "name": "zone-north",
176+ "description": "xsMaq90fRE",
177+ "id": 2,
178+ "resource_uri": "/MAAS/api/2.0/zones/zone-north/"
179+ },
180+ "blockdevice_set": [
181+ {
182+ "id_path": null,
183+ "size": 2250362368,
184+ "block_size": 512,
185+ "tags": [
186+ "tag-OKbSzN",
187+ "tag-IExJAF",
188+ "tag-p2t26t"
189+ ],
190+ "partitions": [],
191+ "system_id": "g8xyqs",
192+ "name": "name-rcEM1G",
193+ "model": "model-RAViIE",
194+ "available_size": 2250362368,
195+ "id": 75,
196+ "filesystem": null,
197+ "type": "physical",
198+ "used_size": 0,
199+ "partition_table_type": null,
200+ "serial": "serial-qlOilQ",
201+ "path": "/dev/disk/by-dname/name-rcEM1G",
202+ "storage_pool": "pool_id-ry2OnY",
203+ "uuid": null,
204+ "used_for": "Unused",
205+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/blockdevices/75/"
206+ },
207+ {
208+ "id_path": null,
209+ "size": 1443074048,
210+ "block_size": 4096,
211+ "tags": [
212+ "tag-sgRDAF",
213+ "tag-kytOd1",
214+ "tag-acWXTG"
215+ ],
216+ "partitions": [],
217+ "system_id": "g8xyqs",
218+ "name": "name-a5uEVy",
219+ "model": "model-0mBTZN",
220+ "available_size": 1443074048,
221+ "id": 76,
222+ "filesystem": null,
223+ "type": "physical",
224+ "used_size": 0,
225+ "partition_table_type": null,
226+ "serial": "serial-fbDnkc",
227+ "path": "/dev/disk/by-dname/name-a5uEVy",
228+ "storage_pool": "pool_id-aMRZUu",
229+ "uuid": null,
230+ "used_for": "Unused",
231+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/blockdevices/76/"
232+ }
233+ ],
234+ "current_commissioning_result_id": 198,
235+ "cpu_test_status": 2,
236+ "address_ttl": null,
237+ "cache_sets": [],
238+ "storage": 3693.436416,
239+ "node_type_name": "Machine",
240+ "hardware_info": {
241+ "system_vendor": "Unknown",
242+ "system_product": "Unknown",
243+ "system_version": "Unknown",
244+ "system_serial": "Unknown",
245+ "cpu_model": "Unknown",
246+ "mainboard_vendor": "Unknown",
247+ "mainboard_product": "Unknown",
248+ "mainboard_firmware_version": "Unknown",
249+ "mainboard_firmware_date": "Unknown"
250+ },
251+ "cpu_count": 7,
252+ "storage_test_status_name": "Passed",
253+ "owner": "user2",
254+ "status": 20,
255+ "volume_groups": [],
256+ "hwe_kernel": null,
257+ "netboot": true,
258+ "current_testing_result_id": 199,
259+ "commissioning_status": 2,
260+ "testing_status_name": "Passed",
261+ "architecture": "i386/generic",
262+ "locked": false,
263+ "power_state": "error",
264+ "memory_test_status_name": "Passed",
265+ "power_type": "virsh",
266+ "interface_set": [
267+ {
268+ "system_id": "g8xyqs",
269+ "name": "eth-jJ5ZwN",
270+ "vlan": {
271+ "vid": 0,
272+ "mtu": 1500,
273+ "dhcp_on": false,
274+ "external_dhcp": null,
275+ "relay_vlan": null,
276+ "name": "untagged",
277+ "fabric_id": 2,
278+ "id": 5005,
279+ "secondary_rack": null,
280+ "space": "undefined",
281+ "primary_rack": null,
282+ "fabric": "fabric-2",
283+ "resource_uri": "/MAAS/api/2.0/vlans/5005/"
284+ },
285+ "vendor": null,
286+ "enabled": true,
287+ "children": [
288+ "bond-VpkNvO"
289+ ],
290+ "discovered": null,
291+ "id": 112,
292+ "params": "",
293+ "type": "physical",
294+ "firmware_version": null,
295+ "mac_address": "3d:fd:40:ef:70:e8",
296+ "parents": [],
297+ "tags": [
298+ "tag-M21kgB",
299+ "tag-CpnGzQ",
300+ "tag-Wgd7Eu"
301+ ],
302+ "links": [],
303+ "effective_mtu": 1500,
304+ "product": null,
305+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/interfaces/112/"
306+ },
307+ {
308+ "system_id": "g8xyqs",
309+ "name": "eth-ex07mq",
310+ "vlan": {
311+ "vid": 0,
312+ "mtu": 1500,
313+ "dhcp_on": false,
314+ "external_dhcp": null,
315+ "relay_vlan": null,
316+ "name": "untagged",
317+ "fabric_id": 2,
318+ "id": 5005,
319+ "secondary_rack": null,
320+ "space": "undefined",
321+ "primary_rack": null,
322+ "fabric": "fabric-2",
323+ "resource_uri": "/MAAS/api/2.0/vlans/5005/"
324+ },
325+ "vendor": null,
326+ "enabled": true,
327+ "children": [
328+ "bond-VpkNvO"
329+ ],
330+ "discovered": null,
331+ "id": 113,
332+ "params": "",
333+ "type": "physical",
334+ "firmware_version": null,
335+ "mac_address": "8f:75:69:58:26:47",
336+ "parents": [],
337+ "tags": [
338+ "tag-ymen6c",
339+ "tag-oKQ7iK",
340+ "tag-yQLBgJ"
341+ ],
342+ "links": [],
343+ "effective_mtu": 1500,
344+ "product": null,
345+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/interfaces/113/"
346+ },
347+ {
348+ "system_id": "g8xyqs",
349+ "name": "eth-CE1j2X",
350+ "vlan": {
351+ "vid": 0,
352+ "mtu": 1500,
353+ "dhcp_on": false,
354+ "external_dhcp": null,
355+ "relay_vlan": null,
356+ "name": "untagged",
357+ "fabric_id": 2,
358+ "id": 5005,
359+ "secondary_rack": null,
360+ "space": "undefined",
361+ "primary_rack": null,
362+ "fabric": "fabric-2",
363+ "resource_uri": "/MAAS/api/2.0/vlans/5005/"
364+ },
365+ "vendor": null,
366+ "enabled": true,
367+ "children": [
368+ "bond-VpkNvO"
369+ ],
370+ "discovered": null,
371+ "id": 114,
372+ "params": "",
373+ "type": "physical",
374+ "firmware_version": null,
375+ "mac_address": "b0:5e:ed:8d:d8:36",
376+ "parents": [],
377+ "tags": [
378+ "tag-LJPUwT",
379+ "tag-U5zGn3",
380+ "tag-dHGEeD"
381+ ],
382+ "links": [],
383+ "effective_mtu": 1500,
384+ "product": null,
385+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/interfaces/114/"
386+ },
387+ {
388+ "system_id": "g8xyqs",
389+ "name": "bond-VpkNvO",
390+ "vlan": {
391+ "vid": 0,
392+ "mtu": 1500,
393+ "dhcp_on": false,
394+ "external_dhcp": null,
395+ "relay_vlan": null,
396+ "name": "untagged",
397+ "fabric_id": 2,
398+ "id": 5005,
399+ "secondary_rack": null,
400+ "space": "undefined",
401+ "primary_rack": null,
402+ "fabric": "fabric-2",
403+ "resource_uri": "/MAAS/api/2.0/vlans/5005/"
404+ },
405+ "vendor": null,
406+ "enabled": true,
407+ "children": [],
408+ "discovered": null,
409+ "id": 115,
410+ "params": "",
411+ "type": "bond",
412+ "firmware_version": null,
413+ "mac_address": "0a:87:3f:94:0e:68",
414+ "parents": [
415+ "eth-CE1j2X",
416+ "eth-ex07mq",
417+ "eth-jJ5ZwN"
418+ ],
419+ "tags": [
420+ "tag-HwhC7n",
421+ "tag-WHGBJc",
422+ "tag-yY8Ap5"
423+ ],
424+ "links": [],
425+ "effective_mtu": 1500,
426+ "product": null,
427+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/interfaces/115/"
428+ }
429+ ],
430+ "owner_data": {},
431+ "bcaches": [],
432+ "hostname": "causal-quagga",
433+ "raids": [],
434+ "other_test_status": 2,
435+ "status_action": "action-BqENyW",
436+ "special_filesystems": [],
437+ "physicalblockdevice_set": [
438+ {
439+ "firmware_version": "firmware_version-tnhqNO",
440+ "partitions": [],
441+ "system_id": "g8xyqs",
442+ "name": "name-rcEM1G",
443+ "id_path": null,
444+ "block_size": 512,
445+ "model": "model-RAViIE",
446+ "available_size": 2250362368,
447+ "id": 75,
448+ "filesystem": null,
449+ "size": 2250362368,
450+ "type": "physical",
451+ "used_size": 0,
452+ "partition_table_type": null,
453+ "serial": "serial-qlOilQ",
454+ "path": "/dev/disk/by-dname/name-rcEM1G",
455+ "tags": [
456+ "tag-OKbSzN",
457+ "tag-IExJAF",
458+ "tag-p2t26t"
459+ ],
460+ "storage_pool": "pool_id-ry2OnY",
461+ "uuid": null,
462+ "used_for": "Unused",
463+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/blockdevices/75/"
464+ },
465+ {
466+ "firmware_version": "firmware_version-UW8ucD",
467+ "partitions": [],
468+ "system_id": "g8xyqs",
469+ "name": "name-a5uEVy",
470+ "id_path": null,
471+ "block_size": 4096,
472+ "model": "model-0mBTZN",
473+ "available_size": 1443074048,
474+ "id": 76,
475+ "filesystem": null,
476+ "size": 1443074048,
477+ "type": "physical",
478+ "used_size": 0,
479+ "partition_table_type": null,
480+ "serial": "serial-fbDnkc",
481+ "path": "/dev/disk/by-dname/name-a5uEVy",
482+ "tags": [
483+ "tag-sgRDAF",
484+ "tag-kytOd1",
485+ "tag-acWXTG"
486+ ],
487+ "storage_pool": "pool_id-aMRZUu",
488+ "uuid": null,
489+ "used_for": "Unused",
490+ "resource_uri": "/MAAS/api/2.0/nodes/g8xyqs/blockdevices/76/"
491+ }
492+ ],
493+ "iscsiblockdevice_set": [],
494+ "testing_status": 2,
495+ "default_gateways": {
496+ "ipv4": {
497+ "gateway_ip": null,
498+ "link_id": null
499+ },
500+ "ipv6": {
501+ "gateway_ip": null,
502+ "link_id": null
503+ }
504+ },
505+ "storage_test_status": 2,
506+ "pod": {
507+ "id": 5,
508+ "name": "sacred-hen",
509+ "resource_uri": "/MAAS/api/2.0/pods/5/"
510+ },
511+ "swap_size": null,
512+ "status_message": "desc-eqGqfo",
513+ "status_name": "Failed to exit rescue mode",
514+ "osystem": "",
515+ "cpu_test_status_name": "Passed",
516+ "memory_test_status": 2,
517+ "other_test_status_name": "Passed",
518+ "virtualblockdevice_set": [],
519+ "cpu_speed": 0,
520+ "resource_uri": "/MAAS/api/2.0/machines/g8xyqs/"
521+ },
522+ "details": {
523+ "lldp": {
524+ "$binary": "cjBZSWw2S1ZkRA==",
525+ "$type": "00"
526+ },
527+ "lshw": {
528+ "$binary": "Nkd5MzRLYjBkTQ==",
529+ "$type": "00"
530+ }
531+ },
532+ "read-visible-nodes": [
533+ {
534+ "commissioning_status": 2,
535+ "version": "2.5.0~beta3-7325-g1425f6d4c-0ubuntu1~18.04.1",
536+ "node_type_name": "Region and rack controller",
537+ "ip_addresses": [
538+ "10.55.32.135",
539+ "192.168.122.1"
540+ ],
541+ "storage_test_status": -1,
542+ "cpu_count": 4,
543+ "hostname": "mymaas",
544+ "domain": {
545+ "authoritative": true,
546+ "ttl": null,
547+ "id": 0,
548+ "name": "maas",
549+ "resource_record_count": 23,
550+ "is_default": true,
551+ "resource_uri": "/MAAS/api/2.0/domains/0/"
552+ },
553+ "swap_size": null,
554+ "power_type": "",
555+ "memory": 8192,
556+ "current_testing_result_id": null,
557+ "osystem": "ubuntu",
558+ "node_type": 4,
559+ "service_set": [
560+ {
561+ "name": "proxy",
562+ "status": "running",
563+ "status_info": ""
564+ },
565+ {
566+ "name": "bind9",
567+ "status": "running",
568+ "status_info": ""
569+ },
570+ {
571+ "name": "ntp_region",
572+ "status": "running",
573+ "status_info": ""
574+ },
575+ {
576+ "name": "regiond",
577+ "status": "running",
578+ "status_info": ""
579+ },
580+ {
581+ "name": "syslog_region",
582+ "status": "running",
583+ "status_info": ""
584+ },
585+ {
586+ "name": "ntp_rack",
587+ "status": "unknown",
588+ "status_info": "managed by the region"
589+ },
590+ {
591+ "name": "dhcpd",
592+ "status": "running",
593+ "status_info": ""
594+ },
595+ {
596+ "name": "tftp",
597+ "status": "running",
598+ "status_info": ""
599+ },
600+ {
601+ "name": "dns_rack",
602+ "status": "unknown",
603+ "status_info": "managed by the region"
604+ },
605+ {
606+ "name": "http",
607+ "status": "running",
608+ "status_info": ""
609+ },
610+ {
611+ "name": "proxy_rack",
612+ "status": "unknown",
613+ "status_info": "managed by the region"
614+ },
615+ {
616+ "name": "syslog_rack",
617+ "status": "unknown",
618+ "status_info": "managed by the region"
619+ },
620+ {
621+ "name": "dhcpd6",
622+ "status": "off",
623+ "status_info": ""
624+ },
625+ {
626+ "name": "rackd",
627+ "status": "running",
628+ "status_info": ""
629+ }
630+ ],
631+ "other_test_status": -1,
632+ "testing_status": -1,
633+ "zone": {
634+ "name": "default",
635+ "description": "",
636+ "id": 1,
637+ "resource_uri": "/MAAS/api/2.0/zones/default/"
638+ },
639+ "status_action": "",
640+ "commissioning_status_name": "Passed",
641+ "interface_set": [
642+ {
643+ "vlan": {
644+ "vid": 0,
645+ "mtu": 1500,
646+ "dhcp_on": true,
647+ "external_dhcp": null,
648+ "relay_vlan": null,
649+ "id": 5001,
650+ "name": "untagged",
651+ "fabric_id": 0,
652+ "secondary_rack": null,
653+ "space": "undefined",
654+ "fabric": "fabric-0",
655+ "primary_rack": "6gsym8",
656+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
657+ },
658+ "mac_address": "fa:16:3e:b8:af:ff",
659+ "tags": [],
660+ "params": "",
661+ "id": 1,
662+ "discovered": null,
663+ "product": "OpenStack Nova",
664+ "parents": [],
665+ "type": "physical",
666+ "name": "ens3",
667+ "enabled": true,
668+ "effective_mtu": 1500,
669+ "vendor": "OpenStack Foundation",
670+ "system_id": "6gsym8",
671+ "children": [],
672+ "firmware_version": null,
673+ "links": [
674+ {
675+ "id": 1,
676+ "mode": "static",
677+ "ip_address": "10.55.32.135",
678+ "subnet": {
679+ "name": "10.55.32.0/20",
680+ "vlan": {
681+ "vid": 0,
682+ "mtu": 1500,
683+ "dhcp_on": true,
684+ "external_dhcp": null,
685+ "relay_vlan": null,
686+ "id": 5001,
687+ "name": "untagged",
688+ "fabric_id": 0,
689+ "secondary_rack": null,
690+ "space": "undefined",
691+ "fabric": "fabric-0",
692+ "primary_rack": "6gsym8",
693+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
694+ },
695+ "cidr": "10.55.32.0/20",
696+ "rdns_mode": 2,
697+ "gateway_ip": "10.55.32.1",
698+ "dns_servers": [],
699+ "allow_dns": true,
700+ "allow_proxy": true,
701+ "active_discovery": false,
702+ "managed": true,
703+ "id": 1,
704+ "space": "undefined",
705+ "resource_uri": "/MAAS/api/2.0/subnets/1/"
706+ }
707+ }
708+ ],
709+ "resource_uri": "/MAAS/api/2.0/nodes/6gsym8/interfaces/1/"
710+ },
711+ {
712+ "vlan": {
713+ "vid": 0,
714+ "mtu": 1500,
715+ "dhcp_on": false,
716+ "external_dhcp": null,
717+ "relay_vlan": null,
718+ "id": 5002,
719+ "name": "untagged",
720+ "fabric_id": 1,
721+ "secondary_rack": null,
722+ "space": "undefined",
723+ "fabric": "fabric-1",
724+ "primary_rack": null,
725+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
726+ },
727+ "mac_address": "52:54:00:09:88:41",
728+ "tags": [],
729+ "params": "",
730+ "id": 17,
731+ "discovered": null,
732+ "product": null,
733+ "parents": [],
734+ "type": "bridge",
735+ "name": "virbr0",
736+ "enabled": true,
737+ "effective_mtu": 1500,
738+ "vendor": null,
739+ "system_id": "6gsym8",
740+ "children": [],
741+ "firmware_version": null,
742+ "links": [
743+ {
744+ "id": 17,
745+ "mode": "static",
746+ "ip_address": "192.168.122.1",
747+ "subnet": {
748+ "name": "192.168.122.0/24",
749+ "vlan": {
750+ "vid": 0,
751+ "mtu": 1500,
752+ "dhcp_on": false,
753+ "external_dhcp": null,
754+ "relay_vlan": null,
755+ "id": 5002,
756+ "name": "untagged",
757+ "fabric_id": 1,
758+ "secondary_rack": null,
759+ "space": "undefined",
760+ "fabric": "fabric-1",
761+ "primary_rack": null,
762+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
763+ },
764+ "cidr": "192.168.122.0/24",
765+ "rdns_mode": 2,
766+ "gateway_ip": null,
767+ "dns_servers": [],
768+ "allow_dns": true,
769+ "allow_proxy": true,
770+ "active_discovery": false,
771+ "managed": true,
772+ "id": 2,
773+ "space": "undefined",
774+ "resource_uri": "/MAAS/api/2.0/subnets/2/"
775+ }
776+ }
777+ ],
778+ "resource_uri": "/MAAS/api/2.0/nodes/6gsym8/interfaces/17/"
779+ }
780+ ],
781+ "cpu_speed": 2400,
782+ "testing_status_name": "Unknown",
783+ "tag_names": [
784+ "virtual"
785+ ],
786+ "current_commissioning_result_id": 1,
787+ "system_id": "6gsym8",
788+ "distro_series": "bionic",
789+ "cpu_test_status": -1,
790+ "memory_test_status_name": "Unknown",
791+ "hardware_info": {
792+ "system_vendor": "OpenStack Foundation",
793+ "system_product": "OpenStack Nova",
794+ "system_version": "2013.2.3",
795+ "system_serial": "33313934-3432-5a43-4339-343532355a35",
796+ "cpu_model": "Intel Core i7 9xx (Nehalem Class Core i7)",
797+ "mainboard_vendor": "Unknown",
798+ "mainboard_product": "Unknown",
799+ "mainboard_firmware_version": "Bochs",
800+ "mainboard_firmware_date": "01/01/2011"
801+ },
802+ "other_test_status_name": "Unknown",
803+ "fqdn": "mymaas.maas",
804+ "power_state": "unknown",
805+ "memory_test_status": -1,
806+ "current_installation_result_id": null,
807+ "storage_test_status_name": "Unknown",
808+ "architecture": "amd64/generic",
809+ "cpu_test_status_name": "Unknown",
810+ "resource_uri": "/MAAS/api/2.0/rackcontrollers/6gsym8/"
811+ }
812+ ],
813+ "set-owner-data": {
814+ "owner_data": {
815+ "somekey": "somevalue"
816+ },
817+ "cpu_speed": 0,
818+ "boot_interface": {
819+ "system_id": "q46awd",
820+ "effective_mtu": 1500,
821+ "product": null,
822+ "type": "physical",
823+ "mac_address": "fc:5f:a6:d0:30:97",
824+ "enabled": true,
825+ "params": "",
826+ "vlan": {
827+ "vid": 0,
828+ "mtu": 1500,
829+ "dhcp_on": false,
830+ "external_dhcp": null,
831+ "relay_vlan": null,
832+ "secondary_rack": null,
833+ "primary_rack": null,
834+ "name": "untagged",
835+ "fabric_id": 0,
836+ "space": "management",
837+ "id": 5001,
838+ "fabric": "fabric-0",
839+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
840+ },
841+ "children": [],
842+ "name": "eth-tlHn9H",
843+ "vendor": null,
844+ "firmware_version": null,
845+ "parents": [],
846+ "id": 100,
847+ "tags": [
848+ "tag-Krwbm6",
849+ "tag-6Ov2DQ",
850+ "tag-ZIbKlm"
851+ ],
852+ "links": [
853+ {
854+ "id": 45,
855+ "mode": "auto",
856+ "subnet": {
857+ "name": "name-rLI3eq",
858+ "vlan": {
859+ "vid": 0,
860+ "mtu": 1500,
861+ "dhcp_on": false,
862+ "external_dhcp": null,
863+ "relay_vlan": null,
864+ "secondary_rack": null,
865+ "primary_rack": null,
866+ "name": "untagged",
867+ "fabric_id": 0,
868+ "space": "management",
869+ "id": 5001,
870+ "fabric": "fabric-0",
871+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
872+ },
873+ "cidr": "172.16.1.0/24",
874+ "rdns_mode": 2,
875+ "gateway_ip": "172.16.1.1",
876+ "dns_servers": [
877+ "fd89:8724:81f1:5512:557f:99c3:6967:8d63"
878+ ],
879+ "allow_dns": true,
880+ "allow_proxy": true,
881+ "active_discovery": false,
882+ "managed": true,
883+ "space": "management",
884+ "id": 1,
885+ "resource_uri": "/MAAS/api/2.0/subnets/1/"
886+ }
887+ }
888+ ],
889+ "discovered": null,
890+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/interfaces/100/"
891+ },
892+ "swap_size": null,
893+ "status": 17,
894+ "zone": {
895+ "name": "zone-Llc45k",
896+ "description": "LirDm9tBHA",
897+ "id": 6,
898+ "resource_uri": "/MAAS/api/2.0/zones/zone-Llc45k/"
899+ },
900+ "other_test_status": 3,
901+ "virtualblockdevice_set": [],
902+ "disable_ipv4": false,
903+ "power_type": "manual",
904+ "pool": {
905+ "name": "default",
906+ "description": "Default pool",
907+ "id": 0,
908+ "resource_uri": "/MAAS/api/2.0/resourcepool/0/"
909+ },
910+ "locked": false,
911+ "system_id": "q46awd",
912+ "boot_disk": {
913+ "firmware_version": "firmware_version-8leXpL",
914+ "system_id": "q46awd",
915+ "type": "physical",
916+ "used_size": 0,
917+ "used_for": "Unused",
918+ "partitions": [],
919+ "uuid": null,
920+ "name": "name-w1MxuB",
921+ "id_path": null,
922+ "tags": [
923+ "tag-iF4AD7",
924+ "tag-BtgV26",
925+ "tag-wZF5A6"
926+ ],
927+ "partition_table_type": null,
928+ "size": 3770708992,
929+ "storage_pool": null,
930+ "path": "/dev/disk/by-dname/name-w1MxuB",
931+ "serial": "serial-u1CbU0",
932+ "block_size": 1024,
933+ "filesystem": null,
934+ "id": 66,
935+ "model": "model-A6yydP",
936+ "available_size": 3770708992,
937+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/66/"
938+ },
939+ "special_filesystems": [],
940+ "current_testing_result_id": 171,
941+ "cache_sets": [],
942+ "memory_test_status_name": "Failed",
943+ "storage_test_status_name": "Failed",
944+ "node_type_name": "Machine",
945+ "architecture": "i386/generic",
946+ "commissioning_status_name": "Passed",
947+ "distro_series": "",
948+ "interface_set": [
949+ {
950+ "system_id": "q46awd",
951+ "effective_mtu": 1500,
952+ "product": null,
953+ "type": "physical",
954+ "mac_address": "fc:5f:a6:d0:30:97",
955+ "enabled": true,
956+ "params": "",
957+ "vlan": {
958+ "vid": 0,
959+ "mtu": 1500,
960+ "dhcp_on": false,
961+ "external_dhcp": null,
962+ "relay_vlan": null,
963+ "secondary_rack": null,
964+ "primary_rack": null,
965+ "name": "untagged",
966+ "fabric_id": 0,
967+ "space": "management",
968+ "id": 5001,
969+ "fabric": "fabric-0",
970+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
971+ },
972+ "children": [],
973+ "name": "eth-tlHn9H",
974+ "vendor": null,
975+ "firmware_version": null,
976+ "parents": [],
977+ "id": 100,
978+ "tags": [
979+ "tag-Krwbm6",
980+ "tag-6Ov2DQ",
981+ "tag-ZIbKlm"
982+ ],
983+ "links": [
984+ {
985+ "id": 45,
986+ "mode": "auto",
987+ "subnet": {
988+ "name": "name-rLI3eq",
989+ "vlan": {
990+ "vid": 0,
991+ "mtu": 1500,
992+ "dhcp_on": false,
993+ "external_dhcp": null,
994+ "relay_vlan": null,
995+ "secondary_rack": null,
996+ "primary_rack": null,
997+ "name": "untagged",
998+ "fabric_id": 0,
999+ "space": "management",
1000+ "id": 5001,
1001+ "fabric": "fabric-0",
1002+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
1003+ },
1004+ "cidr": "172.16.1.0/24",
1005+ "rdns_mode": 2,
1006+ "gateway_ip": "172.16.1.1",
1007+ "dns_servers": [
1008+ "fd89:8724:81f1:5512:557f:99c3:6967:8d63"
1009+ ],
1010+ "allow_dns": true,
1011+ "allow_proxy": true,
1012+ "active_discovery": false,
1013+ "managed": true,
1014+ "space": "management",
1015+ "id": 1,
1016+ "resource_uri": "/MAAS/api/2.0/subnets/1/"
1017+ }
1018+ }
1019+ ],
1020+ "discovered": null,
1021+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/interfaces/100/"
1022+ },
1023+ {
1024+ "system_id": "q46awd",
1025+ "effective_mtu": 1500,
1026+ "product": null,
1027+ "type": "physical",
1028+ "mac_address": "37:96:81:86:7d:26",
1029+ "enabled": true,
1030+ "params": "",
1031+ "vlan": {
1032+ "vid": 0,
1033+ "mtu": 1500,
1034+ "dhcp_on": false,
1035+ "external_dhcp": null,
1036+ "relay_vlan": null,
1037+ "secondary_rack": null,
1038+ "primary_rack": null,
1039+ "name": "untagged",
1040+ "fabric_id": 0,
1041+ "space": "management",
1042+ "id": 5001,
1043+ "fabric": "fabric-0",
1044+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
1045+ },
1046+ "children": [],
1047+ "name": "eth-uHmeXv",
1048+ "vendor": null,
1049+ "firmware_version": null,
1050+ "parents": [],
1051+ "id": 101,
1052+ "tags": [
1053+ "tag-GBBGJm",
1054+ "tag-PorMko",
1055+ "tag-6ZtyQZ"
1056+ ],
1057+ "links": [
1058+ {
1059+ "id": 46,
1060+ "mode": "auto",
1061+ "subnet": {
1062+ "name": "name-rLI3eq",
1063+ "vlan": {
1064+ "vid": 0,
1065+ "mtu": 1500,
1066+ "dhcp_on": false,
1067+ "external_dhcp": null,
1068+ "relay_vlan": null,
1069+ "secondary_rack": null,
1070+ "primary_rack": null,
1071+ "name": "untagged",
1072+ "fabric_id": 0,
1073+ "space": "management",
1074+ "id": 5001,
1075+ "fabric": "fabric-0",
1076+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
1077+ },
1078+ "cidr": "172.16.1.0/24",
1079+ "rdns_mode": 2,
1080+ "gateway_ip": "172.16.1.1",
1081+ "dns_servers": [
1082+ "fd89:8724:81f1:5512:557f:99c3:6967:8d63"
1083+ ],
1084+ "allow_dns": true,
1085+ "allow_proxy": true,
1086+ "active_discovery": false,
1087+ "managed": true,
1088+ "space": "management",
1089+ "id": 1,
1090+ "resource_uri": "/MAAS/api/2.0/subnets/1/"
1091+ }
1092+ }
1093+ ],
1094+ "discovered": null,
1095+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/interfaces/101/"
1096+ },
1097+ {
1098+ "system_id": "q46awd",
1099+ "effective_mtu": 1500,
1100+ "product": null,
1101+ "type": "physical",
1102+ "mac_address": "ec:03:50:cc:92:e7",
1103+ "enabled": true,
1104+ "params": "",
1105+ "vlan": {
1106+ "vid": 0,
1107+ "mtu": 1500,
1108+ "dhcp_on": false,
1109+ "external_dhcp": null,
1110+ "relay_vlan": null,
1111+ "secondary_rack": null,
1112+ "primary_rack": null,
1113+ "name": "untagged",
1114+ "fabric_id": 0,
1115+ "space": "management",
1116+ "id": 5001,
1117+ "fabric": "fabric-0",
1118+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
1119+ },
1120+ "children": [],
1121+ "name": "eth-LCuSY9",
1122+ "vendor": null,
1123+ "firmware_version": null,
1124+ "parents": [],
1125+ "id": 102,
1126+ "tags": [
1127+ "tag-OB7Urg",
1128+ "tag-KI8wUy",
1129+ "tag-2ggdxa"
1130+ ],
1131+ "links": [
1132+ {
1133+ "id": 47,
1134+ "mode": "static",
1135+ "ip_address": "172.16.1.252",
1136+ "subnet": {
1137+ "name": "name-rLI3eq",
1138+ "vlan": {
1139+ "vid": 0,
1140+ "mtu": 1500,
1141+ "dhcp_on": false,
1142+ "external_dhcp": null,
1143+ "relay_vlan": null,
1144+ "secondary_rack": null,
1145+ "primary_rack": null,
1146+ "name": "untagged",
1147+ "fabric_id": 0,
1148+ "space": "management",
1149+ "id": 5001,
1150+ "fabric": "fabric-0",
1151+ "resource_uri": "/MAAS/api/2.0/vlans/5001/"
1152+ },
1153+ "cidr": "172.16.1.0/24",
1154+ "rdns_mode": 2,
1155+ "gateway_ip": "172.16.1.1",
1156+ "dns_servers": [
1157+ "fd89:8724:81f1:5512:557f:99c3:6967:8d63"
1158+ ],
1159+ "allow_dns": true,
1160+ "allow_proxy": true,
1161+ "active_discovery": false,
1162+ "managed": true,
1163+ "space": "management",
1164+ "id": 1,
1165+ "resource_uri": "/MAAS/api/2.0/subnets/1/"
1166+ }
1167+ }
1168+ ],
1169+ "discovered": null,
1170+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/interfaces/102/"
1171+ }
1172+ ],
1173+ "storage_test_status": 3,
1174+ "testing_status_name": "Failed",
1175+ "osystem": "",
1176+ "default_gateways": {
1177+ "ipv4": {
1178+ "gateway_ip": "172.16.1.1",
1179+ "link_id": null
1180+ },
1181+ "ipv6": {
1182+ "gateway_ip": null,
1183+ "link_id": null
1184+ }
1185+ },
1186+ "physicalblockdevice_set": [
1187+ {
1188+ "firmware_version": "firmware_version-8leXpL",
1189+ "system_id": "q46awd",
1190+ "type": "physical",
1191+ "used_size": 0,
1192+ "used_for": "Unused",
1193+ "partitions": [],
1194+ "uuid": null,
1195+ "name": "name-w1MxuB",
1196+ "id_path": null,
1197+ "tags": [
1198+ "tag-iF4AD7",
1199+ "tag-BtgV26",
1200+ "tag-wZF5A6"
1201+ ],
1202+ "partition_table_type": null,
1203+ "size": 3770708992,
1204+ "storage_pool": null,
1205+ "path": "/dev/disk/by-dname/name-w1MxuB",
1206+ "serial": "serial-u1CbU0",
1207+ "block_size": 1024,
1208+ "filesystem": null,
1209+ "id": 66,
1210+ "model": "model-A6yydP",
1211+ "available_size": 3770708992,
1212+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/66/"
1213+ },
1214+ {
1215+ "firmware_version": "firmware_version-fE2JVD",
1216+ "system_id": "q46awd",
1217+ "type": "physical",
1218+ "used_size": 0,
1219+ "used_for": "Unused",
1220+ "partitions": [],
1221+ "uuid": null,
1222+ "name": "name-8Ows7O",
1223+ "id_path": null,
1224+ "tags": [
1225+ "tag-ItoUN0",
1226+ "tag-MM2fGY",
1227+ "tag-oe8y1B"
1228+ ],
1229+ "partition_table_type": null,
1230+ "size": 3681153024,
1231+ "storage_pool": null,
1232+ "path": "/dev/disk/by-dname/name-8Ows7O",
1233+ "serial": "serial-KEhV9v",
1234+ "block_size": 1024,
1235+ "filesystem": null,
1236+ "id": 67,
1237+ "model": "model-XNLSfS",
1238+ "available_size": 3681153024,
1239+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/67/"
1240+ },
1241+ {
1242+ "firmware_version": "firmware_version-MD0sRK",
1243+ "system_id": "q46awd",
1244+ "type": "physical",
1245+ "used_size": 0,
1246+ "used_for": "Unused",
1247+ "partitions": [],
1248+ "uuid": null,
1249+ "name": "name-5UnjsY",
1250+ "id_path": null,
1251+ "tags": [
1252+ "tag-TR2qBE",
1253+ "tag-JJIvWV",
1254+ "tag-pYoDjB"
1255+ ],
1256+ "partition_table_type": null,
1257+ "size": 2411704320,
1258+ "storage_pool": null,
1259+ "path": "/dev/disk/by-dname/name-5UnjsY",
1260+ "serial": "serial-h0LybM",
1261+ "block_size": 1024,
1262+ "filesystem": null,
1263+ "id": 68,
1264+ "model": "model-UEouuL",
1265+ "available_size": 2411704320,
1266+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/68/"
1267+ },
1268+ {
1269+ "firmware_version": "firmware_version-4TDPi8",
1270+ "system_id": "q46awd",
1271+ "type": "physical",
1272+ "used_size": 0,
1273+ "used_for": "Unused",
1274+ "partitions": [],
1275+ "uuid": null,
1276+ "name": "name-xZSseq",
1277+ "id_path": null,
1278+ "tags": [
1279+ "tag-p53o0X",
1280+ "tag-8NIex3",
1281+ "tag-bSwNmr"
1282+ ],
1283+ "partition_table_type": null,
1284+ "size": 3030908928,
1285+ "storage_pool": null,
1286+ "path": "/dev/disk/by-dname/name-xZSseq",
1287+ "serial": "serial-wANhJs",
1288+ "block_size": 4096,
1289+ "filesystem": null,
1290+ "id": 69,
1291+ "model": "model-kIe7Vc",
1292+ "available_size": 3030908928,
1293+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/69/"
1294+ },
1295+ {
1296+ "firmware_version": "firmware_version-IU8B1C",
1297+ "system_id": "q46awd",
1298+ "type": "physical",
1299+ "used_size": 0,
1300+ "used_for": "Unused",
1301+ "partitions": [],
1302+ "uuid": null,
1303+ "name": "name-SmOpsN",
1304+ "id_path": null,
1305+ "tags": [
1306+ "tag-Ois1Gc",
1307+ "tag-DwHmIC",
1308+ "tag-jOzK03"
1309+ ],
1310+ "partition_table_type": null,
1311+ "size": 806171648,
1312+ "storage_pool": null,
1313+ "path": "/dev/disk/by-dname/name-SmOpsN",
1314+ "serial": "serial-c5xGdX",
1315+ "block_size": 1024,
1316+ "filesystem": null,
1317+ "id": 70,
1318+ "model": "model-7ZvrZr",
1319+ "available_size": 806171648,
1320+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/70/"
1321+ }
1322+ ],
1323+ "bcaches": [],
1324+ "iscsiblockdevice_set": [],
1325+ "cpu_test_status": 2,
1326+ "other_test_status_name": "Failed",
1327+ "memory": 1024,
1328+ "current_commissioning_result_id": 170,
1329+ "cpu_test_status_name": "Passed",
1330+ "hwe_kernel": null,
1331+ "current_installation_result_id": null,
1332+ "tag_names": [],
1333+ "netboot": true,
1334+ "hardware_info": {
1335+ "system_vendor": "Unknown",
1336+ "system_product": "Unknown",
1337+ "system_version": "Unknown",
1338+ "system_serial": "Unknown",
1339+ "cpu_model": "Unknown",
1340+ "mainboard_vendor": "Unknown",
1341+ "mainboard_product": "Unknown",
1342+ "mainboard_firmware_version": "Unknown",
1343+ "mainboard_firmware_date": "Unknown"
1344+ },
1345+ "cpu_count": 6,
1346+ "blockdevice_set": [
1347+ {
1348+ "id_path": null,
1349+ "size": 3770708992,
1350+ "block_size": 1024,
1351+ "tags": [
1352+ "tag-iF4AD7",
1353+ "tag-BtgV26",
1354+ "tag-wZF5A6"
1355+ ],
1356+ "system_id": "q46awd",
1357+ "type": "physical",
1358+ "used_size": 0,
1359+ "used_for": "Unused",
1360+ "partitions": [],
1361+ "uuid": null,
1362+ "name": "name-w1MxuB",
1363+ "partition_table_type": null,
1364+ "storage_pool": null,
1365+ "path": "/dev/disk/by-dname/name-w1MxuB",
1366+ "serial": "serial-u1CbU0",
1367+ "filesystem": null,
1368+ "id": 66,
1369+ "model": "model-A6yydP",
1370+ "available_size": 3770708992,
1371+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/66/"
1372+ },
1373+ {
1374+ "id_path": null,
1375+ "size": 3681153024,
1376+ "block_size": 1024,
1377+ "tags": [
1378+ "tag-ItoUN0",
1379+ "tag-MM2fGY",
1380+ "tag-oe8y1B"
1381+ ],
1382+ "system_id": "q46awd",
1383+ "type": "physical",
1384+ "used_size": 0,
1385+ "used_for": "Unused",
1386+ "partitions": [],
1387+ "uuid": null,
1388+ "name": "name-8Ows7O",
1389+ "partition_table_type": null,
1390+ "storage_pool": null,
1391+ "path": "/dev/disk/by-dname/name-8Ows7O",
1392+ "serial": "serial-KEhV9v",
1393+ "filesystem": null,
1394+ "id": 67,
1395+ "model": "model-XNLSfS",
1396+ "available_size": 3681153024,
1397+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/67/"
1398+ },
1399+ {
1400+ "id_path": null,
1401+ "size": 2411704320,
1402+ "block_size": 1024,
1403+ "tags": [
1404+ "tag-TR2qBE",
1405+ "tag-JJIvWV",
1406+ "tag-pYoDjB"
1407+ ],
1408+ "system_id": "q46awd",
1409+ "type": "physical",
1410+ "used_size": 0,
1411+ "used_for": "Unused",
1412+ "partitions": [],
1413+ "uuid": null,
1414+ "name": "name-5UnjsY",
1415+ "partition_table_type": null,
1416+ "storage_pool": null,
1417+ "path": "/dev/disk/by-dname/name-5UnjsY",
1418+ "serial": "serial-h0LybM",
1419+ "filesystem": null,
1420+ "id": 68,
1421+ "model": "model-UEouuL",
1422+ "available_size": 2411704320,
1423+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/68/"
1424+ },
1425+ {
1426+ "id_path": null,
1427+ "size": 3030908928,
1428+ "block_size": 4096,
1429+ "tags": [
1430+ "tag-p53o0X",
1431+ "tag-8NIex3",
1432+ "tag-bSwNmr"
1433+ ],
1434+ "system_id": "q46awd",
1435+ "type": "physical",
1436+ "used_size": 0,
1437+ "used_for": "Unused",
1438+ "partitions": [],
1439+ "uuid": null,
1440+ "name": "name-xZSseq",
1441+ "partition_table_type": null,
1442+ "storage_pool": null,
1443+ "path": "/dev/disk/by-dname/name-xZSseq",
1444+ "serial": "serial-wANhJs",
1445+ "filesystem": null,
1446+ "id": 69,
1447+ "model": "model-kIe7Vc",
1448+ "available_size": 3030908928,
1449+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/69/"
1450+ },
1451+ {
1452+ "id_path": null,
1453+ "size": 806171648,
1454+ "block_size": 1024,
1455+ "tags": [
1456+ "tag-Ois1Gc",
1457+ "tag-DwHmIC",
1458+ "tag-jOzK03"
1459+ ],
1460+ "system_id": "q46awd",
1461+ "type": "physical",
1462+ "used_size": 0,
1463+ "used_for": "Unused",
1464+ "partitions": [],
1465+ "uuid": null,
1466+ "name": "name-SmOpsN",
1467+ "partition_table_type": null,
1468+ "storage_pool": null,
1469+ "path": "/dev/disk/by-dname/name-SmOpsN",
1470+ "serial": "serial-c5xGdX",
1471+ "filesystem": null,
1472+ "id": 70,
1473+ "model": "model-7ZvrZr",
1474+ "available_size": 806171648,
1475+ "resource_uri": "/MAAS/api/2.0/nodes/q46awd/blockdevices/70/"
1476+ }
1477+ ],
1478+ "domain": {
1479+ "authoritative": true,
1480+ "ttl": null,
1481+ "is_default": true,
1482+ "name": "maas",
1483+ "id": 0,
1484+ "resource_record_count": 0,
1485+ "resource_uri": "/MAAS/api/2.0/domains/0/"
1486+ },
1487+ "memory_test_status": 3,
1488+ "status_message": "desc-jWUG7Z",
1489+ "owner": "user2",
1490+ "address_ttl": null,
1491+ "node_type": 0,
1492+ "volume_groups": [],
1493+ "pod": null,
1494+ "storage": 13700.646912,
1495+ "raids": [],
1496+ "status_action": "action-3rkEpa",
1497+ "min_hwe_kernel": null,
1498+ "status_name": "Entering rescue mode",
1499+ "commissioning_status": 2,
1500+ "testing_status": 3,
1501+ "fqdn": "clever-thrush.maas",
1502+ "power_state": "unknown",
1503+ "hostname": "clever-thrush",
1504+ "ip_addresses": [
1505+ "172.16.1.252"
1506+ ],
1507+ "resource_uri": "/MAAS/api/2.0/machines/q46awd/"
1508+ },
1509+ "query-power-state": {
1510+ "state": "on"
1511+ },
1512+ "power-on": {
1513+ "cpu_count": 1,
1514+ "fqdn": "node2.maas",
1515+ "hostname": "node2",
1516+ "power_state": "on",
1517+ "cpu_test_status": -1,
1518+ "storage": 8000,
1519+ "osystem": "ubuntu",
1520+ "cpu_test_status_name": "Unknown",
1521+ "testing_status": 2,
1522+ "iscsiblockdevice_set": [],
1523+ "boot_interface": {
1524+ "vlan": {
1525+ "vid": 0,
1526+ "mtu": 1500,
1527+ "dhcp_on": true,
1528+ "external_dhcp": null,
1529+ "relay_vlan": null,
1530+ "fabric": "fabric-1",
1531+ "fabric_id": 1,
1532+ "primary_rack": "mhce3f",
1533+ "secondary_rack": null,
1534+ "space": "FooSpace",
1535+ "name": "untagged",
1536+ "id": 5002,
1537+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
1538+ },
1539+ "links": [
1540+ {
1541+ "id": 13,
1542+ "mode": "auto",
1543+ "ip_address": "172.16.99.5",
1544+ "subnet": {
1545+ "name": "172.16.99.0/24",
1546+ "vlan": {
1547+ "vid": 0,
1548+ "mtu": 1500,
1549+ "dhcp_on": true,
1550+ "external_dhcp": null,
1551+ "relay_vlan": null,
1552+ "fabric": "fabric-1",
1553+ "fabric_id": 1,
1554+ "primary_rack": "mhce3f",
1555+ "secondary_rack": null,
1556+ "space": "FooSpace",
1557+ "name": "untagged",
1558+ "id": 5002,
1559+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
1560+ },
1561+ "cidr": "172.16.99.0/24",
1562+ "rdns_mode": 2,
1563+ "gateway_ip": "172.16.99.1",
1564+ "dns_servers": [],
1565+ "allow_dns": true,
1566+ "allow_proxy": true,
1567+ "active_discovery": false,
1568+ "managed": true,
1569+ "space": "FooSpace",
1570+ "id": 2,
1571+ "resource_uri": "/MAAS/api/2.0/subnets/2/"
1572+ }
1573+ }
1574+ ],
1575+ "vendor": "QEMU",
1576+ "enabled": true,
1577+ "children": [],
1578+ "name": "ens4",
1579+ "id": 5,
1580+ "discovered": [],
1581+ "parents": [],
1582+ "effective_mtu": 1500,
1583+ "product": "Standard PC (i440FX + PIIX, 1996)",
1584+ "firmware_version": null,
1585+ "system_id": "e8xa8m",
1586+ "mac_address": "52:54:00:52:a5:9e",
1587+ "tags": [],
1588+ "type": "physical",
1589+ "params": "",
1590+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/interfaces/5/"
1591+ },
1592+ "boot_disk": {
1593+ "firmware_version": null,
1594+ "model": "",
1595+ "path": "/dev/disk/by-dname/vda",
1596+ "serial": "",
1597+ "block_size": 4096,
1598+ "partitions": [
1599+ {
1600+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
1601+ "size": 7994343424,
1602+ "bootable": false,
1603+ "tags": [],
1604+ "type": "partition",
1605+ "path": "/dev/disk/by-dname/vda-part1",
1606+ "device_id": 2,
1607+ "used_for": "ext4 formatted filesystem mounted at /",
1608+ "system_id": "e8xa8m",
1609+ "filesystem": {
1610+ "fstype": "ext4",
1611+ "label": "root",
1612+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
1613+ "mount_point": "/",
1614+ "mount_options": null
1615+ },
1616+ "id": 2,
1617+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
1618+ }
1619+ ],
1620+ "available_size": 0,
1621+ "used_size": 7999586304,
1622+ "id_path": "/dev/vda",
1623+ "name": "vda",
1624+ "id": 2,
1625+ "used_for": "MBR partitioned with 1 partition",
1626+ "partition_table_type": "MBR",
1627+ "system_id": "e8xa8m",
1628+ "size": 8000000000,
1629+ "tags": [
1630+ "rotary"
1631+ ],
1632+ "filesystem": null,
1633+ "uuid": null,
1634+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
1635+ "type": "physical",
1636+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
1637+ },
1638+ "bcaches": [],
1639+ "cpu_speed": 2500,
1640+ "ip_addresses": [
1641+ "172.16.99.5"
1642+ ],
1643+ "virtualblockdevice_set": [],
1644+ "special_filesystems": [],
1645+ "owner_data": {},
1646+ "physicalblockdevice_set": [
1647+ {
1648+ "firmware_version": null,
1649+ "model": "",
1650+ "path": "/dev/disk/by-dname/vda",
1651+ "serial": "",
1652+ "block_size": 4096,
1653+ "partitions": [
1654+ {
1655+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
1656+ "size": 7994343424,
1657+ "bootable": false,
1658+ "tags": [],
1659+ "type": "partition",
1660+ "path": "/dev/disk/by-dname/vda-part1",
1661+ "device_id": 2,
1662+ "used_for": "ext4 formatted filesystem mounted at /",
1663+ "system_id": "e8xa8m",
1664+ "filesystem": {
1665+ "fstype": "ext4",
1666+ "label": "root",
1667+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
1668+ "mount_point": "/",
1669+ "mount_options": null
1670+ },
1671+ "id": 2,
1672+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
1673+ }
1674+ ],
1675+ "available_size": 0,
1676+ "used_size": 7999586304,
1677+ "id_path": "/dev/vda",
1678+ "name": "vda",
1679+ "id": 2,
1680+ "used_for": "MBR partitioned with 1 partition",
1681+ "partition_table_type": "MBR",
1682+ "system_id": "e8xa8m",
1683+ "size": 8000000000,
1684+ "tags": [
1685+ "rotary"
1686+ ],
1687+ "filesystem": null,
1688+ "uuid": null,
1689+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
1690+ "type": "physical",
1691+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
1692+ }
1693+ ],
1694+ "testing_status_name": "Passed",
1695+ "disable_ipv4": false,
1696+ "blockdevice_set": [
1697+ {
1698+ "id_path": "/dev/vda",
1699+ "size": 8000000000,
1700+ "block_size": 4096,
1701+ "tags": [
1702+ "rotary"
1703+ ],
1704+ "model": "",
1705+ "path": "/dev/disk/by-dname/vda",
1706+ "serial": "",
1707+ "partitions": [
1708+ {
1709+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
1710+ "size": 7994343424,
1711+ "bootable": false,
1712+ "tags": [],
1713+ "type": "partition",
1714+ "path": "/dev/disk/by-dname/vda-part1",
1715+ "device_id": 2,
1716+ "used_for": "ext4 formatted filesystem mounted at /",
1717+ "system_id": "e8xa8m",
1718+ "filesystem": {
1719+ "fstype": "ext4",
1720+ "label": "root",
1721+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
1722+ "mount_point": "/",
1723+ "mount_options": null
1724+ },
1725+ "id": 2,
1726+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
1727+ }
1728+ ],
1729+ "available_size": 0,
1730+ "used_size": 7999586304,
1731+ "name": "vda",
1732+ "id": 2,
1733+ "used_for": "MBR partitioned with 1 partition",
1734+ "partition_table_type": "MBR",
1735+ "system_id": "e8xa8m",
1736+ "filesystem": null,
1737+ "uuid": null,
1738+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
1739+ "type": "physical",
1740+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
1741+ }
1742+ ],
1743+ "interface_set": [
1744+ {
1745+ "vlan": {
1746+ "vid": 0,
1747+ "mtu": 1500,
1748+ "dhcp_on": true,
1749+ "external_dhcp": null,
1750+ "relay_vlan": null,
1751+ "fabric": "fabric-1",
1752+ "fabric_id": 1,
1753+ "primary_rack": "mhce3f",
1754+ "secondary_rack": null,
1755+ "space": "FooSpace",
1756+ "name": "untagged",
1757+ "id": 5002,
1758+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
1759+ },
1760+ "links": [
1761+ {
1762+ "id": 13,
1763+ "mode": "auto",
1764+ "ip_address": "172.16.99.5",
1765+ "subnet": {
1766+ "name": "172.16.99.0/24",
1767+ "vlan": {
1768+ "vid": 0,
1769+ "mtu": 1500,
1770+ "dhcp_on": true,
1771+ "external_dhcp": null,
1772+ "relay_vlan": null,
1773+ "fabric": "fabric-1",
1774+ "fabric_id": 1,
1775+ "primary_rack": "mhce3f",
1776+ "secondary_rack": null,
1777+ "space": "FooSpace",
1778+ "name": "untagged",
1779+ "id": 5002,
1780+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
1781+ },
1782+ "cidr": "172.16.99.0/24",
1783+ "rdns_mode": 2,
1784+ "gateway_ip": "172.16.99.1",
1785+ "dns_servers": [],
1786+ "allow_dns": true,
1787+ "allow_proxy": true,
1788+ "active_discovery": false,
1789+ "managed": true,
1790+ "space": "FooSpace",
1791+ "id": 2,
1792+ "resource_uri": "/MAAS/api/2.0/subnets/2/"
1793+ }
1794+ }
1795+ ],
1796+ "vendor": "QEMU",
1797+ "enabled": true,
1798+ "children": [],
1799+ "name": "ens4",
1800+ "id": 5,
1801+ "discovered": [],
1802+ "parents": [],
1803+ "effective_mtu": 1500,
1804+ "product": "Standard PC (i440FX + PIIX, 1996)",
1805+ "firmware_version": null,
1806+ "system_id": "e8xa8m",
1807+ "mac_address": "52:54:00:52:a5:9e",
1808+ "tags": [],
1809+ "type": "physical",
1810+ "params": "",
1811+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/interfaces/5/"
1812+ }
1813+ ],
1814+ "architecture": "amd64/generic",
1815+ "commissioning_status": 2,
1816+ "hwe_kernel": "ga-18.04",
1817+ "current_installation_result_id": 8,
1818+ "swap_size": null,
1819+ "memory": 1024,
1820+ "pod": {
1821+ "id": 1,
1822+ "name": "MyPodName",
1823+ "resource_uri": "/MAAS/api/2.0/pods/1/"
1824+ },
1825+ "current_commissioning_result_id": 6,
1826+ "hardware_info": {
1827+ "system_vendor": "QEMU",
1828+ "system_product": "Standard PC (i440FX + PIIX, 1996)",
1829+ "system_version": "pc-i440fx-bionic",
1830+ "system_serial": "Unknown",
1831+ "cpu_model": "QEMU Virtual CPU version 2.5+",
1832+ "mainboard_vendor": "Unknown",
1833+ "mainboard_product": "Unknown",
1834+ "mainboard_firmware_version": "1.10.2-1ubuntu1",
1835+ "mainboard_firmware_date": "04/01/2014"
1836+ },
1837+ "pool": {
1838+ "name": "newname",
1839+ "description": "new description",
1840+ "id": 1,
1841+ "resource_uri": "/MAAS/api/2.0/resourcepool/1/"
1842+ },
1843+ "current_testing_result_id": 7,
1844+ "tag_names": [
1845+ "virtual",
1846+ "mypod"
1847+ ],
1848+ "storage_test_status": 2,
1849+ "address_ttl": null,
1850+ "status_message": "'cloudinit' running modules for final",
1851+ "cache_sets": [],
1852+ "other_test_status_name": "Unknown",
1853+ "node_type_name": "Machine",
1854+ "distro_series": "bionic",
1855+ "zone": {
1856+ "name": "default",
1857+ "description": "",
1858+ "id": 1,
1859+ "resource_uri": "/MAAS/api/2.0/zones/default/"
1860+ },
1861+ "min_hwe_kernel": "",
1862+ "domain": {
1863+ "authoritative": true,
1864+ "ttl": null,
1865+ "name": "maas",
1866+ "resource_record_count": 0,
1867+ "id": 0,
1868+ "is_default": true,
1869+ "resource_uri": "/MAAS/api/2.0/domains/0/"
1870+ },
1871+ "system_id": "e8xa8m",
1872+ "locked": false,
1873+ "power_type": "virsh",
1874+ "node_type": 0,
1875+ "memory_test_status": -1,
1876+ "memory_test_status_name": "Unknown",
1877+ "status": 6,
1878+ "netboot": false,
1879+ "volume_groups": [],
1880+ "raids": [],
1881+ "default_gateways": {
1882+ "ipv4": {
1883+ "gateway_ip": "172.16.99.1",
1884+ "link_id": null
1885+ },
1886+ "ipv6": {
1887+ "gateway_ip": null,
1888+ "link_id": null
1889+ }
1890+ },
1891+ "commissioning_status_name": "Passed",
1892+ "status_action": "modules-final",
1893+ "other_test_status": -1,
1894+ "status_name": "Deployed",
1895+ "storage_test_status_name": "Passed",
1896+ "owner": "admin",
1897+ "resource_uri": "/MAAS/api/2.0/machines/e8xa8m/"
1898+ },
1899+ "power-off": {
1900+ "cpu_count": 1,
1901+ "fqdn": "node2.maas",
1902+ "hostname": "node2",
1903+ "power_state": "on",
1904+ "cpu_test_status": -1,
1905+ "storage": 8000,
1906+ "osystem": "ubuntu",
1907+ "cpu_test_status_name": "Unknown",
1908+ "testing_status": 2,
1909+ "iscsiblockdevice_set": [],
1910+ "boot_interface": {
1911+ "vlan": {
1912+ "vid": 0,
1913+ "mtu": 1500,
1914+ "dhcp_on": true,
1915+ "external_dhcp": null,
1916+ "relay_vlan": null,
1917+ "fabric": "fabric-1",
1918+ "fabric_id": 1,
1919+ "primary_rack": "mhce3f",
1920+ "secondary_rack": null,
1921+ "space": "FooSpace",
1922+ "name": "untagged",
1923+ "id": 5002,
1924+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
1925+ },
1926+ "links": [
1927+ {
1928+ "id": 13,
1929+ "mode": "auto",
1930+ "ip_address": "172.16.99.5",
1931+ "subnet": {
1932+ "name": "172.16.99.0/24",
1933+ "vlan": {
1934+ "vid": 0,
1935+ "mtu": 1500,
1936+ "dhcp_on": true,
1937+ "external_dhcp": null,
1938+ "relay_vlan": null,
1939+ "fabric": "fabric-1",
1940+ "fabric_id": 1,
1941+ "primary_rack": "mhce3f",
1942+ "secondary_rack": null,
1943+ "space": "FooSpace",
1944+ "name": "untagged",
1945+ "id": 5002,
1946+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
1947+ },
1948+ "cidr": "172.16.99.0/24",
1949+ "rdns_mode": 2,
1950+ "gateway_ip": "172.16.99.1",
1951+ "dns_servers": [],
1952+ "allow_dns": true,
1953+ "allow_proxy": true,
1954+ "active_discovery": false,
1955+ "managed": true,
1956+ "space": "FooSpace",
1957+ "id": 2,
1958+ "resource_uri": "/MAAS/api/2.0/subnets/2/"
1959+ }
1960+ }
1961+ ],
1962+ "vendor": "QEMU",
1963+ "enabled": true,
1964+ "children": [],
1965+ "name": "ens4",
1966+ "id": 5,
1967+ "discovered": [],
1968+ "parents": [],
1969+ "effective_mtu": 1500,
1970+ "product": "Standard PC (i440FX + PIIX, 1996)",
1971+ "firmware_version": null,
1972+ "system_id": "e8xa8m",
1973+ "mac_address": "52:54:00:52:a5:9e",
1974+ "tags": [],
1975+ "type": "physical",
1976+ "params": "",
1977+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/interfaces/5/"
1978+ },
1979+ "boot_disk": {
1980+ "firmware_version": null,
1981+ "model": "",
1982+ "path": "/dev/disk/by-dname/vda",
1983+ "serial": "",
1984+ "block_size": 4096,
1985+ "partitions": [
1986+ {
1987+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
1988+ "size": 7994343424,
1989+ "bootable": false,
1990+ "tags": [],
1991+ "type": "partition",
1992+ "path": "/dev/disk/by-dname/vda-part1",
1993+ "device_id": 2,
1994+ "used_for": "ext4 formatted filesystem mounted at /",
1995+ "system_id": "e8xa8m",
1996+ "filesystem": {
1997+ "fstype": "ext4",
1998+ "label": "root",
1999+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
2000+ "mount_point": "/",
2001+ "mount_options": null
2002+ },
2003+ "id": 2,
2004+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
2005+ }
2006+ ],
2007+ "available_size": 0,
2008+ "used_size": 7999586304,
2009+ "id_path": "/dev/vda",
2010+ "name": "vda",
2011+ "id": 2,
2012+ "used_for": "MBR partitioned with 1 partition",
2013+ "partition_table_type": "MBR",
2014+ "system_id": "e8xa8m",
2015+ "size": 8000000000,
2016+ "tags": [
2017+ "rotary"
2018+ ],
2019+ "filesystem": null,
2020+ "uuid": null,
2021+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
2022+ "type": "physical",
2023+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
2024+ },
2025+ "bcaches": [],
2026+ "cpu_speed": 2500,
2027+ "ip_addresses": [
2028+ "172.16.99.5"
2029+ ],
2030+ "virtualblockdevice_set": [],
2031+ "special_filesystems": [],
2032+ "owner_data": {},
2033+ "physicalblockdevice_set": [
2034+ {
2035+ "firmware_version": null,
2036+ "model": "",
2037+ "path": "/dev/disk/by-dname/vda",
2038+ "serial": "",
2039+ "block_size": 4096,
2040+ "partitions": [
2041+ {
2042+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
2043+ "size": 7994343424,
2044+ "bootable": false,
2045+ "tags": [],
2046+ "type": "partition",
2047+ "path": "/dev/disk/by-dname/vda-part1",
2048+ "device_id": 2,
2049+ "used_for": "ext4 formatted filesystem mounted at /",
2050+ "system_id": "e8xa8m",
2051+ "filesystem": {
2052+ "fstype": "ext4",
2053+ "label": "root",
2054+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
2055+ "mount_point": "/",
2056+ "mount_options": null
2057+ },
2058+ "id": 2,
2059+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
2060+ }
2061+ ],
2062+ "available_size": 0,
2063+ "used_size": 7999586304,
2064+ "id_path": "/dev/vda",
2065+ "name": "vda",
2066+ "id": 2,
2067+ "used_for": "MBR partitioned with 1 partition",
2068+ "partition_table_type": "MBR",
2069+ "system_id": "e8xa8m",
2070+ "size": 8000000000,
2071+ "tags": [
2072+ "rotary"
2073+ ],
2074+ "filesystem": null,
2075+ "uuid": null,
2076+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
2077+ "type": "physical",
2078+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
2079+ }
2080+ ],
2081+ "testing_status_name": "Passed",
2082+ "disable_ipv4": false,
2083+ "blockdevice_set": [
2084+ {
2085+ "id_path": "/dev/vda",
2086+ "size": 8000000000,
2087+ "block_size": 4096,
2088+ "tags": [
2089+ "rotary"
2090+ ],
2091+ "model": "",
2092+ "path": "/dev/disk/by-dname/vda",
2093+ "serial": "",
2094+ "partitions": [
2095+ {
2096+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
2097+ "size": 7994343424,
2098+ "bootable": false,
2099+ "tags": [],
2100+ "type": "partition",
2101+ "path": "/dev/disk/by-dname/vda-part1",
2102+ "device_id": 2,
2103+ "used_for": "ext4 formatted filesystem mounted at /",
2104+ "system_id": "e8xa8m",
2105+ "filesystem": {
2106+ "fstype": "ext4",
2107+ "label": "root",
2108+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
2109+ "mount_point": "/",
2110+ "mount_options": null
2111+ },
2112+ "id": 2,
2113+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
2114+ }
2115+ ],
2116+ "available_size": 0,
2117+ "used_size": 7999586304,
2118+ "name": "vda",
2119+ "id": 2,
2120+ "used_for": "MBR partitioned with 1 partition",
2121+ "partition_table_type": "MBR",
2122+ "system_id": "e8xa8m",
2123+ "filesystem": null,
2124+ "uuid": null,
2125+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
2126+ "type": "physical",
2127+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
2128+ }
2129+ ],
2130+ "interface_set": [
2131+ {
2132+ "vlan": {
2133+ "vid": 0,
2134+ "mtu": 1500,
2135+ "dhcp_on": true,
2136+ "external_dhcp": null,
2137+ "relay_vlan": null,
2138+ "fabric": "fabric-1",
2139+ "fabric_id": 1,
2140+ "primary_rack": "mhce3f",
2141+ "secondary_rack": null,
2142+ "space": "FooSpace",
2143+ "name": "untagged",
2144+ "id": 5002,
2145+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
2146+ },
2147+ "links": [
2148+ {
2149+ "id": 13,
2150+ "mode": "auto",
2151+ "ip_address": "172.16.99.5",
2152+ "subnet": {
2153+ "name": "172.16.99.0/24",
2154+ "vlan": {
2155+ "vid": 0,
2156+ "mtu": 1500,
2157+ "dhcp_on": true,
2158+ "external_dhcp": null,
2159+ "relay_vlan": null,
2160+ "fabric": "fabric-1",
2161+ "fabric_id": 1,
2162+ "primary_rack": "mhce3f",
2163+ "secondary_rack": null,
2164+ "space": "FooSpace",
2165+ "name": "untagged",
2166+ "id": 5002,
2167+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
2168+ },
2169+ "cidr": "172.16.99.0/24",
2170+ "rdns_mode": 2,
2171+ "gateway_ip": "172.16.99.1",
2172+ "dns_servers": [],
2173+ "allow_dns": true,
2174+ "allow_proxy": true,
2175+ "active_discovery": false,
2176+ "managed": true,
2177+ "space": "FooSpace",
2178+ "id": 2,
2179+ "resource_uri": "/MAAS/api/2.0/subnets/2/"
2180+ }
2181+ }
2182+ ],
2183+ "vendor": "QEMU",
2184+ "enabled": true,
2185+ "children": [],
2186+ "name": "ens4",
2187+ "id": 5,
2188+ "discovered": [],
2189+ "parents": [],
2190+ "effective_mtu": 1500,
2191+ "product": "Standard PC (i440FX + PIIX, 1996)",
2192+ "firmware_version": null,
2193+ "system_id": "e8xa8m",
2194+ "mac_address": "52:54:00:52:a5:9e",
2195+ "tags": [],
2196+ "type": "physical",
2197+ "params": "",
2198+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/interfaces/5/"
2199+ }
2200+ ],
2201+ "architecture": "amd64/generic",
2202+ "commissioning_status": 2,
2203+ "hwe_kernel": "ga-18.04",
2204+ "current_installation_result_id": 8,
2205+ "swap_size": null,
2206+ "memory": 1024,
2207+ "pod": {
2208+ "id": 1,
2209+ "name": "MyPodName",
2210+ "resource_uri": "/MAAS/api/2.0/pods/1/"
2211+ },
2212+ "current_commissioning_result_id": 6,
2213+ "hardware_info": {
2214+ "system_vendor": "QEMU",
2215+ "system_product": "Standard PC (i440FX + PIIX, 1996)",
2216+ "system_version": "pc-i440fx-bionic",
2217+ "system_serial": "Unknown",
2218+ "cpu_model": "QEMU Virtual CPU version 2.5+",
2219+ "mainboard_vendor": "Unknown",
2220+ "mainboard_product": "Unknown",
2221+ "mainboard_firmware_version": "1.10.2-1ubuntu1",
2222+ "mainboard_firmware_date": "04/01/2014"
2223+ },
2224+ "pool": {
2225+ "name": "newname",
2226+ "description": "new description",
2227+ "id": 1,
2228+ "resource_uri": "/MAAS/api/2.0/resourcepool/1/"
2229+ },
2230+ "current_testing_result_id": 7,
2231+ "tag_names": [
2232+ "virtual",
2233+ "mypod"
2234+ ],
2235+ "storage_test_status": 2,
2236+ "address_ttl": null,
2237+ "status_message": "'cloudinit' running modules for final",
2238+ "cache_sets": [],
2239+ "other_test_status_name": "Unknown",
2240+ "node_type_name": "Machine",
2241+ "distro_series": "bionic",
2242+ "zone": {
2243+ "name": "default",
2244+ "description": "",
2245+ "id": 1,
2246+ "resource_uri": "/MAAS/api/2.0/zones/default/"
2247+ },
2248+ "min_hwe_kernel": "",
2249+ "domain": {
2250+ "authoritative": true,
2251+ "ttl": null,
2252+ "name": "maas",
2253+ "resource_record_count": 0,
2254+ "id": 0,
2255+ "is_default": true,
2256+ "resource_uri": "/MAAS/api/2.0/domains/0/"
2257+ },
2258+ "system_id": "e8xa8m",
2259+ "locked": false,
2260+ "power_type": "virsh",
2261+ "node_type": 0,
2262+ "memory_test_status": -1,
2263+ "memory_test_status_name": "Unknown",
2264+ "status": 6,
2265+ "netboot": false,
2266+ "volume_groups": [],
2267+ "raids": [],
2268+ "default_gateways": {
2269+ "ipv4": {
2270+ "gateway_ip": "172.16.99.1",
2271+ "link_id": null
2272+ },
2273+ "ipv6": {
2274+ "gateway_ip": null,
2275+ "link_id": null
2276+ }
2277+ },
2278+ "commissioning_status_name": "Passed",
2279+ "status_action": "modules-final",
2280+ "other_test_status": -1,
2281+ "status_name": "Deployed",
2282+ "storage_test_status_name": "Passed",
2283+ "owner": "admin",
2284+ "resource_uri": "/MAAS/api/2.0/machines/e8xa8m/"
2285+ },
2286+ "test": {
2287+ "cpu_speed": 2500,
2288+ "disable_ipv4": false,
2289+ "cache_sets": [],
2290+ "other_test_status_name": "Unknown",
2291+ "memory_test_status": -1,
2292+ "tag_names": [
2293+ "virtual",
2294+ "mypod"
2295+ ],
2296+ "netboot": false,
2297+ "power_type": "virsh",
2298+ "hostname": "node2",
2299+ "node_type": 0,
2300+ "testing_status": 0,
2301+ "default_gateways": {
2302+ "ipv4": {
2303+ "gateway_ip": "172.16.99.1",
2304+ "link_id": null
2305+ },
2306+ "ipv6": {
2307+ "gateway_ip": null,
2308+ "link_id": null
2309+ }
2310+ },
2311+ "raids": [],
2312+ "current_installation_result_id": 8,
2313+ "locked": false,
2314+ "zone": {
2315+ "name": "default",
2316+ "description": "",
2317+ "id": 1,
2318+ "resource_uri": "/MAAS/api/2.0/zones/default/"
2319+ },
2320+ "iscsiblockdevice_set": [],
2321+ "current_commissioning_result_id": 6,
2322+ "current_testing_result_id": 49,
2323+ "osystem": "ubuntu",
2324+ "cpu_count": 1,
2325+ "node_type_name": "Machine",
2326+ "blockdevice_set": [
2327+ {
2328+ "id_path": "/dev/vda",
2329+ "size": 8000000000,
2330+ "block_size": 4096,
2331+ "tags": [
2332+ "rotary"
2333+ ],
2334+ "used_size": 7999586304,
2335+ "used_for": "MBR partitioned with 1 partition",
2336+ "filesystem": null,
2337+ "model": "",
2338+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
2339+ "serial": "",
2340+ "partition_table_type": "MBR",
2341+ "type": "physical",
2342+ "id": 2,
2343+ "path": "/dev/disk/by-dname/vda",
2344+ "system_id": "e8xa8m",
2345+ "uuid": null,
2346+ "available_size": 0,
2347+ "partitions": [
2348+ {
2349+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
2350+ "size": 7994343424,
2351+ "bootable": false,
2352+ "tags": [],
2353+ "used_for": "ext4 formatted filesystem mounted at /",
2354+ "filesystem": {
2355+ "fstype": "ext4",
2356+ "label": "root",
2357+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
2358+ "mount_point": "/",
2359+ "mount_options": null
2360+ },
2361+ "device_id": 2,
2362+ "type": "partition",
2363+ "id": 2,
2364+ "path": "/dev/disk/by-dname/vda-part1",
2365+ "system_id": "e8xa8m",
2366+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
2367+ }
2368+ ],
2369+ "name": "vda",
2370+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
2371+ }
2372+ ],
2373+ "boot_interface": {
2374+ "firmware_version": null,
2375+ "vlan": {
2376+ "vid": 0,
2377+ "mtu": 1500,
2378+ "dhcp_on": true,
2379+ "external_dhcp": null,
2380+ "relay_vlan": null,
2381+ "secondary_rack": null,
2382+ "primary_rack": "mhce3f",
2383+ "space": "FooSpace",
2384+ "id": 5002,
2385+ "fabric": "fabric-1",
2386+ "fabric_id": 1,
2387+ "name": "untagged",
2388+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
2389+ },
2390+ "links": [
2391+ {
2392+ "id": 13,
2393+ "mode": "auto",
2394+ "ip_address": "172.16.99.5",
2395+ "subnet": {
2396+ "name": "172.16.99.0/24",
2397+ "vlan": {
2398+ "vid": 0,
2399+ "mtu": 1500,
2400+ "dhcp_on": true,
2401+ "external_dhcp": null,
2402+ "relay_vlan": null,
2403+ "secondary_rack": null,
2404+ "primary_rack": "mhce3f",
2405+ "space": "FooSpace",
2406+ "id": 5002,
2407+ "fabric": "fabric-1",
2408+ "fabric_id": 1,
2409+ "name": "untagged",
2410+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
2411+ },
2412+ "cidr": "172.16.99.0/24",
2413+ "rdns_mode": 2,
2414+ "gateway_ip": "172.16.99.1",
2415+ "dns_servers": [],
2416+ "allow_dns": true,
2417+ "allow_proxy": true,
2418+ "active_discovery": false,
2419+ "managed": true,
2420+ "space": "FooSpace",
2421+ "id": 2,
2422+ "resource_uri": "/MAAS/api/2.0/subnets/2/"
2423+ }
2424+ }
2425+ ],
2426+ "mac_address": "52:54:00:52:a5:9e",
2427+ "parents": [],
2428+ "effective_mtu": 1500,
2429+ "discovered": [],
2430+ "type": "physical",
2431+ "children": [],
2432+ "product": "Standard PC (i440FX + PIIX, 1996)",
2433+ "params": "",
2434+ "tags": [],
2435+ "id": 5,
2436+ "vendor": "QEMU",
2437+ "system_id": "e8xa8m",
2438+ "enabled": true,
2439+ "name": "ens4",
2440+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/interfaces/5/"
2441+ },
2442+ "pod": {
2443+ "id": 1,
2444+ "name": "MyPodName",
2445+ "resource_uri": "/MAAS/api/2.0/pods/1/"
2446+ },
2447+ "storage_test_status": 0,
2448+ "architecture": "amd64/generic",
2449+ "memory_test_status_name": "Unknown",
2450+ "storage": 8000,
2451+ "status_action": "modules-final",
2452+ "virtualblockdevice_set": [],
2453+ "special_filesystems": [],
2454+ "other_test_status": -1,
2455+ "status_name": "Testing",
2456+ "volume_groups": [],
2457+ "ip_addresses": [
2458+ "172.16.99.5"
2459+ ],
2460+ "hardware_info": {
2461+ "system_vendor": "QEMU",
2462+ "system_product": "Standard PC (i440FX + PIIX, 1996)",
2463+ "system_version": "pc-i440fx-bionic",
2464+ "system_serial": "Unknown",
2465+ "cpu_model": "QEMU Virtual CPU version 2.5+",
2466+ "mainboard_vendor": "Unknown",
2467+ "mainboard_product": "Unknown",
2468+ "mainboard_firmware_version": "1.10.2-1ubuntu1",
2469+ "mainboard_firmware_date": "04/01/2014"
2470+ },
2471+ "swap_size": null,
2472+ "owner_data": {},
2473+ "status": 21,
2474+ "cpu_test_status_name": "Unknown",
2475+ "boot_disk": {
2476+ "firmware_version": null,
2477+ "id_path": "/dev/vda",
2478+ "block_size": 4096,
2479+ "used_size": 7999586304,
2480+ "used_for": "MBR partitioned with 1 partition",
2481+ "filesystem": null,
2482+ "model": "",
2483+ "size": 8000000000,
2484+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
2485+ "serial": "",
2486+ "partition_table_type": "MBR",
2487+ "type": "physical",
2488+ "tags": [
2489+ "rotary"
2490+ ],
2491+ "id": 2,
2492+ "path": "/dev/disk/by-dname/vda",
2493+ "system_id": "e8xa8m",
2494+ "uuid": null,
2495+ "available_size": 0,
2496+ "partitions": [
2497+ {
2498+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
2499+ "size": 7994343424,
2500+ "bootable": false,
2501+ "tags": [],
2502+ "used_for": "ext4 formatted filesystem mounted at /",
2503+ "filesystem": {
2504+ "fstype": "ext4",
2505+ "label": "root",
2506+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
2507+ "mount_point": "/",
2508+ "mount_options": null
2509+ },
2510+ "device_id": 2,
2511+ "type": "partition",
2512+ "id": 2,
2513+ "path": "/dev/disk/by-dname/vda-part1",
2514+ "system_id": "e8xa8m",
2515+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
2516+ }
2517+ ],
2518+ "name": "vda",
2519+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
2520+ },
2521+ "address_ttl": null,
2522+ "system_id": "e8xa8m",
2523+ "memory": 1024,
2524+ "domain": {
2525+ "authoritative": true,
2526+ "ttl": null,
2527+ "resource_record_count": 0,
2528+ "is_default": true,
2529+ "id": 0,
2530+ "name": "maas",
2531+ "resource_uri": "/MAAS/api/2.0/domains/0/"
2532+ },
2533+ "min_hwe_kernel": "",
2534+ "physicalblockdevice_set": [
2535+ {
2536+ "firmware_version": null,
2537+ "id_path": "/dev/vda",
2538+ "block_size": 4096,
2539+ "used_size": 7999586304,
2540+ "used_for": "MBR partitioned with 1 partition",
2541+ "filesystem": null,
2542+ "model": "",
2543+ "size": 8000000000,
2544+ "storage_pool": "30c2ef09-cfca-4a17-b2b0-2b69bf4d62d8",
2545+ "serial": "",
2546+ "partition_table_type": "MBR",
2547+ "type": "physical",
2548+ "tags": [
2549+ "rotary"
2550+ ],
2551+ "id": 2,
2552+ "path": "/dev/disk/by-dname/vda",
2553+ "system_id": "e8xa8m",
2554+ "uuid": null,
2555+ "available_size": 0,
2556+ "partitions": [
2557+ {
2558+ "uuid": "b4922056-6481-4d40-87cd-5bac47dca519",
2559+ "size": 7994343424,
2560+ "bootable": false,
2561+ "tags": [],
2562+ "used_for": "ext4 formatted filesystem mounted at /",
2563+ "filesystem": {
2564+ "fstype": "ext4",
2565+ "label": "root",
2566+ "uuid": "bc478524-ad85-419f-8795-aa7b89590f6f",
2567+ "mount_point": "/",
2568+ "mount_options": null
2569+ },
2570+ "device_id": 2,
2571+ "type": "partition",
2572+ "id": 2,
2573+ "path": "/dev/disk/by-dname/vda-part1",
2574+ "system_id": "e8xa8m",
2575+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/partition/2"
2576+ }
2577+ ],
2578+ "name": "vda",
2579+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/blockdevices/2/"
2580+ }
2581+ ],
2582+ "owner": "admin",
2583+ "power_state": "on",
2584+ "hwe_kernel": "ga-18.04",
2585+ "testing_status_name": "Pending",
2586+ "pool": {
2587+ "name": "newname",
2588+ "description": "new description",
2589+ "id": 1,
2590+ "resource_uri": "/MAAS/api/2.0/resourcepool/1/"
2591+ },
2592+ "fqdn": "node2.maas",
2593+ "status_message": "'cloudinit' running modules for final",
2594+ "commissioning_status": 2,
2595+ "distro_series": "bionic",
2596+ "cpu_test_status": -1,
2597+ "storage_test_status_name": "Pending",
2598+ "bcaches": [],
2599+ "interface_set": [
2600+ {
2601+ "firmware_version": null,
2602+ "vlan": {
2603+ "vid": 0,
2604+ "mtu": 1500,
2605+ "dhcp_on": true,
2606+ "external_dhcp": null,
2607+ "relay_vlan": null,
2608+ "secondary_rack": null,
2609+ "primary_rack": "mhce3f",
2610+ "space": "FooSpace",
2611+ "id": 5002,
2612+ "fabric": "fabric-1",
2613+ "fabric_id": 1,
2614+ "name": "untagged",
2615+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
2616+ },
2617+ "links": [
2618+ {
2619+ "id": 13,
2620+ "mode": "auto",
2621+ "ip_address": "172.16.99.5",
2622+ "subnet": {
2623+ "name": "172.16.99.0/24",
2624+ "vlan": {
2625+ "vid": 0,
2626+ "mtu": 1500,
2627+ "dhcp_on": true,
2628+ "external_dhcp": null,
2629+ "relay_vlan": null,
2630+ "secondary_rack": null,
2631+ "primary_rack": "mhce3f",
2632+ "space": "FooSpace",
2633+ "id": 5002,
2634+ "fabric": "fabric-1",
2635+ "fabric_id": 1,
2636+ "name": "untagged",
2637+ "resource_uri": "/MAAS/api/2.0/vlans/5002/"
2638+ },
2639+ "cidr": "172.16.99.0/24",
2640+ "rdns_mode": 2,
2641+ "gateway_ip": "172.16.99.1",
2642+ "dns_servers": [],
2643+ "allow_dns": true,
2644+ "allow_proxy": true,
2645+ "active_discovery": false,
2646+ "managed": true,
2647+ "space": "FooSpace",
2648+ "id": 2,
2649+ "resource_uri": "/MAAS/api/2.0/subnets/2/"
2650+ }
2651+ }
2652+ ],
2653+ "mac_address": "52:54:00:52:a5:9e",
2654+ "parents": [],
2655+ "effective_mtu": 1500,
2656+ "discovered": [],
2657+ "type": "physical",
2658+ "children": [],
2659+ "product": "Standard PC (i440FX + PIIX, 1996)",
2660+ "params": "",
2661+ "tags": [],
2662+ "id": 5,
2663+ "vendor": "QEMU",
2664+ "system_id": "e8xa8m",
2665+ "enabled": true,
2666+ "name": "ens4",
2667+ "resource_uri": "/MAAS/api/2.0/nodes/e8xa8m/interfaces/5/"
2668+ }
2669+ ],
2670+ "commissioning_status_name": "Passed",
2671+ "resource_uri": "/MAAS/api/2.0/machines/e8xa8m/"
2672+ },
2673+ "get-power-params": {
2674+ "dypesm": {
2675+ "power_address": "qemu+ssh://ubuntu@172.16.1.28/system",
2676+ "power_id": "driven-bat"
2677+ },
2678+ "xs7qfn": {
2679+ "power_address": "qemu+ssh://ubuntu@172.16.1.134/system",
2680+ "power_id": "nice-shad"
2681+ }
2682+ }
2683+}
2684diff --git a/src/maasserver/api/nodes.py b/src/maasserver/api/nodes.py
2685index 24086dc..1fe4012 100644
2686--- a/src/maasserver/api/nodes.py
2687+++ b/src/maasserver/api/nodes.py
2688@@ -297,7 +297,8 @@ def get_script_status_name(script_status):
2689
2690
2691 class NodeHandler(OperationsHandler):
2692- """Manage an individual Node.
2693+ """
2694+ Manage an individual Node.
2695
2696 The Node is identified by its system_id.
2697 """
2698@@ -420,9 +421,20 @@ class NodeHandler(OperationsHandler):
2699 return ret
2700
2701 def read(self, request, system_id):
2702- """Read a specific Node.
2703+ """@description-title Read a node
2704+ @description Reads a node with the given system_id.
2705+
2706+ @param (string) "{system_id}" [required=true] A node's system_id.
2707+
2708+ @success (http-status-code) "server-success" 200
2709+ @success (json) "success-json" A JSON object containing
2710+ information about the requested node.
2711+ @success-example "success-json" [exkey=read-node] placeholder text
2712
2713- Returns 404 if the node is not found.
2714+ @error (http-status-code) "404" 404
2715+ @error (content) "not-found" The requested node is not found.
2716+ @error-example "not-found"
2717+ Not Found
2718 """
2719 node = self.model.objects.get_node_or_404(
2720 system_id=system_id, user=request.user, perm=NodePermission.view)
2721@@ -434,11 +446,21 @@ class NodeHandler(OperationsHandler):
2722 return node.as_self()
2723
2724 def delete(self, request, system_id):
2725- """Delete a specific Node.
2726+ """@description-title Delete a node
2727+ @description Deletes a node with a given system_id.
2728+
2729+ @param (string) "{system_id}" [required=true] A node's system_id.
2730+
2731+ @success (http-status-code) "204" 204
2732+
2733+ @error (http-status-code) "404" 404
2734+ @error (content) "not-found" The requested node is not found.
2735+ @error-example "not-found"
2736+ Not Found
2737
2738- Returns 404 if the node is not found.
2739- Returns 403 if the user does not have permission to delete the node.
2740- Returns 204 if the node is successfully deleted.
2741+ @error (http-status-code) "403" 403
2742+ @error (content) "no-perms" The user is not authorized to delete the
2743+ node.
2744 """
2745 node = self.model.objects.get_node_or_404(
2746 system_id=system_id, user=request.user,
2747@@ -476,18 +498,31 @@ class NodeHandler(OperationsHandler):
2748
2749 @operation(idempotent=True)
2750 def details(self, request, system_id):
2751- """Obtain various system details.
2752-
2753- For example, LLDP and ``lshw`` XML dumps.
2754+ """@description-title Get system details
2755+ @description Returns system details -- for example, LLDP and
2756+ ``lshw`` XML dumps.
2757
2758 Returns a ``{detail_type: xml, ...}`` map, where
2759 ``detail_type`` is something like "lldp" or "lshw".
2760
2761 Note that this is returned as BSON and not JSON. This is for
2762- efficiency, but mainly because JSON can't do binary content
2763- without applying additional encoding like base-64.
2764+ efficiency, but mainly because JSON can't do binary content without
2765+ applying additional encoding like base-64. The example output below is
2766+ represented in ASCII using ``bsondump example.bson`` and is for
2767+ demonstrative purposes.
2768+
2769+ @param (string) "{system_id}" [required=true] The node's system_id.
2770+
2771+ @success (http-status-code) "200" 200
2772
2773- Returns 404 if the node is not found.
2774+ @success (content) "success-content" A BSON object represented here in
2775+ ASCII using ``bsondump example.bson``.
2776+ @success-example "success-content" [exkey=details] placeholder text
2777+
2778+ @error (http-status-code) "404" 404
2779+ @error (content) "not-found" The requested node is not found.
2780+ @error-example "not-found"
2781+ Not Found
2782 """
2783 node = get_object_or_404(self.model, system_id=system_id)
2784 probe_details = get_single_probed_details(node)
2785@@ -503,16 +538,26 @@ class NodeHandler(OperationsHandler):
2786 @admin_method
2787 @operation(idempotent=True)
2788 def power_parameters(self, request, system_id):
2789- """Obtain power parameters.
2790-
2791- This method is reserved for admin users and returns a 403 if the
2792- user is not one.
2793-
2794- This returns the power parameters, if any, configured for a
2795- node. For some types of power control this will include private
2796- information such as passwords and secret keys.
2797-
2798- Returns 404 if the node is not found.
2799+ """@description-title Get power parameters
2800+ @description Gets power parameters for a given system_id, if any. For
2801+ some types of power control this will include private information such
2802+ as passwords and secret keys.
2803+
2804+ Note that this method is reserved for admin users and returns a 403 if
2805+ the user is not one.
2806+
2807+ @success (http-status-code) "200" 200
2808+
2809+ @error (http-status-code) "403" 403
2810+ @error (content) "no-perms" The user does not have permission to see
2811+ the power parameters.
2812+ @error-example "no-perms"
2813+ This method is reserved for admin users.
2814+
2815+ @error (http-status-code) "404" 404
2816+ @error (content) "not-found" The requested node is not found.
2817+ @error-example "not-found"
2818+ Not Found
2819 """
2820 node = get_object_or_404(self.model, system_id=system_id)
2821 return node.power_parameters
2822@@ -532,15 +577,24 @@ class AnonNodesHandler(AnonymousOperationsHandler):
2823
2824 @operation(idempotent=True)
2825 def is_registered(self, request):
2826- """Returns whether or not the given MAC address is registered within
2827- this MAAS (and attached to a non-retired node).
2828-
2829- :param mac_address: The mac address to be checked.
2830- :type mac_address: unicode
2831- :return: 'true' or 'false'.
2832- :rtype: unicode
2833-
2834- Returns 400 if any mandatory parameters are missing.
2835+ """@description-title MAC address registered
2836+ @description Returns whether or not the given MAC address is registered
2837+ within this MAAS (and attached to a non-retired node).
2838+
2839+ @param (url-string) "mac_address" [required=true] The MAC address to be
2840+ checked.
2841+ @param-example "mac_address"
2842+ ``/nodes/?op=is_registered&mac_address=28:16:ad:a1:fa:63``
2843+
2844+ @success (http-status-code) "200" 200
2845+ @success (boolean) "success_example" 'true' or 'false'
2846+ @success-example "success_example"
2847+ false
2848+
2849+ @error (http-status-code) "400" 400
2850+ @error (content) "no-address" mac_address was missing
2851+ @error-example "no-address"
2852+ No provided mac_address!
2853 """
2854 # If a node is added with missing/incorrect arch/boot MAC it will
2855 # enter enlistment instead of commissioning. Enlistment should be
2856@@ -555,13 +609,24 @@ class AnonNodesHandler(AnonymousOperationsHandler):
2857
2858 @operation(idempotent=True)
2859 def is_action_in_progress(self, request):
2860- """Returns whether or not the given MAC address is a machine
2861+ """@description-title MAC address of deploying or commissioning node
2862+ @description Returns whether or not the given MAC address is a machine
2863 that's either 'deploying' or 'commissioning'.
2864
2865- :param mac_address: The mac address to be checked.
2866- :type mac_address: unicode
2867- :return: 'true' or 'false'.
2868- :rtype: unicode
2869+ @param (url-string) "mac_address" [required=true] The MAC address to be
2870+ checked.
2871+ @param-example "mac_address"
2872+ ``/nodes/?op=is_action_in_progress&mac_address=28:16:ad:a1:fa:63``
2873+
2874+ @success (http-status-code) "200" 200
2875+ @success (boolean) "success_example" 'true' or 'false'
2876+ @success "success_example"
2877+ false
2878+
2879+ @error (http-status-code) "400" 400
2880+ @error (content) "no-address" mac_address was missing
2881+ @error-example "no-address"
2882+ No provided mac_address!
2883 """
2884 mac_address = get_mandatory_param(request.GET, 'mac_address')
2885 interfaces = Interface.objects.filter(mac_address=mac_address)
2886@@ -583,39 +648,41 @@ class NodesHandler(OperationsHandler):
2887 base_model = Node
2888
2889 def read(self, request):
2890- """List Nodes visible to the user, optionally filtered by criteria.
2891+ """@description-title List Nodes visible to the user
2892+ @description List nodes visible to current user, optionally filtered by
2893+ criteria.
2894
2895 Nodes are sorted by id (i.e. most recent last) and grouped by type.
2896
2897- :param hostname: An optional hostname. Only nodes relating to the node
2898- with the matching hostname will be returned. This can be specified
2899- multiple times to see multiple nodes.
2900- :type hostname: unicode
2901+ @param (string) "hostname" [required=false] Only nodes relating to the
2902+ node with the matching hostname will be returned. This can be specified
2903+ multiple times to see multiple nodes.
2904+
2905+ @param (string) "mac_address" [required=false] Only nodes relating to
2906+ the node owning the specified MAC address will be returned. This can be
2907+ specified multiple times to see multiple nodes.
2908
2909- :param mac_address: An optional MAC address. Only nodes relating to the
2910- node owning the specified MAC address will be returned. This can be
2911- specified multiple times to see multiple nodes.
2912- :type mac_address: unicode
2913+ @param (string) "id" [required=false] Only nodes relating to the nodes
2914+ with matching system ids will be returned.
2915
2916- :param id: An optional list of system ids. Only nodes relating to the
2917- nodes with matching system ids will be returned.
2918- :type id: unicode
2919+ @param (string) "domain" [required=false] Only nodes relating to the
2920+ nodes in the domain will be returned.
2921
2922- :param domain: An optional name for a dns domain. Only nodes relating
2923- to the nodes in the domain will be returned.
2924- :type domain: unicode
2925+ @param (string) "zone" [required=false] Only nodes relating to the
2926+ nodes in the zone will be returned.
2927
2928- :param zone: An optional name for a physical zone. Only nodes relating
2929- to the nodes in the zone will be returned.
2930- :type zone: unicode
2931+ @param (string) "pool" [required=false] Only nodes belonging to the
2932+ pool will be returned.
2933
2934- :param pool: An optional name for a resource pool. Only nodes belonging
2935- to the pool will be returned.
2936- :type pool: unicode
2937+ @param (string) "agent_name" [required=false] Only nodes relating to
2938+ the nodes with matching agent names will be returned.
2939
2940- :param agent_name: An optional agent name. Only nodes relating to the
2941- nodes with matching agent names will be returned.
2942- :type agent_name: unicode
2943+ @success (http-status-code) "200" 200
2944+
2945+ @success (json) "success_json" A JSON object containing a list of node
2946+ objects.
2947+ @success-example "success_json" [exkey=read-visible-nodes] placeholder
2948+ text
2949 """
2950
2951 if self.base_model == Node:
2952@@ -650,29 +717,46 @@ class NodesHandler(OperationsHandler):
2953
2954 @operation(idempotent=True)
2955 def is_registered(self, request):
2956- """Returns whether or not the given MAC address is registered within
2957- this MAAS (and attached to a non-retired node).
2958+ """@description-title MAC address registered
2959+ @description Returns whether or not the given MAC address is registered
2960+ within this MAAS (and attached to a non-retired node).
2961+
2962+ @param (url-string) "mac_address" [required=true] The MAC address to be
2963+ checked.
2964+ @param-example "mac_address"
2965+ ``/nodes/?op=is_registered&mac_address=28:16:ad:a1:fa:63``
2966+
2967+ @success (http-status-code) "200" 200
2968
2969- :param mac_address: The mac address to be checked.
2970- :type mac_address: unicode
2971- :return: 'true' or 'false'.
2972- :rtype: unicode
2973+ @success (boolean) "success_example" 'true' or 'false'
2974+ @success-example "success_example"
2975+ false
2976
2977- Returns 400 if any mandatory parameters are missing.
2978+ @error (http-status-code) "400" 400
2979+ @error (content) "no-address" mac_address was missing
2980+ @error-example "no-address"
2981+ No provided mac_address!
2982 """
2983 return is_registered(request)
2984
2985 @admin_method
2986 @operation(idempotent=False)
2987 def set_zone(self, request):
2988- """Assign multiple nodes to a physical zone at once.
2989+ """@description-title Assign nodes to a zone
2990+ @description Assigns a given node to a given zone.
2991+
2992+ @param (string) "zone" [required=true] The zone name.
2993+ @param (string) "nodes" [required=true] The node to add.
2994+
2995+ @success (http-status-code) "204" 204
2996
2997- :param zone: Zone name. If omitted, the zone is "none" and the nodes
2998- will be taken out of their physical zones.
2999- :param nodes: system_ids of the nodes whose zones are to be set.
3000- (An empty list is acceptable).
3001+ @error (http-status-code) "403" 403
3002+ @error (content) "no-perms" The user does not have set the zone.
3003+ @error-example "no-perms"
3004+ This method is reserved for admin users.
3005
3006- Raises 403 if the user is not an admin.
3007+ @error (http-status-code) "400" 400
3008+ @error (content) "bad-param" The given parameters were not correct.
3009 """
3010 data = {
3011 'action': 'set_zone',
3012@@ -703,17 +787,25 @@ class OwnerDataMixin:
3013
3014 @operation(idempotent=False)
3015 def set_owner_data(self, request, system_id):
3016- """Set key/value data for the current owner.
3017+ """@description-title Set key=value data
3018+ @description Set key=value data for the current owner.
3019
3020- Pass any key/value data to this method to add, modify, or remove. A key
3021- is removed when the value for that key is set to an empty string.
3022+ Pass any key=value form data to this method to add, modify, or remove.
3023+ A key is removed when the value for that key is set to an empty string.
3024
3025 This operation will not remove any previous keys unless explicitly
3026 passed with an empty string. All owner data is removed when the machine
3027 is no longer allocated to a user.
3028
3029- Returns 404 if the machine is not found.
3030- Returns 403 if the user does not have permission.
3031+ @param (string) "key" [required=true] ``key`` can be any string value.
3032+
3033+ @success (http-status-code) "204" 204
3034+
3035+ @error (http-status-code) "404" 404
3036+ @error (content) "not-found" The requested node is not found.
3037+
3038+ @error (http-status-code) "403" 403
3039+ @error (content) "no-perms" The user does not have set the zone.
3040 """
3041 node = self.model.objects.get_node_or_404(
3042 user=request.user, system_id=system_id, perm=NodePermission.edit)
3043@@ -731,20 +823,25 @@ class PowerMixin:
3044
3045 @operation(idempotent=True)
3046 def query_power_state(self, request, system_id):
3047- """Query the power state of a node.
3048-
3049- Send a request to the node's power controller which asks it about
3050- the node's state. The reply to this could be delayed by up to
3051- 30 seconds while waiting for the power controller to respond.
3052- Use this method sparingly as it ties up an appserver thread
3053- while waiting.
3054-
3055- :param system_id: The node to query.
3056- :return: a dict whose key is "state" with a value of one of
3057- 'on' or 'off'.
3058-
3059- Returns 404 if the node is not found.
3060- Returns node's power state.
3061+ """@description-title Get the power state of a node
3062+ @description Gets the power state of a given node. MAAS sends a request
3063+ to the node's power controller, which asks it about the node's state.
3064+ The reply to this could be delayed by up to 30 seconds while waiting
3065+ for the power controller to respond. Use this method sparingly as it
3066+ ties up an appserver thread while waiting.
3067+
3068+ @param (string) "system_id" [required=true] The node to query.
3069+
3070+ @success (http-status-code) "200" 200
3071+ @success (json) "success_json" A JSON object containing the node's
3072+ power state.
3073+ @success-example "success_json" [exkey=query-power-state] placeholder
3074+ text.
3075+
3076+ @error (http-status-code) "404" 404
3077+ @error (content) "not-found" The requested node is not found.
3078+ @error-example "not-found"
3079+ Not Found
3080 """
3081 node = self.model.objects.get_node_or_404(
3082 system_id=system_id, user=request.user,
3083@@ -755,24 +852,33 @@ class PowerMixin:
3084
3085 @operation(idempotent=False)
3086 def power_on(self, request, system_id):
3087- """Turn on a node.
3088-
3089- :param user_data: If present, this blob of user-data to be made
3090- available to the nodes through the metadata service.
3091- :type user_data: base64-encoded unicode
3092- :param comment: Optional comment for the event log.
3093- :type comment: unicode
3094-
3095- Ideally we'd have MIME multipart and content-transfer-encoding etc.
3096- deal with the encapsulation of binary data, but couldn't make it work
3097- with the framework in reasonable time so went for a dumb, manual
3098- encoding instead.
3099-
3100- Returns 404 if the node is not found.
3101- Returns 403 if the user does not have permission to start the machine.
3102- Returns 503 if the start-up attempted to allocate an IP address,
3103- and there were no IP addresses available on the relevant cluster
3104- interface.
3105+ """@description-title Turn on a node
3106+ @description Turn on the given node with optional user-data and
3107+ comment.
3108+
3109+ @param (string) "user_data" [required=false] Base64-encoded blob of
3110+ data to be made available to the nodes through the metadata service.
3111+
3112+ @param (string) "comment" [required=false] Comment for the event log.
3113+
3114+ @success (http-status-code) "204" 204
3115+ @success (json) "success_json" A JSON object containing the node's
3116+ information.
3117+ @success-example "success_json" [exkey=power-on] placeholder text
3118+
3119+ @error (http-status-code) "404" 404
3120+ @error (content) "not-found" The requested node is not found.
3121+ @error-example "not-found"
3122+ Not Found
3123+
3124+ @error (http-status-code) "403" 403
3125+ @error (content) "no-perms" The user is not authorized to power on the
3126+ node.
3127+
3128+ @error (http-status-code) "503" 503
3129+ @error (content) "no-ips" Returns 503 if the start-up attempted to
3130+ allocate an IP address, and there were no IP addresses available on the
3131+ relevant cluster interface.
3132 """
3133 user_data = request.POST.get('user_data', None)
3134 comment = get_optional_param(request.POST, 'comment')
3135@@ -797,21 +903,32 @@ class PowerMixin:
3136
3137 @operation(idempotent=False)
3138 def power_off(self, request, system_id):
3139- """Power off a node.
3140-
3141- :param stop_mode: An optional power off mode. If 'soft',
3142- perform a soft power down if the node's power type supports
3143- it, otherwise perform a hard power off. For all values other
3144- than 'soft', and by default, perform a hard power off. A
3145- soft power off generally asks the OS to shutdown the system
3146- gracefully before powering off, while a hard power off
3147- occurs immediately without any warning to the OS.
3148- :type stop_mode: unicode
3149- :param comment: Optional comment for the event log.
3150- :type comment: unicode
3151-
3152- Returns 404 if the node is not found.
3153- Returns 403 if the user does not have permission to stop the node.
3154+ """@description-title Power off a node
3155+ @description Powers off a given node.
3156+
3157+ @param (string) "stop_mode" [required=false] Power-off mode. If 'soft',
3158+ perform a soft power down if the node's power type supports it,
3159+ otherwise perform a hard power off. For all values other than 'soft',
3160+ and by default, perform a hard power off. A soft power off generally
3161+ asks the OS to shutdown the system gracefully before powering off,
3162+ while a hard power off occurs immediately without any warning to the
3163+ OS.
3164+
3165+ @param (string) "comment" [required=false] Comment for the event log.
3166+
3167+ @success (http-status-code) "204" 204
3168+ @success (json) "success_json" A JSON object containing the node's
3169+ information.
3170+ @success-example "success_json" [exkey=power-off] placeholder text
3171+
3172+ @error (http-status-code) "404" 404
3173+ @error (content) "not-found" The requested node is not found.
3174+ @error-example "not-found"
3175+ Not Found
3176+
3177+ @error (http-status-code) "403" 403
3178+ @error (content) "no-perms" The user is not authorized to power off the
3179+ node.
3180 """
3181 stop_mode = request.POST.get('stop_mode', 'hard')
3182 comment = get_optional_param(request.POST, 'comment')
3183@@ -827,23 +944,32 @@ class PowerMixin:
3184
3185 @operation(idempotent=False)
3186 def test(self, request, system_id):
3187- """Begin testing process for a node.
3188-
3189- :param enable_ssh: Whether to enable SSH for the testing environment
3190- using the user's SSH key(s).
3191- :type enable_ssh: bool ('0' for False, '1' for True)
3192- :param testing_scripts: A comma seperated list of testing script names
3193- and tags to be run. By default all tests tagged 'commissioning'
3194- will be run.
3195- :type testing_scripts: string
3196+ """@description-title Begin testing process for a node
3197+ @description Begins the testing process for a given node.
3198
3199 A node in the 'ready', 'allocated', 'deployed', 'broken', or any failed
3200 state may run tests. If testing is started and successfully passes from
3201- a 'broken', or any failed state besides 'failed commissioning' the node
3202+ 'broken' or any failed state besides 'failed commissioning' the node
3203 will be returned to a ready state. Otherwise the node will return to
3204 the state it was when testing started.
3205
3206- Returns 404 if the node is not found.
3207+ @param (int) "enable_ssh" [required=false] Whether to enable SSH for
3208+ the testing environment using the user's SSH key(s). 0 == false. 1 ==
3209+ true.
3210+
3211+ @param (string) "testing_scripts" [required=false] A comma-separated
3212+ list of testing script names and tags to be run. By default all tests
3213+ tagged 'commissioning' will be run.
3214+
3215+ @success (http-status-code) "204" 204
3216+ @success (json) "success_json" A JSON object containing the node's
3217+ information.
3218+ @success-example "success_json" [exkey=test] placeholder text
3219+
3220+ @error (http-status-code) "404" 404
3221+ @error (content) "not-found" The requested node is not found.
3222+ @error-example "not-found"
3223+ Not Found
3224 """
3225 node = self.model.objects.get_node_or_404(
3226 system_id=system_id, user=request.user, perm=NodePermission.admin)
3227@@ -858,14 +984,21 @@ class PowerMixin:
3228
3229 @operation(idempotent=False)
3230 def override_failed_testing(self, request, system_id):
3231- """Ignore failed tests and put node back into a usable state.
3232+ """@description-title Ignore failed tests
3233+ @description Ignore failed tests and put node back into a usable state.
3234+
3235+ @param (string) "comment" [required=false] Comment for the event log.
3236+
3237+ @success (http-status-code) "204" 204
3238
3239- :param comment: Optional comment for the event log.
3240- :type comment: unicode
3241+ @error (http-status-code) "404" 404
3242+ @error (content) "not-found" The requested node is not found.
3243+ @error-example "not-found"
3244+ Not Found
3245
3246- Returns 404 if the machine is not found.
3247- Returns 403 if the user does not have permission to ignore tests for
3248- the node.
3249+ @error (http-status-code) "403" 403
3250+ @error (content) "no-perms" The user is not authorized to override
3251+ tests.
3252 """
3253 comment = get_optional_param(request.POST, 'comment')
3254 node = self.model.objects.get_node_or_404(
3255@@ -875,13 +1008,20 @@ class PowerMixin:
3256
3257 @operation(idempotent=False)
3258 def abort(self, request, system_id):
3259- """Abort a node's current operation.
3260+ """@description-title Abort a node operation
3261+ @description Abort a node's current operation.
3262
3263- :param comment: Optional comment for the event log.
3264- :type comment: unicode
3265+ @param (string) "comment" [required=false] Comment for the event log.
3266
3267- Returns 404 if the node could not be found.
3268- Returns 403 if the user does not have permission to abort the
3269+ @success (http-status-code) "204" 204
3270+
3271+ @error (http-status-code) "404" 404
3272+ @error (content) "not-found" The requested node is not found.
3273+ @error-example "not-found"
3274+ Not Found
3275+
3276+ @error (http-status-code) "403" 403
3277+ @error (content) "no-perms" The user is not authorized to abort the
3278 current operation.
3279 """
3280 comment = get_optional_param(request.POST, 'comment')
3281@@ -898,15 +1038,26 @@ class PowersMixin:
3282 @admin_method
3283 @operation(idempotent=True)
3284 def power_parameters(self, request):
3285- """Retrieve power parameters for multiple machines.
3286-
3287- :param id: An optional list of system ids. Only machines with
3288- matching system ids will be returned.
3289- :type id: iterable
3290-
3291- :return: A dictionary of power parameters, keyed by machine system_id.
3292-
3293- Raises 403 if the user is not an admin.
3294+ """@description-title Get power parameters
3295+ @description Get power parameters for multiple machines. To request
3296+ power parameters for a specific machine or more than one machine:
3297+ ``op=power_parameters&id=abc123&id=def456``.
3298+
3299+ @param (url-string) "id" [required=false] A system ID. To request more
3300+ than one machine, provide multiple ``id`` arguments in the request.
3301+ Only machines with matching system ids will be returned.
3302+ @param-example "id"
3303+ op=power_parameters&id=abc123&id=def456
3304+
3305+ @success (http-status-code) "200" 200
3306+ @success (json) "success_json" A JSON object containing a list of
3307+ power parameters with system_ids as keys.
3308+ @success-example "success_json" [exkey=get-power-params] placeholder
3309+ text
3310+
3311+ @error (http-status-code) "403" 403
3312+ @error (content) "no-perms" The user is not authorized to view the
3313+ power parameters.
3314 """
3315 match_ids = get_optional_list(request.GET, 'id')
3316
3317diff --git a/src/maasserver/api/tests/test_annotations.py b/src/maasserver/api/tests/test_annotations.py
3318index e669171..896b4a0 100644
3319--- a/src/maasserver/api/tests/test_annotations.py
3320+++ b/src/maasserver/api/tests/test_annotations.py
3321@@ -66,7 +66,10 @@ class TestAPIAnnotations(APITestCase.ForUser):
3322 @success-example "success_name" success content
3323
3324 @success (content) "success_with_exdb" success description
3325- @success-example "success_with_exdb" [exkey=key1] ignored content
3326+ @success-example "success_with_exdb" [exkey=key1] placeholder text
3327+
3328+ @success (content) "success_inherit_node" success description
3329+ @success-example "success_inherit_node" [exkey=read-node] placeholder text
3330
3331 @error (http-status-code) "error_name" error description
3332 @error-example "error_name" error content
3333@@ -606,3 +609,25 @@ class TestAPIAnnotations(APITestCase.ForUser):
3334 d = api_docstring_parser.get_dict()
3335
3336 self.assert_has_api_warning(d)
3337+
3338+ def test_load_nodes_examples_by_default(self):
3339+ """Nodes examples should be loading by default.
3340+
3341+ Some API objects like machines and devices inherit operations from
3342+ nodes, so when we load the examples database, we always start with
3343+ nodes and add on object-specific examples.
3344+ """
3345+ ds = self.sample_api_annotated_docstring
3346+
3347+ api_docstring_parser = APIDocstringParser()
3348+ api_docstring_parser.parse(ds, uri=self.test_uri_plural)
3349+ d = api_docstring_parser.get_dict()
3350+
3351+ # index=2 contains the example with inherited examples from
3352+ # example/nodes.json
3353+ s = d['successes'][2]
3354+
3355+ # The presence of the 'resource-uri' string is a good indicator
3356+ # that the 'read-node' key has picked up the JSON object and
3357+ # converted it to a string for output in API docs.
3358+ self.assertTrue(s['example'].find("resource_uri") != -1)

Subscribers

People subscribed via source and target branches