From f1a722866972a564be8bbaaa954915c5614af383 Mon Sep 17 00:00:00 2001 From: Sam Lee <32776898+minhsuanlee@users.noreply.github.com> Date: Tue, 4 Jun 2024 23:47:56 -0700 Subject: [PATCH] Microsoft.DataReplication Az.Migrate Update for HCI scenario align with preview schedule (#24594) * Update NIC logic * Add retries for operations * Refactor retry logic * Add validation & bug fix * Fix typo * Bug fix * Expose get protected item error * Update autogenerated files including doc --------- Co-authored-by: Sam Lee --- src/Migrate/Migrate.Autorest/Az.Migrate.psd1 | 2 +- .../Get-AzMigrateHCIServerReplication.ps1 | 93 +++++---- .../Helper/AzStackHCICommonSettings.ps1 | 6 + .../custom/Helper/CommonHelper.ps1 | 54 ++++++ ...-AzMigrateHCIReplicationInfrastructure.ps1 | 101 ++++------ .../New-AzMigrateHCINicMappingObject.ps1 | 20 +- .../New-AzMigrateHCIServerReplication.ps1 | 177 ++++++++---------- .../Remove-AzMigrateHCIServerReplication.ps1 | 9 +- .../Set-AzMigrateHCIServerReplication.ps1 | 26 +-- .../docs/New-AzMigrateHCINicMappingObject.md | 6 +- .../Migrate.Autorest/examples/README.md | 11 -- src/Migrate/Migrate.Autorest/test/loadEnv.ps1 | 2 +- 12 files changed, 254 insertions(+), 253 deletions(-) delete mode 100644 src/Migrate/Migrate.Autorest/examples/README.md diff --git a/src/Migrate/Migrate.Autorest/Az.Migrate.psd1 b/src/Migrate/Migrate.Autorest/Az.Migrate.psd1 index 8ed99acfeb5f..7f8413274072 100644 --- a/src/Migrate/Migrate.Autorest/Az.Migrate.psd1 +++ b/src/Migrate/Migrate.Autorest/Az.Migrate.psd1 @@ -11,7 +11,7 @@ DotNetFrameworkVersion = '4.7.2' RequiredAssemblies = './bin/Az.Migrate.private.dll' FormatsToProcess = './Az.Migrate.format.ps1xml' - FunctionsToExport = 'Get-AzMigrateDiscoveredServer', 'Get-AzMigrateJob', 'Get-AzMigrateProject', 'Get-AzMigrateReplicationEligibilityResult', 'Get-AzMigrateReplicationFabric', 'Get-AzMigrateReplicationPolicy', 'Get-AzMigrateReplicationProtectionContainer', 'Get-AzMigrateReplicationProtectionContainerMapping', 'Get-AzMigrateReplicationProtectionIntent', 'Get-AzMigrateReplicationRecoveryServicesProvider', 'Get-AzMigrateReplicationVaultSetting', 'Get-AzMigrateRunAsAccount', 'Get-AzMigrateServerReplication', 'Get-AzMigrateSite', 'Get-AzMigrateSolution', 'Get-AzMigrateSupportedOperatingSystem', 'Initialize-AzMigrateReplicationInfrastructure', 'New-AzMigrateDiskMapping', 'New-AzMigrateNicMapping', 'New-AzMigrateProject', 'New-AzMigrateReplicationPolicy', 'New-AzMigrateReplicationProtectionContainerMapping', 'New-AzMigrateReplicationProtectionIntent', 'New-AzMigrateReplicationVaultSetting', 'New-AzMigrateServerReplication', 'Register-AzMigrateProjectTool', 'Remove-AzMigrateProject', 'Remove-AzMigrateServerReplication', 'Restart-AzMigrateServerReplication', 'Set-AzMigrateDiskMapping', 'Set-AzMigrateServerReplication', 'Start-AzMigrateServerMigration', 'Start-AzMigrateTestMigration', 'Start-AzMigrateTestMigrationCleanup', '*' + FunctionsToExport = 'Get-AzMigrateDiscoveredServer', 'Get-AzMigrateHCIJob', 'Get-AzMigrateHCIReplicationFabric', 'Get-AzMigrateHCIServerReplication', 'Get-AzMigrateJob', 'Get-AzMigrateProject', 'Get-AzMigrateReplicationFabric', 'Get-AzMigrateReplicationPolicy', 'Get-AzMigrateReplicationProtectionContainer', 'Get-AzMigrateReplicationProtectionContainerMapping', 'Get-AzMigrateReplicationRecoveryServicesProvider', 'Get-AzMigrateRunAsAccount', 'Get-AzMigrateServerReplication', 'Get-AzMigrateSite', 'Get-AzMigrateSolution', 'Initialize-AzMigrateHCIReplicationInfrastructure', 'Initialize-AzMigrateReplicationInfrastructure', 'New-AzMigrateDiskMapping', 'New-AzMigrateHCIDiskMappingObject', 'New-AzMigrateHCINicMappingObject', 'New-AzMigrateHCIServerReplication', 'New-AzMigrateNicMapping', 'New-AzMigrateProject', 'New-AzMigrateReplicationPolicy', 'New-AzMigrateReplicationProtectionContainerMapping', 'New-AzMigrateServerReplication', 'New-AzMigrateTestNicMapping', 'Register-AzMigrateProjectTool', 'Remove-AzMigrateHCIServerReplication', 'Remove-AzMigrateProject', 'Remove-AzMigrateServerReplication', 'Restart-AzMigrateServerReplication', 'Resume-AzMigrateServerReplication', 'Set-AzMigrateDiskMapping', 'Set-AzMigrateHCIServerReplication', 'Set-AzMigrateServerReplication', 'Start-AzMigrateHCIServerMigration', 'Start-AzMigrateServerMigration', 'Start-AzMigrateTestMigration', 'Start-AzMigrateTestMigrationCleanup', 'Suspend-AzMigrateServerReplication', '*' AliasesToExport = '*' PrivateData = @{ PSData = @{ diff --git a/src/Migrate/Migrate.Autorest/custom/Get-AzMigrateHCIServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/Get-AzMigrateHCIServerReplication.ps1 index 25a19d1ba311..fac20ae926fd 100644 --- a/src/Migrate/Migrate.Autorest/custom/Get-AzMigrateHCIServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Get-AzMigrateHCIServerReplication.ps1 @@ -162,58 +162,45 @@ function Get-AzMigrateHCIServerReplication { # Occasionally, Get Machine Site will not return machine site even when the site exist, # hence retry get machine site. - $attempts = 4 - for ($i = 1; $i -le $attempts; $i++) { - try { - if ($siteType -eq $SiteTypes.VMwareSites) { - $siteObject = Az.Migrate\Get-AzMigrateSite @PSBoundParameters -ErrorVariable notPresent -ErrorAction SilentlyContinue - } - elseif ($siteType -eq $SiteTypes.HyperVSites) { - $siteObject = Az.Migrate.Internal\Get-AzMigrateHyperVSite @PSBoundParameters -ErrorVariable notPresent -ErrorAction SilentlyContinue - } + if ($siteType -eq $SiteTypes.VMwareSites) { + $siteObject = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate\Get-AzMigrateSite' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Machine site '$siteName' with Type '$siteType' not found." + } elseif ($siteType -eq $SiteTypes.HyperVSites) { + $siteObject = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateHyperVSite' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Machine site '$siteName' with Type '$siteType' not found." + } - if ($null -eq $siteObject) { - throw "Machine site not found." - } - else { - $ProjectName = $siteObject.DiscoverySolutionId.Split("/")[8] - } + # $siteObject is not null or exception would have been thrown + $ProjectName = $siteObject.DiscoverySolutionId.Split("/")[8] - break; - } - catch { - if ($i -lt $attempts) - { - Write-Host "Machine site not found. Retrying in 30 seconds..." - Start-Sleep -Seconds 30 - } - else - { - throw "Machine site '$siteName' with Type '$siteType' not found." - } - } - } - $null = $PSBoundParameters.Remove('SiteName') - $null = $PSBoundParameters.Add("Name", "Servers-Migration-ServerMigration_DataReplication") + # Get the migrate solution. + $amhSolutionName = "Servers-Migration-ServerMigration_DataReplication" + $null = $PSBoundParameters.Add("Name", $amhSolutionName) $null = $PSBoundParameters.Add("MigrateProjectName", $ProjectName) - - $solution = Az.Migrate\Get-AzMigrateSolution @PSBoundParameters - if ($solution -and ($solution.Count -ge 1)) { - $VaultName = $solution.DetailExtendedDetail.AdditionalProperties.vaultId.Split("/")[8] - } - else { - throw "Solution not found." - } + + $solution = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate\Get-AzMigrateSolution' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "No Data Replication Service Solution '$amhSolutionName' found in resource group '$ResourceGroupName' and project '$ProjectName'. Please verify your appliance setup." $null = $PSBoundParameters.Remove("Name") $null = $PSBoundParameters.Remove("MigrateProjectName") + + $VaultName = $solution.DetailExtendedDetail.AdditionalProperties.vaultId.Split("/")[8] + if ([string]::IsNullOrEmpty($VaultName)) { + throw "Azure Migrate Project not configured: missing replication vault. Setup Azure Migrate Project and run the Initialize-AzMigrateHCIReplicationInfrastructure script before proceeding." + } $null = $PSBoundParameters.Add("VaultName", $VaultName) $null = $PSBoundParameters.Add("Name", $ProtectedItemName) - return Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters -ErrorVariable notPresent -ErrorAction SilentlyContinue + return Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters } if (($parameterSet -match 'List') -or ($parameterSet -eq 'GetByMachineName')) { @@ -234,23 +221,27 @@ function Get-AzMigrateHCIServerReplication { $ProjectName = $projectIdArray[8] } + $amhSolutionName = "Servers-Migration-ServerMigration_DataReplication" $null = $PSBoundParameters.Add("ResourceGroupName", $ResourceGroupName) - $null = $PSBoundParameters.Add("Name", "Servers-Migration-ServerMigration_DataReplication") + $null = $PSBoundParameters.Add("Name", $amhSolutionName) $null = $PSBoundParameters.Add("MigrateProjectName", $ProjectName) - - $solution = Az.Migrate\Get-AzMigrateSolution @PSBoundParameters - if ($solution -and ($solution.Count -ge 1)) { - $VaultName = $solution.DetailExtendedDetail.AdditionalProperties.vaultId.Split("/")[8] - } - else { - throw "Solution not found." - } + + $solution = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate\Get-AzMigrateSolution' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "No Data Replication Service Solution '$amhSolutionName' found in resource group '$ResourceGroupName' and project '$ProjectName'. Please verify your appliance setup." $null = $PSBoundParameters.Remove("Name") $null = $PSBoundParameters.Remove("MigrateProjectName") + + $VaultName = $solution.DetailExtendedDetail.AdditionalProperties.vaultId.Split("/")[8] + if ([string]::IsNullOrEmpty($VaultName)) { + throw "Azure Migrate Project not configured: missing replication vault. Setup Azure Migrate Project and run the Initialize-AzMigrateHCIReplicationInfrastructure script before proceeding." + } + $null = $PSBoundParameters.Add("VaultName", $VaultName) - $replicatingItems = Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters -ErrorVariable notPresent -ErrorAction SilentlyContinue + $replicatingItems = Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters if ($parameterSet -eq "GetByMachineName") { $replicatingItems = $replicatingItems | Where-Object { $_.Property.FabricObjectName -eq $MachineName } @@ -274,7 +265,7 @@ function Get-AzMigrateHCIServerReplication { $null = $PSBoundParameters.Add("VaultName", $VaultName) $null = $PSBoundParameters.Add("Name", $ProtectedItemName) - return Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters -ErrorVariable notPresent -ErrorAction SilentlyContinue + return Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters } } } \ No newline at end of file diff --git a/src/Migrate/Migrate.Autorest/custom/Helper/AzStackHCICommonSettings.ps1 b/src/Migrate/Migrate.Autorest/custom/Helper/AzStackHCICommonSettings.ps1 index b358ef4b966e..08d92197d81d 100644 --- a/src/Migrate/Migrate.Autorest/custom/Helper/AzStackHCICommonSettings.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Helper/AzStackHCICommonSettings.ps1 @@ -75,4 +75,10 @@ enum StorageAccountProvisioningState Creating ResolvingDNS Succeeded +} + +# Selection state for VM NIC +$VMNicSelection = @{ + SelectedByUser = "SelectedByUser"; + NotSelected = "NotSelected"; } \ No newline at end of file diff --git a/src/Migrate/Migrate.Autorest/custom/Helper/CommonHelper.ps1 b/src/Migrate/Migrate.Autorest/custom/Helper/CommonHelper.ps1 index ac37011924e3..c3e4e31a347e 100644 --- a/src/Migrate/Migrate.Autorest/custom/Helper/CommonHelper.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Helper/CommonHelper.ps1 @@ -176,4 +176,58 @@ function GenerateHashForArtifact { else { return $hashCode } +} + +function InvokeAzMigrateGetCommandWithRetries { + [Microsoft.Azure.PowerShell.Cmdlets.Migrate.DoNotExportAttribute()] + param( + [Parameter(Mandatory)] + [System.String] + # Specifies the name of Az.Migrate command. + ${CommandName}, + + [Parameter(Mandatory)] + [System.Collections.Hashtable] + # Specifies the parameters for Az.Migrate command. + ${Parameters}, + + [Parameter()] + [System.Int32] + # Specifies the maximum number of retries. + ${MaxRetryCount} = 3, + + [Parameter()] + [System.Int32] + # Specifies the delay between retries in seconds. + ${RetryDelayInSeconds} = 30, + + [Parameter()] + [System.String] + # Specifies the error message to throw if command fails. + ${ErrorMessage} = "Internal Az.Migrate commands failed to execute." + ) + + process { + for ($i = 0; $i -le $MaxRetryCount; $i++) { + try { + $result = & $CommandName @Parameters -ErrorVariable notPresent -ErrorAction SilentlyContinue + + if ($null -eq $result) { + throw $ErrorMessage + } + + break + } + catch { + if ($i -lt $MaxRetryCount) { + Start-Sleep -Seconds $RetryDelayInSeconds + } + else { + throw $ErrorMessage + } + } + } + + return $result + } } \ No newline at end of file diff --git a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateHCIReplicationInfrastructure.ps1 b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateHCIReplicationInfrastructure.ps1 index fb6e1e790348..85665ec5cc72 100644 --- a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateHCIReplicationInfrastructure.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateHCIReplicationInfrastructure.ps1 @@ -137,14 +137,14 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { throw "Please login to Azure to select a subscription." } } - Write-Host "*Selected Subscription Id: '$($SubscriptionId)'." + Write-Host "*Selected Subscription Id: '$($SubscriptionId)'" # Get resource group $resourceGroup = Get-AzResourceGroup -Name $ResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue if ($null -eq $resourceGroup) { throw "Resource group '$($ResourceGroupName)' does not exist in the subscription. Please create the resource group and try again." } - Write-Host "*Selected Resource Group: '$($ResourceGroupName)'." + Write-Host "*Selected Resource Group: '$($ResourceGroupName)'" # Verify user validity $userObject = Get-AzADUser -UserPrincipalName $context.Subscription.ExtendedProperties.Account @@ -169,27 +169,17 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { } # Get Migrate Project - $migrateProject = Az.Migrate\Get-AzMigrateProject ` - -Name $ProjectName ` - -ResourceGroupName $ResourceGroupName ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - if ($null -eq $migrateProject) { - throw "Migrate project '$($ProjectName)' not found." - } + $migrateProject = InvokeAzMigrateGetCommandWithRetries ` + -CommandName "Az.Migrate\Get-AzMigrateProject" ` + -Parameters @{"Name" = $ProjectName; "ResourceGroupName" = $ResourceGroupName} ` + -ErrorMessage "Migrate project '$($ProjectName)' not found." # Access Discovery Service $discoverySolutionName = "Servers-Discovery-ServerDiscovery" - $discoverySolution = Az.Migrate\Get-AzMigrateSolution ` - -SubscriptionId $SubscriptionId ` - -ResourceGroupName $ResourceGroupName ` - -MigrateProjectName $ProjectName ` - -Name $discoverySolutionName ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - if ($discoverySolution.Name -ne $discoverySolutionName) { - throw "Server Discovery Solution not found." - } + $discoverySolution = InvokeAzMigrateGetCommandWithRetries ` + -CommandName "Az.Migrate\Get-AzMigrateSolution" ` + -Parameters @{"SubscriptionId" = $SubscriptionId; "ResourceGroupName" = $ResourceGroupName; "MigrateProjectName" = $ProjectName; "Name" = $discoverySolutionName} ` + -ErrorMessage "Server Discovery Solution '$discoverySolutionName' not found." # Get Appliances Mapping $appMap = @{} @@ -231,16 +221,11 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { } # Get Data Replication Service, or the AMH solution - $amhSolution = Az.Migrate\Get-AzMigrateSolution ` - -ResourceGroupName $ResourceGroupName ` - -MigrateProjectName $ProjectName ` - -Name "Servers-Migration-ServerMigration_DataReplication" ` - -SubscriptionId $SubscriptionId ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - if ($null -eq $amhSolution) { - throw "No Data Replication Service Solution found. Please verify your appliance setup." - } + $amhSolutionName = "Servers-Migration-ServerMigration_DataReplication" + $amhSolution = InvokeAzMigrateGetCommandWithRetries ` + -CommandName "Az.Migrate\Get-AzMigrateSolution" ` + -Parameters @{"SubscriptionId" = $SubscriptionId; "ResourceGroupName" = $ResourceGroupName; "MigrateProjectName" = $ProjectName; "Name" = $amhSolutionName} ` + -ErrorMessage "No Data Replication Service Solution '$amhSolutionName' found. Please verify your appliance setup." # Get Source and Target Fabrics $allFabrics = Az.Migrate\Get-AzMigrateHCIReplicationFabric -ResourceGroupName $ResourceGroupName @@ -267,46 +252,38 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { } if ($null -eq $sourceFabric) { - throw "Source Fabric not found. Please verify your appliance setup." + throw "No source Fabric found. Please verify your appliance setup." } - Write-Host "*Selected Source Fabric: '$($sourceFabric.Name)'." + Write-Host "*Selected Source Fabric: '$($sourceFabric.Name)'" if ($null -eq $targetFabric) { - throw "Target Fabric not found. Please verify your appliance setup." + throw "No target Fabric found. Please verify your appliance setup." } - Write-Host "*Selected Target Fabric: '$($targetFabric.Name)'." + Write-Host "*Selected Target Fabric: '$($targetFabric.Name)'" # Get Source and Target Dras from Fabrics - $sourceDras = Az.Migrate.Internal\Get-AzMigrateDra ` - -FabricName $sourceFabric.Name ` - -ResourceGroupName $ResourceGroupName ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - if ($null -eq $sourceDras) { - throw "Source Dra found. Please verify your appliance setup." - } + $sourceDras = InvokeAzMigrateGetCommandWithRetries ` + -CommandName "Az.Migrate.Internal\Get-AzMigrateDra" ` + -Parameters @{"FabricName" = $sourceFabric.Name; "ResourceGroupName" = $ResourceGroupName} ` + -ErrorMessage "No source Fabric Agent (DRA) found. Please verify your appliance setup." + $sourceDra = $sourceDras[0] - Write-Host "*Selected Source Dra: '$($sourceDra.Name)'." + Write-Host "*Selected Source Dra: '$($sourceDra.Name)'" + + $targetDras = InvokeAzMigrateGetCommandWithRetries ` + -CommandName "Az.Migrate.Internal\Get-AzMigrateDra" ` + -Parameters @{"FabricName" = $targetFabric.Name; "ResourceGroupName" = $ResourceGroupName} ` + -ErrorMessage "No target Fabric Agent (DRA) found. Please verify your appliance setup." - $targetDras = Az.Migrate.Internal\Get-AzMigrateDra ` - -FabricName $targetFabric.Name ` - -ResourceGroupName $ResourceGroupName ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - if ($null -eq $targetDras) { - throw "Source Dra found. Please verify your appliance setup." - } $targetDra = $targetDras[0] - Write-Host "*Selected Target Dra: '$($targetDra.Name)'." + Write-Host "*Selected Target Dra: '$($targetDra.Name)'" # Get Replication Vault $replicationVaultName = $amhSolution.DetailExtendedDetail["vaultId"].Split("/")[8] - $replicationVault = Az.Migrate.Internal\Get-AzMigrateVault ` - -ResourceGroupName $ResourceGroupName ` - -Name $replicationVaultName - if ($null -eq $replicationVault) { - throw "No Replication Vault found in Resource Group '$($ResourceGroupName)'." - } + $replicationVault = InvokeAzMigrateGetCommandWithRetries ` + -CommandName "Az.Migrate.Internal\Get-AzMigrateVault" ` + -Parameters @{"ResourceGroupName" = $ResourceGroupName; "Name" = $replicationVaultName} ` + -ErrorMessage "No Replication Vault '$replicationVaultName' found in Resource Group '$ResourceGroupName'." # Put Policy $policyName = $replicationVault.Name + $instanceType + "policy" @@ -504,7 +481,7 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { throw "Policy '$($policyName)' has an unexpected Provisioning State of '$($policy.Property.ProvisioningState)'. Please re-run this command or contact support if help needed." } else { - Write-Host "*Selected Policy: '$($policyName)'." + Write-Host "*Selected Policy: '$($policyName)'" } # Put Cache Storage Account @@ -789,7 +766,7 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { # Give time for role assignments to be created. Times out after 2min $rsaPermissionGranted = $false - for ($i = 0; $i -lt 4; $i++) { + for ($i = 0; $i -lt 3; $i++) { # Check Source Dra AAD App access to Cache Storage Account as "Contributor" $hasAadAppAccess = Get-AzRoleAssignment ` -ObjectId $params.sourceAppAadId ` @@ -864,7 +841,7 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { -DetailExtendedDetail $amhSolution.DetailExtendedDetail.AdditionalProperties | Out-Null } - Write-Host "*Selected Cache Storage Account: '$($cacheStorageAccount.StorageAccountName)' in Resource Group '$($ResourceGroupName)' at Location '$($cacheStorageAccount.Location)' for Migrate Project '$($migrateProject.Name)'." + Write-Host "*Selected Cache Storage Account: '$($cacheStorageAccount.StorageAccountName)' in Resource Group '$($ResourceGroupName)' at Location '$($cacheStorageAccount.Location)' for Migrate Project '$($migrateProject.Name)'" # Put replication extension $replicationExtensionName = ($sourceFabric.Id -split '/')[-1] + "-" + ($targetFabric.Id -split '/')[-1] + "-MigReplicationExtn" @@ -1098,7 +1075,7 @@ function Initialize-AzMigrateHCIReplicationInfrastructure { throw "Replication Extension '$($replicationExtensionName)' has an unexpected Provisioning State of '$($replicationExtension.Property.ProvisioningState)'. Please re-run this command or contact support if help needed." } else { - Write-Host "*Selected Replication Extension: '$($replicationExtensionName)'." + Write-Host "*Selected Replication Extension: '$($replicationExtensionName)'" } if ($PassThru) { diff --git a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCINicMappingObject.ps1 b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCINicMappingObject.ps1 index 5640d529b518..f7954e9e8b02 100644 --- a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCINicMappingObject.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCINicMappingObject.ps1 @@ -31,7 +31,7 @@ function New-AzMigrateHCINicMappingObject { # Specifies the ID of the NIC to be updated. ${NicID}, - [Parameter(Mandatory)] + [Parameter()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Path')] [System.String] # Specifies the logical network ARM ID that the VMs will use. @@ -53,11 +53,21 @@ function New-AzMigrateHCINicMappingObject { ) process { - if (!$PSBoundParameters.ContainsKey('TargetTestVirtualSwitchId')) { - $TargetTestVirtualSwitchId = $TargetVirtualSwitchId - } + if ($CreateAtTarget -eq "true") { + if (!$PSBoundParameters.ContainsKey('TargetVirtualSwitchId') -or + [string]::IsNullOrEmpty($TargetVirtualSwitchId)) { + throw "TargetVirtualSwitchId is required when CreateAtTarget is 'true'." + } - $selectionTypeForFailover = if ($CreateAtTarget -eq "true") { "SelectedByUser" } else { "NotSelected" } + if (!$PSBoundParameters.ContainsKey('TargetTestVirtualSwitchId')) { + $TargetTestVirtualSwitchId = $TargetVirtualSwitchId + } + + $selectionTypeForFailover = $VMNicSelection.SelectedByUser + } + else { + $selectionTypeForFailover = $VMNicSelection.NotSelected + } $NicObject = [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Models.Api20210216Preview.AzStackHCINicInput]::new( $NicID, diff --git a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCIServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCIServerReplication.ps1 index 01a3870a06ff..c9572169ee9b 100644 --- a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCIServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateHCIServerReplication.ps1 @@ -203,47 +203,55 @@ function New-AzMigrateHCIServerReplication { if ($SiteType -eq $SiteTypes.HyperVSites) { $instanceType = $AzStackHCIInstanceTypes.HyperVToAzStackHCI - $machine = Az.Migrate.Internal\Get-AzMigrateHyperVMachine @PSBoundParameters - + $machine = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateHyperVMachine' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Machine '$MachineName' not found in resource group '$ResourceGroupName' and site '$SiteName'." + $null = $PSBoundParameters.Remove('MachineName') - $siteObject = Az.Migrate.Internal\Get-AzMigrateHyperVSite @PSBoundParameters + + $siteObject = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateHyperVSite' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Machine site '$SiteName' with Type '$SiteType' not found." } elseif ($SiteType -eq $SiteTypes.VMwareSites) { $instanceType = $AzStackHCIInstanceTypes.VMwareToAzStackHCI - $machine = Az.Migrate.Internal\Get-AzMigrateMachine @PSBoundParameters + $machine = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateMachine' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Machine '$MachineName' not found in resource group '$ResourceGroupName' and site '$SiteName'." $null = $PSBoundParameters.Remove('MachineName') - $siteObject = Az.Migrate\Get-AzMigrateSite @PSBoundParameters - } - $null = $PSBoundParameters.Remove('ResourceGroupName') - $null = $PSBoundParameters.Remove('SiteName') - - if ($null -eq $machine) { - throw "No machine '$MachineName' found in resource group '$ResourceGroupName' and site '$SiteName'." + $siteObject = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate\Get-AzMigrateSite' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Machine site '$SiteName' with Type '$SiteType' not found." } - if ($siteObject -and ($siteObject.Count -ge 1)) { - $ProjectName = $siteObject.DiscoverySolutionId.Split("/")[8] - } - else { - throw "No site '$SiteName' found in resource group '$ResourceGroupName'" - } + # $siteObject is not null or exception would have been thrown + $ProjectName = $siteObject.DiscoverySolutionId.Split("/")[8] + + $null = $PSBoundParameters.Remove('SiteName') # Get the migrate solution. - $null = $PSBoundParameters.Add("ResourceGroupName", $ResourceGroupName) - $null = $PSBoundParameters.Add("Name", "Servers-Migration-ServerMigration_DataReplication") + $amhSolutionName = "Servers-Migration-ServerMigration_DataReplication" + $null = $PSBoundParameters.Add("Name", $amhSolutionName) $null = $PSBoundParameters.Add("MigrateProjectName", $ProjectName) - - $solution = Az.Migrate\Get-AzMigrateSolution @PSBoundParameters - $vaultName = $solution.DetailExtendedDetail.AdditionalProperties.vaultId.Split("/")[8] + $solution = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate\Get-AzMigrateSolution' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "No Data Replication Service Solution '$amhSolutionName' found in resource group '$ResourceGroupName' and project '$ProjectName'. Please verify your appliance setup." + $null = $PSBoundParameters.Remove('ResourceGroupName') $null = $PSBoundParameters.Remove("Name") $null = $PSBoundParameters.Remove("MigrateProjectName") - - if (($null -eq $solution) -or [string]::IsNullOrEmpty($vaultName)) { - throw 'Azure Migrate Project not configured. Setup Azure Migrate Project and run the Initialize-AzMigrateHCIReplicationInfrastructure script before proceeding.' + + $VaultName = $solution.DetailExtendedDetail.AdditionalProperties.vaultId.Split("/")[8] + if ([string]::IsNullOrEmpty($VaultName)) { + throw "Azure Migrate Project not configured: missing replication vault. Setup Azure Migrate Project and run the Initialize-AzMigrateHCIReplicationInfrastructure script before proceeding." } # Get fabrics and appliances in the project @@ -269,57 +277,37 @@ function New-AzMigrateHCIServerReplication { } if ($null -eq $targetFabric) { - throw "A target appliance is not available for the target cluster. Deploy and configure a new appliance for the cluster, or select a different cluster.." + throw "A target appliance is not available for the target cluster. Deploy and configure a new appliance for the cluster, or select a different cluster." } # Get Source and Target Dras - $sourceDras = Az.Migrate.Internal\Get-AzMigrateDra ` - -FabricName $sourceFabric.Name ` - -ResourceGroupName $ResourceGroupName ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - if ($null -eq $sourceDras) { - throw "No connected source appliances are found. Kindly deploy an appliance by completing the Discover step of the migration jounery on the source cluster." - } + $sourceDras = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateDra' ` + -Parameters @{ FabricName = $sourceFabric.Name; ResourceGroupName = $ResourceGroupName } ` + -ErrorMessage "No connected source appliances are found. Kindly deploy an appliance by completing the Discover step of the migration jounery on the source cluster." + $sourceDra = $sourceDras[0] - $targetDras = Az.Migrate.Internal\Get-AzMigrateDra ` - -FabricName $targetFabric.Name ` - -ResourceGroupName $ResourceGroupName ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - if ($null -eq $targetDras) { - throw "A target appliance is not available for the target cluster. Deploy and configure a new appliance for the cluster, or select a different cluster.." - } + $targetDras = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateDra' ` + -Parameters @{ FabricName = $targetFabric.Name; ResourceGroupName = $ResourceGroupName } ` + -ErrorMessage "No connected target appliances are found. Deploy and configure a new appliance for the target cluster, or select a different cluster." + $targetDra = $targetDras[0] # Validate Policy $policyName = $vaultName + $instanceType + "policy" - $policyObj = Az.Migrate.Internal\Get-AzMigratePolicy ` - -ResourceGroupName $ResourceGroupName ` - -Name $policyName ` - -VaultName $vaultName ` - -SubscriptionId $SubscriptionId ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - - if ($null -eq $policyObj) { - throw "The replication infrastructure is not initialized. Run the Initialize-AzMigrateHCIReplicationInfrastructure script again." - } + $policy = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigratePolicy' ` + -Parameters @{ ResourceGroupName = $ResourceGroupName; Name = $policyName; VaultName = $vaultName; SubscriptionId = $SubscriptionId } ` + -ErrorMessage "The replication policy '$policyName' not found. The replication infrastructure is not initialized. Run the Initialize-AzMigrateHCIReplicationInfrastructure script again." # Validate Replication Extension $replicationExtensionName = ($sourceFabric.Id -split '/')[-1] + "-" + ($targetFabric.Id -split '/')[-1] + "-MigReplicationExtn" - $replicationExtension = Az.Migrate.Internal\Get-AzMigrateReplicationExtension ` - -ResourceGroupName $ResourceGroupName ` - -Name $replicationExtensionName ` - -VaultName $vaultName ` - -SubscriptionId $SubscriptionId ` - -ErrorVariable notPresent ` - -ErrorAction SilentlyContinue - - if ($null -eq $replicationExtension) { - throw "The replication infrastructure is not initialized. Run the Initialize-AzMigrateHCIReplicationInfrastructure script again." - } + $replicationExtension = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateReplicationExtension' ` + -Parameters @{ ResourceGroupName = $ResourceGroupName; Name = $replicationExtensionName; VaultName = $vaultName; SubscriptionId = $SubscriptionId } ` + -ErrorMessage "The replication extension '$replicationExtensionName' not found. The replication infrastructure is not initialized. Run the Initialize-AzMigrateHCIReplicationInfrastructure script again." $targetClusterId = $targetFabric.Property.CustomProperty.Cluster.ResourceName $targetClusterIdArray = $targetClusterId.Split("/") @@ -334,28 +322,27 @@ function New-AzMigrateHCIServerReplication { # Get source appliance RunAsAccount if ($SiteType -eq $SiteTypes.HyperVSites) { - $runAsAccounts = Az.Migrate.Internal\Get-AzMigrateHyperVRunAsAccount ` - -ResourceGroupName $ResourceGroupName ` - -SiteName $SiteName ` - -SubscriptionId $SubscriptionId + $runAsAccounts = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateHyperVRunAsAccount' ` + -Parameters @{ ResourceGroupName = $ResourceGroupName; SiteName = $SiteName; SubscriptionId = $SubscriptionId } ` + -ErrorMessage "No run as account found for site '$SiteName'." + $runAsAccount = $runAsAccounts | Where-Object { $_.CredentialType -eq $RunAsAccountCredentialTypes.HyperVFabric } } - elseif ($SiteType -eq $SiteTypes.VMwareSites) { - $runAsAccounts = Az.Migrate\Get-AzMigrateRunAsAccount ` - -ResourceGroupName $ResourceGroupName ` - -SiteName $SiteName ` - -SubscriptionId $SubscriptionId + elseif ($SiteType -eq $SiteTypes.VMwareSites) { + $runAsAccounts = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate\Get-AzMigrateRunAsAccount' ` + -Parameters @{ ResourceGroupName = $ResourceGroupName; SiteName = $SiteName; SubscriptionId = $SubscriptionId } ` + -ErrorMessage "No run as account found for site '$SiteName'." + $runAsAccount = $runAsAccounts | Where-Object { $_.CredentialType -eq $RunAsAccountCredentialTypes.VMwareFabric } } - - if ($null -eq $runAsAccount) { - throw "No run as account found for site '$SiteName'." - } # Validate TargetVMName if ($TargetVMName.length -gt 64 -or $TargetVMName.length -eq 0) { throw "The target virtual machine name must be between 1 and 64 characters long." } + Import-Module Az.Resources $vmId = $customProperties.TargetResourceGroupId + "/providers/Microsoft.Compute/virtualMachines/" + $TargetVMName $VMNamePresentInRg = Get-AzResource -ResourceId $vmId -ErrorVariable notPresent -ErrorAction SilentlyContinue @@ -468,31 +455,23 @@ function New-AzMigrateHCIServerReplication { NicId = $sourceNic.NicId TargetNetworkId = $TargetVirtualSwitchId TestNetworkId = if ($HasTargetTestVirtualSwitchId) { $TargetTestVirtualSwitchId } else { $TargetVirtualSwitchId } - SelectionTypeForFailover = "SelectedByUser" + SelectionTypeForFailover = $VMNicSelection.SelectedByUser } $nics += $NicObject } } - else { + else + { + # PowerUser if ($null -eq $DiskToInclude -or $DiskToInclude.length -eq 0) { throw "Invalid DiskToInclude. At least one disk is required." } - if ($null -eq $NicToInclude -or $NicToInclude.length -eq 0) { - throw "Invalid NicToInclude. At least one NIC is required." - } - # Validate OSDisk is set. $osDisk = $DiskToInclude | Where-Object { $_.IsOSDisk } if (($null -eq $osDisk) -or ($osDisk.length -ne 1)) { throw "Invalid DiskToInclude. One and only one disk must be set as OS Disk." } - - # Validate at least one NIC is selected by user. - $selectedNics = $NicToInclude | Where-Object { $_.SelectionTypeForFailover -eq "SelectedByUser"} - if ($null -eq $selectedNics -or $selectedNics.length -eq 0) { - throw "Invalid NicToInclude. At least one NIC is required to be marked as to be created at target." - } # Validate DiskToInclude [PSCustomObject[]]$uniqueDisks = @() @@ -534,26 +513,20 @@ function New-AzMigrateHCIServerReplication { } if ($uniqueNics.Contains($nic.NicId)) { - throw "The Nic id '$($nic.NicId)' is already taken." + throw "The Nic id '$($nic.NicId)' is already included. Please remove the duplicate entry and try again." } + $uniqueNics += $nic.NicId $htNic = @{} $nic.PSObject.Properties | ForEach-Object { $htNic[$_.Name] = $_.Value } - $nics += [PSCustomObject]$htNic - } - # Include Nics not added by user as 'NotSelected' - $userGivenNicIds = $nics | Select-Object -ExpandProperty NicId - $remainingNics = $machine.NetworkAdapter | Where-Object { $_.NicId -notin $userGivenNicIds } - foreach ($remainingNic in $remainingNics) { - $NicObject = [PSCustomObject]@{ - NicId = $remainingNic.NicId - TargetNetworkId = $nics[0].TargetNetworkId - TestNetworkId = $nics[0].TestNetworkId - SelectionTypeForFailover = "NotSelected" + if ($htNic.SelectionTypeForFailover -eq $VMNicSelection.SelectedByUser -and + [string]::IsNullOrEmpty($htNic.TargetNetworkId)) { + throw "TargetVirtualSwitchId is required when the NIC '$($htNic.NicId)' is to be CreateAtTarget. Please utilize the New-AzMigrateHCINicMappingObject command to properly create a Nic mapping object." } - $nics += $NicObject + + $nics += [PSCustomObject]$htNic } } diff --git a/src/Migrate/Migrate.Autorest/custom/Remove-AzMigrateHCIServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/Remove-AzMigrateHCIServerReplication.ps1 index dee3a73c9f0f..773f9d899926 100644 --- a/src/Migrate/Migrate.Autorest/custom/Remove-AzMigrateHCIServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Remove-AzMigrateHCIServerReplication.ps1 @@ -121,11 +121,10 @@ function Remove-AzMigrateHCIServerReplication { $null = $PSBoundParameters.Add("VaultName", $vaultName) $null = $PSBoundParameters.Add("Name", $protectedItemName) - $protectedItem = Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters -ErrorVariable notPresent -ErrorAction SilentlyContinue - if ($null -eq $ProtectedItem) - { - throw "Replication item is not found with Id '$TargetObjectID'." - } + $ProtectedItem = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateProtectedItem' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Replication item is not found with Id '$TargetObjectID'." $null = $PSBoundParameters.Remove('Name') diff --git a/src/Migrate/Migrate.Autorest/custom/Set-AzMigrateHCIServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/Set-AzMigrateHCIServerReplication.ps1 index ced599ff90d4..29de24dde98b 100644 --- a/src/Migrate/Migrate.Autorest/custom/Set-AzMigrateHCIServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Set-AzMigrateHCIServerReplication.ps1 @@ -159,10 +159,10 @@ function Set-AzMigrateHCIServerReplication { $null = $PSBoundParameters.Add("VaultName", $VaultName) $null = $PSBoundParameters.Add("Name", $MachineName) - $ProtectedItem = Az.Migrate.Internal\Get-AzMigrateProtectedItem @PSBoundParameters -ErrorVariable notPresent -ErrorAction SilentlyContinue - if ($null -eq $ProtectedItem) { - throw "Replication item is not found with Id '$TargetObjectID'." - } + $ProtectedItem = InvokeAzMigrateGetCommandWithRetries ` + -CommandName 'Az.Migrate.Internal\Get-AzMigrateProtectedItem' ` + -Parameters $PSBoundParameters ` + -ErrorMessage "Replication item is not found with Id '$TargetObjectID'." $null = $PSBoundParameters.Remove("ResourceGroupName") $null = $PSBoundParameters.Remove("VaultName") @@ -173,8 +173,11 @@ function Set-AzMigrateHCIServerReplication { $MachineIdArray = $customProperties.FabricDiscoveryMachineId.Split("/") $SiteType = $MachineIdArray[7] - if (!$protectedItemProperties.AllowedJob.Contains('PlannedFailover')) { - throw "Set server replication is not allowed for this item '$TargetObjectID'." + # No "DisableProtection" means IR has not been initiated + # "CommitFailover" means migration has been completed + if (!$protectedItemProperties.AllowedJob.Contains('DisableProtection') -or + $protectedItemProperties.AllowedJob.Contains('CommitFailover')) { + throw "Set server replication is not allowed for this item '$TargetObjectID' at the moment. Please check its status and try again later." } if ($HasTargetVMName) { @@ -269,17 +272,16 @@ function Set-AzMigrateHCIServerReplication { if ($null -eq $updatedNic){ throw "The Nic id '$($nic.NicId)' is not found." } + + if ($nic.SelectionTypeForFailover -eq $VMNicSelection.SelectedByUser -and + [string]::IsNullOrEmpty($nic.TargetNetworkId)) { + throw "TargetVirtualSwitchId is required when the NIC '$($nic.NicId)' is to be CreateAtTarget. Please utilize the New-AzMigrateHCINicMappingObject command to properly create a Nic mapping object." + } $updatedNic.TargetNetworkId = $nic.TargetNetworkId $updatedNic.TestNetworkId = $nic.TestNetworkId $updatedNic.SelectionTypeForFailover = $nic.SelectionTypeForFailover } - } - - $selectedNics = $nics | Where-Object { $_.SelectionTypeForFailover -eq "SelectedByUser" } - if ($null -eq $selectedNics -or $selectedNics.length -eq 0) - { - throw "At least one NIC must be selected for creation at target." } # Disks diff --git a/src/Migrate/Migrate.Autorest/docs/New-AzMigrateHCINicMappingObject.md b/src/Migrate/Migrate.Autorest/docs/New-AzMigrateHCINicMappingObject.md index e9ccdb6b7a0a..68d417de44f2 100644 --- a/src/Migrate/Migrate.Autorest/docs/New-AzMigrateHCINicMappingObject.md +++ b/src/Migrate/Migrate.Autorest/docs/New-AzMigrateHCINicMappingObject.md @@ -13,8 +13,8 @@ Creates an object to update NIC properties of a replicating server. ## SYNTAX ``` -New-AzMigrateHCINicMappingObject -NicID -TargetVirtualSwitchId [-CreateAtTarget ] - [-TargetTestVirtualSwitchId ] [] +New-AzMigrateHCINicMappingObject -NicID [-CreateAtTarget ] + [-TargetTestVirtualSwitchId ] [-TargetVirtualSwitchId ] [] ``` ## DESCRIPTION @@ -92,7 +92,7 @@ Type: System.String Parameter Sets: (All) Aliases: -Required: True +Required: False Position: Named Default value: None Accept pipeline input: False diff --git a/src/Migrate/Migrate.Autorest/examples/README.md b/src/Migrate/Migrate.Autorest/examples/README.md deleted file mode 100644 index a4c7754cdc40..000000000000 --- a/src/Migrate/Migrate.Autorest/examples/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Examples -This directory contains examples from the exported cmdlets of the module. When `build-module.ps1` is ran, example stub files will be generated here. If your module support Azure Profiles, the example stubs will be in individual profile folders. These example stubs should be updated to show how the cmdlet is used. The examples are imported into the documentation when `generate-help.ps1` is ran. - -## Info -- Modifiable: yes -- Generated: partial -- Committed: yes -- Packaged: no - -## Purpose -This separates the example documentation details from the generated documentation information provided directly from the generated cmdlets. Since the cmdlets don't have examples from the REST spec, this provides a means to add examples easily. The example stubs provide the markdown format that is required. The 3 core elements are: the name of the example, the code information of the example, and the description of the example. That information, if the markdown format is followed, will be available to documentation generation and be part of the documents in the `../docs` folder. \ No newline at end of file diff --git a/src/Migrate/Migrate.Autorest/test/loadEnv.ps1 b/src/Migrate/Migrate.Autorest/test/loadEnv.ps1 index 5f079e89615e..6a7c385c6b7d 100644 --- a/src/Migrate/Migrate.Autorest/test/loadEnv.ps1 +++ b/src/Migrate/Migrate.Autorest/test/loadEnv.ps1 @@ -25,5 +25,5 @@ if (Test-Path -Path (Join-Path $PSScriptRoot $envFile)) { $env = @{} if (Test-Path -Path $envFilePath) { $env = Get-Content (Join-Path $PSScriptRoot $envFile) | ConvertFrom-Json - $PSDefaultParameterValues=@{"*:SubscriptionId"=$env.SubscriptionId; "*:Tenant"=$env.Tenant} + $PSDefaultParameterValues=@{"*:Tenant"=$env.Tenant} } \ No newline at end of file