Skip to content

Commit

Permalink
Merge pull request #2288 from dkirby-ms/new_vi_scenario
Browse files Browse the repository at this point in the history
VI Scenario Update
  • Loading branch information
dkirby-ms authored Nov 15, 2023
2 parents 7db3365 + d774877 commit 336dc89
Show file tree
Hide file tree
Showing 11 changed files with 5,360 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
param (
[string]$adminUsername,
[string]$appId,
[string]$password,
[string]$tenantId,
[string]$subscriptionId,
[string]$location,
[string]$templateBaseUrl,
[string]$resourceGroup,
[string]$kubernetesDistribution,
[string]$videoIndexerAccountName,
[string]$videoIndexerAccountId,
[string]$rdpPort
)

[System.Environment]::SetEnvironmentVariable('adminUsername', $adminUsername,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('appId', $appId,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('password', $password,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('tenantId', $tenantId,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('resourceGroup', $resourceGroup,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('location', $location,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('subscriptionId', $subscriptionId,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('templateBaseUrl', $templateBaseUrl,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('kubernetesDistribution', $kubernetesDistribution,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('videoIndexerAccountName', $videoIndexerAccountName,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('videoIndexerAccountId', $videoIndexerAccountId,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('rdpPort', $rdpPort,[System.EnvironmentVariableTarget]::Machine)

# Create path
Write-Output "Create deployment path"
$tempDir = "C:\Temp"
New-Item -Path $tempDir -ItemType directory -Force

Start-Transcript "C:\Temp\Bootstrap.log"

$ErrorActionPreference = "SilentlyContinue"

##############################################################
# Change RDP Port
##############################################################
Write-Host "RDP port number from configuration is $rdpPort"
if (($rdpPort -ne $null) -and ($rdpPort -ne "") -and ($rdpPort -ne "3389")) {
Write-Host "Configuring RDP port number to $rdpPort"
$TSPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'
$RDPTCPpath = $TSPath + '\Winstations\RDP-Tcp'
Set-ItemProperty -Path $TSPath -name 'fDenyTSConnections' -Value 0

# RDP port
$portNumber = (Get-ItemProperty -Path $RDPTCPpath -Name 'PortNumber').PortNumber
Write-Host "Current RDP PortNumber: $portNumber"
if (!($portNumber -eq $rdpPort)) {
Write-Host Setting RDP PortNumber to $rdpPort
Set-ItemProperty -Path $RDPTCPpath -name 'PortNumber' -Value $rdpPort
Restart-Service TermService -force
}

#Setup firewall rules
if ($rdpPort -eq 3389) {
netsh advfirewall firewall set rule group="remote desktop" new Enable=Yes
}
else {
$systemroot = get-content env:systemroot
netsh advfirewall firewall add rule name="Remote Desktop - Custom Port" dir=in program=$systemroot\system32\svchost.exe service=termservice action=allow protocol=TCP localport=$RDPPort enable=yes
}

Write-Host "RDP port configuration complete."
}

# Downloading GitHub artifacts
Invoke-WebRequest ($templateBaseUrl + "artifacts/LogonScript.ps1") -OutFile "C:\Temp\LogonScript.ps1"
Invoke-WebRequest ($templateBaseUrl + "artifacts/longhorn.yaml") -OutFile "C:\Temp\longhorn.yaml"
Invoke-WebRequest ($templateBaseUrl + "artifacts/video/video.mp4") -OutFile "C:\Temp\video.mp4"
Invoke-WebRequest "https://raw.githubusercontent.com/microsoft/azure_arc/main/img/jumpstart_wallpaper.png" -OutFile "C:\Temp\wallpaper.png"
Invoke-WebRequest "https://github.com/certbot/certbot/releases/latest/download/certbot-beta-installer-win_amd64_signed.exe" -OutFile "C:\Temp\certbot-beta-installer-win_amd64_signed.exe"

##############################################################
# Install Azure CLI (64-bit not available via Chocolatey)
##############################################################
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri https://aka.ms/installazurecliwindowsx64 -OutFile .\AzureCLI.msi
Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'
Remove-Item .\AzureCLI.msi

# Installing tools
Write-Header "Installing Chocolatey Apps"
$chocolateyAppList = 'az.powershell,kubernetes-cli,kubernetes-helm,vscode'
Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'
Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'
Start-Process "C:\Temp\certbot-beta-installer-win_amd64_signed.exe" -Wait -ArgumentList '/S'

try {
choco config get cacheLocation
}
catch {
Write-Output "Chocolatey not detected, trying to install now"
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
}

Write-Host "Chocolatey Apps Specified"

$appsToInstall = $chocolateyAppList -split "," | ForEach-Object { "$($_.Trim())" }

foreach ($app in $appsToInstall)
{
Write-Host "Installing $app"
& choco install $app /y -Force | Write-Output
}

# Enable VirtualMachinePlatform feature, the vm reboot will be done in DSC extension
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart

# Disable Microsoft Edge sidebar
$RegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Edge'
$Name = 'HubsSidebarEnabled'
$Value = '00000000'
# Create the key if it does not exist
If (-NOT (Test-Path $RegistryPath)) {
New-Item -Path $RegistryPath -Force | Out-Null
}
New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

# Disable Microsoft Edge first-run Welcome screen
$RegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Edge'
$Name = 'HideFirstRunExperience'
$Value = '00000001'
# Create the key if it does not exist
If (-NOT (Test-Path $RegistryPath)) {
New-Item -Path $RegistryPath -Force | Out-Null
}
New-ItemProperty -Path $RegistryPath -Name $Name -Value $Value -PropertyType DWORD -Force

# Creating scheduled task for LogonScript.ps1
$Trigger = New-ScheduledTaskTrigger -AtLogOn
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument 'C:\Temp\LogonScript.ps1'
Register-ScheduledTask -TaskName "LogonScript" -Trigger $Trigger -User $adminUsername -Action $Action -RunLevel "Highest" -Force

# Disabling Windows Server Manager Scheduled Task
Get-ScheduledTask -TaskName ServerManager | Disable-ScheduledTask

# Install Hyper-V and reboot
Write-Host "Installing Hyper-V and restart"
Enable-WindowsOptionalFeature -Online -FeatureName Containers -All -NoRestart
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart
Install-WindowsFeature -Name Hyper-V -IncludeAllSubFeature -IncludeManagementTools -Restart

# Clean up Bootstrap.log
Stop-Transcript
$logSuppress = Get-Content C:\Temp\Bootstrap.log | Where-Object { $_ -notmatch "Host Application: powershell.exe" }
$logSuppress | Set-Content C:\Temp\Bootstrap.log -Force
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
Start-Transcript -Path C:\Temp\LogonScript.log

Set-ExecutionPolicy Bypass -Scope Process -Force

# Parameters
$schemaVersionAksEdgeConfig = "1.9"
$versionAksEdgeConfig = "1.0"
$guid = ([System.Guid]::NewGuid()).ToString().subString(0,5).ToLower()
$clusterName = "$Env:resourceGroup-$guid"

# Configure AKS disk
$storagePoolName = "AKS"
$diskName = "AKSData"
$disks = Get-Disk | Where-Object partitionStyle -eq "raw" | Get-PhysicalDisk
$storageName = Get-StorageSubsystem | Select-Object -expand FriendlyName
New-StoragePool -FriendlyName $storagePoolName -StorageSubSystemFriendlyName $storageName -PhysicalDisks $disks
New-VirtualDisk -StoragePoolFriendlyName $storagePoolName -FriendlyName $diskName -Size (500GB) -ResiliencySettingName Simple
Get-VirtualDisk -FriendlyName $diskName | Get-Disk | Initialize-Disk -Passthru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -NewFileSystemLabel $diskName

# Install AKS EE
$letter = Get-Volume | Where-Object FileSystemLabel -eq $diskName
$installPath = "$($letter.DriveLetter):\AKSEdge"
New-Item -Path $installPath -ItemType Directory
$aksEEk3sUrl = 'https://aka.ms/aks-edge/k3s-msi'
$tempDir = "C:\Temp"
$ProgressPreference = "SilentlyContinue"
Invoke-WebRequest $aksEEk3sUrl -OutFile $tempDir\AKSEEK3s.msi
msiexec.exe /i $tempDir\AKSEEK3s.msi INSTALLDIR=$installPath /q /passive
Start-Sleep 45

Import-Module AksEdge
Get-Command -Module AKSEdge | Format-Table Name, Version

# Here string for the json content
$aksedgeConfig = @"
{
"SchemaVersion": "$schemaVersionAksEdgeConfig",
"Version": "$versionAksEdgeConfig",
"DeploymentType": "SingleMachineCluster",
"Init": {
"ServiceIPRangeSize": 30
},
"Network": {
"NetworkPlugin": "$networkplugin",
"InternetDisabled": false
},
"User": {
"AcceptEula": true,
"AcceptOptionalTelemetry": true
},
"Arc": {
"ClusterName": "$clusterName",
"Location": "${env:location}",
"ResourceGroupName": "${env:resourceGroup}",
"SubscriptionId": "${env:subscriptionId}",
"TenantId": "${env:tenantId}",
"ClientId": "${env:appId}",
"ClientSecret": "${env:password}"
},
"Machines": [
{
"LinuxNode": {
"CpuCount": 12,
"MemoryInMB": 50000,
"DataSizeInGB": 300
}
}
]
}
"@

Set-Content -Path $tempDir\aksedge-config.json -Value $aksedgeConfig -Force

New-AksEdgeDeployment -JsonConfigFilePath $tempDir\aksedge-config.json

Write-Host "`n"
Write-Host "Checking kubernetes nodes"
Write-Host "`n"
kubectl get nodes -o wide
Write-Host "`n"

# az version
az -v

# Login as service principal
az login --service-principal --username $Env:appId --password $Env:password --tenant $Env:tenantId

# Set default subscription to run commands against
# "subscriptionId" value comes from clientVM.json ARM template, based on which
# subscription user deployed ARM template to. This is needed in case Service
# Principal has access to multiple subscriptions, which can break the automation logic
az account set --subscription $Env:subscriptionId

# Installing Azure CLI extensions
az config set extension.use_dynamic_install=yes_without_prompt
Write-Host "`n"
Write-Host "Installing Azure CLI extensions"
# az extension add --name connectedk8s --version 1.3.17
az extension add --name k8s-extension
Write-Host "`n"

# Registering Azure Arc providers
Write-Host "Registering Azure Arc providers, hold tight..."
Write-Host "`n"
az provider register --namespace Microsoft.Kubernetes --wait
az provider register --namespace Microsoft.KubernetesConfiguration --wait
az provider register --namespace Microsoft.HybridCompute --wait
az provider register --namespace Microsoft.GuestConfiguration --wait
az provider register --namespace Microsoft.HybridConnectivity --wait
az provider register --namespace Microsoft.ExtendedLocation --wait

az provider show --namespace Microsoft.Kubernetes -o table
Write-Host "`n"
az provider show --namespace Microsoft.KubernetesConfiguration -o table
Write-Host "`n"
az provider show --namespace Microsoft.HybridCompute -o table
Write-Host "`n"
az provider show --namespace Microsoft.GuestConfiguration -o table
Write-Host "`n"
az provider show --namespace Microsoft.HybridConnectivity -o table
Write-Host "`n"
az provider show --namespace Microsoft.ExtendedLocation -o table
Write-Host "`n"

# Onboarding the cluster to Azure Arc
Write-Host "Onboarding the AKS Edge Essentials cluster to Azure Arc..."
Write-Host "`n"

$kubectlMonShell = Start-Process -PassThru PowerShell { for (0 -lt 1) { kubectl get pod -A; Start-Sleep -Seconds 5; Clear-Host } }

# Connect Arc-enabled kubernetes
Connect-AksEdgeArc -JsonConfigFilePath $tempDir\aksedge-config.json

#####################################################################
### Install ingress-nginx
#####################################################################
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx

#####################################################################
### Longhorn setup for RWX-capable storage class
#####################################################################
Write-Host "Creating longhorn storage on AKS EE cluster."
kubectl apply -f c:\temp\longhorn.yaml
Start-Sleep -Seconds 30

#####################################################################
### Video Indexer setup
#####################################################################
$viApiVersion="2023-06-02-preview"
$extensionName="videoindexer"
#$version="1.0.28-preview" # switch to blank
$namespace="video-indexer"
$releaseTrain="release" # switch to release
$storageClass="longhorn"

Write-Host "Create Cognitive Services on VI resource provider"
$createResourceUri = "https://management.azure.com/subscriptions/${env:subscriptionId}/resourceGroups/${env:resourceGroup}/providers/Microsoft.VideoIndexer/accounts/${env:videoIndexerAccountName}/CreateExtensionDependencies?api-version=${viApiVersion}"
$result = $(az rest --method post --uri $createResourceUri) | ConvertFrom-Json

Write-Host "Retrieving Cognitive Service Credentials..."
$getSecretsUri="https://management.azure.com/subscriptions/${env:subscriptionId}/resourceGroups/${env:resourceGroup}/providers/Microsoft.VideoIndexer/accounts/${env:videoIndexerAccountName}/ListExtensionDependenciesData?api-version=$viApiVersion"
$csResourcesData=$(az rest --method post --uri $getSecretsUri) | ConvertFrom-Json
Write-Host

Write-Host "Getting VM public IP address..."
$hostname = hostname
$ipAddresses = az vm list-ip-addresses -g $env:resourceGroup -n $hostname | ConvertFrom-Json
$ipAddress = $ipAddresses.virtualMachine.network.publicIpAddresses[0].ipAddress

Write-Host "Installing Video Indexer extension into AKS EE cluster."
az k8s-extension create --name $extensionName `
--extension-type Microsoft.VideoIndexer `
--scope cluster `
--release-namespace $namespace `
--cluster-name $clusterName `
--resource-group $Env:resourceGroup `
--cluster-type connectedClusters `
--release-train $releaseTrain `
--auto-upgrade-minor-version false `
--config-protected-settings "speech.endpointUri=$($csResourcesData.speechCognitiveServicesEndpoint)" `
--config-protected-settings "speech.secret=$($csResourcesData.speechCognitiveServicesPrimaryKey)" `
--config-protected-settings "translate.endpointUri=$($csResourcesData.translatorCognitiveServicesEndpoint)" `
--config-protected-settings "translate.secret=$($csResourcesData.translatorCognitiveServicesPrimaryKey)" `
--config "videoIndexer.accountId=${Env:videoIndexerAccountId}" `
--config "frontend.endpointUri=https://$ipAddress" `
--config "storage.storageClass=$storageClass" `
--config "storage.accessMode=ReadWriteMany"

# Allow access to the frontend through the VM NIC interface
Write-Host "Adding Windows Defender firewall rule for VI frontend..."
New-NetFirewallRule -DisplayName "Allow Inbound Port 80" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow
New-NetFirewallRule -DisplayName "Allow Inbound Port 443" -Direction Inbound -LocalPort 443 -Protocol TCP -Action Allow

Write-Host "Adding port forward for VI frontend..."
Start-Sleep -Seconds 20
$ing = kubectl get ing videoindexer-vi-arc -n $namespace -o json | ConvertFrom-Json
$ingIp = $ing.status.loadBalancer.ingress.ip
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=80 connectaddress=$ingIp connectport=80
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=443 connectaddress=$ingIp connectport=443

# Kill the open PowerShell monitoring kubectl get pods
Stop-Process -Id $kubectlMonShell.Id

# Install Postman
choco install postman /y -Force

# Removing the LogonScript Scheduled Task so it won't run on next reboot
Unregister-ScheduledTask -TaskName "LogonScript" -Confirm:$false
Start-Sleep -Seconds 5
$ProgressPreference = "Continue"

# Changing to Client VM wallpaper
$imgPath = "C:\Temp\wallpaper.png"
$code = @'
using System.Runtime.InteropServices;
namespace Win32{
public class Wallpaper{
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern int SystemParametersInfo (int uAction , int uParam , string lpvParam , int fuWinIni) ;
public static void SetWallpaper(string thePath){
SystemParametersInfo(20,0,thePath,3);
}
}
}
'@

add-type $code
[Win32.Wallpaper]::SetWallpaper($imgPath)
Stop-Process -Name powershell -Force

Stop-Transcript
Loading

0 comments on commit 336dc89

Please sign in to comment.