NetApp.CBS.AVS.psm1
using module Microsoft.AVS.Management <# Copyright 2021 Netapp, Inc. #> # # Script module for module 'NetApp.SC' # Set-StrictMode -Version Latest <# .SYNOPSIS Installs Cloud Backup for Virtual Machines to protect Virtual Machines and datastores based on Azure NetApp Files. .DESCRIPTION Installs Cloud Backup for Virtual Machines to protect Virtual Machines and datastores based on Azure NetApp Files. .PARAMETER MaintenanceUserPassword Password for the appliance maintenance user. This is used for performing maintenance tasks in the appliance. .PARAMETER AppliancePassword Password for the appliance user account. This is used for authenticating with the API endpoints that are exposed by the appliance. .PARAMETER ApplianceUser Appliance user account is used for authenticating with the API endpoints that are exposed by the appliance. .PARAMETER PrimaryDNS Primary DNS server IP address. .PARAMETER Gateway Gateway IP address. .PARAMETER Netmask Subnet mask. .PARAMETER ApplianceIPAddress IPV4 address to be used for the appliance. .PARAMETER ApplianceNetworkName Network name to be used for the appliance. .PARAMETER NetworkMapping Destination network to be used for the appliance. .PARAMETER VmDatastore Datastore to be used for the appliance. .PARAMETER EsxiCluster Destination ESXi cluster name to be used for deploying the appliance. .PARAMETER ApplianceVirtualMachineName Virtual Machine name for the appliance. .EXAMPLE Install-NetAppCBSAppliance -AcceptNetAppEulaAggrement $true -ApplianceVirtualMachineName "VM1" -EsxiCluster "cluster1" -VmDatastore "datastore1" -NetworkMapping "VM Network" -ApplianceNetworkName "scvova" -ApplianceIPAddress "19.132.15.124" -Netmask "255.255.255.0" -Gateway "11.252.1.1" -PrimaryDNS "10.232.1.60" Description --------------------------------------- Installs Cloud Backup for Virtual Machines with a static IP address for protection of Virtual Machines and datastores based on Azure NetApp Files. #> function Install-NetAppCBSAppliance { [AVSAttribute(90, UpdatesSDDC = $True)] [CmdletBinding()] param( [Parameter( Mandatory = $true, Position = 12, HelpMessage = 'Password for the appliance maintenance user. This is used for performing maintenance tasks in the appliance.')] [ValidateNotNullOrEmpty()] [Security.SecureString] $MaintenanceUserPassword, [Parameter( Mandatory = $true, Position = 11, HelpMessage = 'Password for the appliance user account. This is used for authenticating with the API endpoints that are exposed by the appliance.')] [ValidateNotNullOrEmpty()] [Security.SecureString] $AppliancePassword, [Parameter( Mandatory = $true, Position = 10, HelpMessage = 'Appliance user account is used for authenticating with the API endpoints that are exposed by the appliance.')] [ValidateNotNullOrEmpty()] [string] $ApplianceUser, [Parameter( Mandatory = $true, Position = 9, HelpMessage = 'Primary DNS server IP address.')] [string] $PrimaryDNS, [Parameter( Mandatory = $true, Position = 8, HelpMessage = 'Gateway IP address.')] [string] $Gateway, [Parameter( Mandatory = $true, Position = 7, HelpMessage = 'Subnet mask.')] [string] $Netmask, [Parameter( Mandatory = $true, Position = 6, HelpMessage = 'IPV4 address to be used for the appliance.')] [string] $ApplianceIPAddress, [Parameter( Mandatory = $true, Position = 5, HelpMessage = 'Network name to be used for the appliance.')] [string] $ApplianceNetworkName, [Parameter( Mandatory = $true, Position = 4, HelpMessage = 'Destination network to be used for the appliance.')] [ValidateNotNullOrEmpty()] [string] $NetworkMapping, [Parameter( Mandatory = $true, Position = 3, HelpMessage = 'Datastore to be used for the appliance.')] [ValidateNotNullOrEmpty()] [string] $VmDatastore, [Parameter( Mandatory = $false, Position = 2, HelpMessage = 'Destination ESXi cluster name to be used for deploying the appliance.')] [string] $EsxiCluster, [Parameter( Mandatory = $true, Position = 1, HelpMessage = 'Virtual Machine name for the appliance.')] [ValidateNotNullOrEmpty()] [string] $ApplianceVirtualMachineName, [Parameter( Mandatory = $true, Position = 0, HelpMessage = "Accept the End User License Agrement 'https://www.netapp.com/pdf.html?item=/media/14114-enduserlicenseagreementworldwide.pdf'")] [ValidateNotNullOrEmpty()] [boolean] $AcceptNetAppEulaAggrement ) $ApplianceIPAddress = $ApplianceIPAddress.Trim() $Netmask = $Netmask.Trim() $Gateway = $Gateway.Trim() $PrimaryDNS = $PrimaryDNS.Trim() $ApplianceUser = $ApplianceUser.Trim() $scvcredential = New-Object System.Management.Automation.PSCredential ($ApplianceUser, $AppliancePassword) $maintusercredential = New-Object System.Management.Automation.PSCredential ("maint", $MaintenanceUserPassword) if ($EsxiCluster -eq $null -or $EsxiCluster -eq '') { Install-Appliance -AcceptNetAppEulaAggrement $AcceptNetAppEulaAggrement -ApplianceVirtualMachine $ApplianceVirtualMachineName -VmDatastore $VmDatastore -NetworkMapping $NetworkMapping -ApplianceNetworkName $ApplianceNetworkName -ApplianceIPAddress $ApplianceIPAddress -Netmask $Netmask -Gateway $Gateway -PrimaryDNS $PrimaryDNS -scvcredential $scvcredential -maintusercredential $maintusercredential } else { Install-Appliance -AcceptNetAppEulaAggrement $AcceptNetAppEulaAggrement -ApplianceVirtualMachine $ApplianceVirtualMachineName -EsxiCluster $EsxiCluster -VmDatastore $VmDatastore -NetworkMapping $NetworkMapping -ApplianceNetworkName $ApplianceNetworkName -ApplianceIPAddress $ApplianceIPAddress -Netmask $Netmask -Gateway $Gateway -PrimaryDNS $PrimaryDNS -scvcredential $scvcredential -maintusercredential $maintusercredential } } <# .SYNOPSIS Installs Cloud Backup for Virtual Machines to protect Virtual Machines and datastores based on Azure NetApp Files. .DESCRIPTION Installs Cloud Backup for Virtual Machines to protect Virtual Machines and datastores based on Azure NetApp Files. .PARAMETER MaintenanceUserPassword Password for the appliance maintenance user. This is used for performing maintenance tasks in the appliance. .PARAMETER AppliancePassword Password for the appliance user account. This is used for authenticating with the API endpoints that are exposed by the appliance. .PARAMETER ApplianceUser Appliance user account is used for authenticating with the API endpoints that are exposed by the appliance. .PARAMETER ApplianceNetworkName Network name to be used for the appliance. .PARAMETER NetworkMapping Destination network to be used for the appliance. .PARAMETER VmDatastore Datastore to be used for the appliance. .PARAMETER EsxiCluster Destination ESXi cluster name to be used for deploying the appliance. .PARAMETER ApplianceVirtualMachineName Virtual Machine name for the appliance. .EXAMPLE Install-NetAppCBSApplianceUsingDHCP -AcceptNetAppEulaAggrement $true -ApplianceVirtualMachineName "VM1" -EsxiCluster "cluster1" -VmDatastore "datastore1" -NetworkMapping "VM Network" -ApplianceNetworkName "scvova" Description --------------------------------------- Installs the OVA file using dynamic IP address. #> function Install-NetAppCBSApplianceUsingDHCP { [AVSAttribute(90, UpdatesSDDC = $True)] [CmdletBinding()] param( [Parameter( Mandatory = $true, Position = 8, HelpMessage = 'Password for the appliance maintenance user. This is used for performing maintenance tasks in the appliance.')] [ValidateNotNullOrEmpty()] [Security.SecureString] $MaintenanceUserPassword, [Parameter( Mandatory = $true, Position = 7, HelpMessage = 'Password for the appliance user account. This is used for authenticating with the API endpoints that are exposed by the appliance.')] [ValidateNotNullOrEmpty()] [Security.SecureString] $AppliancePassword, [Parameter( Mandatory = $true, Position = 6, HelpMessage = 'Appliance user account is used for authenticating with the API endpoints that are exposed by the appliance.')] [ValidateNotNullOrEmpty()] [string] $ApplianceUser, [Parameter( Mandatory = $true, Position = 5, HelpMessage = 'Network name to be used for the appliance.')] [string] $ApplianceNetworkName, [Parameter( Mandatory = $true, Position = 4, HelpMessage = 'Destination network to be used for the appliance.')] [ValidateNotNullOrEmpty()] [string] $NetworkMapping, [Parameter( Mandatory = $true, Position = 3, HelpMessage = 'Datastore to be used for the appliance.')] [ValidateNotNullOrEmpty()] [string] $VmDatastore, [Parameter( Mandatory = $false, Position = 2, HelpMessage = 'Destination ESXi cluster name to be used for deploying the appliance.')] [string] $EsxiCluster, [Parameter( Mandatory = $true, Position = 1, HelpMessage = 'Virtual Machine name for the appliance.')] [ValidateNotNullOrEmpty()] [string] $ApplianceVirtualMachineName, [Parameter( Mandatory = $true, Position = 0, HelpMessage = "Accept End User License Agrement 'https://www.netapp.com/pdf.html?item=/media/14114-enduserlicenseagreementworldwide.pdf'")] [ValidateNotNullOrEmpty()] [boolean] $AcceptNetAppEulaAggrement ) $scvcredential = New-Object System.Management.Automation.PSCredential ($ApplianceUser, $AppliancePassword) $maintusercredential = New-Object System.Management.Automation.PSCredential ("maint", $MaintenanceUserPassword) if ($EsxiCluster -eq $null -or $EsxiCluster -eq '') { Install-Appliance -AcceptNetAppEulaAggrement $AcceptNetAppEulaAggrement -ApplianceVirtualMachine $ApplianceVirtualMachineName -VmDatastore $VmDatastore -NetworkMapping $NetworkMapping -ApplianceNetworkName $ApplianceNetworkName -Dhcp $true -scvcredential $scvcredential -maintusercredential $maintusercredential } else { Install-Appliance -AcceptNetAppEulaAggrement $AcceptNetAppEulaAggrement -ApplianceVirtualMachine $ApplianceVirtualMachineName -EsxiCluster $EsxiCluster -VmDatastore $VmDatastore -NetworkMapping $NetworkMapping -ApplianceNetworkName $ApplianceNetworkName -Dhcp $true -scvcredential $scvcredential -maintusercredential $maintusercredential } } <# .SYNOPSIS Upgrades Cloud Backup for Virtual Machines for protection of Virtual Machines and datastores based on Azure NetApp Files. .DESCRIPTION Upgrades Cloud Backup for Virtual Machines for protection of Virtual Machines and datastores based on Azure NetApp Files. .PARAMETER AppliancePassword Password of the user hosting API services in the appliance. .PARAMETER ApplianceUser User Account for hosting API services in the appliance .EXAMPLE Update-NetAppCBSAppliance Description --------------------------------------- Upgrades the appliance #> function Invoke-UpgradeNetAppCBSAppliance { [AVSAttribute(90, UpdatesSDDC = $True)] [CmdletBinding()] param( [Parameter( Mandatory = $true, Position = 2, HelpMessage = 'Appliance password')] [ValidateNotNullOrEmpty()] [Security.SecureString] $AppliancePassword, [Parameter( Mandatory = $true, Position = 1, HelpMessage = 'Appliance user name.')] [ValidateNotNullOrEmpty()] [string] $ApplianceUser ) $scvcredential = New-Object System.Management.Automation.PSCredential ($ApplianceUser, $AppliancePassword) update-netapp-cbs-appliance -scvcredential $scvcredential } <# .SYNOPSIS Resets the vCenter account used internally by the appliance. .DESCRIPTION Resets the vCenter account used internally by the appliance. .EXAMPLE Invoke-ResetNetAppCBSApplianceVCenterPassword Description --------------------------------------- Resets the vCenter account used internally by the appliance. #> function Invoke-ResetNetAppCBSApplianceVCenterPassword { <# High level task of this cmdlets 1. Check if tag AVS_ANF_CLOUD_ADMIN_VM_TAG exists. 2. If the tag does not exist, throw error. 3. If tag exist, get teh VM detail. 4. Check if VM assosicated with Tag present. 5. If VM not present, throw eror 6. IF VM present A. Change password for teh user 'NetAppSCDPAdmin' B. Update vApp options for the users new password. #> set-netapp-cbs-appliance-password } <# .SYNOPSIS Uninstalls the virtual appliance. .DESCRIPTION Uninstalls the virtual appliance. .EXAMPLE UnInstall-NetAppCBSAppliance Description --------------------------------------- Uninstalls the virtual appliance #> function UnInstall-NetAppCBSAppliance { [CmdletBinding()] param( [Parameter( Mandatory = $true, HelpMessage = 'Accept to uninstall the virtual appliance.')] [bool] $AreYouSureToDelete ) if ($AreYouSureToDelete -eq $True) { uninstall-netapp-cbs-appliance } else { write-error -Message "You must enable 'AreYouSureDelete' to uninstall the virtual appliance." -ErrorAction Stop } } # Internal helper functions function Show-Progress { param( [Parameter(Mandatory)] [int] $TotalNoOfTimes, [Parameter(Mandatory)] [int] $SleepTime, [Parameter(Mandatory)] [string] $ActivityText, [Parameter(Mandatory)] [string] $ProgressText, [Parameter()] [boolean] $HidePercentageComplete ) $TotalNoOfTimes = $TotalNoOfTimes + 1 $i = 0 for ($i = 0; $i -lt $TotalNoOfTimes; $i++) { $percentComplete = ($i / $TotalNoOfTimes) * 100 if ($HidePercentageComplete -eq $true) { Write-DebugLog -Message "-Activity $ActivityText -Status $ProgressText" } else { Write-DebugLog -Message "-Activity $ActivityText -Status $ProgressText : $percentComplete" } Start-Sleep $SleepTime } Write-DebugLog -Message "-Activity $ActivityText -Status $ProgressText : $percentComplete" } function Restart-VMwareVM { <# .DESCRIPTION This fucntion restarts the Virtual Machine. .PARAMETER ApplianceVirtualMachine Specify the Virtual Machine for the virtual appliance. .EXAMPLE Restart-VMwareVM Description --------------------------------------- Restart Virtual Machine #> param( [Parameter(Mandatory)] [string] $ApplianceVirtualMachine ) $VMGuestObject = Get-VMGuest -VM $ApplianceVirtualMachine -ErrorAction SilentlyContinue -ErrorVariable GetVMError if ($GetVMError) { Write-DebugLog $GetVMError | Out-String } if ($VMGuestObject) { if ($VMGuestObject.State -eq "Running") { try { Shutdown-VMGuest -VM $ApplianceVirtualMachine -Confirm:$false -ErrorAction Stop | Out-Null Start-Sleep 5 $Count = 10 For ($i = 0; $i -le $Count; $i++) { $VMGuestObject = Get-VMGuest -VM $ApplianceVirtualMachine if ($VMGuestObject.State -eq "NotRunning") { break } else { Start-Sleep 10 } $PercentComplete = ($i / $Count) * 100 Write-DebugLog -Message "-Activity Shutdown-VMGuest -Status $i/$count : $PercentComplete % " } Write-DebugLog -Message "-Activity Shutdown-VMGuest -Status Done -complete" Start-VM -VM $ApplianceVirtualMachine | Out-Null $Count = 10 For ($i = 0; $i -le $Count; $i++) { $VMGuestObject = Get-VMGuest -VM $ApplianceVirtualMachine if ($VMGuestObject.State -eq "Running") { break } else { Start-Sleep 10 } $PercentComplete = ($i / $Count) * 100 Write-DebugLog -Message "-Activity Start-VM -Status $i/$count : $PercentComplete" } Write-DebugLog -Message "-Activity Start-VM -Status Done -complete" } catch { Write-DebugLog -Message $_.exception Write-Error -ErrorId "MOUNT_FAILED" -Message $_.exception.Message } } else { Start-VM -VM $ApplianceVirtualMachine | Out-Null $Count = 10 For ($i = 0; $i -le $Count; $i++) { $VMGuestObject = Get-VMGuest -VM $ApplianceVirtualMachine if ($VMGuestObject.State -eq "Running") { break } else { Start-Sleep 10 } $PercentComplete = ($i / $Count) * 100 Write-DebugLog -Message "-Activity Start-VM -Status $i/$count : $PercentComplete % Complete -PercentComplete $PercentComplete" } Write-DebugLog -Message "-Activity Start-VM -Status Done -complete" } } Write-DebugLog -Message "Restart vm successfull" Write-Verbose -Message "Restart vm successfull" } function Get-BlobContent { <# .DESCRIPTION This function downloads file from Azure account. .PARAMETER BlobName File name to be downladed. .PARAMETER ContainerName The Azure storage account container name used for downloading the virtual appliance .PARAMETER StorageAccountName The Azure storage account name used for downloading the virtual appliance. Contact NetApp for the account name. .EXAMPLE Get-BlobContent -BlobName 'test.ova' -StorageAccountName 'acountname' -ContainerName 'container' Description --------------------------------------- Downloads file from Azure account. #> param( [Parameter(Mandatory)] [string] $BlobName, [Parameter(Mandatory)] [string] $StorageAccountName, [Parameter(Mandatory)] [string] $ContainerName, [Parameter(Mandatory)] [Long] $TotalBlobSizeInKB ) Write-DebugLog -Message " Get-BlobContent execution is started...." Write-DebugLog -Message "Downloading file $BlobName" $FileUrl = 'https://' + $StorageAccountName + '.blob.core.windows.net/' + $ContainerName + '/' + $BlobName try { $GetLocation = Get-Location Write-DebugLog -Message "Downloading file to location $GetLocation" $downloadtask = Write-Output (New-Object System.Net.WebClient).DownloadFileTaskAsync($FileUrl, "$GetLocation/$BlobName") Write-DebugLog -Message "After DownloadFileTaskAsync called. " $destination = "$GetLocation/$BlobName" $i = 0 for ($i = 0; $i -lt 60; $i++) { if ($downloadtask.IsCompleted -eq $True) { if ($downloadtask.IsCompletedSuccessfully -eq $True) { Write-DebugLog "Percentage Downloaded: 100 %" Write-DebugLog -Message "The file $BlobName downloaded." Write-DebugLog "Downloaded file saved in the location : $GetLocation" } else { $exception = $downloadtask.Exception if ($exception -ne $null -and $exception.message -ne $null) { write-error -Message $downloadtask.Exception.message -ErrorAction Stop } else { if ($downloadtask.Status -eq "Faulted") { write-error -Message "Could not download the requested file." -ErrorAction Stop } } } break } else { Start-Sleep -Seconds 60 $fileSize = ((Get-Item $destination).length / 1KB) $sizeDownloadedPercentage = ($fileSize / $TotalBlobSizeInKB) * 100 Write-DebugLog "Percentage Downloaded: $sizeDownloadedPercentage %" } } } catch { Write-DebugLog -Message $_.exception.Message write-error -Message $_.exception.Message -ErrorAction Stop } Write-DebugLog -Message " Get-BlobContent execution is completed." } function Get-TimeStamp { return "{0:M/d/yyyy} {0:h:mm:ss tt}" -f (Get-Date) } function Write-DebugLog { param( $Message ) Write-Host -Message "$(Get-TimeStamp) $Message" } function Get-RandomCharacters ($length, $characters) { $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length } $private:ofs = "" return [string]$characters[$random] } function getSuffledString ([string]$inputString) { Write-DebugLog -Message "getSuffledString execution is started." $characterArray = $inputString.ToCharArray() $scrambledStringArray = $characterArray | Get-Random -Count $characterArray.length $outputString = -join $scrambledStringArray Write-DebugLog -Message "getSuffledString execution is completed" return $outputString } function changeMaxRepeatingChar ($pwdText, $maxCharAllowed, $AllChars) { Write-DebugLog -Message "changeMaxRepeatingChar execution is started" $len = $pwdText.length; for ($i = 0; $i -lt $len; $i++) { $cur_count = 1; for ($j = $i + 1; $j -lt $len; $j++) { if ($pwdText[$i] -ne $pwdText[$j]) { break } $cur_count = $cur_count + 1; if ($cur_count -gt $maxCharAllowed) { $allcharExpectRepeated = $AllChars -replace $pwdText[$j] $pwdText = ($pwdText.substring(0, $j)) + (Get-RandomCharacters -length 1 -characters $allcharExpectRepeated) + $pwdText.substring(($j + 1)) break } } } Write-DebugLog -Message "changeMaxRepeatingChar execution is completed" return $pwdText } function Get-Password () { <# .DESCRIPTION This function generates a new password based on password policy for the appliance user .EXAMPLE Get-Password Description --------------------------------------- Returns password #> Write-DebugLog -Message "Get-Password execution is started" $password = "" #$SpecialChars ='!"ยง$%&/()=?}][{@#*+' #Password wont work properly when few special characters present. #Thats why few charactors are excluded. $SpecialChars = '!%()=}][{@#' $UppercaseChars = 'ABCDEFGHKLMNOPRSTUVWXYZ' $LowerCaseChars = 'abcdefghiklmnoprstuvwxyz' $Numerics = '1234567890' $AllAlphaBets = $UppercaseChars + $LowerCaseChars $AllChars = $AllAlphaBets + $Numerics $SsoPasswordPolicy = Get-SsoPasswordPolicy $MinNumericCount = $SsoPasswordPolicy | ForEach-Object { $_.MinNumericCount } $password += Get-RandomCharacters -length $MinNumericCount -characters $Numerics $MinSpecialCharCount = $SsoPasswordPolicy | ForEach-Object { $_.MinSpecialCharCount } $password += Get-RandomCharacters -length $MinSpecialCharCount -characters $SpecialChars $MinUppercaseCount = $SsoPasswordPolicy | ForEach-Object { $_.MinUppercaseCount } $password += Get-RandomCharacters -length $MinUppercaseCount -characters $UppercaseChars $MinLowercaseCount = $SsoPasswordPolicy | ForEach-Object { $_.MinLowercaseCount } $password += Get-RandomCharacters -length $MinLowercaseCount -characters $LowerCaseChars $MinAlphabeticCount = $SsoPasswordPolicy | ForEach-Object { $_.MinAlphabeticCount } $ExtraAlphaRequired = $MinAlphabeticCount - ($MinLowercaseCount + $MinUppercaseCount) if ($ExtraAlphaRequired -gt 0) { $password += Get-RandomCharacters -length $ExtraAlphaRequired -characters $AllAlphaBets } $MinLength = $SsoPasswordPolicy | ForEach-Object { $_.MinLength } $ExtraCharRequiredForMinLength = $MinLength - $password.length if ($ExtraCharRequiredForMinLength -gt 0) { $password += Get-RandomCharacters -length $ExtraCharRequiredForMinLength -characters ($AllAlphaBets + $Numerics + $SpecialChars) } $MaxIdenticalAdjacentCharacters = $SsoPasswordPolicy | ForEach-Object { $_.MaxIdenticalAdjacentCharacters } $pwdText = changeMaxRepeatingChar -pwdText $password -maxCharAllowed $MaxIdenticalAdjacentCharacters -AllChars $AllChars $pwdText = getSuffledString $pwdText Write-DebugLog -Message "Get-Password execution is completed" return $pwdText } function Set-Password { <# .DESCRIPTION This function removes the role from the vCenter. .PARAMETER vcUserCre Specify the credential. .EXAMPLE Set-Password Description --------------------------------------- Removes the role 'role1' #> param( [Parameter( Mandatory = $true, HelpMessage = 'Specify the credential.')] [System.Management.Automation.PSCredential] $vcUserCredential ) Write-DebugLog -Message "Set-Password execution is started" $domain = "vsphere.local" $userName = $vcUserCredential.UserName $newPassword = $vcUserCredential.GetNetworkCredential().Password Write-DebugLog -Message "Get-SsoPersonUser -Domain $domain -Name $userName" $User = Get-SsoPersonUser -Domain $domain -Name $userName Write-DebugLog -Message "SCDPAdminObject" if ($null -eq $User) { Write-DebugLog -Message "No such user" write-error "Appliance user with name NetAppSCDPAdmin does not exist" -ErrorAction Stop } else { #Change NetAppSCDPAdmin password try { Set-SsoPersonUser -User $User -NewPassword $newPassword -ErrorAction Stop | Out-Null Write-DebugLog -Message "Password changed" } catch { Write-DebugLog -Message "Password change failed" write-error "Password change failed" -ErrorAction Stop } } Write-DebugLog -Message "Set-Password execution is completed" } function Get-ApplianceVirtualMachineUsingTag { Write-DebugLog -Message " Get-ApplianceVirtualMachineUsingTag execution started" $tagName = "AVS_ANF_CLOUD_ADMIN_VM_TAG" $tagCategoryName = "AVS_ANF_CLOUD_ADMIN_VM_TAG_CATEGORY" $ApplianceVirtualMachine = "" $ApplianceVirtualMachineArray = [System.Collections.ArrayList]@() Write-DebugLog "Checking if the VM exists" $tagAssignment = $null try { $tagAssignment = Get-TagAssignment -Tag $tagName -Category $tagCategoryName -ErrorAction SilentlyContinue } catch { if ($tagAssignment) { Write-DebugLog "Inside catch block but tagAssignment is not empty" if ($tagAssignment.Entity.Name) { Write-DebugLog "Appliance name "$tagAssignment.Entity.Name | Out-String } } Write-DebugLog $_.exception | Out-String } if ($tagAssignment) { Write-DebugLog "Tag Present" if ($tagAssignment.Entity.Name -is [array]) { Write-DebugLog "More than one VM present with tag AVS_ANF_CLOUD_ADMIN_VM_TAG" $noOfVM = $tagAssignment.Entity.Name.Count For ($i = 0; $i -lt $noOfVM; $i++) { $ApplianceVirtualMachineArray.Add($tagAssignment.Entity.Name[$i]) | Out-Null } } else { Write-DebugLog "One VM present with tag AVS_ANF_CLOUD_ADMIN_VM_TAG" $ApplianceVirtualMachineArray.Add($tagAssignment.Entity.Name) | Out-Null Write-DebugLog "First element inside ApplianceVirtualMachineArray: "$ApplianceVirtualMachineArray[0] $totalNumberofVM = $ApplianceVirtualMachineArray.Count Write-DebugLog "No of VMs are: $totalNumberofVM" } if ($ApplianceVirtualMachineArray.Count -lt 1) { Write-DebugLog "VM with the tag $tagName does not exist" return ""; } if ($ApplianceVirtualMachineArray.Count -eq 1) { return $ApplianceVirtualMachineArray[0] } if ($ApplianceVirtualMachineArray.Count -gt 1) { Write-DebugLog -Message "Below Virtual Machine appliance assosiated with the tag $tagName and tag categoy $tagCategoryName." foreach ($element in $ApplianceVirtualMachineArray) { Write-DebugLog -Message $element } $ApplianceVirtualMachine = Read-Host "Appliance Virtual Machine Name " return $ApplianceVirtualMachine } } } function Test-ApplianceExistOrNot { param( [Parameter(Mandatory = $true)] $ApplianceVirtualMachine ) Write-DebugLog -Message "Test-ApplianceExistOrNot execution started" $VMObject = $null try { $VMObject = Get-VM -Name $ApplianceVirtualMachine -ErrorAction Stop } catch { if ($_.CategoryInfo.Category -eq "ObjectNotFound") { Write-DebugLog -Message "VM with name $ApplianceVirtualMachine does not exist" Write-Error -ErrorId "UNINSTALL-NO-SUCH-VM-ERROR" -Message "VM with name $ApplianceVirtualMachine does not exist" write-error $_.exception.Message -ErrorAction Stop } else { Write-DebugLog -Message $_.exception | Out-String write-error $_.exception.Message -ErrorAction Stop } } if ($VMObject) { Write-DebugLog -Message "Virtual Machine exist" } else { Write-DebugLog -Message "VM with name $ApplianceVirtualMachine does not exist" Write-DebugLog -Message "VM with name $ApplianceVirtualMachine does not exist" write-error "VM with name $ApplianceVirtualMachine does not exist" -ErrorAction Stop } ` Write-DebugLog -Message "Test-ApplianceExistOrNot execution completed" return $VMObject } function Test-DataStore { param( [Parameter(Mandatory = $true)] [String] $VmDatastore, [Parameter(Mandatory = $true)] [Int] $FreeSapce ) Write-DebugLog -Message "Test-DataStoreExistOrNot execution started" try { $datastore = Get-Datastore | Where-Object { $_.Name -eq $VmDatastore } if ($datastore) { Write-DebugLog "Datastore exists" $ds_space_gb = $datastore.FreeSpaceGB if ($ds_space_gb -lt $FreeSapce) { write-error "The datastore provided for deployment does not have the required free space. The minimum required space is: $FreeSapce GB" -ErrorAction Stop } else { Write-DebugLog -Message "SUCCESS: Datastore has enough free space for ova deployment." } } else { write-error "Invalid datastore" -ErrorAction Stop } } catch { write-error $_.exception.Message -ErrorAction Stop } } function Test-EsxHost { <# .SYNOPSIS Tests one or more IP Addresses to determine if they are valid. .DESCRIPTION Test-EsxHost is a function that validates EsxHost for vCenter. .PARAMETER EsxHost EsxHost IP address. This parameter is mandatory. .EXAMPLE Test-EsxHost -EsxHost '192.168.0.1' .INPUTS String .OUTPUTS Boolean #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeLine = $true)] [string]$EsxHost ) PROCESS { $VMHostNetworkAdapterList = Get-VMHostNetworkAdapter | select VMhost, Name, IP, SubnetMask $isValidEsxHost = $false; foreach ($VMHostNetworkAdapter in $VMHostNetworkAdapterList) { $VMHostIpAddres = $VMHostNetworkAdapter.IP if ($null -ne $VMHostIpAddres -and $VMHostIpAddres -ne "" -and $VMHostIpAddres -eq $EsxHost) { $isValidEsxHost = $true break } $VMHost = $VMHostNetworkAdapter.VMHost if ($null -ne $VMHost -and $VMHost -ne "" -and $VMHost -eq $EsxHost) { $isValidEsxHost = $true break } } Write-Output $isValidEsxHost } } function Test-IpAddress { <# .SYNOPSIS Tests one or more IP Addresses to determine if they are valid. .DESCRIPTION Test-IpAddress is a function that tests one or more IP Addresses to determine if they are valid. The detailed parameter can be used to return additional information about the IP. .PARAMETER IpAddress One or more IP Addresses to test. This parameter is mandatory. .EXAMPLE Test-IpAddress -IpAddress '192.168.0.1', '192.168.0.256' .EXAMPLE Test-IpAddress -IpAddress '192.168.0.1' .EXAMPLE '::1', '192.168.0.256' | Test-MrIpAddress .INPUTS String .OUTPUTS Boolean #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeLine = $true)] [string[]]$IpAddress ) PROCESS { foreach ($Ip in $IpAddress) { try { $Results = $Ip -match ([IPAddress]$Ip) } catch { Write-Output $false Continue } Write-Output $Results } } } Function Get-VMToolsStatus { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeLine = $true)] [string[]]$ApplianceVirtualMachine ) PROCESS { try { $InputObject = Get-VM $ApplianceVirtualMachine [PSCustomObject]@{ Name = $InputObject.Name Status = $InputObject.ExtensionData.Guest.ToolsStatus GuestState = $InputObject.ExtensionData.Guest.GuestState UpgradeStatus = $InputObject.ExtensionData.Guest.ToolsVersionStatus2 Version = $InputObject.ExtensionData.Guest.ToolsVersion } } catch { Write-Error $_.Exception.Message } } } function checkPSVersion { # This function checks whether Powershell version in the system is greatear than 7 or not $PowerShellVersion = $PSVersionTable.PSVersion.Major if ($PowerShellVersion -lt 7) { write-error "Powershell version is less than 7. Please install powershell version 7.x and run again." -ErrorAction Stop } else { Write-DebugLog -Message "SUCCESS: Check for powershell version passed" } } function checkModule { param( [String]$module ) $module_exists = Get-Module -Name $module if ($module_exists) { Write-DebugLog -Message "SUCCESS: Check for module $module passed" } else { write-error "Module $module not available. Please make sure the module is imported and try again." -ErrorAction Stop } } function checkVcaddress { try { if (-Not $VC_ADDRESS) { Write-Error "VC_ADDRESS is not set as a powershell variable. Please set it and run the script again" -ErrorAction Stop } else { Write-DebugLog -Message "SUCCESS: VCenter Address is set." } } catch { Write-Error "VC_ADDRESS is not set as a powershell variable. Please set it and run the script again" -ErrorAction Stop } } function Invoke-PreflightNetAppCBSAVSCheck { [CmdletBinding()] param() Process { checkPSVersion checkVcaddress checkModule "VMware.VimAutomation.Core" checkModule "VMware.vSphere.SsoAdmin" checkModule "Microsoft.AVS.Management" } } function ping_vm { param( $vm_ip = $( throw "specify vm ip" ), $timeout = 600 ) Write-DebugLog -Message "### $($MyInvocation.MyCommand) ###" $rlt = 0 while ($timeout -gt 0) { $rc = test-connection -computername $vm_ip -quiet if (!$rc) { Write-DebugLog -Message "$vm_ip is not reachable, sleep for 5 seconds.." start-sleep 5 } else { Write-DebugLog -Message "$vm_ip is pingable now." $rlt = 1 break } $timeout -= 5 } return $rlt } # Import Module Advanced Functions Implementation Get-ChildItem -Path $PSScriptRoot -Filter '*.ps1' | ForEach-Object { Write-DebugLog -Message "Importing file: $($_.BaseName)" try { .$_.FullName } catch { Write-Error -Message "Failed to import functions from $($_.Fullname): $_" } } |