Private/New-CustomAzVm.ps1

function Global:New-CustomAzVm {
    [CmdletBinding()]
    <#
    .SYNOPSIS
        Creates a new Application Server, installs Business Central, sys-preps it and saves it as a Scale Set Source
    .DESCRIPTION
        ...
    #>

    param(        
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceGroupName,        
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceLocation,
        [Parameter(Mandatory = $true)]
        [string]
        $Name,        
        [Alias("VirtualNetworkName")]
        [Parameter(Mandatory = $true)]
        [string]
        $VNetName,
        [Parameter(Mandatory = $true)]
        [string]
        $VMName,
        [Parameter(Mandatory = $true)]
        [string]
        $VMImagePublisher,
        [Parameter(Mandatory = $true)]
        [string]
        $VMImageOffer,
        [Parameter(Mandatory = $true)]
        [string]
        $VMImageSku,
        [Parameter(Mandatory = $true)]
        [string]
        $VMSize,
        [Parameter(Mandatory = $true)]
        [PSCredential]
        $VMCredentials,
        [Parameter(Mandatory = $true)]
        [int]
        $VMDiskSizeInGb,
        [Parameter(Mandatory = $true)]
        [string]
        $VMStorageAccountType,
        [Parameter(Mandatory = $true)]
        [string]
        $VMDataDiskName,
        [Alias("NetworkInterfaceName")]
        [Parameter(Mandatory = $true)]
        [string]
        $NicName,
        [Alias("NetworkInterfacePrivateIP")]
        [Parameter(Mandatory = $false)]
        [string]
        $NicPrivateIP,
        [Parameter(Mandatory = $false)]
        [string]
        $SubnetName,
        [Alias("PublicIPName")]
        [Parameter(Mandatory = $false)]
        [string]
        $PipName,
        [Alias("PublicIPDomainNameLabel")]
        [Parameter(Mandatory = $false)]
        [string]
        $PipDnsLabel,
        [Parameter(Mandatory = $false)]
        [string]
        $KeyVaultName,
        [Parameter(Mandatory = $false)]
        [switch]
        $JoinDomain,
        [Parameter(Mandatory = $false)]
        [switch]
        $AsJob,
        [HashTable]
        $Tags
    )
    process {
        Write-CustomHost -Message "Creating VM $VMName..."
        $scriptBlock = {
            # Create Variables in Scope of ScriptBlock for all variables passed in ArgumentList
            $args[0].GetEnumerator() | ForEach-Object {
                if ($_.Key -ne "AsJob") {
                    New-Variable -Name $_.Key -Value $_.Value
                }
            }
            $VirtualMachine = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -ErrorAction SilentlyContinue
            if ($VirtualMachine) {
                Write-CustomHost -Message "VM $VMName already exists"
                $VirtualMachine
                return
            }
            #Write-CustomHost -Message "Creating VM $VMName..."
            $interfaceArguments = @{ }
            foreach ($param in (Get-Variable -Scope Local) | Where-Object { $_.Name -like "*net*" -or $_.Name -like 'Nic*' -or $_.Name -like 'Pip*' -or $_.Name -like 'Resource*' -or $_.Name -like 'Tags' }) {
                $interfaceArguments.Add($param.Name, $param.Value)            
            }
            # Copy arguments for NIC creation from parent call
            <#
            $NicArguments = @{ }
            foreach ($param in $PsBoundParameters.GetEnumerator() | Where-Object { $_.Key -like "*net*" -or $_.Key -like 'Nic*' -or $_.Key -like 'Pip*' -or $_.Key -like 'Resource*' -or $_.Key -like 'Tags' }) {
                $NicArguments.Add($param.Key, $param.Value)
            }
            #>

            $NIC = New-CustomAzNetworkInterface @interfaceArguments

            #Write-CustomHost -Message "Checking if VM $VMName already exists..."
            #$VirtualMachine = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -ErrorAction SilentlyContinue
            if (-not ($VirtualMachine)) {
                # Write-CustomHost -Message "Creating VM $VMName..."
                # Create new VM (as Application Server)
                $VirtualMachine = New-AzVMConfig -VMName $VMName -VMSize $VMSize -AssignIdentity:$SystemAssigned -Tags $Tags
                $VirtualMachine = Set-AzVMOperatingSystem -VM $VirtualMachine -Windows -ComputerName $VMName -Credential $VMCredentials -ProvisionVMAgent
                $VirtualMachine = Add-AzVMNetworkInterface -VM $VirtualMachine -Id $NIC.Id
                $VirtualMachine = Set-AzVMSourceImage -VM $VirtualMachine -PublisherName $VMImagePublisher -Offer $VMImageOffer -Skus $VMImageSku -Version latest
                $VirtualMachine = Add-AzVMDataDisk -VM $VirtualMachine -Name $VMDataDiskName -CreateOption "Empty" -DiskSizeInGB $VMDiskSizeInGb -StorageAccountType $VMStorageAccountType -Lun 0 

                #$AsJob = $true
                Write-CustomHost -Message "Deploying VM (as job = $AsJob)..."                
                if ($AsJob) {
                    $job = New-AzVM -ResourceGroupName $ResourceGroupName -Location $ResourceLocation -VM $VirtualMachine -AsJob
                }
                else {
                    $job = New-AzVM -ResourceGroupName $ResourceGroupName -Location $ResourceLocation -VM $VirtualMachine
                }                
                #$job = New-AzVM -ResourceGroupName $ResourceGroupName -Location $ResourceLocation -VM $VirtualMachine -AsJob:$AsJob -Verbose
                Write-CustomHost -Message "VM Deployed"

                if ($JoinDomain) {
                    if ($AsJob) {
                        Write-CustomHost -Message "Waiting for job before adding Extension..."
                        $job | Receive-Job -Wait | Out-Null
                    }
                    $domainJoinSettings = Get-DomainJoinExtensionSettings -KeyVaultName $keyVaultName
                    $domainJoinExtension = Set-AzVMExtension -ResourceGroupName $ResourceGroupName -Location $ResourceLocation -VMName $VMName `
                        -Publisher $domainJoinSettings.Publisher -Type $domainJoinSettings.Type  -TypeHandlerVersion $domainJoinSettings.TypeHandlerVersion `
                        -Name $domainJoinSettings.Name -Settings $domainJoinSettings.Settings -ProtectedSettings $domainJoinSettings.ProtectedSetting -AsJob:$AsJob
                    
                    #if ($VMImagePublisher -eq "MicrosoftSQLServer") {
                    # Write-CustomHost -Message "Adding SQL extension to VM... "
                    # #Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName | Set-AzVMSqlServerExtension -Name "SQLIaasExtension" -version "1.2" | Update-AzVM | Out-Null
                    # Set-AzVMSqlServerExtension -ResourceGroupName $ResourceGroupName -VMName $VMName -name "SQLIaasExtension" -version "1.2" -Location $ResourceLocation | Out-Null
                    #}
                }
                Write-CustomHost -Message "Returning output"
                Write-Output $job
            }
            else {
                Write-CustomHost -Message "VM $VMName already exists"
                $VirtualMachine
            }
        }
        # Get all parameters from within this function call and pass to actual ScriptBlock
        $params = Get-FunctionParameters $MyInvocation
        if ($AsJob) {            
            Start-Job -ScriptBlock $scriptBlock -InitializationScript { Import-Module SetupD365Environment -Force } -ArgumentList $params
        }
        else {
            Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $params
        }
    }
}