Statistics
| Branch: | Tag: | Revision:

root / snf-app / synnefo / admin / views.py @ 244c552b

History | View | Annotate | Download (8.9 kB)

1
# Copyright 2011 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 functools import wraps
35

    
36
from django.conf import settings
37
from django.http import HttpResponse
38
from django.shortcuts import redirect
39
from django.template.loader import render_to_string
40

    
41
from synnefo.db import models
42
from synnefo.logic import backend, users
43
from synnefo.util.log import getLogger
44

    
45

    
46
log = getLogger('synnefo.admin')
47

    
48

    
49
def render(template, tab, **kwargs):
50
    kwargs.setdefault('tab', tab)
51
    return render_to_string(template, kwargs)
52

    
53

    
54
def requires_admin(func):
55
    @wraps(func)
56
    def wrapper(request, *args):
57
        if not request.user or request.user.type != 'ADMIN':
58
            return HttpResponse('Forbidden', status=403)
59
        return func(request, *args)
60
    return wrapper
61

    
62

    
63
def get_filters(request, session_key, all_filters, default=None):
64
    if default is None:
65
        default = all_filters
66
    filters = request.session.get(session_key, default)
67
    filter = request.GET.get('toggle_filter')
68
    if filter:
69
        if filter in filters:
70
            filters.remove(filter)
71
        elif filter in all_filters:
72
            filters.add(filter)
73
        request.session[session_key] = filters
74
    return filters
75

    
76

    
77
@requires_admin
78
def index(request):
79
    stats = {}
80
    stats['images'] = models.Image.objects.exclude(state='DELETED').count()
81
    stats['flavors'] = models.Flavor.objects.count()
82
    stats['vms'] = models.VirtualMachine.objects.filter(deleted=False).count()
83
    stats['networks'] = models.Network.objects.exclude(state='DELETED').count()
84

    
85
    stats['ganeti_instances'] = len(backend.get_ganeti_instances())
86
    stats['ganeti_nodes'] = len(backend.get_ganeti_nodes())
87
    stats['ganeti_jobs'] = len(backend.get_ganeti_jobs())
88

    
89
    images = []
90
    for image in models.Image.objects.exclude(state='DELETED'):
91
        vms = models.VirtualMachine.objects.filter(imageid=image.id)
92
        count = vms.filter(deleted=False).count()
93
        images.append((count, image.name))
94
    images.sort(reverse=True)
95

    
96
    html = render('index.html', 'home', stats=stats, images=images)
97
    return HttpResponse(html)
98

    
99

    
100
@requires_admin
101
def flavors_list(request):
102
    all_states = set(['DELETED'])
103
    default = set()
104
    filters = get_filters(request, 'flavors_filters', all_states, default)
105
    
106
    flavors = models.Flavor.objects.all()
107
    if 'DELETED' not in filters:
108
        flavors = flavors.exclude(deleted=True)
109
    
110
    html = render('flavors_list.html', 'flavors',
111
                    flavors=flavors,
112
                    all_states=sorted(all_states),
113
                    filters=filters)
114
    return HttpResponse(html)
115

    
116

    
117
@requires_admin
118
def flavors_create(request):
119
    if request.method == 'GET':
120
        html = render('flavors_create.html', 'flavors')
121
        return HttpResponse(html)
122
    if request.method == 'POST':
123
        flavor = models.Flavor()
124
        flavor.cpu = int(request.POST.get('cpu'))
125
        flavor.ram = int(request.POST.get('ram'))
126
        flavor.disk = int(request.POST.get('disk'))
127
        flavor.save()
128
        log.info('User %s created Flavor %s', request.user.name, flavor.name)
129
        return redirect(flavors_info, flavor.id)
130

    
131

    
132
@requires_admin
133
def flavors_info(request, flavor_id):
134
    flavor = models.Flavor.objects.get(id=flavor_id)
135
    html = render('flavors_info.html', 'flavors',
136
                    flavor=flavor,
137
                    disk_templates=settings.GANETI_DISK_TEMPLATES)
138
    return HttpResponse(html)
139

    
140

    
141
@requires_admin
142
def flavors_modify(request, flavor_id):
143
    flavor = models.Flavor.objects.get(id=flavor_id)
144
    flavor.cpu = int(request.POST.get('cpu'))
145
    flavor.ram = int(request.POST.get('ram'))
