getAutorities is now using rest/sfa_api avoiding cache pb in Manifold
[unfold.git] / rest / sfa_api.py
index 002c60a..72f2f92 100644 (file)
@@ -1,44 +1,41 @@
-from __future__ import print_function
+import os
+import json
+import ConfigParser 
+import datetime
+from time                       import mktime
+import xmltodict
+
+from django.shortcuts           import render_to_response
+from django.http                import HttpResponse
 
 from sfa.trust.certificate      import Keypair, Certificate
 from sfa.client.sfaserverproxy  import SfaServerProxy
 from sfa.client.return_value    import ReturnValue
 from sfa.util.xrn               import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
 
 from sfa.trust.certificate      import Keypair, Certificate
 from sfa.client.sfaserverproxy  import SfaServerProxy
 from sfa.client.return_value    import ReturnValue
 from sfa.util.xrn               import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
+
 from manifold.core.query        import Query
 from manifold.models            import db
 from manifold.models.platform   import Platform
 from manifold.models.user       import User
 
 from manifold.core.query        import Query
 from manifold.models            import db
 from manifold.models.platform   import Platform
 from manifold.models.user       import User
 
-from django.shortcuts           import render_to_response
-
 from unfold.loginrequired       import LoginRequiredView
 
 from unfold.loginrequired       import LoginRequiredView
 
-from rest import ObjectRequest, error
-
-from string import join
+from myslice.settings           import logger, config
 
 
-from django.http import HttpResponse
-from rest import error
-import os,json
-
-import ConfigParser 
+from rest.json_encoder          import MyEncoder
 
 def dispatch(request, method):
 
 def dispatch(request, method):
-    Config = ConfigParser.ConfigParser()
-    Config.read(os.getcwd() + "/myslice/monitor.ini")
-
-    # hardcoded user to be replaced by auth
-    user_email = "loic.baron@lip6.fr"
-
-    # Get this as parameters
-    slice_hrn = "fed4fire.upmc.berlin"
-    urn = hrn_to_urn(slice_hrn, "slice")
-    #urn = hrn_to_urn("fed4fire.upmc.loic_baron", "user")
 
 
-    platforms = list()
-    options   = list()
+    hrn = ''
+    urn = ''
+    object_type = ''
     rspec = ''
     rspec = ''
+    recursive = False
+    options   = dict()
+    platforms = list()
+
     results = dict()
     results = dict()
+    display = None
 
     if request.method == 'POST':
         req_items = request.POST
 
     if request.method == 'POST':
         req_items = request.POST
@@ -48,27 +45,114 @@ def dispatch(request, method):
     for el in req_items.items():
         if el[0].startswith('rspec'):
             rspec += el[1]
     for el in req_items.items():
         if el[0].startswith('rspec'):
             rspec += el[1]
-        if el[0].startswith('platform'):
+        elif el[0].startswith('platform'):
             platforms += req_items.getlist('platform[]')
             platforms += req_items.getlist('platform[]')
