<#
### step 1
gather specs
provision virtual machine on hypervisor

final result:
    cpu configured, with hot-add
    memory configured, with hot-add
    disks 1, 2, and 3 attached with correct sizing
    network connected
    virtual machine powered on

    update SCTASK Step 1 completed

### step 2 - customize Windows Guest OS
    wait for SCTASK Step 1 completed message
    configure
        time zone, mount points, page file, etc
    
    update SCTASK Step 2 completed

### step 3 - administration
    wait for SCTASK Step 2 completed message
    domain join
        nd.gov at a minimum
    install sccm
        regardless if domain joined

    update SCTASK Step 3 completed

### step 4 - validation


    confirm all agents are installed
    disks are present and formatted

#>

<#
.SYNOPSIS
    A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
    A longer description of the function, its purpose, common use cases, etc.
.NOTES
    Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
    Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
    $NewITDWindowsVmVMwareParams = @{
        ComputerName = 'itdzmtest300.nd.gov';
        CPU = 2;
        MemoryGB = 8;
        DiskOsGB = 50;
        DiskSwapGB = 9;
        DiskDataGB = 20;
        Subnet = '10.11.12.0/23';
        OS = 'Windows Server 2022 Datacenter';
        Environment = "Test";
        Datacenter = "Bismarck";
        AppName = "ITD-POC-zmeier";
        StartupPriority = 4;
        LicensingRestrictions = "No Licensing Restrictions";
        Credential = $PrvCred;
    }

    New-ITDWindowsVmVMware @NewITDWindowsVmVMwareParams
#>

