From 19c6594e33ba277148f57ec5c4d5ceb11355de30 Mon Sep 17 00:00:00 2001 From: Sam Lee Date: Thu, 16 Apr 2026 12:02:55 -0700 Subject: [PATCH 1/7] Add validation for HA, storagepath, storageaccount, and bug fix for user login --- .../custom/Helper/AzLocalCommonHelper.ps1 | 12 +++-- .../custom/Helper/AzLocalCommonSettings.ps1 | 4 +- ...zMigrateLocalReplicationInfrastructure.ps1 | 49 ++++++++++++------- .../New-AzMigrateLocalServerReplication.ps1 | 33 ++++++++++--- 4 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonHelper.ps1 b/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonHelper.ps1 index a0a89fb4a4dd..2f92fe054ea7 100644 --- a/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonHelper.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonHelper.ps1 @@ -302,9 +302,15 @@ function Test-ReplicationPrequisites { throw $VmReplicationValidationMessages.HyperVIntegrationServicesNotRunning } - # Hyper-V VMs should be highly available - if (![string]::IsNullOrEmpty($Machine.ClusterId) -and $Machine.HighAvailability -eq $HighAvailability.NO) { - throw $VmReplicationValidationMessages.VmNotHighlyAvailable + # Hyper-V VMs on cluster should be highly available + if (![string]::IsNullOrEmpty($Machine.ClusterId)) { + if ($Machine.HighAvailability -eq $HighAvailability.NO) { + throw $VmReplicationValidationMessages.VmNotHighlyAvailable + } + elseif ($Machine.HighAvailability -ne $HighAvailability.YES) { + # Unknown or unexpected value + throw $VmReplicationValidationMessages.VmUnknownHighlyAvailable + } } } diff --git a/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonSettings.ps1 b/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonSettings.ps1 index a0abcb0d4b2d..9e5ed52200cc 100644 --- a/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonSettings.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Helper/AzLocalCommonSettings.ps1 @@ -91,6 +91,7 @@ $PowerStatus = @{ } $HighAvailability = @{ + Unknown = "Unknown"; NO = "No"; YES = "Yes"; } @@ -111,7 +112,8 @@ $VmReplicationValidationMessage = "Replication could not be initiated. Please en $VmReplicationValidationMessages = @{ VmPoweredOff = "The VM is currently powered off. $VmReplicationValidationMessage"; AlreadyInReplication = "The VM is already in replication. $VmReplicationValidationMessage"; - VmNotHighlyAvailable = "VM not highly available. $VmReplicationValidationMessage"; + VmNotHighlyAvailable = "The VM is not highly available. $VmReplicationValidationMessage"; + VmUnknownHighlyAvailable = "The VM has unknown high availability status. $VmReplicationValidationMessage"; HyperVIntegrationServicesNotRunning = "Hyper-V Integration Services are not running on VM. $VmReplicationValidationMessage"; VmWareToolsNotInstalled = "VMware Tools are not installed on the VM. To preserve static IPs during migration, install VMware Tools and wait up to 30 minutes for the system to detect the changes."; VmWareToolsNotRunning = "VMware Tools are not running on the VM. To preserve static IPs during migration, ensure VMware Tools are running and wait up to 30 minutes for the system to detect the changes."; diff --git a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 index 9eedb0cde11b..f60adb556f3d 100644 --- a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 @@ -165,27 +165,27 @@ function Initialize-AzMigrateLocalReplicationInfrastructure { } Write-Host "*Selected Resource Group: '$($ResourceGroupName)'" - # Verify user validity - $userObject = Get-AzADUser -UserPrincipalName $context.Subscription.ExtendedProperties.Account - - if (-not $userObject) { - $userObject = Get-AzADUser -Mail $context.Subscription.ExtendedProperties.Account + # Verify caller identity + if ($context.Account.Type -eq 'ServicePrincipal') { + $userObject = Get-AzADServicePrincipal -ApplicationID $context.Account.Id } - - if (-not $userObject) { - $mailNickname = "{0}#EXT#" -f $($context.Account.Id -replace '@', '_') - - $userObject = Get-AzADUser | - Where-Object { $_.MailNickname -eq $mailNickname } + elseif ($context.Account.Type -eq 'ManagedService' -or $context.Account.Id.StartsWith("MSI@")) { + $hostname = if ($env:COMPUTERNAME) { $env:COMPUTERNAME } else { $env:HOSTNAME } + if ([string]::IsNullOrEmpty($hostname)) { + throw "Unable to determine the hostname for Managed Identity resolution. Please set the COMPUTERNAME or HOSTNAME environment variable." + } + $userObject = Get-AzADServicePrincipal -DisplayName $hostname } + else { + $userObject = Get-AzADUser -UserPrincipalName $context.Subscription.ExtendedProperties.Account - if (-not $userObject) { - if ($context.Account.Id.StartsWith("MSI@")) { - $hostname = $env:COMPUTERNAME - $userObject = Get-AzADServicePrincipal -DisplayName $hostname + if (-not $userObject) { + $userObject = Get-AzADUser -Mail $context.Subscription.ExtendedProperties.Account } - else { - $userObject = Get-AzADServicePrincipal -ApplicationID $context.Account.Id + + if (-not $userObject) { + $mailNickname = "{0}#EXT#" -f $($context.Account.Id -replace '@', '_') + $userObject = Get-AzADUser -Filter "mailNickname eq '$mailNickname'" } } @@ -799,6 +799,21 @@ function Initialize-AzMigrateLocalReplicationInfrastructure { throw "Unexpected error occurs during Cache Storage Account selection process. Please re-run this command or contact support if help needed." } + # Validate Cache Storage Account SKU tier is Standard (not Premium) + if ($cacheStorageAccount.Sku.Tier -ne "Standard") { + throw "Cache Storage Account '$($cacheStorageAccount.StorageAccountName)' uses an unsupported SKU tier '$($cacheStorageAccount.Sku.Tier)'. Only 'Standard' tier storage accounts are supported. Please provide a Standard tier storage account." + } + + # Validate public network access is not restricted (unless using private endpoints) + if ($null -ne $cacheStorageAccount.PublicNetworkAccess -and + $cacheStorageAccount.PublicNetworkAccess -eq "Disabled") { + # Public network access is disabled — skip blob access check as private endpoints are in use + } + elseif ($null -ne $cacheStorageAccount.AllowBlobPublicAccess -and + $cacheStorageAccount.AllowBlobPublicAccess -ne $true) { + throw "Cache Storage Account '$($cacheStorageAccount.StorageAccountName)' does not allow public blob access. Please enable 'Allow Blob public access' on the storage account and re-run this command." + } + $params = @{ contributorRoleDefId = [System.Guid]::parse($RoleDefinitionIds.ContributorId); storageBlobDataContributorRoleDefId = [System.Guid]::parse($RoleDefinitionIds.StorageBlobDataContributorId); diff --git a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 index 1269524c6a1b..72fb137db194 100644 --- a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 @@ -177,9 +177,6 @@ function New-AzMigrateLocalServerReplication { CheckResourceGraphModuleDependency CheckResourcesModuleDependency - $HasMachineId = $PSBoundParameters.ContainsKey('MachineId') - $HasTargetStoragePathId = $PSBoundParameters.ContainsKey('TargetStoragePathId') - $HasTargetResourceGroupId = $PSBoundParameters.ContainsKey('TargetResourceGroupId') $HasTargetVMCPUCore = $PSBoundParameters.ContainsKey('TargetVMCPUCore') $HasIsDynamicMemoryEnabled = $PSBoundParameters.ContainsKey('IsDynamicMemoryEnabled') if ($HasIsDynamicMemoryEnabled) { @@ -212,7 +209,7 @@ function New-AzMigrateLocalServerReplication { $null = $PSBoundParameters.Add('ErrorAction', 'SilentlyContinue') # Validate ARM ID format from inputs - if ($HasMachineId -and !(Test-AzureResourceIdFormat -Data $MachineId -Format $IdFormats.MachineArmIdTemplate)) + if (!(Test-AzureResourceIdFormat -Data $MachineId -Format $IdFormats.MachineArmIdTemplate)) { throw New-InvalidResourceIdProvidedException ` -ResourceId $MachineId ` @@ -220,14 +217,14 @@ function New-AzMigrateLocalServerReplication { -Format $IdFormats.MachineArmIdTemplate } - if ($HasTargetStoragePathId -and !(Test-AzureResourceIdFormat -Data $TargetStoragePathId -Format $IdFormats.StoragePathArmIdTemplate)) { + if (!(Test-AzureResourceIdFormat -Data $TargetStoragePathId -Format $IdFormats.StoragePathArmIdTemplate)) { throw New-InvalidResourceIdProvidedException ` -ResourceId $TargetStoragePathId ` -ResourceType "StorageContainer" ` -Format $IdFormats.StoragePathArmIdTemplate } - if ($HasTargetResourceGroupId -and !(Test-AzureResourceIdFormat -Data $TargetResourceGroupId -Format $IdFormats.ResourceGroupArmIdTemplate)) { + if (!(Test-AzureResourceIdFormat -Data $TargetResourceGroupId -Format $IdFormats.ResourceGroupArmIdTemplate)) { throw New-InvalidResourceIdProvidedException ` -ResourceId $TargetResourceGroupId ` -ResourceType "ResourceGroup" ` @@ -651,6 +648,30 @@ function New-AzMigrateLocalServerReplication { $customProperties.FabricDiscoveryMachineId = $machine.Id $customProperties.RunAsAccountId = $runAsAccountId $customProperties.SourceFabricAgentName = $sourceDra.Name + + # Validate storage path exists and is in a usable state + $storagePath = Get-AzResource ` + -ResourceId $TargetStoragePathId ` + -ErrorVariable notPresent ` + -ErrorAction SilentlyContinue + if ($null -eq $storagePath) { + throw "Storage path with Id '$TargetStoragePathId' not found. Please provide a valid storage path ARM ID." + } + + # Creation must have succeeded for the storage path to be usable + if ($storagePath.Properties.status.provisioningStatus -ne "Succeeded") { + throw "Storage path '$($storagePath.Name)' has a creation provisioning status of '$($storagePath.Properties.status.provisioningStatus)'. Only storage paths with a successful creation can be used. Please select a different storage path or wait for provisioning to complete." + } + + # The latest operation (ProvisioningState) must also be Succeeded + $provisioningState = $storagePath.Properties.provisioningState + if ($provisioningState -eq "Failed") { + throw "Storage path '$($storagePath.Name)' has a failed provisioning state. The latest operation on this storage path did not succeed. Please resolve the issue and retry." + } + elseif ($provisioningState -ne "Succeeded") { + throw "Storage path '$($storagePath.Name)' has a provisioning state of '$provisioningState'. An operation is currently in progress. Please wait for it to complete and retry." + } + $customProperties.StorageContainerId = $TargetStoragePathId $customProperties.TargetArcClusterCustomLocationId = $arbArgResult.CustomLocation $customProperties.TargetFabricAgentName = $targetDra.Name From 923c5ad873285f1ccf393c6a2114cae584f5abc4 Mon Sep 17 00:00:00 2001 From: Sam Lee Date: Thu, 16 Apr 2026 13:30:07 -0700 Subject: [PATCH 2/7] Updated changelog --- src/Migrate/Migrate/ChangeLog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Migrate/Migrate/ChangeLog.md b/src/Migrate/Migrate/ChangeLog.md index 8242405db2ca..8d20841c4331 100644 --- a/src/Migrate/Migrate/ChangeLog.md +++ b/src/Migrate/Migrate/ChangeLog.md @@ -18,6 +18,12 @@ - Additional information about change #1 --> ## Upcoming Release +* Fixed bugs in `Initialize-AzMigrateLocalReplicationInfrastructure` + - Fixed caller identity resolution to correctly handle Service Principal and Managed Identity account types, with a null-guard for hostname lookup. + - Added cache storage account validations to reject unsupported SKU tiers and storage accounts with public blob access disabled. +* Updated `New-AzMigrateLocalServerReplication` + - Removed redundant conditional guards on mandatory parameter ARM ID validation. + - Added storage path validation to verify existence, successful creation status, and latest operation provisioning state before initiating replication ## Version 2.11.0 * Updated DefaultCrashConsistentFrequencyInMinutes and DefaultAppConsistentFrequencyInMinutes to align with Azure Portal UX for Replication Policy From 077f09a1b8805fb06e91d36c7c79680e3cbe752c Mon Sep 17 00:00:00 2001 From: Sam Lee Date: Thu, 16 Apr 2026 14:04:07 -0700 Subject: [PATCH 3/7] Address PR comments and correct storage account access --- ...alize-AzMigrateLocalReplicationInfrastructure.ps1 | 12 ++++-------- src/Migrate/Migrate/ChangeLog.md | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 index f60adb556f3d..fe329715162d 100644 --- a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 @@ -760,7 +760,7 @@ function Initialize-AzMigrateLocalReplicationInfrastructure { -Location $params.location ` -Kind $params.kind ` -Tags $params.tags ` - -AllowBlobPublicAccess $true + -AllowBlobPublicAccess $false if ($null -ne $cacheStorageAccount -and $null -ne $cacheStorageAccount.ProvisioningState -and @@ -804,14 +804,10 @@ function Initialize-AzMigrateLocalReplicationInfrastructure { throw "Cache Storage Account '$($cacheStorageAccount.StorageAccountName)' uses an unsupported SKU tier '$($cacheStorageAccount.Sku.Tier)'. Only 'Standard' tier storage accounts are supported. Please provide a Standard tier storage account." } - # Validate public network access is not restricted (unless using private endpoints) - if ($null -ne $cacheStorageAccount.PublicNetworkAccess -and + # Validate public network access should not be disabled even for private endpoint + if (![string]::IsNullOrEmpty($cacheStorageAccount.PublicNetworkAccess) -and $cacheStorageAccount.PublicNetworkAccess -eq "Disabled") { - # Public network access is disabled — skip blob access check as private endpoints are in use - } - elseif ($null -ne $cacheStorageAccount.AllowBlobPublicAccess -and - $cacheStorageAccount.AllowBlobPublicAccess -ne $true) { - throw "Cache Storage Account '$($cacheStorageAccount.StorageAccountName)' does not allow public blob access. Please enable 'Allow Blob public access' on the storage account and re-run this command." + throw "Cache Storage Account '$($cacheStorageAccount.StorageAccountName)' does not allow public network access. Please enable 'Public network access' on the storage account and re-run this command." } $params = @{ diff --git a/src/Migrate/Migrate/ChangeLog.md b/src/Migrate/Migrate/ChangeLog.md index 8d20841c4331..939cf304ab1e 100644 --- a/src/Migrate/Migrate/ChangeLog.md +++ b/src/Migrate/Migrate/ChangeLog.md @@ -20,7 +20,7 @@ ## Upcoming Release * Fixed bugs in `Initialize-AzMigrateLocalReplicationInfrastructure` - Fixed caller identity resolution to correctly handle Service Principal and Managed Identity account types, with a null-guard for hostname lookup. - - Added cache storage account validations to reject unsupported SKU tiers and storage accounts with public blob access disabled. + - Added cache storage account validations to reject unsupported SKU tiers and storage accounts with public network access disabled. * Updated `New-AzMigrateLocalServerReplication` - Removed redundant conditional guards on mandatory parameter ARM ID validation. - Added storage path validation to verify existence, successful creation status, and latest operation provisioning state before initiating replication From 7846bad07d8f45f495525f8923c9d6e651ff0bc4 Mon Sep 17 00:00:00 2001 From: Sam Lee Date: Fri, 17 Apr 2026 11:43:47 -0700 Subject: [PATCH 4/7] Small bug fix --- .../custom/New-AzMigrateLocalServerReplication.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 index 72fb137db194..4c02cd17d94c 100644 --- a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 @@ -659,8 +659,8 @@ function New-AzMigrateLocalServerReplication { } # Creation must have succeeded for the storage path to be usable - if ($storagePath.Properties.status.provisioningStatus -ne "Succeeded") { - throw "Storage path '$($storagePath.Name)' has a creation provisioning status of '$($storagePath.Properties.status.provisioningStatus)'. Only storage paths with a successful creation can be used. Please select a different storage path or wait for provisioning to complete." + if ($storagePath.Properties.status.provisioningStatus.status -ne "Succeeded") { + throw "Storage path '$($storagePath.Name)' has a creation provisioning status of '$($storagePath.Properties.status.provisioningStatus.status)'. Only storage paths with a successful creation can be used. Please select a different storage path or wait for provisioning to complete." } # The latest operation (ProvisioningState) must also be Succeeded From bd3fcb894b5aab0b6206f101b190ec0bf18ba730 Mon Sep 17 00:00:00 2001 From: Sam Lee Date: Fri, 17 Apr 2026 14:04:03 -0700 Subject: [PATCH 5/7] Remove unnecessary caller identity resolution check --- ...zMigrateLocalReplicationInfrastructure.ps1 | 40 ++++--------------- src/Migrate/Migrate/ChangeLog.md | 8 ++-- 2 files changed, 11 insertions(+), 37 deletions(-) diff --git a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 index fe329715162d..bd502536fc80 100644 --- a/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/Initialize-AzMigrateLocalReplicationInfrastructure.ps1 @@ -130,9 +130,6 @@ function Initialize-AzMigrateLocalReplicationInfrastructure { Import-Module Az.Resources Import-Module Az.Storage - $hasCacheStorageAccountId = $PSBoundParameters.ContainsKey('CacheStorageAccountId') - - $parameterSetName = $PSCmdlet.ParameterSetName $null = $PSBoundParameters.Remove('ResourceGroupName') $null = $PSBoundParameters.Remove('ProjectName') $null = $PSBoundParameters.Remove('CacheStorageAccountId') @@ -143,14 +140,19 @@ function Initialize-AzMigrateLocalReplicationInfrastructure { $null = $PSBoundParameters.Add('ErrorVariable', 'notPresent') $null = $PSBoundParameters.Add('ErrorAction', 'SilentlyContinue') - # Get subscription Id + # Validate Azure login $context = Get-AzContext + if ($null -eq $context -or $null -eq $context.Account) { + throw "Not logged in to Azure. Please run 'Connect-AzAccount' before running this command." + } + + # Get subscription Id if ([string]::IsNullOrEmpty($SubscriptionId)) { Write-Host "No -SubscriptionId provided. Using the one from Get-AzContext." $SubscriptionId = $context.Subscription.Id if ([string]::IsNullOrEmpty($SubscriptionId)) { - throw "Please login to Azure to select a subscription." + throw "No subscription selected. Please run 'Set-AzContext -SubscriptionId ' or provide -SubscriptionId." } } Write-Host "*Selected Subscription Id: '$($SubscriptionId)'" @@ -165,34 +167,6 @@ function Initialize-AzMigrateLocalReplicationInfrastructure { } Write-Host "*Selected Resource Group: '$($ResourceGroupName)'" - # Verify caller identity - if ($context.Account.Type -eq 'ServicePrincipal') { - $userObject = Get-AzADServicePrincipal -ApplicationID $context.Account.Id - } - elseif ($context.Account.Type -eq 'ManagedService' -or $context.Account.Id.StartsWith("MSI@")) { - $hostname = if ($env:COMPUTERNAME) { $env:COMPUTERNAME } else { $env:HOSTNAME } - if ([string]::IsNullOrEmpty($hostname)) { - throw "Unable to determine the hostname for Managed Identity resolution. Please set the COMPUTERNAME or HOSTNAME environment variable." - } - $userObject = Get-AzADServicePrincipal -DisplayName $hostname - } - else { - $userObject = Get-AzADUser -UserPrincipalName $context.Subscription.ExtendedProperties.Account - - if (-not $userObject) { - $userObject = Get-AzADUser -Mail $context.Subscription.ExtendedProperties.Account - } - - if (-not $userObject) { - $mailNickname = "{0}#EXT#" -f $($context.Account.Id -replace '@', '_') - $userObject = Get-AzADUser -Filter "mailNickname eq '$mailNickname'" - } - } - - if (-not $userObject) { - throw 'User Object Id Not Found!' - } - # Get Migrate Project with ResourceGroupName, Name $null = $PSBoundParameters.Add('ResourceGroupName', $ResourceGroupName) $null = $PSBoundParameters.Add('Name', $ProjectName) diff --git a/src/Migrate/Migrate/ChangeLog.md b/src/Migrate/Migrate/ChangeLog.md index 939cf304ab1e..d11ecfeb0275 100644 --- a/src/Migrate/Migrate/ChangeLog.md +++ b/src/Migrate/Migrate/ChangeLog.md @@ -19,11 +19,11 @@ --> ## Upcoming Release * Fixed bugs in `Initialize-AzMigrateLocalReplicationInfrastructure` - - Fixed caller identity resolution to correctly handle Service Principal and Managed Identity account types, with a null-guard for hostname lookup. - - Added cache storage account validations to reject unsupported SKU tiers and storage accounts with public network access disabled. + - Added early Azure login validation with a clear error message when user is not logged in + - Removed unnecessary caller identity resolution + - Added cache storage account validations to reject unsupported SKU tiers and disabled public network access * Updated `New-AzMigrateLocalServerReplication` - - Removed redundant conditional guards on mandatory parameter ARM ID validation. - - Added storage path validation to verify existence, successful creation status, and latest operation provisioning state before initiating replication + - Added storage path health validation before initiating replication ## Version 2.11.0 * Updated DefaultCrashConsistentFrequencyInMinutes and DefaultAppConsistentFrequencyInMinutes to align with Azure Portal UX for Replication Policy From 1adb9d22c48dc50dd952beba55628450a2a9bcdb Mon Sep 17 00:00:00 2001 From: Sam Lee Date: Fri, 17 Apr 2026 14:23:09 -0700 Subject: [PATCH 6/7] Add null guards to storage path status/state --- .../custom/New-AzMigrateLocalServerReplication.ps1 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 index 4c02cd17d94c..cd1884e59105 100644 --- a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 @@ -659,12 +659,19 @@ function New-AzMigrateLocalServerReplication { } # Creation must have succeeded for the storage path to be usable - if ($storagePath.Properties.status.provisioningStatus.status -ne "Succeeded") { - throw "Storage path '$($storagePath.Name)' has a creation provisioning status of '$($storagePath.Properties.status.provisioningStatus.status)'. Only storage paths with a successful creation can be used. Please select a different storage path or wait for provisioning to complete." + $creationStatus = $storagePath.Properties.status.provisioningStatus.status + if ([string]::IsNullOrEmpty($creationStatus)) { + throw "Storage path '$($storagePath.Name)' creation status is unavailable. Please verify the storage path resource is fully provisioned." + } + if ($creationStatus -ne "Succeeded") { + throw "Storage path '$($storagePath.Name)' has a creation provisioning status of '$creationStatus'. Only storage paths with a successful creation can be used. Please select a different storage path or wait for provisioning to complete." } # The latest operation (ProvisioningState) must also be Succeeded $provisioningState = $storagePath.Properties.provisioningState + if ([string]::IsNullOrEmpty($provisioningState)) { + throw "Storage path '$($storagePath.Name)' provisioning state is unavailable. Please verify the storage path resource is fully provisioned." + } if ($provisioningState -eq "Failed") { throw "Storage path '$($storagePath.Name)' has a failed provisioning state. The latest operation on this storage path did not succeed. Please resolve the issue and retry." } From 04b81dfd79ffbef4f0ec5c84b0a952a3ae4b28ec Mon Sep 17 00:00:00 2001 From: Sam Lee Date: Fri, 17 Apr 2026 14:54:28 -0700 Subject: [PATCH 7/7] Simplify provisioningstate error message --- .../custom/New-AzMigrateLocalServerReplication.ps1 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 index cd1884e59105..ee632e5da62e 100644 --- a/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 +++ b/src/Migrate/Migrate.Autorest/custom/New-AzMigrateLocalServerReplication.ps1 @@ -672,11 +672,8 @@ function New-AzMigrateLocalServerReplication { if ([string]::IsNullOrEmpty($provisioningState)) { throw "Storage path '$($storagePath.Name)' provisioning state is unavailable. Please verify the storage path resource is fully provisioned." } - if ($provisioningState -eq "Failed") { - throw "Storage path '$($storagePath.Name)' has a failed provisioning state. The latest operation on this storage path did not succeed. Please resolve the issue and retry." - } - elseif ($provisioningState -ne "Succeeded") { - throw "Storage path '$($storagePath.Name)' has a provisioning state of '$provisioningState'. An operation is currently in progress. Please wait for it to complete and retry." + if ($provisioningState -ne "Succeeded") { + throw "Storage path '$($storagePath.Name)' has a provisioning state of '$provisioningState'. Only storage paths with a 'Succeeded' provisioning state can be used. Please resolve the issue or select a different storage path." } $customProperties.StorageContainerId = $TargetStoragePathId