Skip to content

Commit 96f5092

Browse files
committed
Add new powershell cmdlet for cancel pool operation. Added tests for it and make changes to elastic pool activities
1 parent cd0497d commit 96f5092

File tree

11 files changed

+260
-11
lines changed

11 files changed

+260
-11
lines changed

src/ResourceManager/Sql/AzureRM.Sql.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ CmdletsToExport = 'Get-AzureRmSqlDatabaseTransparentDataEncryption',
189189
'Remove-AzureRmSqlServerVirtualNetworkRule',
190190
'Stop-AzureRmSqlDatabaseActivity', 'Get-AzureRmSqlServerDnsAlias',
191191
'Remove-AzureRmSqlServerDnsAlias', 'New-AzureRmSqlServerDnsAlias',
192-
'Set-AzureRmSqlServerDnsAlias'
192+
'Set-AzureRmSqlServerDnsAlias',
193+
'Stop-AzureRmSqlElasticPoolActivity'
193194

194195
# Variables to export from this module
195196
# VariablesToExport = @()

src/ResourceManager/Sql/Commands.Sql.Test/ScenarioTests/DatabaseCrudTests.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,9 @@ function Test-CancelDatabaseOperationInternal ($location = "westcentralus")
581581
# Alter all properties
582582
$db1 = Set-AzureRmSqlDatabase -ResourceGroupName $db.ResourceGroupName -ServerName $db.ServerName -DatabaseName $db.DatabaseName `
583583
-Edition Standard -RequestedServiceObjectiveName S1
584-
Assert-AreEqual $db1.DatabaseName $db.DatabaseName
585-
Assert-AreEqual $db1.Edition Standard
586-
Assert-AreEqual $db1.CurrentServiceObjectiveName S1
584+
Assert-AreEqual $db1.DatabaseName $db.DatabaseName 'Alter db name not equal'
585+
Assert-AreEqual $db1.Edition Standard 'Alter db edition not equal'
586+
Assert-AreEqual $db1.CurrentServiceObjectiveName S1 'Alter db slo not equal'
587587

588588
# list and cancel a database operation
589589
$dbactivity = Get-AzureRmSqlDatabaseActivity -ResourceGroupName $db.ResourceGroupName -ServerName $db.ServerName -DatabaseName $db.DatabaseName
@@ -598,7 +598,7 @@ function Test-CancelDatabaseOperationInternal ($location = "westcentralus")
598598
Catch
599599
{
600600
$ErrorMessage = $_.Exception.Message
601-
Assert-AreEqual True $ErrorMessage.Contains("Cannot cancel database management operation '" + $dbactivityId + "' in the current state")
601+
Assert-AreEqual True $ErrorMessage.Contains("Cannot cancel management operation '" + $dbactivityId + "' in the current state")
602602
}
603603
}
604604
finally

src/ResourceManager/Sql/Commands.Sql.Test/ScenarioTests/ElasticPoolCrudTests.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,12 @@ public void TestElasticPoolRemove()
7373
{
7474
RunPowerShellTest("Test-RemoveElasticPool");
7575
}
76+
77+
[Fact]
78+
[Trait(Category.AcceptanceType, Category.CheckIn)]
79+
public void TestElasticPoolCancelOperation()
80+
{
81+
RunPowerShellTest("Test-ListAndCancelElasticPoolOperation");
82+
}
7683
}
7784
}

src/ResourceManager/Sql/Commands.Sql.Test/ScenarioTests/ElasticPoolCrudTests.ps1

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,4 +297,57 @@ function Test-RemoveElasticPool
297297
{
298298
Remove-ResourceGroupForTest $rg
299299
}
300+
}
301+
302+
<#
303+
.SYNOPSIS
304+
Test listing and cancelling a elastic pool operation
305+
#>
306+
function Test-ListAndCancelElasticPoolOperation
307+
{
308+
# Setup
309+
$location = "southeastasia";
310+
$rg = Create-ResourceGroupForTest $location
311+
$server = Create-ServerForTest $rg $location
312+
313+
$poolName = Get-ElasticPoolName
314+
$ep = New-AzureRmSqlElasticPool -ServerName $server.ServerName -ResourceGroupName $rg.ResourceGroupName `
315+
-ElasticPoolName $poolName -Edition Premium -Dtu 125 -DatabaseDtuMin 0 -DatabaseDtuMax 50
316+
Assert-NotNull $ep
317+
318+
# Elastic pool will be Premium with DTU 125
319+
320+
try
321+
{
322+
# Update the elastic pool to premium with 250 Dtu
323+
$ep1 = Set-AzureRmSqlElasticPool -ResourceGroupName $ep.ResourceGroupName -ServerName $ep.ServerName -ElasticPoolName $ep.ElasticPoolName `
324+
-Edition Premium -Dtu 250 -DatabaseDtuMin 25 -DatabaseDtuMax 125
325+
Assert-AreEqual $ep.ElasticPoolName $ep1.ElasticPoolName
326+
Assert-AreEqual Premium $ep1.Edition
327+
Assert-AreEqual 250 $ep1.Dtu
328+
329+
# List and Cancel the elastic pool update operation
330+
$epactivity = Get-AzureRmSqlElasticPoolActivity -ResourceGroupName $rg.ResourceGroupName -ServerName $server.ServerName -ElasticPoolName $poolName
331+
$epactivityId
332+
333+
For($i=0; $i -lt $epactivity.Length; $i++) {
334+
if($epactivity[$i].Operation -eq "UPDATE"){
335+
$epactivityId = $epactivity[$i].OperationId
336+
}
337+
}
338+
339+
try
340+
{
341+
$activityCancel = Stop-AzureRmSqlElasticPoolActivity -ResourceGroupName $ep.ResourceGroupName -ServerName $ep.ServerName -ElasticPoolName $ep.ElasticPoolName -OperationId $epactivityId
342+
}
343+
Catch
344+
{
345+
$ErrorMessage = $_.Exception.Message
346+
Assert-AreEqual True $ErrorMessage.Contains("Cannot cancel management operation '" + $epactivityId + "' in the current state") $ErrorMessage
347+
}
348+
}
349+
finally
350+
{
351+
Remove-ResourceGroupForTest $rg
352+
}
300353
}

src/ResourceManager/Sql/Commands.Sql/Database/Model/AzureSqlDatabaseActivityModel.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,20 @@ public class DatabaseState
9797
/// Gets or sets the state of the properties associated with the request
9898
/// </summary>
9999
public DatabaseState Properties { get; set; }
100+
101+
/// <summary>
102+
/// Gets or sets the estimated the completion time of the database operation
103+
/// </summary>
104+
public DateTime? EstimatedCompletionTime { get; set; }
105+
106+
/// <summary>
107+
/// Gets or sets the detailed description of the database operation
108+
/// </summary>
109+
public string Description { get; set; }
110+
111+
/// <summary>
112+
/// Gets or sets the value to indicate if the database operation can be cancelled
113+
/// </summary>
114+
public bool? IsCancellable { get; set; }
100115
}
101116
}

src/ResourceManager/Sql/Commands.Sql/Database/Services/AzureSqlDatabaseAdapter.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,10 @@ internal IEnumerable<AzureSqlDatabaseActivityModel> ListDatabaseActivity(string
306306
{
307307
Current = new Dictionary<string, string>(),
308308
Requested = new Dictionary<string, string>()
309-
}
309+
},
310+
EstimatedCompletionTime = r.EstimatedCompletionTime,
311+
Description = r.Description,
312+
IsCancellable = r.IsCancellable
310313
};
311314
});
312315

src/ResourceManager/Sql/Commands.Sql/Elastic Pools/Cmdlet/AzureSqlElasticPoolActivityCmdletBase.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Microsoft.Azure.Commands.Sql.Common;
1818
using Microsoft.Azure.Commands.Sql.ElasticPool.Model;
1919
using Microsoft.Azure.Commands.Sql.ElasticPool.Services;
20+
using System;
2021
using System.Collections.Generic;
2122
using System.Management.Automation;
2223

@@ -44,6 +45,15 @@ public abstract class AzureSqlElasticPoolActivityCmdletBase : AzureSqlCmdletBase
4445
[ValidateNotNullOrEmpty]
4546
public string ElasticPoolName { get; set; }
4647

48+
/// <summary>
49+
/// Gets or sets the operation id to use.
50+
/// </summary>
51+
[Parameter(Mandatory = false,
52+
ValueFromPipelineByPropertyName = true,
53+
HelpMessage = "The ID of the operation to retrieve.")]
54+
[ValidateNotNullOrEmpty]
55+
public Guid? OperationId { get; set; }
56+
4757
/// <summary>
4858
/// Initializes the adapter
4959
/// </summary>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Commands.Sql.ElasticPool.Model;
16+
using System.Collections.Generic;
17+
using System.Management.Automation;
18+
19+
namespace Microsoft.Azure.Commands.Sql.ElasticPool.Cmdlet
20+
{
21+
[Cmdlet(VerbsLifecycle.Stop, "AzureRmSqlElasticPoolActivity", SupportsShouldProcess = true)]
22+
23+
public class StopAzureSqlElasticPoolActivity : AzureSqlElasticPoolActivityCmdletBase
24+
{
25+
/// <summary>
26+
/// Gets elastic pool activity
27+
/// </summary>
28+
/// <returns>List of elastic pool activies</returns>
29+
protected override IEnumerable<AzureSqlElasticPoolActivityModel> GetEntity()
30+
{
31+
return ModelAdapter.GetElasticPoolActivity(this.ResourceGroupName, this.ServerName, this.ElasticPoolName);
32+
}
33+
34+
/// <summary>
35+
/// No user input to apply to model
36+
/// </summary>
37+
/// <param name="model">Model retrieved from service</param>
38+
/// <returns>The model that wa passed in</returns>
39+
protected override IEnumerable<AzureSqlElasticPoolActivityModel> ApplyUserInputToModel(IEnumerable<AzureSqlElasticPoolActivityModel> model)
40+
{
41+
return model;
42+
}
43+
44+
/// <summary>
45+
/// No changes to persist to server
46+
/// </summary>
47+
/// <param name="entity">The output of apply user input to model</param>
48+
/// <returns>The input entity</returns>
49+
protected override IEnumerable<AzureSqlElasticPoolActivityModel> PersistChanges(IEnumerable<AzureSqlElasticPoolActivityModel> entity)
50+
{
51+
return ModelAdapter.CancelElasticPoolActivity(this.ResourceGroupName, this.ServerName, this.ElasticPoolName, this.OperationId);
52+
}
53+
}
54+
}

src/ResourceManager/Sql/Commands.Sql/Elastic Pools/Model/AzureSqlElasticPoolActivityModel.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,20 @@ public class AzureSqlElasticPoolActivityModel
100100
/// Gets or sets the requested storage limit in GB
101101
/// </summary>
102102
public long? RequestedStorageLimitInGB { get; set; }
103+
104+
/// <summary>
105+
/// Gets or sets the estimated completion time of the elastic pool operation
106+
/// </summary>
107+
public DateTime? EstimatedCompletionTime { get; set; }
108+
109+
/// <summary>
110+
/// Gets or sets the description of the elastic pool operation
111+
/// </summary>
112+
public string Description { get; set; }
113+
114+
/// <summary>
115+
/// Gets or sets the value to indicate if the elastic pool operation can be cancelled
116+
/// </summary>
117+
public bool? IsCancellable { get; set; }
103118
}
104119
}

src/ResourceManager/Sql/Commands.Sql/Elastic Pools/Services/AzureSqlElasticPoolAdapter.cs

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
using Microsoft.Azure.Commands.ResourceManager.Common.Tags;
2626
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
2727
using DatabaseEdition = Microsoft.Azure.Commands.Sql.Database.Model.DatabaseEdition;
28+
using System.Globalization;
2829

2930
namespace Microsoft.Azure.Commands.Sql.ElasticPool.Services
3031
{
@@ -164,12 +165,61 @@ internal ICollection<AzureSqlDatabaseModel> ListElasticPoolDatabases(string reso
164165
/// <returns>A list of Elastic Pool Activities</returns>
165166
internal IList<AzureSqlElasticPoolActivityModel> GetElasticPoolActivity(string resourceGroupName, string serverName, string poolName)
166167
{
167-
var resp = Communicator.ListActivity(resourceGroupName, serverName, poolName);
168+
var activityResp = Communicator.ListActivity(resourceGroupName, serverName, poolName);
169+
var operationResp = Communicator.ListOperation(resourceGroupName, serverName, poolName);
168170

169-
return resp.Select((activity) =>
171+
var resp = from activity in activityResp
172+
join operation in operationResp
173+
on activity.OperationId equals new Guid(operation.Name)
174+
select new {
175+
elasticPoolName = activity.ElasticPoolName,
176+
endTime = activity.EndTime,
177+
errorCode = activity.ErrorCode,
178+
errorMessage = activity.ErrorMessage,
179+
errorSeverity = activity.ErrorSeverity,
180+
operation = activity.Operation,
181+
operationId = activity.OperationId,
182+
percentComplete = activity.PercentComplete,
183+
requestedDatabaseDtuMax = activity.RequestedDatabaseDtuMax,
184+
requestedDatabaseDtuMin = activity.RequestedDatabaseDtuMin,
185+
requestedDtu = activity.RequestedDtu,
186+
requestedElasticPoolName = activity.RequestedElasticPoolName,
187+
requestedStorageLimitInGB = activity.RequestedStorageLimitInGB,
188+
serverName = activity.ServerName,
189+
startTime = activity.StartTime,
190+
state = activity.State,
191+
estimatedCompletionTime = operation.EstimatedCompletionTime,
192+
description = operation.Description,
193+
isCancellable = operation.IsCancellable
194+
};
195+
196+
IEnumerable<AzureSqlElasticPoolActivityModel> listResponse = resp.Select((r) =>
170197
{
171-
return CreateActivityModelFromResponse(activity);
172-
}).ToList();
198+
return new AzureSqlElasticPoolActivityModel()
199+
{
200+
ElasticPoolName = r.elasticPoolName,
201+
EndTime = r.endTime,
202+
ErrorCode = r.errorCode,
203+
ErrorMessage = r.errorMessage,
204+
ErrorSeverity = r.errorSeverity,
205+
Operation = r.operation,
206+
OperationId = r.operationId,
207+
PercentComplete = r.percentComplete,
208+
RequestedDatabaseDtuMax = r.requestedDatabaseDtuMax,
209+
RequestedDatabaseDtuMin = r.requestedDatabaseDtuMin,
210+
RequestedDtu = r.requestedDtu,
211+
RequestedElasticPoolName = r.requestedElasticPoolName,
212+
RequestedStorageLimitInGB = r.requestedStorageLimitInGB,
213+
ServerName = r.serverName,
214+
StartTime = r.startTime,
215+
State = r.state,
216+
EstimatedCompletionTime = r.estimatedCompletionTime,
217+
Description = r.description,
218+
IsCancellable = r.isCancellable
219+
};
220+
});
221+
222+
return listResponse.ToList();
173223
}
174224

175225
/// <summary>
@@ -189,6 +239,27 @@ internal IList<AzureSqlDatabaseActivityModel> ListElasticPoolDatabaseActivity(st
189239
}).ToList();
190240
}
191241

242+
/// <summary>
243+
/// Cancel teh elastic pool activity
244+
/// </summary>
245+
/// <param name="resourceGroupName">The name of the resource group</param>
246+
/// <param name="serverName">The name of the Azure Sql Database server</param>
247+
/// <param name="elasticPoolName">The name of the elastic pool</param>
248+
/// <param name="operationId">The Operation ID</param>
249+
/// <returns></returns>
250+
internal IEnumerable<AzureSqlElasticPoolActivityModel> CancelElasticPoolActivity(string resourceGroupName, string serverName, string elasticPoolName, Guid? operationId)
251+
{
252+
if (!operationId.HasValue)
253+
{
254+
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, Microsoft.Azure.Commands.Sql.Properties.Resources.OperationIdRequired));
255+
}
256+
257+
Communicator.CancelOperation(resourceGroupName, serverName, elasticPoolName, operationId.Value);
258+
259+
// After Cancel event is fired, state will be in 'CancelInProgress' for a while but should expect to finish in a minute
260+
return GetElasticPoolActivity(resourceGroupName, serverName, elasticPoolName);
261+
}
262+
192263
/// <summary>
193264
/// Converts a model received from the server to a powershell model
194265
/// </summary>
@@ -244,7 +315,6 @@ private AzureSqlElasticPoolActivityModel CreateActivityModelFromResponse(Elastic
244315
State = model.State
245316
};
246317

247-
248318
return activity;
249319
}
250320

src/ResourceManager/Sql/Commands.Sql/Elastic Pools/Services/AzureSqlElasticPoolCommunicator.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
using System.Linq;
2727
using System.Threading;
2828
using Microsoft.Azure.Management.Sql.LegacySdk.Models;
29+
using System;
2930

3031
namespace Microsoft.Azure.Commands.Sql.ElasticPool.Services
3132
{
@@ -136,6 +137,26 @@ public void Remove(string resourceGroupName, string serverName, string elasticPo
136137
return GetCurrentSqlClient().ElasticPoolActivities.ListByElasticPool(resourceGroupName, serverName, elasticPoolName).ToList();
137138
}
138139

140+
/// <summary>
141+
/// Gets Elastic Pool Operations
142+
/// </summary>
143+
/// <param name="resourceGroupName"></param>
144+
/// <param name="serverName"></param>
145+
/// <param name="elasticPoolName"></param>
146+
/// <returns></returns>
147+
public IList<Management.Sql.Models.ElasticPoolOperation> ListOperation(string resourceGroupName, string serverName, string elasticPoolName)
148+
{
149+
return GetCurrentSqlClient().ElasticPoolOperations.ListByElasticPool(resourceGroupName, serverName, elasticPoolName).ToList();
150+
}
151+
152+
/// <summary>
153+
/// Cancel elastic pool activities
154+
/// </summary>
155+
public void CancelOperation(string resourceGroupName, string serverName, string elasticPoolName, Guid operationId)
156+
{
157+
GetCurrentSqlClient().ElasticPoolOperations.Cancel(resourceGroupName, serverName, elasticPoolName, operationId);
158+
}
159+
139160
/// <summary>
140161
/// Gets Elastic Pool Database Activity
141162
/// </summary>

0 commit comments

Comments
 (0)