SDVM.psm1

<#
 
.NOTES
    This contains functions for deploying various virtual machines to the virtualization infrastructure.
 
#>


Function Get-SDRebootStatus {
    <#
        .DESCRIPTION
            This function checks the status of a sever to determine if it has finished rebooting.
     
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [String]
        $VM
    )
    Start-Sleep -Seconds 60

    while (-not(Test-Connection $VM -Count 1 -quiet)) {
        "Waiting for $VM to reboot"
    }
    else {
        "$VM is back online!"
    }
}
Function New-SDVM {
    <#
        .DESCRIPTION
            This Function deployes a base Windows Server 2022 OVA to the cluster and addes it to the domain if you specifiy it to.
         
        .PARAMETER addDomain
            This is a boolean value that is set to true for $false
            If set to True it will add the machine to the domain after it is deployed.
 
            By default this is false.
         
        .PARAMETER ipAddress
            This specifies the IP address of the VM in CIDR notation eg. (10.1.8.5/26)
            This is a required parameter
        .PARAMETER core
            Boolean value that specifies if the server should be deployed as a windows core server.
        .PARAMETER vmName
            String value that specifies the name for the VM
        .PARAMETER nonvSAN
            Boolean value that specifies if the VM ashould be deployed on the fixed host vs the vSAN cluster.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Boolean]
        $addDomain = $false,
        # Parameter help description
        [Parameter(Mandatory = $true)]
        [string]
        $ipAddress,
        # Parameter help description
        [Parameter(Mandatory = $true)]
        [System.Boolean]
        $core = $true,
        # Parameter help description
        [Parameter(Mandatory = $true)]
        [string]
        $vmName,
        # Parameter help description
        [Parameter()]
        [System.Boolean]
        $nonvSAN = $false
    )

    if ($nonvSAN -eq $true) {        
        $vmHost = Get-Cluster -Name $site-FixedHosts | Get-VMHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-Random
        $datastore = Get-Datacenter -VMHost $vmHost | where-object { $_.Name -match "Fixed" }
    }
    elseif ($nonvSAN -eq $false) {
        $vmHost = Get-Cluster -Name $site-vSAN | Get-VMHost | Where-Object { $_.ConnectionState -eq "Connected" } | Get-Random
        $datastore = Get-Datacenter -Name $site-vSAN-Data
    }

    if ($core -eq $true) {
        Import-vApp –Source $global:ovas.winsrv22core -Location $vmHost -Datastore $datastore -Name $vmName -Force
    }
    else {
        Import-vApp –Source $global:ovas.winsrv22 -Location $vmHost -Datastore $datastore -Name $vmName -Force
    }
}
Function New-SDDCConfig {

    #Install roles required for Active Directory
    Install-windowsfeature -Name AD-Domain-Services -IncludeManagementTools

    #reboot sercver to complete install of roles
    Restart-Computer -Force

    #Wait For Server to come back
    Get-SDRebootStatus -VM $vmName

    #Get VM object from vmName
    $vm = Get-VM -Name $vmName

    #Create new Disk for AD 120GB
    New-SDNVMeDrive -vmName $vmName -Size 120

    #Format disk function
    Format-SDDisk -vmName $vmName -label "ADDS"

    #Promote the Domain Controller
    Invoke-Command {
        Install-ADDSDomainController -DomainName $domainName -Credential (Get-Credential) `
            -InstallDNS:$true -SysvolPath E:\SYSVOL -LogPath E:\LOGS -DatabasePath E:\AD_DB `
            -SafeModeAdministratorPassword $ADSAFEPASS -SiteName $site } -ComputerName "$vmName.$domainName"

    #Wait For Server to come back
    Get-SDRebootStatus -VM $vmName

    $osInfo = Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName "$vmName.$domainName"
    if ($osInfo.ProductType -eq 2) {
        Write-Host "Completed DC Deployment"
    }
    elseif ($osInfo.ProductType -eq 3) {
        Write-Host "Deployment Failed"
    }
    
    
}
Function New-SDDHCPConfig {

    #Install roles required for Active Directory
    Install-windowsfeature -Name DHCP-Server -IncludeManagementTools

    #reboot sercver to complete install of roles
    Restart-Computer -Force

    #Wait For Server to come back
    Get-SDRebootStatus -VM $vmName

    Add-DhcpServerInDC -DnsName $vmName.$domainName -IPAddress $ipAddress
}
Function Format-SDDisk {
    <#
        .DESCRIPTION
            This Function Finds the new DIsk with a RAW format and Initalizes it with the GPT patition style
            It will then format the disk to NTFS and assign the drive label based off the input from the parameter Label.
 
        .PARAMETER vmName
            This is the name of the VM that this function will execut against.
 
        .PARAMETER label
            This is the volume label that will apply to the new disk.
    #>


    [CmdletBinding()]
    param (
        # Name of the VM
        [Parameter()]
        [String]
        $vmName,
        # Label for the Volume
        [Parameter(Mandatory = $true)]
        [String]
        $label
    )

    Invoke-Command -ScriptBlock { 
        Get-Disk | Where-object -property partitionstyle -eq ‘raw’ | 
        Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -DriveLetter E -UseMaximumSize | 
        Format-Volume -FileSystem NTFS -NewFileSystemLabel $label -Confirm:$false
    } -ComputerName $vmName.$domainName
}
Function New-SDHRZN {
    <#
        .DESCRIPTION
            This Function configures Horizon on a Server and provisions it as either the first Server or a replica server.
        .PARAMETER replica
            This is a Boolean for determining if it is a replica. Optional Parameter default value is false
        .PARAMETER server
            Name of server to deploy horizon on.
         
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [System.Boolean]
        $replica = $false,
        # Server Name to deploy on
        [Parameter(Mandatory = $true)]
        [String]
        $server
    )

    #Sets the Server name with the domain name
    $fqdn = "$server.$domainName"

    #Execute FIPS Check on remote server and Create Deploy Directory
    Invoke-Command -ScriptBlock {
        #Check if FIPS is ENabled on System
        $fipsKey = (Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy\")
    
        if ($fipsKey.Enabled = 0) {
            #Enable FIPS Mode
            Set-ItemProperty -Path $fipsKey -Name "Enabled" -Value 1
        }

        New-Item -ItemType Directory -Path C:\Deploy
    } -ComputerName $fqdn


    $hrznExe = \StackDeploy\Software\Horizon-Server-$global:sdhrznversion.exe

    #Copy Installer to Remote Server
    Copy-Item $hrznExe -Destination "\\$server.$domainName\c$\Deploy\HRZN.exe"

    #Install Server based if it is first or a replica
    if ($replica -eq $false) {
        #Specifies it is standard Install
        $instanceType = 1

        #Installer Arguments
        $installerArgs = '/s /v' + '"/qn VDM_SERVER_INSTANCE_TYPE=' + `
            $instanceType + ' VDM_INITIAL_ADMIN_SID=' + $hrznADGroupSID + `
            ' VDM_IP_PROTOCOL_USAGE=IPv4 FWCHOICE=1 DEPLOYMENT_TYPE=GENERAL VDM_FIPS_ENABLED=1'
        #Start Installation on remote Host
        Invoke-Command -ScriptBlock { Start-Process C:\Deploy\HRZN.EXE -ArgumentList $installerArgs } -ComputerName $fqdn
    }
    elseif ($replica -eq $true) {
        #Specifies it is a Replica Install
        $instanceType = 2

        #Installer Arguments
        $installerArgs = '/s /v' + '"/qn VDM_SERVER_INSTANCE_TYPE=' + `
            $instanceType + ' VDM_INITIAL_ADMIN_SID=' + $hrznADGroupSID + `
            ' VDM_IP_PROTOCOL_USAGE=IPv4 FWCHOICE=1 DEPLOYMENT_TYPE=GENERAL VDM_FIPS_ENABLED=1 ADAM_PRIMARY_NAME=' + "$site-HRZN-001v.$domainName"
        #Start Installation on remote Host
        Invoke-Command -ScriptBlock { Start-Process C:\Deploy\HRZN.EXE -ArgumentList $installerArgs } -ComputerName $fqdn
    }
}
Function New-SDMECM {

    $MECMTemplate = (Get-Content 'C:\StackDeploy\Templates\MECM_PRI.ini')

    $MECMTemplate[4] = $MECMTemplate[4].Replace('$MECMKey', $MECMKey)
    $MECMTemplate[5] = $MECMTemplate[5].Replace('$site', $site)
    $MECMTemplate[6] = $MECMTemplate[6].Replace('$site', $site)
    $MECMTemplate[8] = $MECMTemplate[8].Replace('$fqdn', $fqdn)
    $MECMTemplate[14] = $MECMTemplate[14].Replace('$fqdn', $fqdn)
    $MECMTemplate[16] = $MECMTemplate[16].Replace('$fqdn', $fqdn)
    $MECMTemplate[21] = $MECMTemplate[21].Replace('$fqdn', $fqdn)
    $MECMTemplate[24] = $MECMTemplate[24].Replace('$casfqdn', $casfqdn)
    $MECMTemplate[25] = $MECMTemplate[25].Replace('$site', $site)

    $MECMTemplate | Out-File "C:\StackDeploy\Templates\$site-mecm.ini"

    $sqlInstaller = 'C:\deploy\SQL\setup.exe'
    $sqlArgs = '/ACTION=install /QS /INSTANCENAME=MSSQLSERVER /SUPPRESSPRIVACYSTATEMENTNOTICE' + `
        "/IACCEPTSQLSERVERLICENSETERMS /FEATURES=SQLENGINE /SQLSYSADMINACCOUNTS=$domainName\MECM_SQLAdmin /SQLCOLLATION=SQL_Latin1_General_CP1_CS_AS" + `
        "/SQLSVCACCOUNT=$domainName\$site.msa.mecmsql"

    #Install SQL
    Invoke-Command -ScriptBlock {
        Start-process $sqlInstaller -ArgumentList $sqlArgs -Wait
    } -ComputerName $fqdn

}


#EXPORT MODULE MEMBERS
Export-ModuleMember Get-SDRebootStatus
Export-ModuleMember New-SDVM
Export-ModuleMember New-SDDCConfig
Export-ModuleMember New-SDDHCPConfig
Export-ModuleMember Format-SDDisk
Export-ModuleMember New-SDHRZN