843 lines
31 KiB
PowerShell
843 lines
31 KiB
PowerShell
# 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 '^.+?(?<!\\),', ''
|
|
}
|
|
Else {
|
|
Write-Error "AD object already exists, OU path mismatch"
|
|
Exit
|
|
Exit
|
|
}
|
|
}
|
|
Else {
|
|
switch ($Environment) {
|
|
'Test' {
|
|
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Non-Prod" }
|
|
Else { $EnvString = "Test" }
|
|
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$EnvString"
|
|
}
|
|
'Production' {
|
|
If ($AppName -like "Shared-Peoplesoft*") { $EnvString = "Prod" }
|
|
Else { $EnvString = "Prod" }
|
|
|
|
$OuAppNameEnv = Get-ADOrganizationalUnit -SearchBase $OUAppName.DistinguishedName -Filter * | Where-Object Name -EQ "$EnvString"
|
|
}
|
|
}
|
|
If ($OuAppNameEnv) { $OUFinal = $OUAppNameEnv.DistinguishedName }
|
|
Else { $OuFinal = $OUAppName.DistinguishedName }
|
|
|
|
New-ADComputer -Name $HostName.ToUpper() -Path $OUFinal -Credential $ADCred -Description ($SPItem | Select-Object AppName, Environment | ConvertTo-Json)
|
|
}
|
|
}
|
|
|
|
# disconnect, wait for firewall, then reconnect
|
|
Disconnect-AzAccount
|
|
While ($PingStatus -eq $false) {
|
|
$PingTest = Test-NetConnection -ComputerName $FQDN
|
|
If ($PingTest.PingSuccedded -eq $true) {
|
|
$PingStatus = $true
|
|
}
|
|
Start-Sleep -Seconds 300
|
|
}
|
|
|
|
|
|
Connect-AzAccount -ServicePrincipal -Credential $IaasAutoAzApp -Tenant $tenantId
|
|
Set-AzContext -Subscription $Subscription
|
|
|
|
|
|
|
|
# post-firewall Guest OS customization
|
|
switch ($DomainName) {
|
|
'nd.gov' {
|
|
Write-Warning "Attempting domain join nd.gov"
|
|
Write-Warning "Domain: $DomainName"
|
|
Write-Warning "OuPath: $OuFinal"
|
|
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\8-Domain-ndgov.ps1' -Parameter @{"DomainName" = 'nd.gov'; "OuPath" = ' CN=ITDSOSCMTSQL22,OU=SOS-BLS,OU=SOS-All,OU=Windows,OU=SERVERS,OU=COMPUTERS,OU=ITD,DC=nd,DC=gov' }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Write-Verbose -Message "Activating windows against $KMS..."
|
|
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\9-KMS.ps1'
|
|
|
|
<#
|
|
Write-Warning "[$FQDN]:Register SCCM Client"
|
|
$CcmRegistered = $false
|
|
While ($CcmRegistered -eq $false) {
|
|
$CcmResult = Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroup -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\AzWinBuild\10-SCCM-a.ps1'
|
|
If ($CcmResult.Value -match "SCCM Client is registered") {
|
|
Write-Warning "Client is registered."
|
|
$CcmRegistered = $true
|
|
}
|
|
ElseIf ($CcmRegistered -eq $false) { Start-Sleep -Seconds 60 }
|
|
}
|
|
|
|
Write-Warning -Message "[$FQDN]:Approve SCCM Client"
|
|
#Start-Sleep -Seconds 30 # ADD LOOP/SMARTS TO WAIT FOR DISCOVERY AND ANOTHER FOR APPROVAL
|
|
Invoke-Command -ComputerName itdsccmp2.nd.gov -Credential $CcmCred -ArgumentList $Hostname -ScriptBlock {
|
|
Import-Module 'D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1'
|
|
$PSDrives = Get-PSDrive
|
|
If ($PSDrives | Where-Object Name -EQ "ITD") {
|
|
# ITD Drive exists, do nothing
|
|
}
|
|
else {
|
|
New-PSDrive -Name "ITD" -PSProvider AdminUI.PS.Provider\CMSite -Root itdsccmp2.nd.gov
|
|
}
|
|
|
|
Set-Location ITD:\
|
|
$Device = Get-CMDevice -Name $args[0]
|
|
If ($Device.IsApproved -eq 0) {
|
|
Approve-CMDevice -DeviceName $args[0]
|
|
}
|
|
}
|
|
#>
|
|
|
|
|
|
}
|
|
|
|
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
|
|
|
|
|
|
|
|
#> |