Util/Util.psm1
Import-Module -Name $PSScriptRoot\..\Common\Error\Error Import-Module -Name $PSScriptRoot\..\Common\Wrappers\Wrappers function Test-UserLoggedIn { param() if (-not (Get-Variable -Name "RMContext-UserLogin" -ErrorAction SilentlyContinue)) { Write-RMError -Message "Please login using the cmdlet 'Invoke-RMLogin' and try again." return $false } return $true } function Invoke-RMRestMethod { param( [hashtable] $Params ) try { return Invoke-RestMethod -SkipCertificateCheck @Params } catch [System.Exception] { Show-RMError -ErrorObj $PSItem throw } } function Get-RMStringAsHashtable { param( [string] $InputString ) $Result = @{} if (!("" -ne $InputString -and $InputString.Contains("="))) { return $Result } foreach ($item in $InputString.Split(",").Trim()) { $item = $item.Split("=") $Result.add($item[0].Trim(), $item[1].Trim()) } return $Result } function Get-RMStringArrayAsHashtable { param( [string[]] $InputItems ) $Result = @{} if (0 -eq $InputItems.Count) { return $Result } foreach ($item in $InputItems) { if (!$item.Contains("=")) { throw "Invalid token '$item', each token must be of the format 'key=value" } $item = $item.Split("=") $Result.add($item[0].Trim(), $item[1].Trim()) } return $Result } function Get-RMVolumeType { param( [string] $VolumeType ) if ("GP2" -ieq $VolumeType) { return "ssd2" } if ("GP3" -ieq $VolumeType) { return "ssd3" } if ("magnetic" -ieq $VolumeType) { return "magnetic" } if ("IO1" -ieq $VolumeType) { return "iops_ssd" } if ("IO2" -ieq $VolumeType) { return "iops2_ssd" } throw "Unsupported volume type '$VolumeType'" } function Get-RMExcludedMountPoint { param( [System.Object] $Source ) $ReadValue = Read-Host "Enter the mount points to be excluded, separated by commas[None]" if ("" -eq $ReadValue) { return $ReadValue } $MountsToExclude = $ReadValue.Split(",").Trim() if ("windows" -ieq $Source.os_type) { if ($MountsToExclude -contains "c") { Write-RMError -Message "Cannot exclude 'C' drive, please try again." return Get-RMExcludedMountPoint -Source $Source } } elseif ($MountsToExclude -contains "/" -or $MountsToExclude -contains "/boot" -or $MountsToExclude -contains "/usr") { Write-RMError -Message "Cannot exclude mount points '/', '/boot' or '/usr', please try again." return Get-RMExcludedMountPoint -Source $Source } return $ReadValue } function Get-RMSelectedMount { param( [System.Object[]] $MountPoints, [System.Object[]] $DifferenceList, [bool] $IncludeEqual ) $SelectedMountPoints = @() foreach($MountPoint in $MountPoints) { $Result = Compare-Object -ReferenceObject $MountPoint.values -DifferenceObject $DifferenceList -IncludeEqual if ($IncludeEqual) { if ($Result.SideIndicator -contains "==") { $SelectedMountPoints += $MountPoint } } elseif (!($Result.SideIndicator -contains "==")) { $SelectedMountPoints += $MountPoint } } return $SelectedMountPoints } function Compare-RMMountPoint { param( [System.Object] $Source, [System.Object[]] $SourceMountPoints, [System.Object[]] $UserInputMountPoints ) if("windows" -ieq $Source.os_type) { if ($UserInputMountPoints -inotcontains "c") { throw "Cannot exclude 'C' drive, please try again." } } else { if ($SourceMountPoints.values -contains "/" -and $UserInputMountPoints -notcontains "/") { throw "Cannot exclude mount point '/', please try again" } elseif ($SourceMountPoints.values -contains "/boot" -and $UserInputMountPoints -notcontains "/boot") { throw "Cannot exclude mount point '/boot', please try again" } elseif ($SourceMountPoints.values -contains "/usr" -and $UserInputMountPoints -notcontains "/usr") { throw "Cannot exclude mount point '/usr', please try again" } } } function Watch-RMPreflightStatus { param( [string] $PreflightId ) $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Get" Uri = $Uri.Value + "/preflights/" + $PreflightId Headers = $Headers } $Timeout30MinsInSeconds = 30 * 60 $StartTime = [DateTimeOffset]::Now.ToUnixTimeSeconds() Write-Output "Waiting for attribute collection to complete..." | Out-Host $Response = Invoke-RMRestMethod -Params $Params while ($Response.state -ne "success" -and $Response.state -ne "error") { $TimeNow = [DateTimeOffset]::Now.ToUnixTimeSeconds() if (($TimeNow - $StartTime) -gt $Timeout30MinsInSeconds) { throw "Timed out waiting for collection to complete" } Start-Sleep -Seconds 5 $Response = Invoke-RMRestMethod -Params $Params } return $Response } function Watch-RMTargetInventoryStatus { param( [string] $TargetInventoryId ) $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Get" Uri = $Uri.Value + "/targetinventories/" + $TargetInventoryId Headers = $Headers } $Timeout30MinsInSeconds = 30 * 60 $StartTime = [DateTimeOffset]::Now.ToUnixTimeSeconds() Write-Output "Waiting for target inventory to complete..." | Out-Host $Response = Invoke-RMRestMethod -Params $Params while ($Response.state -ne "success" -and $Response.state -ne "error") { $TimeNow = [DateTimeOffset]::Now.ToUnixTimeSeconds() if (($TimeNow - $StartTime) -gt $Timeout30MinsInSeconds) { throw "Timed out while waiting for target inventory to complete" } Start-Sleep -Seconds 5 $Response = Invoke-RMRestMethod -Params $Params } return $Response } function Get-RMWindowsOSMMapping { param() # ME OSM name to user label return @{ "Windows 10 Pro" = "Windows 10 Professional" "Windows 10 Enterprise" = "Windows 10 Enterprise" "Windows Server 2008 R2 SERVERSTANDARD" = "Windows Server 2008 R2 Standard" "Windows Server 2008 R2 SERVERDATACENTER" = "Windows Server 2008 R2 Datacenter" "Windows Server 2012 SERVERSTANDARD" = "Windows Server 2012 Standard" "Windows Server 2012 SERVERDATACENTER" = "Windows Server 2012 Datacenter" "Windows Server 2012 R2 SERVERSTANDARD" = "Windows Server 2012 R2 Standard" "Windows Server 2012 R2 SERVERDATACENTER" = "Windows Server 2012 R2 Datacenter" "Windows Server 2016 SERVERSTANDARD" = "Windows Server 2016 Standard" "Windows Server 2016 SERVERSTANDARDCORE" = "Windows Server 2016 Standard Core" "Windows Server 2016 SERVERDATACENTER" = "Windows Server 2016 Datacenter" "Windows Server 2016 SERVERDATACENTERCORE" = "Windows Server 2016 Datacenter Core" "Windows Server 2019 SERVERSTANDARD" = "Windows Server 2019 Standard" "Windows Server 2019 SERVERSTANDARDCORE" = "Windows Server 2019 Standard Core" "Windows Server 2019 SERVERDATACENTER" = "Windows Server 2019 Datacenter" "Windows Server 2019 SERVERDATACENTERCORE" = "Windows Server 2019 Datacenter Core" "Windows Server 2022 SERVERSTANDARD" = "Windows Server 2022 Standard" "Windows Server 2022 SERVERSTANDARDCORE" = "Windows Server 2022 Standard Core" "Windows Server 2022 SERVERDATACENTER" = "Windows Server 2022 Datacenter" "Windows Server 2022 SERVERDATACENTERCORE" = "Windows Server 2022 Datacenter Core" } } function Get-RMLinuxOSMMapping { param() # ME OSM name to user label return @{ "RHEL7" = "Red Hat Enterprise Linux Server 7.9" "CENTOS7" = "CentOS 7.9" "UBUNTU1604LTS" = "Ubuntu 16.04 LTS" "SLES15SP1" = "SUSE Linux Enterprise Server 15 SP1" } } function Get-RMOSMMappingBySource { param( [System.Object] $Source ) $ResultOSMMapping = @{} $OSMMapping = @{} if ($Source.os_type -eq "windows") { $OSMMapping = Get-RMWindowsOSMMapping } else { $OSMMapping = Get-RMLinuxOSMMapping } $SourceMigrationState = $Source.attributes.os.source_migration_state | ConvertFrom-Json -Depth 100 foreach ($UpgradeOption in $SourceMigrationState.upgrade_options) { # Mapping of label to ME OSM name - this will be helpful as the user will be # providing labels and we need to send ME OSM name to ME. $ResultOSMMapping.Add($OSMMapping[$UpgradeOption], $UpgradeOption) } return $ResultOSMMapping } function Add-RMResizeMount { param( [string[]] $SelectedMounts, [hashtable] $ResizeMounts, [object] $Source ) $ResizeMountList = @() $ResizeMounts.keys | ForEach-Object { $ResizeMountList += $_ } $Result = Compare-Object -ReferenceObject $SelectedMounts -DifferenceObject $ResizeMountList -IncludeEqual if ($Result.SideIndicator -contains "=>") { Write-RMError -Message "Resize mount points contains a mount point that has not been selected for migration, please check and try again" return $false } $IsValidData = $true $MountsResize = @{} $SourceMountPointObjects = Get-RMMountPointObject -Source $Source foreach ($Mount in $ResizeMounts.keys) { foreach ($MountPoint in $SourceMountPointObjects) { $MountPath = $MountPoint.path if ($MountPath -ne $Mount) { continue } $TotalSpace = [math]::round($MountPoint.size_kb/(1024 * 1024), 2) $UsedSpace = [math]::round($MountPoint.used_kb/(1024 * 1024), 2) $ResizeValue = $ResizeMounts[$Mount] if ($ResizeValue.Contains(".")) { Write-RMError -Message "Mount point '$MountPath' contains non-integer value $ResizeValue , please enter an integer value only" -Category InvalidData $IsValidData = $false continue } $ResizeValue = $ResizeValue -as [int] if (-not($ResizeValue -gt $UsedSpace -and $ResizeValue -lt $TotalSpace)) { Write-RMError -Message "Resize value for mount point '$MountPath' is not valid, resize value should not be greater than the current total size or less than the used size" -Category InvalidData $IsValidData = $false continue } $MountResizeInKiB = $ResizeValue * 1024 * 1024 $MountsResize.Add($MountPath, $MountResizeInKiB) break } } if (!$IsValidData) { return $null } return $MountsResize } function Get-RMMountPointObject { param( [System.Object] $Source ) $MountPoints = @() if ("windows" -ieq $Source.os_type) { foreach ($Mount in $Source.attributes.storage.mounts.psobject.properties.value) { $MountPoints += $Mount } } else { foreach ($Mount in $Source.attributes.storage.mounts.psobject.properties.value) { if ("disk" -ieq $Mount.nature -or "subvolume" -ieq $Mount.nature -and "squashfs" -ine $Mount.fs_type) { $MountPoints += $Mount } } } return $MountPoints } function Get-RMMigrationInstruction { param ( [hashtable] $MigrationInstructions ) $MigrationInstructionList = @() if ($null -ne $MigrationInstructions) { $MigrationInstructionList = $MigrationInstructions.Keys | foreach-object { "$_/$($MigrationInstructions[$_])"} } return $MigrationInstructionList } function Get-RMPartition { param ( [System.Object[]] $SelectedMounts ) $Partitions = @() foreach($MountPoint in $SelectedMounts) { $Partitions += $MountPoint.mount_point } return $Partitions } function Get-MigrationProfile { param( [string] $MigrationProfileId ) $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" $Uri = Get-Variable -Name "RMContext-ReactorURI" $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.Value.token } $Params = @{ Method = "Get" Uri = $Uri.Value + "/migrationprofiles/" + $MigrationProfileId Headers = $Headers ContentType = "application/json" } return Invoke-RMRestMethod -Params $Params } function Get-RMResizeMountsPoint { param ( [string[]] $ResizeMountPoints, [array] $SelectedMountPoints, [System.Object] $Source ) $MountPointList = @() $ResizeMounts = Get-RMStringArrayAsHashtable -InputItems $ResizeMountPoints foreach($SelectedMountPoint in $SelectedMountPoints) { $MountPointList += $SelectedMountPoint.values } $MountsResize = Add-RMResizeMount -SelectedMounts $MountPointList -ResizeMounts $ResizeMounts -Source $Source if($null -eq $MountsResize) { return } return $MountsResize } function Get-RMInteractiveMountsResize { param ( [array] $SelectedMountPoints, [System.Object] $Source ) $ResizeMounts = @{} $MountPointList = @() $SelectedMountPoints | ForEach-Object { $MountPointList += $_.values } $SourceMountPointObjects = Get-RMMountPointObject -Source $Source foreach ($Mount in $MountPointList) { foreach ($MountPoint in $SourceMountPointObjects) { if ($MountPoint.path -ne $Mount) { continue } $TotalSpace = [math]::round($MountPoint.size_kb/(1024 * 1024), 2) $UsedSpace = [math]::round($MountPoint.used_kb/(1024 * 1024), 2) $ReadValue = Read-Host "Enter new size in GiB for mount point $Mount (used space $UsedSpace of $TotalSpace)[$TotalSpace]" if ("" -ne $ReadValue) { $ResizeMounts.Add($Mount, $ReadValue) } break } } if ($ResizeMounts.Count -gt 0) { $MountsResize = Add-RMResizeMount -SelectedMounts $MountPointList -ResizeMounts $ResizeMounts -Source $Source if ($null -eq $MountsResize) { return } } return $MountsResize } function Get-RMMoveGroupList { param ( [string] $OrganizationId, [int] $PageNumber ) $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" -ValueOnly $Uri = Get-Variable -Name "RMContext-ReactorURI" -ValueOnly $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.token } $Params = @{ Method = "Get" Uri = $Uri + "/organizations/" + $OrganizationId + "/movegroups?size=25&page=" + $PageNumber +"&sort=name,desc" Headers = $Headers } $Response = Invoke-RMRestMethod -Params $Params return $Response } function Get-MoveGroupByName { param ( [string] $MoveGroupName, [string] $OrganizationId ) $MoveGroupList = @() $Response = Get-RMMoveGroupList -OrganizationId $OrganizationId -PageNumber 0 $MoveGroupList += $Response $MoveGroup = Get-MoveGroup -MoveGroupName $MoveGroupName -MoveGroupList $MoveGroupList.content if ($null -eq $MoveGroup) { for ($index = 1; $index -lt $Response.page.totalPages; $index++) { $MoveGroupList = Get-RMMoveGroupList -OrganizationId $OrganizationId -PageNumber $index $MoveGroup = Get-MoveGroup -MoveGroupName $MoveGroupName -MoveGroupList $MoveGroupList.content if ($null -ne $MoveGroup) { return $MoveGroup } } } else { return $MoveGroup } return $null } function Get-MoveGroup { param( [string] $MoveGroupName, [array] $MoveGroupList ) foreach($MoveGroup in $MoveGroupList) { if ($MoveGroupName -eq $MoveGroup.name) { return $MoveGroup } } return $null } function Get-RMEntitlement { param() $CurrentProjectId = Get-Variable -Name "RMContext-CurrentProjectId" -ValueOnly $RMLoginResult = Get-Variable -Name "RMContext-UserLogin" -ValueOnly $Uri = Get-Variable -Name "RMContext-ReactorURI" -ValueOnly $Headers = @{ Accept = "application/rm+json" "X-Auth-Token" = $RMLoginResult.token } $Params = @{ Method = "Get" Uri = $Uri + "/organizations/" + $CurrentProjectId + "/entitlements" Headers = $Headers } $Entitlements = Invoke-RMRestMethod -Params $Params foreach ($Entitlement in $Entitlements.content) { $Remaining = $Entitlement.total - $Entitlement.used if ($Remaining -ge 1) { return $Entitlement } } throw "Not enough entitlements available to start the migration" } function Out-MigrationIdFromResponse { param( [System.Object] $Response ) $MigrationId = "" # we expect 3 links in the response if ($Response.links.Count -lt 3) { return $MigrationId } if ($Response.links[1].rel -ine "migrations") { return $MigrationId } $SplitData = $Response.links[1].href.split("/") if ($SplitData.Count -lt 7) { return $MigrationId } $MigrationId = $SplitData[6].SubString(0, $SplitData[6].IndexOf("{")) Write-Output "Migration started successfully, migration ID: $MigrationId" } |