forked from hyperledger/indy-node
-
Notifications
You must be signed in to change notification settings - Fork 0
/
migration_tool.py
135 lines (115 loc) · 4.93 KB
/
migration_tool.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/python3
import importlib
import os
import pkgutil
import platform
import subprocess
import time
from pathlib import Path
from functools import cmp_to_key
from stp_core.common.log import getlogger
from indy_common.util import compose_cmd
from indy_node.server.upgrader import Upgrader
SCRIPT_PREFIX = Path('data', 'migrations')
PLATFORM_PREFIX = {
'Ubuntu': 'deb'
}
logger = getlogger()
def _call_migration_script(migration_script, current_platform, timeout):
migration_script_path = \
os.path.normpath(
os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'..',
'..',
str(SCRIPT_PREFIX),
PLATFORM_PREFIX[current_platform],
migration_script + '.py'))
logger.info('script path {}'.format(migration_script_path))
ret = subprocess.run(
compose_cmd(
['python3 {}'.format(migration_script_path)]
),
shell=True,
timeout=timeout)
if ret.returncode != 0:
msg = 'Migration failed: script returned {}'.format(ret.returncode)
logger.error(msg)
raise Exception(msg)
# Returns number of performed migrations
def migrate(current_version, new_version, timeout):
current_platform = _get_current_platform()
logger.info('Migrating from {} to {} on {}'.format(
current_version, new_version, current_platform))
migration_scripts = _get_migration_scripts(current_platform)
logger.debug('Found migration scripts: {}'.format(migration_scripts))
migration_scripts = _get_relevant_migrations(
migration_scripts, current_version, new_version)
if not len(migration_scripts):
logger.info('No migrations can be applied to the current code.')
return 0
logger.info('Following migrations will be applied: {}'.format(
migration_scripts))
for migration in migration_scripts:
logger.info('Applying migration {}'.format(migration))
start_time = time.time()
_call_migration_script(migration, current_platform, timeout)
logger.info('Migration {} applied in {} seconds'.format(
migration, time.time() - start_time))
return len(migration_scripts)
def _get_migration_scripts(current_platform):
# Data folder is published as a separate 'data' python package
migrations = importlib.import_module(
'.'.join(SCRIPT_PREFIX.parts + (PLATFORM_PREFIX[current_platform],))
)
return [name
for module_finder, name, ispkg
in pkgutil.iter_modules(migrations.__path__)]
def _get_relevant_migrations(migration_scripts, current_version, new_version):
relevant_migrations = []
for migration in migration_scripts:
migration_original_version, migration_new_version = _get_migration_versions(
migration)
if not migration_original_version or not migration_new_version:
continue
if Upgrader.compareVersions(current_version, new_version) >= 0:
if Upgrader.compareVersions(
migration_new_version, migration_original_version) > 0:
continue
if Upgrader.compareVersions(migration_original_version, current_version) <= 0 \
and Upgrader.compareVersions(migration_new_version, new_version) >= 0:
relevant_migrations.append(migration)
else:
if Upgrader.compareVersions(
migration_original_version, migration_new_version) > 0:
continue
if Upgrader.compareVersions(migration_original_version, current_version) >= 0 \
and Upgrader.compareVersions(migration_new_version, new_version) <= 0:
relevant_migrations.append(migration)
relevant_migrations = sorted(
relevant_migrations, key=cmp_to_key(_compare_migration_scripts))
return relevant_migrations
def _get_migration_versions(migration):
migration_split = migration.split('_')
if len(migration_split) != 7:
return None, None
migration_original_version = '.'.join(migration_split[0:3])
migration_new_version = '.'.join(migration_split[-3:])
return migration_original_version, migration_new_version
def _compare_migration_scripts(migration1, migration2):
migration_original_version1, migration_new_version1 = _get_migration_versions(
migration1)
migration_original_version2, migration_new_version2 = _get_migration_versions(
migration2)
if Upgrader.compareVersions(
migration_original_version2, migration_original_version1) == 0:
return Upgrader.compareVersions(
migration_new_version2, migration_new_version1)
return Upgrader.compareVersions(
migration_original_version2, migration_original_version1)
def _get_current_platform():
uname = platform.uname()
version = uname.version
if 'Ubuntu' in version:
return 'Ubuntu'
raise Exception('Platform is not supported')