diff --git a/ChangeLog.md b/ChangeLog.md
index 65d7f779e90f..d574b4d8ff7a 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -43,6 +43,12 @@
* Get-AzureSqlServerActiveDirectoryAdministrator
* Set-AzureSqlServerActiveDirectoryAdministrator
* Remove-AzureSqlServerActiveDirectoryAdministrator
+* SQL Server VM cmdlets (ARM)
+ * New-AzureVMSqlServerAutoPatchingConfig
+ * New-AzureVMSqlServerAutoBackupConfig
+ * Set-AzureVMSqlServerExtension
+ * Get-AzureVMSqlServerExtension
+ * Remove-AzureVMSqlServerExtension
## 2015.08.17 version 0.9.7
* Azure Profile cmdlets
diff --git a/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj b/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj
index b574b78b254a..35f899433f69 100644
--- a/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj
+++ b/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj
@@ -223,6 +223,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs b/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs
index 4b8a9a48c32f..69668d16bab2 100644
--- a/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs
+++ b/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs
@@ -99,5 +99,8 @@ public static class ProfileNouns
public const string VirtualMachineDscConfiguration = "AzureVMDscConfiguration";
public const string Vhd = "AzureVhd";
+
+ // Sql Server
+ public const string VirtualMachineSqlServerExtension = "AzureVMSqlServerExtension";
}
}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoBackupSettings.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoBackupSettings.cs
new file mode 100644
index 000000000000..8ee4fc21c38d
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoBackupSettings.cs
@@ -0,0 +1,56 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+using Newtonsoft.Json;
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// Autobackup settings to configure managed backup on SQL VM
+ ///
+ public class AutoBackupSettings
+ {
+ ///
+ /// Defines if the Auto-backup feature is enabled or disabled
+ ///
+ public bool Enable { get; set; }
+
+ ///
+ /// Defines if backups will be encrypted or not
+ ///
+ public bool EnableEncryption { get; set; }
+
+ ///
+ /// Defines the number of days to keep the backups
+ ///
+ public int RetentionPeriod { get; set; }
+
+ ///
+ /// storage url where databases will be backed up
+ ///
+ [JsonIgnoreAttribute()]
+ public string StorageUrl { get; set; }
+
+ ///
+ /// Key of storage account used by managed backup
+ ///
+ [JsonIgnoreAttribute()]
+ public string StorageAccessKey { get; set; }
+
+ ///
+ /// Password required for certification when encryption is enabled
+ ///
+ [JsonIgnoreAttribute()]
+ public string Password { get; set; }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoPatchingSettings.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoPatchingSettings.cs
new file mode 100644
index 000000000000..f9dfd45d132d
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoPatchingSettings.cs
@@ -0,0 +1,47 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// AutoPatching settings to configure auto-patching on SQL VM
+ ///
+ public class AutoPatchingSettings
+ {
+ ///
+ /// Enable / Disable auto patching
+ ///
+ public bool Enable { get; set; }
+
+ ///
+ /// Day of the week
+ ///
+ public string DayOfWeek { get; set; }
+
+ ///
+ /// Maintainance Windows Start hour ( 0 to 23 )
+ ///
+ public int MaintenanceWindowStartingHour { get; set; }
+
+ ///
+ /// Maintainance window duration in minutes
+ ///
+ public int MaintenanceWindowDuration { get; set; }
+
+ ///
+ /// Patch category returned as string
+ ///
+ public string PatchCategory { get; set; }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoTelemetrySettings.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoTelemetrySettings.cs
new file mode 100644
index 000000000000..30d272831004
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerAutoTelemetrySettings.cs
@@ -0,0 +1,27 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// AutoTelemetry settings to configure telemetry collection on SQL VM
+ ///
+ public class AutoTelemetrySettings
+ {
+ ///
+ /// The name of the region the VM is running in.
+ ///
+ public string Region { get; set; }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerPrivateSettings.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerPrivateSettings.cs
new file mode 100644
index 000000000000..30a6ffb2c61a
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerPrivateSettings.cs
@@ -0,0 +1,37 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// SQL Server extension's private settings
+ ///
+ public class SqlServerPrivateSettings
+ {
+ ///
+ /// Azure blob store URL
+ ///
+ public string StorageUrl;
+
+ ///
+ /// Storage account access key
+ ///
+ public string StorageAccessKey;
+
+ ///
+ /// Password required for certification when encryption is enabled
+ ///
+ public string Password;
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerPublicSettings.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerPublicSettings.cs
new file mode 100644
index 000000000000..d10c6a466a34
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/AzureVMSqlServerPublicSettings.cs
@@ -0,0 +1,37 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// SQL Server Extension's public settings
+ ///
+ public class SqlServerPublicSettings
+ {
+ ///
+ /// Auto patching settings
+ ///
+ public AutoPatchingSettings AutoPatchingSettings { get; set; }
+
+ ///
+ /// Auto-backup settings
+ ///
+ public AutoBackupSettings AutoBackupSettings { get; set; }
+
+ ///
+ /// Auto-telemetry settings
+ ///
+ public AutoTelemetrySettings AutoTelemetrySettings { get; set; }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/GetAzureVMSqlServerExtensionCommand.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/GetAzureVMSqlServerExtensionCommand.cs
new file mode 100644
index 000000000000..e7433aeb6558
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/GetAzureVMSqlServerExtensionCommand.cs
@@ -0,0 +1,134 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.Compute.Common;
+using Microsoft.Azure.Commands.Compute.Models;
+using Microsoft.Azure.Management.Compute;
+using System;
+using System.Management.Automation;
+using Newtonsoft.Json;
+using System.Globalization;
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ [Cmdlet(
+ VerbsCommon.Get,
+ ProfileNouns.VirtualMachineSqlServerExtension,
+ DefaultParameterSetName = GetSqlServerExtensionParamSetName),
+ OutputType(
+ typeof(VirtualMachineSqlServerExtensionContext))]
+ public class GetAzureVMSqlServerExtensionCommand : VirtualMachineExtensionBaseCmdlet
+ {
+ protected const string GetSqlServerExtensionParamSetName = "GetSqlServerExtension";
+
+ [Parameter(
+ Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The resource group name.")]
+ [ValidateNotNullOrEmpty]
+ public string ResourceGroupName { get; set; }
+
+ [Parameter(
+ Mandatory = true,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The virtual machine name.")]
+ [ValidateNotNullOrEmpty]
+ public string VMName { get; set; }
+
+ [Parameter(
+ Position = 2,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Name of the ARM resource that represents the extension. The Set-AzureVMSqlServerExtension cmdlet sets this name to " +
+ "'Microsoft.SqlServer.Management.SqlIaaSAgent', which is the same value used by Get-AzureVMSqlServerExtension. Specify this parameter only if you changed " +
+ "the default name in the Set cmdlet or used a different resource name in an ARM template.")]
+ [ValidateNotNullOrEmpty]
+ public string Name { get; set; }
+
+ public override void ExecuteCmdlet()
+ {
+ base.ExecuteCmdlet();
+
+ if (String.IsNullOrEmpty(Name))
+ {
+ Name = VirtualMachineSqlServerExtensionContext.ExtensionPublishedNamespace + "." + VirtualMachineSqlServerExtensionContext.ExtensionPublishedName;
+ }
+
+ var result = VirtualMachineExtensionClient.GetWithInstanceView(ResourceGroupName, VMName, Name);
+ var extension = result.ToPSVirtualMachineExtension(ResourceGroupName);
+
+ if (
+ extension.Publisher.Equals(VirtualMachineSqlServerExtensionContext.ExtensionPublishedNamespace,
+ StringComparison.InvariantCultureIgnoreCase) &&
+ extension.ExtensionType.Equals(VirtualMachineSqlServerExtensionContext.ExtensionPublishedName,
+ StringComparison.InvariantCultureIgnoreCase))
+ {
+ WriteObject(GetSqlServerExtensionContext(extension));
+ }
+ else
+ {
+ WriteObject(null);
+ }
+ }
+
+ private VirtualMachineSqlServerExtensionContext GetSqlServerExtensionContext(PSVirtualMachineExtension extension)
+ {
+ SqlServerPublicSettings extensionPublicSettings = null;
+ VirtualMachineSqlServerExtensionContext context = null;
+
+ try
+ {
+ extensionPublicSettings = string.IsNullOrEmpty(extension.PublicSettings) ? null
+ : JsonConvert.DeserializeObject(extension.PublicSettings);
+
+ // #$ISSUE- extension.Statuses is always null, follow up with Azure team
+ context = new VirtualMachineSqlServerExtensionContext
+ {
+ ResourceGroupName = extension.ResourceGroupName,
+ Name = extension.Name,
+ Location = extension.Location,
+ Etag = extension.Etag,
+ Publisher = extension.Publisher,
+ ExtensionType = extension.ExtensionType,
+ TypeHandlerVersion = extension.TypeHandlerVersion,
+ Id = extension.Id,
+ PublicSettings = JsonConvert.SerializeObject(extensionPublicSettings),
+ ProtectedSettings = extension.ProtectedSettings,
+ ProvisioningState = extension.ProvisioningState,
+ AutoBackupSettings = extensionPublicSettings.AutoBackupSettings,
+ AutoPatchingSettings = extensionPublicSettings.AutoPatchingSettings,
+ Statuses = extension.Statuses
+ };
+
+ }
+ catch (JsonException e)
+ {
+ ThrowTerminatingError(
+ new ErrorRecord(
+ new JsonException(
+ String.Format(
+ CultureInfo.CurrentUICulture,
+ Properties.Resources.AzureVMSqlServerWrongSettingsFormat,
+ extension.PublicSettings),
+ e),
+ string.Empty,
+ ErrorCategory.ParserError,
+ null));
+ }
+
+ return context;
+ }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/NewAzureVMSqlServerAutoBackupConfig.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/NewAzureVMSqlServerAutoBackupConfig.cs
new file mode 100644
index 000000000000..33cea12ad0a5
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/NewAzureVMSqlServerAutoBackupConfig.cs
@@ -0,0 +1,208 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System;
+using System.Management.Automation;
+using System.Security;
+using Microsoft.WindowsAzure.Commands.Common.Storage;
+using Microsoft.WindowsAzure.Storage;
+using Microsoft.Azure.Management.Storage;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// Helper cmdlet to construct instance of AutoBackup settings class
+ ///
+ [Cmdlet(
+ VerbsCommon.New,
+ AzureVMSqlServerAutoBackupConfigNoun,
+ DefaultParameterSetName = StorageUriParamSetName),
+ OutputType(
+ typeof(AutoBackupSettings))]
+ public class NewAzureVMSqlServerAutoBackupConfigCommand : PSCmdlet
+ {
+ protected const string AzureVMSqlServerAutoBackupConfigNoun = "AzureVMSqlServerAutoBackupConfig";
+
+ protected const string StorageContextParamSetName = "StorageContextSqlServerAutoBackup";
+ protected const string StorageUriParamSetName = "StorageUriSqlServerAutoBackup";
+
+ [Parameter(
+ Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The resource group name.")]
+ [ValidateNotNullOrEmpty]
+ public string ResourceGroupName { get; set; }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Enable Automatic Backup.")]
+ [ValidateNotNullOrEmpty]
+ public SwitchParameter Enable { get; set; }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 2,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Backup Retention period in days.")]
+ [ValidateNotNullOrEmpty]
+ public int RetentionPeriodInDays { get; set; }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 3,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Enable Backup Encryption.")]
+ [ValidateNotNullOrEmpty]
+ public SwitchParameter EnableEncryption { get; set; }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 4,
+ ValueFromPipelineByPropertyName = false,
+ HelpMessage = "Certificate password.")]
+ public SecureString CertificatePassword { get; set; }
+
+ [Parameter(
+ ParameterSetName = StorageContextParamSetName,
+ Mandatory = false,
+ Position = 5,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The storage connection context")]
+ [ValidateNotNullOrEmpty]
+ public AzureStorageContext StorageContext
+ {
+ get;
+ set;
+ }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 4,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The storage uri")]
+ [ValidateNotNullOrEmpty]
+ public Uri StorageUri
+ {
+ get;
+ set;
+ }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 5,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The storage access key")]
+ [ValidateNotNullOrEmpty]
+ public SecureString StorageKey
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Initialzies a new instance of the class.
+ ///
+ public NewAzureVMSqlServerAutoBackupConfigCommand()
+ {
+ }
+
+ ///
+ /// Creates and returns object.
+ ///
+ protected override void ProcessRecord()
+ {
+ AutoBackupSettings autoBackupSettings = new AutoBackupSettings();
+
+ autoBackupSettings.Enable = (Enable.IsPresent) ? Enable.ToBool() : false;
+ autoBackupSettings.EnableEncryption = (EnableEncryption.IsPresent) ? EnableEncryption.ToBool() : false;
+ autoBackupSettings.RetentionPeriod = RetentionPeriodInDays;
+
+ switch(ParameterSetName)
+ {
+ case StorageContextParamSetName:
+ autoBackupSettings.StorageUrl = StorageContext.BlobEndPoint;
+ autoBackupSettings.StorageAccessKey = this.GetStorageKey();
+ break;
+
+ case StorageUriParamSetName:
+ autoBackupSettings.StorageUrl = (StorageUri == null)? null: StorageUri.ToString();
+ autoBackupSettings.StorageAccessKey = (StorageKey == null)? null: ConvertToUnsecureString(StorageKey);
+ break;
+ }
+
+ // Check if certificate password was set
+ autoBackupSettings.Password = (CertificatePassword == null) ? null : ConvertToUnsecureString(CertificatePassword);
+
+ WriteObject(autoBackupSettings);
+ }
+
+ protected string GetStorageKey()
+ {
+ string storageKey = string.Empty;
+ string storageName = (this.StorageContext == null) ? null : this.StorageContext.StorageAccountName;
+
+ if (!string.IsNullOrEmpty(storageName))
+ {
+ var storageClient = new StorageManagementClient();
+
+ var storageAccount = storageClient.StorageAccounts.GetProperties(this.ResourceGroupName, storageName);
+
+ if (storageAccount != null)
+ {
+ var keys = storageClient.StorageAccounts.ListKeys(this.ResourceGroupName, storageName);
+
+ if (keys != null && keys.StorageAccountKeys != null)
+ {
+ storageKey = !string.IsNullOrEmpty(keys.StorageAccountKeys.Key1) ?
+ keys.StorageAccountKeys.Key1 :
+ keys.StorageAccountKeys.Key2;
+ }
+ }
+ }
+
+ return storageKey;
+ }
+
+ ///
+ /// convert secure string to regular string
+ /// $Issue - for ARM cmdlets, check if there is a similair helper class library like Microsoft.WindowsAzure.Commands.ServiceManagement.Helpers
+ ///
+ ///
+ ///
+ [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ private static string ConvertToUnsecureString(SecureString securePassword)
+ {
+ if (securePassword == null)
+ {
+ throw new ArgumentNullException("securePassword");
+ }
+
+ IntPtr unmanagedString = IntPtr.Zero;
+ try
+ {
+ unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
+ return Marshal.PtrToStringUni(unmanagedString);
+ }
+ finally
+ {
+ Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
+ }
+ }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/NewAzureVMSqlServerAutoPatchingConfig.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/NewAzureVMSqlServerAutoPatchingConfig.cs
new file mode 100644
index 000000000000..c589a75436d5
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/NewAzureVMSqlServerAutoPatchingConfig.cs
@@ -0,0 +1,71 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using System.Management.Automation;
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// Helper cmdlet to construct instance of AutoPatching settings class
+ ///
+ [Cmdlet(
+ VerbsCommon.New,
+ AzureVMSqlServerAutoPatchingConfigNoun),
+ OutputType(
+ typeof(AutoPatchingSettings))]
+ public class NewAzureVMSqlServerAutoPatchingConfigCommand : PSCmdlet
+ {
+ protected const string AzureVMSqlServerAutoPatchingConfigNoun = "AzureVMSqlServerAutoPatchingConfig";
+
+ [Parameter]
+ public SwitchParameter Enable { get; set; }
+
+ [Parameter]
+ [ValidateSetAttribute(new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Everyday" })]
+ public string DayOfWeek { get; set; }
+
+ [Parameter]
+ public int MaintenanceWindowStartingHour { get; set; }
+
+ [Parameter]
+ public int MaintenanceWindowDuration { get; set; }
+
+ [Parameter]
+ [ValidateSetAttribute(new string[] { "Important" })]
+ public string PatchCategory { get; set; }
+
+ ///
+ /// Initialzies a new instance of the class.
+ ///
+ public NewAzureVMSqlServerAutoPatchingConfigCommand()
+ {
+ }
+
+ ///
+ /// Creates and returns object.
+ ///
+ protected override void ProcessRecord()
+ {
+ AutoPatchingSettings autoPatchingSettings = new AutoPatchingSettings();
+
+ autoPatchingSettings.Enable = (Enable.IsPresent) ? Enable.ToBool() : false;
+ autoPatchingSettings.DayOfWeek = DayOfWeek;
+ autoPatchingSettings.MaintenanceWindowStartingHour = MaintenanceWindowStartingHour;
+ autoPatchingSettings.MaintenanceWindowDuration = MaintenanceWindowDuration;
+ autoPatchingSettings.PatchCategory = PatchCategory;
+
+ WriteObject(autoPatchingSettings);
+ }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/RemoveAzureVMSqlServerExtensionCommand.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/RemoveAzureVMSqlServerExtensionCommand.cs
new file mode 100644
index 000000000000..cd6ba702c934
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/RemoveAzureVMSqlServerExtensionCommand.cs
@@ -0,0 +1,72 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.Compute.Common;
+using Microsoft.Azure.Management.Compute;
+using System.Management.Automation;
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ [Cmdlet(
+ VerbsCommon.Remove,
+ ProfileNouns.VirtualMachineSqlServerExtension)]
+ public class RemoveAzureVMSqlServerExtensionCommand : VirtualMachineExtensionBaseCmdlet
+ {
+ [Parameter(
+ Mandatory = true,
+ Position = 0,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The resource group name.")]
+ [ValidateNotNullOrEmpty]
+ public string ResourceGroupName { get; set; }
+
+ [Alias("ResourceName")]
+ [Parameter(
+ Mandatory = true,
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The virtual machine name.")]
+ [ValidateNotNullOrEmpty]
+ public string VMName { get; set; }
+
+ [Alias("ExtensionName")]
+ [Parameter(
+ Mandatory = true,
+ Position = 2,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Name of the ARM resource that represents the extension. This is defaulted to 'Microsoft.SqlServer.Management.SqlIaaSAgent'.")]
+ [ValidateNotNullOrEmpty]
+ public string Name { get; set; }
+
+ public override void ExecuteCmdlet()
+ {
+ base.ExecuteCmdlet();
+
+ ExecuteClientAction(() =>
+ {
+ if (string.IsNullOrEmpty(Name))
+ {
+ Name = VirtualMachineSqlServerExtensionContext.ExtensionPublishedNamespace + "." + VirtualMachineSqlServerExtensionContext.ExtensionPublishedName;
+ }
+
+ if (this.ShouldContinue(Properties.Resources.VirtualMachineExtensionRemovalConfirmation, Properties.Resources.VirtualMachineExtensionRemovalCaption))
+ {
+ var op = this.VirtualMachineExtensionClient.Delete(this.ResourceGroupName, this.VMName, this.Name);
+ WriteObject(op);
+ }
+ });
+ }
+
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/SetAzureVMSqlServerExtensionCommand.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/SetAzureVMSqlServerExtensionCommand.cs
new file mode 100644
index 000000000000..3570d6447f18
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/SetAzureVMSqlServerExtensionCommand.cs
@@ -0,0 +1,158 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+using AutoMapper;
+using Microsoft.Azure.Commands.Compute.Common;
+using Microsoft.Azure.Commands.Compute.Models;
+using Microsoft.Azure.Management.Compute;
+using Microsoft.Azure.Management.Compute.Models;
+using Newtonsoft.Json;
+using System.Management.Automation;
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ [Cmdlet(
+ VerbsCommon.Set,
+ ProfileNouns.VirtualMachineSqlServerExtension)]
+ public class SetAzureSqlServerExtensionCommand : VirtualMachineExtensionBaseCmdlet
+ {
+ ///
+ /// The specific version of the SqlServer extension that Set-AzureVMSqlServerExtension will
+ /// apply the settings to.
+ ///
+ [Alias("HandlerVersion")]
+ [Parameter(
+ Position = 1,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The version of the SqlServer extension that Set-AzureVMSqlServerExtension will apply the settings to. " +
+ "Allowed format N.N")]
+ [ValidateNotNullOrEmpty]
+ public string Version { get; set; }
+
+ [Parameter(
+ Mandatory = true,
+ Position = 2,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The resource group name.")]
+ [ValidateNotNullOrEmpty]
+ public string ResourceGroupName { get; set; }
+
+ [Parameter(
+ Mandatory = true,
+ Position = 3,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Name of the virtual machine where Sql Server extension handler would be installed.")]
+ [ValidateNotNullOrEmpty]
+ public string VMName { get; set; }
+
+ [Parameter(
+ ValueFromPipelineByPropertyName = true,
+ Position = 4,
+ HelpMessage = "Name of the ARM resource that represents the extension. This is defaulted to 'Microsoft.SqlServer.Management.SqlIaaSAgent'.")]
+ [ValidateNotNullOrEmpty]
+ public string Name { get; set; }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 5,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The Automatic Patching configuration.")]
+ [ValidateNotNullOrEmpty]
+ public AutoPatchingSettings AutoPatchingSettings { get; set; }
+
+ [Parameter(
+ Mandatory = false,
+ Position = 6,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "The Automatic Backup configuration.")]
+ [ValidateNotNullOrEmpty]
+ public AutoBackupSettings AutoBackupSettings { get; set; }
+
+ [Parameter(
+ Position = 7,
+ ValueFromPipelineByPropertyName = true,
+ HelpMessage = "Location of the resource.")]
+ [ValidateNotNullOrEmpty]
+ public string Location { get; set; }
+
+ public override void ExecuteCmdlet()
+ {
+ base.ExecuteCmdlet();
+
+ var parameters = new VirtualMachineExtension
+ {
+ Location = this.Location,
+ Name = Name ?? VirtualMachineSqlServerExtensionContext.ExtensionPublishedNamespace + "." + VirtualMachineSqlServerExtensionContext.ExtensionPublishedName,
+ Type = VirtualMachineExtensionType,
+ Publisher = VirtualMachineSqlServerExtensionContext.ExtensionPublishedNamespace,
+ ExtensionType = VirtualMachineSqlServerExtensionContext.ExtensionPublishedName,
+ TypeHandlerVersion = string.IsNullOrEmpty(this.Version) ? VirtualMachineSqlServerExtensionContext.ExtensionDefaultVersion : this.Version,
+ Settings = this.GetPublicConfiguration(),
+ ProtectedSettings = this.GetPrivateConfiguration(),
+ };
+
+ // Add retry logic due to CRP service restart known issue CRP bug: 3564713
+ // Similair approach taken in DSC cmdlet as well
+ var count = 1;
+ ComputeLongRunningOperationResponse op = null;
+ while (count <= 2)
+ {
+ op = VirtualMachineExtensionClient.CreateOrUpdate(
+ ResourceGroupName,
+ VMName,
+ parameters);
+
+ if (ComputeOperationStatus.Failed.Equals(op.Status) && op.Error != null && "InternalExecutionError".Equals(op.Error.Code))
+ {
+ count++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ var result = Mapper.Map(op);
+ WriteObject(result);
+ }
+
+ ///
+ /// Returns the public configuration as string
+ ///
+ ///
+ private string GetPublicConfiguration()
+ {
+ return JsonConvert.SerializeObject(
+ new SqlServerPublicSettings
+ {
+ AutoPatchingSettings = this.AutoPatchingSettings,
+ AutoBackupSettings = this.AutoBackupSettings,
+ AutoTelemetrySettings = new AutoTelemetrySettings() { Region = this.Location}
+ });
+ }
+
+ ///
+ /// Returns private configuration as string
+ ///
+ ///
+ private string GetPrivateConfiguration()
+ {
+ return JsonConvert.SerializeObject(
+ new SqlServerPrivateSettings
+ {
+ StorageUrl = (this.AutoBackupSettings == null) ? string.Empty : this.AutoBackupSettings.StorageUrl,
+ StorageAccessKey = (this.AutoBackupSettings == null) ? string.Empty : this.AutoBackupSettings.StorageAccessKey,
+ Password = (this.AutoBackupSettings == null) ? string.Empty : this.AutoBackupSettings.Password
+ });
+ }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/VirtualMachineSqlServerExtensionContext.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/VirtualMachineSqlServerExtensionContext.cs
new file mode 100644
index 000000000000..c172036af9e1
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute/Extension/SqlServer/VirtualMachineSqlServerExtensionContext.cs
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.Azure.Commands.Compute.Models;
+using Newtonsoft.Json;
+using System;
+using System.Collections;
+
+namespace Microsoft.Azure.Commands.Compute
+{
+ ///
+ /// SQL VM Extension's context object used by Get-AzureVMSqlServerExtension
+ ///
+ public class VirtualMachineSqlServerExtensionContext : PSVirtualMachineExtension
+ {
+ ///
+ /// SQLVM Extension's publisher name
+ ///
+ public const string ExtensionPublishedNamespace = "Microsoft.SqlServer.Management";
+
+ ///
+ /// SQLVM Extension's name
+ ///
+ public const string ExtensionPublishedName = "SqlIaaSAgent";
+
+ ///
+ /// SQLVM Extension's default version
+ ///
+ public const string ExtensionDefaultVersion = "1.*";
+
+ ///
+ /// Auto-patching settings
+ ///
+ public AutoPatchingSettings AutoPatchingSettings;
+
+ ///
+ /// Auto-backup settings
+ ///
+ public AutoBackupSettings AutoBackupSettings;
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.Designer.cs b/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.Designer.cs
index e984dd08fc3d..ed794d3ece51 100644
--- a/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.Designer.cs
+++ b/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.Designer.cs
@@ -223,6 +223,16 @@ public static string AzureVMDscWrongSettingsFormat {
}
}
+ ///
+ /// Looks up a localized string similar to Cannot deserialize settings string from Sql Server extension. Updating your Azure PowerShell SDK to the latest version may solve this problem. Settings string:
+ ///{0}.
+ ///
+ public static string AzureVMSqlServerWrongSettingsFormat {
+ get {
+ return ResourceManager.GetString("AzureVMSqlServerWrongSettingsFormat", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Cannot specify both Windows and Linux configurations..
///
diff --git a/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.resx b/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.resx
index 2c5329e5f5f6..461ee2451a21 100644
--- a/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.resx
+++ b/src/ResourceManager/Compute/Commands.Compute/Properties/Resources.resx
@@ -362,4 +362,9 @@ The file needs to be a PowerShell script (.ps1 or .psm1).
A data disk, {0}, is not currently assigned for this VM. Use Add-AzureVMDataDisk to add it.
+
+ Cannot deserialize settings string from Sql Server extension. Updating your Azure PowerShell SDK to the latest version may solve this problem. Settings string:
+{0}
+ {0} settings json string
+
\ No newline at end of file