/// <summary> /// Gets the resource components for the resources in an ARM template /// </summary> /// <param name="template">The object containing the ARM Template</param> /// <param name="paramvalue">The object containing the values in the Parameter file</param> /// <param name="location">The Azure Location</param> /// <param name="cspCreds">CSP Account credentials object. A token will be generated using these credentials and used for making the online ARM API call</param> /// <param name="log">The object that will contain the exception messages</param> /// <returns> Returns the list of resource components</returns> public static List <ResourceComponent> GetResourceComponentsForTemplate(ARMTemplate template, ARMParamValue paramvalue, string location, CSPAccountCreds cspCreds, out StringBuilder log) { List <ResourceComponent> components = new List <ResourceComponent>(); log = new StringBuilder(string.Empty); string locationAsPerARMSpecs = null; try { // Fetch the location as per ARM Specs from the mapping if (!LocationConstants.LocationAsPerARMSpecsMap.TryGetValue(location, out locationAsPerARMSpecs)) { throw new Exception(ExceptionLogger.GenerateLoggerTextForInvalidField("Location", location, "ARMTemplate")); } if (template.Resources != null && template.Resources.Count > 0) { // Loop thru each resource in the ARM Template foreach (Resource res in template.Resources) { ARMResourceType resType = null; string nameOfResource = string.Empty; if (res != null && res.Name != null) { // Fetch the name of the current resource nameOfResource = PropertyHelper.GetValueIfVariableOrParam(res.Name, template.Variables, template.Parameters, paramvalue.Parameters); } // Check if resource or resource type is not null if (res != null && res.Type != null) { // Check if resource type is in supported by this application resType = ResourceTypeHelper.ResourceTypeList.Find(x => res.Type.Equals(x.ARMResourceTypeText, StringComparison.OrdinalIgnoreCase)); if (resType != null) { List <ResourceComponent> currentResourceComponents = new List <ResourceComponent>(); // Check if the resource type of the current resource does not have chargeable components if (!resType.HasChargableComponents) { currentResourceComponents.Add(new ResourceComponent() { ResourceType = res.Type, Quantity = 0, IsChargeable = false }); } else { IComponentFetcher resCompFetcher = null; // Create the appropriate object to fetch the components of the resource switch (resType.ARMResourceTypeText) { // Public IP Resource case ARMResourceTypeConstants.ARMPublicIPResourceType: resCompFetcher = new PublicIPComponentFetcher(); break; // Virtual Machine Resource case ARMResourceTypeConstants.ARMVMResourceType: resCompFetcher = new VMComponentFetcher(); break; default: // Has Chargable Components but not yet supported log.AppendLine(ExceptionLogger.GenerateLoggerTextForUnSupportedResource(res.Type)); break; } StringBuilder resLog = new StringBuilder(string.Empty); // Call the method to fetch the resource components List <ResourceComponent> resComp = resCompFetcher.GetResourceComponents(res, template, paramvalue, locationAsPerARMSpecs, cspCreds, out resLog); if (resLog != null) { log.Append(resLog); } if (resComp != null && resComp.Count > 0) { currentResourceComponents.AddRange(resComp); } else { log.AppendLine(ExceptionLogger.GenerateLoggerTextForNoResourceOutput(nameOfResource)); } } foreach (ResourceComponent component in currentResourceComponents) { component.ResourceName = nameOfResource; } components.AddRange(currentResourceComponents); } else { log.AppendLine(ExceptionLogger.GenerateLoggerTextForUnSupportedResource(res.Type)); } } else { if (res != null) { // Type of the resourse is missing/null, generate the message log.AppendLine(ExceptionLogger.GenerateLoggerTextForMissingField("Type", nameOfResource)); } else { // Resourse is missing/null, generate the message log.AppendLine(ExceptionLogger.GenerateLoggerTextForMissingField("Resource", "ARMTemplate")); } } } } else { // Resources section in ARM template is missing/null, generate a message throw new Exception(ExceptionLogger.GenerateLoggerTextForMissingField("RESOURCES", "ARMTemplate")); } } catch (Exception ex) { // Catch any exception and log the message components = null; log.AppendLine(ex.Message); } // Return the list of components obtained for the resources in the ARM template return(components); }
/// <summary> /// Gets the resource components for the Disks of the Virtual machine resource. /// </summary> /// <param name="diskURI">The URI of the disk</param> /// <param name="diskSize">The size of the Disk</param> /// <param name="storageResourceList">The list of storage resources in the ARM Template</param> /// <param name="isOSDisk">Set true for OS Disk and false for Data Disk</param> /// <returns> Returns the list of resource components </returns> private List <ResourceComponent> GetResourceComponentForDiskStorage(string diskURI, string diskSize, List <Resource> storageResourceList, bool isOSDisk) { List <ResourceComponent> storageComponentList = new List <ResourceComponent>(); List <ResourceComponent> storageDiskComponentList = new List <ResourceComponent>(); List <ResourceComponent> storageTransactionComponentList = new List <ResourceComponent>(); // Get the Storage resource corresponding to the Storage of the Disk of the VM Resource diskStorageResource = PropertyHelper.SearchResourceInListByName(storageResourceList, diskURI); // Create the resource component for Storage of the VM disk, MeterSubCategory and MeterName will be set later ResourceComponent storageDiskComponent = new ResourceComponent { ResourceType = this.resource.Type, MeterCategory = StorageResourceConstants.StorageMeterCategory, MeterSubCategory = null, MeterName = null, IsChargeable = true }; string storageAccountType = null; bool isPremiumStorage = false; StorageProperties storageProp = null; if (diskStorageResource != null && diskStorageResource.Properties != null) { // Get properties of the Storage resource storageProp = this.GetStoragePropertiesForStorageResource(diskStorageResource); } if (storageProp != null) { // Get Account Type of the Storage resource storageAccountType = PropertyHelper.GetValueIfVariableOrParam(storageProp.AccountType, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); } // If Unable to fetch Storage Account Type, then, the template may be using existing storage account, Take Default Storage Account Type if (storageAccountType == null) { storageAccountType = StorageResourceConstants.StorageDefaultAccountType; } string meterSubCategory = null; // Set the Meter SubCategory based on the Storage Account Type if (StorageResourceConstants.StorageTypeAndMeterSubCategoryMap.TryGetValue(storageAccountType, out meterSubCategory)) { storageDiskComponent.MeterSubCategory = meterSubCategory; } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForInvalidField("StorageAccountType", storageAccountType, this.nameOfResource)); } // Check if premium storage is used if (storageAccountType.Equals(StorageResourceConstants.StoragePremiumAccountType, StringComparison.OrdinalIgnoreCase)) { isPremiumStorage = true; } double diskQuantity = 0; if (isOSDisk) { // Get default Storage for OS Disk from Constants/Config diskQuantity = isPremiumStorage ? VMResourceConstants.StoragePremiumOSDiskSize : VMResourceConstants.StorageOSDiskSize; } else { // Get the Storage size for the Data Disk double dataDiskQuantityValue = 0; if (diskSize != null && double.TryParse(diskSize, out dataDiskQuantityValue)) { if (isPremiumStorage) { // If Premium Storage, Map the disk size to the next greater available size of premium disk for (int i = 0; i < StorageResourceConstants.StoragePremiumDiskValuesArray.Count(); i++) { double premiumDiskSizeValue = StorageResourceConstants.StoragePremiumDiskValuesArray[i]; if ((dataDiskQuantityValue <= premiumDiskSizeValue) || (i == StorageResourceConstants.StoragePremiumDiskValuesArray.Count() - 1)) { diskQuantity = premiumDiskSizeValue; break; } } } else { diskQuantity = dataDiskQuantityValue < VMResourceConstants.StorageDataDiskSize ? dataDiskQuantityValue : VMResourceConstants.StorageDataDiskSize; } } } // Set the meter name for the Disk resource based on premium and standard if (isPremiumStorage) { string meterName = null; if (StorageResourceConstants.StoragePremiumDiskSizeAndMeterNameMap.TryGetValue(diskQuantity, out meterName)) { storageDiskComponent.MeterName = meterName; } } else { storageDiskComponent.MeterName = StorageResourceConstants.StorageMeterNameForVMDisk; } // Set the Quantity of the component to the Disk Size, Set 1 if its premium disk storageDiskComponent.Quantity = isPremiumStorage ? 1 : diskQuantity; storageComponentList.Add(storageDiskComponent); if (!isPremiumStorage) { // Add Storage transactions component if not a premium disk storageTransactionComponentList.Add(new ResourceComponent() { ResourceType = this.resource.Type, MeterCategory = StorageResourceConstants.DataManagementMeterCategory, MeterSubCategory = StorageResourceConstants.DataManagementMeterSubCategoryForVMDisk, MeterName = StorageResourceConstants.DataManagementMeterNameForStorageTrans, Quantity = isOSDisk ? VMResourceConstants.DataManagementVMStorageOSDiskTrans : VMResourceConstants.DataManagementVMStorageDataDiskTrans, IsChargeable = true }); } // Add the list of components obtained for the Storage Disk of the VM resource storageComponentList.AddRange(storageDiskComponentList); storageComponentList.AddRange(storageTransactionComponentList); return(storageComponentList); }
/// <summary> /// Gets the resource components for the Diagnostics if applicable/enabled for the Virtual machine resource. /// </summary> /// <returns> Returns the list of resource components </returns> private List <ResourceComponent> GetResourceComponentForDiagnostics() { List <ResourceComponent> componentList = new List <ResourceComponent>(); string diagnosticsEnabled = null; if (this.prop.DiagnosticsProfile != null && this.prop.DiagnosticsProfile.BootDiagnostics != null) { // Fetch the Enabled property for Diagnostics of the VM resource diagnosticsEnabled = this.prop.DiagnosticsProfile.BootDiagnostics.Enabled; } if (diagnosticsEnabled != null && diagnosticsEnabled.Equals("true", StringComparison.OrdinalIgnoreCase)) { // Get list of all storage resources in template List <Resource> storageResourceList = this.template.Resources.FindAll(x => ARMResourceTypeConstants.ARMStorageResourceType.Equals(x.Type, StringComparison.OrdinalIgnoreCase)); string diagnosticsStorageURI = null; if (this.prop.DiagnosticsProfile != null && this.prop.DiagnosticsProfile.BootDiagnostics != null) { // Fetch the URI of Diagnostics diagnosticsStorageURI = this.prop.DiagnosticsProfile.BootDiagnostics.StorageUri; } Resource diagnosticsStorageResource = null; if (diagnosticsStorageResource != null) { diagnosticsStorageResource = PropertyHelper.SearchResourceInListByName(storageResourceList, diagnosticsStorageURI); } string storageAccountType = null; StorageProperties storageProp = null; if (diagnosticsStorageResource != null && diagnosticsStorageResource.Properties != null) { // Get the Properties of the Storage Resource associated with storing the Diagnostics of the VM storageProp = this.GetStoragePropertiesForStorageResource(diagnosticsStorageResource); } if (storageProp != null) { // Get the Storage Account Type storageAccountType = PropertyHelper.GetValueIfVariableOrParam(storageProp.AccountType, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); } // Use Default Storage Account Type, as template may be using existing storage account if (storageAccountType == null) { storageAccountType = StorageResourceConstants.StorageDefaultAccountType; } if (storageAccountType != null && storageAccountType != StorageResourceConstants.StoragePremiumAccountType) { // Create the resource component for Diagnostics ResourceComponent diagnosticsComponent = new ResourceComponent { ResourceType = this.resource.Type, MeterCategory = StorageResourceConstants.StorageMeterCategory, MeterSubCategory = null, MeterName = StorageResourceConstants.StorageMeterNameForTable, Quantity = VMResourceConstants.StorageDiagnosticsTableSize, IsChargeable = true }; string meterSubCategory = null; // Set the Meter SubCategory based on the Storage Account Type if (StorageResourceConstants.StorageTypeAndMeterSubCategoryMap.TryGetValue(storageAccountType, out meterSubCategory)) { diagnosticsComponent.MeterSubCategory = meterSubCategory; } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForInvalidField("StorageAccountType", storageAccountType, this.nameOfResource)); } componentList.Add(diagnosticsComponent); // Add the Storage Transactions component componentList.Add(new ResourceComponent() { ResourceType = this.resource.Type, MeterCategory = StorageResourceConstants.DataManagementMeterCategory, MeterSubCategory = StorageResourceConstants.DataManagementMeterSubCategoryForVMDisk, MeterName = StorageResourceConstants.DataManagementMeterNameForStorageTrans, Quantity = VMResourceConstants.DataManagementVMDiagnosticsStorageTrans, IsChargeable = true }); } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForInvalidField("StorageAccountType for Diagnostics", storageAccountType, this.nameOfResource)); } } return(componentList); }
/// <summary> /// Gets the resource components for the compute hours of the Virtual machine resource. This includes components for software cost if present. /// </summary> /// <returns> Returns the list of resource components </returns> private List <ResourceComponent> GetResourceComponentForComputeHours() { List <ResourceComponent> componentList = new List <ResourceComponent>(); // Create the compute hours component, Meter SubCategory value will be set later ResourceComponent computeHoursComponent = new ResourceComponent { ResourceType = this.resource.Type, MeterCategory = VMResourceConstants.VMMeterCategory, MeterSubCategory = null, MeterName = VMResourceConstants.VMMeterName, Quantity = Constants.HoursinaMonth, IsChargeable = true }; // Create the software cost component, Meter SubCategory value will be set later ResourceComponent softwareCostComponent = new ResourceComponent { ResourceType = this.resource.Type, MeterCategory = VMResourceConstants.VMMeterCategory, MeterSubCategory = null, MeterName = VMResourceConstants.VMMeterName, Quantity = Constants.HoursinaMonth, IsChargeable = true }; string vmSize = null, osType = null, createOption = null; if (this.prop.HardwareProfile != null && this.prop.HardwareProfile.VmSize != null) { // Fetch the VM Size vmSize = PropertyHelper.GetValueIfVariableOrParam(this.prop.HardwareProfile.VmSize, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForMissingField("properties.hardwareProfile.vmSize", this.nameOfResource)); } if (vmSize.Equals(string.Empty)) { throw new Exception(ExceptionLogger.GenerateLoggerTextForMissingField("properties.hardwareProfile.vmSize", this.nameOfResource)); } if (this.prop.StorageProfile != null && this.prop.StorageProfile.OsDisk != null) { // Fetch the OS Disk related info osType = PropertyHelper.GetValueIfVariableOrParam(this.prop.StorageProfile.OsDisk.OsType, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); createOption = PropertyHelper.GetValueIfVariableOrParam(this.prop.StorageProfile.OsDisk.CreateOption, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForMissingField("properties.storageProfile.osDisk", this.nameOfResource)); } if (createOption == null) { throw new Exception(ExceptionLogger.GenerateLoggerTextForMissingField("properties.storageProfile.osDisk.createOption", this.nameOfResource)); } if (osType == null) { if (createOption != null && createOption.Equals("FromImage", StringComparison.OrdinalIgnoreCase)) { string vmImagePublisher = null, vmImageOffer = null, vmImageSKU = null; // Fetch the VM Image info - Publisher, Offer and SKU if (this.prop.StorageProfile != null && this.prop.StorageProfile.ImageReference != null) { vmImagePublisher = PropertyHelper.GetValueIfVariableOrParam(this.prop.StorageProfile.ImageReference.Publisher, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); vmImageOffer = PropertyHelper.GetValueIfVariableOrParam(this.prop.StorageProfile.ImageReference.Offer, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); vmImageSKU = PropertyHelper.GetValueIfVariableOrParam(this.prop.StorageProfile.ImageReference.Sku, this.template.Variables, this.template.Parameters, this.paramValue.Parameters); } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForMissingField("properties.storageProfile.imageReference", this.nameOfResource)); } if (vmImagePublisher != null && vmImageOffer != null && vmImageSKU != null) { // Get the OS Type of the VM Image from the Online Helper method osType = VMOnlineHelper.GetVMImageOSType(this.cspCreds, vmImagePublisher, vmImageOffer, vmImageSKU, this.location); string meterSubCategoryForVMImageWithSoftwareCost = null; // Get the Meter SubCategory for software cost of the VM Image is applicable meterSubCategoryForVMImageWithSoftwareCost = VMImageHelper.GetMeterSubCategoryForVMImageWithSoftwareCost(this.cspCreds, vmImagePublisher, vmImageOffer, vmImageSKU, vmSize, this.location); if (meterSubCategoryForVMImageWithSoftwareCost != null) { // Set the Meter SubCategory for Software Cost component, Add to the List of resource components softwareCostComponent.MeterSubCategory = meterSubCategoryForVMImageWithSoftwareCost; componentList.Add(softwareCostComponent); } } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForMissingField("properties.storageProfile.publisher/offer/sku", this.nameOfResource)); } } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForInvalidField("storageProfile.osDisk.createOption", createOption, this.nameOfResource)); } } string meterSubCategory = null; string modifiedVMSizeString = VMHelper.ModifyVMSizeStringAsPerPricingSpecs(vmSize); if (osType != null) { // Fetch the Meter SubCategory as per the OS Type switch (osType.ToUpper()) { case "WINDOWS": meterSubCategory = string.Format(VMResourceConstants.VMMeterSubCategoryWindowsString, modifiedVMSizeString, osType); break; case "LINUX": meterSubCategory = string.Format(VMResourceConstants.VMMeterSubCategoryLinuxString, modifiedVMSizeString); break; default: throw new Exception(ExceptionLogger.GenerateLoggerTextForInvalidField("OSType", osType, this.nameOfResource)); } } else { throw new Exception(ExceptionLogger.GenerateLoggerTextForInvalidField("OSType", string.Empty, this.nameOfResource)); } // Set the Meter SubCategory for Compute Hours Cost component, Add to the List of resource components computeHoursComponent.MeterSubCategory = meterSubCategory; componentList.Add(computeHoursComponent); return(componentList); }