aeb24aeb10ddceea6f0fa8f6c419a2c63083a6e9
[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 from __future__ import division, print_function, unicode_literals
26
27 try:
28     import configparser
29 except ImportError:
30     import ConfigParser as configparser
31 import datetime
32 import re
33
34 from cumulus import retention
35
36 _BACKUP_PREFIX = "backup:"
37 _TIME_UNITS = {"s": 1, "m": 60, "h": 3600, "D": 86400, "W": 7 * 86400,
38                "M": 30 * 86400, "Y": 365 * 86400}
39 _INTERVAL_RE = r"(\d+)([smhDWMY])"
40
41 def _build_retention_engine(spec):
42     """Parse a retention specification and return a RetentionEngine object."""
43     policy = retention.RetentionEngine()
44     class_re = re.compile(r"^(\w+):((%s)+)$" % _INTERVAL_RE)
45     interval_re = re.compile(r"^%s(.*)$" % _INTERVAL_RE)
46     for s in spec.split():
47         m = class_re.match(s)
48         if not m:
49             print("Invalid retain spec:", s)
50             continue
51         period = datetime.timedelta()
52         classname = m.group(1)
53         intervalspec = m.group(2)
54         while intervalspec:
55             m = interval_re.match(intervalspec)
56             seconds = int(m.group(1)) * _TIME_UNITS[m.group(2)]
57             period = period + datetime.timedelta(seconds=seconds)
58             intervalspec = m.group(3)
59         policy.add_policy(classname, period)
60     return policy
61
62
63 class CumulusConfig(object):
64     def __init__(self, filename):
65         """Parse a Cumulus backup configuration from the specified file."""
66         self._config = configparser.RawConfigParser()
67         self._config.readfp(open(filename))
68
69     def get_global(self, key):
70         return self._config.get("global", key)
71
72     def backup_schemes(self):
73         """Returns a list of backup schemes."""
74         return [s[len(_BACKUP_PREFIX):] for s in self._config.sections()
75                 if s.startswith(_BACKUP_PREFIX)]
76
77     def get_retention_for_scheme(self, scheme):
78         spec = self._config.get(_BACKUP_PREFIX + scheme, "retain")
79         return _build_retention_engine(spec)