diff options
-rw-r--r-- | lava_server/management/commands/device-tags.py | 161 | ||||
-rw-r--r-- | share/black.yaml | 4 |
2 files changed, 165 insertions, 0 deletions
diff --git a/lava_server/management/commands/device-tags.py b/lava_server/management/commands/device-tags.py new file mode 100644 index 000000000..5815f7d78 --- /dev/null +++ b/lava_server/management/commands/device-tags.py @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2018 Linaro Limited +# +# Author: Neil Williams <neil.williams@linaro.org> +# +# This file is part of LAVA. +# +# LAVA is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License version 3 +# as published by the Free Software Foundation +# +# LAVA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with LAVA. If not, see <http://www.gnu.org/licenses/>. + +import contextlib +from django.core.management.base import BaseCommand, CommandError, CommandParser +from lava_scheduler_app.models import Device, Tag + + +class Command(BaseCommand): + help = "Manage device tags" + + def add_arguments(self, parser): + cmd = self + + class SubParser(CommandParser): + """ + Sub-parsers constructor that mimic Django constructor. + See http://stackoverflow.com/a/37414551 + """ + + def __init__(self, **kwargs): + super().__init__(cmd, **kwargs) + + sub = parser.add_subparsers( + dest="sub_command", help="Sub commands", parser_class=SubParser + ) + sub.required = True + + # "add" sub-command + add_parser = sub.add_parser( + "add", help="Add one or more existing device tag(s) to an existing device" + ) + add_parser.add_argument("hostname", help="Hostname of the device") + add_parser.add_argument( + "--tags", + nargs="*", + required=False, + help="List of tags to add to the device", + ) + + # "show" sub-command + show_parser = sub.add_parser( + "show", help="Show all device tag(s) for an existing device" + ) + show_parser.add_argument("hostname", help="Hostname of the device") + + # "list" sub-command + list_parser = sub.add_parser("list", help="List all device tag(s)") + + # "remove" sub-command + remove_parser = sub.add_parser( + "remove", + help="Remove one or more existing device tag(s) from an existing device", + ) + remove_parser.add_argument("hostname", help="Hostname of the device") + remove_parser.add_argument( + "--tags", + nargs="*", + required=False, + help="List of tags to remove from the device", + ) + + # "create" sub-command + create_parser = sub.add_parser("create", help="Create a new device tag") + create_parser.add_argument("name", help="Name of the new tag") + create_parser.add_argument("description", help="Description of the new tag") + + def handle(self, *args, **options): + """ Forward to the right sub-handler """ + if options["sub_command"] == "add": + self.handle_add(options) + elif options["sub_command"] == "list": + self.handle_list(options) + elif options["sub_command"] == "show": + self.handle_show(options) + elif options["sub_command"] == "remove": + self.handle_remove(options) + else: + self.handle_create(options) + + def handle_add(self, options): + hostname = options["hostname"] + try: + device = Device.objects.get(hostname=hostname) + except Device.DoesNotExist: + raise CommandError("Device '%s' does NOT exist!" % hostname) + + tags = options["tags"] + if tags is not None: + for tag in tags: + try: + tag = Tag.objects.get(name=tag) + except Tag.DoesNotExist: + raise CommandError("Tag '%s' does NOT exist!" % tag) + device.tags.add(tag) + device.save() + + def handle_show(self, options): + hostname = options["hostname"] + try: + device = Device.objects.get(hostname=hostname) + except Device.DoesNotExist: + raise CommandError("Device '%s' does NOT exist!" % hostname) + if device.tags.all(): + self.stdout.write("Hostname: %s" % hostname) + for tag in device.tags.all(): + self.stdout.write( + "Tag name: '%s' Description: '%s'" % (tag.name, tag.description) + ) + + def handle_remove(self, options): + hostname = options["hostname"] + try: + device = Device.objects.get(hostname=hostname) + except Device.DoesNotExist: + raise CommandError("Device '%s' does NOT exist!" % hostname) + + tags = options["tags"] + if tags is not None: + for tag in tags: + try: + tag = Tag.objects.get(name=tag) + except Device.DoesNotExist: + raise CommandError("Tag '%s' does NOT exist!" % name) + if tag not in device.tags.all(): + raise CommandError( + "Device %s does not have tag %s" % (hostname, tag.name) + ) + device.tags.remove(tag) + device.save() + + def handle_create(self, options): + name = options["name"] + description = options["description"] + + with contextlib.suppress(Tag.DoesNotExist): + Tag.objects.get(name=name) + raise CommandError("Tag '%s' already exists" % name) + Tag.objects.create(name=name, description=description) + + def handle_list(self, options): + for tag in Tag.objects.all(): + self.stdout.write( + "Name: '%s' Description: '%s'" % (tag.name, tag.description) + ) diff --git a/share/black.yaml b/share/black.yaml index 51ca02369..c920df752 100644 --- a/share/black.yaml +++ b/share/black.yaml @@ -1,3 +1,7 @@ +lava_server: + management: + commands: + device-tags.py share: check-devices.py validate_devices.py |