Refactoring: Moved check parameters from unsorted.py to dedicated modules (CMK-1393)
[check_mk.git] / cmk_base / backup.py
blob91f88c7d0822c3048843d421036944447468533e
1 #!/usr/bin/env python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
26 """ Check_MK comes with a simple backup and restore of the current
27 configuration and cache files (cmk --backup and cmk --restore). This
28 is implemented here. """
30 import os
31 import shutil
32 import tarfile
33 import time
34 import cStringIO as StringIO
36 import cmk.utils.paths
37 import cmk.utils.render as render
38 from cmk.utils.exceptions import MKGeneralException
40 import cmk_base.console as console
43 def backup_paths():
44 # TODO: Refactor to named tuples
45 # yapf: disable
46 return [
47 # tarname path canonical name description is_dir
48 ('check_mk_configfile', cmk.utils.paths.main_config_file, "main.mk", "Main configuration file", False, ),
49 ('final_mk', cmk.utils.paths.final_config_file, "final.mk", "Final configuration file final.mk", False, ),
50 ('check_mk_configdir', cmk.utils.paths.check_mk_config_dir, "", "Configuration sub files", True, ),
51 ('autochecksdir', cmk.utils.paths.autochecks_dir, "", "Automatically inventorized checks", True, ),
52 ('counters_directory', cmk.utils.paths.counters_dir, "", "Performance counters", True, ),
53 ('tcp_cache_dir', cmk.utils.paths.tcp_cache_dir, "", "Agent cache", True, ),
54 ('logwatch_dir', cmk.utils.paths.logwatch_dir, "", "Logwatch", True, ),
56 # yapf: enable
59 def do_backup(tarname):
60 console.verbose("Creating backup file '%s'...\n", tarname)
61 tar = tarfile.open(tarname, "w:gz")
63 for name, path, canonical_name, descr, is_dir, in backup_paths():
65 absdir = os.path.abspath(path)
66 if os.path.exists(path):
67 if is_dir:
68 subtarname = name + ".tar"
69 subfile = StringIO.StringIO()
70 subtar = tarfile.open(mode="w", fileobj=subfile, dereference=True)
71 subtar.add(path, arcname=".")
72 subdata = subfile.getvalue()
73 else:
74 subtarname = canonical_name
75 subdata = file(absdir).read()
77 info = tarfile.TarInfo(subtarname)
78 info.mtime = time.time()
79 info.uid = 0
80 info.gid = 0
81 info.size = len(subdata)
82 info.mode = 0644
83 info.type = tarfile.REGTYPE
84 info.name = subtarname
85 console.verbose(" Added %s (%s) with a size of %s\n", descr, absdir,
86 render.fmt_bytes(info.size))
87 tar.addfile(info, StringIO.StringIO(subdata))
89 tar.close()
90 console.verbose("Successfully created backup.\n")
93 def do_restore(tarname):
94 console.verbose("Restoring from '%s'...\n", tarname)
96 if not os.path.exists(tarname):
97 raise MKGeneralException("Unable to restore: File does not exist")
99 for name, path, canonical_name, descr, is_dir in backup_paths():
100 absdir = os.path.abspath(path)
101 if is_dir:
102 basedir = absdir
103 filename = "."
104 if os.path.exists(absdir):
105 console.verbose(" Deleting old contents of '%s'\n", absdir)
106 # The path might point to a symbalic link. So it is no option
107 # to call shutil.rmtree(). We must delete just the contents
108 for f in os.listdir(absdir):
109 if f not in ['.', '..']:
110 try:
111 p = absdir + "/" + f
112 if os.path.isdir(p):
113 shutil.rmtree(p)
114 else:
115 os.remove(p)
116 except Exception as e:
117 console.warning(" Cannot delete %s: %s", p, e)
118 else:
119 basedir = os.path.dirname(absdir)
120 filename = os.path.basename(absdir)
121 canonical_path = basedir + "/" + canonical_name
122 if os.path.exists(canonical_path):
123 console.verbose(" Deleting old version of '%s'\n", canonical_path)
124 os.remove(canonical_path)
126 if not os.path.exists(basedir):
127 console.verbose(" Creating directory %s\n", basedir)
128 os.makedirs(basedir)
130 console.verbose(" Extracting %s (%s)\n", descr, absdir)
131 tar = tarfile.open(tarname, "r:gz")
132 if is_dir:
133 subtar = tarfile.open(fileobj=tar.extractfile(name + ".tar"))
134 if filename == ".":
135 subtar.extractall(basedir)
136 elif filename in subtar.getnames():
137 subtar.extract(filename, basedir)
138 subtar.close()
139 elif filename in tar.getnames():
140 tar.extract(filename, basedir)
141 tar.close()
143 console.verbose("Successfully restored backup.\n")