root / snf-cyclades-app / synnefo / admin / views.py @ 4500650c
History | View | Annotate | Download (8.9 kB)
1 | 1081c1a0 | Giorgos Verigakis | # Copyright 2011 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 1081c1a0 | Giorgos Verigakis | #
|
3 | 1081c1a0 | Giorgos Verigakis | # Redistribution and use in source and binary forms, with or
|
4 | 1081c1a0 | Giorgos Verigakis | # without modification, are permitted provided that the following
|
5 | 1081c1a0 | Giorgos Verigakis | # conditions are met:
|
6 | 1081c1a0 | Giorgos Verigakis | #
|
7 | 1081c1a0 | Giorgos Verigakis | # 1. Redistributions of source code must retain the above
|
8 | 1081c1a0 | Giorgos Verigakis | # copyright notice, this list of conditions and the following
|
9 | 1081c1a0 | Giorgos Verigakis | # disclaimer.
|
10 | 1081c1a0 | Giorgos Verigakis | #
|
11 | 1081c1a0 | Giorgos Verigakis | # 2. Redistributions in binary form must reproduce the above
|
12 | 1081c1a0 | Giorgos Verigakis | # copyright notice, this list of conditions and the following
|
13 | 1081c1a0 | Giorgos Verigakis | # disclaimer in the documentation and/or other materials
|
14 | 1081c1a0 | Giorgos Verigakis | # provided with the distribution.
|
15 | 1081c1a0 | Giorgos Verigakis | #
|
16 | 1081c1a0 | Giorgos Verigakis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 1081c1a0 | Giorgos Verigakis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 1081c1a0 | Giorgos Verigakis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 1081c1a0 | Giorgos Verigakis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 1081c1a0 | Giorgos Verigakis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 1081c1a0 | Giorgos Verigakis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 1081c1a0 | Giorgos Verigakis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 1081c1a0 | Giorgos Verigakis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 1081c1a0 | Giorgos Verigakis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 1081c1a0 | Giorgos Verigakis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 1081c1a0 | Giorgos Verigakis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 1081c1a0 | Giorgos Verigakis | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 1081c1a0 | Giorgos Verigakis | #
|
29 | 1081c1a0 | Giorgos Verigakis | # The views and conclusions contained in the software and
|
30 | 1081c1a0 | Giorgos Verigakis | # documentation are those of the authors and should not be
|
31 | 1081c1a0 | Giorgos Verigakis | # interpreted as representing official policies, either expressed
|
32 | 1081c1a0 | Giorgos Verigakis | # or implied, of GRNET S.A.
|
33 | 1081c1a0 | Giorgos Verigakis | |
34 | 1f06d8ff | Giorgos Verigakis | from functools import wraps |
35 | 2035039b | Giorgos Verigakis | from logging import getLogger |
36 | 1f06d8ff | Giorgos Verigakis | |
37 | c909cbbd | Giorgos Verigakis | from django.conf import settings |
38 | 1f06d8ff | Giorgos Verigakis | from django.http import HttpResponse |
39 | 1f06d8ff | Giorgos Verigakis | from django.shortcuts import redirect |
40 | 1f06d8ff | Giorgos Verigakis | from django.template.loader import render_to_string |
41 | 1f06d8ff | Giorgos Verigakis | |
42 | 1f06d8ff | Giorgos Verigakis | from synnefo.db import models |
43 | 9e98ba3c | Giorgos Verigakis | from synnefo.logic import backend, users |
44 | e1f81736 | Giorgos Verigakis | |
45 | e1f81736 | Giorgos Verigakis | |
46 | 9e98ba3c | Giorgos Verigakis | log = getLogger('synnefo.admin')
|
47 | 1f06d8ff | Giorgos Verigakis | |
48 | 1f06d8ff | Giorgos Verigakis | |
49 | 1f06d8ff | Giorgos Verigakis | def render(template, tab, **kwargs): |
50 | 1f06d8ff | Giorgos Verigakis | kwargs.setdefault('tab', tab)
|
51 | 1f06d8ff | Giorgos Verigakis | return render_to_string(template, kwargs)
|
52 | 1f06d8ff | Giorgos Verigakis | |
53 | 1f06d8ff | Giorgos Verigakis | |
54 | 53155501 | Giorgos Verigakis | def requires_admin(func): |
55 | 53155501 | Giorgos Verigakis | @wraps(func)
|
56 | 53155501 | Giorgos Verigakis | def wrapper(request, *args): |
57 | 53155501 | Giorgos Verigakis | if not request.user or request.user.type != 'ADMIN': |
58 | 9a6cab7a | Giorgos Verigakis | return HttpResponse('Forbidden', status=403) |
59 | 53155501 | Giorgos Verigakis | return func(request, *args)
|
60 | 53155501 | Giorgos Verigakis | return wrapper
|
61 | 53155501 | Giorgos Verigakis | |
62 | 53155501 | Giorgos Verigakis | |
63 | 89c358a3 | Giorgos Verigakis | def get_filters(request, session_key, all_filters, default=None): |
64 | 89c358a3 | Giorgos Verigakis | if default is None: |
65 | 89c358a3 | Giorgos Verigakis | default = all_filters |
66 | 89c358a3 | Giorgos Verigakis | filters = request.session.get(session_key, default) |
67 | 89c358a3 | Giorgos Verigakis | filter = request.GET.get('toggle_filter')
|
68 | 89c358a3 | Giorgos Verigakis | if filter: |
69 | 89c358a3 | Giorgos Verigakis | if filter in filters: |
70 | 89c358a3 | Giorgos Verigakis | filters.remove(filter)
|
71 | 89c358a3 | Giorgos Verigakis | elif filter in all_filters: |
72 | 89c358a3 | Giorgos Verigakis | filters.add(filter)
|
73 | 89c358a3 | Giorgos Verigakis | request.session[session_key] = filters |
74 | 89c358a3 | Giorgos Verigakis | return filters
|
75 | 89c358a3 | Giorgos Verigakis | |
76 | 89c358a3 | Giorgos Verigakis | |
77 | 53155501 | Giorgos Verigakis | @requires_admin
|
78 | 1f06d8ff | Giorgos Verigakis | def index(request): |
79 | 60f5da1a | Giorgos Verigakis | stats = {} |
80 | 60f5da1a | Giorgos Verigakis | stats['images'] = models.Image.objects.exclude(state='DELETED').count() |
81 | 60f5da1a | Giorgos Verigakis | stats['flavors'] = models.Flavor.objects.count()
|
82 | 60f5da1a | Giorgos Verigakis | stats['vms'] = models.VirtualMachine.objects.filter(deleted=False).count() |
83 | 60f5da1a | Giorgos Verigakis | stats['networks'] = models.Network.objects.exclude(state='DELETED').count() |
84 | 60f5da1a | Giorgos Verigakis | |
85 | f5c6e3f4 | Giorgos Verigakis | stats['ganeti_instances'] = len(backend.get_ganeti_instances()) |
86 | f5c6e3f4 | Giorgos Verigakis | stats['ganeti_nodes'] = len(backend.get_ganeti_nodes()) |
87 | f5c6e3f4 | Giorgos Verigakis | stats['ganeti_jobs'] = len(backend.get_ganeti_jobs()) |
88 | 4416efc0 | Giorgos Verigakis | |
89 | 60f5da1a | Giorgos Verigakis | images = [] |
90 | 60f5da1a | Giorgos Verigakis | for image in models.Image.objects.exclude(state='DELETED'): |
91 | 1588c123 | Giorgos Verigakis | vms = models.VirtualMachine.objects.filter(imageid=image.id) |
92 | 60f5da1a | Giorgos Verigakis | count = vms.filter(deleted=False).count()
|
93 | 60f5da1a | Giorgos Verigakis | images.append((count, image.name)) |
94 | 60f5da1a | Giorgos Verigakis | images.sort(reverse=True)
|
95 | 60f5da1a | Giorgos Verigakis | |
96 | 60f5da1a | Giorgos Verigakis | html = render('index.html', 'home', stats=stats, images=images) |
97 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html)
|
98 | 1f06d8ff | Giorgos Verigakis | |
99 | 1f06d8ff | Giorgos Verigakis | |
100 | 53155501 | Giorgos Verigakis | @requires_admin
|
101 | 1f06d8ff | Giorgos Verigakis | def flavors_list(request): |
102 | 89c358a3 | Giorgos Verigakis | all_states = set(['DELETED']) |
103 | 89c358a3 | Giorgos Verigakis | default = set()
|
104 | 89c358a3 | Giorgos Verigakis | filters = get_filters(request, 'flavors_filters', all_states, default)
|
105 | 89c358a3 | Giorgos Verigakis | |
106 | 89c358a3 | Giorgos Verigakis | flavors = models.Flavor.objects.all() |
107 | 89c358a3 | Giorgos Verigakis | if 'DELETED' not in filters: |
108 | 89c358a3 | Giorgos Verigakis | flavors = flavors.exclude(deleted=True)
|
109 | 89c358a3 | Giorgos Verigakis | |
110 | 89c358a3 | Giorgos Verigakis | html = render('flavors_list.html', 'flavors', |
111 | 89c358a3 | Giorgos Verigakis | flavors=flavors, |
112 | 89c358a3 | Giorgos Verigakis | all_states=sorted(all_states),
|
113 | 89c358a3 | Giorgos Verigakis | filters=filters) |
114 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html)
|
115 | 1f06d8ff | Giorgos Verigakis | |
116 | 53155501 | Giorgos Verigakis | |
117 | 53155501 | Giorgos Verigakis | @requires_admin
|
118 | 1f06d8ff | Giorgos Verigakis | def flavors_create(request): |
119 | 1f06d8ff | Giorgos Verigakis | if request.method == 'GET': |
120 | 1f06d8ff | Giorgos Verigakis | html = render('flavors_create.html', 'flavors') |
121 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html)
|
122 | 1f06d8ff | Giorgos Verigakis | if request.method == 'POST': |
123 | 1f06d8ff | Giorgos Verigakis | flavor = models.Flavor() |
124 | e1f81736 | Giorgos Verigakis | flavor.cpu = int(request.POST.get('cpu')) |
125 | e1f81736 | Giorgos Verigakis | flavor.ram = int(request.POST.get('ram')) |
126 | e1f81736 | Giorgos Verigakis | flavor.disk = int(request.POST.get('disk')) |
127 | 1f06d8ff | Giorgos Verigakis | flavor.save() |
128 | 9e98ba3c | Giorgos Verigakis | log.info('User %s created Flavor %s', request.user.name, flavor.name)
|
129 | 1f06d8ff | Giorgos Verigakis | return redirect(flavors_info, flavor.id)
|
130 | 1f06d8ff | Giorgos Verigakis | |
131 | 53155501 | Giorgos Verigakis | |
132 | 53155501 | Giorgos Verigakis | @requires_admin
|
133 | 1f06d8ff | Giorgos Verigakis | def flavors_info(request, flavor_id): |
134 | 1f06d8ff | Giorgos Verigakis | flavor = models.Flavor.objects.get(id=flavor_id) |
135 | c909cbbd | Giorgos Verigakis | html = render('flavors_info.html', 'flavors', |
136 | c909cbbd | Giorgos Verigakis | flavor=flavor, |
137 | c909cbbd | Giorgos Verigakis | disk_templates=settings.GANETI_DISK_TEMPLATES) |
138 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html)
|
139 | 1f06d8ff | Giorgos Verigakis | |
140 | 53155501 | Giorgos Verigakis | |
141 | 53155501 | Giorgos Verigakis | @requires_admin
|
142 | 1f06d8ff | Giorgos Verigakis | def flavors_modify(request, flavor_id): |
143 | 1f06d8ff | Giorgos Verigakis | flavor = models.Flavor.objects.get(id=flavor_id) |
144 | e1f81736 | Giorgos Verigakis | flavor.cpu = int(request.POST.get('cpu')) |
145 | e1f81736 | Giorgos Verigakis | flavor.ram = int(request.POST.get('ram')) |
146 | e1f81736 | Giorgos Verigakis | flavor.disk = int(request.POST.get('disk')) |
147 | c909cbbd | Giorgos Verigakis | flavor.disk_template = request.POST.get('disk_template')
|
148 | 870c24a0 | Giorgos Verigakis | flavor.deleted = True if request.POST.get('deleted') else False |
149 | 1f06d8ff | Giorgos Verigakis | flavor.save() |
150 | 9e98ba3c | Giorgos Verigakis | log.info('User %s modified Flavor %s', request.user.name, flavor.name)
|
151 | 1f06d8ff | Giorgos Verigakis | return redirect(flavors_info, flavor.id)
|
152 | 1f06d8ff | Giorgos Verigakis | |
153 | 53155501 | Giorgos Verigakis | |
154 | 53155501 | Giorgos Verigakis | @requires_admin
|
155 | 1f06d8ff | Giorgos Verigakis | def flavors_delete(request, flavor_id): |
156 | 1f06d8ff | Giorgos Verigakis | flavor = models.Flavor.objects.get(id=flavor_id) |
157 | 1f06d8ff | Giorgos Verigakis | flavor.delete() |
158 | 9e98ba3c | Giorgos Verigakis | log.info('User %s deleted Flavor %s', request.user.name, flavor.name)
|
159 | 1f06d8ff | Giorgos Verigakis | return redirect(flavors_list)
|
160 | 1f06d8ff | Giorgos Verigakis | |
161 | 1f06d8ff | Giorgos Verigakis | |
162 | 53155501 | Giorgos Verigakis | @requires_admin
|
163 | 1f06d8ff | Giorgos Verigakis | def images_list(request): |
164 | 89c358a3 | Giorgos Verigakis | all_states = set(x[0] for x in models.Image.IMAGE_STATES) |
165 | 89c358a3 | Giorgos Verigakis | default = all_states - set(['DELETED']) |
166 | 89c358a3 | Giorgos Verigakis | filters = get_filters(request, 'images_filters', all_states, default)
|
167 | 89c358a3 | Giorgos Verigakis | |
168 | 89c358a3 | Giorgos Verigakis | images = models.Image.objects.all() |
169 | 89c358a3 | Giorgos Verigakis | for state in all_states - filters: |
170 | 89c358a3 | Giorgos Verigakis | images = images.exclude(state=state) |
171 | 89c358a3 | Giorgos Verigakis | |
172 | 89c358a3 | Giorgos Verigakis | html = render('images_list.html', 'images', |
173 | 89c358a3 | Giorgos Verigakis | images=images.order_by('id'),
|
174 | 89c358a3 | Giorgos Verigakis | all_states=sorted(all_states),
|
175 | 89c358a3 | Giorgos Verigakis | filters=filters) |
176 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html)
|
177 | 1f06d8ff | Giorgos Verigakis | |
178 | 53155501 | Giorgos Verigakis | |
179 | 53155501 | Giorgos Verigakis | @requires_admin
|
180 | 1f06d8ff | Giorgos Verigakis | def images_register(request): |
181 | 1f06d8ff | Giorgos Verigakis | if request.method == 'GET': |
182 | e1f81736 | Giorgos Verigakis | formats = [x[0] for x in models.Image.FORMATS] |
183 | e1f81736 | Giorgos Verigakis | html = render('images_register.html', 'images', formats=formats) |
184 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html)
|
185 | 1f06d8ff | Giorgos Verigakis | elif request.method == 'POST': |
186 | 1f06d8ff | Giorgos Verigakis | image = models.Image() |
187 | 1f06d8ff | Giorgos Verigakis | image.state = 'ACTIVE'
|
188 | 1f06d8ff | Giorgos Verigakis | image.name = request.POST.get('name')
|
189 | 244c552b | Giorgos Verigakis | image.userid = request.POST.get('owner')
|
190 | 1f06d8ff | Giorgos Verigakis | image.backend_id = request.POST.get('backend')
|
191 | e1f81736 | Giorgos Verigakis | image.format = request.POST.get('format')
|
192 | 1f06d8ff | Giorgos Verigakis | image.public = True if request.POST.get('public') else False |
193 | 1f06d8ff | Giorgos Verigakis | image.save() |
194 | 9e98ba3c | Giorgos Verigakis | log.info('User %s registered Image %s', request.user.name, image.name)
|
195 | 1f06d8ff | Giorgos Verigakis | return redirect(images_info, image.id)
|
196 | 1f06d8ff | Giorgos Verigakis | |
197 | 53155501 | Giorgos Verigakis | |
198 | 53155501 | Giorgos Verigakis | @requires_admin
|
199 | 1f06d8ff | Giorgos Verigakis | def images_info(request, image_id): |
200 | 1f06d8ff | Giorgos Verigakis | image = models.Image.objects.get(id=image_id) |
201 | 1f06d8ff | Giorgos Verigakis | states = [x[0] for x in models.Image.IMAGE_STATES] |
202 | 1f06d8ff | Giorgos Verigakis | if not image.state: |
203 | 1f06d8ff | Giorgos Verigakis | states = [''] + states
|
204 | 1f06d8ff | Giorgos Verigakis | formats = [x[0] for x in models.Image.FORMATS] |
205 | 1f06d8ff | Giorgos Verigakis | if not image.format: |
206 | 1f06d8ff | Giorgos Verigakis | formats = [''] + formats
|
207 | 4416efc0 | Giorgos Verigakis | |
208 | 7cc3c7d9 | Giorgos Verigakis | metadata = image.metadata.order_by('meta_key')
|
209 | 1f06d8ff | Giorgos Verigakis | html = render('images_info.html', 'images', |
210 | 4416efc0 | Giorgos Verigakis | image=image, |
211 | 4416efc0 | Giorgos Verigakis | states=states, |
212 | 4416efc0 | Giorgos Verigakis | formats=formats, |
213 | 4416efc0 | Giorgos Verigakis | metadata=metadata) |
214 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html)
|
215 | 1f06d8ff | Giorgos Verigakis | |
216 | 53155501 | Giorgos Verigakis | |
217 | 53155501 | Giorgos Verigakis | @requires_admin
|
218 | 1f06d8ff | Giorgos Verigakis | def images_modify(request, image_id): |
219 | 1f06d8ff | Giorgos Verigakis | image = models.Image.objects.get(id=image_id) |
220 | 1f06d8ff | Giorgos Verigakis | image.name = request.POST.get('name')
|
221 | 1f06d8ff | Giorgos Verigakis | image.state = request.POST.get('state')
|
222 | 244c552b | Giorgos Verigakis | image.userid = request.POST.get('owner')
|
223 | 244c552b | Giorgos Verigakis | vm_id = request.POST.get('sourcevm')
|
224 | 1f06d8ff | Giorgos Verigakis | image.sourcevm = vm_id and models.VirtualMachine.objects.get(id=vm_id)
|
225 | 1f06d8ff | Giorgos Verigakis | image.backend_id = request.POST.get('backend')
|
226 | 1f06d8ff | Giorgos Verigakis | image.format = request.POST.get('format')
|
227 | 1f06d8ff | Giorgos Verigakis | image.public = True if request.POST.get('public') else False |
228 | 1f06d8ff | Giorgos Verigakis | image.save() |
229 | 4416efc0 | Giorgos Verigakis | |
230 | 4416efc0 | Giorgos Verigakis | keys = request.POST.getlist('key')
|
231 | 4416efc0 | Giorgos Verigakis | vals = request.POST.getlist('value')
|
232 | 4416efc0 | Giorgos Verigakis | meta = dict(zip(keys, vals)) |
233 | 7cc3c7d9 | Giorgos Verigakis | image.metadata.all().delete() |
234 | 4416efc0 | Giorgos Verigakis | for key, val in meta.items(): |
235 | 4416efc0 | Giorgos Verigakis | if key:
|
236 | 7cc3c7d9 | Giorgos Verigakis | image.metadata.create(meta_key=key, meta_value=val) |
237 | 4416efc0 | Giorgos Verigakis | |
238 | 9e98ba3c | Giorgos Verigakis | log.info('User %s modified Image %s', request.user.name, image.name)
|
239 | e1f81736 | Giorgos Verigakis | |
240 | 1f06d8ff | Giorgos Verigakis | return redirect(images_info, image.id)
|
241 | 1f06d8ff | Giorgos Verigakis | |
242 | 53155501 | Giorgos Verigakis | |
243 | 53155501 | Giorgos Verigakis | @requires_admin
|
244 | 1f06d8ff | Giorgos Verigakis | def servers_list(request): |
245 | 89c358a3 | Giorgos Verigakis | all_states = set(x[0] for x in models.VirtualMachine.OPER_STATES) |
246 | 89c358a3 | Giorgos Verigakis | default = all_states - set(['DESTROYED']) |
247 | 89c358a3 | Giorgos Verigakis | filters = get_filters(request, 'servers_filters', all_states, default)
|
248 | 89c358a3 | Giorgos Verigakis | |
249 | 89c358a3 | Giorgos Verigakis | servers = models.VirtualMachine.objects.all() |
250 | 89c358a3 | Giorgos Verigakis | for state in all_states - filters: |
251 | 89c358a3 | Giorgos Verigakis | servers = servers.exclude(operstate=state) |
252 | 89c358a3 | Giorgos Verigakis | |
253 | 89c358a3 | Giorgos Verigakis | html = render('servers_list.html', 'servers', |
254 | 89c358a3 | Giorgos Verigakis | servers=servers.order_by('id'),
|
255 | 89c358a3 | Giorgos Verigakis | all_states=sorted(all_states),
|
256 | 89c358a3 | Giorgos Verigakis | filters=filters) |
257 | 1f06d8ff | Giorgos Verigakis | return HttpResponse(html) |