|
12 | 12 | // limitations under the License.
|
13 | 13 | // ----------------------------------------------------------------------------------
|
14 | 14 |
|
| 15 | +using Azure; |
15 | 16 | using Microsoft.Azure.Commands.Management.Storage.Models;
|
16 | 17 | using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
|
17 | 18 | using Microsoft.Azure.Management.Internal.Resources.Utilities.Models;
|
18 |
| -using Microsoft.Azure.Management.Storage; |
19 |
| -using Microsoft.Azure.Management.Storage.Models; |
20 | 19 | using Microsoft.Rest.Azure;
|
| 20 | +using Microsoft.WindowsAzure.Commands.Utilities.Common; |
21 | 21 | using System;
|
| 22 | +using System.Collections.Generic; |
22 | 23 | using System.Management.Automation;
|
23 | 24 | using System.Threading.Tasks;
|
| 25 | +using Track2 = Azure.ResourceManager.Storage; |
| 26 | +using Track2Models = Azure.ResourceManager.Storage.Models; |
24 | 27 |
|
25 | 28 | namespace Microsoft.Azure.Commands.Management.Storage
|
26 | 29 | {
|
@@ -79,7 +82,7 @@ public class RestoreAzureStorageBlobRangeCommand : StorageAccountBaseCmdlet
|
79 | 82 |
|
80 | 83 | [Parameter(Mandatory = true, HelpMessage = "The Time to Restore Blob.")]
|
81 | 84 | [ValidateNotNull]
|
82 |
| - public DateTime TimeToRestore { get; set; } |
| 85 | + public DateTimeOffset TimeToRestore { get; set; } |
83 | 86 |
|
84 | 87 | [Parameter(Mandatory = false, HelpMessage = "The blob range to Restore.")]
|
85 | 88 | [ValidateNotNull]
|
@@ -118,50 +121,116 @@ public override void ExecuteCmdlet()
|
118 | 121 |
|
119 | 122 | if (ShouldProcess(this.StorageAccountName, "Restore Blob Range"))
|
120 | 123 | {
|
121 |
| - if (waitForComplete) |
122 |
| - { |
123 |
| - Task<AzureOperationResponse<BlobRestoreStatus>> beginTask = this.StorageClient.StorageAccounts.BeginRestoreBlobRangesWithHttpMessagesAsync( |
124 |
| - this.ResourceGroupName, |
125 |
| - this.StorageAccountName, |
126 |
| - this.TimeToRestore, |
127 |
| - PSBlobRestoreRange.ParseBlobRestoreRanges(this.BlobRestoreRange)); |
128 |
| - |
129 |
| - beginTask.Wait(); |
130 |
| - |
131 |
| - AzureOperationResponse<BlobRestoreStatus> response = beginTask.Result; |
| 124 | + Track2.StorageAccountResource account = this.StorageClientTrack2.GetStorageAccount(this.ResourceGroupName, this.StorageAccountName); |
| 125 | + var restoreLro = account.RestoreBlobRanges( |
| 126 | + WaitUntil.Started, |
| 127 | + new Track2Models.BlobRestoreContent( |
| 128 | + this.TimeToRestore.ToUniversalTime(), |
| 129 | + PSBlobRestoreRange.ParseBlobRestoreRanges(this.BlobRestoreRange))); |
| 130 | + |
| 131 | + // This is a temporary workaround of SDK issue https://github.com/Azure/azure-sdk-for-net/issues/29060 |
| 132 | + // The workaround is to get the raw response and parse it into the output desired |
| 133 | + // The Blob restore status should be got from SDK directly once the issue is fixed |
| 134 | + Dictionary<string, object> temp = restoreLro.GetRawResponse().Content.ToObjectFromJson() as Dictionary<string, object>; |
132 | 135 |
|
133 |
| - WriteWarning(string.Format("Restore blob ranges with Id '{0}' started. Restore blob ranges time to complete is dependent on the size of the restore.", response.Body is null ? "" : response.Body.RestoreId)); |
| 136 | + if (waitForComplete) |
| 137 | + { |
| 138 | + if (temp == null) |
| 139 | + { |
| 140 | + throw new InvalidJobStateException("Could not fetch the Blob restore response."); |
| 141 | + } |
| 142 | + PSBlobRestoreStatus blobRestoreStatus = ParseRestoreRawResponse(temp); |
| 143 | + if (blobRestoreStatus.RestoreId != null) |
| 144 | + { |
| 145 | + WriteWarning(string.Format("Restore blob ranges with Id '{0}' started. Restore blob ranges time to complete is dependent on the size of the restore.", blobRestoreStatus.RestoreId)); |
| 146 | + } |
| 147 | + else |
| 148 | + { |
| 149 | + WriteWarning(string.Format("Could not fetch the Restore Id.")); |
| 150 | + } |
134 | 151 |
|
135 |
| - Task<AzureOperationResponse<BlobRestoreStatus>> waitTask = ((StorageManagementClient)this.StorageClient).GetPostOrDeleteOperationResultAsync(response, null, new System.Threading.CancellationToken()); |
136 | 152 | try
|
137 | 153 | {
|
138 |
| - waitTask.Wait(); |
| 154 | + var result = restoreLro.WaitForCompletion().Value; |
| 155 | + WriteObject(new PSBlobRestoreStatus(result)); |
139 | 156 | }
|
140 | 157 | catch (System.AggregateException ex) when (ex.InnerException is CloudException)
|
141 | 158 | {
|
142 |
| - throw new InvalidJobStateException(string.Format("Blob ranges restore failed with information: '{0}'.", ((CloudException)ex.InnerException).Response.Content)); |
| 159 | + throw new InvalidJobStateException(string.Format("Blob ranges restore failed with information: '{0}'.", ex.ToString())); |
143 | 160 | }
|
144 |
| - |
145 |
| - AzureOperationResponse<BlobRestoreStatus> result = waitTask.Result; |
146 |
| - |
147 |
| - WriteObject(new PSBlobRestoreStatus(result.Body)); |
148 |
| - |
149 | 161 | }
|
150 | 162 | else
|
151 | 163 | {
|
152 |
| - BlobRestoreStatus status = this.StorageClient.StorageAccounts.BeginRestoreBlobRanges( |
153 |
| - this.ResourceGroupName, |
154 |
| - this.StorageAccountName, |
155 |
| - this.TimeToRestore, |
156 |
| - PSBlobRestoreRange.ParseBlobRestoreRanges(this.BlobRestoreRange)); |
157 |
| - |
158 |
| - WriteObject(new PSBlobRestoreStatus(status)); |
159 |
| - if (status != null && status.Status == BlobRestoreProgressStatus.Failed) |
| 164 | + if (temp == null) |
| 165 | + { |
| 166 | + throw new InvalidJobStateException("Could not fetch the Blob restore response."); |
| 167 | + } |
| 168 | + |
| 169 | + PSBlobRestoreStatus blobRestoreStatus = ParseRestoreRawResponse(temp); |
| 170 | + |
| 171 | + if (blobRestoreStatus.Status != null) |
| 172 | + { |
| 173 | + if (blobRestoreStatus.Status == Track2Models.BlobRestoreProgressStatus.Failed.ToString()) |
| 174 | + { |
| 175 | + throw new InvalidJobStateException("Blob ranges restore failed."); |
| 176 | + } |
| 177 | + } |
| 178 | + else |
160 | 179 | {
|
161 |
| - throw new InvalidJobStateException("Blob ranges restore failed."); |
| 180 | + WriteWarning(string.Format("Could not fetch the status.")); |
162 | 181 | }
|
| 182 | + WriteObject(blobRestoreStatus); |
163 | 183 | }
|
164 | 184 | }
|
165 | 185 | }
|
| 186 | + |
| 187 | + private PSBlobRestoreStatus ParseRestoreRawResponse(Dictionary<string, object> response) |
| 188 | + { |
| 189 | + response.TryGetValue("restoreId", out object restoreId); |
| 190 | + response.TryGetValue("status", out object jobStatus); |
| 191 | + response.TryGetValue("parameters", out object parameters); |
| 192 | + |
| 193 | + PSBlobRestoreParameters blobRestoreParameters; |
| 194 | + Dictionary<string, object> paramMap = parameters as Dictionary<string, object>; |
| 195 | + |
| 196 | + if (paramMap == null) |
| 197 | + { |
| 198 | + blobRestoreParameters = null; |
| 199 | + } |
| 200 | + else |
| 201 | + { |
| 202 | + blobRestoreParameters = new PSBlobRestoreParameters(); |
| 203 | + paramMap.TryGetValue("timetoRestore", out object timeToRestore); |
| 204 | + DateTimeOffset.TryParse(timeToRestore?.ToString(), out DateTimeOffset parseDate); |
| 205 | + blobRestoreParameters.TimeToRestore = parseDate; |
| 206 | + |
| 207 | + paramMap.TryGetValue("blobRanges", out object ranges); |
| 208 | + List<PSBlobRestoreRange> blobRestoreRanges = new List<PSBlobRestoreRange>(); |
| 209 | + |
| 210 | + object[] rangesList = ranges as object[]; |
| 211 | + foreach (object range in rangesList) |
| 212 | + { |
| 213 | + Dictionary<string, object> rangeMap = range as Dictionary<string, object>; |
| 214 | + |
| 215 | + rangeMap.TryGetValue("startRange", out object startRange); |
| 216 | + rangeMap.TryGetValue("endRange", out object endRange); |
| 217 | + |
| 218 | + PSBlobRestoreRange blobRestoreRange = new PSBlobRestoreRange |
| 219 | + { |
| 220 | + StartRange = startRange?.ToString(), |
| 221 | + EndRange = endRange?.ToString() |
| 222 | + }; |
| 223 | + |
| 224 | + blobRestoreRanges.Add(blobRestoreRange); |
| 225 | + } |
| 226 | + blobRestoreParameters.BlobRanges = blobRestoreRanges.ToArray(); |
| 227 | + } |
| 228 | + |
| 229 | + return new PSBlobRestoreStatus( |
| 230 | + status: jobStatus?.ToString(), |
| 231 | + failureReason: null, |
| 232 | + restoreId: restoreId?.ToString(), |
| 233 | + parameters: blobRestoreParameters); |
| 234 | + } |
166 | 235 | }
|
167 | 236 | }
|
0 commit comments