Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / management / commands / server-list.py @ b0e7f310

History | View | Annotate | Download (5 kB)

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

    
34
from optparse import make_option
35

    
36
from synnefo.webproject.management.commands import ListCommand
37
from synnefo.db.models import VirtualMachine
38
from synnefo.management.common import get_backend
39
from synnefo.api.util import get_image
40

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

    
44

    
45
class Command(ListCommand):
46
    help = "List servers"
47

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

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

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

    
83
    def format_vm_state(vm):
84
        if vm.operstate == "BUILD":
85
            return "BUILD(" + str(vm.buildpercentage) + "%)"
86
        else:
87
            return vm.operstate
88

    
89
    FIELDS = {
90
        "id": ("id", "ID of the server"),
91
        "name": ("name", "Name of the server"),
92
        "user.uuid": ("userid", "The UUID of the server's owner"),
93
        "flavor": ("flavor.name", "The name of the server's flavor"),
94
        "backend": ("backend", "The Ganeti backend that hosts the VM"),
95
        "image.id": ("imageid", "The ID of the server's image"),
96
        "image.name": ("image", "The name of the server's image"),
97
        "state": (format_vm_state, "The current state of the server"),
98
        "ip": (get_public_ip, "The public IP of the server"),
99
        "created": ("created", "The date the server was created"),
100
        "deleted": ("deleted", "Whether the server is deleted or not"),
101
        "suspended": ("suspended", "Whether the server is administratively"
102
                      " suspended"),
103
    }
104

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

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

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

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

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

    
122
    def handle_db_objects(self, rows, *args, **kwargs):
123
        icache = ImageCache()
124
        for vm in rows:
125
            vm.image = icache.get_image(vm.imageid, vm.userid)
126

    
127

    
128
class ImageCache(object):
129
    def __init__(self):
130
        self.images = {}
131

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

    
141
        return self.images[imageid]