169.1.1
by Natalia
- Added proper copyright notices and coding headers. |
1 |
# -*- coding: utf-8 -*-
|
2 |
#
|
|
164.1.1
by Facundo Batista
Use simple authentication against the server. |
3 |
# Copyright 2009-2015 Canonical Ltd.
|
169.1.1
by Natalia
- Added proper copyright notices and coding headers. |
4 |
# Copyright 2015-2018 Chicharreros (https://launchpad.net/~chicharreros)
|
22.1.1
by Rodney Dawes
Add the AGPLv3 text to COPYING and in all the source header comments |
5 |
#
|
23.1.2
by Lucio Torre
added cancelled message |
6 |
# This program is free software: you can redistribute it and/or modify it
|
22.1.1
by Rodney Dawes
Add the AGPLv3 text to COPYING and in all the source header comments |
7 |
# under the terms of the GNU Affero General Public License version 3,
|
8 |
# as published by the Free Software Foundation.
|
|
9 |
#
|
|
23.1.2
by Lucio Torre
added cancelled message |
10 |
# This program is distributed in the hope that it will be useful, but
|
11 |
# WITHOUT ANY WARRANTY; without even the implied warranties of
|
|
12 |
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
|
22.1.1
by Rodney Dawes
Add the AGPLv3 text to COPYING and in all the source header comments |
13 |
# PURPOSE. See the GNU Affero General Public License for more details.
|
14 |
#
|
|
15 |
# You should have received a copy of the GNU Affero General Public License
|
|
16 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
144.1.1
by Rodney Dawes
Exception for use of OpenSSL |
17 |
#
|
18 |
# In addition, as a special exception, the copyright holders give
|
|
19 |
# permission to link the code of portions of this program with the
|
|
20 |
# OpenSSL library under certain conditions as described in each
|
|
21 |
# individual source file, and distribute linked combinations
|
|
22 |
# including the two.
|
|
23 |
# You must obey the GNU General Public License in all respects
|
|
24 |
# for all of the code used other than OpenSSL. If you modify
|
|
25 |
# file(s) with this exception, you may extend this exception to your
|
|
26 |
# version of the file(s), but you are not obligated to do so. If you
|
|
27 |
# do not wish to do so, delete this exception statement from your
|
|
28 |
# version. If you delete this exception statement from all source
|
|
29 |
# files in the program, then also delete it here.
|
|
168.1.1
by Facundo Batista
Protocol infrastructure to support public files change and listing. |
30 |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
31 |
"""The storage protocol client."""
|
32 |
||
33 |
import logging |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
34 |
import uuid |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
35 |
|
65.1.4
by guillermo.gonzalez at canonical
remove debug logs |
36 |
from functools import partial |
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
37 |
from itertools import chain |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
38 |
|
39 |
from twisted.internet.protocol import ClientFactory |
|
40 |
from twisted.internet import reactor, defer |
|
41 |
from twisted.python import log |
|
42 |
||
78.1.17
by natalia.bidart at canonical
Avoiding more name clashing. |
43 |
from ubuntuone.storageprotocol import ( |
137.2.7
by Alejandro J. Cura
refactor webclient out of timestamp checker |
44 |
delta, |
168.1.2
by Facundo Batista
Import order. |
45 |
protocol_pb2, |
168.1.1
by Facundo Batista
Protocol infrastructure to support public files change and listing. |
46 |
public_file_info, |
137.2.7
by Alejandro J. Cura
refactor webclient out of timestamp checker |
47 |
request, |
48 |
sharersp, |
|
49 |
volumes, |
|
50 |
)
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
51 |
|
65.1.4
by guillermo.gonzalez at canonical
remove debug logs |
52 |
log_debug = partial(log.msg, loglevel=logging.DEBUG) |
53 |
||
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
54 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
55 |
class StorageClient(request.RequestHandler): |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
56 |
"""A Basic Storage Protocol client."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
57 |
|
58 |
# we are a client, we do odd requests
|
|
59 |
REQUEST_ID_START = 1 |
|
60 |
||
61 |
def __init__(self): |
|
62 |
"""Create the client. done by the factory."""
|
|
63 |
request.RequestHandler.__init__(self) |
|
64 |
self.root_id = None |
|
65 |
self.root_id_defers = [] |
|
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
66 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
67 |
self._node_state_callback = None |
68 |
self._share_change_callback = None |
|
92.1.1
by John OBrien
Split share_delete from change and add some tests |
69 |
self._share_delete_callback = None |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
70 |
self._share_answer_callback = None |
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
71 |
self._free_space_callback = None |
59.1.3
by tim.cole at canonical
initialize _account_info_callback |
72 |
self._account_info_callback = None |
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
73 |
self._volume_created_callback = None |
74 |
self._volume_deleted_callback = None |
|
101.3.1
by facundo at com
New notification: Volume New Generation! |
75 |
self._volume_new_generation_callback = None |
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
76 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
77 |
self.line_mode = True |
132.1.1
by Facundo Batista
Change the way the producer decides how much to send. |
78 |
self.max_payload_size = request.MAX_PAYLOAD_SIZE |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
79 |
|
80 |
def protocol_version(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
81 |
"""Ask for the protocol version
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
82 |
|
83 |
will return a deferred that will get called with
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
84 |
the request object when completed.
|
85 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
86 |
"""
|
87 |
p = ProtocolVersion(self) |
|
88 |
p.start() |
|
89 |
return p.deferred |
|
90 |
||
91 |
def dataReceived(self, data): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
92 |
"""Extend dataReceived.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
93 |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
94 |
First reads the protocol hello line then switch back to len+data.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
95 |
|
96 |
"""
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
97 |
if self.line_mode: |
98 |
# first read the hello line, then back to binary.
|
|
99 |
try: |
|
100 |
pos = data.index("\r\n") |
|
101 |
except ValueError: |
|
102 |
return
|
|
103 |
self.line_mode = False |
|
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
104 |
data = data[pos + 2:] |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
105 |
|
106 |
request.RequestHandler.dataReceived(self, data) |
|
107 |
||
135.1.2
by guillermo.gonzalez at canonical
add metadata optional argument to dummy_authenticate and oauth_authenticate |
108 |
def dummy_authenticate(self, credentials, metadata=None): |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
109 |
"""Authenticate to a server using the 'dummy auth' provider.
|
110 |
||
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
111 |
Return a deferred that will get called with the request
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
112 |
object when completed.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
113 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
114 |
"""
|
135.1.2
by guillermo.gonzalez at canonical
add metadata optional argument to dummy_authenticate and oauth_authenticate |
115 |
p = Authenticate(self, {'dummy_token': credentials}, |
116 |
metadata=metadata) |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
117 |
p.start() |
118 |
return p.deferred |
|
119 |
||
164.1.1
by Facundo Batista
Use simple authentication against the server. |
120 |
def simple_authenticate(self, username, password, metadata=None): |
121 |
"""Authenticate to a server using the username and password."""
|
|
122 |
auth_parameters = { |
|
123 |
'username': username, |
|
124 |
'password': password, |
|
125 |
}
|
|
135.1.2
by guillermo.gonzalez at canonical
add metadata optional argument to dummy_authenticate and oauth_authenticate |
126 |
p = Authenticate(self, auth_parameters, metadata=metadata) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
127 |
p.start() |
164.1.1
by Facundo Batista
Use simple authentication against the server. |
128 |
return p.deferred |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
129 |
|
130 |
def handle_ROOT(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
131 |
"""Handle incoming ROOT message.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
132 |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
133 |
Will notify if someone is waiting for this information.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
134 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
135 |
"""
|
136 |
self.root_id = message.root.node |
|
137 |
if self.root_id_defers: |
|
138 |
for d in self.root_id_defers: |
|
139 |
d.callback(self.root_id) |
|
140 |
self.root_id_defers = [] |
|
141 |
||
142 |
def handle_NODE_STATE(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
143 |
"""Handle incoming NODE_STATE."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
144 |
self.notify_node_state(message.node_state) |
145 |
||
146 |
def handle_NOTIFY_SHARE(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
147 |
"""Handle incoming NOTIFY_SHARE."""
|
92.1.1
by John OBrien
Split share_delete from change and add some tests |
148 |
self.notify_share_change(message.notify_share) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
149 |
|
150 |
def handle_SHARE_DELETED(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
151 |
"""Handle incoming SHARE_DELETED."""
|
92.1.1
by John OBrien
Split share_delete from change and add some tests |
152 |
self.notify_share_deleted(message.share_deleted) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
153 |
|
154 |
def handle_SHARE_ACCEPTED(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
155 |
"""Handle incoming SHARE_ACCEPTED."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
156 |
self.notify_share_answer(message.share_accepted) |
157 |
||
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
158 |
def handle_VOLUME_CREATED(self, message): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
159 |
"""Handle incoming VOLUME_CREATED"""
|
79.1.1
by natalia.bidart at canonical
Fixing parameter passing for handle_VOLUME_CREATED so protocol doesn't leak. |
160 |
assert message.type == protocol_pb2.Message.VOLUME_CREATED |
161 |
msg = message.volume_created |
|
162 |
vol = None |
|
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
163 |
if self._volume_created_callback is not None: |
79.1.1
by natalia.bidart at canonical
Fixing parameter passing for handle_VOLUME_CREATED so protocol doesn't leak. |
164 |
if msg.type == protocol_pb2.Volumes.ROOT: |
165 |
vol = volumes.RootVolume.from_msg(msg.root) |
|
166 |
elif msg.type == protocol_pb2.Volumes.SHARE: |
|
167 |
vol = volumes.ShareVolume.from_msg(msg.share) |
|
168 |
elif msg.type == protocol_pb2.Volumes.UDF: |
|
169 |
vol = volumes.UDFVolume.from_msg(msg.udf) |
|
170 |
else: |
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
171 |
msg = "Message.volume_created's type is not valid: %s" % \ |
172 |
message.volume_created.type |
|
173 |
raise TypeError(msg) |
|
79.1.1
by natalia.bidart at canonical
Fixing parameter passing for handle_VOLUME_CREATED so protocol doesn't leak. |
174 |
|
175 |
self._volume_created_callback(vol) |
|
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
176 |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
177 |
def handle_VOLUME_DELETED(self, message): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
178 |
"""Handle incoming VOLUME_DELETED."""
|
79.1.2
by natalia.bidart at canonical
Fixing handle_VOLUME_DELETED so protocol is not leaked to client. |
179 |
assert message.type == protocol_pb2.Message.VOLUME_DELETED |
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
180 |
if self._volume_deleted_callback is not None: |
79.1.2
by natalia.bidart at canonical
Fixing handle_VOLUME_DELETED so protocol is not leaked to client. |
181 |
vol_id = uuid.UUID(message.volume_deleted.volume) |
182 |
self._volume_deleted_callback(vol_id) |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
183 |
|
101.3.1
by facundo at com
New notification: Volume New Generation! |
184 |
def handle_VOLUME_NEW_GENERATION(self, message): |
185 |
"""Handle incoming VOLUME_NEW_GENERATION."""
|
|
186 |
assert message.type == protocol_pb2.Message.VOLUME_NEW_GENERATION |
|
187 |
if self._volume_new_generation_callback is not None: |
|
188 |
volume = message.volume_new_generation.volume |
|
189 |
if volume != request.ROOT: |
|
190 |
volume = uuid.UUID(volume) |
|
191 |
generation = message.volume_new_generation.generation |
|
192 |
self._volume_new_generation_callback(volume, generation) |
|
193 |
||
7.1.1
by facundo at com
Changes to allow cancel upload. |
194 |
def handle_BEGIN_CONTENT(self, message): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
195 |
"""Accept and discard a misplaced BEGIN_CONTENT.
|
7.1.1
by facundo at com
Changes to allow cancel upload. |
196 |
|
7.1.2
by facundo at com
Typo |
197 |
It can happen that while the server receives a PUT_CONTENT request
|
7.1.1
by facundo at com
Changes to allow cancel upload. |
198 |
and that it tells us to BEGIN_CONTENT, we cancelled the request,
|
199 |
received the OK, and this side's request is gone, so receive this
|
|
200 |
message here.
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
201 |
|
7.1.1
by facundo at com
Changes to allow cancel upload. |
202 |
"""
|
203 |
||
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
204 |
def handle_FREE_SPACE_INFO(self, message): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
205 |
"""Handle unsolicited FREE_SPACE_INFO."""
|
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
206 |
self.notify_free_space(message.free_space_info) |
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
207 |
|
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
208 |
def handle_ACCOUNT_INFO(self, message): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
209 |
"""Handle unsolicited ACCOUNT_INFO."""
|
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
210 |
self.notify_account_info(message.account_info) |
211 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
212 |
def get_root(self): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
213 |
"""Get the root id through a deferred."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
214 |
if self.root_id is not None: |
215 |
return defer.succeed(self.root_id) |
|
216 |
else: |
|
217 |
d = defer.Deferred() |
|
218 |
self.root_id_defers.append(d) |
|
219 |
return d |
|
220 |
||
221 |
def make_dir(self, share, parent, name): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
222 |
"""Create a directory named name on the node parent
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
223 |
|
224 |
the new node id will be on request.new_dir_id.
|
|
225 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
226 |
"""
|
227 |
p = MakeDir(self, share, parent, name) |
|
228 |
p.start() |
|
229 |
return p.deferred |
|
230 |
||
231 |
def make_file(self, share, parent, name): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
232 |
"""Create a file named name on the node parent
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
233 |
|
234 |
the new node id will be on request.new_file_id.
|
|
235 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
236 |
"""
|
237 |
p = MakeFile(self, share, parent, name) |
|
238 |
p.start() |
|
239 |
return p.deferred |
|
240 |
||
241 |
def move(self, share, node, new_parent, new_name): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
242 |
"""Move a node."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
243 |
p = Move(self, share, node, new_parent, new_name) |
244 |
p.start() |
|
245 |
return p.deferred |
|
246 |
||
247 |
def unlink(self, share, node): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
248 |
"""Unlink a node."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
249 |
p = Unlink(self, share, node) |
250 |
p.start() |
|
251 |
return p.deferred |
|
252 |
||
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
253 |
def get_content(self, share, node, a_hash, offset=0, |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
254 |
callback=None, node_attr_callback=None): |
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
255 |
"""Get the content of node with 'a_hash'.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
256 |
|
257 |
the content will be on request.content
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
258 |
or callback will be called for every piece that arrives.
|
259 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
260 |
"""
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
261 |
req = self.get_content_request(share, node, a_hash, offset, |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
262 |
callback, node_attr_callback) |
263 |
return req.deferred |
|
264 |
||
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
265 |
def get_content_request(self, share, node, a_hash, offset=0, |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
266 |
callback=None, node_attr_callback=None): |
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
267 |
"""Get the content of node with 'a_hash', return the request.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
268 |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
269 |
The content will be on request.content, or callback will be
|
270 |
called for every piece that arrives.
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
271 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
272 |
"""
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
273 |
p = GetContent(self, share, node, a_hash, offset, |
274 |
callback, node_attr_callback) |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
275 |
p.start() |
276 |
return p |
|
277 |
||
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
278 |
def put_content(self, share, node, previous_hash, new_hash, |
123.2.3
by Guillermo Gonzalez
add upload_id kwarg to put_content methods |
279 |
crc32, size, deflated_size, fd, upload_id=None, |
124.1.2
by Facundo Batista
Magic hash! |
280 |
upload_id_cb=None, magic_hash=None): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
281 |
"""Put the content of fd into file node."""
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
282 |
req = self.put_content_request(share, node, previous_hash, new_hash, |
123.2.2
by Guillermo Gonzalez
add upload_id_cb kwarg to Client.put_content* methods |
283 |
crc32, size, deflated_size, fd, |
123.2.3
by Guillermo Gonzalez
add upload_id kwarg to put_content methods |
284 |
upload_id=upload_id, |
124.1.2
by Facundo Batista
Magic hash! |
285 |
upload_id_cb=upload_id_cb, |
286 |
magic_hash=magic_hash) |
|
7.1.1
by facundo at com
Changes to allow cancel upload. |
287 |
return req.deferred |
288 |
||
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
289 |
def put_content_request(self, share, node, previous_hash, new_hash, |
123.2.3
by Guillermo Gonzalez
add upload_id kwarg to put_content methods |
290 |
crc32, size, deflated_size, fd, upload_id=None, |
124.1.2
by Facundo Batista
Magic hash! |
291 |
upload_id_cb=None, magic_hash=None): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
292 |
"""Put the content of fd into file node, return the request."""
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
293 |
p = PutContent(self, share, node, previous_hash, new_hash, |
123.2.2
by Guillermo Gonzalez
add upload_id_cb kwarg to Client.put_content* methods |
294 |
crc32, size, deflated_size, fd, |
123.2.3
by Guillermo Gonzalez
add upload_id kwarg to put_content methods |
295 |
upload_id=upload_id, |
124.1.2
by Facundo Batista
Magic hash! |
296 |
upload_id_cb=upload_id_cb, |
297 |
magic_hash=magic_hash) |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
298 |
p.start() |
7.1.1
by facundo at com
Changes to allow cancel upload. |
299 |
return p |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
300 |
|
301 |
def query(self, items): |
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
302 |
"""Get the current hash for items if changed.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
303 |
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
304 |
'items' is a list of (node, hash) tuples.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
305 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
306 |
"""
|
307 |
r = MultiQuery(self, items) |
|
308 |
r.start() |
|
309 |
return r.deferred |
|
310 |
||
111.1.1
by lucio.torre at gmail
get delta from scratch client support |
311 |
def get_delta(self, share_id, from_generation=None, callback=None, |
312 |
from_scratch=False): |
|
101.1.1
by lucio.torre at gmail
added delta messages |
313 |
"""Get a delta for a share_id
|
314 |
||
315 |
'share_id' is the share_id which we want to query.
|
|
316 |
'from_generation' is the generation which we are at.
|
|
317 |
'callback' can be specified to get deltas as they get instead of
|
|
318 |
getting them all at once at the end.
|
|
111.1.1
by lucio.torre at gmail
get delta from scratch client support |
319 |
'from_scratch' at True means list all live nodes.
|
101.1.1
by lucio.torre at gmail
added delta messages |
320 |
|
321 |
"""
|
|
111.1.1
by lucio.torre at gmail
get delta from scratch client support |
322 |
r = GetDelta(self, share_id, from_generation, callback, from_scratch) |
101.1.1
by lucio.torre at gmail
added delta messages |
323 |
r.start() |
324 |
return r.deferred |
|
325 |
||
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
326 |
def get_free_space(self, share_id): |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
327 |
"""Get quota info for the given share (or the user's own space)."""
|
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
328 |
r = FreeSpaceInquiry(self, share_id) |
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
329 |
r.start() |
330 |
return r.deferred |
|
331 |
||
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
332 |
def get_account_info(self): |
333 |
"""Get account information (like purchased space etc.)."""
|
|
334 |
r = AccountInquiry(self) |
|
335 |
r.start() |
|
336 |
return r.deferred |
|
337 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
338 |
def set_node_state_callback(self, callback): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
339 |
"""Define the function to be called when a node_state message arrives
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
340 |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
341 |
The function will be called with the message as argument.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
342 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
343 |
"""
|
344 |
self._node_state_callback = callback |
|
345 |
||
346 |
def notify_node_state(self, node_state): |
|
347 |
"""Call the current node state callback, if any, with the share, node,
|
|
348 |
and hash given in the message.
|
|
349 |
||
350 |
@param: node_state - a (raw) NodeState message
|
|
351 |
||
352 |
"""
|
|
353 |
if self._node_state_callback: |
|
354 |
self._node_state_callback(node_state.share, node_state.node, |
|
355 |
node_state.hash) |
|
356 |
||
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
357 |
def set_free_space_callback(self, callback): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
358 |
"""Set the quota notification callback.
|
359 |
||
360 |
It will be called with the share id and free bytes.
|
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
361 |
|
362 |
"""
|
|
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
363 |
self._free_space_callback = callback |
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
364 |
|
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
365 |
def notify_free_space(self, free_space_info): |
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
366 |
"""Call the current quota info callback, if any, with the share
|
367 |
and available bytes.
|
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
368 |
|
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
369 |
@param: free_space_info - a (raw) FreeSpaceInfo message
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
370 |
|
371 |
"""
|
|
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
372 |
if self._free_space_callback: |
373 |
self._free_space_callback(free_space_info.share_id, |
|
374 |
free_space_info.free_bytes) |
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
375 |
|
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
376 |
def set_account_info_callback(self, callback): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
377 |
"""Set the account info notification callback; the callback
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
378 |
will be passed a raw AccountInfo structure when it is called.
|
379 |
||
380 |
"""
|
|
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
381 |
self._account_info_callback = callback |
382 |
||
383 |
def notify_account_info(self, account_info): |
|
384 |
"""Call the current account info callback, if any."""
|
|
385 |
if self._account_info_callback: |
|
386 |
self._account_info_callback(account_info) |
|
387 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
388 |
def set_share_change_callback(self, callback): |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
389 |
"""Set the callback when something changed regarding a share."""
|
92.1.1
by John OBrien
Split share_delete from change and add some tests |
390 |
if callable(callback): |
391 |
self._share_change_callback = callback |
|
392 |
else: |
|
393 |
raise TypeError('callback for share_change must be callable') |
|
394 |
||
395 |
def notify_share_change(self, notify_share): |
|
396 |
"""Call the current changed share callback, if any, with the
|
|
397 |
notify info.
|
|
398 |
||
399 |
@param notify_share: - a NotifyShare message
|
|
400 |
||
401 |
"""
|
|
402 |
if self._share_change_callback: |
|
403 |
info = sharersp.NotifyShareHolder.load_from_msg(notify_share) |
|
404 |
self._share_change_callback(info) |
|
405 |
||
406 |
def set_share_delete_callback(self, callback): |
|
407 |
"""Set the callback when something changed regarding a share."""
|
|
408 |
if callable(callback): |
|
409 |
self._share_delete_callback = callback |
|
410 |
else: |
|
411 |
raise TypeError('callback for share_delete must be callable') |
|
412 |
||
413 |
def notify_share_deleted(self, share_deleted): |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
414 |
"""Call the current changed share callback, if any, with the
|
415 |
notify info.
|
|
416 |
||
417 |
@param msg: - a (raw) NotifyShare message
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
418 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
419 |
"""
|
92.1.1
by John OBrien
Split share_delete from change and add some tests |
420 |
if self._share_delete_callback: |
421 |
self._share_delete_callback(uuid.UUID(share_deleted.share_id)) |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
422 |
|
423 |
def set_share_answer_callback(self, callback): |
|
424 |
"""Define the function to be called when a share answer is received."""
|
|
92.1.1
by John OBrien
Split share_delete from change and add some tests |
425 |
if callable(callback): |
426 |
self._share_answer_callback = callback |
|
427 |
else: |
|
428 |
raise TypeError('callback for share_answer must be callable') |
|
429 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
430 |
def notify_share_answer(self, msg): |
431 |
"""Call the current share answer callback, if any, with the info.
|
|
432 |
||
433 |
@param msg: - a (raw) ShareAccepted message
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
434 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
435 |
"""
|
436 |
if self._share_answer_callback: |
|
437 |
if msg.answer == protocol_pb2.ShareAccepted.YES: |
|
438 |
answer = "Yes" |
|
439 |
elif msg.answer == protocol_pb2.ShareAccepted.NO: |
|
440 |
answer = "No" |
|
441 |
else: |
|
442 |
raise ValueError("Not supported ShareAccepted answer") |
|
443 |
self._share_answer_callback(uuid.UUID(msg.share_id), answer) |
|
444 |
||
78.1.7
by natalia.bidart at canonical
Final details to callbacks setters. |
445 |
def set_volume_created_callback(self, callback): |
446 |
"""Set the callback for volume creation notification."""
|
|
447 |
if callable(callback): |
|
448 |
self._volume_created_callback = callback |
|
449 |
else: |
|
450 |
raise TypeError('callback for volume_created must be callable') |
|
451 |
||
452 |
def set_volume_deleted_callback(self, callback): |
|
453 |
"""Set the callback for volume deletion notification."""
|
|
454 |
if callable(callback): |
|
455 |
self._volume_deleted_callback = callback |
|
456 |
else: |
|
457 |
raise TypeError('callback for volume_deleted must be callable') |
|
458 |
||
101.3.1
by facundo at com
New notification: Volume New Generation! |
459 |
def set_volume_new_generation_callback(self, callback): |
460 |
"""Set the callback for volume new generation notification."""
|
|
461 |
if callable(callback): |
|
462 |
self._volume_new_generation_callback = callback |
|
463 |
else: |
|
464 |
raise TypeError('callback for volume_new_gen must be callable') |
|
465 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
466 |
def create_share(self, node, share_to, name, access_level): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
467 |
"""Create a share to other user.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
468 |
|
469 |
node: which node to share.
|
|
470 |
share_to: the id of the receiving user.
|
|
471 |
name: the name of the share
|
|
472 |
access_level: the permissions on the share
|
|
473 |
||
474 |
There's no need to indicate where the node lives, as it only can be
|
|
475 |
in own root (there's no re-sharing).
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
476 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
477 |
"""
|
478 |
r = CreateShare(self, node, share_to, name, access_level) |
|
479 |
r.start() |
|
480 |
return r.deferred |
|
481 |
||
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
482 |
def delete_share(self, share_id): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
483 |
"""Delete a share we have offered.
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
484 |
|
485 |
@param share_id: the id of the share to delete
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
486 |
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
487 |
"""
|
488 |
r = DeleteShare(self, share_id) |
|
489 |
r.start() |
|
490 |
return r.deferred |
|
491 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
492 |
def accept_share(self, share_id, answer): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
493 |
"""Accept (or not) a share from other user.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
494 |
|
495 |
share_id: the share id
|
|
496 |
answer: if it was accepted ("Yes") or not ("No")
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
497 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
498 |
"""
|
499 |
r = AcceptShare(self, share_id, answer) |
|
500 |
r.start() |
|
501 |
return r.deferred |
|
502 |
||
503 |
def list_shares(self): |
|
504 |
"""List all the shares the user is involved.
|
|
505 |
||
506 |
This includes the shares the user created, and those that were
|
|
507 |
shared to her.
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
508 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
509 |
"""
|
510 |
p = ListShares(self) |
|
511 |
p.start() |
|
512 |
return p.deferred |
|
513 |
||
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
514 |
def create_udf(self, path, name): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
515 |
"""Create a User Defined Folder.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
516 |
|
517 |
@param path: the path in disk to the UDF.
|
|
518 |
@param name: the name of the UDF.
|
|
519 |
||
520 |
"""
|
|
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
521 |
p = CreateUDF(self, path, name) |
522 |
p.start() |
|
523 |
return p.deferred |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
524 |
|
525 |
def list_volumes(self): |
|
526 |
"""List all the volumes the user has.
|
|
527 |
||
528 |
This includes the volumes:
|
|
529 |
- all the user's UDFs.
|
|
530 |
- all the shares the user has accepted.
|
|
531 |
- the root-root volume.
|
|
532 |
||
533 |
"""
|
|
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
534 |
p = ListVolumes(self) |
535 |
p.start() |
|
536 |
return p.deferred |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
537 |
|
168.1.1
by Facundo Batista
Protocol infrastructure to support public files change and listing. |
538 |
def change_public_access(self, share_id, node_id, is_public): |
539 |
"""Change the public access of a file."""
|
|
540 |
p = ChangePublicAccess(self, share_id, node_id, is_public) |
|
541 |
p.start() |
|
542 |
return p.deferred |
|
543 |
||
544 |
def list_public_files(self): |
|
545 |
"""List the public files."""
|
|
546 |
p = ListPublicFiles(self) |
|
547 |
p.start() |
|
548 |
return p.deferred |
|
549 |
||
78.1.3
by natalia.bidart at canonical
Implementing DELETE_VOLUME. |
550 |
def delete_volume(self, volume_id): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
551 |
"""Delete 'volume' on the server, removing the associated tree.
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
552 |
|
553 |
@param volume: the id of the volume to delete.
|
|
554 |
||
555 |
"""
|
|
78.1.3
by natalia.bidart at canonical
Implementing DELETE_VOLUME. |
556 |
p = DeleteVolume(self, volume_id) |
557 |
p.start() |
|
558 |
return p.deferred |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
559 |
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
560 |
def query_caps(self, caps): |
561 |
"""Query the server to discover its capabilitis.
|
|
562 |
||
563 |
The server should answer if it supports or not all the given
|
|
564 |
caps.
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
565 |
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
566 |
"""
|
51.1.2
by facundo at com
Forgot to join both classes. |
567 |
r = QuerySetCaps(self, caps) |
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
568 |
r.start() |
569 |
return r.deferred |
|
570 |
||
571 |
def set_caps(self, caps): |
|
572 |
"""Set the server to this capabilities."""
|
|
51.1.2
by facundo at com
Forgot to join both classes. |
573 |
r = QuerySetCaps(self, caps, set_mode=True) |
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
574 |
r.start() |
575 |
return r.deferred |
|
576 |
||
577 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
578 |
class GetContent(request.Request): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
579 |
"""A Request to get the content of a node id.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
580 |
|
581 |
@ivar data: the content of the node (available upon success)
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
582 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
583 |
"""
|
584 |
||
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
585 |
__slots__ = ('share', 'node_id', 'hash', 'offset', 'callback', |
134.1.2
by Guillermo Gonzalez
add data attribute to GetContent request |
586 |
'node_attr_callback', 'parts', 'data') |
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
587 |
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
588 |
def __init__(self, protocol, share, node_id, a_hash, |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
589 |
offset=0, callback=None, node_attr_callback=None): |
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
590 |
"""Request the content of node with 'a_hash'.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
591 |
|
592 |
@param protocol: the request handler
|
|
593 |
@param share: the share node or root
|
|
594 |
@param node_id: the node id of the node we want to read
|
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
595 |
@param a_hash: the hash of the content of the version we have
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
596 |
@param offset: offset for reading
|
597 |
@param callback: function to call when data arrives
|
|
598 |
||
599 |
"""
|
|
600 |
request.Request.__init__(self, protocol) |
|
601 |
self.share = share |
|
602 |
self.node_id = node_id |
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
603 |
self.hash = a_hash |
62.1.1
by john.lenton at canonical
this makes downloads resumable. Now to fix the tests... |
604 |
self.offset = offset |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
605 |
self.callback = callback |
606 |
self.node_attr_callback = node_attr_callback |
|
607 |
self.parts = [] |
|
608 |
||
609 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
610 |
"""Send GET_CONTENT."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
611 |
message = protocol_pb2.Message() |
612 |
message.type = protocol_pb2.Message.GET_CONTENT |
|
613 |
message.get_content.node = str(self.node_id) |
|
614 |
message.get_content.hash = str(self.hash) |
|
615 |
message.get_content.share = self.share |
|
616 |
message.get_content.offset = self.offset |
|
617 |
self.sendMessage(message) |
|
618 |
||
619 |
def processMessage(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
620 |
"""Process messages."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
621 |
if message.type == protocol_pb2.Message.NODE_ATTR: |
622 |
if self.node_attr_callback is not None: |
|
623 |
self.node_attr_callback( |
|
624 |
deflated_size=message.node_attr.deflated_size, |
|
625 |
size=message.node_attr.size, |
|
626 |
hash=message.node_attr.hash, |
|
627 |
crc32=message.node_attr.crc32) |
|
628 |
elif message.type == protocol_pb2.Message.BYTES: |
|
629 |
if self.cancelled: |
|
630 |
# don't care about more bytes if already cancelled
|
|
631 |
return
|
|
632 |
if self.callback is not None: |
|
633 |
self.callback(message.bytes.bytes) |
|
634 |
else: |
|
635 |
self.parts.append(message.bytes.bytes) |
|
636 |
elif message.type == protocol_pb2.Message.EOF: |
|
637 |
if self.cancelled: |
|
18.3.1
by Lucio Torre
pending? |
638 |
# eof means that the cancel request arrived late. this is the
|
639 |
# end.
|
|
640 |
self.done() |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
641 |
return
|
642 |
if self.callback is None: |
|
643 |
self.data = "".join(self.parts) |
|
644 |
self.done() |
|
645 |
elif message.type == protocol_pb2.Message.OK: |
|
646 |
self.done() |
|
23.1.1
by Lucio Torre
tmp |
647 |
elif message.type == protocol_pb2.Message.CANCELLED: |
23.1.6
by Lucio Torre
fixed + feature |
648 |
self.error(request.RequestCancelledError("CANCELLED")) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
649 |
else: |
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
650 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
651 |
|
15.2.1
by facundo at com
Now the state is handled by Request. |
652 |
def _cancel(self): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
653 |
"""Cancel the current download."""
|
15.2.1
by facundo at com
Now the state is handled by Request. |
654 |
message = protocol_pb2.Message() |
655 |
message.type = protocol_pb2.Message.CANCEL_REQUEST |
|
656 |
self.sendMessage(message) |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
657 |
|
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
658 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
659 |
class ListShares(request.Request): |
660 |
"""List all the shares the user is involved.
|
|
661 |
||
662 |
This includes the shares the user created, and those that were
|
|
663 |
shared to her.
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
664 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
665 |
"""
|
666 |
||
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
667 |
__slots__ = ('shares',) |
668 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
669 |
def _start(self): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
670 |
"""Send the LIST_SHARES message to the server."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
671 |
message = protocol_pb2.Message() |
672 |
message.type = protocol_pb2.Message.LIST_SHARES |
|
673 |
self.sendMessage(message) |
|
674 |
self.shares = [] |
|
675 |
||
676 |
def processMessage(self, message): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
677 |
"""Process the answer from the server."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
678 |
if message.type == protocol_pb2.Message.SHARES_INFO: |
679 |
share = sharersp.ShareResponse.load_from_msg(message.shares) |
|
680 |
self.shares.append(share) |
|
681 |
elif message.type == protocol_pb2.Message.SHARES_END: |
|
682 |
self.done() |
|
683 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
684 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
685 |
|
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
686 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
687 |
class CreateShare(request.Request): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
688 |
"""Create a share."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
689 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
690 |
__slots__ = ('node', 'share_to', 'name', 'access_level', 'share_id') |
691 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
692 |
# these are the valid access levels and their translation to the
|
693 |
# protocol message
|
|
694 |
_valid_access_levels = { |
|
695 |
"View": protocol_pb2.CreateShare.VIEW, |
|
696 |
"Modify": protocol_pb2.CreateShare.MODIFY, |
|
697 |
}
|
|
698 |
||
699 |
def __init__(self, protocol, node_id, share_to, name, access_level): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
700 |
"""Create a share.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
701 |
|
702 |
@param node_id: which node will be root to share.
|
|
703 |
@param share_to: the id of the receiving user.
|
|
704 |
@param name: the name of the share
|
|
705 |
@param access_level: the permissions on the share
|
|
706 |
||
707 |
"""
|
|
708 |
request.Request.__init__(self, protocol) |
|
709 |
self.node = node_id |
|
710 |
self.share_to = share_to |
|
711 |
self.name = name |
|
712 |
self.access_level = access_level |
|
18.2.3
by guillo.gonzo at gmail
fix lint warning |
713 |
self.share_id = None |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
714 |
|
715 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
716 |
"""Send the CREATE_SHARE message to the server."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
717 |
message = protocol_pb2.Message() |
718 |
message.type = protocol_pb2.Message.CREATE_SHARE |
|
719 |
message.create_share.node = self.node |
|
720 |
message.create_share.share_to = self.share_to |
|
721 |
message.create_share.name = self.name |
|
722 |
||
723 |
# we make this testing here and not in __init__ because it should
|
|
724 |
# be done when creating the message (to support that the access_level
|
|
725 |
# is changed between instantiating and message creation)
|
|
726 |
try: |
|
727 |
message_access_level = self._valid_access_levels[self.access_level] |
|
728 |
except KeyError: |
|
729 |
raise ValueError("Invalid access level! (%r)" % self.access_level) |
|
730 |
message.create_share.access_level = message_access_level |
|
731 |
||
732 |
self.sendMessage(message) |
|
733 |
||
734 |
def processMessage(self, message): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
735 |
"""Process the answer from the server."""
|
18.2.1
by guillo.gonzo at gmail
added ShareCreated message and changed client.create_share to send the share_id |
736 |
if message.type == protocol_pb2.Message.SHARE_CREATED: |
737 |
self.share_id = message.share_created.share_id |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
738 |
self.done() |
18.2.2
by guillo.gonzo at gmail
keep the protocol backward compatible |
739 |
elif message.type == protocol_pb2.Message.OK: |
120.1.1
by Rodney Dawes
Update pylintrc and {disable,enable}-msg comments to work with new pylint |
740 |
# this is for PROTOCOL_VERSION=1 backward compatibility
|
18.2.2
by guillo.gonzo at gmail
keep the protocol backward compatible |
741 |
self.done() |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
742 |
else: |
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
743 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
744 |
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
745 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
746 |
class AcceptShare(request.Request): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
747 |
"""Accept a share (or not)."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
748 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
749 |
__slots__ = ('share_id', 'answer') |
750 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
751 |
# these are the valid answers and their translation to the
|
752 |
# protocol message
|
|
753 |
_valid_answer = { |
|
754 |
"Yes": protocol_pb2.ShareAccepted.YES, |
|
755 |
"No": protocol_pb2.ShareAccepted.NO, |
|
756 |
}
|
|
757 |
||
758 |
def __init__(self, protocol, share_id, answer): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
759 |
"""Accept (or not) a share from other user.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
760 |
|
761 |
@param share_id: the share id
|
|
762 |
@param answer: if it was accepted ("Yes") or not ("No")
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
763 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
764 |
"""
|
765 |
request.Request.__init__(self, protocol) |
|
766 |
self.share_id = share_id |
|
767 |
self.answer = answer |
|
768 |
||
769 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
770 |
"""Send the SHARE_ACCEPTED message to the server."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
771 |
message = protocol_pb2.Message() |
772 |
message.type = protocol_pb2.Message.SHARE_ACCEPTED |
|
773 |
message.share_accepted.share_id = str(self.share_id) |
|
774 |
||
775 |
# we make this testing here and not in __init__ because it should
|
|
776 |
# be done when creating the message (to support that the answer
|
|
777 |
# is changed between instantiating and message creation)
|
|
778 |
try: |
|
779 |
message.share_accepted.answer = self._valid_answer[self.answer] |
|
780 |
except KeyError: |
|
781 |
raise ValueError("Invalid answer! (%r)" % self.answer) |
|
782 |
||
783 |
self.sendMessage(message) |
|
784 |
||
785 |
def processMessage(self, message): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
786 |
"""Process the answer from the server."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
787 |
if message.type == protocol_pb2.Message.OK: |
788 |
self.done() |
|
789 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
790 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
791 |
|
792 |
||
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
793 |
class DeleteShare(request.Request): |
78.1.3
by natalia.bidart at canonical
Implementing DELETE_VOLUME. |
794 |
"""Delete a share."""
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
795 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
796 |
__slots__ = ('share_id',) |
797 |
||
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
798 |
def __init__(self, protocol, share_id): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
799 |
"""Delete a share we had offered to someone else.
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
800 |
|
801 |
@param share_id: the share id
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
802 |
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
803 |
"""
|
804 |
request.Request.__init__(self, protocol) |
|
805 |
self.share_id = share_id |
|
806 |
||
807 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
808 |
"""Send the DELETE_SHARE message to the server."""
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
809 |
message = protocol_pb2.Message() |
810 |
message.type = protocol_pb2.Message.DELETE_SHARE |
|
811 |
message.delete_share.share_id = str(self.share_id) |
|
812 |
||
813 |
self.sendMessage(message) |
|
814 |
||
815 |
def processMessage(self, message): |
|
32.2.2
by tim.cole at canonical
docstrings |
816 |
"""Process the answer from the server."""
|
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
817 |
if message.type == protocol_pb2.Message.OK: |
818 |
self.done() |
|
819 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
820 |
self._default_process_message(message) |
32.2.1
by tim.cole at canonical
add DELETE_SHARE message type |
821 |
|
822 |
||
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
823 |
class CreateUDF(request.Request): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
824 |
"""Create a UDF."""
|
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
825 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
826 |
__slots__ = ('path', 'name', 'volume_id', 'node_id') |
827 |
||
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
828 |
def __init__(self, protocol, path, name): |
78.1.19
by natalia.bidart at canonical
Fixing docstring for UDFs (they are not shares!). |
829 |
"""Create a UDF.
|
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
830 |
|
831 |
@param path: which node will be root to be UDF.
|
|
78.1.19
by natalia.bidart at canonical
Fixing docstring for UDFs (they are not shares!). |
832 |
@param name: the name of the UDF
|
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
833 |
|
834 |
"""
|
|
835 |
request.Request.__init__(self, protocol) |
|
78.1.15
by natalia.bidart at canonical
paths and names are always utf8 strings. |
836 |
self.path = path |
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
837 |
self.name = name |
838 |
self.volume_id = None |
|
78.1.12
by natalia.bidart at canonical
CreateUDF stores now volume_id and node_id. |
839 |
self.node_id = None |
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
840 |
|
841 |
def _start(self): |
|
842 |
"""Send the CREATE_UDF message to the server."""
|
|
843 |
message = protocol_pb2.Message() |
|
844 |
message.type = protocol_pb2.Message.CREATE_UDF |
|
845 |
message.create_udf.path = self.path |
|
846 |
message.create_udf.name = self.name |
|
847 |
self.sendMessage(message) |
|
848 |
||
849 |
def processMessage(self, message): |
|
850 |
"""Process the answer from the server."""
|
|
155.1.1
by Rodney Dawes
Ignore some new PEP8 errors for now and update code to deal with others. |
851 |
if message.type == protocol_pb2.Message.VOLUME_CREATED and \ |
852 |
message.volume_created.type == protocol_pb2.Volumes.UDF: |
|
78.1.12
by natalia.bidart at canonical
CreateUDF stores now volume_id and node_id. |
853 |
self.volume_id = message.volume_created.udf.volume |
854 |
self.node_id = message.volume_created.udf.node |
|
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
855 |
self.done() |
856 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
857 |
self._default_process_message(message) |
78.1.2
by natalia.bidart at canonical
Adding implementation for CREATE_UDF |
858 |
|
859 |
||
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
860 |
class ListVolumes(request.Request): |
861 |
"""List all the volumes the user has.
|
|
862 |
||
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
863 |
Including:
|
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
864 |
- the UDFs the user created.
|
78.1.19
by natalia.bidart at canonical
Fixing docstring for UDFs (they are not shares!). |
865 |
- the shares the user has accepted.
|
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
866 |
- the user's root-root.
|
867 |
||
868 |
"""
|
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
869 |
__slots__ = ('volumes',) |
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
870 |
|
871 |
def __init__(self, protocol): |
|
872 |
"""List volumes."""
|
|
873 |
request.Request.__init__(self, protocol) |
|
874 |
self.volumes = [] |
|
875 |
||
876 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
877 |
"""Send the LIST_VOLUMES message to the server."""
|
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
878 |
self.volumes = [] |
879 |
message = protocol_pb2.Message() |
|
880 |
message.type = protocol_pb2.Message.LIST_VOLUMES |
|
881 |
self.sendMessage(message) |
|
882 |
||
883 |
def processMessage(self, message): |
|
884 |
"""Process the answer from the server."""
|
|
885 |
if message.type == protocol_pb2.Message.VOLUMES_INFO: |
|
78.1.17
by natalia.bidart at canonical
Avoiding more name clashing. |
886 |
if message.list_volumes.type == protocol_pb2.Volumes.SHARE: |
887 |
vol = volumes.ShareVolume.from_msg(message.list_volumes.share) |
|
888 |
self.volumes.append(vol) |
|
889 |
elif message.list_volumes.type == protocol_pb2.Volumes.UDF: |
|
890 |
vol = volumes.UDFVolume.from_msg(message.list_volumes.udf) |
|
891 |
self.volumes.append(vol) |
|
892 |
elif message.list_volumes.type == protocol_pb2.Volumes.ROOT: |
|
893 |
vol = volumes.RootVolume.from_msg(message.list_volumes.root) |
|
894 |
self.volumes.append(vol) |
|
78.1.15
by natalia.bidart at canonical
paths and names are always utf8 strings. |
895 |
else: |
896 |
self.error(request.StorageRequestError(self, message)) |
|
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
897 |
elif message.type == protocol_pb2.Message.VOLUMES_END: |
898 |
self.done() |
|
899 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
900 |
self._default_process_message(message) |
78.1.4
by natalia.bidart at canonical
Implementing LIST_VOLUMES. Adding missing docstrings. |
901 |
|
902 |
||
78.1.3
by natalia.bidart at canonical
Implementing DELETE_VOLUME. |
903 |
class DeleteVolume(request.Request): |
904 |
"""Delete a volume."""
|
|
905 |
||
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
906 |
__slots__ = ('volume_id',) |
907 |
||
78.1.3
by natalia.bidart at canonical
Implementing DELETE_VOLUME. |
908 |
def __init__(self, protocol, volume_id): |
909 |
"""Delete a volume.
|
|
910 |
||
911 |
@param volume_id: the volume id
|
|
912 |
||
913 |
"""
|
|
914 |
request.Request.__init__(self, protocol) |
|
78.1.13
by natalia.bidart at canonical
Adding Root volume. |
915 |
self.volume_id = str(volume_id) |
78.1.3
by natalia.bidart at canonical
Implementing DELETE_VOLUME. |
916 |
|
917 |
def _start(self): |
|
918 |
"""Send the DELETE_VOLUME message to the server."""
|
|
919 |
message = protocol_pb2.Message() |
|
920 |
message.type = protocol_pb2.Message.DELETE_VOLUME |
|
921 |
message.delete_volume.volume = self.volume_id |
|
922 |
||
923 |
self.sendMessage(message) |
|
924 |
||
925 |
def processMessage(self, message): |
|
926 |
"""Process the answer from the server."""
|
|
927 |
if message.type == protocol_pb2.Message.OK: |
|
928 |
self.done() |
|
929 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
930 |
self._default_process_message(message) |
78.1.3
by natalia.bidart at canonical
Implementing DELETE_VOLUME. |
931 |
|
932 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
933 |
class Unlink(request.Request): |
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
934 |
"""Unlink a node.
|
935 |
||
936 |
@ivar new_generation: the generation that the volume is at now
|
|
937 |
"""
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
938 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
939 |
__slots__ = ('share', 'node', 'new_generation') |
940 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
941 |
def __init__(self, protocol, share, node_id): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
942 |
"""Request that node_id be unlinked
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
943 |
|
944 |
@param protocol: the request handler
|
|
945 |
@param share: the share node or root
|
|
946 |
@param node_id: the node id of the node we want to unlink
|
|
947 |
||
948 |
"""
|
|
949 |
request.Request.__init__(self, protocol) |
|
950 |
self.share = share |
|
951 |
self.node = node_id |
|
105.1.1
by facundo at com
Fixed attributes, and how setup.py uses lint |
952 |
self.new_generation = None |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
953 |
|
954 |
def _start(self): |
|
955 |
message = protocol_pb2.Message() |
|
956 |
message.type = protocol_pb2.Message.UNLINK |
|
957 |
message.unlink.share = self.share |
|
958 |
message.unlink.node = self.node |
|
959 |
||
960 |
self.sendMessage(message) |
|
961 |
||
962 |
def processMessage(self, message): |
|
963 |
if message.type == protocol_pb2.Message.OK: |
|
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
964 |
self.new_generation = message.new_generation |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
965 |
self.done() |
966 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
967 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
968 |
|
969 |
||
168.1.1
by Facundo Batista
Protocol infrastructure to support public files change and listing. |
970 |
class ChangePublicAccess(request.Request): |
971 |
"""Change the public access of a file."""
|
|
972 |
||
973 |
__slots__ = ('share_id', 'node_id', 'is_public', 'public_url') |
|
974 |
||
975 |
def __init__(self, protocol, share_id, node_id, is_public): |
|
976 |
request.Request.__init__(self, protocol) |
|
977 |
self.public_url = None |
|
978 |
||
979 |
self.share_id = str(share_id) |
|
980 |
self.node_id = str(node_id) |
|
981 |
self.is_public = is_public |
|
982 |
||
983 |
def _start(self): |
|
984 |
message = protocol_pb2.Message() |
|
985 |
message.type = protocol_pb2.Message.CHANGE_PUBLIC_ACCESS |
|
986 |
message.change_public_access.share = self.share_id |
|
987 |
message.change_public_access.node = self.node_id |
|
988 |
message.change_public_access.is_public = self.is_public |
|
989 |
self.sendMessage(message) |
|
990 |
||
991 |
def processMessage(self, message): |
|
992 |
if message.type == protocol_pb2.Message.OK: |
|
993 |
self.public_url = message.public_url |
|
994 |
self.done() |
|
995 |
else: |
|
996 |
self._default_process_message(message) |
|
997 |
||
998 |
||
999 |
class ListPublicFiles(request.Request): |
|
1000 |
"""List all the public files for an user."""
|
|
1001 |
||
1002 |
__slots__ = ('public_files',) |
|
1003 |
||
1004 |
def __init__(self, protocol): |
|
1005 |
"""List volumes."""
|
|
1006 |
request.Request.__init__(self, protocol) |
|
1007 |
self.public_files = [] |
|
1008 |
||
1009 |
def _start(self): |
|
1010 |
"""Send the LIST_PUBLIC_FILES message to the server."""
|
|
1011 |
message = protocol_pb2.Message() |
|
1012 |
message.type = protocol_pb2.Message.LIST_PUBLIC_FILES |
|
1013 |
self.sendMessage(message) |
|
1014 |
||
1015 |
def processMessage(self, message): |
|
1016 |
"""Process the answer from the server."""
|
|
1017 |
if message.type == protocol_pb2.Message.PUBLIC_FILE_INFO: |
|
1018 |
info = public_file_info.PublicFileInfo.from_message(message) |
|
1019 |
self.public_files.append(info) |
|
1020 |
elif message.type == protocol_pb2.Message.PUBLIC_FILE_INFO_END: |
|
1021 |
self.done() |
|
1022 |
else: |
|
1023 |
self._default_process_message(message) |
|
1024 |
||
1025 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1026 |
class Move(request.Request): |
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1027 |
"""Move a node.
|
1028 |
||
1029 |
@ivar new_generation: the generation that the volume is at now
|
|
1030 |
"""
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1031 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1032 |
__slots__ = ('share', 'node_id', 'new_parent_id', 'new_name', |
1033 |
'new_generation') |
|
1034 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1035 |
def __init__(self, protocol, share, node_id, new_parent_id, new_name): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1036 |
"""Create the move request
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1037 |
|
1038 |
@param protocol: the request handler
|
|
1039 |
@param share: the share node or root
|
|
1040 |
@param node_id: the node id of the node we want to move
|
|
1041 |
@param new_parent_id: the id of the new parent
|
|
1042 |
@param new_name: the new name for this node
|
|
1043 |
@param callback: function to call when data arrives
|
|
1044 |
||
1045 |
"""
|
|
1046 |
request.Request.__init__(self, protocol) |
|
1047 |
self.share = share |
|
1048 |
self.node_id = node_id |
|
1049 |
self.new_parent_id = new_parent_id |
|
1050 |
self.new_name = new_name |
|
105.1.1
by facundo at com
Fixed attributes, and how setup.py uses lint |
1051 |
self.new_generation = None |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1052 |
|
1053 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1054 |
"""Send MOVE."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1055 |
message = protocol_pb2.Message() |
1056 |
message.type = protocol_pb2.Message.MOVE |
|
1057 |
message.move.share = self.share |
|
1058 |
message.move.node = self.node_id |
|
1059 |
message.move.new_parent_node = str(self.new_parent_id) |
|
1060 |
message.move.new_name = self.new_name |
|
1061 |
||
1062 |
self.sendMessage(message) |
|
1063 |
||
1064 |
def processMessage(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1065 |
"""Process messages."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1066 |
if message.type == protocol_pb2.Message.OK: |
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1067 |
self.new_generation = message.new_generation |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1068 |
self.done() |
1069 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1070 |
self._default_process_message(message) |
1071 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1072 |
|
1073 |
class MultiQuery(object): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1074 |
"""Create a Request-like object that encapsulates many Query requests
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1075 |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1076 |
We may need to split this request into many Query rests if the list of
|
1077 |
items to query is to big to fit in one message.
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1078 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1079 |
"""
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1080 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1081 |
__slots__ = ('queries', 'deferred') |
1082 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1083 |
def __init__(self, protocol, items): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1084 |
"""Create a multiquery.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1085 |
|
1086 |
@param protocol: the request handler
|
|
1087 |
@param items: a list of (node, hash) tuples
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1088 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1089 |
"""
|
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
1090 |
items = iter(items) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1091 |
defers = [] |
1092 |
self.queries = [] |
|
1093 |
||
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
1094 |
while True: |
1095 |
r = Query(protocol, items) |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1096 |
self.queries.append(r) |
1097 |
defers.append(r.deferred) |
|
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
1098 |
if r.overflow: |
1099 |
items = chain([r.overflow], items) |
|
1100 |
else: |
|
1101 |
break
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1102 |
|
41.1.2
by tim.cole at canonical
consume MultiQuery subquery errors |
1103 |
self.deferred = defer.DeferredList(defers, consumeErrors=True) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1104 |
|
1105 |
def start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1106 |
"""Start the queries."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1107 |
for q in self.queries: |
1108 |
q.start() |
|
1109 |
||
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1110 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1111 |
class Query(request.Request): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1112 |
"""Query about the hash of a node_id.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1113 |
|
1114 |
@ivar remains: the items that could not fit in the query
|
|
1115 |
@ivar response: the node state messages that were received
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1116 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1117 |
"""
|
1118 |
||
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1119 |
__slots__ = ('query_message', 'response', 'overflow') |
1120 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1121 |
def __init__(self, protocol, items): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1122 |
"""Generate a query message to send to the server.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1123 |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1124 |
Put as much items as it can inside the message whats left is
|
1125 |
left in self.remainder.
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1126 |
|
1127 |
@param protocol: the request handler
|
|
1128 |
@param items: a list of (node, hash, share) tuples
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1129 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1130 |
"""
|
1131 |
request.Request.__init__(self, protocol) |
|
1132 |
self.query_message = qm = protocol_pb2.Message() |
|
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
1133 |
qm.id = 0 # just to have something in the field when calculating size |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1134 |
qm.type = protocol_pb2.Message.QUERY |
1135 |
self.response = [] |
|
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
1136 |
self.overflow = None |
1137 |
items_that_fit = [] |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1138 |
|
1139 |
def add_items(msg, *args): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1140 |
"""Add items to query."""
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
1141 |
for share, node, content_hash in args: |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1142 |
qi = msg.query.add() |
1143 |
qi.share = share |
|
1144 |
qi.node = str(node) |
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
1145 |
qi.hash = content_hash |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1146 |
|
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
1147 |
for item in items: |
1148 |
add_items(qm, item) |
|
1149 |
if qm.ByteSize() > request.MAX_MESSAGE_SIZE: |
|
1150 |
self.overflow = item |
|
1151 |
break
|
|
1152 |
items_that_fit.append(item) |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1153 |
|
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
1154 |
if self.overflow is not None: |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1155 |
qm.ClearField("query") |
25.1.1
by john.lenton at canonical
make MultiQuery able to take a generator |
1156 |
add_items(qm, *items_that_fit) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1157 |
|
1158 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1159 |
"""Send QUERY."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1160 |
self.sendMessage(self.query_message) |
1161 |
||
1162 |
def processMessage(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1163 |
"""Handle messages."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1164 |
if message.type == protocol_pb2.Message.NODE_STATE: |
1165 |
self.response.append(message.node_state) |
|
1166 |
self.protocol.notify_node_state(message.node_state) |
|
1167 |
elif message.type == protocol_pb2.Message.QUERY_END: |
|
1168 |
self.done() |
|
1169 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1170 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1171 |
|
7
by Rodney Dawes
Merge Facundo's changes |
1172 |
|
1173 |
class BytesMessageProducer(object): |
|
1174 |
"""Produce BYTES messages from a file."""
|
|
1175 |
||
129.1.3
by Guillermo Gonzalez
define callLater as a class attribute |
1176 |
# to allow patching this in test and use task.Clock
|
1177 |
callLater = reactor.callLater |
|
1178 |
||
129.1.2
by Guillermo Gonzalez
change the approach to a patcheable callLater method and remove blank line at the end of test_bytesproducer.py |
1179 |
def __init__(self, req, fh, offset): |
7
by Rodney Dawes
Merge Facundo's changes |
1180 |
"""Create a BytesMessageProducer."""
|
121.1.2
by Rodney Dawes
Fix some of the remaining lint issues |
1181 |
self.request = req |
7
by Rodney Dawes
Merge Facundo's changes |
1182 |
self.producing = False |
1183 |
self.fh = fh |
|
64.2.2
by john.lenton at canonical
OBEY. |
1184 |
self.offset = offset |
74.2.1
by facundo at com
Fixed two bugs: in the Producer and in the Throttler |
1185 |
self.finished = False |
7
by Rodney Dawes
Merge Facundo's changes |
1186 |
|
1187 |
def resumeProducing(self): |
|
1188 |
"""IPushProducer interface."""
|
|
1189 |
self.producing = True |
|
1190 |
self.go() |
|
1191 |
||
1192 |
def stopProducing(self): |
|
1193 |
"""IPushProducer interface."""
|
|
1194 |
self.producing = False |
|
1195 |
||
1196 |
def pauseProducing(self): |
|
1197 |
"""IPushProducer interface."""
|
|
1198 |
self.producing = False |
|
1199 |
||
1200 |
def go(self): |
|
1201 |
"""While producing, generates data.
|
|
1202 |
||
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1203 |
Read a little from the file, generates a BYTES message, and pass the
|
1204 |
control to the reactor. If no more data, finish with EOF.
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1205 |
|
7
by Rodney Dawes
Merge Facundo's changes |
1206 |
"""
|
74.2.1
by facundo at com
Fixed two bugs: in the Producer and in the Throttler |
1207 |
if not self.producing or self.request.cancelled or self.finished: |
7
by Rodney Dawes
Merge Facundo's changes |
1208 |
return
|
1209 |
||
66.1.1
by john.lenton at canonical
make BytesMessageProducer only seek if the offset was specified |
1210 |
if self.offset: |
1211 |
self.fh.seek(self.offset) |
|
132.1.1
by Facundo Batista
Change the way the producer decides how much to send. |
1212 |
data = self.fh.read(self.request.max_payload_size) |
7
by Rodney Dawes
Merge Facundo's changes |
1213 |
if data: |
66.1.1
by john.lenton at canonical
make BytesMessageProducer only seek if the offset was specified |
1214 |
if self.offset: |
1215 |
self.offset += len(data) |
|
7
by Rodney Dawes
Merge Facundo's changes |
1216 |
response = protocol_pb2.Message() |
1217 |
response.type = protocol_pb2.Message.BYTES |
|
1218 |
response.bytes.bytes = data |
|
1219 |
self.request.sendMessage(response) |
|
129.1.2
by Guillermo Gonzalez
change the approach to a patcheable callLater method and remove blank line at the end of test_bytesproducer.py |
1220 |
self.callLater(0, self.go) |
7
by Rodney Dawes
Merge Facundo's changes |
1221 |
else: |
1222 |
message = protocol_pb2.Message() |
|
1223 |
message.type = protocol_pb2.Message.EOF |
|
1224 |
self.request.sendMessage(message) |
|
1225 |
self.producing = False |
|
74.2.1
by facundo at com
Fixed two bugs: in the Producer and in the Throttler |
1226 |
self.finished = True |
7
by Rodney Dawes
Merge Facundo's changes |
1227 |
|
1228 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1229 |
class PutContent(request.Request): |
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1230 |
"""Put content request.
|
1231 |
||
1232 |
@ivar new_generation: the generation that the volume is at now
|
|
1233 |
"""
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1234 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1235 |
__slots__ = ('share', 'node_id', 'previous_hash', 'hash', 'crc32', 'size', |
1236 |
'size', 'deflated_size', 'fd', 'upload_id_cb', 'upload_id', |
|
1237 |
'new_generation', 'max_payload_size', 'magic_hash') |
|
1238 |
||
124.1.2
by Facundo Batista
Magic hash! |
1239 |
def __init__(self, protocol, share, node_id, previous_hash, new_hash, |
1240 |
crc32, size, deflated_size, fd, upload_id=None, |
|
129.1.2
by Guillermo Gonzalez
change the approach to a patcheable callLater method and remove blank line at the end of test_bytesproducer.py |
1241 |
upload_id_cb=None, magic_hash=None): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1242 |
"""Put content into a node.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1243 |
|
1244 |
@param protocol: the request handler
|
|
1245 |
@param share: the share node or root
|
|
1246 |
@param node_id: the node to receive the content
|
|
1247 |
@param previous_hash: the hash the node has (for conflict checking)
|
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
1248 |
@param new_hash: the hash hint for the new content
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1249 |
@param crc32: the crc32 hint for the new content
|
1250 |
@param size: the size hint for the new content
|
|
1251 |
@param fd: a file-like object to read data from
|
|
123.2.1
by Guillermo Gonzalez
add upload_id support to PutContent (BEGIN_CONTENT and PUT_CONTENT messages) |
1252 |
@param upload_id: the upload id (to resume the upload.)
|
124.1.2
by Facundo Batista
Magic hash! |
1253 |
@param upload_id_cb: callback that will be called with the upload id
|
1254 |
assigned by the server for the session
|
|
1255 |
@param magic_hash: the magic_hash of the file
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1256 |
|
1257 |
"""
|
|
1258 |
request.Request.__init__(self, protocol) |
|
1259 |
self.share = share |
|
1260 |
self.node_id = node_id |
|
1261 |
self.previous_hash = previous_hash |
|
87.1.1
by natalia.bidart at canonical
Avoiding shadowing builtin hash. |
1262 |
self.hash = new_hash |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1263 |
self.crc32 = crc32 |
1264 |
self.size = size |
|
1265 |
self.deflated_size = deflated_size |
|
1266 |
self.fd = fd |
|
123.2.1
by Guillermo Gonzalez
add upload_id support to PutContent (BEGIN_CONTENT and PUT_CONTENT messages) |
1267 |
self.upload_id_cb = upload_id_cb |
1268 |
self.upload_id = upload_id |
|
105.1.1
by facundo at com
Fixed attributes, and how setup.py uses lint |
1269 |
self.new_generation = None |
124.1.2
by Facundo Batista
Magic hash! |
1270 |
self.magic_hash = magic_hash |
132.1.1
by Facundo Batista
Change the way the producer decides how much to send. |
1271 |
self.max_payload_size = protocol.max_payload_size |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1272 |
|
1273 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1274 |
"""Send PUT_CONTENT."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1275 |
message = protocol_pb2.Message() |
1276 |
message.type = protocol_pb2.Message.PUT_CONTENT |
|
1277 |
message.put_content.share = self.share |
|
1278 |
message.put_content.node = str(self.node_id) |
|
1279 |
message.put_content.previous_hash = self.previous_hash |
|
1280 |
message.put_content.hash = self.hash |
|
1281 |
message.put_content.crc32 = self.crc32 |
|
1282 |
message.put_content.size = self.size |
|
1283 |
message.put_content.deflated_size = self.deflated_size |
|
123.2.1
by Guillermo Gonzalez
add upload_id support to PutContent (BEGIN_CONTENT and PUT_CONTENT messages) |
1284 |
if self.upload_id: |
1285 |
message.put_content.upload_id = self.upload_id |
|
124.1.2
by Facundo Batista
Magic hash! |
1286 |
if self.magic_hash is not None: |
1287 |
message.put_content.magic_hash = self.magic_hash |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1288 |
self.sendMessage(message) |
1289 |
||
1290 |
def processMessage(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1291 |
"""Handle messages."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1292 |
if message.type == protocol_pb2.Message.BEGIN_CONTENT: |
123.2.1
by Guillermo Gonzalez
add upload_id support to PutContent (BEGIN_CONTENT and PUT_CONTENT messages) |
1293 |
# call the upload_id_cb (if the upload_id it's in the message)
|
167.1.1
by Facundo Batista
Callback on BEGIN_CONTENT also with offset. |
1294 |
if message.begin_content.upload_id and self.upload_id_cb: |
1295 |
self.upload_id_cb(message.begin_content.upload_id, |
|
1296 |
message.begin_content.offset) |
|
64.2.2
by john.lenton at canonical
OBEY. |
1297 |
message_producer = BytesMessageProducer( |
129.1.2
by Guillermo Gonzalez
change the approach to a patcheable callLater method and remove blank line at the end of test_bytesproducer.py |
1298 |
self, self.fd, message.begin_content.offset) |
7
by Rodney Dawes
Merge Facundo's changes |
1299 |
self.registerProducer(message_producer, streaming=True) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1300 |
elif message.type == protocol_pb2.Message.OK: |
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1301 |
self.new_generation = message.new_generation |
23.1.1
by Lucio Torre
tmp |
1302 |
self.done() |
1303 |
elif message.type == protocol_pb2.Message.CANCELLED: |
|
23.1.6
by Lucio Torre
fixed + feature |
1304 |
self.error(request.RequestCancelledError("CANCELLED")) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1305 |
else: |
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1306 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1307 |
|
15.2.1
by facundo at com
Now the state is handled by Request. |
1308 |
def _cancel(self): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1309 |
"""Cancel the current upload."""
|
15.2.1
by facundo at com
Now the state is handled by Request. |
1310 |
if self.producer is not None: |
1311 |
self.producer.stopProducing() |
|
1312 |
message = protocol_pb2.Message() |
|
1313 |
message.type = protocol_pb2.Message.CANCEL_REQUEST |
|
1314 |
self.sendMessage(message) |
|
7.1.1
by facundo at com
Changes to allow cancel upload. |
1315 |
|
7
by Rodney Dawes
Merge Facundo's changes |
1316 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1317 |
class MakeObject(request.Request): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1318 |
"""Handle the creation of new objects.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1319 |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1320 |
On completion it will have the attribute 'new_id' with the
|
1321 |
node id of the created object.
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1322 |
|
1323 |
@cvar create_message: must be overridden with the correct creation message
|
|
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
1324 |
to send
|
1325 |
@cvar response_message: must be overridden with the correct creation
|
|
1326 |
success message that will be received
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1327 |
|
1328 |
@ivar new_id: the id of the node that was created (available upon success)
|
|
1329 |
@ivar new_parent_id: the parent id the node now exists under
|
|
1330 |
@ivar new_name: the name the node now exists under
|
|
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1331 |
@ivar new_generation: the generation that the volume is at now
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1332 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1333 |
"""
|
1334 |
||
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1335 |
__slots__ = ('share', 'parent_id', 'name') |
1336 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1337 |
def __init__(self, protocol, share, parent_id, name): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1338 |
"""Create a node.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1339 |
|
1340 |
@param protocol: the request handler
|
|
1341 |
@param share: the share node or root
|
|
1342 |
@param parent_id: the desired parent id
|
|
1343 |
@param name: the desired name
|
|
1344 |
||
1345 |
"""
|
|
1346 |
request.Request.__init__(self, protocol) |
|
1347 |
self.share = share |
|
1348 |
self.parent_id = parent_id |
|
1349 |
self.name = name |
|
1350 |
||
1351 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1352 |
"""Send MAKE message."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1353 |
message = protocol_pb2.Message() |
1354 |
message.type = self.create_message |
|
1355 |
||
1356 |
message.make.share = self.share |
|
1357 |
message.make.parent_node = str(self.parent_id) |
|
1358 |
message.make.name = self.name |
|
1359 |
self.sendMessage(message) |
|
1360 |
||
1361 |
def processMessage(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1362 |
"""Handle messages."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1363 |
if message.type == self.create_response: |
1364 |
self.new_id = message.new.node |
|
1365 |
self.new_parent_id = message.new.parent_node |
|
1366 |
self.new_name = message.new.name |
|
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1367 |
self.new_generation = message.new_generation |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1368 |
self.done() |
1369 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1370 |
self._default_process_message(message) |
1371 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1372 |
|
1373 |
class MakeDir(MakeObject): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1374 |
"""Extend MakeObject to make directories."""
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1375 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1376 |
create_message = protocol_pb2.Message.MAKE_DIR |
1377 |
create_response = protocol_pb2.Message.NEW_DIR |
|
1378 |
||
1379 |
||
1380 |
class MakeFile(MakeObject): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1381 |
"""Extend MakeObject to make files."""
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1382 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1383 |
create_message = protocol_pb2.Message.MAKE_FILE |
1384 |
create_response = protocol_pb2.Message.NEW_FILE |
|
1385 |
||
1386 |
||
1387 |
class ProtocolVersion(request.Request): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1388 |
"""Handle the protocol version query.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1389 |
|
1390 |
when completed will contain the servers protocol version
|
|
1391 |
on `other_protocol_version`
|
|
1392 |
||
1393 |
@ivar other_protocol_version: the other peer's protocol version (available
|
|
1394 |
upon success)
|
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1395 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1396 |
"""
|
1397 |
||
1398 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1399 |
"""Send PROTOCOL_VERSION."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1400 |
message = protocol_pb2.Message() |
1401 |
message.type = protocol_pb2.Message.PROTOCOL_VERSION |
|
1402 |
message.protocol.version = self.protocol.PROTOCOL_VERSION |
|
1403 |
self.sendMessage(message) |
|
1404 |
||
1405 |
def processMessage(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1406 |
"""Handle messages."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1407 |
if message.type == protocol_pb2.Message.PROTOCOL_VERSION: |
1408 |
self.other_protocol_version = message.protocol.version |
|
1409 |
self.done() |
|
1410 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1411 |
self._default_process_message(message) |
1412 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1413 |
|
1414 |
class Authenticate(request.Request): |
|
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1415 |
"""Request to authenticate the user.
|
1416 |
||
1417 |
@ivar session_id: the session id with the server.
|
|
1418 |
"""
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1419 |
|
135.1.1
by guillermo.gonzalez at canonical
add optional metadata key/value list in AUTH_REQUEST message |
1420 |
__slots__ = ('auth_parameters', 'session_id', 'metadata') |
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1421 |
|
135.1.1
by guillermo.gonzalez at canonical
add optional metadata key/value list in AUTH_REQUEST message |
1422 |
def __init__(self, protocol, auth_parameters, metadata=None): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1423 |
"""Create an authentication request.
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1424 |
|
1425 |
@param protocol: the request handler
|
|
1426 |
@param auth_parameters: a dictionary of authentication parameters.
|
|
135.1.1
by guillermo.gonzalez at canonical
add optional metadata key/value list in AUTH_REQUEST message |
1427 |
@param metadata: a dictionary of extra info
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1428 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1429 |
"""
|
1430 |
request.Request.__init__(self, protocol) |
|
1431 |
self.auth_parameters = auth_parameters |
|
135.1.1
by guillermo.gonzalez at canonical
add optional metadata key/value list in AUTH_REQUEST message |
1432 |
self.metadata = metadata |
105.1.1
by facundo at com
Fixed attributes, and how setup.py uses lint |
1433 |
self.session_id = None |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1434 |
|
1435 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1436 |
"""Send AUTH_REQUEST."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1437 |
message = protocol_pb2.Message() |
1438 |
message.type = protocol_pb2.Message.AUTH_REQUEST |
|
1439 |
for key, value in self.auth_parameters.items(): |
|
1440 |
param = message.auth_parameters.add() |
|
1441 |
param.name = key |
|
1442 |
param.value = value |
|
135.1.1
by guillermo.gonzalez at canonical
add optional metadata key/value list in AUTH_REQUEST message |
1443 |
if self.metadata: |
1444 |
for key, value in self.metadata.items(): |
|
1445 |
param = message.metadata.add() |
|
1446 |
param.key = key |
|
1447 |
param.value = value |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1448 |
self.sendMessage(message) |
1449 |
||
1450 |
def processMessage(self, message): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1451 |
"""Handle messages."""
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1452 |
if message.type == protocol_pb2.Message.AUTH_AUTHENTICATED: |
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1453 |
self.session_id = message.session_id |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1454 |
self.done() |
1455 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1456 |
self._default_process_message(message) |
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1457 |
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1458 |
|
51.1.2
by facundo at com
Forgot to join both classes. |
1459 |
class QuerySetCaps(request.Request): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1460 |
"""Query or Set the server to use capabilities."""
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1461 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1462 |
__slots__ = ('caps', 'accepted', 'redirect_hostname', 'redirect_port', |
1463 |
'redirect_srvrecord', 'set_mode') |
|
1464 |
||
51.1.2
by facundo at com
Forgot to join both classes. |
1465 |
def __init__(self, protocol, caps, set_mode=False): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1466 |
"""Generate a query_caps or set_caps message to send to the server.
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1467 |
|
1468 |
@param protocol: the request handler
|
|
51.1.2
by facundo at com
Forgot to join both classes. |
1469 |
@param caps: a list of capabilities to ask for or to set
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1470 |
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1471 |
"""
|
1472 |
request.Request.__init__(self, protocol) |
|
1473 |
self.caps = caps |
|
1474 |
self.accepted = None |
|
1475 |
self.redirect_hostname = None |
|
1476 |
self.redirect_port = None |
|
1477 |
self.redirect_srvrecord = None |
|
51.1.2
by facundo at com
Forgot to join both classes. |
1478 |
self.set_mode = set_mode |
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1479 |
|
1480 |
def _start(self): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1481 |
"""Send QUERY_CAPS or SET_CAPS."""
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1482 |
message = protocol_pb2.Message() |
51.1.2
by facundo at com
Forgot to join both classes. |
1483 |
if self.set_mode: |
1484 |
message.type = protocol_pb2.Message.SET_CAPS |
|
1485 |
for cap in self.caps: |
|
1486 |
qc = message.set_caps.add() |
|
1487 |
qc.capability = cap |
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1488 |
else: |
51.1.2
by facundo at com
Forgot to join both classes. |
1489 |
message.type = protocol_pb2.Message.QUERY_CAPS |
1490 |
for cap in self.caps: |
|
1491 |
qc = message.query_caps.add() |
|
1492 |
qc.capability = cap |
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1493 |
|
1494 |
self.sendMessage(message) |
|
1495 |
||
1496 |
def processMessage(self, message): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1497 |
"""Handle the message."""
|
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1498 |
if message.type == protocol_pb2.Message.ACCEPT_CAPS: |
1499 |
self.accepted = message.accept_caps.accepted |
|
1500 |
self.redirect_hostname = message.accept_caps.redirect_hostname |
|
1501 |
self.redirect_port = message.accept_caps.redirect_port |
|
1502 |
self.redirect_srvrecord = message.accept_caps.redirect_srvrecord |
|
1503 |
self.done() |
|
1504 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1505 |
self._default_process_message(message) |
51.1.1
by facundo at com
Protocol and client changes to dialog with the server about capabilities |
1506 |
|
1507 |
||
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
1508 |
class FreeSpaceInquiry(request.Request): |
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1509 |
"""Query available space."""
|
1510 |
||
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1511 |
__slots__ = ('share_id', 'free_bytes') |
1512 |
||
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1513 |
def __init__(self, protocol, share_id): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1514 |
"""Initialize the request."""
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1515 |
request.Request.__init__(self, protocol) |
1516 |
self.share_id = share_id |
|
1517 |
||
1518 |
def _start(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1519 |
"""Send the FREE_SPACE_INQUIRY message to the server."""
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1520 |
message = protocol_pb2.Message() |
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
1521 |
message.type = protocol_pb2.Message.FREE_SPACE_INQUIRY |
1522 |
message.free_space_inquiry.share_id = self.share_id |
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1523 |
self.sendMessage(message) |
1524 |
self.free_bytes = None |
|
1525 |
||
1526 |
def processMessage(self, message): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1527 |
"""Process the answer from the server."""
|
59.1.4
by tim.cole at canonical
Quota -> FreeSpace, plus fix field index |
1528 |
if message.type == protocol_pb2.Message.FREE_SPACE_INFO: |
1529 |
self.free_bytes = message.free_space_info.free_bytes |
|
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
1530 |
self.done() |
1531 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1532 |
self._default_process_message(message) |
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
1533 |
|
1534 |
||
1535 |
class AccountInquiry(request.Request): |
|
1536 |
"""Query account information."""
|
|
1537 |
||
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1538 |
__slots__ = ('purchased_bytes',) |
1539 |
||
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
1540 |
def _start(self): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1541 |
"""Send the FREE_SPACE_INQUIRY message to the server."""
|
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
1542 |
message = protocol_pb2.Message() |
1543 |
message.type = protocol_pb2.Message.ACCOUNT_INQUIRY |
|
1544 |
self.sendMessage(message) |
|
1545 |
self.purchased_bytes = None |
|
1546 |
||
1547 |
def processMessage(self, message): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1548 |
"""Process the answer from the server."""
|
59.1.2
by tim.cole at canonical
finally get the messages sorted out for account and quota info |
1549 |
if message.type == protocol_pb2.Message.ACCOUNT_INFO: |
1550 |
self.purchased_bytes = message.account_info.purchased_bytes |
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1551 |
self.done() |
1552 |
else: |
|
90.1.5
by natalia.bidart at canonical
Request's implementation now uses default handling for processing messages. |
1553 |
self._default_process_message(message) |
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1554 |
|
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
1555 |
|
101.1.1
by lucio.torre at gmail
added delta messages |
1556 |
class GetDelta(request.Request): |
1557 |
"""Get a delta on a volume
|
|
1558 |
||
1559 |
@ivar end_generation: The generation the volume will be after aplying this
|
|
1560 |
delta
|
|
1561 |
@ivar full: True if all changes were included. False is there is some
|
|
1562 |
later generations not included.
|
|
1563 |
@ivar free_bytes: The free space of the volume.
|
|
1564 |
Only a hint if full is False.
|
|
1565 |
@ivar response: the list of deltanodes received or empty if called with
|
|
1566 |
callback
|
|
1567 |
"""
|
|
1568 |
||
111.1.2
by lucio.torre at gmail
nicer api |
1569 |
def __init__(self, protocol, share_id, from_generation=None, |
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1570 |
callback=None, from_scratch=False): |
101.1.1
by lucio.torre at gmail
added delta messages |
1571 |
"""Generates a GET_DELTA message to the server.
|
1572 |
||
1573 |
@param protocol: the request handler
|
|
1574 |
@param volume_id: the volume id
|
|
1575 |
@param from_generation: the starting generation for the delta
|
|
101.4.3
by lucio.torre at gmail
fixed typos |
1576 |
@param from_scratch: request a delta with all live files
|
101.1.1
by lucio.torre at gmail
added delta messages |
1577 |
|
1578 |
"""
|
|
111.1.1
by lucio.torre at gmail
get delta from scratch client support |
1579 |
if from_generation is None and from_scratch is False: |
1580 |
raise TypeError("get_delta needs from_generation or from_scratch.") |
|
1581 |
||
101.1.1
by lucio.torre at gmail
added delta messages |
1582 |
request.Request.__init__(self, protocol) |
1583 |
self.share_id = str(share_id) |
|
1584 |
self.from_generation = from_generation |
|
1585 |
self.callback = callback |
|
1586 |
self.delta_message = dm = protocol_pb2.Message() |
|
1587 |
dm.type = protocol_pb2.Message.GET_DELTA |
|
1588 |
dm.get_delta.share = self.share_id |
|
111.1.1
by lucio.torre at gmail
get delta from scratch client support |
1589 |
if not from_scratch: |
1590 |
dm.get_delta.from_generation = from_generation |
|
101.4.2
by lucio.torre at gmail
added free bytes, generation info, from scratch deltas and session info |
1591 |
dm.get_delta.from_scratch = from_scratch |
101.1.1
by lucio.torre at gmail
added delta messages |
1592 |
|
1593 |
self.response = [] |
|
1594 |
self.end_generation = None |
|
1595 |
self.full = None |
|
105.1.1
by facundo at com
Fixed attributes, and how setup.py uses lint |
1596 |
self.free_bytes = None |
1597 |
self.generation = None |
|
101.1.1
by lucio.torre at gmail
added delta messages |
1598 |
|
134.1.1
by Guillermo Gonzalez
use slots in Request (and it subclasses) and RequestResponse |
1599 |
__slots__ = ('share_id', 'from_generation', 'callback', 'delta_message', |
1600 |
'response', 'end_generation', 'full', 'free_bytes', |
|
1601 |
'generation') |
|
1602 |
||
101.1.1
by lucio.torre at gmail
added delta messages |
1603 |
def _start(self): |
1604 |
"""Send GET_DELTA."""
|
|
1605 |
self.sendMessage(self.delta_message) |
|
1606 |
||
1607 |
def processMessage(self, message): |
|
1608 |
"""Handle messages."""
|
|
1609 |
if message.type == protocol_pb2.Message.DELTA_INFO: |
|
1610 |
info = delta.from_message(message) |
|
1611 |
if self.callback: |
|
1612 |
self.callback(info) |
|
1613 |
else: |
|
1614 |
self.response.append(info) |
|
1615 |
elif message.type == protocol_pb2.Message.DELTA_END: |
|
113.1.2
by lucio.torre at gmail
fix end_generation |
1616 |
self.end_generation = message.delta_end.generation |
101.1.1
by lucio.torre at gmail
added delta messages |
1617 |
self.full = message.delta_end.full |
1618 |
self.free_bytes = message.delta_end.free_bytes |
|
1619 |
self.done() |
|
1620 |
else: |
|
1621 |
self._default_process_message(message) |
|
59.1.1
by tim.cole at canonical
add QuotaInquiry and QuotaInfo messages |
1622 |
|
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
1623 |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1624 |
class ThrottlingStorageClient(StorageClient): |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1625 |
"""The throttling version of the StorageClient protocol."""
|
1626 |
||
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1627 |
factory = None |
1628 |
||
1629 |
def connectionMade(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1630 |
"""Handle connectionMade."""
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1631 |
if self.factory.client is None: |
1632 |
self.factory.client = self |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1633 |
StorageClient.connectionMade(self) |
1634 |
||
1635 |
def connectionLost(self, reason=None): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1636 |
"""Handle connectionLost."""
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1637 |
if self.factory.client is self: |
1638 |
self.factory.unregisterProtocol(self) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1639 |
StorageClient.connectionLost(self, reason=reason) |
1640 |
||
1641 |
def write(self, data): |
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1642 |
"""Transport API to capture bytes written."""
|
1643 |
if self.factory.client is self: |
|
1644 |
self.factory.registerWritten(len(data)) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1645 |
StorageClient.write(self, data) |
1646 |
||
1647 |
def writeSequence(self, seq): |
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1648 |
"""Transport API to capture bytes written in a sequence."""
|
1649 |
if self.factory.client is self: |
|
74.1.3
by facundo at com
Bye bye reduce |
1650 |
self.factory.registerWritten(sum(len(x) for x in seq)) |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1651 |
StorageClient.writeSequence(self, seq) |
1652 |
||
1653 |
def dataReceived(self, data): |
|
74.1.2
by facundo at com
Typo |
1654 |
"""Override transport default to capture bytes read."""
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1655 |
if self.factory.client is self: |
1656 |
self.factory.registerRead(len(data)) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1657 |
StorageClient.dataReceived(self, data) |
1658 |
||
1659 |
def throttleReads(self): |
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1660 |
"""Pause self.transport."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1661 |
self.transport.pauseProducing() |
1662 |
||
1663 |
def unthrottleReads(self): |
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1664 |
"""Resume self.transport."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1665 |
self.transport.resumeProducing() |
1666 |
||
1667 |
def throttleWrites(self): |
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1668 |
"""Pause producing."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1669 |
self.pauseProducing() |
1670 |
||
1671 |
def unthrottleWrites(self): |
|
74.1.1
by facundo at com
Now ThrottlingStorageClient alters the factory only if there's no client |
1672 |
"""Resume producing."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1673 |
self.resumeProducing() |
1674 |
||
1675 |
||
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1676 |
class StorageClientFactory(ClientFactory): |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1677 |
"""StorageClient factory."""
|
169.1.1
by Natalia
- Added proper copyright notices and coding headers. |
1678 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1679 |
protocol = StorageClient |
1680 |
||
1681 |
||
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1682 |
class ThrottlingStorageClientFactory(StorageClientFactory, object): |
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1683 |
"""The throttling version of StorageClientFactory."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1684 |
|
1685 |
protocol = ThrottlingStorageClient |
|
83.1.1
by guillermo.gonzalez at canonical
use task.Clock.callLater + .advance instead of reactor.callLater in throttling tests |
1686 |
client = None |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1687 |
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1688 |
def __init__(self, throttling_enabled=False, |
1689 |
read_limit=None, write_limit=None): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1690 |
"""Create the instance."""
|
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
1691 |
self._readLimit = None # max bytes we should read per second |
1692 |
self._writeLimit = None # max bytes we should write per second |
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1693 |
self._throttling_reads = False |
1694 |
self._throttling_writes = False |
|
1695 |
self._set_read_limit(read_limit) |
|
1696 |
self._set_write_limit(write_limit) |
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1697 |
self.throttling_enabled = throttling_enabled |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1698 |
self.readThisSecond = 0 |
1699 |
self.writtenThisSecond = 0 |
|
1700 |
self.unthrottleReadsID = None |
|
65.1.1
by guillermo.gonzalez at canonical
allow set the read/write limit in the throttling factory after it creation |
1701 |
self.resetReadThisSecondID = None |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1702 |
self.unthrottleWritesID = None |
65.1.1
by guillermo.gonzalez at canonical
allow set the read/write limit in the throttling factory after it creation |
1703 |
self.resetWriteThisSecondID = None |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1704 |
self.stopped = True |
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1705 |
if self.throttling_enabled: |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1706 |
self.enable_throttling() |
1707 |
else: |
|
1708 |
self.disable_throttling() |
|
1709 |
||
1710 |
def valid_limit(self, limit): |
|
1711 |
"""Check if limit is a valid valid."""
|
|
83.2.4
by guillermo.gonzalez at canonical
Don't allow setting throttling limits to 0 |
1712 |
return limit is None or limit > 0 |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1713 |
|
1714 |
def _set_write_limit(self, limit): |
|
1715 |
"""Set writeLimit value.
|
|
1716 |
||
1717 |
Raise a ValueError if the value ins't valid.
|
|
1718 |
"""
|
|
1719 |
if not self.valid_limit(limit): |
|
83.2.4
by guillermo.gonzalez at canonical
Don't allow setting throttling limits to 0 |
1720 |
raise ValueError('Write limit must be greater than 0.') |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1721 |
self._writeLimit = limit |
1722 |
||
1723 |
def _set_read_limit(self, limit): |
|
1724 |
"""Set readLimit value.
|
|
1725 |
||
1726 |
Raise a ValueError if the value ins't valid.
|
|
1727 |
"""
|
|
1728 |
if not self.valid_limit(limit): |
|
83.2.4
by guillermo.gonzalez at canonical
Don't allow setting throttling limits to 0 |
1729 |
raise ValueError('Read limit must be greater than 0.') |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1730 |
self._readLimit = limit |
169.1.1
by Natalia
- Added proper copyright notices and coding headers. |
1731 |
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1732 |
readLimit = property(lambda self: self._readLimit, _set_read_limit) |
1733 |
writeLimit = property(lambda self: self._writeLimit, _set_write_limit) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1734 |
|
1735 |
def callLater(self, period, func, *args, **kwargs): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1736 |
"""Wrapper around L{reactor.callLater} for test purpose."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1737 |
return reactor.callLater(period, func, *args, **kwargs) |
1738 |
||
121.1.2
by Rodney Dawes
Fix some of the remaining lint issues |
1739 |
def maybeCallLater(self, call_id, period, func): |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1740 |
"""Maybe run callLater(period, func).
|
1741 |
||
1742 |
Only if we don't have a DelayedCall with the
|
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1743 |
specified id already running.
|
1744 |
"""
|
|
121.1.2
by Rodney Dawes
Fix some of the remaining lint issues |
1745 |
delayed_call = getattr(self, call_id) |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1746 |
# check if we already have a DelayedCall running
|
166.1.2
by Facundo Batista
Aesthetic details. |
1747 |
if delayed_call is None or ( |
1748 |
not delayed_call.active() and delayed_call.cancelled): |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1749 |
return self.callLater(period, func) |
1750 |
return delayed_call |
|
1751 |
||
1752 |
def registerWritten(self, length): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1753 |
"""Called by protocol to tell us more bytes were written."""
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1754 |
if self.throttling_enabled: |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1755 |
self.writtenThisSecond += length |
1756 |
self.checkWriteBandwidth() |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1757 |
|
1758 |
def registerRead(self, length): |
|
78.1.1
by natalia.bidart at canonical
Adding new messages for UDF and volumes. |
1759 |
"""Called by protocol to tell us more bytes were read."""
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1760 |
if self.throttling_enabled: |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1761 |
self.readThisSecond += length |
1762 |
self.checkReadBandwidth() |
|
1763 |
||
121.1.2
by Rodney Dawes
Fix some of the remaining lint issues |
1764 |
def _get_throttle_time(self, data_bytes, limit): |
1765 |
"""Calculate the throttle_time for data_bytes and limit."""
|
|
1766 |
return (float(data_bytes) / limit) - 1.0 |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1767 |
|
1768 |
def checkReadBandwidth(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1769 |
"""Check if we've passed bandwidth limits."""
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1770 |
limit_check = self.valid_limit(self.readLimit) and \ |
164.1.1
by Facundo Batista
Use simple authentication against the server. |
1771 |
self.readLimit is not None and \ |
1772 |
self.readThisSecond >= self.readLimit |
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1773 |
should_check = self.throttling_enabled and limit_check and \ |
164.1.1
by Facundo Batista
Use simple authentication against the server. |
1774 |
self.unthrottleReadsID is None |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1775 |
if should_check: |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1776 |
self.throttleReads() |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1777 |
throttle_time = self._get_throttle_time(self.readThisSecond, |
1778 |
self.readLimit) |
|
83.2.4
by guillermo.gonzalez at canonical
Don't allow setting throttling limits to 0 |
1779 |
log_debug("pause reads for: %s", str(throttle_time)) |
1780 |
self.unthrottleReadsID = self.maybeCallLater( |
|
1781 |
'unthrottleReadsID', throttle_time, self.unthrottleReads) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1782 |
|
1783 |
def checkWriteBandwidth(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1784 |
"""Check if we've passed bandwidth limits."""
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1785 |
limit_check = self.valid_limit(self.writeLimit) and \ |
164.1.1
by Facundo Batista
Use simple authentication against the server. |
1786 |
self.writeLimit is not None and \ |
1787 |
self.writtenThisSecond >= self.writeLimit |
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1788 |
should_check = self.throttling_enabled and limit_check and \ |
164.1.1
by Facundo Batista
Use simple authentication against the server. |
1789 |
self.unthrottleWritesID is None |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1790 |
if should_check: |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1791 |
self.throttleWrites() |
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1792 |
throttle_time = self._get_throttle_time(self.writtenThisSecond, |
164.1.1
by Facundo Batista
Use simple authentication against the server. |
1793 |
self.writeLimit) |
83.2.4
by guillermo.gonzalez at canonical
Don't allow setting throttling limits to 0 |
1794 |
log_debug("pause writes for: %s", str(throttle_time)) |
1795 |
self.unthrottleWritesID = self.maybeCallLater( |
|
1796 |
'unthrottleWritesID', throttle_time, self.unthrottleWrites) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1797 |
|
1798 |
def _resetReadThisSecond(self): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1799 |
"""Reset the counter named with 'name' every 1 second."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1800 |
# check the bandwidth limits
|
1801 |
self.readThisSecond = 0 |
|
164.1.1
by Facundo Batista
Use simple authentication against the server. |
1802 |
self.resetReadThisSecondID = self.callLater( |
1803 |
1, self._resetReadThisSecond) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1804 |
|
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
1805 |
def _resetWrittenThisSecond(self): |
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1806 |
"""Reset the counter named with 'name' every 1 second."""
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1807 |
self.writtenThisSecond = 0 |
121.1.1
by Rodney Dawes
Remove contrib contents and pylintrc |
1808 |
self.resetWriteThisSecondID = self.callLater( |
1809 |
1, self._resetWrittenThisSecond) |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1810 |
|
1811 |
def throttleReads(self): |
|
1812 |
"""Throttle reads on all protocols."""
|
|
1813 |
if self.client is not None: |
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1814 |
self._throttling_reads = True |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1815 |
self.client.throttleReads() |
1816 |
||
1817 |
def unthrottleReads(self): |
|
1818 |
"""Stop throttling reads on all protocols."""
|
|
1819 |
self.unthrottleReadsID = None |
|
1820 |
if self.client is not None: |
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1821 |
self._throttling_reads = False |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1822 |
self.client.unthrottleReads() |
1823 |
||
1824 |
def throttleWrites(self): |
|
1825 |
"""Throttle writes on all protocols."""
|
|
1826 |
if self.client is not None: |
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1827 |
self._throttling_writes = True |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1828 |
self.client.throttleWrites() |
1829 |
||
1830 |
def unthrottleWrites(self): |
|
1831 |
"""Stop throttling writes on all protocols."""
|
|
1832 |
self.unthrottleWritesID = None |
|
1833 |
if self.client is not None: |
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1834 |
self._throttling_writes = False |
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1835 |
self.client.unthrottleWrites() |
1836 |
||
1837 |
def buildProtocol(self, addr): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1838 |
"""Build the protocol and start the counters reset loops."""
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1839 |
if self.throttling_enabled: |
1840 |
self.enable_throttling() |
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1841 |
self.stopped = False |
1842 |
return StorageClientFactory.buildProtocol(self, addr) |
|
1843 |
||
1844 |
def unregisterProtocol(self, protocol): |
|
78.1.14
by natalia.bidart at canonical
Fixed all dosctrings. |
1845 |
"""Stop all DelayedCall we have around."""
|
65.1.1
by guillermo.gonzalez at canonical
allow set the read/write limit in the throttling factory after it creation |
1846 |
for delayed in [self.unthrottleReadsID, self.resetReadThisSecondID, |
1847 |
self.unthrottleWritesID, self.resetWriteThisSecondID]: |
|
65.1.3
by guillermo.gonzalez at canonical
remove set/get for limits and move delayed cancelation to it's own method |
1848 |
self._cancel_delayed_call(delayed) |
1849 |
||
1850 |
def _cancel_delayed_call(self, delayed): |
|
1851 |
"""Safely cancel a DelayedCall."""
|
|
1852 |
if delayed is not None and not delayed.cancelled \ |
|
1853 |
and delayed.active(): |
|
1854 |
try: |
|
1855 |
delayed.cancel() |
|
1856 |
except defer.AlreadyCalledError: |
|
1857 |
# ignore AlreadyCalledError
|
|
1858 |
pass
|
|
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1859 |
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1860 |
def enable_throttling(self): |
1861 |
"""Enable throttling and start the counter reset loops."""
|
|
1862 |
# check if we need to start the reset loops
|
|
1863 |
if self.resetReadThisSecondID is None and \ |
|
1864 |
self.valid_limit(self.readLimit): |
|
1865 |
self._resetReadThisSecond() |
|
1866 |
if self.resetWriteThisSecondID is None and \ |
|
1867 |
self.valid_limit(self.writeLimit): |
|
1868 |
self._resetWrittenThisSecond() |
|
1869 |
self.throttling_enabled = True |
|
1870 |
||
1871 |
def disable_throttling(self): |
|
1872 |
"""Disable throttling and cancel the counter reset loops."""
|
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1873 |
# unthrottle if there is an active unthrottle*ID
|
1874 |
self._cancel_delayed_call(self.unthrottleReadsID) |
|
1875 |
self._cancel_delayed_call(self.unthrottleWritesID) |
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1876 |
# Stop the reset loops
|
1877 |
self._cancel_delayed_call(self.resetReadThisSecondID) |
|
1878 |
self._cancel_delayed_call(self.resetWriteThisSecondID) |
|
83.2.3
by guillermo.gonzalez at canonical
add a flag to keep track of throttling read/write status |
1879 |
# unthrottle read/writes
|
1880 |
if self._throttling_reads: |
|
1881 |
self.unthrottleReads() |
|
1882 |
if self._throttling_writes: |
|
1883 |
self.unthrottleWrites() |
|
83.2.2
by guillermo.gonzalez at canonical
moved configurable throttling factory from ubuntuone-client |
1884 |
self.throttling_enabled = False |
1885 |
||
64.1.1
by guillermo.gonzalez at canonical
throttling factory and protocol |
1886 |
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1887 |
if __name__ == "__main__": |
1888 |
# these 3 lines show the different ways of connecting a client to the
|
|
1889 |
# server
|
|
1890 |
||
1891 |
# using tcp
|
|
1892 |
reactor.connectTCP('localhost', 20100, StorageClientFactory()) |
|
1893 |
||
1894 |
# using ssl
|
|
166.1.2
by Facundo Batista
Aesthetic details. |
1895 |
# reactor.connectSSL('localhost', 20101, StorageClientFactory(),
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1896 |
# ssl.ClientContextFactory())
|
1897 |
||
1898 |
# using ssl over a proxy
|
|
166.1.2
by Facundo Batista
Aesthetic details. |
1899 |
# from ubuntuone.storageprotocol import proxy_tunnel
|
1900 |
# proxy_tunnel.connectHTTPS('localhost', 3128,
|
|
2
by Rodney Dawes
Import the ubuntuone-storage-protocol code |
1901 |
# 'localhost', 20101, StorageClientFactory(),
|
1902 |
# user="test", passwd="test")
|
|
1903 |
||
1904 |
reactor.run() |