function New-ITDWindowsVmVMwareStep1 {
    [CmdletBinding()]
    param (
        [string]
        $FQDN,

        [int]
        $CPU,
    
        [int]
        $MemoryGB,

        [int]
        $DiskOsGB,

        [int]
        $DiskSwapGB,

        [int]
        $DiskDataGB,

        [string]
        $Subnet,

        [string]
        $OS,

        [string]
        $VMEnvironment,
    
        [string]
        $Datacenter,

        [string]
        $AppName,

        [int]
        $StartupPriority,

        [string]
        $LicensingRestrictions,

        [PSCredential]
        $Credential

    )
    
    begin {
        
    }
    
    process {
        $FQDN = $FQDN.ToLower()
        $HostName = $FQDN.split('.')[0]

        If ($VMEnvironment -eq "Development") {
            $VMEnvironment = "Test"
        }

        Write-Verbose -Message "Prepare Credentials and Connections"
        $RadiusCred = New-Object System.Management.Automation.PSCredential($Credential.username.split('\')[1], ($Credential.Password))

        Write-Verbose -Message "Infoblox: Find DNS pre-existing record, or create one"
        Write-Verbose -Message "FQDN: $FQDN" -Verbose
        Write-Verbose -Message "Hostname: $Hostname" -Verbose

        Clear-DnsClientCache
        $InfobloxVlanMetadata = Get-ITDIbVlan -CIDR $Subnet -Credential $RadiusCred
        $Cidr = ($InfobloxVlanMetadata.AssignedTo | Out-String).TrimEnd()
        [Net.IpAddress]$NetworkId = $Cidr.split('/')[0]
        #######
        #######  Remove 10.10.10.10 references when DNS sync is fixed
        #######
        [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction SilentlyContinue -Server 10.10.10.10).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 ($null -ne $IpAddress) {
            If (($IpAddress.Address -band $SubnetMask.Address) -eq ($NetworkId.Address -band $SubnetMask.Address)) {
                Write-Verbose -Message "DNS record already exists, CIDR Block match"
            }
            Else {
                Write-Error "DNS record already exists, but does not match CIDR Block"
                Break
            }
        }
        Else {
            Write-Verbose -Message "Pre-existing IP address not found, creating new DNS record."
            try {
                New-ITDIbDNSRecordNextAvailableIP -Hostname $FQDN -CIDR $CIDR -Credential $RadiusCred
                Start-Sleep -Seconds 5
                Write-Verbose -Message ("FQDN is " + $FQDN)
            }
            catch {
                
            }



            #######
            #######  Review this code after DNS problems resolved - 2024/09/24 zm
            #######
            #######  [Net.IPAddress]$IpAddress = (Resolve-DnsName -Name $FQDN -ErrorAction Stop -Server 10.10.10.10).IPAddress

            [Net.IPAddress]$IpAddress = (Get-ITDIbDNSRecord -Hostname $FQDN -Credential $RadiusCred).IPv4Address
            
            If ((Test-NetConnection -ComputerName $IpAddress.IPAddressToString).PingSucceeded) {
                Write-Error "IP Address already in use." -ErrorAction Stop
            }
        }

        Write-Verbose -Message "Passwordstate: If local administrator password does not exist in vault, create it."
        If ($FQDN -like "itdcnd*") {
            $PasswordStateList = "Peoplesoft Share PW"
        }
        Else {
            $PasswordStateList = "CSRC"
        }

        $GuestVMLocalCredential = Get-ITDPassword -Title $FQDN -UserName itdadmin -Credential $Credential
        If ($null -eq $GuestVMLocalCredential) {
            Write-Verbose -Message "Passwordstate: Local admin password record does not exist, creating new credentials"
            $GuestVMLocalCredential = New-ITDPassword -Title $FQDN -UserName itdadmin -Description 'Local Administrator' -PasswordList $PasswordStateList -Credential $Credential
        }
        Else {
            Write-Verbose -Message "Passwordstate: Local admin password record already exists, use those credentials"
        }
        $GuestCredentialAB = New-Object System.Management.Automation.PSCredential ('itdadmin', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))
        $GuestCredentialBB = New-Object System.Management.Automation.PSCredential ('Administrator', ($GuestVMLocalCredential.GetNetworkCredential().Password | ConvertTo-SecureString -AsPlainText -Force))

        Write-Verbose -Message "Decide VMware Cluster and Licensing"
        switch ($LicensingRestrictions) {    
            "No Licensing Restrictions" { $ClusterRoot = "WINDOWS" }
            "Microsoft SharePoint Server" { $ClusterRoot = "WINDOWS" }
            "Microsoft SharePoint Server (Academic)" { $ClusterRoot = "WINDOWS" }
            "Microsoft SQL Developer" { $ClusterRoot = "WINDOWS" }
            "Microsoft SQL MSDN" { $ClusterRoot = "WINDOWS" }
            "Microsoft SQL Standard" { $ClusterRoot = "WINDOWS" }
            "Microsoft SQL Standard (Academic)" { $ClusterRoot = "WINDOWS" }
            "Microsoft SQL Standard (Vendor Provided)" { $ClusterRoot = "WINDOWS" }
            "Microsoft SQL Enterprise" { $ClusterRoot = "SQLe" }
            "Microsoft SQL Enterprise (Academic)" { $ClusterRoot = "SQLa" }
            "IBM Websphere" { $ClusterRoot = "WAS" }
            "Powerschool" { $ClusterRoot = "PS" }
            "Pexip" { $ClusterRoot = "TEL" }
        }

        Write-Verbose -Message "Decide Datacenter"
        switch ($Datacenter) {
            "Bismarck" { $ClusterInt = 1 }
            "Mandan" { $ClusterInt = 2 }
        }
        
        $Cluster = $ClusterRoot + $ClusterInt
        Write-Verbose -Message "VMware Cluster is $Cluster, gathering metadata for $Cluster"
        
        switch ($Cluster) {
            "WINDOWS1" {
                $ViServer = 'itdvmvc1.nd.gov'
                $ComputeCluster = Get-Cluster WINDOWS1
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
        
                If ($LicensingRestrictions -like "*SQL*") {
                    $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_SQL"
                    $DiskStorageFormat = 'EagerZeroedThick'
                }
                Else {
                    $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS1_FS92_Gen"
                    $DiskStorageFormat = 'Thin'
                }
            }
            "WINDOWS2" {
                $ViServer = 'itdvmvc2.nd.gov'
                $ComputeCluster = Get-Cluster WINDOWS2
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
                $DiskStorageFormat = 'Thin'
                If ($LicensingRestrictions -like "*SQL*") {
                    $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_SQL"
                    $DiskStorageFormat = 'EagerZeroedThick'
                }
                Else {
                    $DatastoreCluster = Get-DatastoreCluster -Name "WINDOWS2_FS92_Gen"
                    $DiskStorageFormat = 'Thin'
                }
            }
            "SQLa1" {
                $ViServer = 'itdvmvc1.nd.gov'
                $ComputeCluster = Get-Cluster SQLa1
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
                $DiskStorageFormat = 'EagerZeroedThick'
                $DatastoreCluster = Get-DatastoreCluster -Name "SQLa1_FS92_Gen"
            }
            "SQLa2" {
                $ViServer = 'itdvmvc2.nd.gov'
                $ComputeCluster = Get-Cluster SQLa2
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
                $DiskStorageFormat = 'EagerZeroedThick'
                $DatastoreCluster = Get-DatastoreCluster -Name "SQLa2_FS92_Gen"
            }
            "SQLe1" {
                $ViServer = 'itdvmvc1.nd.gov'
                $ComputeCluster = Get-Cluster SQLe1
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
                $DiskStorageFormat = 'EagerZeroedThick'
                $DatastoreCluster = Get-DatastoreCluster -Name "SQLe1_FS92_Gen"
            }
            "SQLe2" {
                $ViServer = 'itdvmvc2.nd.gov'
                $ComputeCluster = Get-Cluster SQLe2
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
                $DiskStorageFormat = 'EagerZeroedThick'
                $DatastoreCluster = Get-DatastoreCluster -Name "SQLe2_FS92_Gen"
            }
            "WAS1" {
                $ViServer = 'itdvmvc1.nd.gov'
                $ComputeCluster = Get-Cluster WAS1
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
                $DiskStorageFormat = 'Thin'
                $DatastoreCluster = Get-DatastoreCluster -Name "WAS1_FS92_Gen"
            }
            "WAS2" {
                $ViServer = 'itdvmvc2.nd.gov'
                $ComputeCluster = Get-Cluster WAS2
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
                $DiskStorageFormat = 'Thin'
                $DatastoreCluster = Get-DatastoreCluster -Name "WAS2_FS92_Gen"
            }
            "PS1" {
                $ViServer = 'itdvmvc1.nd.gov'
                $ComputeCluster = Get-Cluster PS1
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-Data-Server"
                $DiskStorageFormat = 'Thin'
                $DatastoreCluster = Get-DatastoreCluster -Name "PS1_FS92_Gen"
            }
            "PS2" {
                $ViServer = 'itdvmvc2.nd.gov'
                $ComputeCluster = Get-Cluster PS2
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-SDC-Data-Server"
                $DiskStorageFormat = 'Thin'
                $DatastoreCluster = Get-DatastoreCluster -Name "PS2_FS92_Gen"
            }
            "TEL1" {
                $ViServer = 'itdvmvc1.nd.gov'
                $ComputeCluster = Get-Cluster TEL1
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL1-Data"
                $DiskStorageFormat = 'Thin'
                $DatastoreCluster = Get-DatastoreCluster -Name "TEL1_FS92_Gen"
            }
            "TEL2" {
                $ViServer = 'itdvmvc2.nd.gov'
                $ComputeCluster = Get-Cluster TEL2
                $VirtualSwitch = Get-VDSwitch -Name "dvSwitch-PDC-TEL2-Data"
                $DiskStorageFormat = 'Thin'
                $DatastoreCluster = Get-DatastoreCluster -Name "TEL2_FS92_Gen"
            }
            Default {
                Write-Error "Cluster not found" -ErrorAction Stop
            }
        }

        Write-Verbose -Message "Validate entered disk sizes"
        Write-Verbose -Message "DiskOsGB is $DiskOsGB.  Validating its not a stupid number." -Verbose
        switch ($DiskOsGB) {
            { $_ -lt 50 } {
                Write-Verbose -Message "DiskOsGB is 0 or below.  Since an OS Disk is required, defaulting to 50GB" -Verbose
                $DiskOsGB = 50
            }
        }

        Write-Verbose -Message "DiskSwapGB is $DiskSwapGB.  Validating its not a stupid number." -Verbose
        switch ($DiskSwapGB) {
            { $_ -le 0 } {
                Write-Verbose -Message "DiskSwapGB is zero or below.  Since an Swap Disk is required, defaulting to `$Memory + 1GB." -Verbose
                $DiskSwapGB = ($MemoryGB + 1)
            }
        }

        Write-Verbose -Message "DiskDataGB is $DiskDataGB.  Validating its not a stupid number." -Verbose
        switch ($DiskDataGB) {
            { $_ -le 0 } {
                Write-Verbose -Message "DiskDataGB is 0.  Since an Data Disk is optional, data disk will not be created." -Verbose
                $DiskDataGB = 0
            }
            { $_ -gt 500 } {
                Write-Verbose -Message "DiskDataGB is 500GB or more.  DiskDataGB will be set to the maximum of 500GB." -Verbose
                $DiskDataGB = 500
            }
        }

        Write-Verbose -Message "Determine Datastore / Datastore Cluster"
        $DiskTotal = $DiskOsGB + $DiskSwapGB + $DiskDataGB
        If ($DatastoreCluster) {
        }
        Else {
            $DatastoreCluster = Get-DatastoreCluster | Where-Object Name -Like ("*" + $ComputeCluster + "*")
        }
        $ClusterDatastoreWithHighestFreeSpaceGB = ($DatastoreCluster | Get-Datastore | Sort-Object FreeSpaceGB -Descending | Select-Object -First 1)
        If ($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB -gt $DiskTotal) {
            Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
        }
        else {
            Write-Warning ("VM DiskTotal " + $DiskTotal + "GB, will not fit on " + $ClusterDatastoreWithHighestFreeSpaceGB.Name + " (" + [math]::round($ClusterDatastoreWithHighestFreeSpaceGB.FreeSpaceGB, 0) + "GB free)")
            Write-Error ("New VM " + $FQDN + " needs " + $DiskTotal + "GB of free space on a single datastore in the " + $DatastoreCluster.Name + " datastore cluster.") -ErrorAction Stop
        }

        $FolderLocation = $ComputeCluster | Get-Datacenter | Get-Folder -Name "_New Builds"

        Write-Verbose -Message "Determine VMware VM Template for OS: $OS"
        switch ($OS) {
            "Windows Server 2012R2 Standard" { $Template = "Windows Server 2012R2 Standard" }
            "Windows Server 2016 Standard" { $Template = "Windows Server 2016 Standard" }
            "Windows Server 2019" { $Template = "Windows Server 2019 Standard 1809.19" }
            "Windows Server 2019 Standard" { $Template = "Windows Server 2019 Standard 1809.19" }
            "Windows Server 2019 Datacenter" { $Template = "Windows Server 2019 Standard 1809.19" }
            "Windows Server 2022" { $Template = "Windows Server 2022 Standard 2108.21" }
            "Windows Server 2022 Datacenter" { $Template = "Windows Server 2022 Standard 2108.21" }
            "Windows Server 2025" { $Template = "Windows Server 2025 Standard 24H2.6" }
            Default { Write-Error "Invalid template option: $OS" -ErrorAction Stop }
        }

        Write-Verbose -Message "Determine VMware Port Group"
        $PortGroupsAvailable = Get-VDPortgroup -Server $ViServer -VDSwitch $VirtualSwitch
        $PortGroup = $PortGroupsAvailable | Where-Object Name -Like ("dvPG_*" + $NetworkId.IPAddressToString + "_" + $SubnetMaskInt)
        If (!($PortGroup)) {
            Write-Error "Virtual port group not found" -ErrorAction Stop
            Stop 
        }
        If (@($PortGroup).count -gt 1) {
            Write-Error "Multiple port groups found" -ErrorAction Stop
            Stop
        }

        Write-Verbose -Message "Configure Guest OS Customization Spec"
        $NewOSSpecName = ("AutoBuild-$Hostname-" + (Get-Date -UFormat "%Y%m%d%H%M%S"))
        Write-Warning "NewOSSpecName = $NewOSSpecName"
    
        Get-OSCustomizationSpec -Name 'Windows (Auto)' -Server $ViServer | New-OSCustomizationSpec -Name $NewOSSpecName -Type Persistent -Server $ViServer

        Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | `
            Set-OSCustomizationSpec `
            -NamingScheme fixed `
            -NamingPrefix $Hostname `
            -AdminPassword $GuestCredentialBB.GetNetworkCredential().Password

        Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer | `
            Get-OSCustomizationNicMapping | `
            Set-OSCustomizationNicMapping `
            -IpMode UseStaticIP `
            -IpAddress $IpAddress.IPAddressToString `
            -SubnetMask $SubnetMask.IPAddressToString `
            -DefaultGateway $DefaultGateway.IPAddressToString `
            -Dns "10.2.7.40", "10.10.10.10"
    
        $OSSpec = Get-OSCustomizationSpec -Name $NewOSSpecName -Server $ViServer

        Set-Location C:\Temp
        $NewVMParams = @{
            Name              = $FQDN;
            ResourcePool      = $ComputeCluster.Name;
            Datastore         = $DatastoreCluster;
            DiskStorageFormat = $DiskStorageFormat;
            Location          = $FolderLocation;
            # Removed when using Content Library
            #Template            = $Template;
            #OSCustomizationSpec = $OSSpec
        }

        Get-ContentLibraryItem -Name $Template -Server $ViServer | New-VM @NewVMParams
        $VM = Get-VM -Name $FQDN
        $VM | Set-VM -OSCustomizationSpec $OSSpec -Confirm:$false

        Write-Verbose -Message "Set vCenter Tags on VM"
        New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category AppName -Name $AppName) -Server $VIServer
        New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category DTAP -Name $VMEnvironment) -Server $VIServer
        New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category LicensingRestrictions -Name $LicensingRestrictions) -Server $VIServer
        New-TagAssignment -Entity (Get-VM $FQDN -Server $VIServer) -Tag (Get-Tag -Server $ViServer -Category StartupPriority -Name $StartupPriority) -Server $VIServer

    
        # Ensure CPU/Memory Hot-Add Enabled
        $vmView = $VM | Get-View
        $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $vmOptValCPU = New-Object VMware.Vim.OptionValue
        $vmOptValMem = New-Object VMware.Vim.OptionValue
        $vmOptValCPU.Key = "vcpu.hotadd"
        $vmOptValMem.Key = "mem.hotadd"
        $vmOptValCPU.Value = "true"
        $vmOptValMem.Value = "true"
        $vmConfigSpec.ExtraConfig += $vmOptValCPU
        $vmConfigSpec.ExtraConfig += $vmOptValMem
        $vmView.ReconfigVM($vmConfigSpec)

        # Set CPU, Memory, Network
        $VM | Set-VM -NumCpu $CPU -MemoryGB $MemoryGB -Confirm:$false
        $VM | Get-NetworkAdapter | Set-NetworkAdapter -Portgroup $PortGroup -Confirm:$false



        Write-Verbose -Message "Config and Update Disks"
        $VMDisk = $VM | Get-HardDisk
        $VMDisk1 = $VMDisk | Where-Object Name -EQ "Hard disk 1"
        $VMDisk2 = $VMDisk | Where-Object Name -EQ "Hard disk 2"
        $VMDisk3 = $VMDisk | Where-Object Name -EQ "Hard disk 3"

        Write-Verbose -Message "Update Disk 1"
        $VMDisk1 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 1"
        If ($VMDisk1.CapacityGB -lt $DiskOsGB) { 
            Set-HardDisk -HardDisk $VMDisk1 -CapacityGB $DiskOsGB -Confirm:$false
        }

        Write-Verbose -Message "Config Disk 2"
        If (!$VMDisk2) {
            $VM | New-HardDisk `
                -CapacityGB ($MemoryGB + 1) `
                -StorageFormat Thin `
                -DiskType Flat `
                -Persistence Persistent
        }
        $VMDisk2 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 2"
        If ($VMDisk2.CapacityGB -lt $DiskSwapGB) {
            Set-HardDisk -HardDisk $VMDisk2 -CapacityGB $DiskSwapGB -Confirm:$false
        }

        Write-Verbose -Message "Config Disk 3"
        If ($DiskDataGB -gt 0) {
            Write-Verbose -Message "$DiskDataGB greater than zero"
            If (!$VMDisk3) {
                $VM | New-HardDisk `
                    -CapacityGB $DiskDataGB `
                    -StorageFormat Thin `
                    -DiskType Flat `
                    -Persistence Persistent
            }
            $VMDisk3 = $VM | Get-HardDisk | Where-Object Name -EQ "Hard disk 3"
            If ($VMDisk3.CapacityGB -lt $DiskDataGB) {
                Set-HardDisk -HardDisk $VMDisk3 -CapacityGB $DiskDataGB -Confirm:$false
            }
        }

        Write-Verbose -Message "Set VMware Tools Upgrade Policy to UpgradeAtPowerCycle"
        $VMView = $VM | Get-View
        $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
        $vmConfigSpec.Tools.ToolsUpgradePolicy = "UpgradeAtPowerCycle"
        $VMView.ReconfigVM($vmConfigSpec)

        Write-Verbose -Message "Power On VM"
        $VM | Start-VM 

        Write-Verbose -Message "[$FQDN]:Step 1 End"
    }
    
    end {
        
    }
}