cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
views.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 # @COPYRIGHT_begin
3 #
4 # Copyright [2010-2014] Institute of Nuclear Physics PAN, Krakow, Poland
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # @COPYRIGHT_end
19 
20 ##
21 # @package src.wi.utils.views
22 #
23 # @author Krzysztof Danielowski
24 # @author Piotr W√≥jcik
25 # @date 01.04.2012
26 #
27 
28 from django.contrib.formtools.wizard.views import CookieWizardView
29 from django.http import HttpResponse
30 from django.shortcuts import redirect
31 from django.template import loader, RequestContext
32 from django.template.defaultfilters import force_escape
33 from django.template.loader import render_to_string
34 from django.utils.translation import ugettext_lazy as _
35 from django.views.decorators.csrf import csrf_protect
36 
37 from wi.utils import CLM, check_response_errors, messages_ajax
38 from wi.utils.decorators import django_view
39 from wi.utils.messages_ajax import ajax_request
40 from wi.utils.messages_codes import get_error
41 
42 
43 not_to_be_logged_urls = ['admin_cm/farm/get_list/',
44  'admin_cm/vm/get_list/',
45  'admin_cm/monia/vm_stats/',
46 
47  'user/farm/get_list/',
48  'user/vm/get_list/',
49  'user/monia/vm_stats/']
50 
51 
52 not_to_be_logged_urls = ['admin_cm/farm/get_list/',
53  'admin_cm/vm/get_list/',
54  'admin_cm/monia/vm_stats/',
55 
56  'user/farm/get_list/',
57  'user/vm/get_list/',
58  'user/monia/vm_stats/']
59 
60 
61 ##
62 #
63 # Adds authorization-related information to data dictionary and makes a request to CLM
64 # using given url and data dictionary.
65 #
66 def make_request(url, data, user=None):
67  if not url.startswith('guest'):
68  data.update({'login': user.username, 'password': user.password, 'cm_id': user.cm_id})
69 
70  if url.startswith('admin_cm'):
71  data.update({'cm_password': user.cm_password})
72 
73  return CLM.send_request(url, False if url in not_to_be_logged_urls else True, **data)
74 
75 
76 ##
77 #
78 # Returns a dictionary with results of REST request.
79 #
80 def prep_data(request_urls, session):
81  data = None
82  user = session.get('user')
83 
84  if request_urls is not None:
85  data = {}
86  # function_both is dictionary with pairs: key -> url
87  if isinstance(request_urls, dict):
88  for (key, val) in request_urls.iteritems():
89  url = val
90  args = {}
91  if isinstance(val, tuple):
92  url = val[0]
93  args = val[1]
94  data[key] = check_response_errors(make_request(url, args, user=user), session)['data']
95  # a simple string without any params
96  elif isinstance(request_urls, str):
97  data = check_response_errors(make_request(request_urls, {}, user=user), session)['data']
98  # a simple string with params as a tuple
99  elif isinstance(request_urls, tuple):
100  data = check_response_errors(make_request(request_urls[0], request_urls[1], user=user), session)['data']
101 
102  return data
103 
104 
105 @django_view
106 ##
107 #
108 # Returns rendered template as HttpResponse.
109 #
110 def direct_to_template(request, template_name, content_type=None):
111  context = RequestContext(request)
112  template = loader.get_template(template_name)
113  return HttpResponse(template.render(context), content_type=content_type)
114 
115 
116 ##
117 #
118 # Simple generic ajax view for creating dialogs.
119 #
120 def simple_generic(request, template_name=None, success_msg=lambda x: '', ask_msg=lambda x: '', confirmation=_('Yes'), request_url=None, param=None):
121  return simple_generic_id(request, None, template_name, success_msg, ask_msg, confirmation, request_url, param)
122 
123 
124 def simple_generic_id(request, id1, template_name=None, success_msg=lambda x: '', ask_msg=lambda x: '',
125  confirmation=_('Yes'), request_url=None, param=None, id_key=None):
126  """
127  Simple generic ajax view for creating dialogs (1 entity).
128  """
129  return simple_generic_twoid(request, id1, None, template_name, success_msg, ask_msg, confirmation, request_url,
130  param, id_key, None)
131 
132 
133 @django_view
134 @ajax_request
135 @csrf_protect
136 def simple_generic_twoid(request, id1, id2, template_name=None, success_msg=lambda desc: _('Success') % {'desc': desc}, ask_msg=lambda x: '',
137  confirmation=_('Yes'), request_url=None, param=None, id_key=None, id_key2=None):
138  """
139  Simple generic ajax view for creating dialogs (2 entities).
140  """
141  if request.method == 'POST':
142  if request_url is None:
143  raise Exception("No 'request_url' specified.")
144 
145  args = {}
146  if id1 is not None:
147  if id_key is None:
148  raise Exception('\'id_key\' not set in urls')
149  args[id_key] = int(id1)
150 
151  if id2 is not None:
152  if id_key2 is None:
153  raise Exception('\'id_key2\' not set in urls')
154  args[id_key2] = int(id2)
155 
156  if param is not None:
157  args.update(param)
158 
159  prep_data((request_url, args), request.session)
160  return messages_ajax.success(success_msg(force_escape(request.REQUEST.get('desc'))))
161 
162  if template_name is not None:
163  return messages_ajax.success(render_to_string(template_name, {'text': ask_msg(force_escape(request.REQUEST.get('desc'))),
164  'confirmation': confirmation, 'id': id1}, context_instance=RequestContext(request)))
165 
166 
167 ##
168 #
169 # Generic ajax view returning a list.
170 #
171 def get_list_generic(request, request_url=None):
172  return get_list_generic_id(request, None, request_url)
173 
174 
175 @django_view
176 @ajax_request
177 @csrf_protect
178 ##
179 #
180 # Generic ajax view returning a list.
181 #
182 def get_list_generic_id(request, id1, request_url=None, id_key=None):
183  if request.method == 'GET':
184  if request_url is None:
185  raise Exception("No 'request_url' specified.")
186 
187  args = {}
188  if id1 is not None:
189  if id_key is None:
190  raise Exception('\'id_key\' not set in urls')
191  args[id_key] = int(id1)
192 
193  response = prep_data((request_url, args), request.session)
194  return messages_ajax.success(response)
195 
196  return messages_ajax.error('get_list_generic_id doesn\'t support POST')
197 
198 
199 ##
200 #
201 # Generic ajax view for dialog handling.
202 #
203 def form_generic(request, template_name=None, form_class=None, request_url_post=None, request_url_get=None,
204  success_msg=lambda x: '', ask_msg=lambda x: '', confirmation=_('Yes')):
205  return form_generic_id(request, None, template_name=template_name, form_class=form_class,
206  request_url_post=request_url_post, request_url_get=request_url_get,
207  success_msg=success_msg, ask_msg=ask_msg, confirmation=confirmation)
208 
209 
210 @django_view
211 @ajax_request
212 @csrf_protect
213 ##
214 #
215 # Generic ajax view for dialog handling.
216 #
217 def form_generic_id(request, id1, template_name=None, form_class=None,
218  request_url_post=None, request_url_get=None,
219  success_msg=lambda desc: _('Success'), ask_msg=lambda x: '', confirmation=_('Yes'),
220  request_url_both=None, ajax_success_status=0, id_key=None):
221  rest_data1 = prep_data(request_url_both, request.session)
222 
223  if request.method == 'POST':
224  kwargs = {}
225  if rest_data1 is not None:
226  kwargs['rest_data'] = rest_data1
227  form = form_class(request.POST, **kwargs)
228 
229  if form.is_valid():
230  args = {}
231 
232  if id1 is not None:
233  if id_key is None:
234  raise Exception('\'id_key\' not set in urls')
235  args[id_key] = int(id1)
236  args.update(form.cleaned_data)
237 
238  rest_data2 = prep_data((request_url_post, args), request.session)
239  return messages_ajax.success(success_msg(force_escape(request.REQUEST.get('desc')), rest_data2),
240  status=ajax_success_status)
241  else:
242  args = []
243  kwargs = {}
244 
245  if request_url_get is not None and id1 is not None:
246  response = prep_data((request_url_get, {id_key: id1}), request.session)
247 
248  args.append(response)
249 
250  if rest_data1 is not None:
251  kwargs['rest_data'] = rest_data1
252 
253  form = form_class(*args, **kwargs)
254 
255  return messages_ajax.success(render_to_string(template_name, {'form': form,
256  'text': ask_msg(force_escape(request.REQUEST.get('desc'))),
257  'confirmation': confirmation,
258  'id': id1},
259  context_instance=RequestContext(request)),
260  status=1)
261 
262 
263 @django_view
264 @ajax_request
265 @csrf_protect
266 def generic_multiple_id(request, template_name=None, success_msg=lambda x: _('Success'),
267  ask_msg=lambda x, y: _('Do you want to?'), confirmation=_('Yes'), request_url=None, id_key=None):
268  """
269  Generic ajax view for handling dialogs working on multiple items.
270  """
271  if request.method == 'POST':
272  id_list = request.POST.getlist('ids[]')
273 
274  if id_key is None:
275  raise Exception('\'id_key\' not set in urls')
276 
277  if request_url is None:
278  raise Exception("No 'request_url' specified.")
279 
280  response = prep_data((request_url, {id_key: [int(a) for a in id_list]}), request.session)
281  if response is None:
282  return messages_ajax.success(success_msg(request.POST.get('desc'), int(request.POST.get('length'))))
283  return _multiple_id_return(response, id_list, request.POST.get('desc'), success_msg)
284  else:
285  if request.GET.get('length') is None:
286  return messages_ajax.error(_("Bad argument list"))
287  return messages_ajax.success(render_to_string(template_name,
288  {'text': ask_msg(force_escape(request.GET.get('desc')), int(request.GET.get('length'))),
289  'confirmation': confirmation},
290  context_instance=RequestContext(request)))
291 
292 
293 @django_view
294 @ajax_request
295 @csrf_protect
296 def generic_multiple_id_form(request, template_name=None, success_msg=lambda x: _('Success'),
297  ask_msg=lambda x, y: _('Do you want to?'),
298  confirmation=_('Yes'),
299  request_url=None, form_class=None, request_url_both=None, id_key=None):
300  """
301  Generic ajax view for handling dialogs working on multiple items (with a form).
302  """
303  response1 = prep_data(request_url_both, request.session)
304 
305  if request.method == 'POST':
306  if id_key is None:
307  raise Exception('\'id_key\' not set in urls')
308 
309  if request_url is None:
310  raise Exception("No 'request_url' specified.")
311 
312  kwargs = {}
313  if response1 is not None:
314  kwargs['rest_data'] = response1
315  form = form_class(request.POST, **kwargs)
316 
317  if form.is_valid():
318  id_list = [int(a) for a in request.POST.getlist('ids[]')]
319  dictionary = {id_key: id_list}
320  dictionary.update(form.cleaned_data)
321  response2 = prep_data((request_url, dictionary), request.session)
322 
323  return _multiple_id_return(response2, id_list, request.POST.get('desc'), success_msg)
324  else:
325  args = []
326  kwargs = {}
327 
328  if response1 is not None:
329  kwargs['rest_data'] = response1
330 
331  form = form_class(*args, **kwargs)
332 
333  return messages_ajax.success(render_to_string(template_name,
334  {'form': form,
335  'text': ask_msg(force_escape(request.REQUEST.get('desc')), int(request.REQUEST.get('length'))),
336  'confirmation': confirmation},
337  context_instance=RequestContext(request)),
338  status=1)
339 
340 
341 ##
342 #
343 # Helper function creating ajax response with error codes.
344 #
345 def _multiple_id_return(response, id_list, desc, success_msg):
346  all_ok = True
347  for machine_response in response:
348  if machine_response['status'] != 'ok':
349  all_ok = False
350  if all_ok:
351  count = len(id_list)
352  return messages_ajax.success(success_msg(desc, count))
353  else:
354  for i in range(len(response)):
355  response[i]['type'] = 'vm'
356  response[i]['vmid'] = id_list[i]
357  response[i]['status_text'] = unicode(get_error(response[i]['status']))
358  return messages_ajax.success(response, 7999)
359 
360 
361 ##
362 #
363 # WizardView class handling browser back button after last step submition
364 # and skipping to 2nd step if image is already selected
365 #
366 class CustomWizardView(CookieWizardView):
367 
368  wizard_name = 'custom_wizard'
369  template_dir_name = 'dirname'
370  url_start = 'url_start'
371 
373  return self.template_dir_name + '/' + self.wizard_name + self.steps.current + '.html'
374 
375  def post(self, *args, **kwargs):
376  # problem with hitting browser back button:
377  # if posting on step other then the first and "step_data" in the cookie is an empty dict
378  # do redirect to the first step
379  if self.request.POST[self.wizard_name + '-current_step'] != '0' and self.request.COOKIES.get('wizard_' + self.wizard_name).find("\"step_data\":{}") != -1:
380  return redirect(self.url_start)
381 
382  # not saving 2 first steps in wizard
383  # (avoiding problems with hidden_inputs)
384  if self.request.POST[self.wizard_name + '-current_step'] not in ['0', '1']:
385  form = self.get_form(data=self.request.POST, files=self.request.FILES)
386  self.storage.set_step_data(self.steps.current, self.process_step(form))
387 
388  return super(CustomWizardView, self).post(*args, **kwargs)
389 
390  def get(self, request, *args, **kwargs):
391  self.storage.reset()
392 
393  # reset the current step to the first step.
394  self.storage.current_step = self.steps.first
395 
396  # skipping first step
397  if self.request.GET.get('selected_image'):
398  form = self.get_form(data={'0-image_id': [self.request.REQUEST['selected_image']],
399  self.wizard_name + '-current_step': [u'0']})
400  self.storage.set_step_data(self.steps.current, self.process_step(form))
401 
402  self.storage.current_step = str(int(self.steps.first) + 1)
403 
404  return self.render(self.get_form())
405 
406  ##
407  #
408  # This method must be overridden by a subclass to process to form data
409  # after processing all steps.
410  #
411  def done(self, form_list, **kwargs):
412  raise NotImplementedError("Your %s class has not defined a done() "
413  "method, which is required." % self.__class__.__name__)
414