Merge ~jsseidel/maas:jsseidel-partitions-api-annotations into maas:master

Proposed by Spencer Seidel
Status: Merged
Approved by: Spencer Seidel
Approved revision: a67377294220f9b6fab4e4031c9a3afd1afbce4d
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~jsseidel/maas:jsseidel-partitions-api-annotations
Merge into: maas:master
Diff against target: 565 lines (+425/-50)
2 files modified
src/maasserver/api/examples/nodes.json (+197/-0)
src/maasserver/api/partitions.py (+228/-50)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Mike Pontillo (community) Approve
Review via email: mp+361159@code.launchpad.net

Commit message

Added API annotations and examples to partitions.

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b jsseidel-partitions-api-annotations lp:~jsseidel/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4779/console
COMMIT: ffc1a7cd174501710f37c842835e083b099df6cd

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b jsseidel-partitions-api-annotations lp:~jsseidel/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4796/console
COMMIT: 89a415f783fc9c548bf59dff6c6626dc1f5ed7e1

review: Needs Fixing
Revision history for this message
Mike Pontillo (mpontillo) wrote :

LGTM.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

LANDING
-b jsseidel-partitions-api-annotations lp:~jsseidel/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4820/consoleText

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b jsseidel-partitions-api-annotations lp:~jsseidel/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4822/console
COMMIT: 638dc1b975bbd29d543bef8f58badebf8bbb4eda

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b jsseidel-partitions-api-annotations lp:~jsseidel/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: a67377294220f9b6fab4e4031c9a3afd1afbce4d

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

