-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathbackup.py
More file actions
295 lines (243 loc) · 10.3 KB
/
backup.py
File metadata and controls
295 lines (243 loc) · 10.3 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
__all__ = ["Backup"]
from numbers import Number
from typing import Optional, cast
from arangoasync.exceptions import (
BackupCreateError,
BackupDeleteError,
BackupDownloadError,
BackupGetError,
BackupRestoreError,
BackupUploadError,
)
from arangoasync.executor import ApiExecutor
from arangoasync.request import Method, Request
from arangoasync.response import Response
from arangoasync.result import Result
from arangoasync.serialization import Deserializer, Serializer
from arangoasync.typings import Json, Jsons
class Backup:
"""Backup API wrapper."""
def __init__(self, executor: ApiExecutor) -> None:
self._executor = executor
@property
def serializer(self) -> Serializer[Json]:
"""Return the serializer."""
return self._executor.serializer
@property
def deserializer(self) -> Deserializer[Json, Jsons]:
"""Return the deserializer."""
return self._executor.deserializer
async def get(self, backup_id: Optional[str] = None) -> Result[Json]:
"""Return backup details.
Args:
backup_id (str | None): If set, the returned list is restricted to the
backup with the given id.
Returns:
dict: Backup details.
Raises:
BackupGetError: If the operation fails.
References:
- `list-backups <https://docs.arango.ai/stable/develop/http-api/hot-backups/#list-all-backups>`__
""" # noqa: E501
data: Json = {}
if backup_id is not None:
data["id"] = backup_id
request = Request(
method=Method.POST,
endpoint="/_admin/backup/list",
data=self.serializer.dumps(data) if data else None,
prefix_needed=False,
)
def response_handler(resp: Response) -> Json:
if not resp.is_success:
raise BackupGetError(resp, request)
result: Json = self.deserializer.loads(resp.raw_body)
return cast(Json, result["result"])
return await self._executor.execute(request, response_handler)
async def create(
self,
label: Optional[str] = None,
allow_inconsistent: Optional[bool] = None,
force: Optional[bool] = None,
timeout: Optional[Number] = None,
) -> Result[Json]:
"""Create a backup when the global write lock can be obtained.
Args:
label (str | None): Label for this backup. If not specified, a UUID is used.
allow_inconsistent (bool | None): Allow inconsistent backup when the global
transaction lock cannot be acquired before timeout.
force (bool | None): Forcefully abort all running transactions to ensure a
consistent backup when the global transaction lock cannot be
acquired before timeout. Default (and highly recommended) value
is `False`.
timeout (float | None): The time in seconds that the operation tries to
get a consistent snapshot.
Returns:
dict: Backup information.
Raises:
BackupCreateError: If the backup creation fails.
References:
- `create-backup <https://docs.arango.ai/stable/develop/http-api/hot-backups/#create-a-backup>`__
""" # noqa: E501
data: Json = {}
if label is not None:
data["label"] = label
if allow_inconsistent is not None:
data["allowInconsistent"] = allow_inconsistent
if force is not None:
data["force"] = force
if timeout is not None:
data["timeout"] = timeout
request = Request(
method=Method.POST,
endpoint="/_admin/backup/create",
data=self.serializer.dumps(data),
prefix_needed=False,
)
def response_handler(resp: Response) -> Json:
if not resp.is_success:
raise BackupCreateError(resp, request)
result: Json = self.deserializer.loads(resp.raw_body)
return cast(Json, result["result"])
return await self._executor.execute(request, response_handler)
async def restore(self, backup_id: str) -> Result[Json]:
"""Restore a local backup.
Args:
backup_id (str): Backup ID.
Returns:
dict: Result of the restore operation.
Raises:
BackupRestoreError: If the restore operation fails.
References:
- `restore-backup <https://docs.arango.ai/stable/develop/http-api/hot-backups/#restore-a-backup>`__
""" # noqa: E501
data: Json = {"id": backup_id}
request = Request(
method=Method.POST,
endpoint="/_admin/backup/restore",
data=self.serializer.dumps(data),
prefix_needed=False,
)
def response_handler(resp: Response) -> Json:
if not resp.is_success:
raise BackupRestoreError(resp, request)
result: Json = self.deserializer.loads(resp.raw_body)
return cast(Json, result["result"])
return await self._executor.execute(request, response_handler)
async def delete(self, backup_id: str) -> None:
"""Delete a backup.
Args:
backup_id (str): Backup ID.
Raises:
BackupDeleteError: If the delete operation fails.
References:
- `delete-backup <https://docs.arango.ai/stable/develop/http-api/hot-backups/#delete-a-backup>`__
""" # noqa: E501
data: Json = {"id": backup_id}
request = Request(
method=Method.POST,
endpoint="/_admin/backup/delete",
data=self.serializer.dumps(data),
prefix_needed=False,
)
def response_handler(resp: Response) -> None:
if not resp.is_success:
raise BackupDeleteError(resp, request)
await self._executor.execute(request, response_handler)
async def upload(
self,
backup_id: Optional[str] = None,
repository: Optional[str] = None,
abort: Optional[bool] = None,
config: Optional[Json] = None,
upload_id: Optional[str] = None,
) -> Result[Json]:
"""Manage backup uploads.
Args:
backup_id (str | None): Backup ID used for scheduling an upload. Mutually
exclusive with parameter **upload_id**.
repository (str | None): Remote repository URL(e.g. "local://tmp/backups").
abort (str | None): If set to `True`, running upload is aborted. Used with
parameter **upload_id**.
config (dict | None): Remote repository configuration. Required for scheduling
an upload and mutually exclusive with parameter **upload_id**.
upload_id (str | None): Upload ID. Mutually exclusive with parameters
**backup_id**, **repository**, and **config**.
Returns:
dict: Upload details.
Raises:
BackupUploadError: If upload operation fails.
References:
- `upload-a-backup-to-a-remote-repository <https://docs.arango.ai/stable/develop/http-api/hot-backups/#upload-a-backup-to-a-remote-repository>`__
""" # noqa: E501
data: Json = {}
if upload_id is not None:
data["uploadId"] = upload_id
if backup_id is not None:
data["id"] = backup_id
if repository is not None:
data["remoteRepository"] = repository
if abort is not None:
data["abort"] = abort
if config is not None:
data["config"] = config
request = Request(
method=Method.POST,
endpoint="/_admin/backup/upload",
data=self.serializer.dumps(data),
prefix_needed=False,
)
def response_handler(resp: Response) -> Json:
if not resp.is_success:
raise BackupUploadError(resp, request)
result: Json = self.deserializer.loads(resp.raw_body)
return cast(Json, result["result"])
return await self._executor.execute(request, response_handler)
async def download(
self,
backup_id: Optional[str] = None,
repository: Optional[str] = None,
abort: Optional[bool] = None,
config: Optional[Json] = None,
download_id: Optional[str] = None,
) -> Result[Json]:
"""Manage backup downloads.
Args:
backup_id (str | None): Backup ID used for scheduling a download. Mutually
exclusive with parameter **download_id**.
repository (str | None): Remote repository URL (e.g. "local://tmp/backups").
abort (bool | None): If set to `True`, running download is aborted.
config (dict | None): Remote repository configuration. Required for scheduling
a download and mutually exclusive with parameter **download_id**.
download_id (str | None): Download ID. Mutually exclusive with parameters
**backup_id**, **repository**, and **config**.
Returns:
dict: Download details.
Raises:
BackupDownloadError: If the download operation fails.
References:
- `download-a-backup-from-a-remote-repository <https://docs.arango.ai/stable/develop/http-api/hot-backups/#download-a-backup-from-a-remote-repository>`__
""" # noqa: E501
data: Json = {}
if download_id is not None:
data["downloadId"] = download_id
if backup_id is not None:
data["id"] = backup_id
if repository is not None:
data["remoteRepository"] = repository
if abort is not None:
data["abort"] = abort
if config is not None:
data["config"] = config
request = Request(
method=Method.POST,
endpoint="/_admin/backup/download",
data=self.serializer.dumps(data),
prefix_needed=False,
)
def response_handler(resp: Response) -> Json:
if not resp.is_success:
raise BackupDownloadError(resp, request)
result: Json = self.deserializer.loads(resp.raw_body)
return cast(Json, result["result"])
return await self._executor.execute(request, response_handler)