diff --git a/src/Common/Commands.Common/Commands.Common.csproj b/src/Common/Commands.Common/Commands.Common.csproj index 10af73bb0fbb..3327be6458bd 100644 --- a/src/Common/Commands.Common/Commands.Common.csproj +++ b/src/Common/Commands.Common/Commands.Common.csproj @@ -171,6 +171,7 @@ + diff --git a/src/Common/Commands.Common/DiagnosticsHelper.cs b/src/Common/Commands.Common/DiagnosticsHelper.cs new file mode 100644 index 000000000000..3b5a5007969c --- /dev/null +++ b/src/Common/Commands.Common/DiagnosticsHelper.cs @@ -0,0 +1,127 @@ +// ---------------------------------------------------------------------------------- +// +// 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.WindowsAzure.Commands.Common.Properties; +using System; +using System.Collections; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using Newtonsoft.Json; + +namespace Microsoft.WindowsAzure.Commands.Utilities.Common +{ + public static class DiagnosticsHelper + { + private static string XmlNamespace = "http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration"; + private static string EncodedXmlCfg = "xmlCfg"; + private static string StorageAccount = "storageAccount"; + private static string Path = "path"; + private static string ExpandResourceDirectory = "expandResourceDirectory"; + private static string LocalResourceDirectory = "localResourceDirectory"; + private static string StorageAccountNameTag = "storageAccountName"; + private static string StorageAccountKeyTag = "storageAccountKey"; + private static string StorageAccountEndPointTag = "storageAccountEndPoint"; + + public static string GetJsonSerializedPublicDiagnosticsConfigurationFromFile(string configurationPath, + string storageAccountName) + { + return + JsonConvert.SerializeObject( + DiagnosticsHelper.GetPublicDiagnosticsConfigurationFromFile(configurationPath, storageAccountName)); + } + + public static Hashtable GetPublicDiagnosticsConfigurationFromFile(string configurationPath, string storageAccountName) + { + using (StreamReader reader = new StreamReader(configurationPath)) + { + return GetPublicDiagnosticsConfiguration(reader.ReadToEnd(), storageAccountName); + } + } + + public static Hashtable GetPublicDiagnosticsConfiguration(string config, string storageAccountName) + { + // find the element and extract it + int wadCfgBeginIndex = config.IndexOf(""); + if (wadCfgBeginIndex == -1) + { + throw new ArgumentException(Resources.IaasDiagnosticsBadConfigNoWadCfg); + } + + int wadCfgEndIndex = config.IndexOf(""); + if (wadCfgEndIndex == -1) + { + throw new ArgumentException(Resources.IaasDiagnosticsBadConfigNoEndWadCfg); + } + + if (wadCfgEndIndex <= wadCfgBeginIndex) + { + throw new ArgumentException(Resources.IaasDiagnosticsBadConfigNoMatchingWadCfg); + } + + string encodedConfiguration = Convert.ToBase64String( + Encoding.UTF8.GetBytes( + config.Substring( + wadCfgBeginIndex, wadCfgEndIndex + "".Length - wadCfgBeginIndex).ToCharArray())); + + // Now extract the local resource directory element + XmlDocument doc = new XmlDocument(); + XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable); + ns.AddNamespace("ns", XmlNamespace); + doc.LoadXml(config); + var node = doc.SelectSingleNode("//ns:LocalResourceDirectory", ns); + string localDirectory = (node != null && node.Attributes != null) ? node.Attributes[Path].Value : null; + string localDirectoryExpand = (node != null && node.Attributes != null) + ? node.Attributes["expandEnvironment"].Value + : null; + if (localDirectoryExpand == "0") + { + localDirectoryExpand = "false"; + } + if (localDirectoryExpand == "1") + { + localDirectoryExpand = "true"; + } + + var hashTable = new Hashtable(); + hashTable.Add(EncodedXmlCfg, encodedConfiguration); + hashTable.Add(StorageAccount, storageAccountName); + if (!string.IsNullOrEmpty(localDirectory)) + { + var localDirectoryHashTable = new Hashtable(); + localDirectoryHashTable.Add(Path, localDirectory); + localDirectoryHashTable.Add(ExpandResourceDirectory, localDirectoryExpand); + hashTable.Add(LocalResourceDirectory, localDirectoryHashTable); + } + + return hashTable; + } + + public static string GetJsonSerializedPrivateDiagnosticsConfiguration(string storageAccountName, + string storageKey, string endpoint) + { + return JsonConvert.SerializeObject(GetPrivateDiagnosticsConfiguration( storageAccountName, storageKey, endpoint)); + } + + public static Hashtable GetPrivateDiagnosticsConfiguration(string storageAccountName, string storageKey, string endpoint) + { + var hashTable = new Hashtable(); + hashTable.Add(StorageAccountNameTag, storageAccountName); + hashTable.Add(StorageAccountKeyTag, storageKey); + hashTable.Add(StorageAccountEndPointTag, endpoint); + return hashTable; + } + } +} diff --git a/src/Common/Commands.Common/Properties/Resources.Designer.cs b/src/Common/Commands.Common/Properties/Resources.Designer.cs index 1b2caf4f5f8e..a10815c4434d 100644 --- a/src/Common/Commands.Common/Properties/Resources.Designer.cs +++ b/src/Common/Commands.Common/Properties/Resources.Designer.cs @@ -978,6 +978,33 @@ public static string GlobalSettingsManager_Load_PublishSettingsNotFound { } } + /// + /// Looks up a localized string similar to Cannot find the WadCfg end element in the config.. + /// + public static string IaasDiagnosticsBadConfigNoEndWadCfg { + get { + return ResourceManager.GetString("IaasDiagnosticsBadConfigNoEndWadCfg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to WadCfg start element in the config is not matching the end element.. + /// + public static string IaasDiagnosticsBadConfigNoMatchingWadCfg { + get { + return ResourceManager.GetString("IaasDiagnosticsBadConfigNoMatchingWadCfg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot find the WadCfg element in the config.. + /// + public static string IaasDiagnosticsBadConfigNoWadCfg { + get { + return ResourceManager.GetString("IaasDiagnosticsBadConfigNoWadCfg", resourceCulture); + } + } + /// /// Looks up a localized string similar to iisnode.dll. /// diff --git a/src/Common/Commands.Common/Properties/Resources.resx b/src/Common/Commands.Common/Properties/Resources.resx index 7616e8b49007..c3e3784a3713 100644 --- a/src/Common/Commands.Common/Properties/Resources.resx +++ b/src/Common/Commands.Common/Properties/Resources.resx @@ -1443,4 +1443,13 @@ The file needs to be a PowerShell script (.ps1 or .psm1). Cannot delete '{0}': {1} {0} is the path of a file, {1} is an error message + + Cannot find the WadCfg end element in the config. + + + WadCfg start element in the config is not matching the end element. + + + Cannot find the WadCfg element in the config. + \ No newline at end of file diff --git a/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj b/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj index 076a768a6a8a..3c77972a2462 100644 --- a/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj +++ b/src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj @@ -121,6 +121,9 @@ ..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll True + + ..\..\..\packages\Microsoft.WindowsAzure.Management.Storage.5.1.1\lib\net40\Microsoft.WindowsAzure.Management.Storage.dll + @@ -161,6 +164,9 @@ + + + diff --git a/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs b/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs index 74d022e5c868..a46ca676e876 100644 --- a/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs +++ b/src/ResourceManager/Compute/Commands.Compute/Common/ConstantStringTypes.cs @@ -70,6 +70,7 @@ public static class ProfileNouns public const string VirtualMachineExtension = "AzureVMExtension"; public const string VirtualMachineCustomScriptExtension = "AzureVMCustomScriptExtension"; public const string VirtualMachineAccessExtension = "AzureVMAccessExtension"; + public const string VirtualMachineDiagnosticsExtension = "AzureVMDiagnosticsExtension"; public const string VirtualMachineExtensionImage = "AzureVMExtensionImage"; public const string VirtualMachineExtensionImageVersion = "AzureVMExtensionImageVersion"; public const string VirtualMachineExtensionImageType = "AzureVMExtensionImageType"; diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/GetAzureVMDiagnosticsExtension.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/GetAzureVMDiagnosticsExtension.cs new file mode 100644 index 000000000000..d0c221988dca --- /dev/null +++ b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/GetAzureVMDiagnosticsExtension.cs @@ -0,0 +1,88 @@ +// ---------------------------------------------------------------------------------- +// +// 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.Linq; +using System.Management.Automation; +using Microsoft.Azure.Commands.Compute.Common; +using Microsoft.Azure.Commands.Compute.Models; +using Microsoft.Azure.Management.Compute; +using Microsoft.Azure.Management.Compute.Models; + +namespace Microsoft.Azure.Commands.Compute +{ + [Cmdlet( + VerbsCommon.Get, + ProfileNouns.VirtualMachineDiagnosticsExtension), + OutputType( + typeof(PSVirtualMachineExtension))] + public class GetAzureVMDiagnosticsExtensionCommand : 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 = "Extension Name.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 3, + ValueFromPipelineByPropertyName = true, + HelpMessage = "To show the status.")] + [ValidateNotNullOrEmpty] + public SwitchParameter Status { get; set; } + + public override void ExecuteCmdlet() + { + base.ExecuteCmdlet(); + + ExecuteClientAction(() => + { + VirtualMachineExtensionGetResponse virtualMachineExtensionGetResponse = null; + if (Status.IsPresent) + { + virtualMachineExtensionGetResponse = + this.VirtualMachineExtensionClient.GetWithInstanceView(this.ResourceGroupName, + this.VMName, this.Name); + } + else + { + virtualMachineExtensionGetResponse = this.VirtualMachineExtensionClient.Get(this.ResourceGroupName, + this.VMName, this.Name); + } + + var returnedExtension = virtualMachineExtensionGetResponse.ToPSVirtualMachineExtension(this.ResourceGroupName); + WriteObject(returnedExtension); + }); + } + } +} \ No newline at end of file diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/RemoveAzureVMDiagnosticsExtension.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/RemoveAzureVMDiagnosticsExtension.cs new file mode 100644 index 000000000000..16af517fb880 --- /dev/null +++ b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/RemoveAzureVMDiagnosticsExtension.cs @@ -0,0 +1,66 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.Compute.Common; +using Microsoft.Azure.Management.Compute; +using Microsoft.WindowsAzure.Commands.ServiceManagement.Model; + +namespace Microsoft.Azure.Commands.Compute +{ + [Cmdlet( + VerbsCommon.Remove, + ProfileNouns.VirtualMachineDiagnosticsExtension)] + public class RemoveAzureVMDiagnosticsExtensionCommand : 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 = "Extension Name.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + public override void ExecuteCmdlet() + { + base.ExecuteCmdlet(); + + ExecuteClientAction(() => + { + var op = this.VirtualMachineExtensionClient.Delete(this.ResourceGroupName, this.VMName, + this.Name); + WriteObject(op); + }); + } + } +} diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/SetAzureVMDiagnosticsExtension.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/SetAzureVMDiagnosticsExtension.cs new file mode 100644 index 000000000000..9e6839b7fbcd --- /dev/null +++ b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/SetAzureVMDiagnosticsExtension.cs @@ -0,0 +1,224 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.Compute.Common; +using Microsoft.Azure.Common.Authentication; +using Microsoft.Azure.Common.Authentication.Models; +using Microsoft.Azure.Management.Compute; +using Microsoft.Azure.Management.Compute.Models; +using Microsoft.WindowsAzure.Commands.Common.Storage; +using Microsoft.WindowsAzure.Commands.Utilities.Common; +using Microsoft.WindowsAzure.Management.Storage; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Commands.Compute +{ + [Cmdlet( + VerbsCommon.Set, + ProfileNouns.VirtualMachineDiagnosticsExtension)] + public class SetAzureVMDiagnosticsExtensionCommand : VirtualMachineExtensionBaseCmdlet + { + private string publicConfiguration; + private string privateConfiguration; + private string storageKey; + private const string VirtualMachineExtension = "Microsoft.Compute/virtualMachines/extensions"; + private const string IaaSDiagnosticsExtension = "IaaSDiagnostics"; + private const string ExtensionPublisher = "Microsoft.Azure.Diagnostics"; + private StorageManagementClient storageClient; + + [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; } + + [Parameter( + Mandatory = true, + Position = 2, + ValueFromPipelineByPropertyName = false, + HelpMessage = "XML Diagnostics Configuration")] + [ValidateNotNullOrEmpty] + public string DiagnosticsConfigurationPath + { + get; + set; + } + + [Parameter( + Mandatory = true, + Position = 3, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The storage connection context")] + [ValidateNotNullOrEmpty] + public AzureStorageContext StorageContext + { + get; + set; + } + + [Parameter( + Position = 4, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The location.")] + [ValidateNotNullOrEmpty] + public string Location { get; set; } + + [Alias("ExtensionName")] + [Parameter( + Mandatory = true, + Position = 5, + ValueFromPipelineByPropertyName = true, + HelpMessage = "Extension Name.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + public string StorageAccountName + { + get + { + return this.StorageContext.StorageAccountName; + } + } + + public string Endpoint + { + get + { + return "https://" + this.StorageContext.EndPointSuffix; + } + } + + public string StorageKey + { + get + { + if (string.IsNullOrEmpty(this.storageKey)) + { + this.storageKey = GetStorageKey(); + } + + return this.storageKey; + } + } + + public string PublicConfiguration + { + get + { + if (string.IsNullOrEmpty(this.publicConfiguration)) + { + this.publicConfiguration = + DiagnosticsHelper.GetJsonSerializedPublicDiagnosticsConfigurationFromFile( + this.DiagnosticsConfigurationPath, this.StorageAccountName); + } + + return this.publicConfiguration; + } + } + + public string PrivateConfiguration + { + get + { + if (string.IsNullOrEmpty(this.privateConfiguration)) + { + this.privateConfiguration = DiagnosticsHelper.GetJsonSerializedPrivateDiagnosticsConfiguration(this.StorageAccountName, this.StorageKey, + this.Endpoint); + } + + return this.privateConfiguration; + } + } + + public StorageManagementClient StorageClient + { + get + { + if (this.storageClient == null) + { + this.storageClient = AzureSession.ClientFactory.CreateClient( + Profile.Context, AzureEnvironment.Endpoint.ServiceManagement); + } + + return this.storageClient; + } + } + + internal void ExecuteCommand() + { + base.ExecuteCmdlet(); + + ExecuteClientAction(() => + { + var parameters = new VirtualMachineExtension + { + Location = this.Location, + Name = this.Name, + Type = VirtualMachineExtension, + Settings = this.PublicConfiguration, + ProtectedSettings = this.PrivateConfiguration, + Publisher = ExtensionPublisher, + ExtensionType = IaaSDiagnosticsExtension, + TypeHandlerVersion = "1.4" + }; + + var op = this.VirtualMachineExtensionClient.CreateOrUpdate( + this.ResourceGroupName, + this.VMName, + parameters); + + WriteObject(op); + }); + } + + protected string GetStorageKey() + { + string storageKey = string.Empty; + + if (!string.IsNullOrEmpty(StorageAccountName)) + { + var storageAccount = this.StorageClient.StorageAccounts.Get(StorageAccountName); + if (storageAccount != null) + { + var keys = this.StorageClient.StorageAccounts.GetKeys(StorageAccountName); + if (keys != null) + { + storageKey = !string.IsNullOrEmpty(keys.PrimaryKey) ? keys.PrimaryKey : keys.SecondaryKey; + } + } + } + + return storageKey; + } + + protected override void ProcessRecord() + { + base.ProcessRecord(); + ExecuteCommand(); + } + } +} \ No newline at end of file diff --git a/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/VirtualMachineDiagnosticsExtensionCmdletBase.cs b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/VirtualMachineDiagnosticsExtensionCmdletBase.cs new file mode 100644 index 000000000000..e730fd6f3634 --- /dev/null +++ b/src/ResourceManager/Compute/Commands.Compute/Extension/Diagnostics/VirtualMachineDiagnosticsExtensionCmdletBase.cs @@ -0,0 +1,32 @@ +// ---------------------------------------------------------------------------------- +// +// 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 +{ + public class VirtualMachineDiagnosticsExtensionCmdletBase : VirtualMachineExtensionBaseCmdlet + { + protected const string DiagnosticsExtensionNamespace = "Microsoft.Azure.Diagnostics"; + protected const string DiagnosticsExtensionType = "IaaSDiagnostics"; + + protected string StorageAccountName { get; set; } + protected string StorageKey { get; set; } + protected string Endpoint { get; set; } + + public VirtualMachineDiagnosticsExtensionCmdletBase() + : base() + { + + } + } +} \ No newline at end of file diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/SetAzureVMDiagnosticsExtension.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/SetAzureVMDiagnosticsExtension.cs index 1d4ffeaa82e0..3d9854dfda4b 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/SetAzureVMDiagnosticsExtension.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/SetAzureVMDiagnosticsExtension.cs @@ -21,7 +21,9 @@ using Microsoft.WindowsAzure.Commands.Common.Storage; using Microsoft.WindowsAzure.Commands.ServiceManagement.Model; using Microsoft.WindowsAzure.Commands.ServiceManagement.Properties; +using Microsoft.WindowsAzure.Commands.Utilities.Common; using Microsoft.WindowsAzure.Management.Storage; +using Newtonsoft.Json; namespace Microsoft.WindowsAzure.Commands.ServiceManagement.IaaS.Extensions { @@ -33,11 +35,11 @@ namespace Microsoft.WindowsAzure.Commands.ServiceManagement.IaaS.Extensions typeof(IPersistentVM))] public class SetAzureVMDiagnosticsExtensionCommand : VirtualMachineDiagnosticsExtensionCmdletBase { + private string publicConfiguration; + private string privateConfiguration; + private string storageKey; protected const string SetExtParamSetName = "SetDiagnosticsExtension"; protected const string SetExtRefParamSetName = "SetDiagnosticsWithReferenceExtension"; - private const string PublicConfigurationTemplate = "\"xmlCfg\":\"{0}\", \"StorageAccount\":\"{1}\" "; - private readonly string PrivateConfigurationTemplate = "\"storageAccountName\":\"{0}\", \"storageAccountKey\":\"{1}\", \"storageAccountEndPoint\":\"{2}\""; - private readonly string XmlNamespace = "http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration"; [Parameter( ParameterSetName = SetExtParamSetName, Mandatory = true, @@ -106,117 +108,91 @@ public AzureStorageContext StorageContext HelpMessage = "To specify the reference name.")] public override string ReferenceName { get; set; } - internal void ExecuteCommand() + public string StorageAccountName { - ValidateParameters(); - RemovePredicateExtensions(); - AddResourceExtension(); - WriteObject(VM); - UpdateAzureVMCommand cmd = new UpdateAzureVMCommand(); - } - - protected override void ValidateParameters() - { - base.ValidateParameters(); - ValidateStorageAccount(); - ValidateConfiguration(); - ExtensionName = DiagnosticsExtensionType; - Publisher = DiagnosticsExtensionNamespace; - - // If the user didn't specify an extension reference name and the input VM already has a diagnostics extension, - // reuse its reference name - if (string.IsNullOrEmpty(ReferenceName)) + get { - ResourceExtensionReference diagnosticsExtension = ResourceExtensionReferences.FirstOrDefault(ExtensionPredicate); - if (diagnosticsExtension != null) - { - ReferenceName = diagnosticsExtension.ReferenceName; - } + return this.StorageContext.StorageAccountName; } } - private void ValidateStorageAccount() + public string Endpoint { - StorageAccountName = StorageContext.StorageAccountName; - StorageKey = GetStorageKey(); - // We need the suffix, NOT the full account endpoint. - Endpoint = "https://" + StorageContext.EndPointSuffix; + get + { + return "https://" + this.StorageContext.EndPointSuffix; + } } - private void ValidateConfiguration() + public string StorageKey { - // Public configuration must look like: - // { "xmlCfg":"base-64 encoded string", "StorageAccount":"account_name", "localResourceDirectory":{ "path":"some_path", "expandResourceDirectory": }} - // - // localResourceDirectory is optional - // - // What we have in is something like: - // - // - // - // - // ... - // - // element and extract it - string fullConfig = sr.ReadToEnd(); - int wadCfgBeginIndex = fullConfig.IndexOf(""); - if (wadCfgBeginIndex == -1) + if (string.IsNullOrEmpty(this.storageKey)) { - throw new ArgumentException(Resources.IaasDiagnosticsBadConfigNoWadCfg); + this.storageKey = GetStorageKey(); } - int wadCfgEndIndex = fullConfig.IndexOf(""); - if(wadCfgEndIndex == -1) - { - throw new ArgumentException(Resources.IaasDiagnosticsBadConfigNoEndWadCfg); - } + return this.storageKey; + } + } - if(wadCfgEndIndex <= wadCfgBeginIndex) + public override string PublicConfiguration + { + get + { + if (string.IsNullOrEmpty(this.publicConfiguration)) { - throw new ArgumentException(Resources.IaasDiagnosticsBadConfigNoMatchingWadCfg); + this.publicConfiguration = + JsonConvert.SerializeObject(DiagnosticsHelper.GetPublicDiagnosticsConfigurationFromFile(this.DiagnosticsConfigurationPath, + this.StorageAccountName)); } - config = fullConfig.Substring(wadCfgBeginIndex, wadCfgEndIndex + "".Length - wadCfgBeginIndex); - config = Convert.ToBase64String(Encoding.UTF8.GetBytes(config.ToCharArray())); + return this.publicConfiguration; } + } - // Now extract the local resource directory element - XmlDocument doc = new XmlDocument(); - XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable); - ns.AddNamespace("ns", XmlNamespace); - doc.Load(DiagnosticsConfigurationPath); - var node = doc.SelectSingleNode("//ns:LocalResourceDirectory", ns); - string localDirectory = (node != null && node.Attributes != null) ? node.Attributes["path"].Value : null; - string localDirectoryExpand = (node != null && node.Attributes != null) ? node.Attributes["expandEnvironment"].Value : null; - if (localDirectoryExpand == "0") - { - localDirectoryExpand = "false"; - } - if (localDirectoryExpand == "1") + public override string PrivateConfiguration + { + get { - localDirectoryExpand = "true"; + if (string.IsNullOrEmpty(this.privateConfiguration)) + { + this.privateConfiguration = + JsonConvert.SerializeObject(DiagnosticsHelper.GetPrivateDiagnosticsConfiguration(this.StorageAccountName, this.StorageKey, + this.Endpoint)); + } + + return this.privateConfiguration; } + } - PublicConfiguration = "{ "; - PublicConfiguration += string.Format(PublicConfigurationTemplate, config, StorageAccountName); - if (!string.IsNullOrEmpty(localDirectory)) - { - PublicConfiguration += ", \"localResourceDirectory\":{ \"path\":\"" + localDirectory + "\", \"expandResourceDirectory\":" + localDirectoryExpand + "}"; - } + internal void ExecuteCommand() + { + ValidateParameters(); + RemovePredicateExtensions(); + AddResourceExtension(); + WriteObject(VM); + UpdateAzureVMCommand cmd = new UpdateAzureVMCommand(); + } - PublicConfiguration += "}"; + protected override void ValidateParameters() + { + base.ValidateParameters(); + ExtensionName = DiagnosticsExtensionType; + Publisher = DiagnosticsExtensionNamespace; - // Private configuration must look like: - // { "storageAccountName":"your_account_name", "storageAccountKey":"your_key", "storageAccountEndPoint":"end_point" } - PrivateConfiguration = "{ "; - PrivateConfiguration += string.Format(PrivateConfigurationTemplate, StorageAccountName, StorageKey, Endpoint); - PrivateConfiguration += "}"; + // If the user didn't specify an extension reference name and the input VM already has a diagnostics extension, + // reuse its reference name + if (string.IsNullOrEmpty(ReferenceName)) + { + ResourceExtensionReference diagnosticsExtension = ResourceExtensionReferences.FirstOrDefault(ExtensionPredicate); + if (diagnosticsExtension != null) + { + ReferenceName = diagnosticsExtension.ReferenceName; + } + } } protected string GetStorageKey() diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/VirtualMachineDiagnosticsExtensionCmdletBase.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/VirtualMachineDiagnosticsExtensionCmdletBase.cs index d8e0b599439d..94d7e7407a5f 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/VirtualMachineDiagnosticsExtensionCmdletBase.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/IaaS/Extensions/Diagnostics/VirtualMachineDiagnosticsExtensionCmdletBase.cs @@ -20,10 +20,6 @@ public class VirtualMachineDiagnosticsExtensionCmdletBase : VirtualMachineExtens protected const string DiagnosticsExtensionType = "IaaSDiagnostics"; protected const string VirtualMachineDiagnosticsExtensionNoun = "AzureVMDiagnosticsExtension"; - protected string StorageAccountName { get; set; } - protected string StorageKey { get; set; } - protected string Endpoint { get; set; } - public VirtualMachineDiagnosticsExtensionCmdletBase() : base() {