Skip to content

Commit

Permalink
Write periodic backup scheduler
Browse files Browse the repository at this point in the history
  • Loading branch information
aknuds1 committed Jan 5, 2016
1 parent da873f6 commit 666fb26
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 27 deletions.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*]
indent_style = space
end_of_line = lf
insert_final_newline = true
max_line_length = 79

[*.py]
indent_size = 4
11 changes: 5 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
FROM debian
MAINTAINER "MuzHack" <[email protected]>

RUN apt-get update && apt-get install -y cron python3 python3-pip lsb-release wget
RUN apt-get update && apt-get install -y python3 python3-pip lsb-release wget
RUN echo "deb http://download.rethinkdb.com/apt `lsb_release -cs` main" | tee /etc/apt/sources.list.d/rethinkdb.list
RUN wget -qO- https://download.rethinkdb.com/apt/pubkey.gpg | apt-key add -
RUN apt-get update && apt-get install -y rethinkdb
RUN apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

WORKDIR /app
COPY ./crontab /etc/cron.d/
COPY ./requirements.txt /app/
RUN mkdir -p /app/rethinkdb
COPY ./rethinkdb/backup.py /app/rethinkdb/

COPY ./requirements.txt /app/
RUN pip3 install -r requirements.txt
RUN rm -rf requirements.txt

CMD python3 cron.py
COPY ./schedule-rethinkdb-backup.py /app/

CMD python3 schedule-rethinkdb-backup.py
16 changes: 10 additions & 6 deletions rethinkdb/backup.py → backup-rethinkdb.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
"""Script to back up RethinkDB either locally or remotely to S3."""
import subprocess
import argparse
import os.path
Expand All @@ -24,10 +25,11 @@ def _get_environment_value(key):
return value


parser = argparse.ArgumentParser(description='Back up local RethinkDB instance')
parser = argparse.ArgumentParser(
description='Back up local RethinkDB instance')
parser.add_argument('--s3-bucket', default=None, help='Specify S3 bucket')
parser.add_argument('--remove', action='store_true', default=False,
help='Remove backup archive when done?')
help='Remove backup archive when done?')
args = parser.parse_args()

date_time_str = datetime.utcnow().strftime('%Y-%m-%dT%H:%M')
Expand All @@ -37,16 +39,18 @@ def _get_environment_value(key):
command = ['rethinkdb', 'dump', '-f', filename]
auth_key = os.environ.get('RETHINKDB_AUTH_KEY')
if auth_key:
command.extend(['-a', auth_key,])
command.extend(['-a', auth_key, ])
_info('Backing up database to {}...'.format(filename))
subprocess.check_call(command, stdout=subprocess.PIPE)

if args.s3_bucket:
_info('Uploading \'{}\' to S3 bucket \'{}\'...'.format(filename, args.s3_bucket))
_info('Uploading \'{}\' to S3 bucket \'{}\'...'.format(filename,
args.s3_bucket))
access_key_id = _get_environment_value('AWS_ACCESS_KEY_ID')
secret = _get_environment_value('AWS_SECRET_ACCESS_KEY')
s3_client = boto3.client('s3', region_name='eu-central-1', aws_access_key_id=access_key_id,
aws_secret_access_key=secret)
s3_client = boto3.client('s3', region_name='eu-central-1',
aws_access_key_id=access_key_id,
aws_secret_access_key=secret)
s3_client.upload_file(filename, args.s3_bucket, filename)
# TODO: Implement deleting backups that are older than 100 days

Expand Down
14 changes: 0 additions & 14 deletions cron.py

This file was deleted.

1 change: 0 additions & 1 deletion crontab

This file was deleted.

69 changes: 69 additions & 0 deletions schedule-rethinkdb-backup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env python3
"""Script to schedule RethinkDB backup."""
import asyncio
import subprocess
from datetime import datetime, date, timedelta
import sys
import logging
import contextlib


def _configure_logging():
logging.getLogger().setLevel(logging.WARNING)
logger = logging.getLogger('app')
logger.setLevel(logging.DEBUG)

ch = logging.StreamHandler()
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)

return logger


_logger = _configure_logging()


def _schedule_backup(loop):
hour = 18

now = datetime.now()
today = date.today()
desired_time = datetime(today.year, today.month, today.day, hour=hour)
if now.hour >= hour:
_logger.debug(
'Delaying until {} next day since we\'re already at {}'.format(
hour, now.hour))
desired_time = desired_time + timedelta(days=1)
else:
_logger.debug('Delaying until {} same day'.format(hour))
desired_seconds = (desired_time - now).seconds

_logger.debug(
'Delaying for {} second(s) before backup'.format(desired_seconds))
loop.call_later(desired_seconds, _backup, loop)


def _backup(loop):
"""Perform actual backup."""
now = datetime.now()
_logger.info('Backing up at {}...'.format(
now.strftime('%Y-%m-%d %H:%M:%S')))
_logger.info('Backed up successfully!')
_logger.debug('Scheduling next backup')
_schedule_backup(loop)


def _main():
with contextlib.closing(asyncio.get_event_loop()) as loop:
_schedule_backup(loop)
try:
loop.run_forever()
except KeyboardInterrupt:
_logger.info('Interrupted')
sys.exit(0)


if __name__ == '__main__':
_main()

0 comments on commit 666fb26

Please sign in to comment.