Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / admin / views.py @ 2035039b

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
from logging import getLogger
36

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

    
42
from synnefo.db import models
43
from synnefo.logic import backend, users
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)