server-list.py 4.98 KB
Newer Older
1
# Copyright 2012-2013 GRNET S.A. All rights reserved.
Giorgos Verigakis's avatar
Giorgos Verigakis committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
#   1. Redistributions of source code must retain the above
#      copyright notice, this list of conditions and the following
#      disclaimer.
#
#   2. Redistributions in binary form must reproduce the above
#      copyright notice, this list of conditions and the following
#      disclaimer in the documentation and/or other materials
#      provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.

from optparse import make_option

36
from synnefo.webproject.management.commands import ListCommand
37
from synnefo.db.models import VirtualMachine
38 39
from synnefo.management.common import get_backend
from synnefo.api.util import get_image
Giorgos Verigakis's avatar
Giorgos Verigakis committed
40

41 42
from logging import getLogger
log = getLogger(__name__)
43 44


45
class Command(ListCommand):
Giorgos Verigakis's avatar
Giorgos Verigakis committed
46
    help = "List servers"
47

48
    option_list = ListCommand.option_list + (
49 50
        make_option(
            '--suspended',
51 52 53 54
            action='store_true',
            dest='suspended',
            default=False,
            help="List only suspended servers"),
55 56
        make_option(
            '--backend-id',
57 58
            dest='backend_id',
            help="List only servers of the specified backend"),
59
        make_option(
60 61 62 63 64
            "--build",
            action="store_true",
            dest="build",
            default=False,
            help="List only servers in the building state"),
65
        make_option(
66 67 68
            "--image-name",
            action="store_true",
            dest="image_name",
69
            default=False,
70
            help="Display image name instead of image ID"),
71
    )
72

73 74 75
    object_class = VirtualMachine
    deleted_field = "deleted"
    user_uuid_field = "userid"
76

77 78 79 80 81
    def get_public_ip(vm):
        try:
            return vm.nics.all()[0].ipv4
        except IndexError:
            return None
82

83 84 85
    def format_vm_state(vm):
        if vm.operstate == "BUILD":
            return "BUILD(" + str(vm.buildpercentage) + "%)"
86
        else:
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
            return vm.operstate

    FIELDS = {
        "id": ("id", "ID of the server"),
        "name": ("name", "Name of the server"),
        "user.uuid": ("userid", "The UUID of the server's owner"),
        "flavor": ("flavor.name", "The name of the server's flavor"),
        "backend": ("backend", "The Ganeti backend that hosts the VM"),
        "image.id": ("imageid", "The ID of the server's image"),
        "image.name": ("image", "The name of the server's image"),
        "state": (format_vm_state, "The current state of the server"),
        "ip": (get_public_ip, "The public IP of the server"),
        "created": ("created", "The date the server was created"),
        "deleted": ("deleted", "Whether the server is deleted or not"),
        "suspended": ("suspended", "Whether the server is administratively"
                      " suspended"),
    }

    fields = ["id", "name", "user.uuid", "state", "flavor", "image.id",
              "backend"]

    def handle_args(self, *args, **options):
        if options["suspended"]:
            self.filters["suspended"] = True

        if options["backend_id"]:
            backend = get_backend(options["backend_id"])
            self.filters["backend"] = backend.id

        if options["build"]:
            self.filters["operstate"] = "BUILD"

        if options["image_name"]:
            self.fields.replace("image.id", "image.name")

    def handle_db_objects(self, rows, *args, **kwargs):
        icache = ImageCache()
        for vm in rows:
            vm.image = icache.get_image(vm.imageid, vm.userid)
126 127 128 129 130 131 132 133


class ImageCache(object):
    def __init__(self):
        self.images = {}

    def get_image(self, imageid, userid):
        if not imageid in self.images:
134 135 136
            try:
                self.images[imageid] = get_image(imageid, userid)['name']
            except Exception as e:
Stratos Psomadakis's avatar
Stratos Psomadakis committed
137
                log.warning("Error getting image name from imageid %s: %s",
138 139 140
                            imageid, e)
                self.images[imageid] = imageid

141
        return self.images[imageid]