Skip to content

Commit 99e7784

Browse files
Got rpmbuilds working again, made it much simpler. Add log support
1 parent 126c79d commit 99e7784

File tree

7 files changed

+140
-30
lines changed

7 files changed

+140
-30
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
bin
22
build
3-
rpmbuild
43
tmp
54
*.pyc
65
.idea

Makefile

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,24 @@ install: bin/mongodb-consistent-backup
1818
rm -rf bin build 2>/dev/null
1919
mkdir -p $(BINDIR) $(SHAREDIR)/$(NAME) || true
2020
install -m 0755 bin/mongodb-consistent-backup $(BINDIR)/mongodb-consistent-backup
21-
install -m 0644 conf/example.yml $(SHAREDIR)/$(NAME)/example.yml
21+
install -m 0644 conf/mongodb-consistent-backup.example.yml $(SHAREDIR)/$(NAME)/example.yml
2222
install -m 0644 LICENSE $(SHAREDIR)/$(NAME)/LICENSE
2323
install -m 0644 README.rst $(SHAREDIR)/$(NAME)/README.rst
2424

2525
uninstall:
2626
rm -f $(BINDIR)/mongodb-consistent-backup
2727
rm -rf $(SHAREDIR)/$(NAME)
2828

29-
rpm: clean
30-
mkdir -p rpmbuild/{SPECS,SOURCES/$(NAME)}
31-
cp -dpR $(NAME) conf Makefile setup.py scripts requirements.txt LICENSE README.rst VERSION rpmbuild/SOURCES/$(NAME)
32-
install scripts/$(NAME).spec rpmbuild/SPECS/$(NAME).spec
33-
tar --remove-files -C rpmbuild/SOURCES -czf rpmbuild/SOURCES/$(NAME).tar.gz $(NAME)
34-
rpmbuild -D "_topdir $(PWD)/rpmbuild" -D "version $(VERSION)" -bb rpmbuild/SPECS/$(NAME).spec
29+
rpm: bin/mongodb-consistent-backup
30+
rm -rf build/rpm 2>/dev/null || true
31+
mkdir -p build/rpm/SOURCES
32+
cp -f $(PWD)/{LICENSE,README.rst} build/rpm/SOURCES
33+
cp -f $(PWD)/bin/mongodb-consistent-backup build/rpm/SOURCES/mongodb-consistent-backup
34+
cp -f $(PWD)/conf/mongodb-consistent-backup.example.yml build/rpm/SOURCES/mongodb-consistent-backup.yml
35+
rpmbuild -D "_topdir $(PWD)/build/rpm" -D "version $(VERSION)" -bb scripts/$(NAME).spec
3536

3637
docker:
3738
docker build --no-cache -t mongodb_consistent_backup .
3839

3940
clean:
40-
rm -rf bin build rpmbuild $(NAME).egg-info tmp 2>/dev/null
41+
rm -rf bin build $(NAME).egg-info tmp 2>/dev/null

conf/mongodb-consistent-backup.example.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ production:
44
#username:
55
#password:
66
#authdb: admin
7+
log: /tmp/mongodb_consistent_backup.log
78
backup:
89
method: mongodump
9-
name: test
10+
name: default
1011
location: /opt/mongodb/backup
1112
mongodump:
1213
binary: /usr/bin/mongodump

