4 5
6
7 8
Update due to process yaml update
on 11:11 AM Jul 2 2024
backup.yaml
5
6
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
name: Backup (full)
triggers:
manual_trigger:
assignments:
backup.store: |
'jonathanroach/Backups'
backup.pattern: |
'%(backups)s/%(username)s_%(reponame)s_%(ver)d_full'
role:
policies:
- urn/api/policy/svnplace/Allow Everything
parents:
- urn/api/role/{user.username}/
- urn/api/role/svnplace/Backup Creater
jobs:
do_backup:
runs_on:
host_instance: "{repo.primary.rootdirectory.instance.api_id}"
mapped_repo: "{repo.primary.api_id}"
steps:
-
name: Backup
python: |
import os
import subprocess
import sys
import xml.etree.ElementTree as ET
from api_api import API
repo = '{repo.urn}'
repo_user = repo.rsplit('/',2)[1]
repo_name = repo.rsplit('/',2)[2]
repo_file = '/var/svnplace/process/repo'
backup_file = os.path.abspath('./backup')
def get_repo_version(repo):
r = subprocess.run(['svn','info','--xml', 'FILE://'+repo], capture_output=True)
if r.returncode != 0:
print(r.stdout)
print(r.stderr)
return None
tree = ET.fromstring(r.stdout)
return int(tree.find('entry').attrib['revision'])
def backup_blob(ver):
return '{backup.pattern}' % {{
'backups': '{backup.store}',
'username': repo_user,
'reponame': repo_name,
'ver': ver,
}
api = API('https://svnplace.com/api', ['~/.svnplace/config'])
repo_desc = api.repos.describe_repo(repo)
repo_ver = get_repo_version(repo_file)
try:
r = api.blobs.describe_blob('urn/blob/'+backup_blob(repo_ver))
except FileNotFoundError:
pass
else:
print(f'{{repo_user}/{{repo_name}@{{repo_ver} is already backed up - nothing to do')
sys.exit(0)
print('Creating backup copy')
r = subprocess.run(['svnadmin','hotcopy', repo_file, backup_file])
if r.returncode != 0:
print('Failed to complete backup')
sys.exit(1)
backup_ver = get_repo_version(backup_file)
if backup_ver is None:
print('Failed to read backup version')
sys.exit(1)
print(f'Archiving backup {{repo_user}/{{repo_name}@{{backup_ver}')
r0 = subprocess.Popen(('tar', '--strip-component', str(len(backup_file.split('/'))+1), '-cz', backup_file), stdout=subprocess.PIPE)
r1 = subprocess.run(['blobcp', '-s', repo_desc.seal.api_id, '-s', 'urn/seal/user/svnplace/Backup - Full', '-', 'blob:'+backup_blob(backup_ver)], stdin=r0.stdout)
if r1.returncode:
print('Backup failed')
sys.exit(1)
print('Backup complete')
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
name: Backup (full)
args:
-
name: backup.store
label: Backup location
placeholder: Path to blob directory
-
name: backup.pattern
label: Backup names
placeholder: The bit between the directory and _<ver>_full
role:
policies:
- urn/api/policy/svnplace/Allow Everything
parents:
- urn/api/role/{user.username}/
- urn/api/role/svnplace/Backup Creater
jobs:
do_backup:
runs_on:
host_instance: "{repo.primary.rootdirectory.instance.api_id}"
mapped_repo: "{repo.primary.api_id}"
steps:
-
name: Backup
python: |
import os
import subprocess
import sys
import xml.etree.ElementTree as ET
from api_api import API
repo = '{repo.urn}'
repo_user = repo.rsplit('/',2)[1]
repo_name = repo.rsplit('/',2)[2]
repo_file = '/var/svnplace/process/repo'
backup_file = os.path.abspath('./backup')
def get_repo_version(repo):
r = subprocess.run(['svn','info','--xml', 'FILE://'+repo], capture_output=True)
if r.returncode != 0:
print(r.stdout)
print(r.stderr)
return None
tree = ET.fromstring(r.stdout)
return int(tree.find('entry').attrib['revision'])
def backup_blob(ver):
return '{backup.store}/{backup.pattern}_%(ver)d_full' % {{
'backups': '{backup.store}',
'username': repo_user,
'reponame': repo_name,
'ver': ver,
}
api = API('https://svnplace.com/api', ['~/.svnplace/config'])
repo_desc = api.repos.describe_repo(repo)
repo_ver = get_repo_version(repo_file)
try:
r = api.blobs.describe_blob('urn/blob/'+backup_blob(repo_ver))
except FileNotFoundError:
pass
else:
print(f'{{repo_user}/{{repo_name}@{{repo_ver} is already backed up - nothing to do')
sys.exit(0)
print('Creating backup copy')
r = subprocess.run(['svnadmin','hotcopy', repo_file, backup_file])
if r.returncode != 0:
print('Failed to complete backup')
sys.exit(1)
backup_ver = get_repo_version(backup_file)
if backup_ver is None:
print('Failed to read backup version')
sys.exit(1)
print(f'Archiving backup {{repo_user}/{{repo_name}@{{backup_ver}')
r0 = subprocess.Popen(('tar', '--strip-components', '1', '-C', backup_file, '-cz', '.'), stdout=subprocess.PIPE)
r1 = subprocess.run(['blobcp', '-s', repo_desc.seal.api_id, '-s', 'urn/seal/user/svnplace/Backup - Full', '-', 'blob:'+backup_blob(backup_ver)], stdin=r0.stdout)
if r1.returncode:
print('Backup failed')
sys.exit(1)
print('Backup complete')