Improve tracking of segments and segment utilization.
[cumulus.git] / python / cumulus / config.py
1 # Cumulus: Efficient Filesystem Backup to the Cloud
2 # Copyright (C) 2012 The Cumulus Developers
3 # See the AUTHORS file for a list of contributors.
4 #
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.
9 #
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.
14 #
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.
18
19 """Parsing of Cumulus backup configuration files.
20
21 See the Cumulus documentation for a description of the configuration file
22 format.
23 """
24
25 import ConfigParser
26 import datetime
27 import re
28
29 from cumulus import retention
30
31 _BACKUP_PREFIX = "backup:"
32 _TIME_UNITS = {"s": 1, "m": 60, "h": 3600, "D": 86400, "W": 7 * 86400,
33                "M": 30 * 86400, "Y": 365 * 86400}
34 _INTERVAL_RE = r"(\d+)([smhDWMY])"
35
36 def _build_retention_engine(spec):
37     """Parse a retention specification and return a RetentionEngine object."""
38     policy = retention.RetentionEngine()
39     class_re = re.compile(r"^(\w+):((%s)+)$" % _INTERVAL_RE)
40     interval_re = re.compile(r"^%s(.*)$" % _INTERVAL_RE)
41     for s in spec.split():
42         m = class_re.match(s)
43         if not m:
44             print "Invalid retain spec:", s
45             continue
46         period = datetime.timedelta()
47         classname = m.group(1)
48         intervalspec = m.group(2)
49         while intervalspec:
50             m = interval_re.match(intervalspec)
51             seconds = int(m.group(1)) * _TIME_UNITS[m.group(2)]
52             period = period + datetime.timedelta(seconds=seconds)
53             intervalspec = m.group(3)
54         policy.add_policy(classname, period)
55     return policy
56
57
58 class CumulusConfig(object):
59     def __init__(self, filename):
60         """Parse a Cumulus backup configuration from the specified file."""
61         self._config = ConfigParser.RawConfigParser()
62         self._config.readfp(open(filename))
63
64     def get_global(self, key):
65         return self._config.get("global", key)
66
67     def backup_schemes(self):
68         """Returns a list of backup schemes."""
69         return [s[len(_BACKUP_PREFIX):] for s in self._config.sections()
70                 if s.startswith(_BACKUP_PREFIX)]
71
72     def get_retention_for_scheme(self, scheme):
73         spec = self._config.get(_BACKUP_PREFIX + scheme, "retain")
74         return _build_retention_engine(spec)