зеркало из https://github.com/microsoft/MSLab.git
Merge branch 'dev' of https://github.com/microsoft/MSLab into dev
This commit is contained in:
Коммит
2a361898c9
|
@ -16,7 +16,7 @@ jobs:
|
|||
environment: release
|
||||
name: Bump version
|
||||
if: "!contains(github.event.head_commit.message, '[no release]')"
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
# needed to create a release
|
||||
contents: write
|
||||
|
@ -54,7 +54,7 @@ jobs:
|
|||
new-release:
|
||||
name: Create release
|
||||
if: "!contains(github.event.head_commit.message, '[no release]')"
|
||||
runs-on: self-hosted
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
# needed to create a release
|
||||
contents: write
|
||||
|
@ -69,7 +69,7 @@ jobs:
|
|||
SIGN_SCRIPT_URI: ${{ secrets.SIGN_SCRIPT_URI }}
|
||||
CLIENT_ID: ${{ secrets.CLIENT_ID }} # just to obfusctate it in the output
|
||||
run: |
|
||||
./build.ps1 -Version ${{ needs.new-version.outputs.new_tag }} -SignScripts $true -SignScriptUri $env:SIGN_SCRIPT_URI -ClientId $env:CLIENT_ID
|
||||
./build.ps1 -Version ${{ needs.new-version.outputs.new_tag }} -SignScripts $false -SignScriptUri $env:SIGN_SCRIPT_URI -ClientId $env:CLIENT_ID
|
||||
Move-Item ./Release.zip mslab_${{ needs.new-version.outputs.new_tag }}.zip
|
||||
- name: Create changelog
|
||||
id: changelog
|
||||
|
|
|
@ -0,0 +1,644 @@
|
|||
#region CreateUnattendFileVHD
|
||||
|
||||
#Create Unattend for VHD
|
||||
Function CreateUnattendFileVHD {
|
||||
param (
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Computername,
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$AdminPassword,
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Path,
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$TimeZone
|
||||
)
|
||||
|
||||
if ( Test-Path "$path\Unattend.xml" ) {
|
||||
Remove-Item "$Path\Unattend.xml"
|
||||
}
|
||||
$unattendFile = New-Item "$Path\Unattend.xml" -type File
|
||||
|
||||
$fileContent = @"
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<settings pass="offlineServicing">
|
||||
<component
|
||||
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
language="neutral"
|
||||
name="Microsoft-Windows-PartitionManager"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
versionScope="nonSxS"
|
||||
>
|
||||
<SanPolicy>1</SanPolicy>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ComputerName>$Computername</ComputerName>
|
||||
$oeminformation
|
||||
<RegisteredOwner>PFE</RegisteredOwner>
|
||||
<RegisteredOrganization>Contoso</RegisteredOrganization>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value>$AdminPassword</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||
<SkipUserOOBE>true</SkipUserOOBE>
|
||||
</OOBE>
|
||||
<TimeZone>$TimeZone</TimeZone>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
|
||||
"@
|
||||
|
||||
Set-Content -path $unattendFile -value $fileContent
|
||||
|
||||
#return the file object
|
||||
Return $unattendFile
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hydrate DC
|
||||
function Hydrate-DC {
|
||||
|
||||
param(
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]$DCName,
|
||||
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]$VhdPath,
|
||||
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]$VmPath,
|
||||
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]$SwitchName,
|
||||
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]$TimeZone,
|
||||
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]$DhcpScope,
|
||||
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]$AdminPassword)
|
||||
|
||||
WriteInfoHighlighted "Starting DC Hydration"
|
||||
$dcHydrationStartTime = Get-Date
|
||||
|
||||
#DCHP scope
|
||||
$ReverseDnsRecord = $DhcpScope -replace '^(\d+)\.(\d+)\.\d+\.(\d+)$','$3.$2.$1.in-addr.arpa'
|
||||
$DhcpScope = $DhcpScope.Substring(0,$DhcpScope.Length-1)
|
||||
|
||||
#If the switch does not already exist, then create a switch with the name $SwitchName
|
||||
if (-not [bool](Get-VMSwitch -Name $SwitchName -ErrorAction SilentlyContinue)) {
|
||||
WriteInfoHighlighted "`t Creating temp hydration switch $SwitchName"
|
||||
New-VMSwitch -SwitchType Private -Name $SwitchName
|
||||
}
|
||||
|
||||
#create VM DC
|
||||
WriteInfoHighlighted "`t Creating DC VM"
|
||||
if ($LabConfig.DCVMVersion){
|
||||
$DC=New-VM -Name $DCName -VHDPath $VhdPath -MemoryStartupBytes 2GB -path $VmPath -SwitchName $SwitchName -Generation 2 -Version $LabConfig.DCVMVersion
|
||||
}else{
|
||||
$DC=New-VM -Name $DCName -VHDPath $VhdPath -MemoryStartupBytes 2GB -path $VmPath -SwitchName $SwitchName -Generation 2
|
||||
}
|
||||
$DC | Set-VMProcessor -Count 2
|
||||
$DC | Set-VMMemory -DynamicMemoryEnabled $true -MinimumBytes 2GB
|
||||
if ($LabConfig.Secureboot -eq $False) {$DC | Set-VMFirmware -EnableSecureBoot Off}
|
||||
if ($DC.AutomaticCheckpointsEnabled -eq $True){
|
||||
$DC | Set-VM -AutomaticCheckpointsEnabled $False
|
||||
}
|
||||
if ($LabConfig.InstallSCVMM -eq "Yes"){
|
||||
#SCVMM 2022 requires 4GB of memory
|
||||
$DC | Set-VMMemory -StartupBytes 4GB -MinimumBytes 4GB
|
||||
}
|
||||
|
||||
#Apply Unattend to VM
|
||||
if ($VMVersion.Build -ge 17763){
|
||||
$oeminformation=@"
|
||||
<OEMInformation>
|
||||
<SupportProvider>MSLab</SupportProvider>
|
||||
<SupportURL>https://aka.ms/mslab</SupportURL>
|
||||
</OEMInformation>
|
||||
"@
|
||||
}else{
|
||||
$oeminformation=$null
|
||||
}
|
||||
|
||||
WriteInfoHighlighted "`t Applying Unattend and copying Powershell DSC Modules"
|
||||
if (Test-Path $mountdir){
|
||||
Remove-Item -Path $mountdir -Recurse -Force
|
||||
}
|
||||
if (Test-Path "$PSScriptRoot\Temp\unattend"){
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\unattend.xml"
|
||||
}
|
||||
$unattendfile=CreateUnattendFileVHD -Computername $DCName -AdminPassword $AdminPassword -path "$PSScriptRoot\temp\" -TimeZone $TimeZone
|
||||
New-item -type directory -Path $mountdir -force
|
||||
[System.Version]$VMVersion=(Get-WindowsImage -ImagePath $VHDPath -Index 1).Version
|
||||
Mount-WindowsImage -Path $mountdir -ImagePath $VHDPath -Index 1
|
||||
Use-WindowsUnattend -Path $mountdir -UnattendPath $unattendFile
|
||||
#&"$PSScriptRoot\Temp\dism\dism" /mount-image /imagefile:$VhdPath /index:1 /MountDir:$mountdir
|
||||
#&"$PSScriptRoot\Temp\dism\dism" /image:$mountdir /Apply-Unattend:$unattendfile
|
||||
New-item -type directory -Path "$mountdir\Windows\Panther" -force
|
||||
Copy-Item -Path $unattendfile -Destination "$mountdir\Windows\Panther\unattend.xml" -force
|
||||
Copy-Item -Path "$PSScriptRoot\Temp\DSC\*" -Destination "$mountdir\Program Files\WindowsPowerShell\Modules\" -Recurse -force
|
||||
WriteInfoHighlighted "`t Adding Hyper-V feature into DC"
|
||||
#Install Hyper-V feature
|
||||
Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V -Path "$mountdir"
|
||||
|
||||
#Create credentials for DSC
|
||||
|
||||
$username = "$($LabConfig.DomainNetbiosName)\Administrator"
|
||||
$password = $AdminPassword
|
||||
$secstr = New-Object -TypeName System.Security.SecureString
|
||||
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
|
||||
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
|
||||
|
||||
#Create DSC configuration
|
||||
configuration DCHydration
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[pscredential]$safemodeAdministratorCred,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[pscredential]$domainCred,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[pscredential]$NewADUserCred
|
||||
|
||||
)
|
||||
|
||||
Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion "6.3.0"
|
||||
Import-DscResource -ModuleName DnsServerDsc -ModuleVersion "3.0.0"
|
||||
Import-DSCResource -ModuleName NetworkingDSC -ModuleVersion "9.0.0"
|
||||
Import-DSCResource -ModuleName xDHCPServer -ModuleVersion "3.1.1"
|
||||
Import-DSCResource -ModuleName xPSDesiredStateConfiguration -ModuleVersion "9.1.0"
|
||||
Import-DSCResource -ModuleName xHyper-V -ModuleVersion "3.18.0"
|
||||
Import-DscResource -ModuleName PSDesiredStateConfiguration
|
||||
|
||||
Node $AllNodes.Where{$_.Role -eq "Parent DC"}.Nodename
|
||||
|
||||
{
|
||||
WindowsFeature ADDSInstall
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "AD-Domain-Services"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureGPMC
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "GPMC"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureADPowerShell
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-AD-PowerShell"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureADAdminCenter
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-AD-AdminCenter"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureADDSTools
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-ADDS-Tools"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature Hyper-V-PowerShell
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "Hyper-V-PowerShell"
|
||||
}
|
||||
|
||||
xVMSwitch VMSwitch
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "vSwitch"
|
||||
Type = "External"
|
||||
AllowManagementOS = $true
|
||||
NetAdapterName = "Ethernet"
|
||||
EnableEmbeddedTeaming = $true
|
||||
DependsOn = "[WindowsFeature]Hyper-V-PowerShell"
|
||||
}
|
||||
|
||||
ADDomain FirstDS
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
SafemodeAdministratorPassword = $safemodeAdministratorCred
|
||||
DomainNetbiosName = $node.DomainNetbiosName
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WaitForADDomain DscForestWait
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
}
|
||||
|
||||
ADOrganizationalUnit DefaultOU
|
||||
{
|
||||
Name = $Node.DefaultOUName
|
||||
Path = $Node.DomainDN
|
||||
ProtectedFromAccidentalDeletion = $true
|
||||
Description = 'Default OU for all user and computer accounts'
|
||||
Ensure = 'Present'
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
}
|
||||
|
||||
ADUser SQL_SA
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = "SQL_SA"
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADOrganizationalUnit]DefaultOU"
|
||||
Description = "SQL Service Account"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADUser SQL_Agent
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = "SQL_Agent"
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADOrganizationalUnit]DefaultOU"
|
||||
Description = "SQL Agent Account"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADUser Domain_Admin
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = $Node.DomainAdminName
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADOrganizationalUnit]DefaultOU"
|
||||
Description = "DomainAdmin"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADUser VMM_SA
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = "VMM_SA"
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADUser]Domain_Admin"
|
||||
Description = "VMM Service Account"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADGroup DomainAdmins
|
||||
{
|
||||
GroupName = "Domain Admins"
|
||||
DependsOn = "[ADUser]VMM_SA"
|
||||
MembersToInclude = "VMM_SA",$Node.DomainAdminName
|
||||
}
|
||||
|
||||
ADGroup SchemaAdmins
|
||||
{
|
||||
GroupName = "Schema Admins"
|
||||
GroupScope = "Universal"
|
||||
DependsOn = "[ADUser]VMM_SA"
|
||||
MembersToInclude = $Node.DomainAdminName
|
||||
}
|
||||
|
||||
ADGroup EntAdmins
|
||||
{
|
||||
GroupName = "Enterprise Admins"
|
||||
GroupScope = "Universal"
|
||||
DependsOn = "[ADUser]VMM_SA"
|
||||
MembersToInclude = $Node.DomainAdminName
|
||||
}
|
||||
|
||||
ADUser AdministratorNeverExpires
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
UserName = "Administrator"
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
IPaddress IP
|
||||
{
|
||||
IPAddress = ($DhcpScope+"1/24")
|
||||
AddressFamily = "IPv4"
|
||||
InterfaceAlias = "vEthernet (vSwitch)"
|
||||
DependsOn = "[xVMSwitch]VMSwitch"
|
||||
}
|
||||
|
||||
WindowsFeature DHCPServer
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "DHCP"
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
}
|
||||
|
||||
Service DHCPServer #since insider 17035 dhcpserver was not starting for some reason
|
||||
{
|
||||
Name = "DHCPServer"
|
||||
State = "Running"
|
||||
DependsOn = "[WindowsFeature]DHCPServer"
|
||||
}
|
||||
|
||||
WindowsFeature DHCPServerManagement
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-DHCP"
|
||||
DependsOn = "[WindowsFeature]DHCPServer"
|
||||
}
|
||||
|
||||
xDhcpServerScope ManagementScope
|
||||
{
|
||||
Ensure = 'Present'
|
||||
ScopeId = ($DhcpScope+"0")
|
||||
IPStartRange = ($DhcpScope+"10")
|
||||
IPEndRange = ($DhcpScope+"254")
|
||||
Name = 'ManagementScope'
|
||||
SubnetMask = '255.255.255.0'
|
||||
LeaseDuration = '00:08:00'
|
||||
State = 'Active'
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[Service]DHCPServer"
|
||||
}
|
||||
|
||||
# Setting scope gateway
|
||||
DhcpScopeOptionValue 'ScopeOptionGateway'
|
||||
{
|
||||
OptionId = 3
|
||||
Value = ($DhcpScope+"1")
|
||||
ScopeId = ($DhcpScope+"0")
|
||||
VendorClass = ''
|
||||
UserClass = ''
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[xDhcpServerScope]ManagementScope"
|
||||
}
|
||||
|
||||
# Setting scope DNS servers
|
||||
DhcpScopeOptionValue 'ScopeOptionDNS'
|
||||
{
|
||||
OptionId = 6
|
||||
Value = ($DhcpScope+"1")
|
||||
ScopeId = ($DhcpScope+"0")
|
||||
VendorClass = ''
|
||||
UserClass = ''
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[xDhcpServerScope]ManagementScope"
|
||||
}
|
||||
|
||||
# Setting scope DNS domain name
|
||||
DhcpScopeOptionValue 'ScopeOptionDNSDomainName'
|
||||
{
|
||||
OptionId = 15
|
||||
Value = $Node.DomainName
|
||||
ScopeId = ($DhcpScope+"0")
|
||||
VendorClass = ''
|
||||
UserClass = ''
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[xDhcpServerScope]ManagementScope"
|
||||
}
|
||||
|
||||
xDhcpServerAuthorization LocalServerActivation
|
||||
{
|
||||
IsSingleInstance = 'Yes'
|
||||
Ensure = 'Present'
|
||||
}
|
||||
|
||||
WindowsFeature DSCServiceFeature
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "DSC-Service"
|
||||
}
|
||||
|
||||
DnsServerADZone addReverseADZone
|
||||
{
|
||||
Name = $ReverseDnsRecord
|
||||
DynamicUpdate = "Secure"
|
||||
ReplicationScope = "Forest"
|
||||
Ensure = "Present"
|
||||
DependsOn = "[DhcpScopeOptionValue]ScopeOptionGateway"
|
||||
}
|
||||
|
||||
If ($LabConfig.PullServerDC){
|
||||
xDscWebService PSDSCPullServer
|
||||
{
|
||||
UseSecurityBestPractices = $false
|
||||
Ensure = "Present"
|
||||
EndpointName = "PSDSCPullServer"
|
||||
Port = 8080
|
||||
PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\PSDSCPullServer"
|
||||
CertificateThumbPrint = "AllowUnencryptedTraffic"
|
||||
ModulePath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules"
|
||||
ConfigurationPath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Configuration"
|
||||
State = "Started"
|
||||
DependsOn = "[WindowsFeature]DSCServiceFeature"
|
||||
}
|
||||
|
||||
File RegistrationKeyFile
|
||||
{
|
||||
Ensure = 'Present'
|
||||
Type = 'File'
|
||||
DestinationPath = "$env:ProgramFiles\WindowsPowerShell\DscService\RegistrationKeys.txt"
|
||||
Contents = $Node.RegistrationKey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ConfigData = @{
|
||||
|
||||
AllNodes = @(
|
||||
@{
|
||||
Nodename = $DCName
|
||||
Role = "Parent DC"
|
||||
DomainAdminName=$LabConfig.DomainAdminName
|
||||
DomainName = $LabConfig.DomainName
|
||||
DomainNetbiosName = $LabConfig.DomainNetbiosName
|
||||
DomainDN = $LabConfig.DN
|
||||
DefaultOUName=$LabConfig.DefaultOUName
|
||||
RegistrationKey='14fc8e72-5036-4e79-9f89-5382160053aa'
|
||||
PSDscAllowPlainTextPassword = $true
|
||||
PsDscAllowDomainUser= $true
|
||||
RetryCount = 50
|
||||
RetryIntervalSec = 30
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#create LCM config
|
||||
[DSCLocalConfigurationManager()]
|
||||
configuration LCMConfig
|
||||
{
|
||||
Node DC
|
||||
{
|
||||
Settings
|
||||
{
|
||||
RebootNodeIfNeeded = $true
|
||||
ActionAfterReboot = 'ContinueConfiguration'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#create DSC MOF files
|
||||
WriteInfoHighlighted "`t Creating DSC Configs for DC"
|
||||
LCMConfig -OutputPath "$PSScriptRoot\Temp\config" -ConfigurationData $ConfigData
|
||||
DCHydration -OutputPath "$PSScriptRoot\Temp\config" -ConfigurationData $ConfigData -safemodeAdministratorCred $cred -domainCred $cred -NewADUserCred $cred
|
||||
|
||||
#copy DSC MOF files to DC
|
||||
WriteInfoHighlighted "`t Copying DSC configurations (pending.mof and metaconfig.mof)"
|
||||
New-item -type directory -Path "$PSScriptRoot\Temp\config" -ErrorAction Ignore
|
||||
Copy-Item -path "$PSScriptRoot\Temp\config\dc.mof" -Destination "$mountdir\Windows\system32\Configuration\pending.mof"
|
||||
Copy-Item -Path "$PSScriptRoot\Temp\config\dc.meta.mof" -Destination "$mountdir\Windows\system32\Configuration\metaconfig.mof"
|
||||
|
||||
#close VHD and apply changes
|
||||
WriteInfoHighlighted "`t Applying changes to VHD"
|
||||
Dismount-WindowsImage -Path $mountdir -Save
|
||||
#&"$PSScriptRoot\Temp\dism\dism" /Unmount-Image /MountDir:$mountdir /Commit
|
||||
|
||||
#Start DC VM and wait for configuration
|
||||
WriteInfoHighlighted "`t Starting DC"
|
||||
$DC | Start-VM
|
||||
|
||||
$VMStartupTime = 250
|
||||
WriteInfoHighlighted "`t Configuring DC using DSC takes a while."
|
||||
WriteInfo "`t `t Initial configuration in progress. Sleeping $VMStartupTime seconds"
|
||||
Start-Sleep $VMStartupTime
|
||||
$i=1
|
||||
do{
|
||||
$test=Invoke-Command -VMGuid $DC.id -ScriptBlock {Get-DscConfigurationStatus} -Credential $cred -ErrorAction SilentlyContinue
|
||||
if ($test -eq $null) {
|
||||
WriteInfo "`t `t Configuration in Progress. Sleeping 10 seconds"
|
||||
Start-Sleep 10
|
||||
}elseif ($test.status -ne "Success" -and $i -eq 1) {
|
||||
WriteInfo "`t `t Current DSC state: $($test.status), ResourncesNotInDesiredState: $($test.resourcesNotInDesiredState.count), ResourncesInDesiredState: $($test.resourcesInDesiredState.count)."
|
||||
WriteInfoHighlighted "`t `t Invoking DSC Configuration again"
|
||||
Invoke-Command -VMGuid $DC.id -ScriptBlock {Start-DscConfiguration -UseExisting} -Credential $cred
|
||||
$i++
|
||||
}elseif ($test.status -ne "Success" -and $i -gt 1) {
|
||||
WriteInfo "`t `t Current DSC state: $($test.status), ResourncesNotInDesiredState: $($test.resourcesNotInDesiredState.count), ResourncesInDesiredState: $($test.resourcesInDesiredState.count)."
|
||||
WriteInfoHighlighted "`t `t Restarting DC"
|
||||
Invoke-Command -VMGuid $DC.id -ScriptBlock {Restart-Computer} -Credential $cred
|
||||
}elseif ($test.status -eq "Success" ) {
|
||||
WriteInfo "`t `t Current DSC state: $($test.status), ResourncesNotInDesiredState: $($test.resourcesNotInDesiredState.count), ResourncesInDesiredState: $($test.resourcesInDesiredState.count)."
|
||||
WriteInfoHighlighted "`t `t DSC Configured DC Successfully"
|
||||
}
|
||||
}until ($test.Status -eq 'Success' -and $test.rebootrequested -eq $false)
|
||||
$test
|
||||
|
||||
#configure default OU where new Machines will be created using redircmp and add reverse lookup zone (as setting reverse lookup does not work with DSC)
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ErrorAction SilentlyContinue -ArgumentList $LabConfig -ScriptBlock {
|
||||
Param($LabConfig);
|
||||
redircmp "OU=$($LabConfig.DefaultOUName),$($LabConfig.DN)"
|
||||
Add-DnsServerPrimaryZone -NetworkID ($DhcpScope+"/24") -ReplicationScope "Forest"
|
||||
}
|
||||
#install SCVMM or its prereqs if specified so
|
||||
if (($LabConfig.InstallSCVMM -eq "Yes") -or ($LabConfig.InstallSCVMM -eq "SQL") -or ($LabConfig.InstallSCVMM -eq "ADK") -or ($LabConfig.InstallSCVMM -eq "Prereqs")){
|
||||
$DC | Add-VMHardDiskDrive -Path $toolsVHD.Path
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "Yes"){
|
||||
WriteInfoHighlighted "Installing System Center Virtual Machine Manager and its prerequisites"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\1_SQL_Install.ps1
|
||||
d:\scvmm\2_ADK_Install.ps1
|
||||
#install prereqs
|
||||
if (Test-Path "D:\SCVMM\SCVMM\Prerequisites\VCRedist\amd64\vcredist_x64.exe"){
|
||||
Start-Process -FilePath "D:\SCVMM\SCVMM\Prerequisites\VCRedist\amd64\vcredist_x64.exe" -ArgumentList "/passive /quiet /norestart" -Wait
|
||||
}
|
||||
Restart-Computer
|
||||
}
|
||||
Start-Sleep 10
|
||||
|
||||
WriteInfoHighlighted "$($DC.name) was restarted, waiting for Active Directory on $($DC.name) to be started."
|
||||
do{
|
||||
$test=Invoke-Command -VMGuid $DC.id -Credential $cred -ArgumentList $LabConfig -ErrorAction SilentlyContinue -ScriptBlock {
|
||||
param($LabConfig);
|
||||
Get-ADComputer -Filter * -SearchBase "$($LabConfig.DN)" -ErrorAction SilentlyContinue}
|
||||
Start-Sleep 5
|
||||
}
|
||||
until ($test -ne $Null)
|
||||
WriteSuccess "Active Directory on $($DC.name) is up."
|
||||
|
||||
Start-Sleep 30 #Wait as sometimes VMM failed to install without this.
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\3_SCVMM_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "SQL"){
|
||||
WriteInfoHighlighted "Installing SQL"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\1_SQL_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "ADK"){
|
||||
WriteInfoHighlighted "Installing ADK"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\2_ADK_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "Prereqs"){
|
||||
WriteInfoHighlighted "Installing System Center VMM Prereqs"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\1_SQL_Install.ps1
|
||||
d:\scvmm\2_ADK_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if (($LabConfig.InstallSCVMM -eq "Yes") -or ($LabConfig.InstallSCVMM -eq "SQL") -or ($LabConfig.InstallSCVMM -eq "ADK") -or ($LabConfig.InstallSCVMM -eq "Prereqs")){
|
||||
$DC | Get-VMHardDiskDrive | Where-Object path -eq $toolsVHD.Path | Remove-VMHardDiskDrive
|
||||
}
|
||||
|
||||
WriteInfo "`t Disconnecting VMNetwork Adapter from DC"
|
||||
$DC | Get-VMNetworkAdapter | Disconnect-VMNetworkAdapter
|
||||
|
||||
$dcHydrationEndTime = Get-Date
|
||||
}
|
||||
#endregion
|
|
@ -178,7 +178,7 @@ function Get-WindowsBuildNumber {
|
|||
$downloadurl = $webcontent.BaseResponse.ResponseUri.AbsoluteUri.Substring(0,$webcontent.BaseResponse.ResponseUri.AbsoluteUri.LastIndexOf('/'))+($webcontent.Links | where-object { $_.'data-url' -match '/Diskspd.*zip$' }|Select-Object -ExpandProperty "data-url")
|
||||
}
|
||||
#>
|
||||
$downloadurl="https://github.com/microsoft/diskspd/releases/download/v2.1/DiskSpd.ZIP"
|
||||
$downloadurl="https://github.com/microsoft/diskspd/releases/download/v2.2/DiskSpd.ZIP"
|
||||
Invoke-WebRequest -Uri $downloadurl -OutFile "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\diskspd.zip"
|
||||
}catch{
|
||||
WriteError "`t Failed to download Diskspd!"
|
||||
|
|
|
@ -14,79 +14,7 @@ If (-not $isAdmin) {
|
|||
|
||||
#region Functions
|
||||
. $PSScriptRoot\0_Shared.ps1 # [!build-include-inline]
|
||||
|
||||
#Create Unattend for VHD
|
||||
Function CreateUnattendFileVHD {
|
||||
param (
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Computername,
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$AdminPassword,
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Path,
|
||||
[parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$TimeZone
|
||||
)
|
||||
|
||||
if ( Test-Path "$path\Unattend.xml" ) {
|
||||
Remove-Item "$Path\Unattend.xml"
|
||||
}
|
||||
$unattendFile = New-Item "$Path\Unattend.xml" -type File
|
||||
|
||||
$fileContent = @"
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<settings pass="offlineServicing">
|
||||
<component
|
||||
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
language="neutral"
|
||||
name="Microsoft-Windows-PartitionManager"
|
||||
processorArchitecture="amd64"
|
||||
publicKeyToken="31bf3856ad364e35"
|
||||
versionScope="nonSxS"
|
||||
>
|
||||
<SanPolicy>1</SanPolicy>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ComputerName>$Computername</ComputerName>
|
||||
$oeminformation
|
||||
<RegisteredOwner>PFE</RegisteredOwner>
|
||||
<RegisteredOrganization>Contoso</RegisteredOrganization>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value>$AdminPassword</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||
<SkipUserOOBE>true</SkipUserOOBE>
|
||||
</OOBE>
|
||||
<TimeZone>$TimeZone</TimeZone>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
|
||||
"@
|
||||
|
||||
Set-Content -path $unattendFile -value $fileContent
|
||||
|
||||
#return the file object
|
||||
Return $unattendFile
|
||||
}
|
||||
. $PSScriptRoot\0_DCHydrate.ps1 # [!build-include-inline]
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -155,11 +83,6 @@ If (-not $isAdmin) {
|
|||
#Grab Installation type
|
||||
$WindowsInstallationType=Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\' -Name InstallationType
|
||||
|
||||
#DCHP scope
|
||||
$DHCPscope = $LabConfig.DHCPscope
|
||||
$ReverseDNSrecord = $DHCPscope -replace '^(\d+)\.(\d+)\.\d+\.(\d+)$','$3.$2.$1.in-addr.arpa'
|
||||
$DHCPscope = $DHCPscope.Substring(0,$DHCPscope.Length-1)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Check prerequisites
|
||||
|
@ -571,575 +494,55 @@ If (-not $isAdmin) {
|
|||
$vhdStatusInfo[$toolsVhdStatus.Kind] = $toolsVhdStatus
|
||||
#endregion
|
||||
|
||||
#region Hydrate DC
|
||||
if (-not $DCFilesExists){
|
||||
WriteInfoHighlighted "Starting DC Hydration"
|
||||
$dcHydrationStartTime = Get-Date
|
||||
#region Create DC VHD
|
||||
if (-not $DCFilesExists){
|
||||
$vhdpath="$PSScriptRoot\LAB\$DCName\Virtual Hard Disks\$DCName.vhdx"
|
||||
$VMPath="$PSScriptRoot\LAB\"
|
||||
|
||||
$vhdpath="$PSScriptRoot\LAB\$DCName\Virtual Hard Disks\$DCName.vhdx"
|
||||
$VMPath="$PSScriptRoot\LAB\"
|
||||
#reuse VHD if already created
|
||||
$DCVHDName=($ServerVHDs | Where-Object Edition -eq $LabConfig.DCEdition).VHDName
|
||||
if ((($DCVHDName) -ne $null) -and (Test-Path -Path "$PSScriptRoot\ParentDisks\$DCVHDName")){
|
||||
WriteSuccess "`t $DCVHDName found, reusing, and copying to $vhdpath"
|
||||
New-Item -Path "$VMPath\$DCName" -Name "Virtual Hard Disks" -ItemType Directory
|
||||
Copy-Item -Path "$PSScriptRoot\ParentDisks\$DCVHDName" -Destination $vhdpath
|
||||
}else{
|
||||
#Create Parent VHD
|
||||
WriteInfoHighlighted "`t Creating VHD for DC"
|
||||
if ($packages){
|
||||
Convert-WindowsImage -SourcePath "$($ServerMediaDriveLetter):\sources\install.wim" -Edition $LabConfig.DCEdition -VHDPath $vhdpath -SizeBytes 60GB -VHDFormat VHDX -DiskLayout UEFI -package $packages
|
||||
}else{
|
||||
Convert-WindowsImage -SourcePath "$($ServerMediaDriveLetter):\sources\install.wim" -Edition $LabConfig.DCEdition -VHDPath $vhdpath -SizeBytes 60GB -VHDFormat VHDX -DiskLayout UEFI
|
||||
}
|
||||
}
|
||||
|
||||
#reuse VHD if already created
|
||||
$DCVHDName=($ServerVHDs | Where-Object Edition -eq $LabConfig.DCEdition).VHDName
|
||||
if ((($DCVHDName) -ne $null) -and (Test-Path -Path "$PSScriptRoot\ParentDisks\$DCVHDName")){
|
||||
WriteSuccess "`t $DCVHDName found, reusing, and copying to $vhdpath"
|
||||
New-Item -Path "$VMPath\$DCName" -Name "Virtual Hard Disks" -ItemType Directory
|
||||
Copy-Item -Path "$PSScriptRoot\ParentDisks\$DCVHDName" -Destination $vhdpath
|
||||
}else{
|
||||
#Create Parent VHD
|
||||
WriteInfoHighlighted "`t Creating VHD for DC"
|
||||
if ($packages){
|
||||
Convert-WindowsImage -SourcePath "$($ServerMediaDriveLetter):\sources\install.wim" -Edition $LabConfig.DCEdition -VHDPath $vhdpath -SizeBytes 60GB -VHDFormat VHDX -DiskLayout UEFI -package $packages
|
||||
}else{
|
||||
Convert-WindowsImage -SourcePath "$($ServerMediaDriveLetter):\sources\install.wim" -Edition $LabConfig.DCEdition -VHDPath $vhdpath -SizeBytes 60GB -VHDFormat VHDX -DiskLayout UEFI
|
||||
}
|
||||
#Get VM Version
|
||||
[System.Version]$VMVersion=(Get-WindowsImage -ImagePath $VHDPath -Index 1).Version
|
||||
WriteInfo "`t VM Version is $($VMVersion.Build).$($VMVersion.Revision)"
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region create DC if it does not exist
|
||||
if (-not $DCFilesExists) {
|
||||
if (-not $LabConfig.NoDehydrateDC){
|
||||
Hydrate-DC -DCName $DCName -VhdPath $vhdpath -VmPath $VmPath -SwitchName $Switchname -TimeZone $TimeZone -DhcpScope $LabConfig.DHCPscope -AdminPassword $AdminPassword
|
||||
$DC=Get-VM -Name $DCName
|
||||
if ($DC -eq $null){
|
||||
WriteErrorAndExit "DC was not created successfully Press any key to continue ..."
|
||||
} else {
|
||||
WriteInfo "`t`t Virtual Machine $($DC.name) located in folder $($DC.Path) hydrated"
|
||||
}
|
||||
|
||||
#Get VM Version
|
||||
[System.Version]$VMVersion=(Get-WindowsImage -ImagePath $VHDPath -Index 1).Version
|
||||
WriteInfo "`t VM Version is $($VMVersion.Build).$($VMVersion.Revision)"
|
||||
|
||||
#If the switch does not already exist, then create a switch with the name $SwitchName
|
||||
if (-not [bool](Get-VMSwitch -Name $Switchname -ErrorAction SilentlyContinue)) {
|
||||
WriteInfoHighlighted "`t Creating temp hydration switch $Switchname"
|
||||
New-VMSwitch -SwitchType Private -Name $Switchname
|
||||
}
|
||||
|
||||
#create VM DC
|
||||
WriteInfoHighlighted "`t Creating DC VM"
|
||||
if ($LabConfig.DCVMVersion){
|
||||
$DC=New-VM -Name $DCName -VHDPath $vhdpath -MemoryStartupBytes 2GB -path $vmpath -SwitchName $Switchname -Generation 2 -Version $LabConfig.DCVMVersion
|
||||
}else{
|
||||
$DC=New-VM -Name $DCName -VHDPath $vhdpath -MemoryStartupBytes 2GB -path $vmpath -SwitchName $Switchname -Generation 2
|
||||
}
|
||||
$DC | Set-VMProcessor -Count 2
|
||||
$DC | Set-VMMemory -DynamicMemoryEnabled $true -MinimumBytes 2GB
|
||||
if ($LabConfig.Secureboot -eq $False) {$DC | Set-VMFirmware -EnableSecureBoot Off}
|
||||
if ($DC.AutomaticCheckpointsEnabled -eq $True){
|
||||
$DC | Set-VM -AutomaticCheckpointsEnabled $False
|
||||
}
|
||||
if ($LabConfig.InstallSCVMM -eq "Yes"){
|
||||
#SCVMM 2022 requires 4GB of memory
|
||||
$DC | Set-VMMemory -StartupBytes 4GB -MinimumBytes 4GB
|
||||
}
|
||||
|
||||
#Apply Unattend to VM
|
||||
if ($VMVersion.Build -ge 17763){
|
||||
$oeminformation=@"
|
||||
<OEMInformation>
|
||||
<SupportProvider>MSLab</SupportProvider>
|
||||
<SupportURL>https://aka.ms/mslab</SupportURL>
|
||||
</OEMInformation>
|
||||
"@
|
||||
}else{
|
||||
$oeminformation=$null
|
||||
}
|
||||
|
||||
WriteInfoHighlighted "`t Applying Unattend and copying Powershell DSC Modules"
|
||||
if (Test-Path $mountdir){
|
||||
Remove-Item -Path $mountdir -Recurse -Force
|
||||
}
|
||||
if (Test-Path "$PSScriptRoot\Temp\unattend"){
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\unattend.xml"
|
||||
}
|
||||
$unattendfile=CreateUnattendFileVHD -Computername $DCName -AdminPassword $AdminPassword -path "$PSScriptRoot\temp\" -TimeZone $TimeZone
|
||||
New-item -type directory -Path $mountdir -force
|
||||
[System.Version]$VMVersion=(Get-WindowsImage -ImagePath $VHDPath -Index 1).Version
|
||||
Mount-WindowsImage -Path $mountdir -ImagePath $VHDPath -Index 1
|
||||
Use-WindowsUnattend -Path $mountdir -UnattendPath $unattendFile
|
||||
#&"$PSScriptRoot\Temp\dism\dism" /mount-image /imagefile:$vhdpath /index:1 /MountDir:$mountdir
|
||||
#&"$PSScriptRoot\Temp\dism\dism" /image:$mountdir /Apply-Unattend:$unattendfile
|
||||
New-item -type directory -Path "$mountdir\Windows\Panther" -force
|
||||
Copy-Item -Path $unattendfile -Destination "$mountdir\Windows\Panther\unattend.xml" -force
|
||||
Copy-Item -Path "$PSScriptRoot\Temp\DSC\*" -Destination "$mountdir\Program Files\WindowsPowerShell\Modules\" -Recurse -force
|
||||
WriteInfoHighlighted "`t Adding Hyper-V feature into DC"
|
||||
#Install Hyper-V feature
|
||||
Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V -Path "$mountdir"
|
||||
|
||||
#Create credentials for DSC
|
||||
|
||||
$username = "$($LabConfig.DomainNetbiosName)\Administrator"
|
||||
$password = $AdminPassword
|
||||
$secstr = New-Object -TypeName System.Security.SecureString
|
||||
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
|
||||
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
|
||||
|
||||
#Create DSC configuration
|
||||
configuration DCHydration
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
[pscredential]$safemodeAdministratorCred,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[pscredential]$domainCred,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[pscredential]$NewADUserCred
|
||||
|
||||
)
|
||||
|
||||
Import-DscResource -ModuleName ActiveDirectoryDsc -ModuleVersion "6.3.0"
|
||||
Import-DscResource -ModuleName DnsServerDsc -ModuleVersion "3.0.0"
|
||||
Import-DSCResource -ModuleName NetworkingDSC -ModuleVersion "9.0.0"
|
||||
Import-DSCResource -ModuleName xDHCPServer -ModuleVersion "3.1.1"
|
||||
Import-DSCResource -ModuleName xPSDesiredStateConfiguration -ModuleVersion "9.1.0"
|
||||
Import-DSCResource -ModuleName xHyper-V -ModuleVersion "3.18.0"
|
||||
Import-DscResource -ModuleName PSDesiredStateConfiguration
|
||||
|
||||
Node $AllNodes.Where{$_.Role -eq "Parent DC"}.Nodename
|
||||
|
||||
{
|
||||
WindowsFeature ADDSInstall
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "AD-Domain-Services"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureGPMC
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "GPMC"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureADPowerShell
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-AD-PowerShell"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureADAdminCenter
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-AD-AdminCenter"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature FeatureADDSTools
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-ADDS-Tools"
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WindowsFeature Hyper-V-PowerShell
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "Hyper-V-PowerShell"
|
||||
}
|
||||
|
||||
xVMSwitch VMSwitch
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "vSwitch"
|
||||
Type = "External"
|
||||
AllowManagementOS = $true
|
||||
NetAdapterName = "Ethernet"
|
||||
EnableEmbeddedTeaming = $true
|
||||
DependsOn = "[WindowsFeature]Hyper-V-PowerShell"
|
||||
}
|
||||
|
||||
ADDomain FirstDS
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
SafemodeAdministratorPassword = $safemodeAdministratorCred
|
||||
DomainNetbiosName = $node.DomainNetbiosName
|
||||
DependsOn = "[WindowsFeature]ADDSInstall"
|
||||
}
|
||||
|
||||
WaitForADDomain DscForestWait
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
}
|
||||
|
||||
ADOrganizationalUnit DefaultOU
|
||||
{
|
||||
Name = $Node.DefaultOUName
|
||||
Path = $Node.DomainDN
|
||||
ProtectedFromAccidentalDeletion = $true
|
||||
Description = 'Default OU for all user and computer accounts'
|
||||
Ensure = 'Present'
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
}
|
||||
|
||||
ADUser SQL_SA
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = "SQL_SA"
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADOrganizationalUnit]DefaultOU"
|
||||
Description = "SQL Service Account"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADUser SQL_Agent
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = "SQL_Agent"
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADOrganizationalUnit]DefaultOU"
|
||||
Description = "SQL Agent Account"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADUser Domain_Admin
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = $Node.DomainAdminName
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADOrganizationalUnit]DefaultOU"
|
||||
Description = "DomainAdmin"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADUser VMM_SA
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
Credential = $domainCred
|
||||
UserName = "VMM_SA"
|
||||
Password = $NewADUserCred
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADUser]Domain_Admin"
|
||||
Description = "VMM Service Account"
|
||||
Path = "OU=$($Node.DefaultOUName),$($Node.DomainDN)"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
ADGroup DomainAdmins
|
||||
{
|
||||
GroupName = "Domain Admins"
|
||||
DependsOn = "[ADUser]VMM_SA"
|
||||
MembersToInclude = "VMM_SA",$Node.DomainAdminName
|
||||
}
|
||||
|
||||
ADGroup SchemaAdmins
|
||||
{
|
||||
GroupName = "Schema Admins"
|
||||
GroupScope = "Universal"
|
||||
DependsOn = "[ADUser]VMM_SA"
|
||||
MembersToInclude = $Node.DomainAdminName
|
||||
}
|
||||
|
||||
ADGroup EntAdmins
|
||||
{
|
||||
GroupName = "Enterprise Admins"
|
||||
GroupScope = "Universal"
|
||||
DependsOn = "[ADUser]VMM_SA"
|
||||
MembersToInclude = $Node.DomainAdminName
|
||||
}
|
||||
|
||||
ADUser AdministratorNeverExpires
|
||||
{
|
||||
DomainName = $Node.DomainName
|
||||
UserName = "Administrator"
|
||||
Ensure = "Present"
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
PasswordNeverExpires = $true
|
||||
}
|
||||
|
||||
IPaddress IP
|
||||
{
|
||||
IPAddress = ($DHCPscope+"1/24")
|
||||
AddressFamily = "IPv4"
|
||||
InterfaceAlias = "vEthernet (vSwitch)"
|
||||
DependsOn = "[xVMSwitch]VMSwitch"
|
||||
}
|
||||
|
||||
WindowsFeature DHCPServer
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "DHCP"
|
||||
DependsOn = "[ADDomain]FirstDS"
|
||||
}
|
||||
|
||||
Service DHCPServer #since insider 17035 dhcpserver was not starting for some reason
|
||||
{
|
||||
Name = "DHCPServer"
|
||||
State = "Running"
|
||||
DependsOn = "[WindowsFeature]DHCPServer"
|
||||
}
|
||||
|
||||
WindowsFeature DHCPServerManagement
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "RSAT-DHCP"
|
||||
DependsOn = "[WindowsFeature]DHCPServer"
|
||||
}
|
||||
|
||||
xDhcpServerScope ManagementScope
|
||||
{
|
||||
Ensure = 'Present'
|
||||
ScopeId = ($DHCPscope+"0")
|
||||
IPStartRange = ($DHCPscope+"10")
|
||||
IPEndRange = ($DHCPscope+"254")
|
||||
Name = 'ManagementScope'
|
||||
SubnetMask = '255.255.255.0'
|
||||
LeaseDuration = '00:08:00'
|
||||
State = 'Active'
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[Service]DHCPServer"
|
||||
}
|
||||
|
||||
# Setting scope gateway
|
||||
DhcpScopeOptionValue 'ScopeOptionGateway'
|
||||
{
|
||||
OptionId = 3
|
||||
Value = ($DHCPscope+"1")
|
||||
ScopeId = ($DHCPscope+"0")
|
||||
VendorClass = ''
|
||||
UserClass = ''
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[xDhcpServerScope]ManagementScope"
|
||||
}
|
||||
|
||||
# Setting scope DNS servers
|
||||
DhcpScopeOptionValue 'ScopeOptionDNS'
|
||||
{
|
||||
OptionId = 6
|
||||
Value = ($DHCPscope+"1")
|
||||
ScopeId = ($DHCPscope+"0")
|
||||
VendorClass = ''
|
||||
UserClass = ''
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[xDhcpServerScope]ManagementScope"
|
||||
}
|
||||
|
||||
# Setting scope DNS domain name
|
||||
DhcpScopeOptionValue 'ScopeOptionDNSDomainName'
|
||||
{
|
||||
OptionId = 15
|
||||
Value = $Node.DomainName
|
||||
ScopeId = ($DHCPscope+"0")
|
||||
VendorClass = ''
|
||||
UserClass = ''
|
||||
AddressFamily = 'IPv4'
|
||||
DependsOn = "[xDhcpServerScope]ManagementScope"
|
||||
}
|
||||
|
||||
xDhcpServerAuthorization LocalServerActivation
|
||||
{
|
||||
IsSingleInstance = 'Yes'
|
||||
Ensure = 'Present'
|
||||
}
|
||||
|
||||
WindowsFeature DSCServiceFeature
|
||||
{
|
||||
Ensure = "Present"
|
||||
Name = "DSC-Service"
|
||||
}
|
||||
|
||||
DnsServerADZone addReverseADZone
|
||||
{
|
||||
Name = $ReverseDNSrecord
|
||||
DynamicUpdate = "Secure"
|
||||
ReplicationScope = "Forest"
|
||||
Ensure = "Present"
|
||||
DependsOn = "[DhcpScopeOptionValue]ScopeOptionGateway"
|
||||
}
|
||||
|
||||
If ($LabConfig.PullServerDC){
|
||||
xDscWebService PSDSCPullServer
|
||||
{
|
||||
UseSecurityBestPractices = $false
|
||||
Ensure = "Present"
|
||||
EndpointName = "PSDSCPullServer"
|
||||
Port = 8080
|
||||
PhysicalPath = "$env:SystemDrive\inetpub\wwwroot\PSDSCPullServer"
|
||||
CertificateThumbPrint = "AllowUnencryptedTraffic"
|
||||
ModulePath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules"
|
||||
ConfigurationPath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Configuration"
|
||||
State = "Started"
|
||||
DependsOn = "[WindowsFeature]DSCServiceFeature"
|
||||
}
|
||||
|
||||
File RegistrationKeyFile
|
||||
{
|
||||
Ensure = 'Present'
|
||||
Type = 'File'
|
||||
DestinationPath = "$env:ProgramFiles\WindowsPowerShell\DscService\RegistrationKeys.txt"
|
||||
Contents = $Node.RegistrationKey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ConfigData = @{
|
||||
|
||||
AllNodes = @(
|
||||
@{
|
||||
Nodename = $DCName
|
||||
Role = "Parent DC"
|
||||
DomainAdminName=$LabConfig.DomainAdminName
|
||||
DomainName = $LabConfig.DomainName
|
||||
DomainNetbiosName = $LabConfig.DomainNetbiosName
|
||||
DomainDN = $LabConfig.DN
|
||||
DefaultOUName=$LabConfig.DefaultOUName
|
||||
RegistrationKey='14fc8e72-5036-4e79-9f89-5382160053aa'
|
||||
PSDscAllowPlainTextPassword = $true
|
||||
PsDscAllowDomainUser= $true
|
||||
RetryCount = 50
|
||||
RetryIntervalSec = 30
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#create LCM config
|
||||
[DSCLocalConfigurationManager()]
|
||||
configuration LCMConfig
|
||||
{
|
||||
Node DC
|
||||
{
|
||||
Settings
|
||||
{
|
||||
RebootNodeIfNeeded = $true
|
||||
ActionAfterReboot = 'ContinueConfiguration'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#create DSC MOF files
|
||||
WriteInfoHighlighted "`t Creating DSC Configs for DC"
|
||||
LCMConfig -OutputPath "$PSScriptRoot\Temp\config" -ConfigurationData $ConfigData
|
||||
DCHydration -OutputPath "$PSScriptRoot\Temp\config" -ConfigurationData $ConfigData -safemodeAdministratorCred $cred -domainCred $cred -NewADUserCred $cred
|
||||
|
||||
#copy DSC MOF files to DC
|
||||
WriteInfoHighlighted "`t Copying DSC configurations (pending.mof and metaconfig.mof)"
|
||||
New-item -type directory -Path "$PSScriptRoot\Temp\config" -ErrorAction Ignore
|
||||
Copy-Item -path "$PSScriptRoot\Temp\config\dc.mof" -Destination "$mountdir\Windows\system32\Configuration\pending.mof"
|
||||
Copy-Item -Path "$PSScriptRoot\Temp\config\dc.meta.mof" -Destination "$mountdir\Windows\system32\Configuration\metaconfig.mof"
|
||||
|
||||
#close VHD and apply changes
|
||||
WriteInfoHighlighted "`t Applying changes to VHD"
|
||||
Dismount-WindowsImage -Path $mountdir -Save
|
||||
#&"$PSScriptRoot\Temp\dism\dism" /Unmount-Image /MountDir:$mountdir /Commit
|
||||
|
||||
#Start DC VM and wait for configuration
|
||||
WriteInfoHighlighted "`t Starting DC"
|
||||
$DC | Start-VM
|
||||
|
||||
$VMStartupTime = 250
|
||||
WriteInfoHighlighted "`t Configuring DC using DSC takes a while."
|
||||
WriteInfo "`t `t Initial configuration in progress. Sleeping $VMStartupTime seconds"
|
||||
Start-Sleep $VMStartupTime
|
||||
$i=1
|
||||
do{
|
||||
$test=Invoke-Command -VMGuid $DC.id -ScriptBlock {Get-DscConfigurationStatus} -Credential $cred -ErrorAction SilentlyContinue
|
||||
if ($test -eq $null) {
|
||||
WriteInfo "`t `t Configuration in Progress. Sleeping 10 seconds"
|
||||
Start-Sleep 10
|
||||
}elseif ($test.status -ne "Success" -and $i -eq 1) {
|
||||
WriteInfo "`t `t Current DSC state: $($test.status), ResourncesNotInDesiredState: $($test.resourcesNotInDesiredState.count), ResourncesInDesiredState: $($test.resourcesInDesiredState.count)."
|
||||
WriteInfoHighlighted "`t `t Invoking DSC Configuration again"
|
||||
Invoke-Command -VMGuid $DC.id -ScriptBlock {Start-DscConfiguration -UseExisting} -Credential $cred
|
||||
$i++
|
||||
}elseif ($test.status -ne "Success" -and $i -gt 1) {
|
||||
WriteInfo "`t `t Current DSC state: $($test.status), ResourncesNotInDesiredState: $($test.resourcesNotInDesiredState.count), ResourncesInDesiredState: $($test.resourcesInDesiredState.count)."
|
||||
WriteInfoHighlighted "`t `t Restarting DC"
|
||||
Invoke-Command -VMGuid $DC.id -ScriptBlock {Restart-Computer} -Credential $cred
|
||||
}elseif ($test.status -eq "Success" ) {
|
||||
WriteInfo "`t `t Current DSC state: $($test.status), ResourncesNotInDesiredState: $($test.resourcesNotInDesiredState.count), ResourncesInDesiredState: $($test.resourcesInDesiredState.count)."
|
||||
WriteInfoHighlighted "`t `t DSC Configured DC Successfully"
|
||||
}
|
||||
}until ($test.Status -eq 'Success' -and $test.rebootrequested -eq $false)
|
||||
$test
|
||||
|
||||
#configure default OU where new Machines will be created using redircmp and add reverse lookup zone (as setting reverse lookup does not work with DSC)
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ErrorAction SilentlyContinue -ArgumentList $LabConfig -ScriptBlock {
|
||||
Param($LabConfig);
|
||||
redircmp "OU=$($LabConfig.DefaultOUName),$($LabConfig.DN)"
|
||||
Add-DnsServerPrimaryZone -NetworkID ($DHCPscope+"/24") -ReplicationScope "Forest"
|
||||
}
|
||||
#install SCVMM or its prereqs if specified so
|
||||
if (($LabConfig.InstallSCVMM -eq "Yes") -or ($LabConfig.InstallSCVMM -eq "SQL") -or ($LabConfig.InstallSCVMM -eq "ADK") -or ($LabConfig.InstallSCVMM -eq "Prereqs")){
|
||||
$DC | Add-VMHardDiskDrive -Path $toolsVHD.Path
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "Yes"){
|
||||
WriteInfoHighlighted "Installing System Center Virtual Machine Manager and its prerequisites"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\1_SQL_Install.ps1
|
||||
d:\scvmm\2_ADK_Install.ps1
|
||||
#install prereqs
|
||||
if (Test-Path "D:\SCVMM\SCVMM\Prerequisites\VCRedist\amd64\vcredist_x64.exe"){
|
||||
Start-Process -FilePath "D:\SCVMM\SCVMM\Prerequisites\VCRedist\amd64\vcredist_x64.exe" -ArgumentList "/passive /quiet /norestart" -Wait
|
||||
}
|
||||
Restart-Computer
|
||||
}
|
||||
Start-Sleep 10
|
||||
|
||||
WriteInfoHighlighted "$($DC.name) was restarted, waiting for Active Directory on $($DC.name) to be started."
|
||||
do{
|
||||
$test=Invoke-Command -VMGuid $DC.id -Credential $cred -ArgumentList $LabConfig -ErrorAction SilentlyContinue -ScriptBlock {
|
||||
param($LabConfig);
|
||||
Get-ADComputer -Filter * -SearchBase "$($LabConfig.DN)" -ErrorAction SilentlyContinue}
|
||||
Start-Sleep 5
|
||||
}
|
||||
until ($test -ne $Null)
|
||||
WriteSuccess "Active Directory on $($DC.name) is up."
|
||||
|
||||
Start-Sleep 30 #Wait as sometimes VMM failed to install without this.
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\3_SCVMM_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "SQL"){
|
||||
WriteInfoHighlighted "Installing SQL"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\1_SQL_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "ADK"){
|
||||
WriteInfoHighlighted "Installing ADK"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\2_ADK_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "Prereqs"){
|
||||
WriteInfoHighlighted "Installing System Center VMM Prereqs"
|
||||
Invoke-Command -VMGuid $DC.id -Credential $cred -ScriptBlock {
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
d:\scvmm\1_SQL_Install.ps1
|
||||
d:\scvmm\2_ADK_Install.ps1
|
||||
}
|
||||
}
|
||||
|
||||
if (($LabConfig.InstallSCVMM -eq "Yes") -or ($LabConfig.InstallSCVMM -eq "SQL") -or ($LabConfig.InstallSCVMM -eq "ADK") -or ($LabConfig.InstallSCVMM -eq "Prereqs")){
|
||||
$DC | Get-VMHardDiskDrive | Where-Object path -eq $toolsVHD.Path | Remove-VMHardDiskDrive
|
||||
}
|
||||
|
||||
$dcHydrationEndTime = Get-Date
|
||||
} else {
|
||||
WriteInfoHighlighted "Skipping creation of dehydrated Domain Controller"
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region backup DC and cleanup
|
||||
#cleanup DC
|
||||
if (-not $DCFilesExists){
|
||||
if (-not $DCFilesExists -and -not $LabConfig.NoDehydrateDC){
|
||||
WriteInfoHighlighted "Backup DC and cleanup"
|
||||
#shutdown DC
|
||||
WriteInfo "`t Disconnecting VMNetwork Adapter from DC"
|
||||
$DC | Get-VMNetworkAdapter | Disconnect-VMNetworkAdapter
|
||||
WriteInfo "`t Shutting down DC"
|
||||
$DC | Stop-VM
|
||||
$DC | Set-VM -MemoryMinimumBytes 512MB
|
||||
|
|
|
@ -14,6 +14,7 @@ If (-not $isAdmin) {
|
|||
|
||||
#region Functions
|
||||
. $PSScriptRoot\0_Shared.ps1 # [!build-include-inline]
|
||||
. $PSScriptRoot\0_DCHydrate.ps1 # [!build-include-inline]
|
||||
|
||||
Function CreateUnattendFileBlob{
|
||||
#Create Unattend (parameter is Blob)
|
||||
|
@ -892,6 +893,10 @@ If (-not $isAdmin) {
|
|||
$LabConfig.SwitchName = 'LabSwitch'
|
||||
}
|
||||
|
||||
If (!$LabConfig.DHCPscope){
|
||||
$LabConfig.DHCPscope="10.0.0.0"
|
||||
}
|
||||
|
||||
WriteInfoHighlighted "List of variables used"
|
||||
WriteInfo "`t Prefix used in lab is $($labconfig.prefix)"
|
||||
|
||||
|
@ -1226,27 +1231,46 @@ If (-not $isAdmin) {
|
|||
}
|
||||
|
||||
if (!(get-vm -Name ($labconfig.prefix+"DC") -ErrorAction SilentlyContinue)){
|
||||
#import DC
|
||||
WriteInfo "`t Looking for DC to be imported"
|
||||
$dcCandidates = [array](Get-ChildItem $LABFolder -Recurse | Where-Object {($_.extension -eq '.vmcx' -and $_.directory -like '*Virtual Machines*') -or ($_.extension -eq '.xml' -and $_.directory -like '*Virtual Machines*')})
|
||||
$dcCandidates | ForEach-Object -Process {
|
||||
# If the VM ID is already used create a copy of the DC VM configuration instead of in-place registration
|
||||
$vm = Get-VM -Id $_.BaseName -ErrorAction SilentlyContinue
|
||||
if($vm -and $dcCandidates.Length -eq 1) { # allow duplicating of the DC VM only if it is the only one VM in lab folder (as if more than one exists, probably just labprefix was changed after the deployment)
|
||||
WriteInfoHighlighted "You are trying to deploy a previously deployed lab from a different location as there is another DC VM with a same VM ID (is this a copied lab folder?) -> this DC VM will be registered with new VM ID."
|
||||
$directory = $_.Directory.FullName.replace("\Virtual Machines", "")
|
||||
$DC = Import-VM -Path $_.FullName -GenerateNewId -Copy -VirtualMachinePath $directory -VhdDestinationPath "$directory\Virtual Hard Disks"
|
||||
WriteInfo "`t`t Virtual Machine $($DC.Name) registered with a new VM ID $($DC.Id)"
|
||||
} else {
|
||||
$DC = Import-VM -Path $_.FullName
|
||||
}
|
||||
}
|
||||
if ($LabConfig.NoDehydrateDC) {
|
||||
$DCName = "DC"
|
||||
$vhdpath="$PSScriptRoot\LAB\$DCName\Virtual Hard Disks\$DCName.vhdx"
|
||||
$VMPath="$PSScriptRoot\LAB\"
|
||||
$HydrationSwitchname="DC_HydrationSwitch_$([guid]::NewGuid())"
|
||||
|
||||
Hydrate-DC -DCName $DCName -VhdPath $vhdpath -VMPath $VMPath -Switchname $HydrationSwitchname -TimeZone $TimeZone -DHCPScope $LabConfig.DHCPscope -AdminPassword $LabConfig.AdminPassword
|
||||
$DC=Get-VM -Name $DCName
|
||||
if ($DC -eq $null){
|
||||
WriteErrorAndExit "DC was not imported successfully Press any key to continue ..."
|
||||
}else{
|
||||
WriteInfo "`t`t Virtual Machine $($DC.name) located in folder $($DC.Path) imported"
|
||||
WriteErrorAndExit "DC was not created successfully Press any key to continue ..."
|
||||
} else {
|
||||
WriteInfo "`t`t Virtual Machine $($DC.name) located in folder $($DC.Path) hydrated"
|
||||
}
|
||||
|
||||
# Clean up hydration switch
|
||||
WriteInfo "`t Removing switch $HydrationSwitchname"
|
||||
Remove-VMSwitch -Name $HydrationSwitchname -Force -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
#import DC
|
||||
WriteInfo "`t Looking for DC to be imported"
|
||||
$dcCandidates = [array](Get-ChildItem $LABFolder -Recurse | Where-Object {($_.extension -eq '.vmcx' -and $_.directory -like '*Virtual Machines*') -or ($_.extension -eq '.xml' -and $_.directory -like '*Virtual Machines*')})
|
||||
$dcCandidates | ForEach-Object -Process {
|
||||
# If the VM ID is already used create a copy of the DC VM configuration instead of in-place registration
|
||||
$vm = Get-VM -Id $_.BaseName -ErrorAction SilentlyContinue
|
||||
if($vm -and $dcCandidates.Length -eq 1) { # allow duplicating of the DC VM only if it is the only one VM in lab folder (as if more than one exists, probably just labprefix was changed after the deployment)
|
||||
WriteInfoHighlighted "You are trying to deploy a previously deployed lab from a different location as there is another DC VM with a same VM ID (is this a copied lab folder?) -> this DC VM will be registered with new VM ID."
|
||||
$directory = $_.Directory.FullName.replace("\Virtual Machines", "")
|
||||
$DC = Import-VM -Path $_.FullName -GenerateNewId -Copy -VirtualMachinePath $directory -VhdDestinationPath "$directory\Virtual Hard Disks"
|
||||
WriteInfo "`t`t Virtual Machine $($DC.Name) registered with a new VM ID $($DC.Id)"
|
||||
} else {
|
||||
$DC = Import-VM -Path $_.FullName
|
||||
}
|
||||
}
|
||||
if ($DC -eq $null){
|
||||
WriteErrorAndExit "DC was not imported successfully Press any key to continue ..."
|
||||
}else{
|
||||
WriteInfo "`t`t Virtual Machine $($DC.name) located in folder $($DC.Path) imported"
|
||||
}
|
||||
}
|
||||
|
||||
#create checkpoint to be able to return to consistent state when cleaned with cleanup.ps1
|
||||
$DC | Checkpoint-VM -SnapshotName Initial
|
||||
WriteInfo "`t Virtual Machine $($DC.name) checkpoint created"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
$LabConfig=@{AllowedVLANs="1-10,711-719" ; DomainAdminName='LabAdmin'; AdminPassword='LS1setup!'; Prefix = 'MSLab-' ; DCEdition='4'; Internet=$true ; AdditionalNetworksConfig=@(); VMs=@()}
|
||||
# Windows Server 2022
|
||||
1..4 | ForEach-Object {$LABConfig.VMs += @{ VMName = "$S2D$_" ; Configuration = 'S2D' ; ParentVHD = 'Win2022Core_G2.vhdx'; SSDNumber = 0; SSDSize=800GB ; HDDNumber = 12; HDDSize= 4TB ; MemoryStartupBytes= 512MB }}
|
||||
1..4 | ForEach-Object {$LABConfig.VMs += @{ VMName = "S2D$_" ; Configuration = 'S2D' ; ParentVHD = 'Win2022Core_G2.vhdx'; SSDNumber = 0; SSDSize=800GB ; HDDNumber = 12; HDDSize= 4TB ; MemoryStartupBytes= 512MB }}
|
||||
# Or Azure Stack HCI 23H2 (non-domain joined) https://github.com/DellGEOS/AzureStackHOLs/tree/main/lab-guides/01a-DeployAzureStackHCICluster-CloudBasedDeployment
|
||||
#1..2 | ForEach-Object {$LABConfig.VMs += @{ VMName = "ASNode$_" ; Configuration = 'S2D' ; ParentVHD = 'AzSHCI23H2_G2.vhdx' ; HDDNumber = 4 ; HDDSize= 2TB ; MemoryStartupBytes= 24GB; VMProcessorCount=16 ; vTPM=$true ; Unattend="NoDjoin" ; NestedVirt=$true }}
|
||||
# Or Windows Server 2025 https://github.com/DellGEOS/AzureLocalHOLs/tree/main/lab-guides/03-TestingWindowsServer2025
|
||||
|
@ -47,6 +47,7 @@ $LabConfig=@{AllowedVLANs="1-10,711-719" ; DomainAdminName='LabAdmin'; AdminPass
|
|||
SshKeyPath="$($env:USERPROFILE)\.ssh\id_rsa" # (Optional) If set, specified SSH key will be used to build and access Linux images.
|
||||
AutoClosePSWindows=$false; # (Optional) If set, the PowerShell console windows will automatically close once the script has completed successfully. Best suited for use in automated deployments.
|
||||
AutoCleanUp=$false; # (Optional) If set, after creating initial parent disks, files that are no longer necessary will be cleaned up. Best suited for use in automated deployments.
|
||||
NoDehydrateDC=$false; # (Optional) If set, do not attempt to create a dehydrated DC.
|
||||
AdditionalNetworksConfig=@(); # Just empty array for config below
|
||||
VMs=@(); # Just empty array for config below
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ $signedToolsOutputDir = Join-Path $outputBaseDir "Tools"
|
|||
$scriptsOutputFile = "Release.zip"
|
||||
|
||||
# Files that would be skipped by Build function (no replacements)
|
||||
[array]$scriptsBuildIgnoredFiles = "0_Shared.ps1"
|
||||
[array]$scriptsBuildIgnoredFiles = @("0_Shared.ps1", "0_DCHydrate.ps1")
|
||||
[array]$toolsBuildIgnoredFiles = @()
|
||||
|
||||
# Files that won't be signed after build function
|
||||
|
|
Загрузка…
Ссылка в новой задаче