LANDING
-b jsseidel-partitions-api-annotations lp:~jsseidel/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/4827/consoleText

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/examples/nodes.json b/src/maasserver/api/examples/nodes.json
2index dfebdee..b862bb4 100644
3--- a/src/maasserver/api/examples/nodes.json
4+++ b/src/maasserver/api/examples/nodes.json
5@@ -5224,6 +5224,203 @@
6 "type": "physical",
7 "resource_uri": "/MAAS/api/2.0/nodes/thr3am/interfaces/37/"
8 },
9+ "partitions-read": [
10+ {
11+ "id_path": "/dev/vda",
12+ "size": 8000000000,
13+ "block_size": 4096,
14+ "tags": [
15+ "rotary"
16+ ],
17+ "path": "/dev/disk/by-dname/vda",
18+ "system_id": "ccrfnk",
19+ "uuid": null,
20+ "used_size": 7999586304,
21+ "used_for": "MBR partitioned with 1 partition",
22+ "partitions": [
23+ {
24+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
25+ "size": 7994343424,
26+ "bootable": false,
27+ "tags": [],
28+ "path": "/dev/disk/by-dname/vda-part1",
29+ "system_id": "ccrfnk",
30+ "used_for": "ext4 formatted filesystem mounted at /",
31+ "filesystem": {
32+ "fstype": "ext4",
33+ "label": "root",
34+ "uuid": "f698b5ee-d53c-4538-86cf-ee4b23d37db6",
35+ "mount_point": "/",
36+ "mount_options": null
37+ },
38+ "id": 1,
39+ "type": "partition",
40+ "device_id": 1,
41+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
42+ }
43+ ],
44+ "filesystem": null,
45+ "id": 1,
46+ "partition_table_type": "MBR",
47+ "storage_pool": "18afd485-1491-43c9-a876-7af737d03698",
48+ "type": "physical",
49+ "name": "vda",
50+ "serial": "",
51+ "available_size": 0,
52+ "model": "",
53+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/"
54+ }
55+ ],
56+ "partitions-read-by-id": {
57+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
58+ "size": 7994343424,
59+ "bootable": false,
60+ "tags": [],
61+ "path": "/dev/disk/by-dname/vda-part1",
62+ "system_id": "ccrfnk",
63+ "used_for": "ext4 formatted filesystem mounted at /",
64+ "filesystem": {
65+ "fstype": "ext4",
66+ "label": "root",
67+ "uuid": "f698b5ee-d53c-4538-86cf-ee4b23d37db6",
68+ "mount_point": "/",
69+ "mount_options": null
70+ },
71+ "id": 1,
72+ "type": "partition",
73+ "device_id": 1,
74+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
75+ },
76+ "partitions-format": {
77+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
78+ "size": 7994343424,
79+ "bootable": false,
80+ "tags": [],
81+ "device_id": 1,
82+ "system_id": "ccrfnk",
83+ "filesystem": {
84+ "fstype": "ext4",
85+ "label": "",
86+ "uuid": "ad185012-fa9e-486d-8869-16bf297272c8",
87+ "mount_point": null,
88+ "mount_options": null
89+ },
90+ "used_for": "Unmounted ext4 formatted filesystem",
91+ "type": "partition",
92+ "id": 1,
93+ "path": "/dev/disk/by-dname/vda-part1",
94+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
95+ },
96+ "partitions-unformat": {
97+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
98+ "size": 7994343424,
99+ "bootable": false,
100+ "tags": [],
101+ "used_for": "Unused",
102+ "filesystem": null,
103+ "system_id": "ccrfnk",
104+ "path": "/dev/disk/by-dname/vda-part1",
105+ "type": "partition",
106+ "id": 1,
107+ "device_id": 1,
108+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
109+ },
110+ "partitions-mount": {
111+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
112+ "size": 7994343424,
113+ "bootable": false,
114+ "tags": [],
115+ "device_id": 1,
116+ "system_id": "ccrfnk",
117+ "filesystem": {
118+ "fstype": "ext4",
119+ "label": "",
120+ "uuid": "a73c0701-9216-40ca-857f-63c65b4e7059",
121+ "mount_point": "/",
122+ "mount_options": ""
123+ },
124+ "used_for": "ext4 formatted filesystem mounted at /",
125+ "type": "partition",
126+ "id": 1,
127+ "path": "/dev/disk/by-dname/vda-part1",
128+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
129+ },
130+ "partitions-unmount": {
131+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
132+ "size": 7994343424,
133+ "bootable": false,
134+ "tags": [],
135+ "device_id": 1,
136+ "system_id": "ccrfnk",
137+ "filesystem": {
138+ "fstype": "ext4",
139+ "label": "",
140+ "uuid": "a73c0701-9216-40ca-857f-63c65b4e7059",
141+ "mount_point": null,
142+ "mount_options": null
143+ },
144+ "used_for": "Unmounted ext4 formatted filesystem",
145+ "type": "partition",
146+ "id": 1,
147+ "path": "/dev/disk/by-dname/vda-part1",
148+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
149+ },
150+ "partitions-add-tag": {
151+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
152+ "size": 7994343424,
153+ "bootable": false,
154+ "tags": [
155+ "mytag"
156+ ],
157+ "device_id": 1,
158+ "system_id": "ccrfnk",
159+ "filesystem": {
160+ "fstype": "ext4",
161+ "label": "",
162+ "uuid": "a73c0701-9216-40ca-857f-63c65b4e7059",
163+ "mount_point": null,
164+ "mount_options": null
165+ },
166+ "used_for": "Unmounted ext4 formatted filesystem",
167+ "type": "partition",
168+ "id": 1,
169+ "path": "/dev/disk/by-dname/vda-part1",
170+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
171+ },
172+ "partitions-rem-tag": {
173+ "uuid": "95f5d47d-0abd-408b-b3f1-c3f4df152609",
174+ "size": 7994343424,
175+ "bootable": false,
176+ "tags": [],
177+ "device_id": 1,
178+ "system_id": "ccrfnk",
179+ "filesystem": {
180+ "fstype": "ext4",
181+ "label": "",
182+ "uuid": "a73c0701-9216-40ca-857f-63c65b4e7059",
183+ "mount_point": null,
184+ "mount_options": null
185+ },
186+ "used_for": "Unmounted ext4 formatted filesystem",
187+ "type": "partition",
188+ "id": 1,
189+ "path": "/dev/disk/by-dname/vda-part1",
190+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/1"
191+ },
192+ "partitions-create": {
193+ "uuid": "ecfa7d5b-bb76-4443-83ab-ad600c23b4de",
194+ "size": 7994343424,
195+ "bootable": false,
196+ "tags": [],
197+ "device_id": 1,
198+ "system_id": "ccrfnk",
199+ "filesystem": null,
200+ "used_for": "Unused",
201+ "type": "partition",
202+ "id": 2,
203+ "path": "/dev/disk/by-dname/vda-part1",
204+ "resource_uri": "/MAAS/api/2.0/nodes/ccrfnk/blockdevices/1/partition/2"
205+ },
206 "raids-placeholder": {
207 "message": "Information about this object is not available at this time."
208 }
209diff --git a/src/maasserver/api/partitions.py b/src/maasserver/api/partitions.py
210index 8ca0a26..6339687 100644
211--- a/src/maasserver/api/partitions.py
212+++ b/src/maasserver/api/partitions.py
213@@ -83,9 +83,24 @@ class PartitionsHandler(OperationsHandler):
214 'partitions_handler', ["system_id", "device_id"])
215
216 def read(self, request, system_id, device_id):
217- """List all partitions on the block device.
218-
219- Returns 404 if the node or the block device are not found.
220+ """@description-title List partitions
221+ @description List partitions on a device with the given system_id and
222+ device_id.
223+
224+ @param (string) "{system_id}" [required=true] The system_id.
225+ @param (int) "{device_id}" [required=true] The block device_id.
226+
227+ @success (http-status-code) "server-success" 200
228+ @success (json) "success-json" A JSON object containing a list of
229+ partition objects.
230+ @success-example "success-json" [exkey=partitions-read]
231+ placeholder text
232+
233+ @error (http-status-code) "404" 404
234+ @error (content) "not-found" The requested machine or device is not
235+ found.
236+ @error-example "not-found"
237+ Not Found
238 """
239 device = BlockDevice.objects.get_block_device_or_404(
240 system_id, device_id, request.user, NodePermission.view)
241@@ -96,15 +111,32 @@ class PartitionsHandler(OperationsHandler):
242 return partition_table.partitions.all()
243
244 def create(self, request, system_id, device_id):
245- """Create a partition on the block device.
246+ """@description-title Create a partition
247+ @description Create a partition on a block device.
248+
249+ @param (string) "{system_id}" [required=true] The system_id.
250+ @param (int) "{device_id}" [required=true] The block device_id.
251+
252+ @param (int) "size" [required=false] The size of the partition. If not
253+ specified, all available space will be used.
254
255- :param size: The size of the partition. If not specified, all
256- available space will be used.
257- :param uuid: UUID for the partition. Only used if the partition table
258- type for the block device is GPT.
259- :param bootable: If the partition should be marked bootable.
260+ @param (string) "uuid" [required=false] UUID for the partition. Only
261+ used if the partition table type for the block device is GPT.
262
263- Returns 404 if the node or the block device are not found.
264+ @param (boolean) "bootable" [required=false] If the partition should be
265+ marked bootable.
266+
267+ @success (http-status-code) "server-success" 200
268+ @success (json) "success-json" A JSON object containing the new
269+ partition object.
270+ @success-example "success-json" [exkey=partitions-create]
271+ placeholder text
272+
273+ @error (http-status-code) "404" 404
274+ @error (content) "not-found" The requested machine or device is not
275+ found.
276+ @error-example "not-found"
277+ Not Found
278 """
279 device = BlockDevice.objects.get_block_device_or_404(
280 system_id, device_id, request.user, NodePermission.admin)
281@@ -167,9 +199,25 @@ class PartitionHandler(OperationsHandler):
282 return partition.partition_table.block_device.id
283
284 def read(self, request, system_id, device_id, id):
285- """Read partition.
286-
287- Returns 404 if the node, block device, or partition are not found.
288+ """@description-title Read a partition
289+ @description Read the partition from machine system_id and device
290+ device_id with the given partition id.
291+
292+ @param (string) "{system_id}" [required=true] The system_id.
293+ @param (int) "{device_id}" [required=true] The block device_id.
294+ @param (int) "{id}" [required=true] The partition id.
295+
296+ @success (http-status-code) "server-success" 200
297+ @success (json) "success-json" A JSON object containing the requested
298+ partition object.
299+ @success-example "success-json" [exkey=partitions-read]
300+ placeholder text
301+
302+ @error (http-status-code) "404" 404
303+ @error (content) "not-found" The requested machine, device or partition
304+ is not found.
305+ @error-example "not-found"
306+ Not Found
307 """
308 device = BlockDevice.objects.get_block_device_or_404(
309 system_id, device_id, request.user, NodePermission.view)
310@@ -179,9 +227,21 @@ class PartitionHandler(OperationsHandler):
311 id, partition_table)
312
313 def delete(self, request, system_id, device_id, id):
314- """Delete partition.
315+ """@description-title Delete a partition
316+ @description Delete the partition from machine system_id and device
317+ device_id with the given partition id.
318
319- Returns 404 if the node, block device, or partition are not found.
320+ @param (string) "{system_id}" [required=true] The system_id.
321+ @param (int) "{device_id}" [required=true] The block device_id.
322+ @param (int) "{id}" [required=true] The partition id.
323+
324+ @success (http-status-code) "server-success" 204
325+
326+ @error (http-status-code) "404" 404
327+ @error (content) "not-found" The requested machine, device or partition
328+ is not found.
329+ @error-example "not-found"
330+ Not Found
331 """
332 device = BlockDevice.objects.get_block_device_or_404(
333 system_id, device_id, request.user, NodePermission.admin)
334@@ -198,15 +258,35 @@ class PartitionHandler(OperationsHandler):
335
336 @operation(idempotent=False)
337 def format(self, request, system_id, device_id, id):
338- """Format a partition.
339+ """@description-title Format a partition
340+ @description Format the partition on machine system_id and device
341+ device_id with the given partition id.
342+
343+ @param (string) "{system_id}" [required=true] The system_id.
344+ @param (int) "{device_id}" [required=true] The block device_id.
345+ @param (int) "{id}" [required=true] The partition id.
346+
347+ @param (string) "fstype" [required=true] Type of filesystem.
348+
349+ @param (string) "uuid" [required=false] The UUID for the filesystem.
350
351- :param fstype: Type of filesystem.
352- :param uuid: The UUID for the filesystem.
353- :param label: The label for the filesystem.
354+ @param (string) "label" [required=false] The label for the filesystem.
355
356- Returns 403 when the user doesn't have the ability to format the \
357- partition.
358- Returns 404 if the node, block device, or partition is not found.
359+ @success (http-status-code) "server-success" 200
360+ @success (json) "success-json" A JSON object containing the updated
361+ partition object.
362+ @success-example "success-json" [exkey=partitions-format]
363+ placeholder text
364+
365+ @error (http-status-code) "403" 403
366+ @error (content) "no-perms" The user does not have permissions to
367+ format the partition.
368+
369+ @error (http-status-code) "404" 404
370+ @error (content) "not-found" The requested machine, device or partition
371+ is not found.
372+ @error-example "not-found"
373+ Not Found
374 """
375 device = BlockDevice.objects.get_block_device_or_404(
376 system_id, device_id, request.user, NodePermission.edit)
377@@ -225,7 +305,26 @@ class PartitionHandler(OperationsHandler):
378
379 @operation(idempotent=False)
380 def unformat(self, request, system_id, device_id, id):
381- """Unformat a partition."""
382+ """@description-title Unformat a partition
383+ @description Unformat the partition on machine system_id and device
384+ device_id with the given partition id.
385+
386+ @param (string) "{system_id}" [required=true] The system_id.
387+ @param (int) "{device_id}" [required=true] The block device_id.
388+ @param (int) "{id}" [required=true] The partition id.
389+
390+ @success (http-status-code) "server-success" 200
391+ @success (json) "success-json" A JSON object containing the updated
392+ partition object.
393+ @success-example "success-json" [exkey=partitions-unformat]
394+ placeholder text
395+
396+ @error (http-status-code) "404" 404
397+ @error (content) "not-found" The requested machine, device or partition
398+ is not found.
399+ @error-example "not-found"
400+ Not Found
401+ """
402 device = BlockDevice.objects.get_block_device_or_404(
403 system_id, device_id, request.user, NodePermission.edit)
404 partition_table = get_object_or_404(
405@@ -253,14 +352,35 @@ class PartitionHandler(OperationsHandler):
406
407 @operation(idempotent=False)
408 def mount(self, request, system_id, device_id, id):
409- """Mount the filesystem on partition.
410-
411- :param mount_point: Path on the filesystem to mount.
412- :param mount_options: Options to pass to mount(8).
413-
414- Returns 403 when the user doesn't have the ability to mount the \
415- partition.
416- Returns 404 if the node, block device, or partition is not found.
417+ """@description-title Mount a filesystem
418+ @description Mount a filesystem on machine system_id, device device_id
419+ and partition id.
420+
421+ @param (string) "{system_id}" [required=true] The system_id.
422+ @param (int) "{device_id}" [required=true] The block device_id.
423+ @param (int) "{id}" [required=true] The partition id.
424+
425+ @param (string) "mount_point" [required=true] Path on the filesystem to
426+ mount.
427+
428+ @param (string) "mount_options" [required=false] Options to pass to
429+ mount(8).
430+
431+ @success (http-status-code) "server-success" 200
432+ @success (json) "success-json" A JSON object containing the updated
433+ partition object.
434+ @success-example "success-json" [exkey=partitions-mount] placeholder
435+ text
436+
437+ @error (http-status-code) "403" 403
438+ @error (content) "no-perms" The user does not have permissions to mount
439+ the filesystem.
440+
441+ @error (http-status-code) "404" 404
442+ @error (content) "not-found" The requested machine, device or partition
443+ is not found.
444+ @error-example "not-found"
445+ Not Found
446 """
447 device = BlockDevice.objects.get_block_device_or_404(
448 system_id, device_id, request.user, NodePermission.edit)
449@@ -280,13 +400,33 @@ class PartitionHandler(OperationsHandler):
450
451 @operation(idempotent=False)
452 def unmount(self, request, system_id, device_id, id):
453- """Unmount the filesystem on partition.
454-
455- Returns 400 if the partition is not formatted or not currently \
456- mounted.
457- Returns 403 when the user doesn't have the ability to unmount the \
458- partition.
459- Returns 404 if the node, block device, or partition is not found.
460+ """@description-title Unmount a filesystem
461+ @description Unmount a filesystem on machine system_id, device
462+ device_id and partition id.
463+
464+ @param (string) "{system_id}" [required=true] The system_id.
465+ @param (int) "{device_id}" [required=true] The block device_id.
466+ @param (int) "{id}" [required=true] The partition id.
467+
468+ @success (http-status-code) "server-success" 200
469+ @success (json) "success-json" A JSON object containing the updated
470+ partition object.
471+ @success-example "success-json" [exkey=partitions-unmount] placeholder
472+ text
473+
474+ @error (http-status-code) "400" 400
475+ @error (content) "part-prob" The partition is not formatted or not
476+ currently mounted.
477+
478+ @error (http-status-code) "403" 403
479+ @error (content) "no-perms" The user does not have permissions to
480+ unmount the filesystem.
481+
482+ @error (http-status-code) "404" 404
483+ @error (content) "not-found" The requested machine, device or partition
484+ is not found.
485+ @error-example "not-found"
486+ Not Found
487 """
488 device = BlockDevice.objects.get_block_device_or_404(
489 system_id, device_id, request.user, NodePermission.edit)
490@@ -309,12 +449,31 @@ class PartitionHandler(OperationsHandler):
491
492 @operation(idempotent=False)
493 def add_tag(self, request, system_id, device_id, id):
494- """Add a tag to partition.
495-
496- :param tag: The tag being added.
497-
498- Returns 403 when the user doesn't have the ability to add tag.
499- Returns 404 if the node, block device, or partition is not found.
500+ """@description-title Add a tag
501+ @description Add a tag to a partition on machine system_id, device
502+ device_id and partition id.
503+
504+ @param (string) "{system_id}" [required=true] The system_id.
505+ @param (int) "{device_id}" [required=true] The block device_id.
506+ @param (int) "{id}" [required=true] The partition id.
507+
508+ @param (string) "tag" [required=true] The tag being added.
509+
510+ @success (http-status-code) "server-success" 200
511+ @success (json) "success-json" A JSON object containing the updated
512+ partition object.
513+ @success-example "success-json" [exkey=partitions-add-tag] placeholder
514+ text
515+
516+ @error (http-status-code) "403" 403
517+ @error (content) "no-perms" The user does not have permissions to
518+ add a tag.
519+
520+ @error (http-status-code) "404" 404
521+ @error (content) "not-found" The requested machine, device or partition
522+ is not found.
523+ @error-example "not-found"
524+ Not Found
525 """
526 device = BlockDevice.objects.get_block_device_or_404(
527 system_id, device_id, request.user, NodePermission.admin)
528@@ -328,12 +487,31 @@ class PartitionHandler(OperationsHandler):
529
530 @operation(idempotent=False)
531 def remove_tag(self, request, system_id, device_id, id):
532- """Remove a tag from partition.
533-
534- :param tag: The tag being removed.
535-
536- Returns 403 when the user doesn't have the ability to add tag.
537- Returns 404 if the node, block device, or partition is not found.
538+ """@description-title Remove a tag
539+ @description Remove a tag from a partition on machine system_id, device
540+ device_id and partition id.
541+
542+ @param (string) "{system_id}" [required=true] The system_id.
543+ @param (int) "{device_id}" [required=true] The block device_id.
544+ @param (int) "{id}" [required=true] The partition id.
545+
546+ @param (string) "tag" [required=true] The tag being removed.
547+
548+ @success (http-status-code) "server-success" 200
549+ @success (json) "success-json" A JSON object containing the updated
550+ partition object.
551+ @success-example "success-json" [exkey=partitions-rem-tag] placeholder
552+ text
553+
554+ @error (http-status-code) "403" 403
555+ @error (content) "no-perms" The user does not have permissions to
556+ remove a tag.
557+
558+ @error (http-status-code) "404" 404
559+ @error (content) "not-found" The requested machine, device or partition
560+ is not found.
561+ @error-example "not-found"
562+ Not Found
563 """
564 device = BlockDevice.objects.get_block_device_or_404(
565 system_id, device_id, request.user, NodePermission.admin)

Subscribers

People subscribed via source and target branches