functions/Invoke-SetupLab.ps1

Function Invoke-SetupLab {
    [CmdletBinding(SupportsShouldProcess)]
    [Alias("Setup-Lab")]
    Param (
        [Parameter(HelpMessage = "The path to the configuration folder. Normally, you should run all commands from within the configuration folder.")]
        [ValidateNotNullOrEmpty()]
        [ValidateScript( { Test-Path $_ })]
        [String]$Path = ".",
        [Switch]$IgnorePendingReboot,
        [Parameter(HelpMessage = "Override any configuration specified time zone and use the local time zone on this computer.")]
        [Switch]$UseLocalTimeZone,
        [Parameter(HelpMessage = "Run the command but suppress all status messages.")]
        [Switch]$NoMessages
    )

    Write-Verbose "Starting $($MyInvocation.MyCommand)"

    $Path = Convert-Path $path
    $LabName = Split-Path $Path -Leaf
    $LabData = Import-PowerShellDataFile -Path $(Join-Path $Path -ChildPath *.psd1)
    $DSCResources = $LabData.NonNodeData.Lability.DSCResource
    if (-Not $DSCResources) {
        Write-Warning "Failed to find DSC Resource information. Are you in a directory with configuration data .psd1 file?"
        #bail out
        return
    }

    if (-Not $NoMessages) {

        Microsoft.PowerShell.Utility\Write-Host -ForegroundColor Green -Object @"
 
        This is the Setup-Lab script. This script will perform the following:
 
        * Run the configs to generate the required .mof files
        Note! - If there is an error creating the .mof files, the setup will fail.
 
        * Run the lab setup
        Note! If this is the first time you have run this, it can take several
        hours to download the ISO files and resources depending on the configuration.
        You may also see new drives being added and removed as the ISO is mounted
        and converted. This step should only happen the first time you run this
        command.
 
        ** Possible problem
        If the downloads finish but the script doesn't continue (pauses),
        press the Enter key once and it should continue
 
        *You will be able to wipe and rebuild this lab without needing to perform
        the downloads again.
"@

    }

    if ($UseLocalTimeZone) {
        #modifying this old code since it doesn't translate properly from some
        #non-US locations. (Issue #227)
        # $LocalTz = [System.TimeZone]::CurrentTimeZone.StandardName
        $LocalTz = (Get-TimeZone).ID
        Write-Verbose "Using local time zone $LocalTz"
        if ($LabData.AllNodes.count -gt 1) {
            if (-Not $NoMessages) {
                Microsoft.PowerShell.Utility\Write-Host "Overriding configured time zones to use $LocalTz" -ForegroundColor yellow
            }
            $nodes = $LabData.AllNodes.where( { $_.NodeName -ne "*" })
            foreach ($node in $nodes) {
                # $tz = $node.Lability_timezone
                $node.Lability_timeZone = $LocalTz
            }
        }
        else {
            if (-Not $NoMessages) {
                Microsoft.PowerShell.Utility\Write-Host "Updating AllNodes to $LocalTz" -ForegroundColor Yellow
            }
            $LabData.AllNodes.Lability_TimeZone = $LocalTz
        }
    } #use local timezone

    $LabData.AllNodes | Out-String | Write-Verbose

    Write-Verbose "Install DSC Resource modules specified in the .PSD1"

    If (-Not $NoMessages) {
        Microsoft.PowerShell.Utility\Write-Host -ForegroundColor Cyan -Object 'Installing required DSCResource modules from PSGallery'
        Microsoft.PowerShell.Utility\Write-Host -ForegroundColor Yellow -Object 'You may need to say "yes" to a Nuget Provider'
    }
    #force updating/installing nuget to bypass the prompt
    [void](Install-PackageProvider -Name nuget -Force -ForceBootstrap)

    Foreach ($DSCResource in $DSCResources) {
        #test if current version is installed otherwise update or install it
        $DSCMod = Get-Module -FullyQualifiedName @{ModuleName = $DSCResource.name; ModuleVersion = $DSCResource.RequiredVersion } -ListAvailable

        if ((-not $DSCMod ) -or ($DSCMod.version -ne $DSCResource.RequiredVersion)) {
            if (-Not $NoMessages) {
                Microsoft.PowerShell.Utility\Write-Host "install $($DSCResource.name) version $($DSCResource.RequiredVersion)" -ForegroundColor yellow
            }
            if ($PSCmdlet.ShouldProcess($DSCResource.name, "Install-Module")) {
                Install-Module -Name $DSCResource.Name -RequiredVersion $DSCResource.RequiredVersion
            }
        }
        elseif ($DSCMod.version -ne ($DSCResource.RequiredVersion -as [version])) {
            if (-not $NoMessages) {
                Microsoft.PowerShell.Utility\Write-Host "Update $($DSCMod.name) to version $($DSCResource.RequiredVersion)" -ForegroundColor cyan
            }
            if ($PSCmdlet.ShouldProcess($DSCResource.name, "Update-Module")) {
                Update-Module -Name $DSCResource.Name -RequiredVersion $DSCResource.RequiredVersion
            }
        }
        else {
            If (-Not $NoMessages) {
                Microsoft.PowerShell.Utility\Write-Host "$($DSCMod.name) [v$($DSCMod.version)] requires no updates." -ForegroundColor green
            }
        }
    }

    Write-Verbose "Run the config to generate the .mof files"
    If (-Not $NoMessages) {
        Microsoft.PowerShell.Utility\Write-Host -ForegroundColor Cyan -Object 'Build the .Mof files from the configs'
    }
    $VMConfig = Join-Path -Path $path -ChildPath 'VMConfiguration.ps1'
    if ($PSCmdlet.ShouldProcess($VMConfig)) {
        . $VMConfig
    }
    # Build the lab without a snapshot

    if (-Not $NoMessages) {
        Microsoft.PowerShell.Utility\Write-Host -ForegroundColor Cyan -Object "Building the lab environment for $LabName"
    }

    # Creates the lab environment without making a Hyper-V Snapshot
    $Password = ConvertTo-SecureString -String "$($LabData.AllNodes.LabPassword)" -AsPlainText -Force
    $startParams = @{
        ConfigurationData   = $LabData
        #Import-PowerShellDataFile -path (Join-Path -path $path -childpath "VMConfigurationData.psd1")
        Path                = $Path
        NoSnapshot          = $True
        Password            = $Password
        IgnorePendingReboot = $True
        WarningAction       = "SilentlyContinue"
        ErrorAction         = "stop"
    }

    Write-Verbose "Using these start parameters"
    Write-Verbose ($startParams | Out-String)
    if ($PSCmdlet.ShouldProcess($LabName, "Start-LabConfiguration")) {
        Try {
            Write-Verbose "Invoking Start-LabConfiguration"
            Lability\Start-LabConfiguration @startParams
        }
        Catch {
            Microsoft.PowerShell.Utility\Write-Host "Failed to start lab configuration." -foreground red
            throw $_
        }
        Write-Verbose "Disable secure boot for VM's"
        $VM = Hyper-V\Get-VM ( Lability\Get-LabVM -ConfigurationData "$path\*.psd1" ).Name
        Hyper-V\Set-VMFirmware -VM $vm -EnableSecureBoot Off -SecureBootTemplate MicrosoftUEFICertificateAuthority

        If (-Not $NoMessages) {

            Microsoft.PowerShell.Utility\Write-Host -ForegroundColor Green -Object @"
 
            Next Steps:
 
            When this task is complete, run:
            Run-Lab
 
            To enable Internet access for the VM's, run:
            Enable-Internet
 
            Run the following to validate when configurations have converged:
            Validate-Lab
 
            To stop the lab VM's:
            Shutdown-lab
 
            When the configurations have finished, you can checkpoint the VM's with:
            Snapshot-Lab
 
            To quickly rebuild the labs from the checkpoint, run:
            Refresh-Lab
 
            To destroy the lab to build again:
            Wipe-Lab
 
"@

        }

    } #should process

    Write-Verbose "Ending $($MyInvocation.MyCommand)"
}