root / python / pithos.py @ 31:697cc04f1ab9
History | View | Annotate | Download (5 kB)
1 |
#!/usr/bin/python
|
---|---|
2 |
|
3 |
# Bindings for GRNET's "Pithos" storage system's REST API
|
4 |
# Author: Apollon Oikonomopoulos (apollon@noc.grnet.gr)
|
5 |
# Distributed under the terms of GNU General Public License v3
|
6 |
|
7 |
import urllib |
8 |
import base64 |
9 |
from httplib2 import Http |
10 |
from hmac import HMAC |
11 |
from hashlib import sha1 |
12 |
from time import strftime |
13 |
from simplejson import JSONEncoder, JSONDecoder |
14 |
|
15 |
class AuthenticationError(Exception): |
16 |
def __init__(self, value): |
17 |
self.parameter = value
|
18 |
def __str__(self): |
19 |
return repr(self.parameter) |
20 |
|
21 |
|
22 |
class PithosObject: |
23 |
def __init__(self, name, uri, pithos): |
24 |
self.name = name
|
25 |
self.uri = uri
|
26 |
self.pithos = pithos
|
27 |
|
28 |
class PithosGroup(PithosObject): |
29 |
def get_members(self): |
30 |
data = self.pithos.get_resource(self.uri) |
31 |
members = self.pithos.jsondecoder.decode(data)
|
32 |
return map(lambda x: x.replace(self.uri + '/', '', 1), members) |
33 |
|
34 |
def stat(self): |
35 |
return len(self.read()) |
36 |
|
37 |
def read(self): |
38 |
return "\n".join(self.getMembers()) |
39 |
|
40 |
def __repr__(self): |
41 |
return "<PithosGroup: '" + self.name + "'>" |
42 |
|
43 |
class PithosFile(PithosObject): |
44 |
def __init__(self, name, uri, pithos): |
45 |
self.position = 0 |
46 |
PithosObject.__init__(self, name, uri, pithos)
|
47 |
|
48 |
def __repr__(self): |
49 |
return "<PithosFile: '" + self.name + "'>" |
50 |
|
51 |
def get_metadata(self): |
52 |
metadata = self.pithos.get_resource(self.uri, "HEAD") |
53 |
metadata = self.pithos.jsondecoder.decode(metadata)
|
54 |
return metadata
|
55 |
|
56 |
def read(self, length=None): |
57 |
headers = {} |
58 |
if length:
|
59 |
headers['Range'] = 'bytes %d-%d' % (self.position, self.position + length - 1) |
60 |
elif self.position > 0: |
61 |
headers['Range'] = 'bytes %d-' % self.position |
62 |
|
63 |
buf = self.pithos.get_resource(self.uri, headers=headers) |
64 |
self.position += len(buf) |
65 |
return buf
|
66 |
|
67 |
def seek(self,position): |
68 |
self.position = position
|
69 |
|
70 |
class PithosDir(PithosObject): |
71 |
def __repr__(self): |
72 |
return "<PithosDir: '" + self.name + "'>" |
73 |
|
74 |
def stat(self): |
75 |
metadata = self.pithos.get_resource(self.uri) |
76 |
metadata = self.pithos.jsondecoder.decode(metadata)
|
77 |
return metadata
|
78 |
|
79 |
def list(self): |
80 |
metadata = self.pithos.get_resource(self.uri) |
81 |
metadata = self.pithos.jsondecoder.decode(metadata)
|
82 |
print metadata
|
83 |
files = [] |
84 |
folders = [] |
85 |
for file in metadata['files']: |
86 |
files.append(PithosFile(file['name'], file['uri'], self.pithos)) |
87 |
for dir in metadata['folders']: |
88 |
folders.append(PithosDir(dir['name'], dir['uri'], self.pithos)) |
89 |
return files + folders
|
90 |
|
91 |
|
92 |
class Pithos: |
93 |
def __init__(self, username, token, url="pithos.grnet.gr"): |
94 |
self.username = username
|
95 |
self.token = base64.decodestring(token)
|
96 |
self.url = url
|
97 |
self.connection = Http()
|
98 |
self.jsonencoder = JSONEncoder()
|
99 |
self.jsondecoder = JSONDecoder()
|
100 |
|
101 |
self._get_root_elements()
|
102 |
print self.accountdata['username'] |
103 |
print self.accountdata['name'] |
104 |
print self.accountdata['quota']['bytesRemaining'] |
105 |
|
106 |
def _get_root_elements(self): |
107 |
reply = self.get_resource('/') |
108 |
self.accountdata = self.jsondecoder.decode(reply) |
109 |
|
110 |
def get_resource(self, resource, method="GET", headers={}): |
111 |
if resource.startswith('http://'): |
112 |
resource = resource.replace('http://pithos.grnet.gr/pithos/rest/' + self.username, '', 1) |
113 |
else:
|
114 |
resource = urllib.quote(resource) |
115 |
|
116 |
print 'Getting ' + resource |
117 |
current_time = strftime("%a, %d %b %Y %H:%M:%S %z")
|
118 |
digest = HMAC(self.token, digestmod=sha1)
|
119 |
digest.update(method + current_time + '/' + self.username + resource) |
120 |
headers['Authorization'] = self.username + " " + \ |
121 |
base64.encodestring(digest.digest()).strip() |
122 |
headers['user-agent'] = 'zythos' |
123 |
headers['X-GSS-Date'] = current_time
|
124 |
response, content = self.connection.request(
|
125 |
"http://pithos.grnet.gr/pithos/rest/" + self.username + resource, |
126 |
method, headers=headers |
127 |
) |
128 |
print response
|
129 |
if method == "HEAD": |
130 |
return response['x-gss-metadata'] |
131 |
return content
|
132 |
|
133 |
def get_groups(self): |
134 |
groups = self.get_resource(self.accountdata['groups']) |
135 |
groups = self.jsondecoder.decode(groups)
|
136 |
return map(lambda x: PithosGroup(x['name'], x['uri'], self), groups) |
137 |
|
138 |
def get_group(self,name): |
139 |
return PithosGroup(name, self.accountdata['groups'] + '/' + name, self) |
140 |
|
141 |
def get_files(self): |
142 |
listing = self.get_resource(self.accountdata['files']) |
143 |
listing = self.jsondecoder.decode(listing)
|
144 |
return map(lambda x: PithosFile(x['name'], x['uri'], self), listing['files']) + \ |
145 |
map(lambda x: PithosDir(x['name'], x['uri'], self), listing['folders']) |
146 |
|
147 |
def get_file(self,path): |
148 |
return PithosFile(path.split('/')[-1], |
149 |
self.accountdata['files'] + '/' + urllib.quote(path), self) |