Small rewrite + Version check. NT
[sfa.git] / sfa / senslab / OARrestapi.py
1 # import modules used here -- sys is a very standard one
2 import sys
3 import httplib
4 import json
5
6 OARIP='192.168.0.109'
7
8 OARrequests_list = ["GET_version", "GET_timezone", "GET_jobs", "GET_jobs_table", "GET_jobs_details",
9 "GET_resources_full", "GET_resources"]
10
11 OARrequests_uri_list = ['/oarapi/version.json','/oarapi/timezone.json', '/oarapi/jobs.json',
12 '/oarapi/jobs/details.json', '/oarapi/resources/full.json', '/oarapi/resources.json'] 
13
14 OARrequests_get_uri_dict = { 'GET_version': '/oarapi/version.json',
15                         'GET_timezone':'/oarapi/timezone.json' ,
16                         'GET_jobs': '/oarapi/jobs.json',
17                         'GET_jobs_table': '/oarapi/jobs/table.json',
18                         'GET_jobs_details': '/oarapi/jobs/details.json',
19                         'GET_resources_full': '/oarapi/resources/full.json',
20                         'GET_resources':'/oarapi/resources.json',
21 }
22
23 POSTformat = {  #'yaml': {'content':"text/yaml", 'object':yaml}
24 'json' : {'content':"application/json",'object':json}, 
25 #'http': {'content':"applicaton/x-www-form-urlencoded",'object': html},
26 }
27
28 class OARrestapi:
29         def __init__(self):
30                 self.oarserver= {}
31                 self.oarserver['ip'] = OARIP
32                 self.oarserver['port'] = 80
33                 self.oarserver['uri'] = None
34                 self.oarserver['postformat'] = None     
35                 
36         def GETRequestToOARRestAPI(self, request ): 
37                 self.oarserver['uri'] = OARrequests_get_uri_dict[request]
38                 try :
39                         conn = httplib.HTTPConnection(self.oarserver['ip'],self.oarserver['port'])
40                         conn.request("GET",self.oarserver['uri'] )
41                         resp = ( conn.getresponse()).read()
42                         conn.close()
43                 except:
44                         raise ServerError("GET_OAR_SRVR : Could not reach OARserver")
45                 try:
46                         js = json.loads(resp)
47                         return js
48                 
49                 except ValueError:
50                         raise ServerError("Failed to parse Server Response:" + js)
51
52                 
53                 
54         def POSTRequestToOARRestAPI(self, uri,format, data): 
55                 self.oarserver['uri'] = uri
56                 if format in POSTformat:
57                         try :
58                                 conn = httplib.HTTPConnection(self.oarserver['ip'],self.oarserver['port'])
59                                 conn.putrequest("POST",self.oarserver['uri'] )
60                                 self.oarserver['postformat'] = POSTformat[format]
61                                 conn.putheader('content-type', self.oarserver['postformat']['content'])
62                                 conn.putheader('content-length', str(len(data))) 
63                                 conn.endheaders()
64                                 conn.send(data)
65                                 resp = ( conn.getresponse()).read()
66                                 conn.close()
67                 
68                         except:
69                                 raise ServerError("POST_OAR_SRVR : error")
70                                 
71                         try:
72                                 answer = self.oarserver['postformat']['object'].loads(resp)
73                                 return answer
74         
75                         except ValueError:
76                                 raise ServerError("Failed to parse Server Response:" + answer)
77                 else:
78                         print>>sys.stderr, "\r\n POSTRequestToOARRestAPI : ERROR_POST_FORMAT"
79                         
80                         
81 class OARGETParser:
82
83         #Insert a new node into the dictnode dictionary
84         def AddNodeId(self,dictnode,value):
85                 #Inserts new key. The value associated is a tuple list.
86                 node_id = int(value)
87                 dictnode[node_id] = [('node_id',node_id) ]      
88                 return node_id
89         
90         def AddNodeNetworkAddr(self,tuplelist,value):
91                 #tuplelist.append(('hostname',str(value)))
92                 tuplelist.append(('hostname',str(value)+'.demolab.fr'))
93                 tuplelist.append(('site_id',3)) 
94                 
95         def AddNodeSite(self,tuplelist,value):
96                 tuplelist.append(('site_login_base',str(value)))        
97                 
98         def AddNodeRadio(self,tuplelist,value):
99                 tuplelist.append(('radio',str(value)))  
100         
101         
102         def AddMobility(self,tuplelist,value):
103                 tuplelist.append(('mobile',int(value))) 
104                 return 0
105         
106         
107         def AddPosX(self,tuplelist,value):
108                 tuplelist.append(('posx',value))        
109         
110         
111         def AddPosY(self,tuplelist,value):
112                 tuplelist.append(('posy',value))        
113         
114         
115         
116         def ParseVersion(self) : 
117                 print self.raw_json
118                 self.version_json_dict.update(api_version=self.raw_json['oar'] ,
119                                     apilib_version=self.raw_json['apilib'],
120                                     api_timezone=self.raw_json['api_timezone'],
121                                     api_timestamp=self.raw_json['api_timestamp'],
122                                     oar_version=self.raw_json['oar'] )
123                 print self.version_json_dict['apilib_version']
124                 
125         def ParseTimezone(self) : 
126                 print " ParseTimezone" 
127                 
128         def ParseJobs(self) :
129                 self.jobs_list = []
130                 print " ParseJobs "
131                 
132         def ParseJobsTable(self) : 
133                 print "ParseJobsTable"
134                   
135         def ParseJobsDetails (self): 
136                 print "ParseJobsDetails"
137                 
138         def ParseResources(self) : 
139                 #resources are listed inside the 'items' list from the json
140                 self.raw_json = self.raw_json['items']
141                 self.ParseNodes()
142                 self.ParseSites()
143                 
144                 
145                 
146         def ParseResourcesFull(self ) :
147                 print self.raw_json[1]
148                 #resources are listed inside the 'items' list from the json
149                 if self.version_json_dict['apilib_version'] != "0.2.10" :
150                         self.raw_json = self.raw_json['items']
151                 self.ParseNodes()
152                 self.ParseSites()
153                 
154                 
155         #Parse nodes properties from OAR
156         #Put them into a dictionary with key = node id and value is a dictionary 
157         #of the node properties and properties'values.
158         def ParseNodes(self):  
159                 node_id = None
160                 for dictline in self.raw_json:
161                         for k in dictline.keys():
162                                 if k in self.resources_fulljson_dict:
163                                         # dictionary is empty and/or a new node has to be inserted 
164                                         if node_id is None :
165                                                 node_id = self.resources_fulljson_dict[k](self,self.node_dictlist, dictline[k]) 
166                                         else:
167                                                 ret = self.resources_fulljson_dict[k](self,self.node_dictlist[node_id], dictline[k])
168                                                 #If last property has been inserted in the property tuple list, reset node_id 
169                                                 if ret == 0:
170                                                         #Turn the property tuple list (=dict value) into a dictionary
171                                                         self.node_dictlist[node_id] = dict(self.node_dictlist[node_id])
172                                                         node_id = None
173                                         
174                                 else:
175                                         pass
176
177         #Retourne liste de dictionnaires contenant attributs des sites  
178         def ParseSites(self):
179                 nodes_per_site = {}
180                 # Create a list of nodes per  site_id
181                 for node_id in self.node_dictlist.keys():
182                         node  = self.node_dictlist[node_id]
183                         if node['site_id'] not in nodes_per_site.keys():
184                                 nodes_per_site[node['site_id']] = []
185                                 nodes_per_site[node['site_id']].append(node['node_id'])
186                         else:
187                                 if node['node_id'] not in nodes_per_site[node['site_id']]:
188                                         nodes_per_site[node['site_id']].append(node['node_id'])
189                 #Create a site dictionary with key is site_login_base (name of the site)
190                 # and value is a dictionary of properties, including the list of the node_ids
191                 for node_id in self.node_dictlist.keys():
192                         node  = self.node_dictlist[node_id]
193                         if node['site_id'] not in self.site_dict.keys():
194                                 self.site_dict[node['site_login_base']] = [('site_id',node['site_id']),\
195                                                                          ('login_base', node['site_login_base']),\
196                                                                         ('node_ids',nodes_per_site[node['site_id']]),\
197                                                                         ('latitude',"48.83726"),\
198                                                                         ('longitude',"- 2.10336")]
199                                 self.site_dict[node['site_login_base']] = dict(self.site_dict[node['site_login_base']])
200                 print self.site_dict
201                 
202                 
203         def GetNodesFromOARParse(self):
204                 print>>sys.stderr, " \r\n =========GetNodesFromOARParse: node_dictlist %s "%(self.node_dictlist)
205                 return self.node_dictlist
206
207         def GetSitesFromOARParse(self):
208                 return self.site_dict
209         
210         def GetJobsFromOARParse(self):
211                 return self.jobs_list   
212
213         OARrequests_uri_dict = { 
214                 'GET_version': {'uri':'/oarapi/version.json', 'parse_func': ParseVersion},
215                 'GET_timezone':{'uri':'/oarapi/timezone.json' ,'parse_func': ParseTimezone },
216                 'GET_jobs': {'uri':'/oarapi/jobs.json','parse_func': ParseJobs},
217                 'GET_jobs_table': {'uri':'/oarapi/jobs/table.json','parse_func': ParseJobsTable},
218                 'GET_jobs_details': {'uri':'/oarapi/jobs/details.json','parse_func': ParseJobsDetails},
219                 'GET_resources_full': {'uri':'/oarapi/resources/full.json','parse_func': ParseResourcesFull},
220                 'GET_resources':{'uri':'/oarapi/resources.json' ,'parse_func': ParseResources},
221                 }
222         resources_fulljson_dict= {
223                 'resource_id' : AddNodeId,
224                 'network_address' : AddNodeNetworkAddr,
225                 'site': AddNodeSite, 
226                 'radio': AddNodeRadio,
227                 'mobile': AddMobility,
228                 'posx': AddPosX,
229                 'posy': AddPosY,
230                 }
231
232         
233         def __init__(self, srv ):
234                 self.version_json_dict= { 'api_version' : None , 'apilib_version' :None,  'api_timezone': None, 'api_timestamp': None, 'oar_version': None ,}
235                 self.timezone_json_dict = { 'timezone': None, 'api_timestamp': None, }
236                 self.jobs_json_dict = { 'total' : None, 'links' : [] , 'offset':None , 'items' : [] , }
237                 self.jobs_table_json_dict = self.jobs_json_dict
238                 self.jobs_details_json_dict = self.jobs_json_dict               
239                 self.server = srv
240                 self.node_dictlist = {}
241                 self.site_dict = {}
242                 self.SendRequest("GET_version")
243
244         def SendRequest(self,request):
245                 if request in OARrequests_get_uri_dict:
246                         self.raw_json = self.server.GETRequestToOARRestAPI(request)
247                         self.OARrequests_uri_dict[request]['parse_func'](self)
248                 else:
249                         print>>sys.stderr, "\r\n OARGetParse __init__ : ERROR_REQUEST " ,request
250                 
251 class OARapi:
252
253         def __init__(self):
254                 self.server = OARrestapi()
255                 self.parser = OARGETParser(self.server)
256
257         def GetNodes(self,node_filter= None, return_fields=None):
258                 print>>sys.stderr, " \r\n GetNodes node_filter %s return_fields %s" %(node_filter,return_fields) 
259                 self.parser.SendRequest("GET_resources_full")
260                 node_dict = self.parser.GetNodesFromOARParse()
261                 return_node_list = []
262                 print>>sys.stderr, " \r\n GetNodes   node_dict %s" %(node_dict) 
263                 if not (node_filter or return_fields):
264                         return_node_list = node_dict.values()
265                         return return_node_list
266
267                 return_node_list= parse_filter(node_dict.values(),node_filter ,'node', return_fields)
268                 return return_node_list
269
270                 
271         def GetSites(self, site_filter= None, return_fields=None):
272                 print>>sys.stderr, " \r\n GetSites" 
273                 self.parser.SendRequest("GET_resources_full")   
274                 site_dict = self.parser.GetSitesFromOARParse()
275                 return_site_list = []
276                 print>>sys.stderr, " \r\n  GetSites sites_dict %s" %(site_dict) 
277                 if not (site_filter or return_fields):
278                         return_site_list = site_dict.values()
279                         return return_site_list
280                 
281                 return_site_list = parse_filter(site_dict.values(),site_filter ,'site', return_fields)
282                 return return_site_list
283         
284                         
285         def GetJobs(self):
286                 print>>sys.stderr, " \r\n GetJobs" 
287                 self.parser.SendRequest("GET_jobs")     
288                 return self.parser.GetJobsFromOARParse()
289