Search code examples
powershellazure-powershell

How to call one ps1 from other ps1 with parameters


The below is my powershell script which will do backup if azure VM using recovery service vault. Now I have separated my Powershell scripts one for creating RSV,creating new backup policy,calling backup powershell script and disable the policy.Second powershell script will only do the backup of VM using existing RSV.So in order to call backup script from backuppolicy script along with parameters I am getting errors for multiple ways I tried. I couldn't find the best way to do this.Please help me to understand how to call another powershell script from one powershell script with arguments/parameters.

The below commands I tried in my else block to call other powershell script with arguments but none of them are giving solution and throwing errors.

**

# Invoke-Command -ComputerName server -ScriptBlock $sb
    # [PowerShell]::Create().AddCommand($PSScriptRoot+ "\vmbackup.ps1").AddParameters(@{ Storagetype = "LocallyRedundant"; WorkLoadType = "AzureVM" }).Invoke()
        # & ((Split-Path $MyInvocation.InvocationName) + "\vmbackup.ps1")
        # Invoke-Item (start powershell ((Split-Path $MyInvocation.InvocationName) + "\vmbackup.ps1"))
        #  $script = $PSScriptRoot+"\vmbackup.ps1"
        #  . $script -SourceVMname `"$SourceVMname`" -WorkLoadType `"$WorkLoadType`"
        # "-file $PSScriptRoot\vmbackup.ps1 -SourceVMname `"$SourceVMname`" -WorkLoadType `"$WorkLoadType`""
        # & .\vmbackup.ps1 $WorkLoadType $SourceVMname
        # Invoke-Expression -Command ".\vmbackup.ps1 $WorkLoadType $SourceVMname" 
        # Invoke-Expression "$PSScriptRoot\vmbackup.ps1" -ContainerType $WorkLoadType -FriendlyName $SourceVMname
        # Invoke-Expression "$PSScriptRoot\vmbackup.ps1" $WorkLoadType $SourceVMname

**

vmbackuppolicy.ps1

####################### Paramaters for the VM Backup Process #######################
param (
    [Parameter(Mandatory = $false)][String]$ResourceGroupName,
    [Parameter(Mandatory = $false)][String]$SourceVMname,
    [Parameter(Mandatory = $false)][String]$RSVaultname,
    [Parameter(Mandatory = $false)][String]$PolicyName,
    [Parameter(Mandatory = $false)][String]$Location,
    [Parameter(Mandatory = $false)][String]$Storagetype,
    [Parameter(Mandatory = $false)][String]$WorkLoadType
)

 $argumentList = @()
$argumentList += ("`"$WorkLoadType`"", "`"$SourceVMname`"")
####################### Connecting to Azure via Service principal and install the AZ modules #######################
Write-Host "Check for AZ modules and install the AZ modules if not available"
    if (-not(Get-Module -Name Az.Accounts -ListAvailable)){
        Write-Warning "Module 'Az.Accounts' is missing or out of date. Installing module now."
        Install-Module -Name Az.Accounts, Az.Resources, Az.Automation, Az.RecoveryServices -Scope CurrentUser -Force -AllowClobber
    }

####################### Registering the Azure Recovery Service provider in the subscription #######################

Write-Host "Registering the Azure Recovery Service provider in the subscription"
try {
    Register-AzResourceProvider -ProviderNamespace "Microsoft.RecoveryServices" -ErrorAction SilentlyContinue
}
catch {
    $message = $_
    Write-Warning "An error occurred! $message"
}

#######################  Check if RSV is exist,create if not exist already and setup vault context ####################### 
Write-Host "Check if RSV is exist,create if not exist already and setup vault context"
Get-AzRecoveryServicesVault -ResourceGroupName $ResourceGroupName -Name $RSVaultname -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
    New-AzRecoveryServicesVault -Name $RSVaultname -ResourceGroupName $ResourceGroupName -Location $Location
    Get-AzRecoveryServicesVault -Name $RSVaultname | Set-AzRecoveryServicesVaultContext


####################### Fetching vault resource values #######################
Write-Host "Fetching vault resource values"
$targetVault = Get-AzRecoveryServicesVault -ResourceGroupName $ResourceGroupName -Name $RSVaultname
$targetVault.ID

####################### Setting up VaultContext using Vault and Setting up Storage redundancy #######################
Write-Host "Setting up VaultContext using Vault and Setting up Storage redundancy"
Set-AzRecoveryServicesVaultContext -Vault $targetVault
Set-AzRecoveryServicesBackupProperty -Vault $targetVault -BackupStorageRedundancy $Storagetype

####################### Setting up new backup policy #######################
Get-AzRecoveryServicesBackupProtectionPolicy -Name $PolicyName -VaultId $targetVault.ID -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
    Write-Host "Setting up a new valid Backup Policy"
    $schPol = Get-AzRecoveryServicesBackupSchedulePolicyObject -WorkloadType $WorkLoadType
    $UtcTime = Get-Date -Date 0001-01-01T00:00:00 #This is the time that you want to start the backup
    $UtcTime = $UtcTime.ToUniversalTime()
    $schpol.ScheduleRunTimes[0] = $UtcTime
    $retPol = Get-AzRecoveryServicesBackupRetentionPolicyObject -WorkloadType $WorkLoadType
    New-AzRecoveryServicesBackupProtectionPolicy -Name $PolicyName -WorkloadType $WorkLoadType -RetentionPolicy $retPol -SchedulePolicy $schPol -VaultId $targetVault.ID
}
$pol = Get-AzRecoveryServicesBackupProtectionPolicy -Name $PolicyName -VaultId $targetVault.ID
$pol