mongodb_consistent_backup/Common/Config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ def makeParser(self):
4343
parser.add_argument("-n", "--backup.name", dest="backup.name", help="Name of the backup set (required)", type=str)
4444
parser.add_argument("-l", "--backup.location", dest="backup.location", help="Base path to store the backup data (required)", type=str)
4545
parser.add_argument("-m", "--backup.method", dest="backup.method", help="Method to be used for backup (default: mongodump)", default='mongodump', choices=['mongodump'])
46-
parser.add_argument("--lockfile", dest="lockfile", help="Location of lock file (default: /tmp/mongodb_consistent_backup.lock)", default='/tmp/mongodb_consistent_backup.lock', type=str)
46+
parser.add_argument("-L", "--log-dir", dest="log_dir", help="Path to write log files to (default: disabled)", default='', type=str)
47+
parser.add_argument("--lock-file", dest="lock_file", help="Location of lock file (default: /tmp/mongodb_consistent_backup.lock)", default='/tmp/mongodb_consistent_backup.lock', type=str)
4748
parser.add_argument("--sharding.balancer.wait_secs", dest="sharding.balancer.wait_secs", help="Maximum time to wait for balancer to stop, in seconds (default: 300)", default=300, type=int)
4849
parser.add_argument("--sharding.balancer.ping_secs", dest="sharding.balancer.ping_secs", help="Interval to check balancer state, in seconds (default: 3)", default=3, type=int)
4950
return parser
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import logging
2+
import os
3+
4+
from gzip import GzipFile
5+
6+
7+
class Logger:
8+
def __init__(self, config, backup_time):
9+
self.config = config
10+
self.backup_time = backup_time
11+
12+
self.log_level = logging.INFO
13+
if self.config.verbose:
14+
self.log_level = logging.DEBUG
15+
16+
self.do_file_log = False
17+
if self.config.log_dir is not '':
18+
if os.path.isdir(self.config.log_dir):
19+
self.do_file_log = True
20+
else:
21+
print("ERROR: Log directory: %s does not exist! Skipping file-based logging" % self.config.log_dir)
22+
23+
self.log_format = '[%(asctime)s] [%(levelname)s] [%(processName)s] [%(module)s:%(funcName)s:%(lineno)d] %(message)s'
24+
self.file_log = None
25+
self.last_log = None
26+
27+
def start(self):
28+
try:
29+
logging.basicConfig(level=self.log_level, format=self.log_format)
30+
if self.do_file_log:
31+
self.current_log_file = os.path.join(self.config.log_dir, "backup.log")
32+
self.backup_log_file = os.path.join(self.config.log_dir, "backup.%s.log" % self.backup_time)
33+
self.file_log = logging.FileHandler(self.backup_log_file)
34+
self.file_log.setLevel(self.log_level)
35+
self.file_log.setFormatter(logging.Formatter(self.log_format))
36+
logging.getLogger('').addHandler(self.file_log)
37+
except OSError, e:
38+
logging.warning("Could not start file log handler, writing to stdout only")
39+
pass
40+
41+
def close(self):
42+
if self.file_log:
43+
self.file_log.close()
44+
45+
def compress_last(self):
46+
gz_log = None
47+
try:
48+
if not os.path.isfile(self.last_log):
49+
return
50+
gz_file = "%s.gz" % self.last_log
51+
gz_log = GzipFile(gz_file, "w+")
52+
with open(self.last_log) as f:
53+
for line in f:
54+
gz_log.write(line)
55+
os.remove(self.last_log)
56+
finally:
57+
if gz_log:
58+
gz_log.close()
59+
60+
def rotate(self):
61+
if self.do_file_log:
62+
if os.path.islink(self.current_log_file):
63+
logging.info("Rotating previous log file")
64+
self.last_log = os.readlink(self.current_log_file)
65+
if self.last_log == self.backup_log_file:
66+
return
67+
os.remove(self.current_log_file)
68+
self.compress_last()
69+
os.symlink(self.backup_log_file, self.current_log_file)

mongodb_consistent_backup/Main.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from Backup import Backup
1111
from Common import Config, DB, Lock, MongoUri, Timer
1212
from Errors import Error, NotifyError, OperationError
13+
from Logger import Logger
1314
from Notify import Notify
1415
from Oplog import Tailer, Resolver
1516
from Replication import Replset, ReplsetSharded
@@ -44,6 +45,10 @@ def __init__(self, prog_name="mongodb-consistent-backup"):
4445
self.manager = Manager()
4546
self.timer = Timer(self.manager)
4647
self.timer_name = "mongodb_consistent_backup.%s" % self.__class__.__name__
48+
self.backup_time = datetime.now().strftime("%Y%m%d_%H%M")
49+
self.logger = None
50+
self.current_log_file = None
51+
self.backup_log_file = None
4752

4853
try:
4954
self.setup_config()
@@ -65,11 +70,11 @@ def setup_config(self):
6570
sys.exit(1)
6671

6772
def setup_logger(self):
68-
self.log_level = logging.INFO
69-
if self.config.verbose:
70-
self.log_level = logging.DEBUG
71-
logging.basicConfig(level=self.log_level,
72-
format='[%(asctime)s] [%(levelname)s] [%(processName)s] [%(module)s:%(funcName)s:%(lineno)d] %(message)s')
73+
try:
74+
self.logger = Logger(self.config, self.backup_time)
75+
self.logger.start()
76+
except Exception, e:
77+
self.exception("Could not start logger: %s" % e, e)
7378

7479
def setup_signal_handlers(self):
7580
try:
@@ -80,7 +85,6 @@ def setup_signal_handlers(self):
8085
sys.exit(1)
8186

8287
def set_backup_dirs(self):
83-
self.backup_time = datetime.now().strftime("%Y%m%d_%H%M")
8488
self.backup_root_directory = os.path.join(self.config.backup.location, self.config.backup.name)
8589
self.backup_latest_symlink = os.path.join(self.backup_root_directory, "latest")
8690
self.backup_previous_symlink = os.path.join(self.backup_root_directory, "previous")
@@ -107,11 +111,11 @@ def get_db_conn(self):
107111
def get_lock(self):
108112
# noinspection PyBroadException
109113
try:
110-
if not self.config.lockfile:
111-
self.config.lockfile = '/tmp/%s.lock' % self.program_name
112-
self.lock = Lock(self.config.lockfile)
114+
if not self.config.lock_file:
115+
self.config.lock_file = '/tmp/%s.lock' % self.program_name
116+
self.lock = Lock(self.config.lock_file)
113117
except Exception:
114-
logging.fatal("Could not acquire lock: '%s'! Is another %s process running? Exiting" % (self.config.lockfile, self.program_name))
118+
logging.fatal("Could not acquire lock: '%s'! Is another %s process running? Exiting" % (self.config.lock_file, self.program_name))
115119
self.cleanup_and_exit(None, None)
116120