-        elif el[0].startswith('options'):
-            options += req_items.getlist('options[]')
+        #elif el[0].startswith('options'):
+        #    options += req_items.getlist('options[]')
+        elif el[0].startswith('hrn'):
+            hrn = el[1]
+        elif el[0].startswith('urn'):
+            urn = el[1]
+        elif el[0].startswith('type'):
+            object_type = el[1]
+        elif el[0].startswith('recursive'):
+            if el[1] == '1':
+                recursive = True
+            else:
+                recursive = False
+        elif el[0].startswith('display'):
+            display = el[1]
+
+    results = sfa_client(request, method, hrn, urn, object_type, recursive, options, platforms)
+
+    if display == 'table':
+        return render_to_response('table-default.html', {'data' : data, 'fields' : columns, 'id' : '@component_id', 'options' : None})
+    else:
+        return HttpResponse(json.dumps(results, cls=MyEncoder), content_type="application/json")
+
+def get_user_account(user_email, platform_name):
+    """
+    Returns the user configuration for a given platform.
+    This function does not resolve references.
+    """
+    user = db.query(User).filter(User.email == user_email).one()
+    platform = db.query(Platform).filter(Platform.platform == platform_name).one()
+    accounts = [a for a in user.accounts if a.platform == platform]
+    if not accounts:
+        raise Exception, "this account does not exist"
+
+    if accounts[0].auth_type == 'reference':
+        pf = json.loads(accounts[0].config)['reference_platform']
+        return get_user_account(user_email, pf)
+
+    return accounts[0]
+
+def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None, recursive=None, options=None, platforms=None, admin=False):
+
+    Config = ConfigParser.ConfigParser()
+    Config.read(os.getcwd() + "/myslice/monitor.ini")
+
+    if admin:
+        user_email, admin_password = config.manifold_admin_user_password()
+    else:
+        #logger.debug(request.session['user']['email'])
+        user_email = request.session['user']['email']
+
+    results = dict()
+
+    if hrn is None:
+        hrn = ''
+    if urn is None:
+        urn = ''
+    if object_type is None:
+        object_type = ''
+    if rspec is None:
+        rspec = ''
+    if recursive is None:
+        recursive = False
+    if options is None:
+        options  = dict()
+    if platforms is None:
+        platforms = list()
+
+    if method not in ['GetVersion','ListResources']:
+        try:
+            if not hrn:
+                hrn = urn_to_hrn(urn)
+            else:
+                urn = hrn_to_urn(hrn, object_type) 
+        except Exception,e:
+            logger.error(e)
+            raise Exception, "Provide urn OR hrn + type as parameters of method %s" % method
 
     if len(platforms)==0:
 
     if len(platforms)==0:
-        platforms.append('myslice')
+        platforms = get_platforms()
+        #platforms.append('myslice')
     #results = {'method':method,'platforms':platforms,'rspec':rspec,'options':options}
 
     #results = {'method':method,'platforms':platforms,'rspec':rspec,'options':options}
 
+    result = []
+    dict_result = {}
+    data = []
+    columns = []
+    api_options = {}
+    api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+    api_options['list_leases'] = 'all'
+    server_am = False
     from manifoldapi.manifoldapi    import execute_admin_query
     for pf in platforms:
         platform = get_platform_config(pf)
     from manifoldapi.manifoldapi    import execute_admin_query
     for pf in platforms:
         platform = get_platform_config(pf)
-        print(platform)
+        logger.debug("platform={}".format(platform))
         if 'sm' in platform and len(platform['sm']) > 0:
         if 'sm' in platform and len(platform['sm']) > 0:
-            print('sm')
+            logger.debug('sm')
+            server_am = True
             server_url = platform['sm']
         if 'rm' in platform and len(platform['rm']) > 0:
             server_url = platform['sm']
         if 'rm' in platform and len(platform['rm']) > 0:
-            print('rm')
+            logger.debug('rm')
+            server_am = False
             server_url = platform['rm']
         if 'registry' in platform and len(platform['registry']) > 0:
             server_url = platform['rm']
         if 'registry' in platform and len(platform['registry']) > 0:
-            print('registry')
+            logger.debug('registry')
+            server_am = False
             server_url = platform['registry']
     
         if not Config.has_option('monitor', 'cert') :
             server_url = platform['registry']
     
         if not Config.has_option('monitor', 'cert') :
@@ -87,58 +171,167 @@ def dispatch(request, method):
  
         server = SfaServerProxy(server_url, pkey, cert)
 
  
         server = SfaServerProxy(server_url, pkey, cert)
 