####################### Enable Backup protection in the new Policy #######################
Write-host "Enable Backup protection in the $PolicyName"
try {
   
    Enable-AzRecoveryServicesBackupProtection -ResourceGroupName $ResourceGroupName -Name $SourceVMname -Policy $pol -ErrorAction SilentlyContinue
}
catch {
    $message = $_
    Write-Warning "An error occurred! $message"
}

####################### Checking the status of backup jobs and wait until its configuring the backup #######################
Write-Host "Checking the status of Configure backup jobs and wait until its configuring the backup"
$ConfigureBackup=Get-AzRecoveryservicesBackupJob
while ($ConfigureBackup.Status -eq "In progress") {
    start-sleep -s 30
    write-host "Configure Backup is still in progress"
}
$script = $PSScriptRoot+"\vmbackup.ps1"
& $script


####################### Disable backup protection in the RSV #######################
Write-Host "Disable backup protection in the RSV"
try {
    $containers = Get-AzRecoveryServicesBackupContainer -ContainerType $WorkLoadType -FriendlyName $SourceVMname
    $backupItems = Get-AzRecoveryServicesBackupItem -Container $containers[0] -WorkloadType $WorkLoadType
    # Disble the backup protection in RSV to delete backup items
    Disable-AzRecoveryServicesBackupProtection -Item $backupItems -Force
    Write-Host "Backup is successfully disabled"
}
catch {
    $message = $_
    Write-Warning "An error occured! $message"
}
                  }
else {
     $script = $PSScriptRoot+"\vmbackup.ps1"
     & $script $argumentList
    
}

Vmbackup.ps1 (This is my script which is being called from the vmbackupplicy.ps1)

####################### Paramaters for the VM Backup Process #######################
param (
    [Parameter(Mandatory = $false)][String]$ResourceGroupName,
    [Parameter(Mandatory = $false)][String]$SourceVMname,
    [Parameter(Mandatory = $false)][String]$RSVaultname,
    [Parameter(Mandatory = $false)][String]$PolicyName,
    [Parameter(Mandatory = $false)][String]$Location,
    [Parameter(Mandatory = $false)][String]$Storagetype,
    [Parameter(Mandatory = $false)][String]$WorkLoadType
)

Get-AzRecoveryServicesVault -Name $RSVaultname | Set-AzRecoveryServicesVaultContext

####################### Fetching vault resource values #######################
Write-Host "Fetching vault resource values"
$targetVault = Get-AzRecoveryServicesVault -ResourceGroupName $ResourceGroupName -Name $RSVaultname
$targetVault.ID

####################### Setting up VaultContext using Vault and Setting up Storage redundancy #######################
Write-Host "Setting up VaultContext using Vault and Setting up Storage redundancy"
Set-AzRecoveryServicesVaultContext -Vault $targetVault
# Set-AzRecoveryServicesBackupProperty -Vault $targetVault -BackupStorageRedundancy $Storagetype

####################### Fetching the right container and backup items #######################
Write-Host "Fetching the right container and backup items"
$backupcontainer = Get-AzRecoveryServicesBackupContainer -ContainerType $WorkLoadType -FriendlyName $SourceVMname
$item = Get-AzRecoveryServicesBackupItem -Container $backupcontainer -WorkloadType $WorkLoadType

####################### Check if backup is already in progress or Transfer data to vault process is running #######################
Write-Host "Backup process begins"
$backupjob=Backup-AzRecoveryServicesBackupItem -Item $item
$backupjob
start-sleep -s 60

####################### Fail the pipeline if backup is failed #######################

if ($backupjob.Status -eq "Failed") {
   throw "Backup is failed"
}

####################### Get the Backup Status #######################
Write-Host "Current Backup Status"
Get-AzRecoveryservicesBackupJob

####################### Look for the backup subtask: Take Snapshot in RSV for Backup job and wait for it to complete #######################
Write-Host "Look for the backup subtask: Take Snapshot in RSV for Backup job and wait for it to complete"
$Jobs = Get-AzRecoveryServicesBackupJob -Status InProgress -VaultId $targetVault.ID
$JobId = $Jobs[0].JobId
DO {
   $subtasks = Get-AzRecoveryServicesBackupJobDetail -JobId $JobId -VaultId $targetVault.ID
   $subtask = $subtasks.SubTasks | Where-Object { $_.Name -eq "Take Snapshot" }
   $subtask.Status
   Start-Sleep -Seconds 20
}UNTIL ($subtask.Status -eq "Completed")

####################### Fail the pipeline if backup is failed #######################
try { 
   if ($backupjob.Status -eq "Failed") {   
       throw "Backup is failed"
   }
}
catch {
   $message = $_
   Write-Warning "An error occurred! $message"
}
start-sleep -s 30
####################### Here is the final backup status #######################
Write-Host "Here is the final backup status"
Get-AzRecoveryservicesBackupJob
Write-Output "Backup process is completed successfully"

Solution

  • If you have the path of the script, you can just use & instead of Invoke-Expression like this:

    & $PSScriptRoot\vmbackup.ps1 -ContainerType $WorkLoadType -FriendlyName $SourceVMname
    

    Ref: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.2#call-operator-