72
69
self.cloudfiles = pyrax.cloudfiles
73
70
self.container = pyrax.cloudfiles.create_container(container)
75
def put(self, source_path, remote_filename = None):
76
if not remote_filename:
77
remote_filename = source_path.get_filename()
79
for n in range(1, globals.num_retries + 1):
80
log.Info("Uploading '%s/%s' " % (self.container, remote_filename))
82
self.container.upload_file(source_path.name, remote_filename)
84
except self.client_exc as error:
85
log.Warn("Upload of '%s' failed (attempt %d): pyrax returned: %s %s"
86
% (remote_filename, n, error.__class__.__name__, error.message))
87
except Exception as e:
88
log.Warn("Upload of '%s' failed (attempt %s): %s: %s"
89
% (remote_filename, n, e.__class__.__name__, str(e)))
90
log.Debug("Backtrace of previous error: %s"
91
% exception_traceback())
93
log.Warn("Giving up uploading '%s' after %s attempts"
94
% (remote_filename, globals.num_retries))
95
raise BackendException("Error uploading '%s'" % remote_filename)
97
def get(self, remote_filename, local_path):
98
for n in range(1, globals.num_retries + 1):
99
log.Info("Downloading '%s/%s'" % (self.container, remote_filename))
101
sobject = self.container.get_object(remote_filename)
102
f = open(local_path.name, 'w')
72
def _error_code(self, e):
73
if isinstance(e, self.client_exc):
75
return log.ErrorCode.backend_not_found
77
def _put(self, source_path, remote_filename):
78
self.container.upload_file(source_path.name, remote_filename)
80
def _get(self, remote_filename, local_path):
82
sobject = self.container.get_object(remote_filename)
83
with open(local_path.name, 'wb') as f:
103
84
f.write(sobject.get())
108
except self.client_exc as resperr:
109
log.Warn("Download of '%s' failed (attempt %s): pyrax returned: %s %s"
110
% (remote_filename, n, resperr.__class__.__name__, resperr.message))
111
except Exception as e:
112
log.Warn("Download of '%s' failed (attempt %s): %s: %s"
113
% (remote_filename, n, e.__class__.__name__, str(e)))
114
log.Debug("Backtrace of previous error: %s"
115
% exception_traceback())
117
log.Warn("Giving up downloading '%s' after %s attempts"
118
% (remote_filename, globals.num_retries))
119
raise BackendException("Error downloading '%s/%s'"
120
% (self.container, remote_filename))
123
for n in range(1, globals.num_retries + 1):
124
log.Info("Listing '%s'" % (self.container))
126
# Cloud Files will return a max of 10,000 objects. We have
127
# to make multiple requests to get them all.
128
objs = self.container.get_object_names()
130
while len(objs) == 10000:
131
objs = self.container.get_object_names(marker = keys[-1])
134
except self.client_exc as resperr:
135
log.Warn("Listing of '%s' failed (attempt %s): pyrax returned: %s %s"
136
% (self.container, n, resperr.__class__.__name__, resperr.message))
137
except Exception as e:
138
log.Warn("Listing of '%s' failed (attempt %s): %s: %s"
139
% (self.container, n, e.__class__.__name__, str(e)))
140
log.Debug("Backtrace of previous error: %s"
141
% exception_traceback())
143
log.Warn("Giving up listing of '%s' after %s attempts"
144
% (self.container, globals.num_retries))
145
raise BackendException("Error listing '%s'"
148
def delete_one(self, remote_filename):
149
for n in range(1, globals.num_retries + 1):
150
log.Info("Deleting '%s/%s'" % (self.container, remote_filename))
152
self.container.delete_object(remote_filename)
154
except self.client_exc as resperr:
155
if n > 1 and resperr.status == 404:
156
# We failed on a timeout, but delete succeeded on the server
157
log.Warn("Delete of '%s' missing after retry - must have succeded earler" % remote_filename)
159
log.Warn("Delete of '%s' failed (attempt %s): pyrax returned: %s %s"
160
% (remote_filename, n, resperr.__class__.__name__, resperr.message))
161
except Exception as e:
162
log.Warn("Delete of '%s' failed (attempt %s): %s: %s"
163
% (remote_filename, n, e.__class__.__name__, str(e)))
164
log.Debug("Backtrace of previous error: %s"
165
% exception_traceback())
167
log.Warn("Giving up deleting '%s' after %s attempts"
168
% (remote_filename, globals.num_retries))
169
raise BackendException("Error deleting '%s/%s'"
170
% (self.container, remote_filename))
172
def delete(self, filename_list):
173
for file_ in filename_list:
174
self.delete_one(file_)
175
log.Debug("Deleted '%s/%s'" % (self.container, file_))
178
def _query_file_info(self, filename, raise_errors = False):
89
# Cloud Files will return a max of 10,000 objects. We have
90
# to make multiple requests to get them all.
91
objs = self.container.get_object_names()
93
while len(objs) == 10000:
94
objs = self.container.get_object_names(marker = keys[-1])
98
def _delete(self, filename):
99
self.container.delete_object(filename)
101
def _query(self, filename):
180
103
sobject = self.container.get_object(filename)
181
104
return {'size': sobject.total_bytes}
182
105
except self.nso_exc:
183
106
return {'size': -1}
184
except Exception as e:
185
log.Warn("Error querying '%s/%s': %s"
186
"" % (self.container,
192
return {'size': None}
194
108
duplicity.backend.register_backend("cf+http", PyraxBackend)