Skip to content
This repository has been archived by the owner on May 16, 2019. It is now read-only.

Added a backup tool to import/export store data #35

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions api/restapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from market.profile import Profile
from market.contracts import Contract
from net.upnp import PortMapper
import db.backuptool

DEFAULT_RECORDS_COUNT = 20
DEFAULT_RECORDS_OFFSET = 0
Expand Down Expand Up @@ -795,5 +796,14 @@ def get_response(num):
request.finish()
return server.NOT_DONE_YET



@POST('^/api/v1/backup_files')
def backup_files(self, request):
"""Archives OpenBazaar files in a single tar archive."""
output_name = request.args["output_name"][0]
return db.backuptool.backupfiles(output_name)

@POST('^/api/v1/restore_files')
def restore_files(self, request):
"""Restores files of given archive to OpenBazaar folder."""
input_file = request.args["input_file"][0]
return db.backuptool.restorefiles(input_file)
62 changes: 62 additions & 0 deletions db/backuptool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Import and export data for the OpenBazaar server."""
__author__ = 'marc'
from constants import DATA_FOLDER
import db.datastore as db
import os
import sqlite3 as lite
import tarfile
import time

BACKUP_FOLDER = 'backup'

def _getdatabase():
"""Retrieves the OpenBazaar database file."""
database = db.Database()
return database.DATABASE

def backupfiles(output_name=None):
"""Archives OpenBazaar files in a single tar archive."""
os.chdir(DATA_FOLDER)
if not os.path.exists(BACKUP_FOLDER):
os.makedirs(BACKUP_FOLDER)
if not output_name:
output_name = 'backup_{0}.tar.gz'.format(time.strftime('%Y-%m-%d'))
if not os.path.isabs(output_name):
output = BACKUP_FOLDER + os.sep + output_name
if os.path.isfile(output):
raise IOError(output + ' already exists.')

# Lock the database
db_file = _getdatabase()
db_connection = lite.connect(db_file)
db_connection.commit()

# Archive files
files = os.listdir(DATA_FOLDER)
with tarfile.open(output, 'w:gz') as tar:
for fil in files:
if fil != BACKUP_FOLDER:
tar.add(fil)
tar.close()

# Unlock database
db_connection.rollback()
db_connection.close()

return True


def restorefiles(input_file):
"""Restores files of given archive to OpenBazaar folder."""
os.chdir(DATA_FOLDER)
if not os.path.isabs(input_file):
input_file = BACKUP_FOLDER + os.sep + input_file

if not os.path.isfile(input_file):
raise IOError(input_file + ' does not exist.')

# Unarchive files
with tarfile.open(input_file, 'r:gz') as tar:
tar.extractall()

return True
47 changes: 47 additions & 0 deletions db/tests/test_backuptool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Test for db/backuptool"""
from constants import DATA_FOLDER
import os
import unittest

import db.backuptool as bt

TEST_FOLDER = 'test'
TEST_TAR = 'test.tar.gz'
TEST_FILE_1 = 'test.txt'
TEST_FILE_2 = TEST_FOLDER + os.sep + 'test2.txt'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP8-nitpicking: Please add an extra blank line here, before the class definition.

class BackuptoolTest(unittest.TestCase):
"""Test class for backuptool functions"""
def setUp(self):
os.chdir(DATA_FOLDER)
# Create test folder
if not os.path.exists(TEST_FOLDER):
os.makedirs(TEST_FOLDER)
# Create test files "test.txt", "test/test2.txt"
fil = open(TEST_FILE_1, 'w')
fil.close()
fil = open(TEST_FILE_2, 'w')
fil.close()
# Backup to "test.tar.gz"
if os.path.exists(bt.BACKUP_FOLDER + os.sep + TEST_TAR):
os.remove(bt.BACKUP_FOLDER + os.sep + TEST_TAR)
bt.backupfiles(TEST_TAR)
# Remove test files and directory
os.remove(TEST_FILE_1)
os.remove(TEST_FILE_2)
# Restore from "test.tar.gz"
bt.restorefiles(TEST_TAR)

def tearDown(self):
os.remove(TEST_FILE_1)
os.remove(TEST_FILE_2)
os.remove(bt.BACKUP_FOLDER + os.sep + TEST_TAR)

def test_backupexists(self):
"""Checks if the backup file exists"""
self.assertTrue(os.path.isfile(bt.BACKUP_FOLDER + os.sep + TEST_TAR))

def test_restoreexists(self):
"""Checks if the restored files exists"""
self.assertTrue(os.path.isfile(TEST_FILE_1))
self.assertTrue(os.path.isfile(TEST_FILE_2))