Rest SFA Client
[unfold.git] / rest / sfa_api.py
1 import os
2 import json
3 import ConfigParser 
4 import datetime
5 from time                       import mktime
6
7 from django.shortcuts           import render_to_response
8 from django.http                import HttpResponse
9
10 from sfa.trust.certificate      import Keypair, Certificate
11 from sfa.client.sfaserverproxy  import SfaServerProxy
12 from sfa.client.return_value    import ReturnValue
13 from sfa.util.xrn               import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
14
15 from manifold.core.query        import Query
16 from manifold.models            import db
17 from manifold.models.platform   import Platform
18 from manifold.models.user       import User
19
20 from unfold.loginrequired       import LoginRequiredView
21
22 from myslice.settings           import logger
23
24 from rest.json_encoder          import MyEncoder
25
26 def dispatch(request, method):
27     Config = ConfigParser.ConfigParser()
28     Config.read(os.getcwd() + "/myslice/monitor.ini")
29
30     #logger.debug(request.session['user']['email'])
31     user_email = request.session['user']['email']
32
33     platforms = list()
34     options   = dict()
35     rspec = ''
36     results = dict()
37     urn = ''
38     hrn = ''
39     object_type = ''
40
41     if request.method == 'POST':
42         req_items = request.POST
43     elif request.method == 'GET':
44         req_items = request.GET
45
46     for el in req_items.items():
47         if el[0].startswith('rspec'):
48             rspec += el[1]
49         elif el[0].startswith('platform'):
50             platforms += req_items.getlist('platform[]')
51         #elif el[0].startswith('options'):
52         #    options += req_items.getlist('options[]')
53         elif el[0].startswith('hrn'):
54             hrn = el[1]
55         elif el[0].startswith('urn'):
56             urn = el[1]
57         elif el[0].startswith('type'):
58             object_type = el[1]
59
60     if method not in ['GetVersion','ListResources']:
61         try:
62             if not hrn:
63                 hrn = urn_to_hrn(urn)
64             else:
65                 urn = hrn_to_urn(hrn, object_type) 
66         except Exception,e:
67             logger.error(e)
68             raise Exception, "Provide urn OR hrn + type as parameters of method %s" % method
69
70     if len(platforms)==0:
71         platforms = get_platforms()
72         #platforms.append('myslice')
73     #results = {'method':method,'platforms':platforms,'rspec':rspec,'options':options}
74
75     result = []
76     api_options = {}
77     api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
78     server_am = False
79     from manifoldapi.manifoldapi    import execute_admin_query
80     for pf in platforms:
81         platform = get_platform_config(pf)
82         logger.debug("platform={}".format(platform))
83         if 'sm' in platform and len(platform['sm']) > 0:
84             logger.debug('sm')
85             server_am = True
86             server_url = platform['sm']
87         if 'rm' in platform and len(platform['rm']) > 0:
88             logger.debug('rm')
89             server_am = False
90             server_url = platform['rm']
91         if 'registry' in platform and len(platform['registry']) > 0:
92             logger.debug('registry')
93             server_am = False
94             server_url = platform['registry']
95     
96         if not Config.has_option('monitor', 'cert') :
97              return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
98
99         cert = os.path.abspath(Config.get('monitor', 'cert'))
100         if not os.path.isfile(cert) :
101              return HttpResponse(json.dumps({'error' : '-1'}), content_type="application/json")
102
103         if not Config.has_option('monitor', 'pkey') :
104              return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
105
106         pkey = os.path.abspath(Config.get('monitor', 'pkey'))
107         if not os.path.isfile(pkey) :
108              return HttpResponse(json.dumps({'error' : '-2'}), content_type="application/json")
109  
110         server = SfaServerProxy(server_url, pkey, cert)
111
112         try:
113             # Get user config from Manifold
114             user_config = get_user_config(user_email, pf)
115             if 'delegated_user_credential' in user_config:
116                 user_cred = user_config['delegated_user_credential']
117             else:
118                 user_cred = {}
119
120             if object_type:
121                 if 'delegated_%s_credentials'%object_type in user_config:
122                     for obj_name, cred in user_config['delegated_%s_credentials'%object_type].items():
123                         if obj_name == hrn:
124                             object_cred = cred
125
126             # Both AM & Registry
127             if method == "GetVersion": 
128                 result = server.GetVersion()
129             else:
130                 # AM V3
131                 if server_am:
132                     if method == "ListResources":
133                         result = server.ListResources([user_cred], api_options)
134                     elif method == "Describe":
135                         # if GetVersion = v2
136                         # ListResources(slice_hrn)
137                         # else GetVersion = v3
138                         result = server.Describe([urn] ,[object_cred], api_options)
139                     elif method == 'Renew':
140                         result = server.Renew([urn] ,[object_cred], api_options)
141                     elif method == 'Delete':
142                         result = server.Delete([urn] ,[object_cred], api_options)
143                     elif method == 'Allocate':
144                         # if GetVersion = v2
145                         # CreateSliver(slice_hrn)
146                         # else GetVersion = v3
147                         api_options['call_id']    = unique_call_id()
148                         # List of users comes from the Registry
149                         api_options['sfa_users']  = sfa_users
150                         api_options['geni_users'] = geni_users
151                         result = server.Allocate([urn] ,[object_cred], rspec, api_options)
152                     elif method == 'Provision':
153                         # if GetVersion = v2
154                         # Nothing it is not supported by v2 AMs
155                         api_options['call_id']    = unique_call_id()
156                         # List of users comes from the Registry
157                         api_options['sfa_users']  = sfa_users
158                         api_options['geni_users'] = geni_users
159                         result = server.Provision([urn] ,[object_cred], api_options)
160                     elif method == 'Status':
161                         result = server.Status([urn] ,[object_cred], api_options)
162                     elif method == 'PerformOperationalAction':
163                         # if GetVersion = v2
164                         # Nothing it is not supported by v2 AMs
165                         result = server.PerformOperationalAction([urn] ,[object_cred], action, api_options)
166                     elif method == 'Shutdown':
167                         result = server.Shutdown(urn ,[object_cred], api_options)
168                     else:
169                         #return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported by AM'}), content_type="application/json")
170                         logger.debug('method %s not handled by AM' % method)
171                         result = []
172                 else:
173                     if method == "List":
174                         # hrn is required
175                         result = server.List(hrn, user_cred, options)
176                         logger.debug(result)
177                     elif method == "Resolve":
178                         # hrn is required
179                         # details can be True or False
180                         options['details']=True
181                         result = server.Resolve(hrn, user_cred, options)
182                         logger.debug(result)
183                     elif method == "Register":
184                         # record_dict must be crafted
185                         # auth_cred must be selected in the list of auth_creds from user's account
186                         result = server.Register(record_dict, auth_cred)
187                     elif method == "Update":
188                         # record_dict must be crafted
189                         # object_cred must be selected in the list of creds for the object type
190                         # from user's account
191                         result = server.Update(record_dict, object_cred)
192                     elif method == "Remove":
193                         # hrn is required
194                         # auth_cred must be selected in the list of auth_creds from user's account
195                         # object_type is required
196                         result = server.Remove(hrn, auth_cred, object_type)
197                     else:
198                         #return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported by Registry'}), content_type="application/json")
199                         logger.debug('method %s not handled by Registry' % method)
200                         result = []
201
202             results[pf] = result
203         except Exception,e:
204             import traceback
205             logger.error(traceback.format_exc())
206             logger.error(e)
207             results[pf] = {'error':'-3', 'error_msg': str(e)}
208
209     return HttpResponse(json.dumps(results, cls=MyEncoder), content_type="application/json")
210
211 def get_user_account(user_email, platform_name):
212     """
213     Returns the user configuration for a given platform.
214     This function does not resolve references.
215     """
216     user = db.query(User).filter(User.email == user_email).one()
217     platform = db.query(Platform).filter(Platform.platform == platform_name).one()
218     accounts = [a for a in user.accounts if a.platform == platform]
219     if not accounts:
220         raise Exception, "this account does not exist"
221
222     if accounts[0].auth_type == 'reference':
223         pf = json.loads(accounts[0].config)['reference_platform']
224         return get_user_account(user_email, pf)
225
226     return accounts[0]
227
228 def get_user_config(user_email, platform_name):
229     account = get_user_account(user_email, platform_name)
230     return json.loads(account.config) if account.config else {}
231
232 def get_platforms():
233     ret = list()
234     platforms = db.query(Platform).all()
235     for p in platforms:
236         ret.append(p.platform)
237     return ret
238
239
240 def get_platform_config(platform_name):
241     platform = db.query(Platform).filter(Platform.platform == platform_name).one()
242     return json.loads(platform.config) if platform.config else {}