Need help translating azure recoveryservices powershell to .net azure resourcemanagement sDK calls

67 views Asked by At

I made the following powershell script to restore a database from azure recovery services. I now need to repeat this in c# using the Azure.ResourceManager SDK.

I have a hard time matching the various commandlets to the equivalent invocations in the SDK, it seems to be rather poorly documented and uses a different naming convention. Microsoft being microsoft also seems to change naming every minor version.

If anyone could tell met what the equivalent is of things like Get-AzRecoveryServicesBackupContainer -ContainerType AzureVMAppContainer -VaultId $vault.ID -FriendlyName "abcd" in the .net azure resource management SDK....

The core of the script I made that I try to translate to c#:

function Restore-OTADatabaseFromAzure {
    param (
        [string] $SourceSqlInstanceName,
        [string] $SourceSqlAGName,
        [string] $SourceDatabaseName,
        [string] $NewDatabaseName,
        [string] $HaNode,
        [string] $DataPath,
        [string] $LogPath
    )

    try 

        Select-azSubscription -Subscription $subscription
        
        #https://learn.microsoft.com/en-us/rest/api/recoveryservices/vaults/get?view=rest-recoveryservices-2023-04-01&tabs=HTTP
        $vault = Get-AzRecoveryServicesVault  -ResourceGroupName $resourceGroupName -Name $vaultName  -Verbose 
        #Write-Host "Vault: $($vault.ID)"

        #$Container = Get-AzRecoveryServicesBackupContainer -ContainerType AzureVMAppContainer -VaultId $vault.ID -FriendlyName "abcd"
        #Write-Host "Container: $($container.Name)"

        $backupItem = Get-AzRecoveryServicesBackupItem -BackupManagementType AzureWorkload -WorkloadType MSSQL -Name "SQLDataBase;$($SourceSqlAGName);$($SourceDatabaseName)" -VaultId $vault.ID  -ProtectionStatus Healthy

        $startDate = (Get-Date).AddDays(-10).ToUniversalTime()
        $endDate = (Get-Date).ToUniversalTime()
        $recoveryPoints = Get-AzRecoveryServicesBackupRecoveryPoint -Item $backupItem -VaultId $vault.ID -StartDate $startdate -EndDate $endDate
        $latestRecoveryPoint = Get-AzRecoveryServicesBackupRecoveryPoint -Item $backupItem -VaultId $vault.ID -RecoveryPointId $recoveryPoints[0].RecoveryPointId

        # Restoring Friendly name is case-sensitive
        $TargetContainer =  Get-AzRecoveryServicesBackupContainer -ContainerType AzureVMAppContainer -VaultId $vault.ID -FriendlyName $HaNode.ToLower()

        #Write-Host "TagetContainer: $($TargetContainer.Name)" warning! case sensitive names
        $TargetInstance = Get-AzRecoveryServicesBackupProtectableItem -WorkloadType MSSQL -ItemType SQLInstance -Name "sqlinstance;ota" -ServerName "servername..." -VaultId $vault.ID


        $recoveryconfig = Get-AzRecoveryServicesBackupWorkloadRecoveryConfig -RecoveryPoint $latestRecoveryPoint -TargetItem $TargetInstance -AlternateWorkloadRestore -VaultId $vault.ID -TargetContainer $TargetContainer 


        $recoveryconfig.targetPhysicalPath
        $recoveryconfig.RestoredDBName = $NewDatabaseName

        $recoveryconfig.targetPhysicalPath[0].TargetPath = "$($DataPath)$($NewDatabaseName).mdf"
        $recoveryconfig.targetPhysicalPath[1].TargetPath = "$($LogPath)\$($NewDatabaseName).ldf"


        $recoveryconfig | Format-List

        $recoveryconfig.targetPhysicalPath

        # run the actual restore.
        $RestoreJob = Restore-AzRecoveryServicesBackupItem -WLRecoveryConfig $recoveryconfig -VaultId $vault.ID 

        do
        {
            $RestoreJob = Get-AzRecoveryServicesBackupJob -JobId $RestoreJob.JobID -VaultId $vault.ID
            Write-Host "Restoring: $($RestoreJob.Status), $($RestoreJob.StartTime), $($RestoreJob.EndTime), $($RestoreJob.Duration), $($RestoreJob.Operation)"
            Start-Sleep -Seconds 5
        }
        while (($RestoreJob.Status -ne "Completed") -And ($RestoreJob.Status -ne "Failed"))

        if ($RestoreJob.Status -eq "Completed") {
            return $true
        }
        else {
            return $false
        }
    }
    catch {
        return $false
    }
}

I made a start:

 // using Azure.Identity;
            var options = new ClientCertificateCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
            };

            // https://learn.microsoft.com/dotnet/api/azure.identity.clientcertificatecredential
            var clientCertCredential = new ClientCertificateCredential(
                tenantId, clientId, clientCertificate, options);


            ArmClient client = new ArmClient(clientCertCredential);

            SubscriptionResource subscription = client.GetSubscriptionResource(new ResourceIdentifier($"/subscriptions/{subscriptionId}"));
            ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();
            ResourceGroupResource resourceGroup = await resourceGroups.GetAsync(resourceGroupName);


            //$vault = Get-AzRecoveryServicesVault  -ResourceGroupName $resourceGroupName -Name $vaultName  -Verbose 
            RecoveryServicesVaultResource vault = await resourceGroup.GetRecoveryServicesVaultAsync(vaultName);

Just pointing to a proper example or such is fine to. I want to do the work, but I can't find the information I need.

1

There are 1 answers

5
jdweng On

My college System Engineering Teach said requirements come from two places 1) Specifications 2) Visions. It is the job of a System Engineer to turn Visons into Specifications.

You are the System Engineer. You have to work with your customer to turn his Visions into Specifications.

In my opinion "Written in c# is a Vision", not a Specification. It doesn't specify what libraries you can use or not use. Can you use libraries from Github? Can you use 3rd party libraries? c# is managed and runs slow. So can you write code in c++ when necessary to meet speed requirements? Can you use compiled Matlab dlls?

Written in c# also doesn't say if you can or cannot use Process Class to call executables and scripts. Can you use BAT files? Can you use Python? It doesn't say the type of projects you can use. Can you use Windows Forms? Can you have more than one project? Can you use WPF or ASP.Net? Do you need to target CORE or can you use Net? Do code need to be run by an ADMIN or can normal users run code?

Both c# and Powershell use Net/Core Libraries. There is really no differences between written in c# and Powershell. Many c# libraries are not well documented especially the ones that interface with Windows System Methods. The equivalent Powershell are just wrappers that have well documented interfaces to the same methods as c#.

So why struggle interfacing with the c# libraries when you can do same in Powershell?