session.py 7.05 KB
Newer Older
Marco Govoni's avatar
Marco Govoni committed
1
2
from __future__ import print_function

3
4
class Session(object):
    """Class for setting up a session, connected to a remove server via rest APIs.
Marco Govoni's avatar
Marco Govoni committed
5
6
7
8
    
    :Example:
    
    >>> from westpy import *
9
    >>> session = Session("email@domain.com")
Marco Govoni's avatar
Marco Govoni committed
10
11
12
    
    """
    def __init__(self,emailId) :
13
        self.token = None
Marco Govoni's avatar
Marco Govoni committed
14
        self.emailId = str(emailId)
15
16
17
        #
        # --- CONFIGURABLE PARAMETERS --- 
        self.serverName = "imedevel.uchicago.edu"
atanikan's avatar
atanikan committed
18
19
20
21
22
        self.restAPIinit = "http://imedevel.uchicago.edu:8000/init"
        self.restAPIrun  = "http://imedevel.uchicago.edu:8000/run"
        self.restAPIstop = "http://imedevel.uchicago.edu:8000/stop"
        self.restAPIstatus = "http://imedevel.uchicago.edu:8000/status"
        self.maxSessionTime = 3600 # seconds
Marco Govoni's avatar
Marco Govoni committed
23
        self.maxWaitTime = 1800 # seconds
24
25
26
        self.maxNumberOfCores = 4
        self.allowedExecutables = ["pw","wstat","wfreq"]
        # -------------------------------
Marco Govoni's avatar
Marco Govoni committed
27
        #
Marco Govoni's avatar
Marco Govoni committed
28
        data = {'emailId': self.emailId ,'sessionTime':str(self.maxSessionTime)} 
Marco Govoni's avatar
Marco Govoni committed
29
30
31
32
33
34
35
36
37
        #
        import requests
        import json
        #
        response = None
        try:
            output = requests.post(self.restAPIinit, data=json.dumps(data))
            response = json.loads(output.text)
        except Exception as e:
38
            print('The server is not responding.',e)
Marco Govoni's avatar
Marco Govoni committed
39
40
        if response:
            if "Error" in response:
41
                print("Server failed with the following error \n",response['Error'])
Marco Govoni's avatar
Marco Govoni committed
42
43
44
                return None
            else:
                print("Check the inbox/spam folder of your email and click on the link to activate the session")
45
                self.token = response["token"]
Marco Govoni's avatar
Marco Govoni committed
46
        else:
47
            print('The server is not responding.')
Marco Govoni's avatar
Marco Govoni committed
48
    
49
50
    def getToken(self):
        """Returns the token of the session.
Marco Govoni's avatar
Marco Govoni committed
51
52
53
54
        
        :Example:
        
        >>> from westpy import *
55
56
        >>> session = Session("email@domain.com")
        >>> token = session.getToken()
Marco Govoni's avatar
Marco Govoni committed
57
58
        
        """
59
60
        if self.token :
            return self.token
Marco Govoni's avatar
Marco Govoni committed
61
62
63
64
        else:
            raise ValueError("Cannot find output.")
    
    def stop(self):
65
        """Stops the session and clears the remote workspace. 
Marco Govoni's avatar
Marco Govoni committed
66
67
68
69
        
        :Example:
        
        >>> from westpy import *
70
71
        >>> session = Session("email@domain.com")
        >>> session.stop()
Marco Govoni's avatar
Marco Govoni committed
72
73
74
75
76
77
        
        """
        
        import requests
        import json
        #
78
        headers = {'Content-Type':'application/json; charset=utf-8','emailId':self.emailId,'token':self.token}
Marco Govoni's avatar
Marco Govoni committed
79
80
81
        try:
            response = requests.get(self.restAPIstop, headers=headers, timeout=None)
        except Exception as e:
82
            print('The server is not responding.',e)		 
Marco Govoni's avatar
Marco Govoni committed
83
        return json.loads(response.text) 
atanikan's avatar
atanikan committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

    def status(self):
        """Returns whether the session is active and time left. 
        
        :Example:
        
        >>> from westpy import *
        >>> session = Session("email@domain.com")
        >>> session.status()
        
        """
        
        import requests
        import json
        #
        headers = {'Content-Type':'application/json; charset=utf-8','emailId':self.emailId,'token':self.token}
        try:
            response = requests.get(self.restAPIstatus, headers=headers, timeout=None)
        except Exception as e:
            print('The server is not responding.',e)		 
        return json.loads(response.text) 
		
