341 lines
18 KiB
PowerShell
341 lines
18 KiB
PowerShell
function New-ITDWindowsVMAzureStep2 {
|
|
[CmdletBinding()]
|
|
param (
|
|
[string]
|
|
$FQDN,
|
|
|
|
[string]
|
|
$AppName,
|
|
|
|
[string]
|
|
$VMEnvironment,
|
|
|
|
[PSCredential]
|
|
$Credential
|
|
)
|
|
|
|
begin {
|
|
$search = @()
|
|
#$Hostname = $VMName.split('-')[1]
|
|
$HostName = $FQDN.split('.')[0]
|
|
###$VMEnvironment = $VMName.split('-')[2] ####
|
|
|
|
Write-Verbose -Message ("Searching for Az VM name like " + $HostName)
|
|
Get-AzSubscription | ForEach-Object {
|
|
$Subscription = $_
|
|
Set-AzContext $_ | Out-Null
|
|
$search += Get-AzVM | Where-Object Name -Like "*$HostName*" | Select-Object *, @{n = 'SubscriptionName'; e = { $Subscription.Name } }
|
|
}
|
|
}
|
|
|
|
process {
|
|
switch (@($Search).count) {
|
|
{ $_ -gt 1 } { Write-Error -Message "More than one virtual machine match found." }
|
|
{ $_ -lt 1 } { Write-Error -Message "Less than one virtual machine match found." }
|
|
{ $_ -eq 1 } {
|
|
Write-Verbose -Message "Prep VM variables"
|
|
$VMName = $search.Name
|
|
$ResourceGroupName = $search.ResourceGroupName
|
|
#$VMEnvironment = $VMName.split('-')[2]
|
|
$SubscriptionName = $search.SubscriptionName
|
|
Set-AzContext -Subscription $SubscriptionName
|
|
|
|
$VM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName
|
|
|
|
Write-Verbose -Message "Set firewall tag"
|
|
$Tags = @{"Network"="StandardWindows"}
|
|
New-AzTag -ResourceId $VM.Id -Tag $Tags
|
|
|
|
Write-Verbose -Message "Wait two minutes before Pre-Firewall Guest OS customization"
|
|
#Start-Sleep -Seconds 120
|
|
|
|
Write-Verbose -Message "Begin Pre-Firewall Guest OS customization"
|
|
$InvokeAzVMRunCommandParams = @{
|
|
ResourceGroupName = $ResourceGroupName;
|
|
Name = $VMName;
|
|
CommandId = 'RunPowerShellScript'
|
|
}
|
|
|
|
Write-Verbose -Message "1-Set WMI Tags"
|
|
$ScriptBlock = {
|
|
try {
|
|
Write-Verbose "Create new Class"
|
|
$Class = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null);
|
|
|
|
$Class["__CLASS"] = "ITD";
|
|
$Class.Qualifiers.Add("Static", $true)
|
|
$Class.Properties.Add("MyKey", [System.Management.CimType]::String, $false)
|
|
$Class.Properties["MyKey"].Qualifiers.Add("Key", $true)
|
|
|
|
$Class.Properties.Add("LastModified", [System.Management.CimType]::String, $false)
|
|
$Class.Properties.Add("DTAP", [System.Management.CimType]::String, $false)
|
|
$Class.Properties.Add("Baseline", [System.Management.CimType]::String, $false)
|
|
|
|
$Class.Put()
|
|
|
|
Write-Verbose "Create single ITD Object"
|
|
Set-WmiInstance -Class ITD -Arguments @{LastModified = (Get-Date); DTAP = "Prod"; Baseline = "000" }
|
|
}
|
|
catch {
|
|
Throw $_
|
|
Break
|
|
}
|
|
}
|
|
Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock
|
|
|
|
Write-Verbose -Message "3-Disk Configuration"
|
|
$ScriptBlock = {
|
|
try {
|
|
# Non-initialized and MBR-initialized disks will have 0 partitions by default, but GPT-initialized disks will have 1 system reserved partition by default
|
|
$disks = Get-Disk | Where-Object { $_.NumberOfPartitions -eq 0 -or ( $_.PartitionStyle -eq 'GPT' -and $_.NumberOfPartitions -eq 1 ) } | Sort-Object -Property Number
|
|
|
|
if ($disks) {
|
|
Write-Verbose -Message "Found $(@($disks).Count) unpartitioned disks."
|
|
|
|
# Prevent the "You must format this partition before using it." popup
|
|
if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Stop-Service ShellHWDetection -ErrorAction SilentlyContinue }
|
|
|
|
foreach ($disk in $disks) {
|
|
if ($disk.IsOffline) {
|
|
Set-Disk $disk.Number -IsOffline $false
|
|
Write-Verbose -Message "Brought disk $($disk.Number)($("{0:n0}GB" -f ($disk.Size / 1GB))) online..."
|
|
}
|
|
|
|
if ($disk.IsReadOnly) { Set-Disk $disk.Number -IsReadOnly $false }
|
|
if ($disk.PartitionStyle -eq 'RAW') { Initialize-Disk $disk.Number -PartitionStyle GPT -ErrorAction SilentlyContinue }
|
|
|
|
$diskParam = @{
|
|
FileSystem = 'NTFS'
|
|
Confirm = $false
|
|
}
|
|
|
|
$driveLetter = [Int][Char]'D'
|
|
while (Get-Volume -DriveLetter $([Char]$driveLetter) -ErrorAction SilentlyContinue) {
|
|
$driveLetter++
|
|
}
|
|
|
|
$diskParam.DriveLetter = [Char]$driveLetter
|
|
|
|
if (@($disks).IndexOf($disk) -eq 0 -and (-not (Get-Volume -DriveLetter D -ErrorAction SilentlyContinue))) {
|
|
$diskParam.NewFileSystemLabel = 'Temporary Storage'
|
|
}
|
|
elseif (@($disks).IndexOf($disk) -eq 1 -and (-not (Get-Volume -DriveLetter E -ErrorAction SilentlyContinue))) {
|
|
$diskParam.NewFileSystemLabel = 'Data'
|
|
}
|
|
|
|
[void](New-Partition -DiskNumber $disk.Number -DriveLetter $diskParam.DriveLetter -UseMaximumSize)
|
|
[void](Format-Volume @diskParam)
|
|
}
|
|
}
|
|
else {
|
|
Write-Verbose -Message "No unpartitioned disks found, continuing..."
|
|
}
|
|
}
|
|
catch {
|
|
Throw $_
|
|
Break
|
|
}
|
|
finally {
|
|
if (Get-Service ShellHWDetection -ErrorAction SilentlyContinue) { Start-Service ShellHWDetection -ErrorAction SilentlyContinue }
|
|
}
|
|
}
|
|
Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock
|
|
|
|
Write-Verbose -Message "5-Time Zone"
|
|
$ScriptBlock = {
|
|
if ((Get-TimeZone).Id -ne 'Central Standard Time') {
|
|
Write-Verbose -Message "Current time zone set to $((Get-TimeZone).Id), setting to Central Standard Time."
|
|
|
|
Set-TimeZone -Id 'Central Standard Time'
|
|
|
|
Write-Verbose -Message "Time zone set to Central Standard Time."
|
|
}
|
|
else {
|
|
Write-Verbose -Message "Time zone is already set to Central Standard Time."
|
|
}
|
|
}
|
|
Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock
|
|
|
|
Write-Verbose -Message "6-Enable Performance Counters"
|
|
$ScriptBlock = {
|
|
# Enable Performance Counters
|
|
try {
|
|
if (Get-ScheduledTask -TaskName "Server Manager Performance Monitor" | Where-Object State -NE "Running" -ErrorAction SilentlyContinue) {
|
|
Enable-ScheduledTask -TaskPath "\Microsoft\Windows\PLA\" -TaskName "Server Manager Performance Monitor" | Start-ScheduledTask
|
|
|
|
Write-Verbose -Message "Performance monitors enabled."
|
|
}
|
|
else {
|
|
Write-Verbose -Message "Performance monitors already enabled, continuing..."
|
|
}
|
|
}
|
|
catch {
|
|
Throw $_
|
|
Break
|
|
}
|
|
}
|
|
Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock
|
|
|
|
Write-Verbose -Message "7-Disable Windows Firewall"
|
|
$ScriptBlock = {
|
|
# Disable Windows Firewall
|
|
Write-Verbose -Message "Checking for active Windows Firewall..."
|
|
|
|
if ((Get-NetFirewallProfile).Enabled -contains 'True') {
|
|
Write-Verbose -Message "Windows Firewall is still enabled, disabling it..."
|
|
|
|
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled False
|
|
|
|
Write-Verbose -Message "Windows Firewall disabled."
|
|
}
|
|
else {
|
|
Write-Verbose -Message "Windows Firewall already disabled, continuing..."
|
|
}
|
|
}
|
|
Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock
|
|
|
|
# determine Active Directory Forest and OU
|
|
Write-Verbose -Message "8a-Determine domain join"
|
|
$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 ($null -eq $OUAppName) {
|
|
Write-Verbose -Message "Dedicated AppName OU for $AppName not found, placing in All-General OU"
|
|
$OUAppName = Get-ADOrganizationalUnit -Server $DomainName -SearchBase ("OU=Windows,OU=SERVERS,ou=COMPUTERS,ou=ITD," + $SearchBaseDomain) -Filter { Name -eq 'All-General' }
|
|
}
|
|
Write-Verbose -Message ("OUAppName: " + $OUAppName.distinguishedName) -Verbose
|
|
|
|
# Determine if the Environment sub-ou is special for the selected AppName
|
|
switch ($OUAppName.Name) {
|
|
'Shared-PeopleSoft-HigherEd' {
|
|
switch ($VMEnvironment) {
|
|
'Test' { $EnvString = "Non-Prod" }
|
|
'Production' { $EnvString = "Prod" }
|
|
}
|
|
}
|
|
'Shared-PeopleSoft-State' {
|
|
switch ($VMEnvironment) {
|
|
'Test' { $EnvString = "Non-Prod" }
|
|
'Production' { $EnvString = "Prod" }
|
|
}
|
|
}
|
|
Default {
|
|
switch ($VMEnvironment) {
|
|
'Test' { $EnvString = "Test" }
|
|
'Production' { $EnvString = "Prod" }
|
|
}
|
|
}
|
|
}
|
|
|
|
# Gather all sub OUs for the AppName OU
|
|
Write-Verbose -Message "EnvString is $EnvString" -Verbose
|
|
$SubOUs = Get-ADOrganizationalUnit -Server $DomainName -SearchBase $OUAppName -Filter *
|
|
Write-Verbose -Message ("SubOUs:") -Verbose
|
|
$SubOUs | ForEach-Object { Write-Verbose -Message $_.DistinguishedName -Verbose }
|
|
$LikeFilter = ("OU=$EnvString,OU=" + $OUAppName.Name + "*")
|
|
Write-Verbose -Message "LikeFilter: $LikeFilter"
|
|
$OUToUse = $SubOUs | Where-Object { $_.DistinguishedName -like $LikeFilter }
|
|
Write-Verbose -Message ("OUToUse: " + $OUToUse.distinguishedName) -Verbose
|
|
|
|
<#$MatchFilter = ("OU=$EnvString,OU=" + $OUAppName.Name)
|
|
Write-Verbose -Message "MatchFiler: $MatchFilter"
|
|
$OutToUseMatch = ($SubOUs | Where-Object {$_.DistinguishedName -match "^$MatchFilter"})
|
|
Write-Verbose -Message ("OUToUseMatch: " + $OUToUseMatch.distinguishedName) -Verbose
|
|
#>
|
|
# Determine if AD Computer object already exists
|
|
$ExistingADComputer = Get-ADComputer -Filter { Name -eq $HostName }
|
|
If ($ExistingADComputer) {
|
|
Write-Verbose -Message "AD Object already exists in AD"
|
|
# Determine if AD Computer object is in the correct OU, or a sub-OU of the correct OU
|
|
If ($ExistingADComputer.DistinguishedName -like ("*" + $OUToUse.DistinguishedName)) {
|
|
Write-Verbose -Message "AD Object is in the correct OU, will attempt domain join"
|
|
$AttemptDomainJoin = $true
|
|
}
|
|
Else {
|
|
Write-Verbose -Message "AD Object is NOT in the correct OU, domain join will not occur, needs human review"
|
|
$AttemptDomainJoin = $false
|
|
}
|
|
}
|
|
Else {
|
|
$AttemptDomainJoin = $true
|
|
}
|
|
|
|
If ($AttemptDomainJoin) {
|
|
$OuFinal = $OUToUse.DistinguishedName
|
|
Write-Verbose -Message "OuFinal: $OuFinal" -Verbose
|
|
|
|
$FirstScriptBlock = { $DomainJoinCred = New-Object System.Management.Automation.PSCredential('svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force)) }
|
|
$SecondScriptText = 'Add-Computer -DomainName <DomainName> -OUPath "<OuPath>" -Credential $DomainJoinCred -Server itddc42.nd.gov -Verbose; Restart-Computer -Force -Verbose;'
|
|
$SecondScriptText = $SecondScriptText -replace '<DomainName>', $DomainName
|
|
$SecondScriptText = $SecondScriptText -replace '<OuPath>', $OuFinal
|
|
|
|
#Write-Verbose -Message "[$FQDN]:Invoke-VMScript to AD join"
|
|
$InvokeVMScriptFunc = [System.Management.Automation.ScriptBlock]::Create("$FirstScriptBlock ; $SecondScriptText")
|
|
}
|
|
Write-Verbose -Message $InvokeVMScriptFunc.tostring() -Verbose ###
|
|
<# wait for firewall and reconnect
|
|
Write-Verbose -Message "8b-Verify if firewall is open before domain join attempt"
|
|
$connectivity = $false
|
|
while ($connectivity -eq $false) {
|
|
If ( (Test-NetConnection -ComputerName $FQDN).PingSuccedded) {
|
|
Write-Verbose -Message "Ping successful" -Verbose
|
|
$connectivity = $true
|
|
}
|
|
Else {
|
|
Write-Verbose -Message "Ping failed, may need to wait for PA IP sync" -Verbose
|
|
Start-Sleep -Seconds 60
|
|
}
|
|
}
|
|
#>
|
|
Write-Verbose -Message "8c-Attempt domain join"
|
|
switch ($DomainName) {
|
|
'nd.gov' {
|
|
Write-Verbose -Message "Attempting domain join nd.gov"
|
|
Write-Verbose -Message "Domain: $DomainName"
|
|
Write-Verbose -Message "OuPath: $OuFinal"
|
|
<#Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptPath 'C:\AzWinBuild\8-Domain-ndgov.ps1' -Parameter @{
|
|
"DomainName" = 'nd.gov';
|
|
"OuPath" = "$OuFinal"
|
|
}#>
|
|
$ScriptBlock = {
|
|
Param(
|
|
[string]
|
|
$DomainName,
|
|
|
|
[string]
|
|
$OuPath
|
|
)
|
|
|
|
Write-Host $OuPath
|
|
Test-NetConnection -ComputerName nd.gov
|
|
|
|
$DomainJoinCred = New-Object System.Management.Automation.PSCredential('ndgov\svcitdvmdomainjoin', ('hypes-Vgv8h89' | ConvertTo-SecureString -AsPlainText -Force))
|
|
Add-Computer -DomainName $DomainName -OUPath $OuPath -Credential $DomainJoinCred
|
|
|
|
Restart-Computer -Force
|
|
}
|
|
Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $ScriptBlock -Parameter @{
|
|
"DomainName" = 'nd.gov';
|
|
"OuPath" = "$OuFinal"
|
|
}
|
|
#Invoke-AzVMRunCommand @InvokeAzVMRunCommandParams -ScriptString $InvokeVMScriptFunc
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
end {
|
|
|
|
}
|
|
} |