Skip to content

Commit 359b474

Browse files
authored
Made naming rules more lax and migration script more stable. (#70)
1 parent fac47e0 commit 359b474

File tree

4 files changed

+99
-14
lines changed

4 files changed

+99
-14
lines changed

filetracker/scripts/migrate.py

+26-10
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@
66

77
import argparse
88
import os
9+
import sys
910

10-
from filetracker.client import Client
11+
from filetracker.client import Client, FiletrackerError
1112
from filetracker.scripts import progress_bar
1213

1314
# Value used for aligning printed action names
1415
_ACTION_LENGTH = 25
1516

1617

1718
_DESCRIPTION = """
18-
Uploads all files to a remote filetracker server.
19+
Uploads files to a remote filetracker server.
20+
21+
Use --root parameter to upload only parts of the storage.
1922
2023
The intention for this script is to support migration to new filetracker
2124
servers that change the format of disk storage.
@@ -25,15 +28,24 @@
2528
"""
2629

2730

28-
def main():
31+
def main(args=None):
2932
parser = argparse.ArgumentParser(description=_DESCRIPTION)
30-
parser.add_argument('files', help='root of the file tree to be uploaded')
33+
parser.add_argument('files', help='file tree to be uploaded')
3134
parser.add_argument('url', help='URL of the filetracker server')
35+
parser.add_argument('--root',
36+
help='the directory that corresponds to the storage root')
3237
parser.add_argument('-s', '--silent', action='store_true',
3338
help='if set, progress bar is not printed')
3439

35-
args = parser.parse_args()
36-
root, url, silent = args.files, args.url, args.silent
40+
args = parser.parse_args(args)
41+
42+
upload_root = args.files
43+
url = args.url
44+
storage_root = args.root
45+
silent = args.silent
46+
47+
if storage_root is None:
48+
storage_root = upload_root
3749

3850
# Create a client without local cache.
3951
client = Client(local_store=None, remote_url=url)
@@ -50,7 +62,7 @@ def main():
5062

5163
with progress_bar.conditional(show=not silent,
5264
widgets=size_widgets) as bar:
53-
for cur_dir, _, files in os.walk(root):
65+
for cur_dir, _, files in os.walk(upload_root):
5466
for file_name in files:
5567
total_size += os.path.getsize(os.path.join(cur_dir, file_name))
5668
bar.update(total_size)
@@ -69,18 +81,22 @@ def main():
6981
with progress_bar.conditional(show=not silent,
7082
max_value=total_size,
7183
widgets=upload_widgets) as bar:
72-
for cur_dir, _, files in os.walk(root):
84+
for cur_dir, _, files in os.walk(upload_root):
7385
for file_name in files:
7486
file_path = os.path.join(cur_dir, file_name)
75-
remote_path = '/' + os.path.relpath(file_path, root)
87+
remote_path = '/' + os.path.relpath(file_path, storage_root)
7688

7789
file_stat = os.stat(file_path)
7890
file_size = file_stat.st_size
7991
file_version = int(file_stat.st_mtime)
8092

8193
remote_name = '{}@{}'.format(remote_path, file_version)
8294

83-
client.put_file(remote_name, file_path, to_local_store=False)
95+
try:
96+
client.put_file(remote_name, file_path, to_local_store=False)
97+
except FiletrackerError as e:
98+
print('ERROR when uploading {}:\n{}'.format(file_path, e),
99+
file=sys.stderr)
84100

85101
processed_size += file_size
86102
bar.update(processed_size)

filetracker/scripts/migrate_test.py

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Tests for migrate script."""
2+
3+
from __future__ import absolute_import
4+
from __future__ import division
5+
from __future__ import print_function
6+
7+
from multiprocessing import Process
8+
import os
9+
import shutil
10+
import tempfile
11+
import time
12+
import unittest
13+
14+
from filetracker.client import Client, FiletrackerError
15+
from filetracker.scripts import migrate
16+
from filetracker.servers.run import main as server_main
17+
18+
_TEST_PORT_NUMBER = 45785
19+
20+
21+
class MigrateScriptTest(unittest.TestCase):
22+
def setUp(self):
23+
self.temp_dir = tempfile.mkdtemp()
24+
os.makedirs(os.path.join(self.temp_dir, 'old_root', 'foo', 'bar'))
25+
os.makedirs(os.path.join(self.temp_dir, 'new_root'))
26+
27+
self.server_process = Process(
28+
target=_start_server,
29+
args=(os.path.join(self.temp_dir, 'new_root'),))
30+
self.server_process.start()
31+
time.sleep(2)
32+
33+
self.server_url = 'http://127.0.0.1:{}'.format(_TEST_PORT_NUMBER)
34+
self.client = Client(local_store=None, remote_url=self.server_url)
35+
36+
def tearDown(self):
37+
self.server_process.terminate()
38+
shutil.rmtree(self.temp_dir)
39+
40+
def test_should_upload_files_with_correct_relative_root(self):
41+
_touch(os.path.join(self.temp_dir, 'old_root', 'foo', 'a.txt'))
42+
_touch(os.path.join(self.temp_dir, 'old_root', 'foo', 'bar', 'b.txt'))
43+
_touch(os.path.join(self.temp_dir, 'old_root', 'c.txt'))
44+
_touch(os.path.join(self.temp_dir, 'old_root', 'd.txt'))
45+
46+
migrate.main([
47+
os.path.join(self.temp_dir, 'old_root', 'foo'),
48+
self.server_url,
49+
'--root',
50+
os.path.join(self.temp_dir, 'old_root'),
51+
'-s'])
52+
53+
self.assertEqual(self.client.get_stream('/foo/a.txt')[0].read(), b'')
54+
self.assertEqual(self.client.get_stream('/foo/bar/b.txt')[0].read(), b'')
55+
56+
with self.assertRaises(FiletrackerError):
57+
self.client.get_stream('/c.txt')
58+
59+
with self.assertRaises(FiletrackerError):
60+
self.client.get_stream('/d.txt')
61+
62+
63+
def _start_server(server_dir):
64+
server_main(['-p', str(_TEST_PORT_NUMBER), '-d', server_dir, '-D',
65+
'--workers', '4'])
66+
67+
def _touch(path):
68+
with open(path, 'w') as f:
69+
pass

filetracker/servers/base.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ def get_endpoint_and_path(environ):
6767
of them are without leading slashes.
6868
"""
6969
path = environ['PATH_INFO']
70-
if '..' in path:
71-
raise HttpError('400 Bad Request', 'Path cannot contain "..".')
72-
7370
components = path.split('/')
7471

72+
if '..' in components:
73+
raise HttpError('400 Bad Request', 'Path cannot contain "..".')
74+
7575
# Strip closing slash
7676
if components and components[-1] == '':
7777
components.pop()

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from setuptools import setup, find_packages
22
setup(
33
name = 'filetracker',
4-
version = '2.1.1',
4+
version = '2.1.2',
55
author = 'SIO2 Project Team',
66
author_email = '[email protected]',
77
description = 'Filetracker caching file storage',

0 commit comments

Comments
 (0)