source: TI03-DataExtractor/trunk/pydxs/DXController.py @ 1109

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/trunk/pydxs/DXController.py@1109
Revision 1109, 11.3 KB checked in by astephen, 13 years ago (diff)

Stable-ish version with fully-ish working dxc client.

Line 
1#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
2#   This software may be distributed under the terms of the
3#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
4
5"""
6DXController.py
7================
8
9The core class for controlling the package.
10
11"""
12
13# Import required modules
14import sys
15import os 
16import time 
17
18# Bring package into local scope
19from serverConfig import BASEDIR
20sys.path.insert(0, os.path.split(BASEDIR)[0])
21sys.path.insert(0, "..")
22from pydxs import *
23
24 
25# Add any other locally required directories in which you have modules.
26for path in LOCAL_PYTHONPATH:
27   sys.path.insert(0, path) 
28
29
30class DXController:
31    """
32    Controls the overall process flow of the a session.
33    This class is called through each stage of the extraction process
34    and responds according to the environment and arguments provided.
35    Note that this class is called by the WSInterface
36    class which then reads various instance variables. As a result, very
37    little is returned from the methods below. Instead the data is stored
38    in the instance object.
39    """
40   
41    def __init__(self, args):
42        """
43        Takes in a group of arguments and then calls the appropriate
44        methods to process the user request.
45        """
46        self.username=None 
47        self.password=None
48        self.userRoles=[]
49        self.sessionID=None
50        self.sessionObj=None
51        self.bag=self.sessionObj # alias               
52        self.secureToken="undefined"
53        self.error=None
54   
55        # Parse the arguments
56        try:
57            self._parseArgs(args)
58        except Exception, error:
59            raise DXArgumentError, error
60           
61        # If switched on check security       
62        if self.error==None:
63            if RESTRICTED_DATA==1:
64                try:
65                    self._checkSecurity()
66                except Exception, error:
67                    raise DXSecurityError, error   
68            else:
69                self.secureToken="undefined"
70                   
71        # Construct the session object
72        if self.error==None:   
73            try:   
74                self._constructSessionObject()   
75            except Exception, error:
76                print error
77                raise DXSessionObjectError, error   
78
79        # Generate the options object
80        if self.error==None:   
81            try:   
82                self._generateOptions() 
83            except Exception, error:
84                raise DXOptionHandlingError, error
85
86
87        # Write request to a file if it has some content
88        if self.error==None:
89            if overlap(["datasetGroup_1", "datasetURI_1", "sessionID", "numberOfDatasets"], 
90                      self.bag.keys()):         
91                try:     
92                    self.bag["accessTime"]=time.time() 
93                    self.sessionObjectManager.writeSessionObject(self.bag) 
94                except Exception, error:
95                    raise DXSessionObjectError, error
96                   
97                """# Validate the selection against known information
98                try:       
99                    self._validate()               
100                except Exception, error:
101                    raise DXValidationError, error"""
102           
103        # Estimate the cost of the extraction
104        creditChecked=None
105        if self.error==None:   
106            if self.bag.has_key("action") and self.bag["action"]=="checkCredit":           
107                # Check user has sufficient credit
108                try:       
109                    self._checkCredit()   
110                    creditChecked="yes"             
111                except Exception, error:
112                    raise DXCreditError, error
113                   
114
115        # Estimate the cost of the extraction
116        if self.error==None:   
117            if (self.bag.has_key("action") and self.bag["action"]=="requestCosts") and self.options==[]:
118           
119                try:
120                    (self.estimatedDuration, self.estimatedVolume)=self._createOutput(costOnly=1)
121                    sizeLimitInBytes=REQUEST_SIZE_LIMIT*2L**20
122                    # If size is over limit then send a tidy error to the user
123                    if self.estimatedVolume>sizeLimitInBytes:
124
125                        sizeInMB=self.estimatedVolume/(2L**20.)
126
127                        err="""Your request of %.1f MB is over the current %s MB size limit.   
128The Data Extractor cannot yet deal with such large requests.
129Consider mailing <A HREF="mailto:%s">%s</A> for advice or submit multiple smaller requests.""" % (sizeInMB, 
130                               REQUEST_SIZE_LIMIT, ADMIN_MAIL_ADDRESS, ADMIN_MAIL_ADDRESS)     
131                        raise DXSizeLimitError, err
132                except Exception, error:
133                    raise Exception, error
134                     
135        # Process the selections to generate some data
136        if self.error==None:   
137            if (self.bag.has_key("getOutput") and creditChecked==None) and self.options==[]:
138                # Check user has sufficient credit
139                try:       
140                    self._checkCredit()                     
141                except Exception, error:
142                    raise Exception, error
143                           
144                try:       
145                    self._createOutput() 
146                    self.logger=LogManager(self.bag)       
147                    self.bag["status"]="complete"       
148                    self.logger.logCompletedRequest(self.bag["outputFilePaths"])               
149                except Exception, error:
150                    raise DXProcessingError, error
151       
152        if self.error==None:
153            print "\nSaving session details:\n", self.bag, "\n\n" 
154            if self.bag.has_key("action") and self.bag["action"]=="clearRequest":
155                del self.bag["action"]
156            self.sessionObjectManager.writeSessionObject(self.bag)
157        else:
158            self.logger=LogManager(self.bag) 
159            self.logger.logError(self.error)
160         
161           
162    def _parseArgs(self, args):
163        """
164        Parses the argument dictionary that are sent.
165        """                     
166        self.args={}
167        print "ARGS in...", args
168        for key, value in args.items():
169            if type(key)==type(u""):
170                newkey=str(key)
171            else:
172                newkey=key
173                   
174            if type(value)==type(u""):
175                newvalue=str(value)
176            else:
177                newvalue=value
178               
179            self.args[newkey]=newvalue
180           
181   
182        for item in ("username", "password", "secureToken"):
183            if self.args.has_key(item):             
184                value=self.args[item]               
185                setattr(self, item, value)
186                del self.args[item]
187               
188        print "ARGS and SecureToken:", self.args, self.secureToken
189                             
190
191    def _checkSecurity(self):
192        """
193        Checks security by getting username and
194        allowed groups from whatever implementation you have put in place.
195        """
196        if SECURITY_MODEL=="basic":
197            secChecker=NDGSecurityManager(self.username, self.password, self.secureToken)
198        elif SECURITY_MODEL=="ndg":
199            secChecker=SecurityManager(self.username, self.password, self.secureToken) 
200        else:
201            raise DXSecurityError, "Security model '%s' not supported." % SECURITY_MODEL
202         
203        # Do something about logout here as well
204     
205        secCheck=secChecker.validateUser() 
206        self.username=secChecker.username
207
208        if type(secCheck)==type(""):
209            raise DXSecurityError, secCheck
210        elif type(secCheck)==type([]):
211            (self.secureToken, self.userRoles)=secCheck 
212        else: 
213            raise DXSecurityError, str(secCheck)+str(type(secCheck))#"No response from Security class!"
214           
215
216    def _constructSessionObject(self):
217        """
218        Ensures that all appropriate arguments are being written
219        to the session object in the correct manner. Note that the
220        session object "sessionObj" is just a dictionary but is read
221        in from a shelve object (if it exists already).
222        """     
223        # self.args now holds the input arguments
224        if not self.args.has_key("sessionID"): 
225            self.sessionObjectManager=SessionObject()
226            self.bag=self.sessionObjectManager.dict
227            #self.sessionObj["targetPage"]=STAGES=[0]
228        else: 
229            self.sessionObjectManager=SessionObject(self.args["sessionID"]) 
230            self.bag=self.sessionObjectManager.readSessionObject() 
231            # Clear the session object if requested
232            if self.args.has_key("clearRequest") or self.args.has_key("newRequest"):
233                self.sessionObjectManager.clearSessionObject(self.bag) 
234               
235        if type(self.sessionID)==type(u""):
236            self.sessionID=str(self.sessionID) 
237               
238        # Update session object with allowed roles at each stage (this is checked every reload)
239        self.bag["userRoles"]=self.userRoles
240
241        # Say it is under construction at present
242        self.bag["status"]="constructing"
243       
244        # Add the rest of the arguments to the session object
245        for key in self.args.keys(): 
246            self.bag[key]=self.args[key] 
247
248        # Might need username later
249        if self.bag.has_key("username"):
250            self.username=self.bag["username"]
251        else:
252            self.bag["username"]=self.username
253           
254        # Sort out time selections if lists
255        axisSelections=getDictSubsetMatching(self.bag, "axis_")
256        axKeys=axisSelections.keys()
257        if len(axKeys)>0:
258            for key, value in axisSelections.items():
259                if type(value[0])==type([1,2]) and len(value[0])==6:
260                    self.bag[key]=("%.4d-%.2d-%.2dT%.2d:%.2d:%f" % tuple(value[0]),
261                                   "%.4d-%.2d-%.2dT%.2d:%.2d:%f" % tuple(value[1]))
262
263
264    def _generateOptions(self):
265        """
266        Method that examines the current status of the request to create an appropriate
267        list of options for the user. Made up of many if clauses to control a logical
268        response to the current request.
269        """
270        optHandler=OptionHandler(self.bag)
271        self.options=optHandler.options
272        print "\nself.options:", self.options
273       
274       
275    def DEPRECATED_validate(self):
276        """
277        Validates the selections made by the user. Returns 1 if successful
278        and a string if failure.
279        """
280        try:
281            ValidateSelection(self.bag)
282        except Exception, error:
283            raise DXValidationError, error
284           
285     
286    def _checkCredit(self):
287        """
288        Checks if the user has the available credit to the selection task. Returns 1 if successful
289        and a string if failure.
290        """
291        creditChecker=CreditManager(self.username, self.bag)
292        creditResponse=creditChecker.creditCheck()
293        if creditResponse!=1:
294            raise creditResponse
295           
296           
297    def _createOutput(self, costOnly=None):
298        """
299        Creates either data files or a dataSubsetSpecifier xml file.
300        """   
301        outputManager=OutputManager(self.bag)
302        pathDict=outputManager.getOutputFilePathDict()
303        sizeDict=outputManager.getOutputSizes()
304        durationDict=outputManager.getOutputDurationEstimates()
305       
306        outputFilePaths=[]
307        outputSize=0
308        duration=0
309       
310        for key in pathDict.keys():
311            outputSize=outputSize+sizeDict[key]
312            duration=duration+durationDict[key]
313            outputFilePaths=outputFilePaths+pathDict[key]
314           
315        self.bag["outputFilePaths"]=outputFilePaths   
316           
317        if costOnly==1:
318            return (duration, outputSize)
319       
320        print """Should really fork this process at this point so that we can return
321              something if likely to be large job."""
322        outputManager.createOutputs() 
323
324
325if __name__=="__main__":
326    x=DXController({}).bag
327    sessionID=x["sessionID"]
328    DXController({"sessionID":sessionID, "secureToken":None})
329    DXController({"sessionID":sessionID, "secureToken":None, "datasetGroup_1":"Test Data Group 1"})
330    DXController({"sessionID":sessionID, "secureToken":None, "dataset_1.1":"Test Dataset 1"})   
331    DXController({"sessionID":sessionID, "secureToken":None, "variable_1.1.1":"pqn"})
332    DXController({"sessionID":sessionID, "secureToken":None, "axis_1.1.1.2":(-30,30)}) 
333    DXController({"sessionID":sessionID, "secureToken":None, "axis_1.1.1.1":("1999-01-01T00:00:00", "1999-01-01T06:00:00")})
334    DXController({"sessionID":sessionID, "secureToken":None, "outputFormat_1.1.1":"NetCDF"}) 
335    DXController({"sessionID":sessionID, "secureToken":None, "outputFormat_1.1.1":"NetCDF", "action":"requestCosts"})           
336    DXController({"sessionID":sessionID, "secureToken":None, "getOutput":"getOutput"})   
337   
Note: See TracBrowser for help on using the repository browser.