Marco Govoni's avatar
Marco Govoni committed
106
    def run(self,executable=None,inputFile=None,outputFile=None,downloadUrl=[],number_of_cores=2) :
107
        """Runs the executable on the remote server.
Marco Govoni's avatar
Marco Govoni committed
108
109
110
111
112
113
114
        
        :param executable: name of executable
        :type executable: string
        :param inputFile: name of input file
        :type inputFile: string
        :param outputFile: name of output file
        :type outputFile: string
Marco Govoni's avatar
Marco Govoni committed
115
116
        :param downloadUrl: URLs to be downloaded
        :type downloadUrl: list of string
Marco Govoni's avatar
Marco Govoni committed
117
118
119
120
121
122
        :param number_of_cores: number of cores
        :type number_of_cores: int
        
        :Example:
        
        >>> from westpy import *
123
124
125
        >>> session = Session("email@domain.com")
        >>> session.run( "pw", "pw.in", "pw.out", ["http://www.quantum-simulation.org/potentials/sg15_oncv/upf/C_ONCV_PBE-1.0.upf"] , 2 )
        >>> session.stop()
Marco Govoni's avatar
Marco Govoni committed
126
127
128
129
130
        
        """
        #
        import json
        #
131
132
133
134
        assert( number_of_cores <= self.maxNumberOfCores )
        #
        output_dict = {}
        if executable in self.allowedExecutables : 
Marco Govoni's avatar
Marco Govoni committed
135
136
137
138
139
140
           # set inputs
           if inputFile is None:
              inputFile = str(executable)+".in"
           if outputFile is None:
              outputFile = str(executable)+".out"		 
           try:
Marco Govoni's avatar
Marco Govoni committed
141
              output = self.__runExecutable(executable,inputFile,downloadUrl,number_of_cores)
Marco Govoni's avatar
Marco Govoni committed
142
143
              output_json = json.loads(output)
              if "Error" in output_json:
144
                 print("Server failed with the following error \n",output_json['Error'])
Marco Govoni's avatar
Marco Govoni committed
145
146
147
148
149
                 return None			   
              elif "JOB DONE." not in str(output_json['output']).strip():
                 print("MPI execution failed with the following error:  \n"+str(output))
                 return None
              output_data = str(output_json['output']).strip()
150
              output_dict = json.loads(output_json['output_dict'])
Marco Govoni's avatar
Marco Govoni committed
151
152
153
154
155
156
157
              # write the output file
              with open(outputFile, "w") as file :
                 file.write(str(output_data))
           except Exception as e:
              print("Session Expired! Invalid Request sent, Please recreate session and recheck your input. \n"+ e)		 
              return None          
        else:
158
           raise ValueError("Invalid executable name") 
Marco Govoni's avatar
Marco Govoni committed
159
160
161
        #
        print("Generated ",outputFile)
        return output_dict
Marco Govoni's avatar
Marco Govoni committed
162
      
Marco Govoni's avatar
Marco Govoni committed
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
    def __runExecutable(self,executable,input_file,download_urls,number_of_cores) :
        """Runs remotely the executable using a REST api.
        """
        #
        import requests
        import json
        # suck in the input file
        try:
           file_content = ""	     
           with open(input_file,'r') as f :
              for line in f :
                 file_content = file_content + line + "\\n"
        except FileNotFoundError:
           error = "Could not find "+ input_file + ". \n Generate input file "+ input_file +" and try again."	  
           print(error)
           return None
Marco Govoni's avatar
Marco Govoni committed
179
        body = {'urls':download_urls,'file':file_content,'cmd_timeout':str(self.maxWaitTime),'script_type':str(executable),'no_of_cores':str(number_of_cores)}  
Marco Govoni's avatar
Marco Govoni committed
180
181
        jsondata = json.dumps(body)
        jsondataasbytes = jsondata.encode('utf-8')   # needs to be bytes
182
        headers = {'Content-Type':'application/json; charset=utf-8','emailId':self.emailId,'token':self.token}
Marco Govoni's avatar
Marco Govoni committed
183
        response = ""
184
        print("Requested to run executable", executable, "on server", self.serverName)
Marco Govoni's avatar
Marco Govoni committed
185
186
187
188
        try:
           response = requests.post(self.restAPIrun, data = jsondataasbytes, headers=headers, timeout=None)
           return response.text
        except Exception as e:
189
           print('The server is not responding.',e)	
Marco Govoni's avatar
Marco Govoni committed
190
191
           return None
        return None