2
2
# Copyright (c) Microsoft Corporation.
3
3
# Licensed under the MIT License.
4
4
# ------------------------------------
5
+ import base64
5
6
import functools
7
+ import pickle
6
8
from typing import TYPE_CHECKING
7
9
8
- from azure .core .polling .base_polling import LROBasePolling
10
+ from six import raise_from
11
+ from six .moves .urllib_parse import urlparse
9
12
10
13
from ._models import KeyVaultBackupOperation
11
14
from ._internal import KeyVaultClientBase , parse_folder_url
12
- from ._internal .polling import KeyVaultBackupClientPolling
15
+ from ._internal .polling import KeyVaultBackupClientPolling , KeyVaultBackupClientPollingMethod
13
16
14
17
if TYPE_CHECKING :
15
18
# pylint:disable=unused-import
16
19
from typing import Any
17
20
from azure .core .polling import LROPoller
18
21
19
22
23
+ def _parse_status_url (url ):
24
+ parsed = urlparse (url )
25
+ job_id = parsed .path .split ("/" )[2 ]
26
+ return job_id
27
+
28
+
20
29
class KeyVaultBackupClient (KeyVaultClientBase ):
21
30
"""Performs Key Vault backup and restore operations.
22
31
@@ -37,15 +46,48 @@ def begin_backup(self, blob_storage_url, sas_token, **kwargs):
37
46
:returns: An :class:`~azure.core.polling.LROPoller` instance. Call `result()` on this object to wait for the
38
47
operation to complete and get a :class:`KeyVaultBackupOperation`.
39
48
:rtype: ~azure.core.polling.LROPoller[~azure.keyvault.administration.KeyVaultBackupOperation]
49
+
50
+ Example:
51
+ .. literalinclude:: ../tests/test_examples_administration.py
52
+ :start-after: [START begin_backup]
53
+ :end-before: [END begin_backup]
54
+ :language: python
55
+ :caption: Create a vault backup
56
+ :dedent: 8
40
57
"""
41
58
polling_interval = kwargs .pop ("_polling_interval" , 5 )
42
59
sas_parameter = self ._models .SASTokenParameter (storage_resource_uri = blob_storage_url , token = sas_token )
60
+
61
+ continuation_token = kwargs .pop ("continuation_token" , None )
62
+ status_response = None
63
+ if continuation_token :
64
+ status_url = base64 .b64decode (continuation_token .encode ()).decode ("ascii" )
65
+ try :
66
+ job_id = _parse_status_url (status_url )
67
+ except Exception as ex : # pylint: disable=broad-except
68
+ raise_from (
69
+ ValueError (
70
+ "The provided continuation_token is malformed. A valid token can be obtained from the "
71
+ + "operation poller's continuation_token() method"
72
+ ),
73
+ ex ,
74
+ )
75
+
76
+ pipeline_response = self ._client .full_backup_status (
77
+ vault_base_url = self ._vault_url , job_id = job_id , cls = lambda pipeline_response , _ , __ : pipeline_response
78
+ )
79
+ if "azure-asyncoperation" not in pipeline_response .http_response .headers :
80
+ pipeline_response .http_response .headers ["azure-asyncoperation" ] = status_url
81
+ status_response = base64 .b64encode (pickle .dumps (pipeline_response )).decode ("ascii" )
82
+
43
83
return self ._client .begin_full_backup (
44
84
vault_base_url = self ._vault_url ,
45
85
azure_storage_blob_container_uri = sas_parameter ,
46
86
cls = KeyVaultBackupOperation ._from_generated ,
47
- continuation_token = kwargs .pop ("continuation_token" , None ),
48
- polling = LROBasePolling (lro_algorithms = [KeyVaultBackupClientPolling ()], timeout = polling_interval , ** kwargs ),
87
+ continuation_token = status_response ,
88
+ polling = KeyVaultBackupClientPollingMethod (
89
+ lro_algorithms = [KeyVaultBackupClientPolling ()], timeout = polling_interval , ** kwargs
90
+ ),
49
91
** kwargs
50
92
)
51
93
@@ -62,14 +104,50 @@ def begin_restore(self, folder_url, sas_token, **kwargs):
62
104
:keyword str continuation_token: a continuation token to restart polling from a saved state
63
105
:keyword str key_name: name of a single key in the backup. When set, only this key will be restored.
64
106
:rtype: ~azure.core.polling.LROPoller
107
+
108
+ Examples:
109
+ .. literalinclude:: ../tests/test_examples_administration.py
110
+ :start-after: [START begin_restore]
111
+ :end-before: [END begin_restore]
112
+ :language: python
113
+ :caption: Restore a vault backup
114
+ :dedent: 8
115
+
116
+ .. literalinclude:: ../tests/test_examples_administration.py
117
+ :start-after: [START begin_selective_restore]
118
+ :end-before: [END begin_selective_restore]
119
+ :language: python
120
+ :caption: Restore a single key
121
+ :dedent: 8
65
122
"""
66
123
# LROBasePolling passes its kwargs to pipeline.run(), so we remove unexpected args before constructing it
67
124
continuation_token = kwargs .pop ("continuation_token" , None )
68
125
key_name = kwargs .pop ("key_name" , None )
69
126
127
+ status_response = None
128
+ if continuation_token :
129
+ status_url = base64 .b64decode (continuation_token .encode ()).decode ("ascii" )
130
+ try :
131
+ job_id = _parse_status_url (status_url )
132
+ except Exception as ex : # pylint: disable=broad-except
133
+ raise_from (
134
+ ValueError (
135
+ "The provided continuation_token is malformed. A valid token can be obtained from the "
136
+ + "operation poller's continuation_token() method"
137
+ ),
138
+ ex ,
139
+ )
140
+
141
+ pipeline_response = self ._client .restore_status (
142
+ vault_base_url = self ._vault_url , job_id = job_id , cls = lambda pipeline_response , _ , __ : pipeline_response
143
+ )
144
+ if "azure-asyncoperation" not in pipeline_response .http_response .headers :
145
+ pipeline_response .http_response .headers ["azure-asyncoperation" ] = status_url
146
+ status_response = base64 .b64encode (pickle .dumps (pipeline_response )).decode ("ascii" )
147
+
70
148
container_url , folder_name = parse_folder_url (folder_url )
71
149
sas_parameter = self ._models .SASTokenParameter (storage_resource_uri = container_url , token = sas_token )
72
- polling = LROBasePolling (
150
+ polling = KeyVaultBackupClientPollingMethod (
73
151
lro_algorithms = [KeyVaultBackupClientPolling ()], timeout = kwargs .pop ("_polling_interval" , 5 ), ** kwargs
74
152
)
75
153
@@ -88,7 +166,7 @@ def begin_restore(self, folder_url, sas_token, **kwargs):
88
166
vault_base_url = self ._vault_url ,
89
167
restore_blob_details = restore_details ,
90
168
cls = lambda * _ : None , # poller.result() returns None
91
- continuation_token = continuation_token ,
169
+ continuation_token = status_response ,
92
170
polling = polling ,
93
171
** kwargs
94
172
)
0 commit comments