MigrationProfile/AzureMigrationProfile.psm1
Import-Module -Name $PSScriptRoot\..\Util\Util function New-RMAzureMigrationProfile { param( [Parameter(Mandatory)] [System.Object] $CloudAccount, [Parameter(Mandatory)] [System.Object] $CloudAttributes, [Parameter(Mandatory)] [System.Object] $Entitlement, [Parameter(Mandatory)] [System.Object] $Source, [Parameter(Mandatory)] [string] $TargetVMName, [Parameter(Mandatory)] [string] $TransferMethod, [Parameter(Mandatory)] [string] $ResourceGroup, [string] $ResourceGroupRegion, [Parameter(Mandatory)] [System.Object] $VMSize, [System.Object] $DiskTypeMappings, [string] $VolumeType, [Parameter(Mandatory)] [System.Object[]] $MountPoints, [Parameter(Mandatory)] [hashtable] $ResizeMountPoints, [Parameter(Mandatory)] [string] $VirtualNetwork, [Parameter(Mandatory)] [string] $DestinationNetworkName, [Parameter(Mandatory)] [bool] $AssignPublicIP, [string] $StaticPrivateIP, [string] $SecurityGroup, [Parameter(Mandatory)] [bool] $DisableTargetDNSRegistration, [hashtable] $InstanceTags, [string] $AvailabilityZone, [string] $AvailabilitySet, [System.Object] $FaultDomainCount, [System.Object] $UpdateDomainCount, [Parameter(Mandatory)] [bool] $EnableBootDiagnostics, [string] $StorageAccount, [string] $EncryptionSet, [Parameter(Mandatory)] [bool] $EnableHybridUseBenefit, [Parameter(Mandatory)] [bool] $InPlaceUpgrade, [System.Object] $UpgradeOSVersion, [Parameter(Mandatory)] [bool] $ShutdownSource, [Parameter(Mandatory)] [bool] $ShutdownTarget, [Parameter(Mandatory)] [bool] $RemoveRMSAgent, [hashtable] $MigrationInstructions ) if ("" -ne $ResourceGroupRegion) { $ReturnedValue = Get-ResourceGroupRegionByUserInput -ResourceGroupRegion $ResourceGroupRegion -CloudAccount $CloudAccount if ($null -eq $ReturnedValue) { throw "Region '$ResourceGroupRegion' does not exist." } else { $ResourceGroupRegion = $ReturnedValue } } $license_type = $null if ($EnableHybridUseBenefit) { $license_type = "Windows_Server" } $EncryptionSetId = $null if ("" -ne $EncryptionSet) { $EncryptionSetId = Get-DiskEncryptionSetIdByName -EncryptionSetName $EncryptionSet -CachedCloudAttributes $CloudAttributes } $VolumeType = Get-VolumeType -VolumeType $VolumeType if ("" -eq $VolumeType) { # For the interactive case, take volume type of the first disk - this is what the UI is doing. $VolumeType = $DiskTypeMappings[0]["type"] } else { $DiskTypeMappings = @() $ReturnedValue = Get-DiskTypeMappingBySource -Source $Source -VolumeType $VolumeType -IsInteractive $false if ($ReturnedValue -is [hashtable]) { # The method "Get-DiskTypeMappingBySource" returns an array of hashtables, but it # has been observed that if the source contains a single disk, the returned value # is of type HashTable; hence we are checking the type and re-adding it to an array $DiskTypeMappings += $ReturnedValue } else { $DiskTypeMappings = $ReturnedValue } } $VirtualNetworkResourceGroup = $null $VirtualNetworkResourceGroup = Get-VirtualNetworkResourceGroup -CachedCloudAttributes $CloudAttributes -VirtualNetworkName $VirtualNetwork if ($null -eq $VirtualNetworkResourceGroup) { throw "Virtual network '$VirtualNetwork' does not exists, cannot start migration" } $SecurityGroupNode = $null if ("" -ne $SecurityGroup -and $null -ne $SecurityGroup) { $SecurityGroupNode = Get-SecurityGroup -SecurityGroupName $SecurityGroup -CachedCloudAttributes $CloudAttributes if ($null -eq $SecurityGroupNode) { throw "Security group '$SecurityGroup' does not exists, cannot start migration" } } if (!$VMSize.vmsizeSupported) { $Name = $VMSize.name throw "RiverMeadow does not support VM size '$Name', please use a different VM size and try again." } if ("" -ne $AvailabilityZone -and $VMSize.availability_zones -notcontains $AvailabilityZone) { $Name = $VMSize.name throw "The VM size '$Name' does not support the availability zone $AvailabilityZone" } $AvailabilitySetHash = @{} if ($null -eq $FaultDomainCount -or $null -eq $UpdateDomainCount) { $AvailabilitySetHash.Add("name", $AvailabilitySet) } else { $AvailabilitySetHash.Add("name", $AvailabilitySet) $AvailabilitySetHash.Add("fault_domain_count", $FaultDomainCount) $AvailabilitySetHash.Add("update_domain_count", $UpdateDomainCount) } $CurrentTime = Get-Date -Format "yyyy/MM/dd HH:mm:ss" $MigrationProfile = @{ "name"= "powershell-" + $Source.host + "-" + $CurrentTime "tags"= @() "entitlement"=$Entitlement.id "cloud_account"=$CloudAccount.id "is_data_only"= $false "is_vdi"= $false "appliance_id"= $CloudAccount.appliance.id "schedule"= $null "transfer_mode"= "run-once" "sources"= @( @{ "source"= $Source.id "transfer_type"= $TransferMethod "target_config"= @{ "vm_details"= @{ "vm_name"= $TargetVMName "vapp_name"= $TargetVMName "tags"= $InstanceTags "resource_group"= $ResourceGroup "flavor"= @{ "flavor_type"= $VMSize.name "volume_type"= $VolumeType } "enable_accelerated_networking"= $VMSize.enable_accelerated_networking "disk_type_mappings"= $DiskTypeMappings "license_type"= $license_type "availability_set"= $AvailabilitySetHash "availability_zone_id"= $AvailabilityZone "enable_boot_diagnostics"= $EnableBootDiagnostics "boot_diagnostics_storage_account"= $StorageAccount "disk_encryption_set_id"= $EncryptionSetId } "properties"= @{ "network"= @{ "interfaces"= @{ "eth0"= @{ "ip_type"= "dhcp" "type"= "Ethernet" "network_name"= $DestinationNetworkName "vnet"= $VirtualNetwork "assign_public_ip"= $AssignPublicIP "ip_addr"= $StaticPrivateIP "resource_group"= $VirtualNetworkResourceGroup "security_group"= $SecurityGroupNode } } "automatic_dns_registration"= !$DisableTargetDNSRegistration } "selected_mounts"= $MountPoints "name"= $TargetVMName "mounts_new_size"= $ResizeMountPoints } "options"= @{ "region"= $CloudAttributes.properties.subscriptions[0].regions[0].name "resource_group_region"= $ResourceGroupRegion "subscription_id"= $CloudAttributes.properties.subscriptions[0].id "network"= @{ "name"= $VirtualNetwork "resource_group"= $VirtualNetworkResourceGroup } } } "os_type"= $Source.os_type "name"= $Source.hostname "collection_type"= $null "shutdown_source"= $ShutdownSource "shutdown_target"= $ShutdownTarget "remove_target_agent"= $RemoveRMSAgent "in_place_upgrade"= $InPlaceUpgrade "upgrade_os_version"= $UpgradeOSVersion "migration_instructions"= $MigrationInstructions "data_transfer_port"= $null "ignore_validation_errors"= $false #TODO - handle this when preflights are added "preflight_warning"= $false #TODO - handle this when preflights are added } ) } # Giving max depth otherwise the cmdlet 'ConvertTo-Json' will truncate the JSON $MigrationProfileJson = $MigrationProfile |ConvertTo-Json -Depth 100 $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 = "Post" Uri = $Uri + "/migrationprofiles" Body = $MigrationProfileJson ContentType = "application/json" Headers = $Headers } Invoke-RMRestMethod -Params $Params } function Get-VolumeType { param( [string] $VolumeType ) $VolumeTypes = @{ "Standard_SSD" = "StandardSSD_LRS" "Standard_HDD" = "Standard_LRS" "Premium_SSD" = "Premium_LRS" } return $VolumeTypes[$VolumeType] } function Get-DiskEncryptionSetIdByName { param( [string] $EncryptionSetName, [System.Object] $CachedCloudAttributes ) $DiskEncryptionSets = $CachedCloudAttributes.properties.subscriptions[0].regions[0].disk_encryption_sets foreach ($DiskEncryptionSet in $DiskEncryptionSets) { if ($DiskEncryptionSet.name -ieq $EncryptionSetName) { return $DiskEncryptionSet.id } } return $null } function Get-DiskTypeMappingBySource { param( [System.Object] $Source, [System.Object] $VMSize, [string] $VolumeType, [bool] $IsInteractive ) $DiskTypeMappings = @() foreach ($Disk in $Source.attributes.storage.disks.psobject.Properties.Value) { if ($IsInteractive) { $Size = $Disk.size_kb/(1024*1024) $Size = [math]::round($Size, 2) $VolumeType = "Standard_SSD" $ReadValue = "" if ($VMSize.premium_disk_support) { $ReadValue = Read-Host "Enter the volume type for disk with size $Size GiB (Standard_SSD, Standard_HDD, Premium_SSD)[Standard_SSD]" } else { $ReadValue = Read-Host "Enter the volume type for disk with size $Size GiB (Standard_SSD, Standard_HDD)[Standard_SSD]" } if ("" -ne $ReadValue) { $VolumeType = $ReadValue } $VolumeType = Get-VolumeType -VolumeType $VolumeType } $DiskMapping = @{ "source_disk_identifier" = $Disk.device "type" = $VolumeType } $DiskTypeMappings += $DiskMapping } return $DiskTypeMappings } function Get-VirtualNetworkResourceGroup { param( [System.Object] $CachedCloudAttributes, [string] $VirtualNetworkName ) foreach($Network in $CachedCloudAttributes.properties.subscriptions[0].regions[0].networks) { if ($Network.name -ieq $VirtualNetworkName) { return $Network.resource_group } } return $null } function Get-SecurityGroup { param( [string] $SecurityGroupName, [System.Object] $CachedCloudAttributes ) if ("" -eq $SecurityGroup) { return $null } foreach($SecurityGroup in $CachedCloudAttributes.properties.subscriptions[0].regions[0].security_groups) { if ($SecurityGroup.name -eq $SecurityGroupName) { $Result = @{ "name" = $SecurityGroupName "resource_group" = $SecurityGroup.resource_group } return $Result } } return $null } function Get-VMSizeByName { param( [string] $VMSizeName, [System.Object] $CloudAttributes ) foreach($VMSize in $CloudAttributes.properties.subscriptions[0].regions[0].vm_sizes) { if ($VMSize.name -ieq $VMSizeName) { return $VMSize } } return $null } function Get-ResourceGroupRegionByUserInput { param( [string] $ResourceGroupRegion, [System.Object] $CloudAccount ) $CloudAttributesSummary = Get-CloudAttributesSummary -CloudAccount $CloudAccount foreach ($Subscription in $CloudAttributesSummary.properties.subscriptions) { if (-not($Subscription.id -eq $CloudAccount.appliance.cloud_properties.subscription_id)) { continue } foreach ($Region in $Subscription.regions) { if ($Region.name -eq $ResourceGroupRegion -or $Region.label -eq $ResourceGroupRegion) { return $Region.name } } } return $null } Export-ModuleMember -Function New-RMAzureMigrationProfile, Get-VMSizeByName, Get-DiskTypeMappingBySource |