From df79461986a0a1e5e2d18ec8e6bc61f73dc1d58a Mon Sep 17 00:00:00 2001 From: "Alexander (Sasha) Nosov" Date: Fri, 5 Jul 2024 17:05:23 -0700 Subject: [PATCH] Modified to remove downloading the image file --- .../install-payg-sql-server.ps1 | 186 ++++++++++++------ 1 file changed, 131 insertions(+), 55 deletions(-) diff --git a/samples/manage/azure-arc-enabled-sql-server/install-payg-sql-server/install-payg-sql-server.ps1 b/samples/manage/azure-arc-enabled-sql-server/install-payg-sql-server/install-payg-sql-server.ps1 index 4bb0bddf..7f78eda0 100644 --- a/samples/manage/azure-arc-enabled-sql-server/install-payg-sql-server/install-payg-sql-server.ps1 +++ b/samples/manage/azure-arc-enabled-sql-server/install-payg-sql-server/install-payg-sql-server.ps1 @@ -2,7 +2,7 @@ param ( [Parameter (Mandatory=$true)] [string]$AzureSubscriptionId, [Parameter (Mandatory=$true)] - [string]$AzureResourceGroupUri, + [string]$AzureResourceGroup, [Parameter (Mandatory=$true)] [string]$AzureRegion, [Parameter (Mandatory=$false)] @@ -16,7 +16,9 @@ param ( [Parameter (Mandatory=$true)] [string]$SqlServerEdition, [Parameter (Mandatory=$true)] - [string]$isoFolder + [string]$IsoFolder, + [Parameter (Mandatory=$false)] + [string]$Proxy ) # This function checks if the specified module is imported into the session and if not installes and/or imports it @@ -49,7 +51,7 @@ function LoadModule # If module is not imported, not available on disk, but is in online gallery then install and import if (Find-Module -Name $name) { - Install-Module -Name $name -Force -Verbose -Scope CurrentUser + Install-Module -Name $name -Force -Scope CurrentUser try { Import-Module $name -ErrorAction SilentlyContinue @@ -75,7 +77,8 @@ function LoadModule try { - #Step 0: Ensure PS version and load missing Azure modules + write-host "==== Ensure PS version and load missing Azure modules ====" + # # Suppress warnings # @@ -89,41 +92,55 @@ try { "Az.ResourceGraph" ) $requiredModules | Foreach-Object {LoadModule $_} + + write-host "==== Check if setup.exe is already running and kill it if so ====" - # Step 1: Check if setup.exe is already running and kill it if so if (Get-Process setup -ErrorAction SilentlyContinue) { Stop-Process -Name setup -Force Write-Host "Existing setup.exe process terminated." } - # Step 2: Log in to Azure - Connect-AzAccount + write-host "==== Log in to Azure ====" + + Connect-AzAccount | Out-Null $subscription = Get-AzSubscription -SubscriptionId $AzureSubscriptionId -ErrorAction SilentlyContinue if (-not $subscription) { Write-Error "Azure subscription with ID '$AzureSubscriptionId' does not exist." exit } + Set-AzContext -Subscription $AzureSubscriptionId | Out-Null - # Step 2: Block auto-onboarding to Arc by tagging the resource group - $existingResourceGroup = Get-AzResourceGroup -Name $AzureResourceGroupUri -ErrorAction SilentlyContinue + write-host "==== Block auto-onboarding to Arc ====" + + $existingResourceGroup = Get-AzResourceGroup -Name $AzureResourceGroup -ErrorAction SilentlyContinue if ($existingResourceGroup) { - Write-Host "Resource group '$AzureResourceGroupUri' exists." + $tags = @{"ArcOnboarding" = "Blocked"} + Set-AzResourceGroup -Name $AzureResourceGroup -Tag $tags | Out-Null } else { - Write-Error "Resource group '$AzureResourceGroupUri' does not exist." + Write-Error "Resource group '$AzureResourceGroup' does not exist." exit } - $tags = @{"ArcOnboarding" = "Blocked"} - Set-AzResourceGroup -Name $AzureResourceGroupUri -Tag $tags - # Step 3: Onboard the VM to Azure Arc - $hostName = (Get-WmiObject Win32_ComputerSystem).Name + write-host "==== Mount the ISO file as a volume ====" - New-AzConnectedMachine -ResourceGroupName $AzureResourceGroupUri -Name $hostName -Location $AzureRegion + $isoFiles = Get-ChildItem $IsoFolder -Filter "*.iso" - # Step 4: Retrieve the product key + foreach ($isoFile in $isoFiles) { + # Mount the ISO file + $imagePath = $isoFile.FullName + $mountResult = Mount-DiskImage -ImagePath $imagePath + $driveLetter = ($mountResult | Get-Volume).DriveLetter + Write-Host "ISO file $($isoFile.Name) mounted as drive $($driveLetter):" + break + } + + + write-host "==== Run unattended SQL Server setup from the mounted volume ====" + + # Retrieve the product key - $keyFiles = Get-ChildItem $isoFolder -Filter "*.txt" + $keyFiles = Get-ChildItem $IsoFolder -Filter "*.txt" foreach ($keyFile in $keyFiles) { # Read each line from the file @@ -133,25 +150,12 @@ try { $productKey = [regex]::Match($_, '[A-Z0-9]{5,}-[A-Z0-9]{5,}-[A-Z0-9]{5,}-[A-Z0-9]{5,}-[A-Z0-9]{5,}.*').Value # Strip any text after the product key $productKey = $productKey -replace " .*$" - Write-Host "Found product key in $($keyFile.Name): $productKey" } } } - # Step 5: Mount the ISO file as a volume - $isoFiles = Get-ChildItem $isoFolder -Filter "*.iso" + # Launch setup - foreach ($isoFile in $isoFiles) { - # Mount the ISO file - $mountResult = Mount-DiskImage -ImagePath $isoFile.FullName - $driveLetter = ($mountResult | Get-Volume).DriveLetter - $mountedIsoFile = $isoFile - Write-Host "ISO file $($isoFile.Name) mounted as drive $driveLetter" - break - } - - - # Step 6: Run unattended SQL Server setup from the mounted volume $setupPath = ($driveLetter + ":\setup.exe") $argumentList = " /q @@ -172,45 +176,117 @@ try { } Start-Process -FilePath $setupPath -ArgumentList $argumentList + + write-host "==== Dismount the ISO file after installation ====" - # Step 7: Install SQL Arc extension with LT=PAYG + Dismount-DiskImage -ImagePath $imagePath | Out-Null + + write-host "==== Onboard the VM to Azure Arc ====" + + $hostName = (Get-WmiObject Win32_ComputerSystem).Name + + if ($Proxy) { + Connect-AzConnectedMachine -ResourceGroupName $AzureResourceGroup -Name $hostName -Location $AzureRegion -Proxi $Proxy | Out-Null + } else { + Connect-AzConnectedMachine -ResourceGroupName $AzureResourceGroup -Name $hostName -Location $AzureRegion | Out-Null + } + + write-host "==== Install SQL Arc extension with LT=PAYG and upgrade to the latest version ====" + + $extensionName = "WindowsAgent.SqlServer" $Settings = @{ SqlManagement = @{ IsEnabled = $true }; LicenseType = "PAYG"; enableExtendedSecurityUpdates = $True; esuLastUpdatedTimestamp = [DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') } - New-AzConnectedMachineExtension -ResourceGroupName $AzureResourceGroupUri -MachineName $hostName -Name "WindowsAgent.SqlServer" -Publisher "Microsoft.AzureData" -Type "WindowsAgent.SqlServer" -TypeHandlerVersion "1.0" -Settings $settings + New-AzConnectedMachineExtension -ResourceGroupName $AzureResourceGroup -MachineName $hostName -Name "Microsoft.AzureData" -Publisher "Microsoft.AzureData" -ExtensionType "WindowsAgent.SqlServer" -Location $AzureRegion -Settings $Settings -EnableAutomaticUpgrade - # Step 8: Dismount the ISO file after installation - Dismount-DiskImage -ImagePath $isoFolder + $mountedIsoFile + # Step 10: Display the status of the Azure resource for Arc-enabled SQL Server + write-host "==== Display the status of the billable Arc-enabled host ====" - # Step 9: Display the status of the Azure resource for Arc-enabled SQL Server $query = " resources - | where type =~ 'microsoft.hybridcompute/machines' - | where resourceGroup =~ '$($AzureResourceGroupUri)' - | where properties.detectedProperties.mssqldiscovered == 'true' - | extend machineIdHasSQLServerDiscovered = id - | project name, machineIdHasSQLServerDiscovered, resourceGroup, subscriptionId - | join kind= leftouter ( - resources - | where type == 'microsoft.hybridcompute/machines/extensions' | where properties.type in ('WindowsAgent.SqlServer','LinuxAgent.SqlServer') - | extend machineIdHasSQLServerExtensionInstalled = iff(id contains '/extensions/WindowsAgent.SqlServer' or id contains '/extensions/LinuxAgent.SqlServer', substring(id, 0, indexof(id, '/extensions/')), '') - | project Extension_State = properties.provisioningState, - License_Type = properties.settings.LicenseType, - ESU = iff(notnull(properties.settings.enableExtendedSecurityUpdates), iff(properties.settings.enableExtendedSecurityUpdates == true,'enabled','disabled'), ''), - Extension_Version = properties.instanceView.typeHandlerVersion, - machineIdHasSQLServerExtensionInstalled)on $left.machineIdHasSQLServerDiscovered == $right.machineIdHasSQLServerExtensionInstalled - | where isnotempty(machineIdHasSQLServerExtensionInstalled) - | project-away machineIdHasSQLServerDiscovered, machineIdHasSQLServerExtensionInstalled + | where type =~ 'Microsoft.HybridCompute/machines' + | where subscriptionId =~ '$($AzureSubscriptionId)' + | where resourceGroup =~ '$($AzureResourceGroup)' + | extend status = tostring(properties.status) + | where status =~ 'Connected' + | extend machineID = tolower(id) + | extend VMbyManufacturer = toboolean(iff(properties.detectedProperties.manufacturer in ( + 'VMware', + 'QEMU', + 'Amazon EC2', + 'OpenStack', + 'Hetzner', + 'Mission Critical Cloud', + 'DigitalOcean', + 'UpCloud', + 'oVirt', + 'Alibaba', + 'KubeVirt', + 'Parallels', + 'XEN' + ), 1, 0)) + | extend VMbyModel = toboolean(iff(properties.detectedProperties.model in ( + 'OpenStack', + 'Droplet', + 'oVirt', + 'Hypervisor', + 'Virtual', + 'BHYVE', + 'KVM' + ), 1, 0)) + | extend GoogleVM = toboolean(iff((properties.detectedProperties.manufacturer =~ 'Google') and (properties.detectedProperties.model =~ 'Google Compute Engine'), 1, 0)) + | extend NutanixVM = toboolean(iff((properties.detectedProperties.manufacturer =~ 'Nutanix') and (properties.detectedProperties.model =~ 'AHV'), 1, 0)) + | extend MicrosoftVM = toboolean(iff((properties.detectedProperties.manufacturer =~ 'Microsoft Corporation') and (properties.detectedProperties.model =~ 'Virtual Machine'), 1, 0)) + | extend billableCores = iff(VMbyManufacturer or VMbyModel or GoogleVM or NutanixVM or MicrosoftVM, properties.detectedProperties.logicalCoreCount, properties.detectedProperties.coreCount) + | join kind = leftouter // Join Extension + ( + resources + | where type =~ 'Microsoft.HybridCompute/machines/extensions' + | where name == 'WindowsAgent.SqlServer' or name == 'LinuxAgent.SqlServer' + | extend extMachineID = substring(id, 0, indexof(id, '/extensions')) + | extend extensionId = id + ) + on `$left.id == `$right.extMachineID + | join kind = inner // Join SQL Arc + ( + resources + | where type =~ 'microsoft.azurearcdata/sqlserverinstances' + | extend sqlVersion = tostring(properties.version) + | extend sqlEdition = tostring(properties.edition) + | extend is_Enterprise = toint(iff(sqlEdition == 'Enterprise', 1, 0)) + | extend sqlStatus = tostring(properties.status) + | extend licenseType = tostring(properties.licenseType) + | where sqlEdition in ('Enterprise', 'Standard') + | where licenseType !~ 'HADR' + | where sqlStatus =~ 'Connected' + | extend ArcServer = tolower(tostring(properties.containerResourceId)) + | order by sqlEdition + ) + on `$left.machineID == `$right.ArcServer + | where isnotnull(extensionId) + | summarize Edition = iff(sum(is_Enterprise) > 0, 'Enterprise', 'Standard') by machineID + , name + , resourceGroup + , subscriptionId + , Model = tostring(properties.detectedProperties.model) + , Manufacturer = tostring(properties.detectedProperties.manufacturer) + , License_Type = tostring(properties1.settings.LicenseType) + , OS = tostring(properties.osName) + , Uses_UV = tostring(properties1.settings.UsePhysicalCoreLicense.IsApplied) + , Cores = tostring(billableCores) + , Version = sqlVersion + | project-away machineID + | order by Edition, name asc " - Search-AzGraph -Query "$($query)" + Search-AzGraph -Query $query } catch { Write-Error "An error occurred: $_" # You can add additional error handling logic here } finally { # Cleanup or other actions that should always run - Write-Host "Script execution completed." + Write-Host "==== Installation completed ====" }