зеркало из https://github.com/microsoft/MSLab.git
Windows Server 2019 Released + Tools Scripts moved
Former-commit-id: e1a04c1db3
This commit is contained in:
Родитель
ae8367bd98
Коммит
6849a2d2e7
|
@ -64,6 +64,12 @@ Note: Some videos may be a bit outdated as there is continuous innovation going
|
|||
|
||||
### or Windows Server 2019
|
||||
|
||||
* [ISO](https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2019)
|
||||
* [Latest Cumulative Update](http://catalog.update.microsoft.com/v7/site/Search.aspx?q=Cumulative%20Update%20for%20Windows%20Server%202019%20for%20x64-based%20Systems%20) for Windows Server 2019
|
||||
* For Labconfig uncomment 2019 part in LabConfig.
|
||||
|
||||
### or Windows Server Insider Preview
|
||||
|
||||
* [LTSC ISO](https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewserver)
|
||||
* [Insider labconfig.ps1](/Insider/LabConfig.ps1)
|
||||
|
||||
|
|
|
@ -78,844 +78,111 @@ function Get-WindowsBuildNumber {
|
|||
}
|
||||
|
||||
# Checking Folder Structure
|
||||
"ParentDisks","Tools\DSC","Tools\ToolsVHD\DiskSpd","Tools\ToolsVHD\SCVMM\ADK","Tools\ToolsVHD\SCVMM\SQL","Tools\ToolsVHD\SCVMM\SCVMM","Tools\ToolsVHD\SCVMM\UpdateRollup","Tools\ToolsVHD\VMFleet" | ForEach-Object {
|
||||
"ParentDisks","Temp","Temp\DSC","Temp\ToolsVHD\DiskSpd","Temp\ToolsVHD\SCVMM\ADK","Temp\ToolsVHD\SCVMM\SQL","Temp\ToolsVHD\SCVMM\SCVMM","Temp\ToolsVHD\SCVMM\UpdateRollup","Temp\ToolsVHD\VMFleet" | ForEach-Object {
|
||||
if (!( Test-Path "$PSScriptRoot\$_" )) { New-Item -Type Directory -Path "$PSScriptRoot\$_" } }
|
||||
|
||||
"Tools\ToolsVHD\SCVMM\ADK\Copy_ADK_with_adksetup.exe_here.txt","Tools\ToolsVHD\SCVMM\SQL\Copy_SQL2016_or_SQL2017_with_setup.exe_here.txt","Tools\ToolsVHD\SCVMM\SCVMM\Copy_SCVMM_with_setup.exe_here.txt","Tools\ToolsVHD\SCVMM\UpdateRollup\Copy_SCVMM_Update_Rollup_MSPs_here.txt" | ForEach-Object {
|
||||
"Temp\ToolsVHD\SCVMM\ADK\Copy_ADK_with_adksetup.exe_here.txt","Temp\ToolsVHD\SCVMM\SQL\Copy_SQL2016_or_SQL2017_with_setup.exe_here.txt","Temp\ToolsVHD\SCVMM\SCVMM\Copy_SCVMM_with_setup.exe_here.txt","Temp\ToolsVHD\SCVMM\UpdateRollup\Copy_SCVMM_Update_Rollup_MSPs_here.txt" | ForEach-Object {
|
||||
if (!( Test-Path "$PSScriptRoot\$_" )) { New-Item -Type File -Path "$PSScriptRoot\$_" } }
|
||||
#endregion
|
||||
|
||||
#region add scripts for SCVMM
|
||||
#adding scripts for SQL install
|
||||
$script = New-Item "$PSScriptRoot\Tools\ToolsVHD\SCVMM\1_SQL_Install.ps1" -type File -Force
|
||||
$fileContent = @'
|
||||
#region Download Scripts
|
||||
|
||||
# Sample SQL Install
|
||||
#add scripts for VMM
|
||||
$Filenames="1_SQL_Install","2_ADK_Install.ps1","3_SCVMM_Install.ps1"
|
||||
foreach ($Filename in $filenames){
|
||||
$Path="$PSScriptRoot\Temp\ToolsVHD\SCVMM\$Filename.ps1"
|
||||
If (Test-Path -Path $Path){
|
||||
WriteSuccess "`t $Filename is present, skipping download"
|
||||
}else{
|
||||
$FileContent = (Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/Microsoft/WSLab/master/Tools/$Filename.ps1").Content
|
||||
if ($FileContent){
|
||||
$script = New-Item $Path -type File -Force
|
||||
$FileContent=$FileContent -replace "PasswordGoesHere",$LabConfig.AdminPassword #only applies to 1_SQL_Install and 3_SCVMM_Install.ps1
|
||||
$FileContent=$FileContent -replace "DomainNameGoesHere",$LabConfig.DomainNetbiosName #only applies to 1_SQL_Install and 3_SCVMM_Install.ps1
|
||||
Set-Content -path $script -value $FileContent
|
||||
}else{
|
||||
WriteErrorAndExit "Unable to download $Filename."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# You can grab eval version here: http://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2016
|
||||
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
Start-Transcript -Path "$PSScriptRoot\SQL_Install.log"
|
||||
|
||||
$StartDateTime = get-date
|
||||
Write-host "Script started at $StartDateTime"
|
||||
|
||||
<#
|
||||
#check for .net 3.5
|
||||
if ((Get-WindowsOptionalFeature -Online -FeatureName NetFx3).State -ne 'Enabled'){
|
||||
do{
|
||||
If (Test-Path -Path "$PSScriptRoot\dotNET\microsoft-windows-netfx3-ondemand-package.cab"){
|
||||
$dotNET = Get-Item -Path "$PSScriptRoot\dotNET\microsoft-windows-netfx3-ondemand-package.cab" -ErrorAction SilentlyContinue
|
||||
Write-Host "microsoft-windows-netfx3-ondemand-package.cab found in dotNET folder... installing" -ForegroundColor Cyan
|
||||
#Download SetupVMFleet script
|
||||
$Filename="SetupVMFleet"
|
||||
$Path="$PSScriptRoot\Temp\ToolsVHD\$FileName.ps1"
|
||||
If (Test-Path -Path $Path){
|
||||
WriteSuccess "`t $Filename is present, skipping download"
|
||||
}else{
|
||||
Write-Host "No .NET found in $PSScriptRoot\dotNET" -ForegroundColor Cyan
|
||||
Write-Host "please browse for dotNET package (microsoft-windows-netfx3-ondemand-package.cab)" -ForegroundColor Green
|
||||
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "cab files (*.cab)|*.cab|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK"){
|
||||
Write-Host "File $openfile selected" -ForegroundColor Cyan
|
||||
$dotNET = Get-Item -Path $openfile.filename -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
Write-Host "CAB was not selected... Exitting" -ForegroundColor Red
|
||||
Write-Host "Press any key to continue ..."
|
||||
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
|
||||
$HOST.UI.RawUI.Flushinputbuffer()
|
||||
Exit
|
||||
}
|
||||
}
|
||||
install-windowsfeature WAS-NET-Environment -Source $dotnet.Directory
|
||||
}
|
||||
until ((Get-WindowsOptionalFeature -Online -FeatureName NetFx3).State -eq 'Enabled')
|
||||
}
|
||||
#>
|
||||
|
||||
#install SQL
|
||||
|
||||
If (Test-Path -Path "$PSScriptRoot\SQL\setup.exe"){
|
||||
$setupfile = (Get-Item -Path "$PSScriptRoot\SQL\setup.exe" -ErrorAction SilentlyContinue).fullname
|
||||
Write-Host "$Setupfile found..." -ForegroundColor Cyan
|
||||
}else{
|
||||
# Open File dialog
|
||||
Write-Host "Please locate SQL Setup.exe" -ForegroundColor Green
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "setup.exe files |setup.exe|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK")
|
||||
{
|
||||
$setupfile=$openfile.filename
|
||||
Write-Host "File $setupfile selected" -ForegroundColor Cyan
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
Write-Host "setup.exe was not selected... Exitting" -ForegroundColor Red
|
||||
Write-Host "Press any key to continue ..."
|
||||
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
|
||||
$HOST.UI.RawUI.Flushinputbuffer()
|
||||
Exit
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Installing SQL..." -ForegroundColor Green
|
||||
& $setupfile /q /ACTION=Install /FEATURES=SQLEngine /INSTANCENAME=MSSQLSERVER /SQLSVCACCOUNT="DomainNameGoesHere\SQL_SA" /SQLSVCPASSWORD="PasswordGoesHere" /SQLSYSADMINACCOUNTS="DomainNameGoesHere\Domain admins" /AGTSVCACCOUNT="DomainNameGoesHere\SQL_Agent" /AGTSVCPASSWORD="PasswordGoesHere" /TCPENABLED=1 /IACCEPTSQLSERVERLICENSETERMS /Indicateprogress /UpdateEnabled=0
|
||||
|
||||
Write-Host "Script finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
Stop-Transcript
|
||||
|
||||
Write-Host "Job Done..." -ForegroundColor Green
|
||||
Start-Sleep 5
|
||||
exit
|
||||
|
||||
'@
|
||||
$fileContent=$fileContent -replace "PasswordGoesHere",$LabConfig.AdminPassword
|
||||
$fileContent=$fileContent -replace "DomainNameGoesHere",$LabConfig.DomainNetbiosName
|
||||
Set-Content -path $script -value $fileContent
|
||||
|
||||
# adding scripts for ADK install
|
||||
$script = New-Item "$PSScriptRoot\Tools\ToolsVHD\SCVMM\2_ADK_Install.ps1" -type File -Force
|
||||
$fileContent = @'
|
||||
|
||||
#Sample ADK install
|
||||
|
||||
# You can grab ADK here: https://msdn.microsoft.com/en-us/windows/hardware/dn913721.aspx
|
||||
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
|
||||
Start-Transcript -Path "$PSScriptRoot\ADK_Install.log"
|
||||
|
||||
$StartDateTime = get-date
|
||||
Write-host "Script started at $StartDateTime"
|
||||
|
||||
|
||||
If (Test-Path -Path "$PSScriptRoot\ADK\ADKsetup.exe"){
|
||||
$setupfile = (Get-Item -Path "$PSScriptRoot\ADK\ADKsetup.exe" -ErrorAction SilentlyContinue).fullname
|
||||
}else{
|
||||
# Open File dialog
|
||||
Write-Host "Please locate ADKSetup.exe" -ForegroundColor Green
|
||||
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "ADKSetup.exe files |ADKSetup.exe|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK")
|
||||
{
|
||||
$setupfile=$openfile.filename
|
||||
Write-Host "File $setupfile selected" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Installing ADK..." -ForegroundColor Cyan
|
||||
|
||||
Write-Host "ADK Is being installed..." -ForegroundColor Cyan
|
||||
Start-Process -Wait -FilePath $setupfile -ArgumentList "/features OptionID.DeploymentTools OptionID.WindowsPreinstallationEnvironment /quiet"
|
||||
Write-Host "ADK install finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
Stop-Transcript
|
||||
Write-Host "Job Done..." -ForegroundColor Green
|
||||
Start-Sleep 5
|
||||
exit
|
||||
|
||||
'@
|
||||
Set-Content -path $script -value $fileContent
|
||||
|
||||
# adding scripts for SCVMM install
|
||||
$script = New-Item "$PSScriptRoot\Tools\ToolsVHD\SCVMM\3_SCVMM_Install.ps1" -type File -Force
|
||||
$fileContent = @'
|
||||
|
||||
# Sample VMM Install
|
||||
|
||||
# You can grab eval version here: http://www.microsoft.com/en-us/evalcenter/evaluate-system-center-technical-preview
|
||||
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
Start-Transcript -Path "$PSScriptRoot\SCVMM_Install.log"
|
||||
|
||||
$StartDateTime = get-date
|
||||
Write-host "Script started at $StartDateTime"
|
||||
|
||||
if ((get-service MSSQLServer).Status -ne "Running"){
|
||||
do{
|
||||
Write-Host "Waiting for SQL Service to start"
|
||||
Start-Sleep 10
|
||||
Start-Service -Name MSSQLServer
|
||||
}until ((get-service MSSQLServer).Status -eq "Running")
|
||||
Write-Host "SQL Service is running"
|
||||
}
|
||||
|
||||
If (Test-Path -Path "$PSScriptRoot\SCVMM\setup.exe"){
|
||||
$setupfile = (Get-Item -Path "$PSScriptRoot\SCVMM\setup.exe" -ErrorAction SilentlyContinue).fullname
|
||||
Write-Host "$Setupfile found..." -ForegroundColor Cyan
|
||||
}else{
|
||||
# Open File dialog
|
||||
Write-Host "Please locate Setup.exe" -ForegroundColor Green
|
||||
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "setup.exe files |setup.exe|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK")
|
||||
{
|
||||
$setupfile=$openfile.filename
|
||||
Write-Host "File $setupfile selected" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Installing VMM..." -ForegroundColor Green
|
||||
|
||||
###Get workdirectory###
|
||||
#Install VMM
|
||||
$unattendFile = New-Item "$PSScriptRoot\VMServer.ini" -type File
|
||||
$fileContent = @"
|
||||
[OPTIONS]
|
||||
CompanyName=Contoso
|
||||
CreateNewSqlDatabase=1
|
||||
SqlInstanceName=MSSQLServer
|
||||
SqlDatabaseName=VirtualManagerDB
|
||||
SqlMachineName=DC
|
||||
VmmServiceLocalAccount=0
|
||||
LibrarySharePath=C:\ProgramData\Virtual Machine Manager Library Files
|
||||
LibraryShareName=MSSCVMMLibrary
|
||||
SQMOptIn = 1
|
||||
MUOptIn = 1
|
||||
"@
|
||||
Set-Content $unattendFile $fileContent
|
||||
|
||||
Write-Host "VMM is being installed..." -ForegroundColor Cyan
|
||||
& $setupfile /server /i /f $PSScriptRoot\VMServer.ini /IACCEPTSCEULA /VmmServiceDomain DomainNameGoesHere /VmmServiceUserName vmm_SA /VmmServiceUserPassword PasswordGoesHere
|
||||
do{
|
||||
Start-Sleep 1
|
||||
}until ((Get-Process | Where-Object {$_.Description -eq "Virtual Machine Manager Setup"} -ErrorAction SilentlyContinue) -eq $null)
|
||||
Write-Host "VMM is Installed" -ForegroundColor Green
|
||||
|
||||
Remove-Item "$PSScriptRoot\VMServer.ini" -ErrorAction Ignore
|
||||
|
||||
Write-Host "VMM install finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
|
||||
$StartDateTime = get-date
|
||||
$URs=(Get-ChildItem -Path $PSScriptRoot\UpdateRollup -Recurse | where extension -eq .msp).FullName
|
||||
|
||||
Foreach ($UR in $URs){
|
||||
Write-Host "Update Rollup $UR is being installed"
|
||||
Start-Process -Wait -Filepath msiexec.exe -Argumentlist "/update $UR /quiet /norestart"
|
||||
}
|
||||
If ($URs){
|
||||
Write-Host "UpdateRollups install finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
}
|
||||
|
||||
Stop-Transcript
|
||||
Write-Host "Job Done..." -ForegroundColor Green
|
||||
start-sleep 5
|
||||
Exit
|
||||
|
||||
'@
|
||||
|
||||
$fileContent=$fileContent -replace "PasswordGoesHere",$LabConfig.AdminPassword
|
||||
$fileContent=$fileContent -replace "DomainNameGoesHere",$LabConfig.DomainNetbiosName
|
||||
Set-Content -path $script -value $fileContent
|
||||
|
||||
|
||||
# adding createparentdisks script
|
||||
|
||||
$script = New-Item "$PSScriptRoot\Tools\CreateParentDisk.ps1" -type File -Force
|
||||
$fileContent = @'
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Start-Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
#region Functions
|
||||
|
||||
|
||||
function WriteInfo($message){
|
||||
Write-Host $message
|
||||
}
|
||||
|
||||
function WriteInfoHighlighted($message){
|
||||
Write-Host $message -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function WriteSuccess($message){
|
||||
Write-Host $message -ForegroundColor Green
|
||||
}
|
||||
|
||||
function WriteError($message){
|
||||
Write-Host $message -ForegroundColor Red
|
||||
}
|
||||
|
||||
function WriteErrorAndExit($message){
|
||||
Write-Host $message -ForegroundColor Red
|
||||
Write-Host "Press enter to continue ..."
|
||||
$exit=Read-Host
|
||||
Exit
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ask for ISO
|
||||
WriteInfoHighlighted "Please select ISO image"
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Title="Please select ISO image"
|
||||
}
|
||||
$openFile.Filter = "iso files (*.iso)|*.iso|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK"){
|
||||
WriteInfo "File $($openfile.FileName) selected"
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
WriteErrorAndExit "Iso was not selected... Exitting"
|
||||
}
|
||||
$ISO = Mount-DiskImage -ImagePath $openFile.FileName -PassThru
|
||||
|
||||
$ISOMediaPath = (Get-Volume -DiskImage $ISO).DriveLetter+':'
|
||||
|
||||
#endregion
|
||||
|
||||
#region ask for MSU packages
|
||||
WriteInfoHighlighted "Please select msu packages you want to add to image. Click cancel if you don't want any."
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$msupackages = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Multiselect = $true;
|
||||
Title="Please select msu packages you want to add to image. Click cancel if you don't want any."
|
||||
}
|
||||
$msupackages.Filter = "msu files (*.msu)|*.msu|All files (*.*)|*.*"
|
||||
If($msupackages.ShowDialog() -eq "OK"){
|
||||
WriteInfoHighlighted "Following patches selected:"
|
||||
foreach ($filename in $msupackages.FileNames){
|
||||
WriteInfo "`t $filename"
|
||||
}
|
||||
}
|
||||
|
||||
#Write info if nothing is selected
|
||||
if (!$msupackages.FileNames){
|
||||
WriteInfoHighlighted "No msu was selected..."
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region download convert-windowsimage if needed and load it
|
||||
|
||||
if (!(Test-Path "$PSScriptRoot\convert-windowsimage.ps1")){
|
||||
WriteInfo "`t Downloading Convert-WindowsImage"
|
||||
try{
|
||||
Invoke-WebRequest -UseBasicParsing -Uri https://raw.githubusercontent.com/MicrosoftDocs/Virtualization-Documentation/live/hyperv-tools/Convert-WindowsImage/Convert-WindowsImage.ps1 -OutFile "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
}catch{
|
||||
WriteErrorAndExit "`t Failed to download convert-windowsimage.ps1!"
|
||||
}
|
||||
}
|
||||
|
||||
#load convert-windowsimage
|
||||
. "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
|
||||
#endregion
|
||||
|
||||
#region do the job
|
||||
$BuildNumber=(Get-ItemProperty -Path "$ISOMediaPath\setup.exe").versioninfo.FileBuildPart
|
||||
|
||||
if ($BuildNumber -eq 14393){
|
||||
$NanoServer=(Read-Host -Prompt "Server 2016 ISO Selected. Do you want to build NanoServer? Y/N")
|
||||
}
|
||||
|
||||
if ($Nanoserver -eq "Y"){
|
||||
$WindowsImage=Get-WindowsImage -ImagePath "$ISOMediaPath\NanoServer\NanoServer.wim"
|
||||
|
||||
#ask for edition
|
||||
$Edition=($WindowsImage | Out-GridView -OutputMode Single).ImageName
|
||||
|
||||
#ask for cab files
|
||||
WriteInfoHighlighted "Please select cab packages you want to add to image. Click cancel if you want default."
|
||||
$nanocabs=(Get-ChildItem -Path "$ISOMediaPath\NanoServer\Packages" -filter *.cab| select BaseName) | Out-GridView -OutputMode Multiple
|
||||
if (!$nanocabs){
|
||||
$nanocabs="Microsoft-NanoServer-DSC-Package","Microsoft-NanoServer-FailoverCluster-Package","Microsoft-NanoServer-Guest-Package","Microsoft-NanoServer-Storage-Package","Microsoft-NanoServer-SCVMM-Package","Microsoft-NanoServer-Compute-Package","Microsoft-NanoServer-SCVMM-Compute-Package","Microsoft-NanoServer-SecureStartup-Package","Microsoft-NanoServer-DCB-Package","Microsoft-NanoServer-ShieldedVM-Package"
|
||||
}
|
||||
#grab Nano packages
|
||||
$NanoPackages=@()
|
||||
foreach ($NanoPackage in $nanocabs){
|
||||
$NanoPackages+=(Get-ChildItem -Path "$ISOMediaPath\NanoServer\Packages" -Recurse | Where-Object Name -like $NanoPackage*).FullName
|
||||
}
|
||||
WriteInfoHighlighted "Following patches selected:"
|
||||
$NanoPackages
|
||||
#create temp name
|
||||
$tempvhdname="Win2016NanoHV_G2.vhdx"
|
||||
|
||||
$FileContent = (Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/Microsoft/WSLab/master/Tools/$Filename.ps1").Content
|
||||
if ($FileContent){
|
||||
$script = New-Item $Path -type File -Force
|
||||
$FileContent=$FileContent -replace "PasswordGoesHere",$LabConfig.AdminPassword
|
||||
$FileContent=$FileContent -replace "DomainNameGoesHere",$LabConfig.DomainNetbiosName
|
||||
Set-Content -path $script -value $FileContent
|
||||
}else{
|
||||
$WindowsImage=Get-WindowsImage -ImagePath "$ISOMediaPath\sources\install.wim"
|
||||
if ($BuildNumber -lt 7600){
|
||||
if ($ISO -ne $Null){
|
||||
$ISO | Dismount-DiskImage
|
||||
}
|
||||
WriteErrorAndExit "`t Use Windows 7 or newer!"
|
||||
}
|
||||
#ask for edition
|
||||
$Edition=($WindowsImage | Out-GridView -OutputMode Single).ImageName
|
||||
|
||||
#Generate vhdx name
|
||||
if ($Edition -like "*Server*Core*"){
|
||||
$tempvhdname = switch ($BuildNumber){
|
||||
7600 {
|
||||
"Win2008R2Core_G1.vhdx"
|
||||
}
|
||||
7601 {
|
||||
"Win2008R2SP1Core_G1.vhdx"
|
||||
}
|
||||
9200 {
|
||||
"Win2012Core_G2.vhdx"
|
||||
}
|
||||
9600 {
|
||||
"Win2012R2Core_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win2016Core_G2.vhdx"
|
||||
}
|
||||
|
||||
}
|
||||
if ($BuildNumber -GT 17134){
|
||||
$tempvhdname="Win2019Core_$BuildNumber.vhdx"
|
||||
}
|
||||
}elseif($Edition -like "*Server*"){
|
||||
$tempvhdname = switch ($BuildNumber){
|
||||
7600 {
|
||||
"Win2008R2_G1.vhdx"
|
||||
}
|
||||
7601 {
|
||||
"Win2008R2SP1_G1.vhdx"
|
||||
}
|
||||
9200 {
|
||||
"Win2012_G2.vhdx"
|
||||
}
|
||||
9600 {
|
||||
"Win2012R2_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win2016_G2.vhdx"
|
||||
}
|
||||
16299 {
|
||||
"WinServer1709_G2.vhdx"
|
||||
}
|
||||
17134 {
|
||||
"WinServer1803_G2.vhdx"
|
||||
}
|
||||
}
|
||||
if ($BuildNumber -GT 17134){
|
||||
$tempvhdname="Win2019_$BuildNumber.vhdx"
|
||||
}
|
||||
}else{
|
||||
$tempvhdname = switch ($BuildNumber){
|
||||
7600 {
|
||||
"Win7_G1.vhdx"
|
||||
}
|
||||
7601 {
|
||||
"Win7SP1_G1.vhdx"
|
||||
}
|
||||
9200 {
|
||||
"Win8_G2.vhdx"
|
||||
}
|
||||
9600 {
|
||||
"Win8.1_G2.vhdx"
|
||||
}
|
||||
10240 {
|
||||
"Win10TH1_G2.vhdx"
|
||||
}
|
||||
10586 {
|
||||
"Win10TH2_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win10RS1_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win10RS1_G2.vhdx"
|
||||
}
|
||||
15064 {
|
||||
"Win10RS2_G2.vhdx"
|
||||
}
|
||||
16299 {
|
||||
"Win10RS3_G2.vhdx"
|
||||
}
|
||||
17134 {
|
||||
"Win10RS4_G2.vhdx"
|
||||
}
|
||||
}
|
||||
if ($BuildNumber -GT 17134){
|
||||
$tempvhdname="Win10Insider_$BuildNumber.vhdx"
|
||||
}
|
||||
}
|
||||
WriteErrorAndExit "Unable to download $Filename."
|
||||
}
|
||||
}
|
||||
|
||||
#ask for imagename
|
||||
$vhdname=(Read-Host -Prompt "Please type VHD name (if nothing specified, $tempvhdname is used")
|
||||
if(!$vhdname){$vhdname=$tempvhdname}
|
||||
|
||||
#ask for size
|
||||
[int64]$size=(Read-Host -Prompt "Please type size of the Image in GB. If nothing specified, 60 is used")
|
||||
$size=$size*1GB
|
||||
if (!$size){$size=60GB}
|
||||
|
||||
#Create VHD
|
||||
if ($nanoserver -eq "y"){
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\NanoServer\NanoServer.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI -Package ($msupackages.FileNames+$NanoPackages)
|
||||
# add createparentdisks script
|
||||
$Filename="CreateParentDisk"
|
||||
$Path="$PSScriptRoot\ParentDisks\$FileName.ps1"
|
||||
If (Test-Path -Path $Path){
|
||||
WriteSuccess "`t $Filename is present, skipping download"
|
||||
}else{
|
||||
$FileContent = (Invoke-WebRequest -UseBasicParsing -Uri https://raw.githubusercontent.com/Microsoft/WSLab/master/Tools/CreateParentDisk.ps1).Content
|
||||
if ($FileContent){
|
||||
$script = New-Item "$PSScriptRoot\ParentDisks\CreateParentDisk.ps1" -type File -Force
|
||||
Set-Content -path $script -value $FileContent
|
||||
}else{
|
||||
if ($msupackages.FileNames -ne $null){
|
||||
if ($BuildNumber -le 7601){
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout BIOS -Package $msupackages.FileNames
|
||||
}else{
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI -Package $msupackages.FileNames
|
||||
}
|
||||
}else{
|
||||
if ($BuildNumber -le 7601){
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout BIOS
|
||||
}else{
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI
|
||||
}
|
||||
}
|
||||
WriteErrorAndExit "Unable to download $Filename."
|
||||
}
|
||||
|
||||
WriteInfo "Dismounting ISO Image"
|
||||
if ($ISO -ne $Null){
|
||||
$ISO | Dismount-DiskImage
|
||||
}
|
||||
|
||||
WriteSuccess "Job Done. Press enter to continue..."
|
||||
$exit=Read-Host
|
||||
#endregion
|
||||
'@
|
||||
|
||||
Set-Content -path $script -value $fileContent
|
||||
|
||||
# adding SetupVMFleet script
|
||||
|
||||
$script = New-Item "$PSScriptRoot\Tools\ToolsVHD\SetupVMFleet.ps1" -type File -Force
|
||||
$fileContent = @'
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Start-Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
#region functions
|
||||
|
||||
function WriteInfo($message)
|
||||
{
|
||||
Write-Host $message
|
||||
}
|
||||
|
||||
function WriteInfoHighlighted($message)
|
||||
{
|
||||
Write-Host $message -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function WriteSuccess($message)
|
||||
{
|
||||
Write-Host $message -ForegroundColor Green
|
||||
}
|
||||
|
||||
function WriteError($message)
|
||||
{
|
||||
Write-Host $message -ForegroundColor Red
|
||||
}
|
||||
|
||||
function WriteErrorAndExit($message){
|
||||
Write-Host $message -ForegroundColor Red
|
||||
Write-Host "Press enter to continue ..."
|
||||
$exit=Read-Host
|
||||
Exit
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region grab variables
|
||||
#verify management tools to be able to list S2D Cluster
|
||||
if ((Get-WmiObject Win32_OperatingSystem).ProductType -ne 1){
|
||||
#Install AD PowerShell if not available
|
||||
if (-not (Get-WindowsFeature RSAT-AD-PowerShell)){
|
||||
Install-WindowsFeature RSAT-AD-PowerShell
|
||||
}
|
||||
}else{
|
||||
#detect RSAT
|
||||
if (!((Get-HotFix).hotfixid -contains "KB2693643") ){
|
||||
Write-Host "Please install RSAT, Exitting in 5s"
|
||||
Start-Sleep 5
|
||||
Exit
|
||||
}
|
||||
}
|
||||
|
||||
#Grab S2D Cluster
|
||||
WriteInfoHighlighted "Asking for S2D Cluster"
|
||||
$ClusterName=((Get-ADComputer -Filter 'serviceprincipalname -like "MSServercluster/*"').Name | ForEach-Object {get-cluster -Name $_ | Where-Object S2DEnabled -eq 1} | Out-GridView -OutputMode Single -Title "Please select your S2D Cluster(s)").Name
|
||||
|
||||
if (-not $ClusterName){
|
||||
Write-Output "No cluster was selected. Exitting"
|
||||
Start-Sleep 5
|
||||
Exit
|
||||
}
|
||||
|
||||
#Grab ClusterNodes
|
||||
$ClusterNodes=(Get-ClusterNode -Cluster $ClusterName).Name
|
||||
|
||||
#ask for Password that will be configured inside VHD
|
||||
WriteInfoHighlighted "Please provide password that will be injected as admin password into VHD"
|
||||
$AdminPassword=Read-Host
|
||||
|
||||
#Ask for VHD
|
||||
WriteInfoHighlighted "Please select VHD created by convert-windowsimage. Click cancel if you want to create it"
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Title="Please select VHD created by convert-windowsimage. Click cancel if you want to create it"
|
||||
}
|
||||
$openFile.Filter = "vhdx files (*.vhdx)|*.vhdx|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK"){
|
||||
WriteInfo "File $($openfile.FileName) selected"
|
||||
}
|
||||
$VHDPath=$openfile.FileName
|
||||
|
||||
#endregion
|
||||
|
||||
#region if VHD not selected, create one
|
||||
if (-not $VHDPath){
|
||||
#Ask for ISO
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Title="Please select ISO image with Windows Server 2016"
|
||||
}
|
||||
$openFile.Filter = "iso files (*.iso)|*.iso|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK")
|
||||
{
|
||||
WriteInfo "File $($openfile.FileName) selected"
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
WriteErrorAndExit "Iso was not selected... Exitting"
|
||||
}
|
||||
$ISOServer = Mount-DiskImage -ImagePath $openFile.FileName -PassThru
|
||||
|
||||
$ServerMediaPath = (Get-Volume -DiskImage $ISOServer).DriveLetter+':'
|
||||
|
||||
if (!(Test-Path "$PSScriptRoot\convert-windowsimage.ps1")){
|
||||
#download latest convert-windowsimage
|
||||
# Download convert-windowsimage if its not in tools folder
|
||||
WriteInfo "`t Downloading Convert-WindowsImage"
|
||||
try{
|
||||
Invoke-WebRequest -UseBasicParsing -Uri https://raw.githubusercontent.com/MicrosoftDocs/Virtualization-Documentation/live/hyperv-tools/Convert-WindowsImage/Convert-WindowsImage.ps1 -OutFile "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
}catch{
|
||||
WriteErrorAndExit "`t Failed to download convert-windowsimage.ps1!"
|
||||
}
|
||||
}
|
||||
|
||||
#load convert-windowsimage
|
||||
. "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
|
||||
#ask for server edition
|
||||
$Edition=(Get-WindowsImage -ImagePath "$ServerMediaPath\sources\install.wim" | Out-GridView -OutputMode Single).ImageName
|
||||
|
||||
#ask for imagename
|
||||
$vhdname=(Read-Host -Prompt "Please type VHD name (if nothing specified, Win10_G2.vhdx is used")
|
||||
if(!$vhdname){$vhdname="Win10_G2.vhdx"}
|
||||
|
||||
#ask for size
|
||||
[int64]$size=(Read-Host -Prompt "Please type size of the Image in GB. If nothing specified, 60 is used")
|
||||
$size=$size*1GB
|
||||
if (!$size){$size=60GB}
|
||||
|
||||
#Create VHD
|
||||
Convert-WindowsImage -SourcePath "$ServerMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI
|
||||
|
||||
WriteInfo "Dismounting ISO Image"
|
||||
if ($ISOServer -ne $Null){
|
||||
$ISOServer | Dismount-DiskImage
|
||||
}
|
||||
|
||||
$VHDPath="$PSScriptRoot\$vhdname"
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Mount VHD and apply unattend
|
||||
WriteInfoHighlighted "`t Applying Unattend"
|
||||
if (Test-Path "$PSScriptRoot\Temp\*"){
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\*" -Recurse
|
||||
}
|
||||
New-item -type directory -Path $PSScriptRoot\Temp\mountdir -force
|
||||
Mount-WindowsImage -Path "$PSScriptRoot\Temp\mountdir" -ImagePath $VHDPath -Index 1
|
||||
New-item -type directory -Path "$PSScriptRoot\Temp\mountdir\Users\Administrator" -force
|
||||
New-item -type directory -Path "$PSScriptRoot\Temp\mountdir\Windows\Panther" -force
|
||||
$unattendFile = New-Item "$PSScriptRoot\Temp\mountdir\Windows\Panther\unattend.xml" -type File -Force
|
||||
$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"
|
||||
>
|
||||
</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">
|
||||
<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">
|
||||
<AutoLogon>
|
||||
<Password>
|
||||
<Value>$AdminPassword</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
<Enabled>true</Enabled>
|
||||
<LogonCount>999</LogonCount>
|
||||
<Username>administrator</Username>
|
||||
</AutoLogon>
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value>$AdminPassword</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||
<SkipUserOOBE>true</SkipUserOOBE>
|
||||
</OOBE>
|
||||
<TimeZone>Pacific Standard Time</TimeZone>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
|
||||
"@
|
||||
Set-Content -path $unattendFile -value $fileContent -Force
|
||||
|
||||
#close VHD and apply changes
|
||||
WriteInfoHighlighted "`t Applying changes to VHD"
|
||||
Dismount-WindowsImage -Path "$PSScriptRoot\Temp\mountdir" -Save
|
||||
|
||||
#cleanup mountdir
|
||||
Remove-Item -Path "$PSScriptRoot\Temp" -Recurse
|
||||
|
||||
#endregion
|
||||
|
||||
#region create volumes
|
||||
WriteInfoHighlighted "Create Volumes"
|
||||
Foreach ($ClusterNode in $ClusterNodes){
|
||||
WriteInfo "Creating Volume $ClusterNode"
|
||||
if (-not (Get-VirtualDisk -CimSession $ClusterName -FriendlyName $ClusterNode -ErrorAction SilentlyContinue)){
|
||||
New-Volume -CimSession $ClusterName -StoragePoolFriendlyName "S2D on $ClusterName" -FriendlyName $ClusterNode -FileSystem CSVFS_ReFS -StorageTierfriendlyNames Performance -StorageTierSizes 1TB
|
||||
}
|
||||
}
|
||||
WriteInfo "Creating Volume collect"
|
||||
if (-not (Get-VirtualDisk -CimSession $ClusterName -FriendlyName "Collect" -ErrorAction SilentlyContinue)){
|
||||
New-Volume -CimSession $ClusterName -StoragePoolFriendlyName "S2D on $ClusterName" -FriendlyName collect -FileSystem CSVFS_ReFS -StorageTierFriendlyNames Performance -StorageTierSizes 1TB
|
||||
}
|
||||
|
||||
#rename CSV(s) to match name
|
||||
Get-ClusterSharedVolume -Cluster $ClusterName | % {
|
||||
$volumepath=$_.sharedvolumeinfo.friendlyvolumename
|
||||
$newname=$_.name.Substring(22,$_.name.Length-23)
|
||||
Invoke-Command -ComputerName (Get-ClusterSharedVolume -Cluster $ClusterName -Name $_.Name).ownernode -ScriptBlock {param($volumepath,$newname); Rename-Item -Path $volumepath -NewName $newname} -ArgumentList $volumepath,$newname -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
#Install Failover Clustering PowerShell on nodes
|
||||
foreach ($ClusterNode in $ClusterNodes){
|
||||
Install-WindowsFeature -Name RSAT-Clustering-PowerShell -ComputerName $ClusterNode
|
||||
}
|
||||
|
||||
#copy VMfleet and VHD to one node
|
||||
New-item -Path "\\$($ClusterNodes[0])\c$\" -Name VMFleet -Type Directory -Force
|
||||
WriteInfoHighlighted "Copying Scripts to \\$($ClusterNodes[0])\c$\VMFleet"
|
||||
Copy-Item "$PSScriptRoot\VMFleet\*" -Destination "\\$($ClusterNodes[0])\c$\VMFleet"
|
||||
WriteInfoHighlighted "Copying $VHDPath to \\$ClusterName\ClusterStorage$\Collect\FleetImage.vhdx"
|
||||
if (-not (Test-Path -Path "\\$ClusterName\ClusterStorage$\Collect\FleetImage.vhdx")){
|
||||
Copy-Item $VHDPath -Destination "\\$ClusterName\ClusterStorage$\Collect\FleetImage.vhdx"
|
||||
}
|
||||
|
||||
WriteInfoHighlighted "Run following commands from $($ClusterNodes[0])"
|
||||
"c:\VMFleet\install-vmfleet.ps1 -source C:\VMFleet"
|
||||
"Copy-Item \\DC\D$\DiskSpd\Diskspd.exe -Destination c:\ClusterStorage\Collect\Control\Tools\Diskspd.exe"
|
||||
"c:\VMFleet\create-vmfleet.ps1 -basevhd C:\ClusterStorage\Collect\FleetImage.vhdx -vms 1 -adminpass $AdminPassword -connectuser DomainNameGoesHere\Administrator -connectpass PasswordGoesHere -FixedVHD:"+'$False'
|
||||
"c:\VMFleet\set-vmfleet.ps1 -ProcessorCount 2 -MemoryStartupBytes 512MB -MemoryMinimumBytes 512MB -MemoryMaximumBytes 2GB"
|
||||
"c:\VMFleet\Start-Vmfleet.ps1"
|
||||
"c:\VMFleet\start-sweep.ps1 -b 4 -t 2 -o 40 -w 0 -d 300"
|
||||
"c:\VMFleet\watch-cluster.ps1"
|
||||
|
||||
WriteSuccess "Press enter to exit..."
|
||||
$exit=Read-Host
|
||||
|
||||
'@
|
||||
$fileContent=$fileContent -replace "PasswordGoesHere",$LabConfig.AdminPassword
|
||||
$fileContent=$fileContent -replace "DomainNameGoesHere",$LabConfig.DomainNetbiosName
|
||||
Set-Content -path $script -value $fileContent
|
||||
|
||||
#endregion
|
||||
|
||||
#region some tools to download
|
||||
# Downloading diskspd if its not in tools folder
|
||||
# Downloading diskspd if its not in ToolsVHD folder
|
||||
WriteInfoHighlighted "Testing diskspd presence"
|
||||
If ( Test-Path -Path "$PSScriptRoot\Tools\ToolsVHD\DiskSpd\diskspd.exe" ) {
|
||||
If ( Test-Path -Path "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\diskspd.exe" ) {
|
||||
WriteSuccess "`t Diskspd is present, skipping download"
|
||||
}else{
|
||||
WriteInfo "`t Diskspd not there - Downloading diskspd"
|
||||
try {
|
||||
$webcontent = Invoke-WebRequest -Uri aka.ms/diskspd -UseBasicParsing
|
||||
$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")
|
||||
Invoke-WebRequest -Uri $downloadurl -OutFile "$PSScriptRoot\Tools\ToolsVHD\DiskSpd\diskspd.zip"
|
||||
Invoke-WebRequest -Uri $downloadurl -OutFile "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\diskspd.zip"
|
||||
}catch{
|
||||
WriteError "`t Failed to download Diskspd!"
|
||||
}
|
||||
# Unnzipping and extracting just diskspd.exe x64
|
||||
Expand-Archive "$PSScriptRoot\Tools\ToolsVHD\DiskSpd\diskspd.zip" -DestinationPath "$PSScriptRoot\Tools\ToolsVHD\DiskSpd\Unzip"
|
||||
Copy-Item -Path (Get-ChildItem -Path "$PSScriptRoot\tools\toolsvhd\diskspd\" -Recurse | Where-Object {$_.Directory -like '*amd64*' -and $_.name -eq 'diskspd.exe' }).fullname -Destination "$PSScriptRoot\Tools\ToolsVHD\DiskSpd\"
|
||||
Remove-Item -Path "$PSScriptRoot\Tools\ToolsVHD\DiskSpd\diskspd.zip"
|
||||
Remove-Item -Path "$PSScriptRoot\Tools\ToolsVHD\DiskSpd\Unzip" -Recurse -Force
|
||||
Expand-Archive "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\diskspd.zip" -DestinationPath "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\Unzip"
|
||||
Copy-Item -Path (Get-ChildItem -Path "$PSScriptRoot\Temp\ToolsVHD\diskspd\" -Recurse | Where-Object {$_.Directory -like '*amd64*' -and $_.name -eq 'diskspd.exe' }).fullname -Destination "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\"
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\diskspd.zip"
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\ToolsVHD\DiskSpd\Unzip" -Recurse -Force
|
||||
}
|
||||
|
||||
#Download VMFleet
|
||||
WriteInfoHighlighted "Testing VMFleet presence"
|
||||
If ( Test-Path -Path "$PSScriptRoot\Tools\ToolsVHD\VMFleet\install-vmfleet.ps1" ) {
|
||||
If ( Test-Path -Path "$PSScriptRoot\Temp\ToolsVHD\VMFleet\install-vmfleet.ps1" ) {
|
||||
WriteSuccess "`t VMFleet is present, skipping download"
|
||||
}else{
|
||||
WriteInfo "`t VMFleet not there - Downloading VMFleet"
|
||||
try {
|
||||
$downloadurl = "https://github.com/Microsoft/diskspd/archive/master.zip"
|
||||
Invoke-WebRequest -Uri $downloadurl -OutFile "$PSScriptRoot\Tools\ToolsVHD\VMFleet\VMFleet.zip"
|
||||
Invoke-WebRequest -Uri $downloadurl -OutFile "$PSScriptRoot\Temp\ToolsVHD\VMFleet\VMFleet.zip"
|
||||
}catch{
|
||||
WriteError "`t Failed to download VMFleet!"
|
||||
}
|
||||
# Unnzipping and extracting just VMFleet
|
||||
Expand-Archive "$PSScriptRoot\Tools\ToolsVHD\VMFleet\VMFleet.zip" -DestinationPath "$PSScriptRoot\Tools\ToolsVHD\VMFleet\Unzip"
|
||||
Copy-Item -Path "$PSScriptRoot\Tools\ToolsVHD\VMFleet\Unzip\diskspd-master\Frameworks\VMFleet\*" -Destination "$PSScriptRoot\Tools\ToolsVHD\VMFleet\"
|
||||
Remove-Item -Path "$PSScriptRoot\Tools\ToolsVHD\VMFleet\VMFleet.zip"
|
||||
Remove-Item -Path "$PSScriptRoot\Tools\ToolsVHD\VMFleet\Unzip" -Recurse -Force
|
||||
Expand-Archive "$PSScriptRoot\Temp\ToolsVHD\VMFleet\VMFleet.zip" -DestinationPath "$PSScriptRoot\Temp\ToolsVHD\VMFleet\Unzip"
|
||||
Copy-Item -Path "$PSScriptRoot\Temp\ToolsVHD\VMFleet\Unzip\diskspd-master\Frameworks\VMFleet\*" -Destination "$PSScriptRoot\Temp\ToolsVHD\VMFleet\"
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\ToolsVHD\VMFleet\VMFleet.zip"
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\ToolsVHD\VMFleet\Unzip" -Recurse -Force
|
||||
}
|
||||
|
||||
# Download convert-windowsimage into ToolsRoot and ToolsVHD
|
||||
# Download convert-windowsimage into ParentDisks and ToolsVHD
|
||||
WriteInfoHighlighted "Testing convert-windowsimage presence"
|
||||
If ( Test-Path -Path "$PSScriptRoot\Tools\convert-windowsimage.ps1" ) {
|
||||
If ( Test-Path -Path "$PSScriptRoot\ParentDisks\convert-windowsimage.ps1" ) {
|
||||
WriteSuccess "`t Convert-windowsimage.ps1 is present, skipping download"
|
||||
}else{
|
||||
WriteInfo "`t Downloading Convert-WindowsImage"
|
||||
|
@ -926,24 +193,24 @@ $exit=Read-Host
|
|||
}
|
||||
}
|
||||
|
||||
If ( Test-Path -Path "$PSScriptRoot\Tools\ToolsVHD\convert-windowsimage.ps1" ) {
|
||||
If ( Test-Path -Path "$PSScriptRoot\Temp\ToolsVHD\convert-windowsimage.ps1" ) {
|
||||
WriteSuccess "`t Convert-windowsimage.ps1 is in ToolsVHD, skipping copy"
|
||||
}else{
|
||||
WriteInfo "`t Copying Convert-windowsimage.ps1 into ToolsVHD"
|
||||
Copy-Item -Path "$PSScriptRoot\Tools\convert-windowsimage.ps1" -Destination "$PSScriptRoot\Tools\ToolsVHD\convert-windowsimage.ps1"
|
||||
Copy-Item -Path "$PSScriptRoot\ParentDisks\convert-windowsimage.ps1" -Destination "$PSScriptRoot\Temp\ToolsVHD\convert-windowsimage.ps1"
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Downloading required Posh Modules
|
||||
# Downloading modules into Tools folder if needed.
|
||||
# Downloading modules into Temp folder if needed.
|
||||
|
||||
$modules=("xActiveDirectory","2.19.0.0"),("xDHCpServer","2.0.0.0"),("xDNSServer","1.11.0.0"),("NetworkingDSC","6.0.0.0"),("xPSDesiredStateConfiguration","8.4.0.0")
|
||||
foreach ($module in $modules){
|
||||
WriteInfoHighlighted "Testing if modules are present"
|
||||
$modulename=$module[0]
|
||||
$moduleversion=$module[1]
|
||||
if (!(Test-Path "$PSScriptRoot\Tools\DSC\$modulename\$Moduleversion")){
|
||||
if (!(Test-Path "$PSScriptRoot\Temp\DSC\$modulename\$Moduleversion")){
|
||||
WriteInfo "`t Module $module not found... Downloading"
|
||||
#Install NuGET package provider
|
||||
if ((Get-PackageProvider -Name NuGet) -eq $null){
|
||||
|
@ -964,7 +231,7 @@ $exit=Read-Host
|
|||
WriteInfo "`t Module $module will be installed"
|
||||
$modulename=$module[0]
|
||||
$moduleversion=$module[1]
|
||||
Copy-item -Path "$PSScriptRoot\Tools\DSC\$modulename" -Destination "C:\Program Files\WindowsPowerShell\Modules" -Recurse -Force
|
||||
Copy-item -Path "$PSScriptRoot\Temp\DSC\$modulename" -Destination "C:\Program Files\WindowsPowerShell\Modules" -Recurse -Force
|
||||
WriteSuccess "`t Module was installed."
|
||||
Get-DscResource -Module $modulename
|
||||
} else {
|
||||
|
|
|
@ -199,7 +199,7 @@ If (!( $isAdmin )) {
|
|||
#check if VMM prereqs files are present if InstallSCVMM or SCVMM prereq is requested and tools.vhdx not present
|
||||
if (-not (Get-ChildItem -Path "$PSScriptRoot\ParentDisks" -ErrorAction SilentlyContinue).name -contains "tools.vhdx"){
|
||||
if ($LabConfig.InstallSCVMM -eq "Yes"){
|
||||
"Tools\ToolsVHD\SCVMM\ADK\ADKsetup.exe","Tools\ToolsVHD\SCVMM\SCVMM\setup.exe","Tools\ToolsVHD\SCVMM\SQL\setup.exe","Tools\ToolsVHD\SCVMM\ADK\Installers\Windows PE x86 x64-x86_en-us.msi" | ForEach-Object {
|
||||
"Temp\ToolsVHD\SCVMM\ADK\ADKsetup.exe","Temp\ToolsVHD\SCVMM\SCVMM\setup.exe","Temp\ToolsVHD\SCVMM\SQL\setup.exe","Temp\ToolsVHD\SCVMM\ADK\Installers\Windows PE x86 x64-x86_en-us.msi" | ForEach-Object {
|
||||
if(!(Test-Path -Path "$PSScriptRoot\$_")){
|
||||
WriteErrorAndExit "file $_ needed for SCVMM install not found. Exitting"
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ If (!( $isAdmin )) {
|
|||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "Prereqs"){
|
||||
"Tools\ToolsVHD\SCVMM\ADK\ADKsetup.exe","Tools\ToolsVHD\SCVMM\SQL\setup.exe","Tools\ToolsVHD\SCVMM\ADK\Installers\Windows PE x86 x64-x86_en-us.msi" | ForEach-Object {
|
||||
"Temp\ToolsVHD\SCVMM\ADK\ADKsetup.exe","Temp\ToolsVHD\SCVMM\SQL\setup.exe","Temp\ToolsVHD\SCVMM\ADK\Installers\Windows PE x86 x64-x86_en-us.msi" | ForEach-Object {
|
||||
if(!(Test-Path -Path "$PSScriptRoot\$_")){
|
||||
WriteErrorAndExit "file $_ needed for SCVMM Prereqs install not found. Exitting"
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ If (!( $isAdmin )) {
|
|||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "SQL"){
|
||||
"Tools\ToolsVHD\SCVMM\ADK\ADKsetup.exe","Tools\ToolsVHD\SCVMM\SQL\setup.exe" | ForEach-Object {
|
||||
"Temp\ToolsVHD\SCVMM\ADK\ADKsetup.exe","Temp\ToolsVHD\SCVMM\SQL\setup.exe" | ForEach-Object {
|
||||
if(!(Test-Path -Path "$PSScriptRoot\$_")){
|
||||
WriteErrorAndExit "file $_ needed for SQL install not found. Exitting"
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ If (!( $isAdmin )) {
|
|||
}
|
||||
|
||||
if ($LabConfig.InstallSCVMM -eq "ADK"){
|
||||
"Tools\ToolsVHD\SCVMM\ADK\ADKsetup.exe" | ForEach-Object {
|
||||
"Temp\ToolsVHD\SCVMM\ADK\ADKsetup.exe" | ForEach-Object {
|
||||
if(!(Test-Path -Path "$PSScriptRoot\$_")){
|
||||
WriteErrorAndExit "file $_ needed for ADK install not found. Exitting"
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ If (!( $isAdmin )) {
|
|||
}
|
||||
|
||||
#load convert-windowsimage to memory
|
||||
. "$PSScriptRoot\tools\convert-windowsimage.ps1"
|
||||
. "$PSScriptRoot\ParentDisks\convert-windowsimage.ps1"
|
||||
|
||||
#Create client OS VHD
|
||||
If ($LabConfig.CreateClientParent -eq $true){
|
||||
|
@ -536,7 +536,7 @@ If (!( $isAdmin )) {
|
|||
}
|
||||
}
|
||||
|
||||
#create Tools VHDX from .\tools\ToolsVHD
|
||||
#create Tools VHDX from .\Temp\ToolsVHD
|
||||
if (!(Test-Path "$PSScriptRoot\ParentDisks\tools.vhdx")){
|
||||
WriteInfoHighlighted "Creating Tools.vhdx"
|
||||
$toolsVHD=New-VHD -Path "$PSScriptRoot\ParentDisks\tools.vhdx" -SizeBytes 30GB -Dynamic
|
||||
|
@ -545,18 +545,18 @@ If (!( $isAdmin )) {
|
|||
$vhddisk = $VHDMount| get-disk
|
||||
$vhddiskpart = $vhddisk | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -UseMaximumSize -AssignDriveLetter |Format-Volume -FileSystem NTFS -AllocationUnitSize 8kb -NewFileSystemLabel ToolsDisk
|
||||
|
||||
$VHDPathTest=Test-Path -Path "$PSScriptRoot\Tools\ToolsVHD\"
|
||||
$VHDPathTest=Test-Path -Path "$PSScriptRoot\Temp\ToolsVHD\"
|
||||
if (!$VHDPathTest){
|
||||
New-Item -Type Directory -Path "$PSScriptRoot\Tools\ToolsVHD"
|
||||
New-Item -Type Directory -Path "$PSScriptRoot\Temp\ToolsVHD"
|
||||
}
|
||||
if ($VHDPathTest){
|
||||
WriteInfo "Found $PSScriptRoot\Tools\ToolsVHD\*, copying files into VHDX"
|
||||
Copy-Item -Path "$PSScriptRoot\Tools\ToolsVHD\*" -Destination "$($vhddiskpart.DriveLetter):\" -Recurse -Force
|
||||
WriteInfo "Found $PSScriptRoot\Temp\ToolsVHD\*, copying files into VHDX"
|
||||
Copy-Item -Path "$PSScriptRoot\Temp\ToolsVHD\*" -Destination "$($vhddiskpart.DriveLetter):\" -Recurse -Force
|
||||
}else{
|
||||
WriteInfo "Files not found"
|
||||
WriteInfoHighlighted "Add required tools into $PSScriptRoot\Tools\toolsVHD and Press any key to continue..."
|
||||
WriteInfoHighlighted "Add required tools into $PSScriptRoot\Temp\ToolsVHD and Press any key to continue..."
|
||||
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
|
||||
Copy-Item -Path "$PSScriptRoot\Tools\ToolsVHD\*" -Destination ($vhddiskpart.DriveLetter+':\') -Recurse -Force
|
||||
Copy-Item -Path "$PSScriptRoot\Temp\ToolsVHD\*" -Destination ($vhddiskpart.DriveLetter+':\') -Recurse -Force
|
||||
}
|
||||
|
||||
Dismount-VHD $vhddisk.Number
|
||||
|
@ -1092,10 +1092,10 @@ If (!( $isAdmin )) {
|
|||
WriteSuccess "Script finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
|
||||
WriteInfoHighlighted "Do you want to cleanup unnecessary files and folders?"
|
||||
WriteInfo "`t (.\Tools\ToolsVHD 1_Prereq.ps1 2_CreateParentDisks.ps1 and rename 3_deploy to just deploy)"
|
||||
WriteInfo "`t (.\Temp\ToolsVHD 1_Prereq.ps1 2_CreateParentDisks.ps1 and rename 3_deploy to just deploy)"
|
||||
If ((Read-host "`t Please type Y or N") -like "*Y"){
|
||||
WriteInfo "`t `t Cleaning unnecessary items"
|
||||
"$PSScriptRoot\Tools\ToolsVHD","$PSScriptRoot\Tools\DSC","$PSScriptRoot\1_Prereq.ps1","$PSScriptRoot\2_CreateParentDisks.ps1" | ForEach-Object {
|
||||
"$PSScriptRoot\Temp\ToolsVHD","$PSScriptRoot\Tools\DSC","$PSScriptRoot\1_Prereq.ps1","$PSScriptRoot\2_CreateParentDisks.ps1" | ForEach-Object {
|
||||
WriteInfo "`t `t `t Removing $_"
|
||||
Remove-Item -Path $_ -Force -Recurse -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
|
|
@ -1,8 +1,28 @@
|
|||
#basic config, that creates VMs for S2D Hyperconverged scenario https://github.com/Microsoft/WSLab/tree/master/Scenarios/S2D%20Hyperconverged
|
||||
#basic config for Windows Server 2016, that creates VMs for S2D Hyperconverged scenario https://github.com/Microsoft/WSLab/tree/master/Scenarios/S2D%20Hyperconverged
|
||||
|
||||
$LabConfig=@{ DomainAdminName='LabAdmin'; AdminPassword='LS1setup!'; Prefix = 'WSLab-'; SwitchName = 'LabSwitch'; DCEdition='4'; Internet=$false ; AdditionalNetworksConfig=@(); VMs=@(); ServerVHDs=@()}
|
||||
1..4 | ForEach-Object {$VMNames="S2D"; $LABConfig.VMs += @{ VMName = "$VMNames$_" ; Configuration = 'S2D' ; ParentVHD = 'Win2016Core_G2.vhdx'; SSDNumber = 0; SSDSize=800GB ; HDDNumber = 12; HDDSize= 4TB ; MemoryStartupBytes= 512MB }}
|
||||
|
||||
# Basic Windows Server 2019 Labconfig
|
||||
|
||||
<#
|
||||
|
||||
$LabConfig=@{ DomainAdminName='LabAdmin'; AdminPassword='LS1setup!'; Prefix = 'WSLab-'; SwitchName = 'LabSwitch'; DCEdition='4'; Internet=$false ; AdditionalNetworksConfig=@(); VMs=@(); ServerVHDs=@()}
|
||||
1..4 | ForEach-Object {$VMNames="S2D"; $LABConfig.VMs += @{ VMName = "$VMNames$_" ; Configuration = 'S2D' ; ParentVHD = 'Win2019Core_G2.vhdx'; SSDNumber = 0; SSDSize=800GB ; HDDNumber = 12; HDDSize= 4TB ; MemoryStartupBytes= 512MB }}
|
||||
|
||||
$LabConfig.ServerVHDs += @{
|
||||
Edition="4"
|
||||
VHDName="Win2019_G2.vhdx"
|
||||
Size=60GB
|
||||
}
|
||||
$LabConfig.ServerVHDs += @{
|
||||
Edition="3"
|
||||
VHDName="Win2019Core_G2.vhdx"
|
||||
Size=30GB
|
||||
}
|
||||
|
||||
#>
|
||||
|
||||
### HELP ###
|
||||
|
||||
#If you need more help or different configuration options, ping me at jaromirk@microsoft.com
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
# Sample SQL Install
|
||||
|
||||
# You can grab eval version here: http://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2017
|
||||
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
Start-Transcript -Path "$PSScriptRoot\SQL_Install.log"
|
||||
|
||||
$StartDateTime = get-date
|
||||
Write-host "Script started at $StartDateTime"
|
||||
|
||||
<#
|
||||
#check for .net 3.5
|
||||
if ((Get-WindowsOptionalFeature -Online -FeatureName NetFx3).State -ne 'Enabled'){
|
||||
do{
|
||||
If (Test-Path -Path "$PSScriptRoot\dotNET\microsoft-windows-netfx3-ondemand-package.cab"){
|
||||
$dotNET = Get-Item -Path "$PSScriptRoot\dotNET\microsoft-windows-netfx3-ondemand-package.cab" -ErrorAction SilentlyContinue
|
||||
Write-Host "microsoft-windows-netfx3-ondemand-package.cab found in dotNET folder... installing" -ForegroundColor Cyan
|
||||
}else{
|
||||
Write-Host "No .NET found in $PSScriptRoot\dotNET" -ForegroundColor Cyan
|
||||
Write-Host "please browse for dotNET package (microsoft-windows-netfx3-ondemand-package.cab)" -ForegroundColor Green
|
||||
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "cab files (*.cab)|*.cab|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK"){
|
||||
Write-Host "File $openfile selected" -ForegroundColor Cyan
|
||||
$dotNET = Get-Item -Path $openfile.filename -ErrorAction SilentlyContinue
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
Write-Host "CAB was not selected... Exitting" -ForegroundColor Red
|
||||
Write-Host "Press any key to continue ..."
|
||||
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
|
||||
$HOST.UI.RawUI.Flushinputbuffer()
|
||||
Exit
|
||||
}
|
||||
}
|
||||
install-windowsfeature WAS-NET-Environment -Source $dotnet.Directory
|
||||
}
|
||||
until ((Get-WindowsOptionalFeature -Online -FeatureName NetFx3).State -eq 'Enabled')
|
||||
}
|
||||
#>
|
||||
|
||||
#install SQL
|
||||
|
||||
If (Test-Path -Path "$PSScriptRoot\SQL\setup.exe"){
|
||||
$setupfile = (Get-Item -Path "$PSScriptRoot\SQL\setup.exe" -ErrorAction SilentlyContinue).fullname
|
||||
Write-Host "$Setupfile found..." -ForegroundColor Cyan
|
||||
}else{
|
||||
# Open File dialog
|
||||
Write-Host "Please locate SQL Setup.exe" -ForegroundColor Green
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "setup.exe files |setup.exe|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK")
|
||||
{
|
||||
$setupfile=$openfile.filename
|
||||
Write-Host "File $setupfile selected" -ForegroundColor Cyan
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
Write-Host "setup.exe was not selected... Exitting" -ForegroundColor Red
|
||||
Write-Host "Press any key to continue ..."
|
||||
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
|
||||
$HOST.UI.RawUI.Flushinputbuffer()
|
||||
Exit
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Installing SQL..." -ForegroundColor Green
|
||||
& $setupfile /q /ACTION=Install /FEATURES=SQLEngine /INSTANCENAME=MSSQLSERVER /SQLSVCACCOUNT="DomainNameGoesHere\SQL_SA" /SQLSVCPASSWORD="PasswordGoesHere" /SQLSYSADMINACCOUNTS="DomainNameGoesHere\Domain admins" /AGTSVCACCOUNT="DomainNameGoesHere\SQL_Agent" /AGTSVCPASSWORD="PasswordGoesHere" /TCPENABLED=1 /IACCEPTSQLSERVERLICENSETERMS /Indicateprogress /UpdateEnabled=0
|
||||
|
||||
Write-Host "Script finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
Stop-Transcript
|
||||
|
||||
Write-Host "Job Done..." -ForegroundColor Green
|
||||
Start-Sleep 5
|
||||
exit
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
#Sample ADK install
|
||||
|
||||
# You can grab ADK here: https://msdn.microsoft.com/en-us/windows/hardware/dn913721.aspx
|
||||
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
Start-Transcript -Path "$PSScriptRoot\ADK_Install.log"
|
||||
|
||||
$StartDateTime = get-date
|
||||
Write-host "Script started at $StartDateTime"
|
||||
|
||||
If (Test-Path -Path "$PSScriptRoot\ADK\ADKsetup.exe"){
|
||||
$setupfile = (Get-Item -Path "$PSScriptRoot\ADK\ADKsetup.exe" -ErrorAction SilentlyContinue).fullname
|
||||
}else{
|
||||
# Open File dialog
|
||||
Write-Host "Please locate ADKSetup.exe" -ForegroundColor Green
|
||||
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "ADKSetup.exe files |ADKSetup.exe|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK"){
|
||||
$setupfile=$openfile.filename
|
||||
Write-Host "File $setupfile selected" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Installing ADK..." -ForegroundColor Cyan
|
||||
|
||||
Write-Host "ADK Is being installed..." -ForegroundColor Cyan
|
||||
Start-Process -Wait -FilePath $setupfile -ArgumentList "/features OptionID.DeploymentTools OptionID.WindowsPreinstallationEnvironment /quiet"
|
||||
Write-Host "ADK install finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
Stop-Transcript
|
||||
Write-Host "Job Done..." -ForegroundColor Green
|
||||
Start-Sleep 5
|
||||
exit
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
# Sample VMM Install
|
||||
|
||||
# You can grab eval version here: http://www.microsoft.com/en-us/evalcenter/evaluate-system-center-technical-preview
|
||||
|
||||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
Start-Transcript -Path "$PSScriptRoot\SCVMM_Install.log"
|
||||
|
||||
$StartDateTime = get-date
|
||||
Write-host "Script started at $StartDateTime"
|
||||
|
||||
if ((get-service MSSQLServer).Status -ne "Running"){
|
||||
do{
|
||||
Write-Host "Waiting for SQL Service to start"
|
||||
Start-Sleep 10
|
||||
Start-Service -Name MSSQLServer
|
||||
}until ((get-service MSSQLServer).Status -eq "Running")
|
||||
Write-Host "SQL Service is running"
|
||||
}
|
||||
|
||||
If (Test-Path -Path "$PSScriptRoot\SCVMM\setup.exe"){
|
||||
$setupfile = (Get-Item -Path "$PSScriptRoot\SCVMM\setup.exe" -ErrorAction SilentlyContinue).fullname
|
||||
Write-Host "$Setupfile found..." -ForegroundColor Cyan
|
||||
}else{
|
||||
# Open File dialog
|
||||
Write-Host "Please locate Setup.exe" -ForegroundColor Green
|
||||
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFile.Filter = "setup.exe files |setup.exe|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK")
|
||||
{
|
||||
$setupfile=$openfile.filename
|
||||
Write-Host "File $setupfile selected" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Installing VMM..." -ForegroundColor Green
|
||||
|
||||
###Get workdirectory###
|
||||
#Install VMM
|
||||
$unattendFile = New-Item "$PSScriptRoot\VMServer.ini" -type File
|
||||
$fileContent = @"
|
||||
[OPTIONS]
|
||||
CompanyName=Contoso
|
||||
CreateNewSqlDatabase=1
|
||||
SqlInstanceName=MSSQLServer
|
||||
SqlDatabaseName=VirtualManagerDB
|
||||
SqlMachineName=DC
|
||||
VmmServiceLocalAccount=0
|
||||
LibrarySharePath=C:\ProgramData\Virtual Machine Manager Library Files
|
||||
LibraryShareName=MSSCVMMLibrary
|
||||
SQMOptIn = 1
|
||||
MUOptIn = 1
|
||||
"@
|
||||
Set-Content $unattendFile $fileContent
|
||||
|
||||
Write-Host "VMM is being installed..." -ForegroundColor Cyan
|
||||
& $setupfile /server /i /f $PSScriptRoot\VMServer.ini /IACCEPTSCEULA /VmmServiceDomain DomainNameGoesHere /VmmServiceUserName vmm_SA /VmmServiceUserPassword PasswordGoesHere
|
||||
do{
|
||||
Start-Sleep 1
|
||||
}until ((Get-Process | Where-Object {$_.Description -eq "Virtual Machine Manager Setup"} -ErrorAction SilentlyContinue) -eq $null)
|
||||
|
||||
Write-Host "VMM is Installed" -ForegroundColor Green
|
||||
|
||||
Remove-Item "$PSScriptRoot\VMServer.ini" -ErrorAction Ignore
|
||||
|
||||
Write-Host "VMM install finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
|
||||
$StartDateTime = get-date
|
||||
$URs=(Get-ChildItem -Path $PSScriptRoot\UpdateRollup -Recurse | where extension -eq .msp).FullName
|
||||
|
||||
Foreach ($UR in $URs){
|
||||
Write-Host "Update Rollup $UR is being installed"
|
||||
Start-Process -Wait -Filepath msiexec.exe -Argumentlist "/update $UR /quiet /norestart"
|
||||
}
|
||||
If ($URs){
|
||||
Write-Host "UpdateRollups install finished at $(Get-date) and took $(((get-date) - $StartDateTime).TotalMinutes) Minutes"
|
||||
}
|
||||
|
||||
Stop-Transcript
|
||||
Write-Host "Job Done..." -ForegroundColor Green
|
||||
start-sleep 5
|
||||
Exit
|
|
@ -0,0 +1,272 @@
|
|||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Start-Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
#region Functions
|
||||
|
||||
|
||||
function WriteInfo($message){
|
||||
Write-Host $message
|
||||
}
|
||||
|
||||
function WriteInfoHighlighted($message){
|
||||
Write-Host $message -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function WriteSuccess($message){
|
||||
Write-Host $message -ForegroundColor Green
|
||||
}
|
||||
|
||||
function WriteError($message){
|
||||
Write-Host $message -ForegroundColor Red
|
||||
}
|
||||
|
||||
function WriteErrorAndExit($message){
|
||||
Write-Host $message -ForegroundColor Red
|
||||
Write-Host "Press enter to continue ..."
|
||||
$exit=Read-Host
|
||||
Exit
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ask for ISO
|
||||
WriteInfoHighlighted "Please select ISO image"
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Title="Please select ISO image"
|
||||
}
|
||||
$openFile.Filter = "iso files (*.iso)|*.iso|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK"){
|
||||
WriteInfo "File $($openfile.FileName) selected"
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
WriteErrorAndExit "Iso was not selected... Exitting"
|
||||
}
|
||||
$ISO = Mount-DiskImage -ImagePath $openFile.FileName -PassThru
|
||||
|
||||
$ISOMediaPath = (Get-Volume -DiskImage $ISO).DriveLetter+':'
|
||||
|
||||
#endregion
|
||||
|
||||
#region ask for MSU packages
|
||||
WriteInfoHighlighted "Please select msu packages you want to add to image. Click cancel if you don't want any."
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$msupackages = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Multiselect = $true;
|
||||
Title="Please select msu packages you want to add to image. Click cancel if you don't want any."
|
||||
}
|
||||
$msupackages.Filter = "msu files (*.msu)|*.msu|All files (*.*)|*.*"
|
||||
If($msupackages.ShowDialog() -eq "OK"){
|
||||
WriteInfoHighlighted "Following patches selected:"
|
||||
foreach ($filename in $msupackages.FileNames){
|
||||
WriteInfo "`t $filename"
|
||||
}
|
||||
}
|
||||
|
||||
#Write info if nothing is selected
|
||||
if (!$msupackages.FileNames){
|
||||
WriteInfoHighlighted "No msu was selected..."
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region download convert-windowsimage if needed and load it
|
||||
|
||||
if (!(Test-Path "$PSScriptRoot\convert-windowsimage.ps1")){
|
||||
WriteInfo "`t Downloading Convert-WindowsImage"
|
||||
try{
|
||||
Invoke-WebRequest -UseBasicParsing -Uri https://raw.githubusercontent.com/MicrosoftDocs/Virtualization-Documentation/live/hyperv-tools/Convert-WindowsImage/Convert-WindowsImage.ps1 -OutFile "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
}catch{
|
||||
WriteErrorAndExit "`t Failed to download convert-windowsimage.ps1!"
|
||||
}
|
||||
}
|
||||
|
||||
#load convert-windowsimage
|
||||
. "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
|
||||
#endregion
|
||||
|
||||
#region do the job
|
||||
$BuildNumber=(Get-ItemProperty -Path "$ISOMediaPath\setup.exe").versioninfo.FileBuildPart
|
||||
|
||||
if ($BuildNumber -eq 14393){
|
||||
$NanoServer=(Read-Host -Prompt "Server 2016 ISO Selected. Do you want to build NanoServer? Y/N")
|
||||
}
|
||||
|
||||
if ($Nanoserver -eq "Y"){
|
||||
$WindowsImage=Get-WindowsImage -ImagePath "$ISOMediaPath\NanoServer\NanoServer.wim"
|
||||
|
||||
#ask for edition
|
||||
$Edition=($WindowsImage | Out-GridView -OutputMode Single).ImageName
|
||||
|
||||
#ask for cab files
|
||||
WriteInfoHighlighted "Please select cab packages you want to add to image. Click cancel if you want default."
|
||||
$nanocabs=(Get-ChildItem -Path "$ISOMediaPath\NanoServer\Packages" -filter *.cab| select BaseName) | Out-GridView -OutputMode Multiple
|
||||
if (!$nanocabs){
|
||||
$nanocabs="Microsoft-NanoServer-DSC-Package","Microsoft-NanoServer-FailoverCluster-Package","Microsoft-NanoServer-Guest-Package","Microsoft-NanoServer-Storage-Package","Microsoft-NanoServer-SCVMM-Package","Microsoft-NanoServer-Compute-Package","Microsoft-NanoServer-SCVMM-Compute-Package","Microsoft-NanoServer-SecureStartup-Package","Microsoft-NanoServer-DCB-Package","Microsoft-NanoServer-ShieldedVM-Package"
|
||||
}
|
||||
#grab Nano packages
|
||||
$NanoPackages=@()
|
||||
foreach ($NanoPackage in $nanocabs){
|
||||
$NanoPackages+=(Get-ChildItem -Path "$ISOMediaPath\NanoServer\Packages" -Recurse | Where-Object Name -like $NanoPackage*).FullName
|
||||
}
|
||||
WriteInfoHighlighted "Following patches selected:"
|
||||
$NanoPackages
|
||||
#create temp name
|
||||
$tempvhdname="Win2016NanoHV_G2.vhdx"
|
||||
|
||||
}else{
|
||||
$WindowsImage=Get-WindowsImage -ImagePath "$ISOMediaPath\sources\install.wim"
|
||||
if ($BuildNumber -lt 7600){
|
||||
if ($ISO -ne $Null){
|
||||
$ISO | Dismount-DiskImage
|
||||
}
|
||||
WriteErrorAndExit "`t Use Windows 7 or newer!"
|
||||
}
|
||||
#ask for edition
|
||||
$Edition=($WindowsImage | Out-GridView -OutputMode Single).ImageName
|
||||
|
||||
#Generate vhdx name
|
||||
if ($Edition -like "*Server*Core*"){
|
||||
$tempvhdname = switch ($BuildNumber){
|
||||
7600 {
|
||||
"Win2008R2Core_G1.vhdx"
|
||||
}
|
||||
7601 {
|
||||
"Win2008R2SP1Core_G1.vhdx"
|
||||
}
|
||||
9200 {
|
||||
"Win2012Core_G2.vhdx"
|
||||
}
|
||||
9600 {
|
||||
"Win2012R2Core_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win2016Core_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win2016Core_G2.vhdx"
|
||||
}
|
||||
16299 {
|
||||
"WinServer1709_G2.vhdx"
|
||||
}
|
||||
17134 {
|
||||
"WinServer1803_G2.vhdx"
|
||||
}
|
||||
17763 {
|
||||
"Win2019Core_G2.vhdx"
|
||||
}
|
||||
}
|
||||
if ($BuildNumber -GT 17763 -or $BuildNumber -eq 17744){
|
||||
$tempvhdname="Win2019Core_$BuildNumber.vhdx"
|
||||
}
|
||||
}elseif($Edition -like "*Server*"){
|
||||
$tempvhdname = switch ($BuildNumber){
|
||||
7600 {
|
||||
"Win2008R2_G1.vhdx"
|
||||
}
|
||||
7601 {
|
||||
"Win2008R2SP1_G1.vhdx"
|
||||
}
|
||||
9200 {
|
||||
"Win2012_G2.vhdx"
|
||||
}
|
||||
9600 {
|
||||
"Win2012R2_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win2016_G2.vhdx"
|
||||
}
|
||||
17763 {
|
||||
"Win2019_G2.vhdx"
|
||||
}
|
||||
}
|
||||
if ($BuildNumber -GT 17763 -or $BuildNumber -eq 17744){
|
||||
$tempvhdname="Win2019_$BuildNumber.vhdx"
|
||||
}
|
||||
}else{
|
||||
$tempvhdname = switch ($BuildNumber){
|
||||
7600 {
|
||||
"Win7_G1.vhdx"
|
||||
}
|
||||
7601 {
|
||||
"Win7SP1_G1.vhdx"
|
||||
}
|
||||
9200 {
|
||||
"Win8_G2.vhdx"
|
||||
}
|
||||
9600 {
|
||||
"Win8.1_G2.vhdx"
|
||||
}
|
||||
10240 {
|
||||
"Win10TH1_G2.vhdx"
|
||||
}
|
||||
10586 {
|
||||
"Win10TH2_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win10RS1_G2.vhdx"
|
||||
}
|
||||
14393 {
|
||||
"Win10RS1_G2.vhdx"
|
||||
}
|
||||
15064 {
|
||||
"Win10RS2_G2.vhdx"
|
||||
}
|
||||
16299 {
|
||||
"Win10RS3_G2.vhdx"
|
||||
}
|
||||
17134 {
|
||||
"Win10RS4_G2.vhdx"
|
||||
}
|
||||
17763 {
|
||||
"Win10RS5_G2.vhdx"
|
||||
}
|
||||
}
|
||||
if ($BuildNumber -GT 17763 -or $BuildNumber -eq 17744){
|
||||
$tempvhdname="Win10Insider_$BuildNumber.vhdx"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ask for imagename
|
||||
$vhdname=(Read-Host -Prompt "Please type VHD name (if nothing specified, $tempvhdname is used")
|
||||
if(!$vhdname){$vhdname=$tempvhdname}
|
||||
|
||||
#ask for size
|
||||
[int64]$size=(Read-Host -Prompt "Please type size of the Image in GB. If nothing specified, 60 is used")
|
||||
$size=$size*1GB
|
||||
if (!$size){$size=60GB}
|
||||
|
||||
#Create VHD
|
||||
if ($nanoserver -eq "y"){
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\NanoServer\NanoServer.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI -Package ($msupackages.FileNames+$NanoPackages)
|
||||
}else{
|
||||
if ($msupackages.FileNames -ne $null){
|
||||
if ($BuildNumber -le 7601){
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout BIOS -Package $msupackages.FileNames
|
||||
}else{
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI -Package $msupackages.FileNames
|
||||
}
|
||||
}else{
|
||||
if ($BuildNumber -le 7601){
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout BIOS
|
||||
}else{
|
||||
Convert-WindowsImage -SourcePath "$ISOMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WriteInfo "Dismounting ISO Image"
|
||||
if ($ISO -ne $Null){
|
||||
$ISO | Dismount-DiskImage
|
||||
}
|
||||
|
||||
WriteSuccess "Job Done. Press enter to continue..."
|
||||
$exit=Read-Host
|
||||
#endregion
|
|
@ -0,0 +1,260 @@
|
|||
# Verify Running as Admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||
If (!( $isAdmin )) {
|
||||
Write-Host "-- Restarting as Administrator" -ForegroundColor Cyan ; Start-Sleep -Seconds 1
|
||||
Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
||||
exit
|
||||
}
|
||||
|
||||
#region functions
|
||||
|
||||
function WriteInfo($message)
|
||||
{
|
||||
Write-Host $message
|
||||
}
|
||||
|
||||
function WriteInfoHighlighted($message)
|
||||
{
|
||||
Write-Host $message -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function WriteSuccess($message)
|
||||
{
|
||||
Write-Host $message -ForegroundColor Green
|
||||
}
|
||||
|
||||
function WriteError($message)
|
||||
{
|
||||
Write-Host $message -ForegroundColor Red
|
||||
}
|
||||
|
||||
function WriteErrorAndExit($message){
|
||||
Write-Host $message -ForegroundColor Red
|
||||
Write-Host "Press enter to continue ..."
|
||||
$exit=Read-Host
|
||||
Exit
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region grab variables
|
||||
#verify management tools to be able to list S2D Cluster
|
||||
if ((Get-WmiObject Win32_OperatingSystem).ProductType -ne 1){
|
||||
#Install AD PowerShell if not available
|
||||
if (-not (Get-WindowsFeature RSAT-AD-PowerShell)){
|
||||
Install-WindowsFeature RSAT-AD-PowerShell
|
||||
}
|
||||
}else{
|
||||
#detect RSAT
|
||||
if (!((Get-HotFix).hotfixid -contains "KB2693643") ){
|
||||
Write-Host "Please install RSAT, Exitting in 5s"
|
||||
Start-Sleep 5
|
||||
Exit
|
||||
}
|
||||
}
|
||||
|
||||
#Grab S2D Cluster
|
||||
WriteInfoHighlighted "Asking for S2D Cluster"
|
||||
$ClusterName=((Get-ADComputer -Filter 'serviceprincipalname -like "MSServercluster/*"').Name | ForEach-Object {get-cluster -Name $_ | Where-Object S2DEnabled -eq 1} | Out-GridView -OutputMode Single -Title "Please select your S2D Cluster(s)").Name
|
||||
|
||||
if (-not $ClusterName){
|
||||
Write-Output "No cluster was selected. Exitting"
|
||||
Start-Sleep 5
|
||||
Exit
|
||||
}
|
||||
|
||||
#Grab ClusterNodes
|
||||
$ClusterNodes=(Get-ClusterNode -Cluster $ClusterName).Name
|
||||
|
||||
#ask for Password that will be configured inside VHD
|
||||
WriteInfoHighlighted "Please provide password that will be injected as admin password into VHD"
|
||||
$AdminPassword=Read-Host
|
||||
|
||||
#Ask for VHD
|
||||
WriteInfoHighlighted "Please select VHD created by convert-windowsimage. Click cancel if you want to create it"
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Title="Please select VHD created by convert-windowsimage. Click cancel if you want to create it"
|
||||
}
|
||||
$openFile.Filter = "vhdx files (*.vhdx)|*.vhdx|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK"){
|
||||
WriteInfo "File $($openfile.FileName) selected"
|
||||
}
|
||||
$VHDPath=$openfile.FileName
|
||||
|
||||
#endregion
|
||||
|
||||
#region if VHD not selected, create one
|
||||
if (-not $VHDPath){
|
||||
#Ask for ISO
|
||||
[reflection.assembly]::loadwithpartialname("System.Windows.Forms")
|
||||
$openFile = New-Object System.Windows.Forms.OpenFileDialog -Property @{
|
||||
Title="Please select ISO image with Windows Server 2016"
|
||||
}
|
||||
$openFile.Filter = "iso files (*.iso)|*.iso|All files (*.*)|*.*"
|
||||
If($openFile.ShowDialog() -eq "OK")
|
||||
{
|
||||
WriteInfo "File $($openfile.FileName) selected"
|
||||
}
|
||||
if (!$openFile.FileName){
|
||||
WriteErrorAndExit "Iso was not selected... Exitting"
|
||||
}
|
||||
$ISOServer = Mount-DiskImage -ImagePath $openFile.FileName -PassThru
|
||||
|
||||
$ServerMediaPath = (Get-Volume -DiskImage $ISOServer).DriveLetter+':'
|
||||
|
||||
if (!(Test-Path "$PSScriptRoot\convert-windowsimage.ps1")){
|
||||
#download latest convert-windowsimage
|
||||
# Download convert-windowsimage if its not in tools folder
|
||||
WriteInfo "`t Downloading Convert-WindowsImage"
|
||||
try{
|
||||
Invoke-WebRequest -UseBasicParsing -Uri https://raw.githubusercontent.com/MicrosoftDocs/Virtualization-Documentation/live/hyperv-tools/Convert-WindowsImage/Convert-WindowsImage.ps1 -OutFile "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
}catch{
|
||||
WriteErrorAndExit "`t Failed to download convert-windowsimage.ps1!"
|
||||
}
|
||||
}
|
||||
|
||||
#load convert-windowsimage
|
||||
. "$PSScriptRoot\convert-windowsimage.ps1"
|
||||
|
||||
#ask for server edition
|
||||
$Edition=(Get-WindowsImage -ImagePath "$ServerMediaPath\sources\install.wim" | Out-GridView -OutputMode Single).ImageName
|
||||
|
||||
#ask for imagename
|
||||
$vhdname=(Read-Host -Prompt "Please type VHD name (if nothing specified, Win10_G2.vhdx is used")
|
||||
if(!$vhdname){$vhdname="Win10_G2.vhdx"}
|
||||
|
||||
#ask for size
|
||||
[int64]$size=(Read-Host -Prompt "Please type size of the Image in GB. If nothing specified, 60 is used")
|
||||
$size=$size*1GB
|
||||
if (!$size){$size=60GB}
|
||||
|
||||
#Create VHD
|
||||
Convert-WindowsImage -SourcePath "$ServerMediaPath\sources\install.wim" -Edition $Edition -VHDPath "$PSScriptRoot\$vhdname" -SizeBytes $size -VHDFormat VHDX -DiskLayout UEFI
|
||||
|
||||
WriteInfo "Dismounting ISO Image"
|
||||
if ($ISOServer -ne $Null){
|
||||
$ISOServer | Dismount-DiskImage
|
||||
}
|
||||
|
||||
$VHDPath="$PSScriptRoot\$vhdname"
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Mount VHD and apply unattend
|
||||
WriteInfoHighlighted "`t Applying Unattend"
|
||||
if (Test-Path "$PSScriptRoot\Temp\*"){
|
||||
Remove-Item -Path "$PSScriptRoot\Temp\*" -Recurse
|
||||
}
|
||||
New-item -type directory -Path $PSScriptRoot\Temp\mountdir -force
|
||||
Mount-WindowsImage -Path "$PSScriptRoot\Temp\mountdir" -ImagePath $VHDPath -Index 1
|
||||
New-item -type directory -Path "$PSScriptRoot\Temp\mountdir\Users\Administrator" -force
|
||||
New-item -type directory -Path "$PSScriptRoot\Temp\mountdir\Windows\Panther" -force
|
||||
$unattendFile = New-Item "$PSScriptRoot\Temp\mountdir\Windows\Panther\unattend.xml" -type File -Force
|
||||
$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"
|
||||
>
|
||||
</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">
|
||||
<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">
|
||||
<AutoLogon>
|
||||
<Password>
|
||||
<Value>$AdminPassword</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
<Enabled>true</Enabled>
|
||||
<LogonCount>999</LogonCount>
|
||||
<Username>administrator</Username>
|
||||
</AutoLogon>
|
||||
<UserAccounts>
|
||||
<AdministratorPassword>
|
||||
<Value>$AdminPassword</Value>
|
||||
<PlainText>true</PlainText>
|
||||
</AdministratorPassword>
|
||||
</UserAccounts>
|
||||
<OOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||
<SkipUserOOBE>true</SkipUserOOBE>
|
||||
</OOBE>
|
||||
<TimeZone>Pacific Standard Time</TimeZone>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
|
||||
"@
|
||||
Set-Content -path $unattendFile -value $fileContent -Force
|
||||
|
||||
#close VHD and apply changes
|
||||
WriteInfoHighlighted "`t Applying changes to VHD"
|
||||
Dismount-WindowsImage -Path "$PSScriptRoot\Temp\mountdir" -Save
|
||||
|
||||
#cleanup mountdir
|
||||
Remove-Item -Path "$PSScriptRoot\Temp" -Recurse
|
||||
|
||||
#endregion
|
||||
|
||||
#region create volumes
|
||||
WriteInfoHighlighted "Create Volumes"
|
||||
Foreach ($ClusterNode in $ClusterNodes){
|
||||
WriteInfo "Creating Volume $ClusterNode"
|
||||
if (-not (Get-VirtualDisk -CimSession $ClusterName -FriendlyName $ClusterNode -ErrorAction SilentlyContinue)){
|
||||
New-Volume -CimSession $ClusterName -StoragePoolFriendlyName "S2D on $ClusterName" -FriendlyName $ClusterNode -FileSystem CSVFS_ReFS -StorageTierfriendlyNames Performance -StorageTierSizes 1TB
|
||||
}
|
||||
}
|
||||
WriteInfo "Creating Volume collect"
|
||||
if (-not (Get-VirtualDisk -CimSession $ClusterName -FriendlyName "Collect" -ErrorAction SilentlyContinue)){
|
||||
New-Volume -CimSession $ClusterName -StoragePoolFriendlyName "S2D on $ClusterName" -FriendlyName collect -FileSystem CSVFS_ReFS -StorageTierFriendlyNames Performance -StorageTierSizes 1TB
|
||||
}
|
||||
|
||||
#rename CSV(s) to match name
|
||||
Get-ClusterSharedVolume -Cluster $ClusterName | % {
|
||||
$volumepath=$_.sharedvolumeinfo.friendlyvolumename
|
||||
$newname=$_.name.Substring(22,$_.name.Length-23)
|
||||
Invoke-Command -ComputerName (Get-ClusterSharedVolume -Cluster $ClusterName -Name $_.Name).ownernode -ScriptBlock {param($volumepath,$newname); Rename-Item -Path $volumepath -NewName $newname} -ArgumentList $volumepath,$newname -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
#Install Failover Clustering PowerShell on nodes
|
||||
foreach ($ClusterNode in $ClusterNodes){
|
||||
Install-WindowsFeature -Name RSAT-Clustering-PowerShell -ComputerName $ClusterNode
|
||||
}
|
||||
|
||||
#copy VMfleet and VHD to one node
|
||||
New-item -Path "\\$($ClusterNodes[0])\c$\" -Name VMFleet -Type Directory -Force
|
||||
WriteInfoHighlighted "Copying Scripts to \\$($ClusterNodes[0])\c$\VMFleet"
|
||||
Copy-Item "$PSScriptRoot\VMFleet\*" -Destination "\\$($ClusterNodes[0])\c$\VMFleet"
|
||||
WriteInfoHighlighted "Copying $VHDPath to \\$ClusterName\ClusterStorage$\Collect\FleetImage.vhdx"
|
||||
if (-not (Test-Path -Path "\\$ClusterName\ClusterStorage$\Collect\FleetImage.vhdx")){
|
||||
Copy-Item $VHDPath -Destination "\\$ClusterName\ClusterStorage$\Collect\FleetImage.vhdx"
|
||||
}
|
||||
|
||||
WriteInfoHighlighted "Run following commands from $($ClusterNodes[0])"
|
||||
"c:\VMFleet\install-vmfleet.ps1 -source C:\VMFleet"
|
||||
"Copy-Item \\DC\D$\DiskSpd\Diskspd.exe -Destination c:\ClusterStorage\Collect\Control\Tools\Diskspd.exe"
|
||||
"c:\VMFleet\create-vmfleet.ps1 -basevhd C:\ClusterStorage\Collect\FleetImage.vhdx -vms 1 -adminpass $AdminPassword -connectuser DomainNameGoesHere\Administrator -connectpass PasswordGoesHere -FixedVHD:"+'$False'
|
||||
"c:\VMFleet\set-vmfleet.ps1 -ProcessorCount 2 -MemoryStartupBytes 512MB -MemoryMinimumBytes 512MB -MemoryMaximumBytes 2GB"
|
||||
"c:\VMFleet\Start-Vmfleet.ps1"
|
||||
"c:\VMFleet\start-sweep.ps1 -b 4 -t 2 -o 40 -w 0 -d 300"
|
||||
"c:\VMFleet\watch-cluster.ps1"
|
||||
|
||||
WriteSuccess "Press enter to exit..."
|
||||
$exit=Read-Host
|
Загрузка…
Ссылка в новой задаче