Skip to content

Instantly share code, notes, and snippets.

@Pyromaniaxxx
Created April 12, 2016 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pyromaniaxxx/c762844a3361ae59c26da84d25d88bbe to your computer and use it in GitHub Desktop.
Save Pyromaniaxxx/c762844a3361ae59c26da84d25d88bbe to your computer and use it in GitHub Desktop.
Nested Azure Stack 環境を展開するためのスクリプト的な何か
<#
.DESCRIPTION
Nested Azure Stack Deployment Script
.EXAMPLE
.\Deploy-NestedAzureStack.ps1 -Verbose
.EXAMPLE
.\Deploy-NestedAzureStack.ps1 -Verbose -VMName "HostName" -Remove
.EXAMPLE
.\Deploy-NestedAzureStack.ps1 -VMName "MAS" -CPUCore 32 -RAMSize 184 -DiskSize 200 -Verbose
.INPUTS
[System.String]
[System.Int]
.NOTES
Auther : S.Hiro
Create : 2016/02/01
version: 2.0.0
スクリプトと同じフォルダに「MAS_POC_Data」フォルダを作成し
Azure Stack TP1 の解凍したデータをすべて配置する。
"Deploy Parameter" の項目を各自の環境の合わせ修正する。
#>
param
(
[CmdletBinding()]
[Parameter(Mandatory=$false)]
[String]$VMName = "MAS101",
[Parameter(Mandatory=$false)]
[int]$CPUCore = 32,
[Parameter(Mandatory=$false)]
[int]$RAMSize = 120,
[Parameter(Mandatory=$false)]
[int]$DiskSize = 200,
[Parameter(Mandatory=$false)]
[switch]$Remove ,
[Parameter(Mandatory=$false)]
[switch]$HostSetupOnlyMode
)
$Error.Clear()
$ErrorActionPreference = "Stop"
$Msg = "┏━━━━━━━━━━━━━━━━━━━━━━━┓`r`n ━╋━━┃    ┃┃           ━━┓  `r`n ┏╋┳┓┃        ┣╋┓      ━━┻┓`r`n ┃┃┃┃┃        ┃┃┃━━━ ┏━━┫`r`n ┗┻┛┛┗━━┛  ┃┃┛      ┗━━┛`r`n  ━━━╋ ╋━━       ┏┛`r`n   ┏━┫ ┃━━┓ ━━┓┏┛  `r`n   ┗━┫ ┃       ┃┗┓  `r`n    ━┛ ┃┗━━  ━┛ ┗┓`r`n Power of Azure in your datacenter!! `r`n┗━━━━━━━━━━━━━━━━━━━━━━━┛`r`n "
Write-Host $Msg -ForegroundColor Cyan 
#### Deploy Parameter ####
$DeployPath = "C:\VMData"
$DeployDataDiskPath = "D:\VMData"
$VlanID = 0
$vSwitchName = "External"
# MAS Host settings
$HostVMIP = "10.10.100.1"
$HostVMMASK = "24"
$HostVMGW = "10.10.100.250"
$HostVMDNS = "10.10.100.249"
# MAS NATVM settings
$NATVMIP = "10.10.100.11/24"
$NATVMGW = "10.10.100.250"
### credential
# MAS Host
$LoginUser = "Administrator"
$LoginPass = "password!"
# VM Password
$VMPassword = "password!"
# AAD
$AADAccount = "MASAdmin@testTenant.onmicrosoft.com"
$AADPassword = "password!"
$initializeMessage = "initialize"
Write-Progress $initializeMessage
#region ## initialize
$MasterVHDPath = $PSScriptRoot
$MasterVHDName = "AzureStackBoot.vhdx"
$mp1 = "$MasterVHDPath\MAS_POC_Data\WindowsServer2016Datacenter.vhdx"
$MasterPath = (Join-Path $MasterVHDPath $MasterVHDName)
$VMPath = (Join-Path $DeployPath $VMName)
$VMRAMSize = $RAMSize * 1GB
$VMDiskSize = $DiskSize * 1GB
$VMDiskCount = 4
$NicName = "Eth01"
$AADTenant = $AADAccount.Split('@')[1].ToString()
$Sstr = ConvertTo-SecureString $LoginPass -AsPlainText -Force
$psc = New-Object System.Management.Automation.PsCredential($LoginUser, $Sstr)
$Cred = Get-Credential -Credential $psc
$Unattend = @'
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:ms="urn:schemas-microsoft-com:asm.v3">
<settings pass="specialize">
<component name="Microsoft-Windows-Security-Licensing-SLC-UX" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64">
<SkipAutoActivation>true</SkipAutoActivation>
</component>
<component name="Microsoft-Windows-Shell-Setup" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64">
<ComputerName>SamplePOCHost</ComputerName>
</component>
<component name="Microsoft-Windows-ServerManager-SvrMgrNc" 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">
<DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>
</component>
<component name="Microsoft-Windows-IE-ESC" 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">
<IEHardenAdmin>false</IEHardenAdmin>
<IEHardenUser>false</IEHardenUser>
</component>
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" 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">
<fDenyTSConnections>false</fDenyTSConnections>
</component>
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" 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">
<UserAuthentication>0</UserAuthentication>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-Security-Licensing-SLC-UX" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64">
<SkipAutoActivation>true</SkipAutoActivation>
</component>
<component name="Microsoft-Windows-International-Core" 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">
<InputLocale>en-US</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<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">
<AutoLogon>
<Enabled>true</Enabled>
<Username>Administrator</Username>
<Domain>.</Domain>
<Password>
<Value>SampleVMPassword</Value>
<PlainText>true</PlainText>
</Password>
</AutoLogon>
<UserAccounts>
<AdministratorPassword>
<Value>SampleVMPassword</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
</UserAccounts>
<Display>
<HorizontalResolution>1024</HorizontalResolution>
<VerticalResolution>768</VerticalResolution>
</Display>
<OOBE>
<SkipMachineOOBE>true</SkipMachineOOBE>
<SkipUserOOBE>true</SkipUserOOBE>
<HideEULAPage>true</HideEULAPage>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<NetworkLocation>Other</NetworkLocation>
<ProtectYourPC>3</ProtectYourPC>
</OOBE>
<TimeZone>Pacific Standard Time</TimeZone>
<!--TODO: azure pack self-signed certificate has wrong valid time-->
</component>
</settings>
</unattend>
'@
$Unattend = $Unattend.Replace("SamplePOCHost","POCHost01")
$Unattend = $Unattend.Replace("SampleVMPassword",$VMPassword)
$DeployScript = @'
# Admin credential
$AdminSstr = ConvertTo-SecureString 'SampleVMPassword' -AsPlainText -Force
# AAD credential
$LoginUser = 'SampleAADAccount'
$LoginPass = 'SampleAADPassword'
$Sstr = ConvertTo-SecureString $LoginPass -AsPlainText -Force
$psc = New-Object System.Management.Automation.PsCredential($LoginUser, $Sstr)
$AADCred = Get-Credential -Credential $psc
C:\MAS_POC_Data\DeployAzureStack.ps1 -AdminPassword $AdminSstr -AADCredential $AADCred -AADTenant "SampleAADTenant" -NATVMStaticIP "SampleNATVMIP" -NATVMStaticGateway "SampleNATVMGW" -Verbose -Force
'@
$DeployScript = $DeployScript.Replace("SampleVMPassword",$VMPassword)
$DeployScript = $DeployScript.Replace("SampleAADAccount",$AADAccount)
$DeployScript = $DeployScript.Replace("SampleAADPassword",$AADPassword)
$DeployScript = $DeployScript.Replace("SampleAADTenant",$AADTenant)
$DeployScript = $DeployScript.Replace("SampleNATVMIP",$NATVMIP)
$DeployScript = $DeployScript.Replace("SampleNATVMGW",$NATVMGW)
#endregion
Write-Progress $initializeMessage -Completed
## remove switch process
if ($Remove)
{
Write-Host " Starting Nested Azure Stack vm remove ! " -ForegroundColor Yellow
if (@(Get-VM | Where-Object {$_.Name -eq $VMName}).Count -eq 1)
{
Stop-VM -Name $VMName -Force
Remove-VM -Name $VMName -Force -Confirm:$false
}
if (Test-Path $VMPath )
{
Remove-Item -Path $VMPath -Force -Confirm:$false -Recurse
}
Get-ChildItem $DeployDataDiskPath | Remove-Item -Force -Confirm:$false -Recurse
Write-Host " complete ! " -ForegroundColor Yellow
return $true
}
else
{
Write-Host " Starting Nested Azure Stack Deployment! " -ForegroundColor Green
}
## Master VHDX Copy
if (-not(Test-Path $MasterPath))
{
Write-Verbose -Message (" Master VHDX Copy")
Copy-Item $mp1 $MasterPath
}
#region ## pre check
Write-Verbose -Message (" pre check ")
if (@(Get-VM | Where-Object {$_.Name -eq $VMName}).Count -ne 0)
{
Write-Warning -Message "Already there is a VM with the same name."
return $false
}
if (Test-Path $VMPath )
{
Write-Warning -Message "Already folder of the same name exists."
return $false
}
$mem = Get-WmiObject -Class Win32_ComputerSystem
$totalMemory = $mem.TotalPhysicalMemory / 1GB
if ($totalMemory -lt ($RAMSize + 5 ))
{
Write-Warning -Message ("Check system memory requirement failed. At least {0}GB physical memory is required." -f ( $RAMSize + 5))
return $false
}
if ($RAMSize -lt 65)
{
$MemChkErrMsg = "`r`n Azure Stack Host に割り当てるメモリが不足しています。`r`n Azure Stack Technical Preview 1の展開には65GB以上のメモリを指定する必要があります。"
Write-Error -Message $MemChkErrMsg
return $false
}
#endregion
Write-Verbose -Message (" ----- ----- ")
Write-Verbose -Message (" VM Name : {0}" -f $VMName)
Write-Verbose -Message (" CPU Core : {0}" -f $CPUCore)
Write-Verbose -Message (" Memory : {0} ({1})" -f $RAMSize, $VMRAMSize)
Write-Verbose -Message (" Disk Size: {0} ({1})" -f $DiskSize, $VMDiskSize)
Write-Verbose -Message (" vSwitch : {0}" -f $vSwitchName)
Write-Verbose -Message (" VLAN : {0}" -f $VlanID)
Write-Verbose -Message (" VM Path : {0}" -f $DeployPath)
Write-Verbose -Message (" ----- ----- ")
$MountVHDMessage = "Mounting Nested Azure Stack HOST VHDX"
Write-Progress $MountVHDMessage
#region ## MASTER VHDX settings
Write-Progress $MountVHDMessage -Status " Mount Master VHDX" -PercentComplete 0
Dismount-DiskImage -ImagePath $MasterPath
$MountDisk = Mount-DiskImage -ImagePath $MasterPath -StorageType vhdx
$DriveLetter = (Get-DiskImage -ImagePath $MasterPath | Get-Disk | Get-Partition | Get-Volume).DriveLetter
Write-Verbose -Message (" Mounted Master VHDX")
Write-Progress $MountVHDMessage -Status " unattend.xml updating" -PercentComplete 20
$Unattend | Out-File "$DriveLetter`:\Windows\Panther\unattend.xml" -Force
Write-Verbose -Message (" unattend.xml updated")
if (-not(Test-Path "$DriveLetter`:\MAS_POC_Data"))
{
Write-Progress $MountVHDMessage -Status " Copy PoC Data" -PercentComplete 40
Copy-Item "$PSScriptRoot\MAS_POC_Data\" "$DriveLetter`:\MAS_POC_Data\" -Recurse
Write-Verbose -Message (" Copied PoC Data")
}
Write-Progress $MountVHDMessage -Status " Copy DeployStart.ps1 " -PercentComplete 60
$DeployScript | Out-File "$DriveLetter`:\MAS_POC_Data\DeployStart.ps1"
Write-Verbose -Message (" Copied DeployStart.ps1")
Write-Progress $MountVHDMessage -Status " Dismount Master VHDX" -PercentComplete 80
Dismount-DiskImage -ImagePath $MasterPath
Write-Verbose -Message (" Dismount Master VHDX")
#endregion
Write-Progress $MountVHDMessage -Completed
$NewVMMessage = "create virtual machine"
Write-Progress $NewVMMessage
#region ## create vm
Write-Progress $NewVMMessage -Status " Create Virtual Machine" -PercentComplete 0
$VM = New-VM -Name $VMName -MemoryStartupBytes $VMRAMSize -Path $DeployPath -NoVHD -Generation 2
Remove-VMNetworkAdapter -VM $VM
Write-Verbose -Message (" Created VM")
Set-VMProcessor -VM $VM -Count $CPUCore
Write-Progress $NewVMMessage -Status " Copy master VHDX" -PercentComplete 16
Copy-Item $MasterPath $VMPath
Write-Verbose -Message (" Copied master VHDX ")
Write-Progress $NewVMMessage -Status " Copy master VHDX" -PercentComplete 33
Add-VMHardDiskDrive -VM $VM -Path (Join-Path $VMPath $MasterVHDName)
Write-Verbose -Message (" Attachd master VHDX ")
Write-Progress $NewVMMessage -Status " Change Boot Device" -PercentComplete 50
Set-VMFirmware -VM $VM -FirstBootDevice (Get-VMHardDiskDrive -VM $VM)
Write-Verbose -Message (" Changed Boot Device ")
Write-Progress $NewVMMessage -Status " Add Network Adapter" -PercentComplete 66
Add-VMNetworkAdapter -VM $VM -SwitchName $vSwitchName -Name $NicName
Write-Verbose -Message (" Added a network adapter")
Write-Progress $NewVMMessage -Status " set NIC Device Naming" -PercentComplete 83
Set-VMNetworkAdapter -VM $VM -Name $NicName -DeviceNaming On
Write-Verbose -Message (" NIC Device Naming configuration ")
Write-Progress $NewVMMessage -Status " set VLAN" -PercentComplete 100
if ($VlanID -eq 0)
{
Write-Verbose -Message (" None VLAN configuration")
}
else
{
Set-VMNetworkAdapterVlan -VM $VM -VMNetworkAdapterName $NicName -VlanId $VlanID -Access
Write-Verbose -Message (" VLAN configuration : $VlanID")
}
#endregion
Write-Progress $NewVMMessage -Completed
$NewDiskMessage = "Create & Attach Data Disk"
Write-Progress $NewDiskMessage
#region ## Create & Attach Data Disk
$Disk = @{}
for ($i = 1; $i -le $VMDiskCount; $i++)
{
Write-Progress -id 2 "Create VHDX" -Status " Create $i/$VMDiskCount" -PercentComplete ((100/$VMDiskCount) * $i)
$Disk[$i] = New-VHD -Path (Join-Path $DeployDataDiskPath "MASDATA_0$i.vhdx") -SizeBytes $VMDiskSize -Fixed
Write-Verbose -Message (" Created Data Disk $i")
}
Write-Progress -id 2 "Create VHDX" -Completed
Write-Progress $NewDiskMessage -PercentComplete 50
for ($i = 1; $i -le $VMDiskCount; $i++)
{
Write-Progress -id 2 "Attach VHDX" -Status " Attach VHDX $i/$VMDiskCount" -PercentComplete ((100/$VMDiskCount) * $i)
Add-VMHardDiskDrive -VM $VM -ControllerType SCSI -Path $Disk[$i].Path
Write-Verbose -Message (" Attached Data Disk $i")
}
Write-Progress -id 2 "Attach VHDX" -Completed
#endregion
Write-Progress $NewDiskMessage -Completed
$EnableNestedVmMessage = " Enable Nest Hyper-V"
Write-Progress $EnableNestedVmMessage
Set-VMProcessor -VMName $VMName -ExposeVirtualizationExtensions $true
Set-VMNetworkAdapter -VMName $VMName -MacAddressSpoofing on
Write-Progress $EnableNestedVmMessage -Completed
$VMinitialSettingsMessage = " Start VM Initial Settings"
Write-Progress $VMinitialSettingsMessage
#region ## VM Initial Settings
Start-VM -VMName $VMName
Write-Progress $VMinitialSettingsMessage -PercentComplete 11
$SleepTime = 120
$VMBootCheckMessage = " VM boot check"
Write-Progress -Id 1 $VMBootCheckMessage -Status " Process Sleep $SleepTime Seconds"
for ($i = 1; $i -lt ($SleepTime/10); $i++)
{
sleep -Seconds ($SleepTime/10)
Write-Progress -Id 1 $VMBootCheckMessage -Status " Process Sleep $SleepTime Seconds" -PercentComplete ($i * (1000/$SleepTime))
}
Write-Progress -Id 1 $VMBootCheckMessage -Completed
Write-Verbose -Message (" boot host vm ")
Write-Progress $VMinitialSettingsMessage -Status " Invoke Get Process" -PercentComplete 22
$Proc = Invoke-Command -VMName $VMName -ScriptBlock { Get-Process | Where-Object {$_.ProcessName -like "*Sys*"} } -Credential $Cred
Write-Progress $VMinitialSettingsMessage -Status " IP address configuration" -PercentComplete 33
$ret3 = Invoke-Command -VMName $VMName -ScriptBlock { New-NetIPAddress -InterfaceAlias ((Get-NetAdapterAdvancedProperty | Where-Object {$_.DisplayValue -EQ $args[0]}).Name) -IPAddress $args[1] -PrefixLength $args[2] -DefaultGateway $args[3]} -Credential $Cred -ArgumentList $NicName,$HostVMIP,$HostVMMASK,$HostVMGW
Write-Verbose -Message (" IP address configuration")
Write-Progress $VMinitialSettingsMessage -Status " DNS configuration" -PercentComplete 44
$ret4 = Invoke-Command -VMName $VMName -ScriptBlock { Set-DnsClientServerAddress -InterfaceIndex ((Get-NetIPAddress |Where-Object {$_.Interfacealias -eq ((Get-NetAdapterAdvancedProperty | Where-Object {$_.DisplayValue -EQ $args[0]}).Name)}).InterfaceIndex) -ServerAddresses $args[1]} -Credential $Cred -ArgumentList $NicName,$HostVMDNS
Write-Verbose -Message (" DNS configuration")
Write-Progress $VMinitialSettingsMessage -Status " disable IPv6" -PercentComplete 56
$ret2 = Invoke-Command -VMName $VMName -ScriptBlock { Get-NetAdapter | ForEach-Object {Disable-NetAdapterBinding -Name $_.Name -ComponentID ms_tcpip6 }} -Credential $Cred
Write-Verbose -Message (" disable IPv6")
Write-Progress $VMinitialSettingsMessage -Status " set Admin account never Password Expires" -PercentComplete 67
$ret1 = Invoke-Command -VMName $VMName -ScriptBlock { wmic useraccount where "Name='Administrator'" Set PasswordExpires=FALSE} -Credential $Cred
Write-Verbose -Message (" set Admin account never Password Expires ")
Write-Progress $VMinitialSettingsMessage -Status " Enable Remote Desktop FirewallRules " -PercentComplete 78
$ret1 = Invoke-Command -VMName $VMName -ScriptBlock { Enable-NetFirewallRule -DisplayGroup "Remote Desktop" } -Credential $Cred
Write-Verbose -Message (" Enable Remote Desktop FirewallRules ")
Write-Progress $VMinitialSettingsMessage -Status " delete unattend.xml file" -PercentComplete 89
Invoke-Command -VMName $VMName -ScriptBlock { Remove-Item "c:\Windows\Panther\unattend.xml" -Force} -Credential $Cred
Write-Verbose -Message (" remove unattend.xml")
#endregion
Write-Progress $VMinitialSettingsMessage -Completed
Write-Verbose -Message (" starting vmconnect.exe")
vmconnect.exe localhost $VMName
if ($HostSetupOnlyMode)
{
Write-Verbose -Message (" host setup only mode")
return " Host Deploy Script complete !"
}
else
{
Write-Verbose -Message (" process sleep 10 Second...")
sleep -Seconds 10
Write-Verbose -Message (" Starting Azure Stack Deploy Script")
Invoke-Command -VMName $VMName -ScriptBlock { C:\MAS_POC_Data\DeployStart.ps1 } -Credential $Cred
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment