Private/Start-CustomVMUpdate.ps1
# Will be called in VM function Global:Start-CustomVMUpdate { [CmdletBinding()] <# .SYNOPSIS ... Parameters for Commands Command | Parameter 1 | Parameter 2 | JoinDomain | none | none | CreateInstances | Typefilter (e.g. "TEST") [x] | "RestartService" [ ] | UpdateInstanceConfiguration | Typefilter (e.g. "TEST") [x] | "RestartService" [ ] | UpdateLicense | URI to Licensefile [x] | "RestartService" [ ] | ... .DESCRIPTION ... #> param( [Parameter(Mandatory = $true, Position = 1)] [string] $ObjectName, [Parameter(Mandatory = $false, Position = 2)] [switch] $IsScaleSet, [Parameter(Mandatory = $true, Position = 3)] [string] $ResourceGroupName, [Parameter(Mandatory = $true, Position = 4)] [string] $StorageAccountName, [Parameter(Mandatory = $true, Position = 5)] [string] $KeyVaultName, [Parameter(Mandatory = $true, Position = 6)] [string] $StorageTableNameSetup, [Parameter(Mandatory = $true, Position = 7)] [string] $StorageTableNameEnvironments, [Parameter(Mandatory = $true, Position = 8)] [string] $StorageTableNameEnvironmentDefaults, [Parameter(Mandatory = $true, Position = 9)] [string] $StorageTableNameInfrastructureData ) process { Write-Host "Starting auto update..." # Uses managed identity to connect to Azure Account Connect-FromMachineToAzAccount Write-Host "Loading pending commands..." $storageAccount = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName $storageAccountContext = $storageAccount.Context $storageAccountTable = Get-AzStorageTable -Name $StorageTableNameSetup -Context $storageAccountContext.Context $cloudTable = $storageAccountTable.CloudTable $rows = Get-AzTableRow -Table $cloudTable | Where-Object { ($_.ExecutedBy -notlike "*$env:computername*") -and (($_.ObjectName -eq 'NULL') -or ($_.ObjectName -eq $ObjectName)) } foreach ($row in $rows) { Write-Host "Handling Command: $($row.Command)" switch ($row.Command) { # This command is not really used anymore; was in the beginning, but now it's done via a VM Extension 'JoinDomain' { if ((Get-WmiObject win32_computersystem).partofdomain -eq $false) { Write-Host "Loading credentials..." # Load Admin Credentials from KeyVault $adminUserName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminUsername').SecretValueText $adminUserPass = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminPassword').SecretValueText $domainName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainName').SecretValueText $adminUserName = "$domainName\$adminUserName" $domainAdminCredentials = New-Object System.Management.Automation.PSCredential ($adminUserName, (ConvertTo-SecureString -String $adminUserPass -AsPlainText -Force)) if ($row.RestartNecessary -eq $true) { # Update Command Table, because machine will be restartet in a moment Set-StorageCommandExecuted -CommandRow $row -ExecutedByName $env:computername } Add-Computer -DomainName $domainName -Credential $domainAdminCredentials -Restart -Force | Out-Null } else { Write-Host "Machine is already part of domain." } } 'CreateInstances' { Write-Host "Importing Cloud.Ready.Software.NAV..." Import-Module Cloud.Ready.Software.NAV -Force Write-Host "Importing NAV Modules..." Import-NAVModules $environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableNameEnvironments $StorageTableNameEnvironments -TableNameDefaults $StorageTableNameEnvironmentDefaults -TypeFilter $row.Parameter1 -ConfigType Application foreach ($environment in $environments) { if (-not (Get-NavServerInstance -ServerInstance $environment.ServerInstance)) { Write-Host "Creating instance: $($environment.ServerInstance)" New-NAVServerInstance $environment.ServerInstance ` -DatabaseServer $environment.DatabaseServer ` -DatabaseInstance $environment.DatabaseInstance ` -Databasename $environment.Databasename ` -ClientServicesPort $environment.ClientServicesPort ` -ManagementServicesPort $environment.ManagementServicesPort ` -SOAPServicesPort $environment.SoapServicesPort ` -ODataServicesPort $environment.OdataServicesPort Write-Host "Changing port-configuration..." Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName DeveloperServicesPort -KeyValue $environment.DeveloperServicesPort Write-Host "Updating authentication-method..." Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName ClientServicesCredentialType -KeyValue $environment.Authentication Write-Host "Updating service-account..." $adminUserName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminUsername').SecretValueText $adminUserPass = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminPassword').SecretValueText $domainName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainName').SecretValueText $adminUserName = "$domainName\$adminUserName" # TODO: Switch to different user (create setup?) $credentialsObject = New-Object System.Management.Automation.PSCredential ($adminUserName, (ConvertTo-SecureString $adminUserPass -AsPlainText -Force)) Set-NAVServerInstance -ServerInstance $environment.ServerInstance -ServiceAccount User -ServiceAccountCredential $credentialsObject foreach ($key in $environment.Settings.Keys) { if ((-not([string]::IsNullOrEmpty($key))) -and (-not([string]::IsNullOrEmpty($environment.Settings[$key])))) { Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName $key -KeyValue $environment.Settings[$key] } } if ($row.Parameter2 -eq "RestartService") { Write-Host "Restarting service" Restart-NAVServerInstance -ServerInstance $environment.ServerInstance } } } } 'UpdateInstanceConfiguration' { Write-Host "Importing Cloud.Ready.Software.NAV..." Import-Module Cloud.Ready.Software.NAV -Force Write-Host "Importing NAV Modules..." Import-NAVModules $environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableNameEnvironments $StorageTableNameEnvironments -TableNameDefaults $StorageTableNameEnvironmentDefaults -TypeFilter $row.Parameter1 -ConfigType Application foreach ($environment in $environments) { if (Get-NavServerInstance -ServerInstance $environment.ServerInstance) { $config = Get-NAVServerConfiguration -ServerInstance $environment.ServerInstance # Convert Result to HashTable $currentConf = @{ } $config | ForEach-Object { $currentConf[$_.key] = $_.value } $updated = $false $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName DeveloperServicesPort -KeyValue $environment.DeveloperServicesPort -CurrentConfiguration $config -Verbose) $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName ODataServicesPort -KeyValue $environment.OdataServicesPort -CurrentConfiguration $config -Verbose) $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName SOAPServicesPort -KeyValue $environment.SoapServicesPort -CurrentConfiguration $config -Verbose) $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName ClientServicesCredentialType -KeyValue $environment.Authentication -CurrentConfiguration $config -Verbose) foreach ($key in $environment.Settings.Keys) { if ((-not([string]::IsNullOrEmpty($key))) -and (-not([string]::IsNullOrEmpty($environment.Settings[$key])))) { $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName $key -KeyValue $environment.Settings[$key] -CurrentConfiguration $config -Verbose) } } if ($updated -and ($row.Parameter2 -eq "RestartService")) { Write-Host "Restarting service" Restart-NAVServerInstance -ServerInstance $environment.ServerInstance } } } } 'UpdateLicense' { Write-Host "Loading Instance-data..." Import-Module Cloud.Ready.Software.NAV -Force Import-NAVModules # Download License $targetFilename = 'C:\Install\ScriptDownload\license.flf' Download-CustomFile -URI $row.Parameter1 -DestinationFile $targetFilename $environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableNameEnvironments $StorageTableNameEnvironments -TableNameDefaults $StorageTableNameEnvironmentDefaults -TypeFilter $row.Parameter1 -ConfigType Application foreach ($environment in $environments) { if (Get-NavServerInstance -ServerInstance $environment.ServerInstance) { Write-Host "Updating license..." Import-NAVServerLicense -ServerInstance $environment.ServerInstance -LicenseFile $targetFilename if ($row.Parameter2 -eq "RestartService") { Write-Host "Restarting service..." Restart-NAVServerInstance -ServerInstance $environment.ServerInstance | Out-Null } } } } 'CreateWebInstances' { Write-Host "Importing Cloud.Ready.Software.NAV..." Import-Module Cloud.Ready.Software.NAV -Force Write-Host "Importing NAV Modules..." # On the WebServer-VM there is no complete NAV/BC installation, so we need to only load the relevant WebClient-module #Import-NAVModules $path = "C:\Program Files\Microsoft Dynamics *\*\Web Client\Modules\NAVWebClientManagement\NAVWebClientManagement.psm1" $modulePath = (Get-ChildItem -Path $path | Select-Object -First 1).FullName Import-Module -Name $modulePath $infrastructureData = Get-InfrastructureDataFromStorage -StorageAccountContext $storageAccountContext -TableNameInfrastructureData $StorageTableNameInfrastructureData $environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableNameEnvironments $StorageTableNameEnvironments -TableNameDefaults $StorageTableNameEnvironmentDefaults -TypeFilter $row.Parameter1 -ConfigType Application foreach ($environment in $environments) { $serverInstanceName = "$($environment.ServerInstance)-Web" if (-not (Get-NAVWebServerInstance -WebServerInstance $serverInstanceName)) { Write-Host "Creating instance: $serverInstanceName" $params = @{ WebServerInstance = $serverInstanceName Server = $infrastructureData.ApplicationServerLoadBalancerIP ServerInstance = $environment.ServerInstance ClientServicesCredentialType = $environment.Authentication ClientServicesPort = $environment.ClientServicesPort } if (-not([string]::IsNullOrEmpty($infrastructureData.DnsIdentity))){ $params.Add("DnsIdentity", $infrastructureData.DnsIdentity) } New-NAVWebServerInstance @params Write-Host "Updating navsettings.json..." $configFile = "C:\inetpub\wwwroot\$($serverInstanceName)\navsettings.json" $a = Get-Content $configFile -raw | ConvertFrom-Json $a.NAVWebSettings.ManagementServicesPort = $environment.ManagementServicesPort $a | ConvertTo-Json -depth 32 | set-content $configFile } } } # Add "CreateWebInstances" # Add "UpdateWebInstanceConfiguration" # Add "UpdateCertificate" # Add "UpdateWebCertificate" # Add "CreateDelegation" # Add "CreateSPN" default { Write-Host "Not implemented yet." } } if ($row.RestartNecessary -eq $false) { # Update Command Table, because machine will be restartet in a moment Set-StorageCommandExecuted -CommandRow $row -ExecutedByName $env:computername } if ($row.RestartNecessary -eq $true) { break } } } } |