-        # Get user config from Manifold
-        user_config = get_user_config(user_email, pf)
-        if 'delegated_user_credential' in user_config:
-            user_cred = user_config['delegated_user_credential']
-        else:
-            user_cred = {}
-
-        #if 'delegated_slice_credentials' in user_config:
-        #    for slice_name, cred in user_config['delegated_slice_credentials']:
-        #        if slice_name == slice_param
-
-        if method == "GetVersion": 
-            result = server.GetVersion()
-        elif method == "ListResources":
-            api_options = {}
-            #api_options ['call_id'] = unique_call_id()
-            api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
-            result = server.ListResources([user_cred], api_options)
-        elif method == "Describe":
-            api_options = {}
-            #api_options ['call_id'] = unique_call_id()
-            api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
-            result = server.Describe([urn] ,[object_cred], api_options)
-
-        else:
-            return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported yet'}), content_type="application/json")
-
-        results[pf] = result
-
-    return HttpResponse(json.dumps(results), content_type="application/json")
+        try:
+            # Get user config from Manifold
+            user_config = get_user_config(user_email, pf)
+            if 'delegated_user_credential' in user_config:
+                user_cred = user_config['delegated_user_credential']
+            elif 'user_credential' in user_config:
+                user_cred = user_config['user_credential']
+            else:
+                user_cred = {}
 
 
-def get_user_account(user_email, platform_name):
-    """
-    Returns the user configuration for a given platform.
-    This function does not resolve references.
-    """
-    user = db.query(User).filter(User.email == user_email).one()
-    platform = db.query(Platform).filter(Platform.platform == platform_name).one()
-    accounts = [a for a in user.accounts if a.platform == platform]
-    if not accounts:
-        raise Exception, "this account does not exist"
+            if object_type:
+                if 'delegated_%s_credentials'%object_type in user_config:
+                    for obj_name, cred in user_config['delegated_%s_credentials'%object_type].items():
+                        if obj_name == hrn:
+                            object_cred = cred
+                elif '%s_credentials'%object_type in user_config:
+                    for obj_name, cred in user_config['%s_credentials'%object_type].items():
+                        if obj_name == hrn:
+                            object_cred = cred
 
 
-    if accounts[0].auth_type == 'reference':
-        pf = json.loads(accounts[0].config)['reference_platform']
-        return get_user_account(user_email, pf)
+            # Both AM & Registry
+            if method == "GetVersion": 
+                result = server.GetVersion()
+            else:
+                # AM API Calls
+                if server_am:
+                    if method == "ListResources":
+                        result = server.ListResources([user_cred], api_options)
+                        dict_result = xmltodict.parse(result['value'])
+                        result['json'] = json.dumps(dict_result)
+                        if isinstance(dict_result['rspec']['node'], list):
+                            columns.extend(dict_result['rspec']['node'][0].keys())
+                        else:
+                            columns.extend(dict_result['rspec']['node'].keys())
 
 
-    return accounts[0]
+                    elif method == "Describe":
+                        version = server.GetVersion()
+                        logger.debug(version['geni_api'])
+                        # if GetVersion = v2
+                        if version['geni_api'] == 2:
+                            # ListResources(slice_hrn)
+                            api_options['geni_slice_urn'] = urn
+                            result = server.ListResources([object_cred], api_options)
+                            dict_result = xmltodict.parse(result['value'])
+                        # else GetVersion = v3
+                        else:
+                            result = server.Describe([urn] ,[object_cred], api_options)
+                            dict_result = xmltodict.parse(result['value']['geni_rspec'])
+
+                        result['json'] = json.dumps(dict_result)
+                        if isinstance(dict_result['rspec']['node'], list):
+                            columns.extend(dict_result['rspec']['node'][0].keys())
+                        else:
+                            columns.extend(dict_result['rspec']['node'].keys())
+
+                    elif method == 'Renew':
+                        # Renew till 1 month from now
+                        d = datetime.datetime.utcnow() + datetime.timedelta(365/12)
+                        date = d.isoformat("T") + "Z"
+                        result = server.Renew([urn] ,[object_cred], date, api_options)
+                    elif method == 'Delete':
+                        result = server.Delete([urn] ,[object_cred], api_options)
+                    elif method == 'Allocate':
+                        # if GetVersion = v2
+                        # CreateSliver(slice_hrn)
+                        # else GetVersion = v3
+                        api_options['call_id']    = unique_call_id()
+                        # List of users comes from the Registry
+                        api_options['sfa_users']  = sfa_users
+                        api_options['geni_users'] = geni_users
+                        result = server.Allocate([urn] ,[object_cred], rspec, api_options)
+                    elif method == 'Provision':
+                        # if GetVersion = v2
+                        # Nothing it is not supported by v2 AMs
+                        api_options['call_id']    = unique_call_id()
+                        # List of users comes from the Registry
+                        api_options['sfa_users']  = sfa_users
+                        api_options['geni_users'] = geni_users
+                        result = server.Provision([urn] ,[object_cred], api_options)
+                    elif method == 'Status':
+                        result = server.Status([urn] ,[object_cred], api_options)
+                    elif method == 'PerformOperationalAction':
+                        # if GetVersion = v2
+                        # Nothing it is not supported by v2 AMs
+                        result = server.PerformOperationalAction([urn] ,[object_cred], action, api_options)
+                    elif method == 'Shutdown':
+                        result = server.Shutdown(urn ,[object_cred], api_options)
+                    else:
+                        #return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported by AM'}), content_type="application/json")
+                        logger.debug('method %s not handled by AM' % method)
+                        result = []
+
+                # Registry API Calls 
+                else:
+                    record_dict = {'urn': urn, 'hrn': hrn, 'type': object_type}
+                    if method == "List":
+                        # hrn is required
+                        api_options['recursive'] = recursive
+                        result = server.List(hrn, user_cred, api_options)
+                        if object_type:
+                            result = filter_records(object_type, result)
+                    elif method == "Resolve":
+                        # hrn is required
+                        # details can be True or False
+                        api_options['details']=True
+                        result = server.Resolve(hrn, user_cred, api_options)
+                        if object_type:
+                            result = filter_records(object_type, result)
+                    elif method == "Register":
+                        # record_dict must be crafted
+                        # auth_cred must be selected in the list of auth_creds from user's account
+                        result = server.Register(record_dict, auth_cred)
+                    elif method == "Update":
+                        # record_dict must be crafted
+                        # object_cred must be selected in the list of creds for the object type
+                        # from user's account
+                        result = server.Update(record_dict, object_cred)
+                    elif method == "Remove":
+                        # hrn is required
+                        # auth_cred must be selected in the list of auth_creds from user's account
+                        # object_type is required
+                        result = server.Remove(hrn, auth_cred, object_type)
+                    else:
+                        #return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported by Registry'}), content_type="application/json")
+                        logger.debug('method %s not handled by Registry' % method)
+                        result = []
+
+            results[pf] = result
+            if dict_result:
+                if isinstance(dict_result['rspec']['node'], list):
+                    data = data + dict_result['rspec']['node']
+                else:
+                    data.append(dict_result['rspec']['node'])
+        except Exception,e:
+            import traceback
+            logger.error(traceback.format_exc())
+            logger.error(e)
+            results[pf] = {'error':'-3', 'error_msg': str(e)}
+
+    results['columns'] = columns
+    return results
 
 def get_user_config(user_email, platform_name):
     account = get_user_account(user_email, platform_name)
     return json.loads(account.config) if account.config else {}
 
 
 def get_user_config(user_email, platform_name):
     account = get_user_account(user_email, platform_name)
     return json.loads(account.config) if account.config else {}
 
+def get_platforms():
+    ret = list()
+    platforms = db.query(Platform).filter(Platform.gateway_type == 'sfa', Platform.disabled == 0).all()
+    for p in platforms:
+        ret.append(p.platform)
+    return ret
+
+
 def get_platform_config(platform_name):
     platform = db.query(Platform).filter(Platform.platform == platform_name).one()
     return json.loads(platform.config) if platform.config else {}
 def get_platform_config(platform_name):
     platform = db.query(Platform).filter(Platform.platform == platform_name).one()
     return json.loads(platform.config) if platform.config else {}
+
+def filter_records(type, records):
+    filtered_records = []
+    for record in records:
+        if (record['type'] == type) or (type == "all"):
+            filtered_records.append(record)
+    return filtered_records