146
    flavor.disk = int(request.POST.get('disk'))
147
    flavor.disk_template = request.POST.get('disk_template')
148
    flavor.deleted = True if request.POST.get('deleted') else False
149
    flavor.save()
150
    log.info('User %s modified Flavor %s', request.user.name, flavor.name)
151
    return redirect(flavors_info, flavor.id)
152

    
153

    
154
@requires_admin
155
def flavors_delete(request, flavor_id):
156
    flavor = models.Flavor.objects.get(id=flavor_id)
157
    flavor.delete()
158
    log.info('User %s deleted Flavor %s', request.user.name, flavor.name)
159
    return redirect(flavors_list)
160

    
161

    
162
@requires_admin
163
def images_list(request):
164
    all_states = set(x[0] for x in models.Image.IMAGE_STATES)
165
    default = all_states - set(['DELETED'])
166
    filters = get_filters(request, 'images_filters', all_states, default)
167
    
168
    images = models.Image.objects.all()
169
    for state in all_states - filters:
170
        images = images.exclude(state=state)
171
    
172
    html = render('images_list.html', 'images',
173
                    images=images.order_by('id'),
174
                    all_states=sorted(all_states),
175
                    filters=filters)
176
    return HttpResponse(html)
177

    
178

    
179
@requires_admin
180
def images_register(request):
181
    if request.method == 'GET':
182
        formats = [x[0] for x in models.Image.FORMATS]
183
        html = render('images_register.html', 'images', formats=formats)
184
        return HttpResponse(html)
185
    elif request.method == 'POST':
186
        image = models.Image()
187
        image.state = 'ACTIVE'
188
        image.name = request.POST.get('name')
189
        image.userid = request.POST.get('owner')
190
        image.backend_id = request.POST.get('backend')
191
        image.format = request.POST.get('format')
192
        image.public = True if request.POST.get('public') else False
193
        image.save()
194
        log.info('User %s registered Image %s', request.user.name, image.name)
195
        return redirect(images_info, image.id)
196

    
197

    
198
@requires_admin
199
def images_info(request, image_id):
200
    image = models.Image.objects.get(id=image_id)
201
    states = [x[0] for x in models.Image.IMAGE_STATES]
202
    if not image.state:
203
        states = [''] + states
204
    formats = [x[0] for x in models.Image.FORMATS]
205
    if not image.format:
206
        formats = [''] + formats
207
    
208
    metadata = image.metadata.order_by('meta_key')
209
    html = render('images_info.html', 'images',
210
                    image=image,
211
                    states=states,
212
                    formats=formats,
213
                    metadata=metadata)
214
    return HttpResponse(html)
215

    
216

    
217
@requires_admin
218
def images_modify(request, image_id):
219
    image = models.Image.objects.get(id=image_id)
220
    image.name = request.POST.get('name')
221
    image.state = request.POST.get('state')
222
    image.userid = request.POST.get('owner')
223
    vm_id = request.POST.get('sourcevm')
224
    image.sourcevm = vm_id and models.VirtualMachine.objects.get(id=vm_id)
225
    image.backend_id = request.POST.get('backend')
226
    image.format = request.POST.get('format')
227
    image.public = True if request.POST.get('public') else False
228
    image.save()
229
    
230
    keys = request.POST.getlist('key')
231
    vals = request.POST.getlist('value')
232
    meta = dict(zip(keys, vals))
233
    image.metadata.all().delete()
234
    for key, val in meta.items():
235
        if key:
236
            image.metadata.create(meta_key=key, meta_value=val)
237
    
238
    log.info('User %s modified Image %s', request.user.name, image.name)
239

    
240
    return redirect(images_info, image.id)
241

    
242

    
243
@requires_admin
244
def servers_list(request):
245
    all_states = set(x[0] for x in models.VirtualMachine.OPER_STATES)
246
    default = all_states - set(['DESTROYED'])
247
    filters = get_filters(request, 'servers_filters', all_states, default)
248
    
249
    servers = models.VirtualMachine.objects.all()
250
    for state in all_states - filters:
251
        servers = servers.exclude(operstate=state)
252
    
253
    html = render('servers_list.html', 'servers',
254
                    servers=servers.order_by('id'),
255
                    all_states=sorted(all_states),
256
                    filters=filters)
257
    return HttpResponse(html)