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