source: TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/ndgInterface.py @ 2787

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/ows_framework/trunk/ows_server/ows_server/lib/ndgInterface.py@2787
Revision 2787, 7.1 KB checked in by pjkersha, 12 years ago (diff)

ows_server/ndgDiscovery.config:

  • refs. to saturn host replaced with localhost
  • acIssuerName security param changed to acIssuer - this is used by the

gatekeeper to check that the AC submitted was issued by the expected AA.

ows_server/ows_server/models/ndgSecurity.py:

  • working version but Nb. hack for AA URI. This is hard-wired until final

AA URI is agreed upon for storage in the data.

ows_server/ows_server/controllers/login.py:

params for security are only passed across the redirect if the two parties are
in separate domains.

ows_server/ows_server/lib/ndgInterface.py:

  • switched on security. To switch off again change True to False in if

statement around line 186.

ows_server/ows_server/lib/base.py:

  • fix to qs setting. There was a ref'd before declaration error.
Line 
1# Copyright (C) 2007 STFC & NERC (Science and Technology Facilities Council).
2# This software may be distributed under the terms of the
3# Q Public License, version 1.0 or later.
4# http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
5"""
6Manages interface to NDG documents and data, including caching
7"""
8
9from cache import Cache
10import os, tempfile
11import cdms, csml
12from ows_server.models import ndgRetrieve, ndgObject
13from pylons import request,session
14import logging
15logger = logging.getLogger('ndgInterface')
16from ows_server.models.ndgSecurity import HandleSecurity
17
18class CDMSEntry(object):
19    """
20    A reference to a CDMS file that will delete the file when it is
21    garbage collected.
22
23    Instances of this class are used as Cache entry values.  When entries are
24    automatically removed from the cache the CDMSEntry object will be
25    garbage collected unless it is being accessed by another thread.
26
27    """
28
29    __slots__ = ['_f', 'var']
30   
31    def __init__(self, filename, varname):
32        logger.info('Caching file variable %s in %s' % (varname, filename))
33        self._f = cdms.open(filename)
34        self.var = self._f[varname]
35    def __del__(self):
36        filename = self._f.id
37        logger.info('Removing file %s' % filename)
38        self._f.close()
39        os.remove(filename)
40 
41
42class CSMLExtractCache(Cache):
43   
44    def __init__(self, cache_dir, max_size=0):
45        super(CSMLExtractCache, self).__init__(max_size)
46        self._cache_dir = cache_dir
47
48    def _extract(self, feature, sel):
49        (fd, filename) = tempfile.mkstemp('.nc', 'csml_wxs_', self._cache_dir)
50        os.close(fd)
51        (outputdir, ncname) = os.path.split(filename)
52
53        # Workarround until ticket:778 (TestExtractAll) is fixed
54        sel.update(longitude=(-180, 180), latitude=(-90, 90))
55
56        feature.subsetToGridSeries(ncname=ncname, outputdir=outputdir, **sel)
57
58        return filename
59   
60    def key(self, name):
61        """
62        Cache provides this method to map externally visible entry names
63        to internal keys.  We use it here to turn selectors into hashable
64        values.
65
66        """
67        (feature, sel) = name
68       
69        return (feature.id, tuple(sorted(sel.items())))
70
71    def build(self, key, name, opened, entry):
72        (feature, sel) = name
73        filename = self._extract(feature, sel)
74
75        return CDMSEntry(filename, feature.name.CONTENT)
76
77    def __getitem__(self, name):
78        """
79        Returns the opened CDMS object.
80
81        """
82        return super(CSMLExtractCache, self).__getitem__(name).var
83
84class ndgInterface:
85   
86    def __init__(self):
87        ''' Instantiate with three level cache:
88                - a file cache
89                - a xmlhandler object cache, and
90                - a parsed CSML object cache.'''
91               
92        self.CSMLDataCache=CSMLExtractCache(
93                request.environ['paste.config']['app_conf']['tmp_dir'],max_size=10)
94        self.CSMLDocCache=Cache(max_size=10)
95        self.XMLHCache=Cache(max_size=10)
96       
97
98    def GetXML(self,uri,format=''):
99        ''' This method provides a secure interface to the server
100        document cache and a remote NDG exist. It is assumed that
101        the local filesystem is protected in that you can't get to
102        files except via the CSML api '''
103        #    Note that this method should not be used to obtain
104        #unsecured discovery documents, these are called directly
105        #in the retrieve controller!
106       
107        try:
108            ndgO=ndgObject.ndgObject(uri)
109            localFile=0
110        except ValueError:
111            ''' It's a local file not an ndg identifier '''
112            ndg0=uri
113            localFile=1
114       
115        if 'ndgCleared' in session:
116            cleared=session['ndgCleared']
117        else:
118            cleared=None
119         
120        try:
121            xmlh=self.XMLHCache[uri]
122            status=1
123            logging.info('XMLH Cache hit for [%s]'%uri)
124        except:
125            logging.info('XMLH Cache miss for [%s]'%uri)
126            if localFile:
127                status,xmlH=self.__getLocal(uri)
128            else:   
129                status,xmlh=ndgRetrieve.ndgRetrieve(ndgO,request.environ['ndgConfig'],logger,format)
130            if status: self.XMLHCache[uri]=xmlh
131           
132        if not status: return status,xmlh
133       
134        if not status: return status,xmlh
135        # valid values of the return objects SHOULD BE
136        #   ok:         status=1, xmlh=an xml handler instance.
137        #   exceptions, status=0, xmlh='Exception(e)'
138       
139        status,xmlh=self.__GateKeep(ndgO,xmlh)
140        if status:
141            if cleared is None:
142                session['ndgCleared']=[uri]
143            else:
144                session['ndgCleared'].append(uri)
145            session.save()
146       
147        return status,xmlh
148           
149    def GetParsedCSML(self,uri):
150       
151        ''' This method gets a parsed CSML object corresponding to the URI '''
152       
153        # do we need an xml handler instance to test the security?
154        if 'ndgCleared' not in session:
155            status,xmlh=self.GetXML(uri)
156        else: 
157            if uri not in session['ndgCleared']: 
158                status,xmlh=self.GetXML(uri)
159            else: status=1
160        if not status: return status,xmlh
161       
162        try:
163            d=self.CSMLDocCache[uri]
164            logging.info('CSML Cache hit for [%s]'%uri)
165        except:
166            logging.info('CSML Cache miss for [%s]'%uri)
167            status,xmlh=self.GetXML(uri)
168            if not status: return status,xmlh   
169            d=csml.parser.Dataset()
170            d.parseElemTree(xmlh.tree)
171            self.CSMLDocCache[uri]=d
172        status=1
173        return status,d
174       
175    def __GateKeep(self,uri,x):
176        ''' This is the NDG gatekeeper '''
177        if 'ndgSec' in session:
178            securityTokens=session['ndgSec']
179        else:
180            securityTokens=None
181       
182        if uri.schema=='DIF':
183            pass # no access control
184        elif uri.schema =='NDG-B0':
185            #cred=x.find('dgSecurityCondition/simpleCondition')
186            #if cred:
187            #    return 0,'<p> Access Control: <br/>[<![CDAT[%s]]> </p>'
188            pass
189        elif uri.schema =='NDG-B1':
190            pass # for the moment
191        elif uri.schema =='NDG-A0':
192            if True:  # use this for turning security on and off during testing
193                s=x.tree.find('{http://ndg.nerc.ac.uk/csml}AccessControlPolicy/{http://ndg.nerc.ac.uk/csml}dgSecurityCondition')
194                if s is not None:
195                    status,message=HandleSecurity(s,securityTokens)
196                    if not status: return 0,'<p> Access Denied </p><p>%s</p>'%message
197        return 1,x
198               
199    def __getLocal(self,uri):
200        ''' Returns a local csml file (used for testing) '''
201        csml_dir = request.environ['paste.config']['app_conf']['csml_dir']
202        path = os.path.join(csml_dir, file)
203        if os.path.exists(path+'.csml'):
204            f = path+'.csml'
205        elif os.path.exists(path+'.xml'):
206            f = path +'.xml'
207        else:
208            return 0, '<p>Cannot find CSML file %s</p>' % file
209        r=f.read()
210        return 1,r     
211       
212
213
214interface=ndgInterface()
Note: See TracBrowser for help on using the repository browser.