1 contributor
101 lines3.1 KB
1name: Initialise RepoRepository from Full Backup
2
3args:
4 -
5 name: reporepository
6 label: Repo repository
7 placeholder: Urn or api id
8 python_type: str
9 -
10 name: host
11 label: Host instance
12 placeholder: Urn or api id
13 python_type: str
14 -
15 name: blob
16 label: Backup blob
17 placeholder: Urn or api id
18 python_type: str
19
20role:
21 policies:
22 - urn/api/policy/svnplace/Allow Everything
23 parents:
24 - urn/api/role/{user.username}/
25 - urn/api/role/svnplace/Backup Restorer
26
27jobs:
28 restore:
29 runs_on:
30 host_instance: "{host}"
31 mapped_repo: "{reporepository}"
32 steps:
33 -
34 name: Restore
35 python: |
36 blob = '{escape(blob)}'
37 import os
38 import subprocess
39 import sys
40 import xml.etree.ElementTree as ET
41 from api_api import API
42
43 repo = '{repo.urn}'
44 repo_user = repo.rsplit('/',2)[1]
45 repo_name = repo.rsplit('/',2)[2]
46 repo_file = '/var/svnplace/process/repo'
47
48 api = API('https://svnplace.com/api', ['~/.svnplace/config'])
49
50 reporepo_desc = api.repos.describe_reporepository('{reporepository}')
51 if reporepo_desc.state.name != 'Initialising':
52 print(f'Reporepository in wrong state:{{reporepo_desc.state}')
53 sys.exit(1)
54
55 # confirm backup is an actual backup
56 backup_desc = api.blobs.describe_blob(blob)
57 backup_seal = api.blobs.describe_seal('urn/seal/user/svnplace/Backup - Full')
58 if backup_seal.id not in backup_desc.seals:
59 print('Blob not a full backup')
60 sys.exit(1)
61
62 # restore the backup files to the root directory
63
64 r0 = subprocess.Popen(['blobcp', f'blob:{{backup_desc.fullpath}', '-'], stdout=subprocess.PIPE)
65 r1 = subprocess.run(['tar', '--keep-old-files', '-xzf', '-', '-C', repo_file], stdin=r0.stdout)
66
67 if r1.returncode:
68 print('Backup failed: could not unpack backup')
69 sys.exit(1)
70
71 r0.wait()
72 if r0.returncode:
73 print('Backup failed: reading blob failed')
74 sys.exit(1)
75
76 backup_desc2 = api.blobs.describe_blob(blob)
77 if backup_desc2.seal_tag != backup_desc.seal_tag:
78 print('Backup failed: backup changed during restore')
79 sys.exit(1)
80
81 repo_desc = api.repos.describe_repo(repo)
82 if repo_desc.seal in backup_desc2.seals:
83 # backup is of this repo...
84 # leave the UUID alone
85 # leave the hooks in place
86 pass
87 else:
88 # backup is of a different repo...
89
90 # replace the uuid with a new one
91 r = subprocess.run(['svnadmin', 'setuuid', repo_file])
92
93 # clear all hooks
94 for item in os.scandir(f'{{repo_file}/hooks/descriptions'):
95 if item.is_file():
96 os.remove(item.path)
97
98 api.repos.modify_reporepository('{reporepository}', state='Ready')
99
100 print('Restore complete')
101