Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / management / commands / server-list.py @ 475d4a85

History | View | Annotate | Download (5.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 snf_django.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
from synnefo.settings import (CYCLADES_SERVICE_TOKEN as ASTAKOS_TOKEN,
41
                              ASTAKOS_AUTH_URL)
42
from logging import getLogger
43
log = getLogger(__name__)
44

    
45

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

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

    
74
    object_class = VirtualMachine
75
    deleted_field = "deleted"
76
    user_uuid_field = "userid"
77
    astakos_auth_url = ASTAKOS_AUTH_URL
78
    astakos_token = ASTAKOS_TOKEN
79

    
80
    def get_ipv4(vm):
81
        return vm.nics.filter(ips__subnet__ipversion=4)\
82
                      .values_list("ips__address", flat=True)
83

    
84
    def get_ipv6(vm):
85
        return vm.nics.filter(ips__subnet__ipversion=6)\
86
                      .values_list("ips__address", flat=True)
87

    
88
    def format_vm_state(vm):
89
        if vm.operstate == "BUILD":
90
            return "BUILD(" + str(vm.buildpercentage) + "%)"
91
        else:
92
            return vm.operstate
93

    
94
    FIELDS = {
95
        "id": ("id", "ID of the server"),
96
        "name": ("name", "Name of the server"),
97
        "user.uuid": ("userid", "The UUID of the server's owner"),
98
        "flavor": ("flavor.name", "The name of the server's flavor"),
99
        "backend": ("backend", "The Ganeti backend that hosts the VM"),
100
        "image.id": ("imageid", "The ID of the server's image"),
101
        "image.name": ("image", "The name of the server's image"),
102
        "state": (format_vm_state, "The current state of the server"),
103
        "ipv4": (get_ipv4, "The IPv4 addresses of the server"),
104
        "ipv6": (get_ipv6, "The IPv6 addresses of the server"),
105
        "created": ("created", "The date the server was created"),
106
        "deleted": ("deleted", "Whether the server is deleted or not"),
107
        "suspended": ("suspended", "Whether the server is administratively"
108
                      " suspended"),
109
    }
110

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

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

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

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

    
125
        if options["image_name"]:
126
            self.fields = ["image.name" if x == "image.id" else x
127
                           for x in self.fields]
128

    
129
    def handle_db_objects(self, rows, *args, **kwargs):
130
        if "image.name" in self.fields:
131
            icache = ImageCache()
132
            for vm in rows:
133
                vm.image = icache.get_image(vm.imageid, vm.userid)
134

    
135

    
136
class ImageCache(object):
137
    def __init__(self):
138
        self.images = {}
139

    
140
    def get_image(self, imageid, userid):
141
        if not imageid in self.images:
142
            try:
143
                self.images[imageid] = get_image(imageid, userid)['name']
144
            except Exception as e:
145
                log.warning("Error getting image name from imageid %s: %s",
146
                            imageid, e)
147
                self.images[imageid] = imageid
148

    
149
        return self.images[imageid]