CreateSlice: url and purpose no longer required
[myslice.git] / portal / slicerequestview.py
1 import json
2 import time
3 import re
4
5 from django.shortcuts           import render
6 from django.shortcuts           import render_to_response
7 from django.template                    import RequestContext
8
9 from unfold.page                import Page
10
11 from manifold.core.query        import Query
12 from manifoldapi.manifoldapi    import execute_admin_query, execute_query
13
14 from portal.actions             import is_pi, create_slice, create_pending_slice, clear_user_creds, authority_check_pis, getAuthorities
15 #from portal.forms               import SliceRequestForm
16 from unfold.loginrequired       import LoginRequiredAutoLogoutView
17 from ui.topmenu                 import topmenu_items_live, the_user
18
19 from myslice.theme import ThemeView
20 from myslice.settings import logger
21
22 import activity.user
23 theme = ThemeView()
24
25 class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
26     template_name = 'slicerequest_view.html'
27     
28     # because we inherit LoginRequiredAutoLogoutView that is implemented by redefining 'dispatch'
29     # we cannot redefine dispatch here, or we'd lose LoginRequired and AutoLogout behaviours
30     def post (self, request):
31         return self.get_or_post (request, 'POST')
32
33     def get (self, request):
34         return self.get_or_post (request, 'GET')
35
36     def get_or_post  (self, request, method):
37         """
38         """
39
40         errors = []
41         slice_name =''
42         #purpose=''
43         #url=''
44         authority_hrn = None
45         authority_name = None
46         # Retrieve the list of authorities
47
48         authorities = getAuthorities(request, admin=True)
49
50         ##if self.theme == 'fed4fire' or self.theme == 'onelab':
51         #authorities_query = Query.get('myslice:authority').select('authority_hrn')
52         ##else:
53         ##    authorities_query = Query.get('authority').select('name', 'authority_hrn')
54         #authorities = execute_admin_query(request, authorities_query)
55         #if authorities is not None:
56         #    authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
57         #    #if self.theme != 'fed4fire' or  self.theme != 'onelab':
58         #    #    authorities = sorted(authorities, key=lambda k: k['name'])
59
60         # Get user_email (XXX Would deserve to be simplified)
61         user_query  = Query().get('local:user').select('email','config')
62         user_details = execute_query(request, user_query)
63         user_email = user_details[0].get('email')
64         # getting user_hrn
65         for user_detail in user_details:
66             user_config = json.loads(user_detail['config'])
67             user_authority = user_config.get('authority','N/A')              
68         # getting the org from authority        
69        # for authority in authorities:
70        #     if 'name' in authority and authority['authority_hrn'] == user_authority:
71        #         authority_name = authority['name']
72
73         # Handle the case when we use only hrn and not name
74         #if authority_name is None:
75         #    authority_name = user_authority
76         
77         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
78         account_details = execute_query(request, account_query)
79         
80         platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
81         platform_details = execute_query(request, platform_query)
82         user_hrn = None
83         #getting user_hrn from local:account
84         for account_detail in account_details:
85             for platform_detail in platform_details:
86                 if platform_detail['platform_id'] == account_detail['platform_id']:
87                     # taking user_hrn only from myslice account
88                     # NOTE: we should later handle accounts filter_by auth_type= managed OR user
89                     if 'myslice' in platform_detail['platform']:
90                         account_config = json.loads(account_detail['config'])
91                         user_hrn = account_config.get('user_hrn','N/A')
92         #                acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
93
94         pi = request.session['user']['pi']
95
96         # Page rendering
97         page = Page(request)
98         page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
99         page.add_css_files ( [ "css/jquery-ui.css" ] )
100         page.expose_js_metadata()
101
102         if method == 'POST':
103             # The form has been submitted
104
105             if request.is_secure():
106                 current_site = 'https://'
107             else:
108                 current_site = 'http://'
109             current_site += request.META['HTTP_HOST']
110
111             #if theme.theme != 'fed4fire' or  self.theme != 'onelab':
112                 # getting the authority_hrn from the selected organization
113             #    for authority in authorities:
114              #       if authority['name'] == request.POST.get('org_name', ''):
115               #          authority_hrn = authority['authority_hrn']
116
117             # Handle the case when we use only hrn and not name
118             if authority_hrn is None:
119                 authority_hrn = request.POST.get('org_name', '')
120
121             # Handle project if used
122             project = request.POST.get('org_name', None)
123             if project is not None and project != '':
124                 authority_hrn = project
125             slice_name = request.POST.get('slice_name', '')
126             if not slice_name or len(slice_name) == 0 :
127                 errors.append('Slice name can\'t be empty')
128
129             # accept only lowercase names
130             slice_name = slice_name.lower()
131
132             slice_request = {
133                 'type'              : 'slice',
134                 'id'                : None,
135                 'user_hrn'          : user_hrn,
136                 'email'             : user_email,
137                 'timestamp'         : time.time(),
138                 'authority_hrn'     : authority_hrn,
139                 'organization'      : request.POST.get('org_name', ''),
140                 'slice_name'        : slice_name,
141                 #'url'               : request.POST.get('url', ''),
142                 #'purpose'           : request.POST.get('purpose', ''),
143                 'current_site'      : current_site
144             }
145
146             # slice name is unique among all authorities 
147             slice_query = Query().get('myslice:slice').select('slice_hrn')
148             slice_details_sfa = execute_admin_query(request, slice_query)
149             for _slice in slice_details_sfa:
150                 split_list = _slice['slice_hrn'].split('.')
151                 sfa_slice_name = split_list[-1]
152                 if sfa_slice_name == slice_name:
153                     errors.append('Slice already exists. Please use a different slice name.')
154             
155
156             # What kind of slice name is valid?
157             if slice_name is None or slice_name == '':
158                 errors.append('Slice name is mandatory')
159             
160             if re.search(r'^[A-Za-z0-9_]*$', slice_name) is None:
161                 errors.append('Slice name may contain only letters, numbers, and underscore.')
162             
163             organization = slice_request['organization']
164             if theme.theme == 'fed4fire' or  self.theme == 'onelab':
165                 if organization is None or organization == '':
166                     errors.append('Selecting project is mandatory')
167             else:
168                 if organization is None or organization == '':
169                     errors.append('Organization is mandatory')
170
171             slice_length= len(slice_request['slice_name'])
172             if slice_length >19:
173                 errors.append('Slice name can be maximum 19 characters long')
174
175
176     
177            # purpose = slice_request['purpose']
178            # if purpose is None or purpose == '':
179            #     errors.append('Experiment purpose is mandatory')
180
181             #url = slice_request['url']
182
183             if not errors:
184                 if is_pi(request, user_hrn, authority_hrn):
185                     # PIs can directly create slices in their own authority...
186                     create_slice(request, slice_request)
187                     clear_user_creds(request, user_email)
188                     self.template_name = 'slice-request-done-view.html'
189                 else:
190                     # Otherwise a request is sent to the PI
191                     create_pending_slice(request, slice_request, user_email)
192                     self.template_name = 'slice-request-ack-view.html'
193                 
194                 # log user activity
195                 activity.user.slice(request)
196                 return render_to_response(self.template, {'theme': self.theme, 'request':request}, context_instance=RequestContext(request))
197                 #return render(request, self.template, {'theme': self.theme}) # Redirect after POST
198         else:
199             slice_request = {}
200
201         template_env = {
202             'username': request.user.email,
203             'topmenu_items': topmenu_items_live('Request a slice', page),
204             'errors': errors,
205             'slice_name': slice_name,
206             #'purpose': purpose,
207             'email': user_email,
208             'user_hrn': user_hrn,
209             #'url': url,
210             'pi': pi,
211             'authority_name': authority_name,        
212             'authority_hrn': user_authority,        
213             'cc_myself': True,
214             'authorities': authorities,
215             'theme': self.theme,
216             'section': "Slice request",
217             'request': request,
218         }
219         template_env.update(slice_request)
220         template_env.update(page.prelude_env())
221
222         return render_to_response(self.template,template_env, context_instance=RequestContext(request))
223         #return render(request, self.template, template_env)