PythonOlogClientLibrary
OlogClient.py
1 '''
2 Copyright (c) 2010 Brookhaven National Laboratory
3 All rights reserved. Use is subject to license terms and conditions.
4 
5 Created on Jan 10, 2013
6 
7 @author: shroffk
8 '''
9 import requests
10 from json import JSONEncoder, JSONDecoder
11 from OlogDataTypes import LogEntry, Logbook, Tag, Property, Attachment
12 from _conf import _conf
13 import json
14 from requests import auth
15 import logging
16 from urllib import urlencode
17 from collections import OrderedDict
18 import tempfile
19 
20 class OlogClient(object):
21  '''
22  classdocs
23  '''
24  __jsonheader = {'content-type':'application/json', 'accept':'application/json'}
25  __logsResource = '/resources/logs'
26  __propertiesResource = '/resources/properties'
27  __tagsResource = '/resources/tags'
28  __logbooksResource = '/resources/logbooks'
29  __attachmentResource = '/resources/attachments'
30 
31  def __init__(self, url=None, username=None, password=None):
32  '''
33  Constructor
34  '''
35  try:
36  requests_log = logging.getLogger("requests")
37  requests_log.setLevel(logging.DEBUG)
38  self.__url = self.__getDefaultConfig('url', url)
39  self.__username = self.__getDefaultConfig('username', username)
40  self.__password = self.__getDefaultConfig('password', password)
41  if username and password:
42  self.__auth = auth.HTTPBasicAuth(username, password)
43  else:
44  self.__auth = None
45  requests.get(self.__url + self.__tagsResource, verify=False, headers=self.__jsonheader).raise_for_status()
46  except:
47  raise
48 
49  def __getDefaultConfig(self, arg, value):
50  '''
51  If Value is None, this will try to find the value in one of the configuration files
52  '''
53  if value == None and _conf.has_option('DEFAULT', arg):
54  return _conf.get('DEFAULT', arg)
55  else:
56  return value
57 
58  def log(self, logEntry):
59  '''
60  create a logEntry
61  '''
62  resp = requests.post(self.__url + self.__logsResource,
63  data=LogEntryEncoder().encode(logEntry),
64  verify=False,
65  headers=self.__jsonheader,
66  auth=self.__auth)
67  resp.raise_for_status()
68  id = LogEntryDecoder().dictToLogEntry(resp.json()[0]).getId()
69  '''Attachments'''
70  for attachment in logEntry.getAttachments():
71  resp = requests.post(self.__url + self.__attachmentResource +'/'+ str(id),
72  verify=False,
73  auth=self.__auth,
74  files={'file':attachment.getFile()}
75  )
76  resp.raise_for_status()
77 
78 
79 
80  def createLogbook(self, logbook):
81  '''
82  Create Logbook
83  '''
84  requests.put(self.__url + self.__logbooksResource + '/' + logbook.getName(),
85  data=LogbookEncoder().encode(logbook),
86  verify=False,
87  headers=self.__jsonheader,
88  auth=self.__auth).raise_for_status()
89 
90 
91  def createTag(self, tag):
92  '''
93  Create Tag
94  '''
95  url = self.__url + self.__tagsResource + '/' + tag.getName()
96  requests.put(url,
97  data=TagEncoder().encode(tag),
98  verify=False,
99  headers=self.__jsonheader,
100  auth=self.__auth).raise_for_status()
101 
102  def createProperty(self, property):
103  '''
104  Create Property
105  '''
106  url = self.__url + self.__propertiesResource + '/' + property.getName()
107  p = PropertyEncoder().encode(property)
108  requests.put(url,
109  data=PropertyEncoder().encode(property),
110  verify=False,
111  headers=self.__jsonheader,
112  auth=self.__auth).raise_for_status()
113 
114  def find(self, **kwds):
115  '''
116  Search for logEntries based on one or many search criteria
117  >> find(search='*Timing*')
118  find logentries with the text Timing in the description
119 
120  >> find(tag='magnets')
121  find log entries with the a tag named 'magnets'
122 
123  >> find(logbook='controls')
124  find log entries in the logbook named 'controls'
125 
126  >> find(property='context')
127  find log entires with property named 'context'
128 
129  >> find(start=str(time.time() - 3600)
130  find the log entries made in the last hour
131  >> find(start=123243434, end=123244434)
132  find all the log entries made between the epoc times 123243434 and 123244434
133 
134  Searching using multiple criteria
135  >>find(logbook='contorls', tag='magnets')
136  find all the log entries in logbook 'controls' AND with tag named 'magnets'
137  '''
138  #search = '*' + text + '*'
139  query_string = self.__url + self.__logsResource + '?' + urlencode(OrderedDict(kwds))
140  resp = requests.get(query_string,
141  verify=False,
142  headers=self.__jsonheader,
143  auth=self.__auth
144  )
145  resp.raise_for_status()
146  logs = []
147  for jsonLogEntry in resp.json():
148  logs.append(LogEntryDecoder().dictToLogEntry(jsonLogEntry))
149  return logs
150 
151  def listAttachments(self, logEntryId):
152  '''
153  Search for attachments on logentry _id_
154  '''
155  resp = requests.get(self.__url+self.__attachmentResource+'/'+str(logEntryId),
156  verify=False,
157  headers=self.__jsonheader)
158  resp.raise_for_status()
159  attachments = []
160  for jsonAttachment in resp.json().pop('attachment'):
161  fileName = jsonAttachment.pop('fileName')
162  f = requests.get(self.__url+
163  self.__attachmentResource+'/'+
164  str(logEntryId)+'/'+
165  fileName,
166  verify=False)
167  testFile = tempfile.NamedTemporaryFile(delete=False)
168  testFile.name = fileName
169  testFile.write(f.content)
170  attachments.append(Attachment(file=testFile))
171  return attachments
172 
173  def listTags(self):
174  '''
175  List all tags.
176  '''
177  resp = requests.get(self.__url + self.__tagsResource,
178  verify=False,
179  headers=self.__jsonheader,
180  auth=self.__auth)
181  resp.raise_for_status()
182  tags = []
183  for jsonTag in resp.json().pop('tag'):
184  tags.append(TagDecoder().dictToTag(jsonTag))
185  return tags
186 
187  def listLogbooks(self):
188  '''
189  List all logbooks
190  '''
191  resp = requests.get(self.__url + self.__logbooksResource,
192  verify=False,
193  headers=self.__jsonheader,
194  auth=self.__auth)
195  resp.raise_for_status()
196  logbooks = []
197  for jsonLogbook in resp.json().pop('logbook'):
198  logbooks.append(LogbookDecoder().dictToLogbook(jsonLogbook))
199  return logbooks
200 
201  def listProperties(self):
202  '''
203  List all Properties and their attributes
204  '''
205  resp = requests.get(self.__url + self.__propertiesResource,
206  verify=False,
207  headers=self.__jsonheader,
208  auth=self.__auth)
209  resp.raise_for_status()
210  properties = []
211  for jsonProperty in resp.json().pop('property'):
212  properties.append(PropertyDecoder().dictToProperty(jsonProperty))
213  return properties
214 
215 
216  def delete(self, **kwds):
217  '''
218  Method to delete a logEntry, logbook, property, tag
219  delete(logEntryId = int)
220  >>> delete(logEntryId=1234)
221 
222  delete(logbookName = String)
223  >>> delete(logbookName = 'logbookName')
224 
225  delete(tagName = String)
226  >>> delete(tagName = 'myTag')
227  # tagName = tag name of the tag to be deleted (it will be removed from all logEntries)
228 
229  delete(propertyName = String)
230  >>> delete(propertyName = 'position')
231  # propertyName = property name of property to be deleted (it will be removed from all logEntries)
232  '''
233  if len(kwds) == 1:
234  self.__handleSingleDeleteParameter(**kwds)
235  else:
236  raise Exception, 'incorrect usage: Delete a single Logbook/tag/property'
237 
238 
239  def __handleSingleDeleteParameter(self, **kwds):
240  if 'logbookName' in kwds:
241  requests.delete(self.__url + self.__logbooksResource + '/' + kwds['logbookName'].strip(),
242  verify=False,
243  headers=self.__jsonheader,
244  auth=self.__auth).raise_for_status()
245  pass
246  elif 'tagName' in kwds:
247  requests.delete(self.__url + self.__tagsResource + '/' + kwds['tagName'].strip(),
248  verify=False,
249  headers=self.__jsonheader,
250  auth=self.__auth).raise_for_status()
251  pass
252  elif 'propertyName' in kwds:
253  requests.delete(self.__url + self.__propertiesResource + '/' + kwds['propertyName'].strip(),
254  data=PropertyEncoder().encode(Property(kwds['propertyName'].strip(), attributes={})),
255  verify=False,
256  headers=self.__jsonheader,
257  auth=self.__auth).raise_for_status()
258  pass
259  elif 'logEntryId' in kwds:
260  requests.delete(self.__url + self.__logsResource + '/' + str(kwds['logEntryId']).strip(),
261  verify=False,
262  headers=self.__jsonheader,
263  auth=self.__auth).raise_for_status()
264  pass
265  else:
266  raise Exception, ' unkown key, use logEntryId, logbookName, tagName or propertyName'
267 
268 class PropertyEncoder(JSONEncoder):
269 
270  def default(self, obj):
271  if isinstance(obj, Property):
272  test = {}
273  for key in obj.getAttributes():
274  test[str(key)] = str(obj.getAttributeValue(key))
275  prop = OrderedDict()
276  prop["name"] = obj.getName()
277  prop["attributes"] = test
278  return prop
279  return json.JSONEncoder.default(self, obj)
280 
281 class PropertyDecoder(JSONDecoder):
282 
283  def __init__(self):
284  json.JSONDecoder.__init__(self, object_hook=self.dictToProperty)
285 
286  def dictToProperty(self, d):
287  if d:
288  return Property(name=d.pop('name'), attributes=d.pop('attributes'))
289 
290 class LogbookEncoder(JSONEncoder):
291 
292  def default(self, obj):
293  if isinstance(obj, Logbook):
294  return {"name":obj.getName(), "owner":obj.getOwner()}
295  return json.JSONEncoder.default(self, obj)
296 
297 class LogbookDecoder(JSONDecoder):
298 
299  def __init__(self):
300  json.JSONDecoder.__init__(self, object_hook=self.dictToLogbook)
301 
302  def dictToLogbook(self, d):
303  if d:
304  return Logbook(name=d.pop('name'), owner=d.pop('owner'))
305  else:
306  return None
307 
308 class TagEncoder(JSONEncoder):
309 
310  def default(self, obj):
311  if isinstance(obj, Tag):
312  return {"state": obj.getState(), "name": obj.getName()}
313  return json.JSONEncoder.default(self, obj)
314 
315 class TagDecoder(JSONDecoder):
316 
317  def __init__(self):
318  json.JSONDecoder.__init__(self, object_hook=self.dictToTag)
319 
320  def dictToTag(self, d):
321  if d:
322  return Tag(name=d.pop('name'), state=d.pop('state'))
323  else:
324  return None
325 
326 class LogEntryEncoder(JSONEncoder):
327 
328  def default(self, obj):
329  if isinstance(obj, LogEntry):
330  logbooks = []
331  for logbook in obj.getLogbooks():
332  logbooks.append(LogbookEncoder().default(logbook))
333  tags = []
334  for tag in obj.getTags():
335  tags.append(TagEncoder().default(tag))
336  properties = []
337  for property in obj.getProperties():
338  properties.append(PropertyEncoder().default(property))
339  return [{"description":obj.getText(),
340  "owner":obj.getOwner(),
341  "level":"Info",
342  "logbooks":logbooks,
343  "tags":tags,
344  "properties":properties}]
345  return json.JSONEncoder.default(self, obj)
346 
347 class LogEntryDecoder(JSONDecoder):
348 
349  def __init__(self):
350  json.JSONDecoder.__init__(self, object_hook=self.dictToLogEntry)
351 
352  def dictToLogEntry(self, d):
353  if d:
354  return LogEntry(text=d.pop('description'),
355  owner=d.pop('owner'),
356  logbooks=[LogbookDecoder().dictToLogbook(logbook) for logbook in d.pop('logbooks')],
357  tags=[TagDecoder().dictToTag(tag) for tag in d.pop('tags')],
358  properties=[PropertyDecoder().dictToProperty(property) for property in d.pop('properties')],
359  id=d.pop('id'),
360  createTime=d.pop('createdDate'),
361  modifyTime=d.pop('modifiedDate'))
362  else:
363  return None