1 # Cumulus: Efficient Filesystem Backup to the Cloud
2 # Copyright (C) 2008-2010 The Cumulus Developers
3 # See the AUTHORS file for a list of contributors.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 from __future__ import division, print_function, unicode_literals
25 from urllib import parse as urlparse
26 from urllib.parse import quote, unquote
29 from urllib import quote, unquote
33 'checksums': re.compile(r"^snapshot-(.*)\.(\w+)sums$"),
34 'segments': re.compile(r"^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(\.\S+)?$"),
35 'snapshots': re.compile(r"^snapshot-(.*)\.(cumulus|lbs)$")
38 class NotFoundError(KeyError):
39 """Exception thrown when a file is not found in a repository."""
44 """Base class for all cumulus storage backends."""
46 def __init__(self, url):
47 """Initializes a new storage backend.
50 url: The parsed (by urlsplit) URL that specifies the storage
55 # TODO: Implement context manager.
58 raise NotImplementedError
61 raise NotImplementedError
63 def put(self, path, fp):
64 raise NotImplementedError
66 def delete(self, path):
67 raise NotImplementedError
70 raise NotImplementedError
73 """Cache file information stored in this backend.
75 This might make subsequent list or stat calls more efficient, but this
76 function is intended purely as a performance optimization."""
81 """Tear down the connection explicitly if needed
83 Currently needed for sftp to be able to end the program."""
91 """Parse a storage url, then locate and initialize a backend for it."""
92 parsed_url = urlparse.urlsplit(url)
94 # If there is no scheme, fall back to treating the string as local path and
95 # construct a file:/// URL.
96 if not parsed_url.scheme:
97 parsed_url = urlparse.SplitResult("file", "", quote(url), "", "")
100 # TODO: Support a registry for schemes that don't map to a module.
101 if re.match(r"^\w+$", parsed_url.scheme):
102 handler = importlib.import_module("cumulus.store.%s" %
104 obj = handler.Store(parsed_url)
107 # Fall through to error below
110 raise NotImplementedError("Scheme %s not implemented" % scheme)