Statistics
| Branch: | Revision:

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)