# https://96bdfe01-af80-4575-8f23-e7057184c8f6.webhook.cus.azure-automation.net/webhooks?token=dVIj9zHSJwNeR2Ow8QTOoiSoKaPPux9EVJsQAMiGUPg%3d <# $ComputerName = 'itddotfrsql3.nd.gov' $CPU = 8 $MemoryGB = 32 $OS = 'Windows Server 2019 Datacenter' $Subnet = '10.21.12.0/22' $Environment = "Production" $Platform = "Azure" $AppName = 'DOT-FacialRec' $LicensingRestrictions='Microsoft SQL Enterprise' $Credential = $PrvCred #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [object] $WebhookData ) <# New-ITDVMwareWindowsVMAA #> function New-ITDAzureWindowsVMAA { [CmdLetBinding()] Param( [Parameter(Mandatory = $true)] [string] $ComputerName, [Parameter(Mandatory = $true)] [int] $CPU, [Parameter(Mandatory = $true)] [int] $MemoryGB, #[Parameter(Mandatory = $true)] #[int] #$DiskOS, #[Parameter(Mandatory = $true)] #[int] #$DiskData, [Parameter(Mandatory = $true)] [string] $Subnet, [Parameter(Mandatory = $true)] [string] $OS, [Parameter(Mandatory = $true)] [string] $Environment, [Parameter(Mandatory = $true)] [string] $AppName, [Parameter(Mandatory = $true)] [string] $LicensingRestrictions #[Parameter(Mandatory = $true)] #[PSCredential] #$Credential ) $Body = " ComputerName=$ComputerName CPU=$CPU MemoryGB=$MemoryGB VlanId=$VlanId OS=$OS Environment=$Environment Datacenter=$Datacenter LicensingRestrictions=$LicensingRestrictions AppName=$AppName RunningOn=$env:computername RunningAs=$env:username Credential=$Credential.UserName " Send-MailMessage -From "zmauto@nd.gov" -To "zmeier@nd.gov" -SmtpServer apprelay1.nd.gov -Body $Body -Subject "AutoBuildAzure-$ComputerName" $FQDN = $ComputerName $tenantId = '2dea0464-da51-4a88-bae2-b3db94bc0c54' If ($Credential) { $IaasAuto = $Credential } #$IaasAutoAzApp = Get-AutomationPSCredential -Name 'Azure IaaS Service Principal' Write-Warning "[$FQDN]:Start" $SPCred = $IaasAuto $ADCred = $IaasAuto $PSCred = $IaasAuto $VMCred = $IaasAuto $CcmCred = $IaasAuto #$RadiusCred = $RadiusCred $RadiusCred = New-Object System.Management.Automation.PSCredential($IaasAuto.username.split('\')[1], ($IaaSAuto.Password)) Clear-DnsClientCache $HostName = $FQDN.split('.')[0] # Infoblox #$InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred # not valid for Azure #$Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd() $Cidr = $Subnet [Net.IpAddress]$NetworkId = $Cidr.split('/')[0] [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress $SubnetMaskInt = $CIDR.split('/')[1] $Int64 = ([convert]::ToInt64(('1' * $SubnetMaskInt + '0' * (32 - $SubnetMaskInt)), 2)) [Net.IPAddress]$SubnetMask = '{0}.{1}.{2}.{3}' -f ([math]::Truncate($Int64 / 16777216)).ToString(), ([math]::Truncate(($Int64 % 16777216) / 65536)).ToString(), ([math]::Truncate(($Int64 % 65536) / 256)).ToString(), ([math]::Truncate($Int64 % 256)).ToString() $IPSplit = $Subnet.Split('.') [Net.IPAddress]$DefaultGateway = ($IPSplit[0] + '.' + $IPSplit[1] + '.' + $IPSplit[2] + '.' + (($CIDR.split('/')[0].split('.')[-1] -as [int]) + 1) ) If ($IpAddress) { If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) { Write-Warning "DNS record already exists, CIDR Block match" } Else { Write-Error "DNS record already exists, and does not match CIDR Block" Break } } Else { New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred Start-Sleep -Seconds 5 [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue).IPAddress If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) { Write-Error "IP Address already in use." -ErrorAction Stop } } # Passwordstate If ($FQDN -like "itdcnd*") { $PasswordStateList = "Peoplesoft Share PW" } Else { $PasswordStateList = "CSRC" } $LocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $PSCred #$GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) #$GuestCredentialAB = New-Object System.Management.Automation.PSCredential ($LocalCredential.UserName, ($LocalCredential.Password | ConvertTo-SecureString -AsPlainText -Force)) $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($LocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force)) #$GuestCredential = $GuestCredentialBB switch ($Environment) { { $_ -eq 'Test' -or $_ -eq 'Development' } { Write-Warning 'Environment is Test or Development' $EnvShortString = 'tst' #$VMSizeFilter="*_B*s*" $VMSizeFilter1 = "*_D[0-9]*s_v3" $VMSizeFilter2 = "*_E[0-9]*s_v3" $VMSizeFilter3 = "*_F[0-9]*s_v2" $Subscription = "npd01" $VNet = "vnet-npd01-001" $VNetSubnet = "sn-shared-zerotrust-npd-10.21.8.0_22" } 'Production' { Write-Warning 'Environment is Production' $EnvShortString = 'prd' #$VMSizeFilter="*_D*s_*" $VMSizeFilter1 = "*_D[0-9]*s_v3" $VMSizeFilter2 = "*_E[0-9]*s_v3" $VMSizeFilter3 = "*_F[0-9]*s_v2" $Subscription = "prd01" $VNet = "vnet-prd01-001" $VnetSubnet = "sn-shared-zerotrust-prd-10.21.12.0_22" } 'CARES-tst' { Write-Warning 'Environment is CARES-tst' $EnvShortString = 'tst' #$VMSizeFilter="*_D*s_*" $VMSizeFilter1 = "*_D[0-9]*s_v3" $VMSizeFilter2 = "*_E[0-9]*s_v3" $VMSizeFilter3 = "*_F[0-9]*s_v2" $Subscription = "cares01" $VNet = "vnet-infra-azurenetworking-cares01-npd" $VnetSubnet = "sn-shared-zerotrust-npd-10.69.254.0_24" } 'CARES-prd' { Write-Warning 'Environment is CARES-prd' $EnvShortString = 'prd' #$VMSizeFilter="*_D*s_*" $VMSizeFilter1 = "*_D[0-9]*s_v3" $VMSizeFilter2 = "*_E[0-9]*s_v3" $VMSizeFilter3 = "*_F[0-9]*s_v2" $Subscription = "cares01" $VNet = "vnet-infra-azurenetworking-cares01-prd" $VnetSubnet = "sn-shared-zerotrust-prd-10.69.126.0_24" } Default { Write-Error "Environment failed" -ErrorAction Stop } } switch ($OS) { "Windows Server 2019 Datacenter" { $VMOS = "Windows" $Publisher = "MicrosoftWindowsServer" $Offer = "WindowsServer" $sku = "2019-Datacenter" } "Windows Server 2022 Datacenter" { $VMOS = "Windows" $Publisher = "MicrosoftWindowsServer" $Offer = "WindowsServer" $sku = "2022-datacenter" } Default { Write-Error "Invalid operating system" -ErrorAction Stop } } # finalize VM size Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId $location = "centralus" $VMSize = Get-AzVMSize -Location $location | ` Where-Object { $_.Name -Like "$VMSizeFilter1" -or $_.Name -Like "$VMSizeFilter2" -or $_.Name -Like "$VMSizeFilter3" } | ` Where-Object { $_.NumberOfCores -ge $CPU -and $_.MemoryInMB -ge ($Memory * 1024) } | ` Where-Object Name -NotMatch "_Promo" | ` Sort-Object NumberOfCores, MemoryInMB | ` Select-Object -First 1 # resource group things $VMOwner = $AppName.split('-')[0].ToLower() $VMFunction = (($AppName -replace "$VMOwner-") -replace "-").ToLower() -replace " " #$IPAddress = (Resolve-DnsName -Name $ComputerName -ErrorAction Stop).IpAddress $ResourceGroup = "rg-$VMOwner-$VMFunction-$EnvShortString" If ($ResourceGroupIndex) { $ResourceGroup = $ResourceGroup + "-$ResourceGroupIndex" } $VMName = "vm-$HostName-$EnvShortString" $NewITDAzureRMVMParams = @{ VMFQDN = $ComputerName VMSubscription = $Subscription VMEnvironment = $EnvShortString VMOwner = $VMOwner VMFunction = $VMFunction VMSize = $VMSize.Name VMOS = $VMOS VMPublisher = $Publisher VMOffer = $Offer VMSku = $sku VMVnetName = $VNet VMSubnet = $VNetSubnet VMLocation = $location VMIP = $IPAddress.IPAddressToString VMCredential = $LocalCredential AppName = $AppName } <# $VMFQDN = $ComputerName $VMSubscription = $Subscription $VMEnvironment = $EnvShortString $VMOwner = $VMOwner $VMFunction = $VMFunction $VMSize = $VMSize.Name $VMOS = $VMOS $VMPublisher = $Publisher $VMOffer = $Offer $VMSku = $sku $VMVnetName = $VNet $VMSubnet = $VNetSubnet $VMLocation = $location $VMIP = $IPAddress $VMCredential = $LocalCredential $AppName = $AppName #> New-ITDAzureRMVM @NewITDAzureRMVMParams # wait for build $VMName = ('vm-' + $ComputerName.split('.')[0] + '-' + $EnvShortString) $VMStatus = $null $VMCreation = $Null While ($VMCreation -ne "Complete") { If (( (Get-AzVM -ResourceGroupName $ResourceGroup -Name $VMName -Status).Statuses | Where-Object Code -Match "PowerState").Code -eq "PowerState/running") { $VMCreation = "Complete" } else { Start-Sleep -Seconds 300 } } Start-Sleep -Seconds 30 # Add extra disk Add-ITDAzureRMNewDataDisk -VMName $VMName -SizeGB 20 # pre-firewall Guest OS customization Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\1-SetWMITags.ps1' Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\3-Disks.ps1' Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\5-TimeZone.ps1' Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\6-PerformanceCounters.ps1' Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\7-DisableWindowsFirewall.ps1' # determine Active Directory Forest and OU $DomainName = $FQDN.Substring($FQDN.IndexOf(".") + 1) switch ($DomainName) { 'nd.gov' { $SearchBaseDomain = "dc=nd,dc=gov" } 'ndcloud.gov' { $SearchBaseDomain = "dc=ndcloud,dc=gov" } } If ($DomainName -eq "nd.gov") { $OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq $AppName } If (!($OUAppName)) { $OUAppName = Get-ADOrganizationalUnit -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' } } $ExistingADComputer = Get-ADComputer -Filter { Name -eq $Hostname } If ($ExistingADComputer) { If ($ExistingADComputer.DistinguishedName -like ("*" + $AppName + "*") -or $ExistingADComputer.DistinguishedName -like "*All-General*") { Write-Warning "AD object already exists, OU path does match" $OuFinal = $ExistingADComputer.DistinguishedName -replace '^.+?(? } function New-ITDAzureRMVM { [CmdletBinding()] Param ( # VM Computer Name (FQDN) [Parameter(Mandatory = $true, Position = 0)] [String] $VMFQDN, # VM Subscription (tst,prd,dr) [Parameter(Mandatory = $true)] [string] $VMSubscription, # Environment (tst,prd,dr) [Parameter(Mandatory = $true)] [string] $VMEnvironment, # Owner (infra,shared,ITD,DHS,etc) [Parameter(Mandatory = $true)] [string] $VMOwner, # Function (testdc, POC, etc) [Parameter(Mandatory = $true)] [string] $VMFunction, #[Parameter(Mandatory=$true)] [string] $ResourceGroupIndexNumber, # Azure VM Size [Parameter(Mandatory = $true)] [string] $VMSize, # Azure OS (Windows or Linux) [Parameter(Mandatory = $true)] [string] $VMOS, # Availability Set [switch] $VMAS, # Availability Set Tier [string] $VMASTier, # Availability Zone [ValidateSet(1, 2, 3)] [int] $VMAvailZone, # Azure Publisher [string] $VMPublisher, # Azure Offer [string] $VMOffer, # Azure Sku [string] $VMSku, # Azure vNet [Parameter(Mandatory = $true)] [string] $VMVNetName, # Azure Subnet [Parameter(Mandatory = $true)] [string] $VMSubnet, # Azure Location [Parameter(Mandatory = $true)] [string] $VMLocation, # Azure Private IP [Parameter(Mandatory = $true)] [string] $VMIP, [Parameter(Mandatory = $true)] [PSCredential] $VMCredential, # App name to be used for the RG [Parameter(Mandatory = $true)] [string] $AppName ) Begin { $VMName = $VMFQDN.Split('.')[0] #$VMIndexNumber = "001" $VMIPConfigName = "ipconfig-$VMName-$VMEnvironment" $VMNicName = "nic-$VMName-$VMEnvironment" ###### $VMObjectName = "vm-$VMName-$VMEnvironment" $ResourceGroup = "rg-$VMOwner-$VMFunction-$VMEnvironment" #If($ResourceGroupIndexNumber){$ResourceGroup = $ResourceGroup + "-$ResourceGroupIndexNumber"} #removing diag storage account because replaced by managed storage accounts for boot diagnostics #$VMDiagStorageAcct = "sa" + $VMOwner + $VMFunction + "diag" + $VMEnvironment $VMOSDiskName = "vm-$VMName-os-$VMEnvironment" <# If($VMASTier) { $VMASName = "as-$VMOwner-$VMFunction-$VMASTier-$VMEnvironment" } Else { $VMASName = "as-$VMOwner-$VMFunction-$VMEnvironment" } #> <# Write-Verbose "Checking Storage Account Length" If (($VmDiagStorageAcct.Length) -gt 24){ Write-Verbose "Storage Account Length is too long. Truncating function...." $TruncateCharacters = $VmDiagStorageAcct.Length - 24 $ShortVMFunction = $VMFunction.Substring(0, ($VMFunction.length) - $TruncateCharacters) $VMDiagStorageAcct = "sa" + $VMOwner + $ShortVMFunction + "diag" + $VMEnvironment } If (($VmDiagStorageAcct.Length) -gt 24){ Write-Verbose "Storage Account Length is too long after truncating. Terminating Build" Return } #> Write-Verbose "Verifying Applicable Inputs are Lowercase" $VMIPConfigName = $VMIPConfigName.ToLower() $VMNicName = $VMNicName.ToLower() $VMObjectName = $VMObjectName.ToLower() $ResourceGroup = $ResourceGroup.ToLower() #$VMDiagStorageAcct = $VMDiagStorageAcct.ToLower() $VMOSDiskName = $VMOSDiskName.ToLower() } Process { Set-AzContext $VMSubscription $ResGroupExist = "" Write-Verbose "Creating Resource Group if it doesn't exist" $ResGroupExist = Get-AzResourceGroup -Name $ResourceGroup -ErrorAction SilentlyContinue If (@($ResGroupExist).count -gt 1) { Write-Error "Multiple Resource Groups matched" -ErrorAction Stop } If (@($ResGroupExist).count -lt 1) { Write-Warning "No matching resource group found, creating it now" New-AzResourceGroup -Name $ResourceGroup -Location $VMLocation -Tag @{ApplicationName = $AppName } $ResourceGroupName = $ResourceGroupSearch.ResourceGroupName #Write-Error "No Resource Groups matched" -ErrorAction Stop } If (@($ResGroupExist).count -eq 1) { Write-Warning "Exactly one matching resource group found" $ResourceGroupName = $ResourceGroupSearch.ResourceGroupName } <# Write-Verbose "Checking Storage Account Availability in Subscription" If (!(Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $VMDiagStorageAcct})) { If ((Get-AzureRmStorageAccountNameAvailability -Name $VMDiagStorageAcct).NameAvailable -eq $True) { New-AzureRmStorageAccount -Name $VMDiagStorageAcct -Location $VMLocation -ResourceGroupName $ResourceGroup -SkuName "Standard_LRS" -EnableHttpsTrafficOnly $true #Start-Sleep -Seconds 5 Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct | Update-AzureRmStorageAccountNetworkRuleSet -DefaultAction Deny -Bypass None #Update-AzureRmStorageAccountNetworkRuleSet -ResourceGroupName $ResourceGroup -Name $VMDiagStorageAcct -DefaultAction Deny -Bypass None Add-AzureRmStorageAccountNetworkRule -ResourceGroupName $ResourceGroup -AccountName $VMDiagStorageAcct -IPAddressOrRange "165.234.248.3" } Else { Write-Verbose "Storage Account already exists. Re-run with a valid storage account" Return } } #> <# Write-Verbose "Evaluating Availability Set" If($VMAS) { Write-Verbose "Checking for existing Availability Set" $VMASExist = Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -ErrorAction SilentlyContinue If($VMASExisting) { $VMASID = $VMASExist.id } Else { New-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName -Location $VMLocation -PlatformFaultDomainCount 3 -PlatformUpdateDomainCount 5 -Sku Aligned $VMASID = (Get-AzAvailabilitySet -ResourceGroupName $ResourceGroup -Name $VMASName).id } } #> Write-Verbose "Preparing Network Config" $VNet = (Get-AzVirtualNetwork | where { $_.Name -eq $VMVNetName }) $VNetID = $VNet.id $Subnet = ($VNet.Subnets | where { $_.Name -eq $VMSubnet }) $SubnetName = $Subnet.name $SubnetID = $Subnet.id Write-Verbose "Creating IPConfig and NIC" $IPConfig = New-AzNetworkInterfaceIpConfig -Name $VMIPConfigName -PrivateIpAddress $VMIP -PrivateIpAddressVersion IPv4 -Subnet $Subnet $VMNIC = New-AzNetworkInterface -IpConfigurationName $IPConfig -Location $VMLocation -Name $VMNICName -ResourceGroupName $ResourceGroup -SubnetId $SubnetID $VMNIC.IpConfigurations[0].PrivateIpAllocationMethod = "Static" $VMNIC.IpConfigurations[0].PrivateIpAddress = $VMIP Set-AzNetworkInterface -NetworkInterface $VMNIC Write-Verbose "Building VM Config" #If($VMAS) #{ #$vmConfig = New-AzVMConfig -VMName $VMObjectName -VMSize $VMSize -AvailabilitySetId $VMASID #} #Else #{ #If($VMAvailZone) #{ # Write-Verbose "AvailZone $VMAvailZone" # $vmConfigParams = @{ # VMName = $VMObjectName # VMSize = $VMSize # Zone = $VMAvailZone # } #} #Else #{ # Write-Verbose "No AvailZone" $vmConfigParams = @{ VMName = $VMObjectName VMSize = $VMSize } #} #$vmConfig = New-AzureRmVMConfig -VMName $VMObjectName -VMSize $VMSize $vmConfig = New-AzVMConfig @vmConfigParams #} $vmConfig | Set-AzVMOSDisk -Name $VMOSDiskName -CreateOption FromImage If ($VMOS -eq "Windows") { $vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $VMName -Credential $VMCredential $vmConfig | Set-AzVMSourceImage -PublisherName $VMPublisher -Offer $VMOffer -Skus $VMSku -Version latest } If ($VMOS -eq "Linux") { $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $VMFQDN -Credential $VMCredential Switch ($VMSubscription) { #"npd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"} #"infra01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-001"} #"prd01" {$vmConfig | Set-AzureRmVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-002"} "npd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/76297098-764c-43de-8525-c9fda1b237be/resourceGroups/rg-infra-templates-tst-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-103" } "infra01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/e53aa0c7-824d-40a2-b420-4ab77b1051d2/resourceGroups/rg-infra-templates-prd-001/providers/Microsoft.Compute/images/vm-rhel74template-prd-403" } "prd01" { $vmConfig | Set-AzVMSourceImage -Id "/subscriptions/437b2bfa-850e-4464-b6c2-38a68cda7c69/resourceGroups/rg-infra-templates-prd-002/providers/Microsoft.Compute/images/vm-rhel74template-prd-003" } } } $vmConfig | Add-AzVMNetworkInterface -Id $VMNIC.ID #$vmConfig | Set-AzureRmVMBootDiagnostics -Enable -ResourceGroupName $ResourceGroup -StorageAccountName $VMDiagStorageAcct ##set to use managed storage account after module conversion to Az #$vmConfig | Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup Set-AzVMBootDiagnostic -VM $vmConfig -Enable -ResourceGroupName $ResourceGroup Write-Verbose "Creating VM" New-AzVM -VM $vmConfig -ResourceGroupName $resourceGroup -Location $VMLocation -DisableBginfoExtension -LicenseType "Windows_Server" -AsJob } End { } } function Add-ITDAzureRMNewDataDisk { [CmdletBinding()] Param ( [string] $VMName, [int[]] $SizeGB ) Begin { $search = @() $Hostname = $VMName.split('-')[1] $Environment = $VMName.split('-')[2] Get-AzSubscription | ForEach-Object { $Subscription = $_ Set-AzContext $_ | Out-Null $search += Get-AzVM | Where-Object Name -EQ $VMName | Select-Object *, @{n = 'SubscriptionName'; e = { $Subscription.Name } } } } Process { If ($search.count -eq 1) { Set-AzContext $search.SubscriptionName $ResourceGroup = $search.ResourceGroupName.ToLower() $Location = (Get-AzResourceGroup -Name $ResourceGroup).Location $VM = Get-AzVM -Name $VMName -ResourceGroupName $ResourceGroup $Zone = $VM.Zones ForEach ($Size in $SizeGB) { $ExistingDisks = @($VM.StorageProfile.DataDisks | Select-Object *, @{n = 'ItdId'; e = { [int]($_.Name -replace "vm-$hostname-app-$environment-") } }) $NewDiskItdIdInt = ($ExistingDisks | Sort-Object ItdId -Descending | Select-Object -First 1).ItdId + 1 $NewDiskItdIdStr = $NewDiskItdIdInt.ToString("000") $NewDiskName = "vm-$Hostname-app-$Environment-$NewDiskItdIdStr" #vm-itduc4p1-app-tst-001 $LunID = ($ExistingDisks | Sort-Object Lun -Descending | Select-Object -First 1).Lun + 1 $count = 0 If ($ExistingDisks) { while ($Size -match $ExistingDisks.DiskSizeGB) { $count++ Write-Warning "SizeGB: $Size, Count: $count" If ($count -ge 11) { Write-Error "Disk size not available" -ErrorAction Stop } Else { $Size = $Size - 1 } } } Write-Warning "SizeGB: $Size, Count: $count" $AzureRmDiskConfigParams = @{ DiskSizeGB = $Size Location = $Location CreateOption = "Empty" SkuName = "Premium_LRS" } If ($Zone) { Write-Verbose "VM is located in Zone $Zone" $AzureRmDiskConfigParams += @{Zone = $Zone } } #$DiskConfig = New-AzureRmDiskConfig -DiskSizeGB $Size -Location $Location -CreateOption Empty -SkuName Premium_LRS $DiskConfig = New-AzDiskConfig @AzureRmDiskConfigParams If (!(Get-AzDisk -ResourceGroupName $ResourceGroup -DiskName $NewDiskName -ErrorAction SilentlyContinue)) { $NewDisk = New-AzDisk -DiskName $NewDiskName -Disk $DiskConfig -ResourceGroupName $ResourceGroup $VM = Add-AzVMDataDisk -Name $NewDiskName -CreateOption Attach -ManagedDiskId $NewDisk.Id -VM $VM -Lun $LunID -Caching ReadOnly Update-AzVM -VM $VM -ResourceGroupName $ResourceGroup -AsJob } } } Else { Write-Error "Search count invalid" -ErrorAction SilentlyContinue } } End { } } $IaasAutoCred = Get-AutomationPSCredential -Name 'ITD Iaas Automation' $IaasAutoCred = $IaaSAutoAz <# New-ITDAzureWindowsVMAA ` -ComputerName itdbuilddba.nd.gov ` -CPU 2 ` -MemoryGB 8 ` -Subnet '10.21.8.0/22'` -OS 'Windows Server 2019 Datacenter' ` -Environment 'Test' ` -AppName 'Infra-SoftDev-TFS' ` -LicensingRestrictions 'No Licensing Restrictions' ` -verbose #> <# $params = @{ ComputerName = "itdpurshir1.nd.gov" CPU = 2; MemoryGB = 8; Subnet = '10.69.254.0/24'; OS = 'Windows Server 2022 Datacenter'; Environment = 'CARES-tst'; AppName = 'ITD-POC-Purview'; LicensingRestrictions = 'No Licensing Restrictions'; Verbose = $true; } New-ITDAzureWindowsVMAA @params #> $params = @{ ComputerName = "itdsoscmtsql22.nd.gov" CPU = 4; MemoryGB = 16; Subnet = '10.21.8.0/22'; OS = 'Windows Server 2022 Datacenter'; Environment = 'Test'; AppName = 'SOS-BLS'; LicensingRestrictions = 'Microsoft SQL Standard'; Verbose = $true; } New-ITDAzureWindowsVMAA @params #>