117121
def release_lock(self):
@@ -180,6 +184,11 @@ def cleanup_and_exit(self, code, frame):
180184
self.db.close()
181185

182186
logging.info("Cleanup complete, exiting")
187+
188+
if self.logger:
189+
self.logger.rotate()
190+
self.logger.close()
191+
183192
self.release_lock()
184193
sys.exit(1)
185194

@@ -448,4 +457,6 @@ def run(self):
448457
self.update_symlinks()
449458
logging.info("Completed %s in %.2f sec" % (self.program_name, self.timer.duration(self.timer_name)))
450459

460+
self.logger.rotate()
461+
self.logger.close()
451462
self.release_lock()

scripts/mongodb_consistent_backup.spec

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
%define debug_package %{nil}
22
%define bin_name mongodb-consistent-backup
3+
%define log_dir /var/log/mongodb-consistent-backup
4+
%define data_dir /var/lib/mongodb-consistent-backup
5+
%define run_user mongodb_consistent_backup
6+
%define run_group mongodb_consistent_backup
37

48
Name: mongodb_consistent_backup
59
Version: %{version}
@@ -9,7 +13,10 @@ Summary: MongoDB Consistent Backup Tool
913
Group: Software/Database
1014
License: Apache License Version 2.0
1115
URL: https://github.com/Percona-Lab/mongodb_consistent_backup
12-
Source: %{name}.tar.gz
16+
Source0: %{bin_name}
17+
Source1: %{bin_name}.yml
18+
Source2: LICENSE
19+
Source3: README.rst
1320
Prefix: /usr
1421

1522
# Use CentOS SCL python27 (https://www.softwarecollections.org/en/scls/rhscl/python27/) on CentOS 6 (RHEL6 untested)
@@ -27,23 +34,44 @@ Prefix: /usr
2734
Tool for getting consistent backups from MongoDB Clusters and ReplicaSet
2835

2936

30-
%prep
31-
%setup -q -n %{name}
37+
%install
38+
mkdir -p %{buildroot}%{_sysconfdir}/cron.d %{buildroot}%{prefix}/bin %{buildroot}/usr/share/%{name}
3239

40+
install -m 0755 %{SOURCE0} %{buildroot}%{prefix}/bin/%{bin_name}
41+
install -m 0644 %{SOURCE1} %{buildroot}/usr/share/%{name}/%{bin_name}.example.yml
42+
install -m 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/%{bin_name}.yml
43+
install -m 0644 %{SOURCE2} %{buildroot}/usr/share/%{name}/LICENSE
44+
install -m 0644 %{SOURCE3} %{buildroot}/usr/share/%{name}/README.rst
3345

34-
%build
35-
make
3646

47+
# Generate cron.d file:
48+
%{__cat} <<EOF >%{buildroot}%{_sysconfdir}/cron.d/%{name}
49+
### Uncomment and adjust time to enable backups (default time below is 00:00 every day):
50+
#
51+
#0 0 * * * %{run_user} /usr/bin/mongodb-consistent-backup --config=/etc/mongodb-consistent-backup.yml >/dev/null 2>&1
52+
EOF
53+
54+
# Change /etc config file to use rpm paths for logs and data
55+
sed -i \
56+
-e s@/tmp/mongodb_consistent_backup.log@%{log_dir}/mongodb-consistent-backup.log@g \
57+
-e s@/opt/mongodb/backup@%{data_dir}@g \
58+
%{buildroot}%{_sysconfdir}/%{bin_name}.yml
59+
60+
61+
%pre
62+
/usr/bin/getent group %{run_group} >/dev/null 2>&1 || /usr/sbin/groupadd -r %{run_group}
63+
/usr/bin/getent passwd %{run_user} >/dev/null 2>&1 || /usr/sbin/useradd -r -d %{data_dir} -g %{run_group} -s /sbin/nologin %{run_user}
3764

38-
%install
39-
mkdir -p %{buildroot}%{_sysconfdir}
40-
install -m 0644 conf/mongodb-consistent-backup.example.yml %{buildroot}%{_sysconfdir}/%{bin_name}.yml
4165

42-
make PREFIX=%{prefix} DESTDIR=%{buildroot} install
66+
%post
67+
[ ! -d %{data_dir} ] && mkdir -m 0750 -p %{data_dir}
68+
[ ! -d %{log_dir} ] && mkdir -m 0755 -p %{log_dir}
69+
chown %{run_user}:%{run_group} %{data_dir} %{log_dir}
4370

4471

4572
%files
4673
%{_sysconfdir}/%{bin_name}.yml
74+
%{_sysconfdir}/cron.d/%{name}
4775
%{prefix}/bin/%{bin_name}
4876
%{prefix}/share/%{name}/%{bin_name}.example.yml
4977
%{prefix}/share/%{name}/LICENSE

0 commit comments

Comments
 (0)