Upgrade.ps1

function update-netapp-cbs-appliance { 
  
  [CmdletBinding()]
  param(          
    [Parameter(Mandatory)]
    [System.Management.Automation.PSCredential]
    $scvcredential
  )
 
  BEGIN {
      
    $ISOName = "Cb-vm-1.0x11.iso"
    $ContainerName = "cbsavsanfova"   
    $StorageAccountName = "cbsavsanfovahosting"   
    
    $ApplianceUser = $ApplianceUser.Trim()
  }

  PROCESS {
    
    Write-DebugLog -Message "Update-NetAppCBSAppliance execution is started."
    
    Invoke-PreflightNetAppCBSAVSCheck

    Write-DebugLog -Message "Downloading ISO file..." 
    $GetLocation = Get-Location
    Write-DebugLog -Message "OVA path: $GetLocation"
    Write-DebugLog -Message "Source path: $GetLocation/$ISOName"
    
    try {
      
      $BlobContent = Get-BlobContent -BlobName $ISOName -StorageAccountName $StorageAccountName -ContainerName $ContainerName -TotalBlobSizeInKB 744824.832 -ErrorAction Stop
      Write-DebugLog -Message $BlobContent
      Write-DebugLog -Message "ISO file downloaded."
    }
    catch {
      Write-DebugLog -Message $_.exception | Out-String
      Write-Error -ErrorId  "UPGRADE_DOWNLOAD_ISO_FAILED" -Message  "Unable to download the ISO file."
      Write-Error $_.exception.message  -ErrorAction Stop
    } 

    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
    
    $scvLogin = $scvcredential.UserName
    $scvPwd = $scvcredential.GetNetworkCredential().Password
    
    $Body = @{
      username = $scvLogin
      password = $scvPwd
    }     
  
    $mobObject = (Get-View ExtensionManager | Select-Object -ExpandProperty ExtensionList | Select-Object Key, @{N = 'Server'; E = { $_.Server.url } } |  Where-Object { $_.Key -eq "com.netapp.aegis" })
    Write-DebugLog $mobObject | out-string

    if ($mobObject) {
      Write-DebugLog "Cloud Backup Service is registered"
      Write-DebugLog $mobObject.Server
      $serverUrl = $mobObject.Server
    }
    else {
      Write-DebugLog "Cloud Backup Service is not registered"
      Write-Error "Cloud Backup Service is not registered"  -ErrorAction Stop
    }
    
    Write-DebugLog $serverUrl
    $serverUrlWithouthHttps = $serverUrl.replace("https://", "")
    Write-DebugLog $serverUrlWithouthHttps
    $ApplianceIPAddress = $serverUrlWithouthHttps.substring(0, $serverUrlWithouthHttps.indexof(":"))
    Write-DebugLog "ApplianceIPAddress"
    Write-DebugLog $ApplianceIPAddress

    try {
      Write-DebugLog -Message "Validating appliance credentials"    
      $scvURL = "https://$ApplianceIPAddress"
      
      $JsonBody = $Body | ConvertTo-Json  
      $response = Invoke-RestMethod -Uri $scvURL":8080/login" -Body $JsonBody -Method POST -ContentType "application/json" -SkipCertificateCheck
        
      if ($response.PSObject.Properties.Match('error').Count) {
        Write-DebugLog -Message $response.error | Out-String
    
        if ($response.error.name -eq "USER_NAME_OR_PASSWORD_DO_NOT_MATCH") {
          Write-Error -ErrorId  "UPGRADE_USER_NAME_OR_PASSWORD_DO_NOT_MATCH" -Message  "Unable to login to appliance"
          Write-Error $response.error.message  -ErrorAction Stop
        }
        else {
          Write-Error -ErrorId  "UPGRADE_UNABLE_TO_LOGIN" -Message  "Unable to login to appliance"
          Write-Error $response.error.message  -ErrorAction Stop
        }
      }
      else {
        Write-DebugLog -Message "Appliance user credential validated"
      }
    }
    catch {
      Write-Error $_.exception.message  -ErrorAction Stop
    }  
    
    $ApplianceVirtualMachine = Get-ApplianceVirtualMachineUsingTag
  
    Write-DebugLog "Before Test-ApplianceExistOrNot"
    $testVMObject = Test-ApplianceExistOrNot -ApplianceVirtualMachine  $ApplianceVirtualMachine
    Write-DebugLog "After Test-ApplianceExistOrNot"
    
    $vmObject = Get-VM -Name  $ApplianceVirtualMachine
     
    Write-DebugLog "After Get-VM method called"
     
    $IsIPInExtensionData = $vmObject.ExtensionData.Guest.IpAddress -eq $ApplianceIPAddress
        
    Write-DebugLog "IsIPInExtensionData : $IsIPInExtensionData"
        
    if ($IsIPInExtensionData -eq $false) {
      Write-DebugLog "Appliance IP address not found"
      Write-Error "No IP address assigned for the appliance"  -ErrorAction Stop
    }
  
    $VmDatastore = Get-Datastore -RelatedObject $ApplianceVirtualMachine
  
    Test-DataStore -VmDatastore $VmDatastore -FreeSapce 3
    
    Test-Configuration -ApplianceIPAddress "" -ApplianceVirtualMachine $ApplianceVirtualMachine
        
    Write-DebugLog -Message "Test-Configuration execution is completed"
    
    Write-DebugLog -Message $ApplianceVirtualMachine
    
    Write-DebugLog -Message  "Generate datastore drive name"    
    
    $ds = "NetAppCBSUpgradeDatastoreSDrive"
    try {
      Write-DebugLog -Message  "Get-Datastore $VmDatastore | New-DatastoreDrive -Name ${ds}" | Out-String  
      $NewDatastoreDrive = Get-Datastore $VmDatastore | New-DatastoreDrive -Name ${ds}  -ErrorAction Stop   | Out-Null
    }
    catch {
      Write-DebugLog -Message  "Error while creating datastore drive."
      Write-DebugLog -Message  $_.exception | Out-String
      Write-Error -ErrorId "UPGRADE_NEW_DATASTORE_DRIVE_FAILED" -Message  "Error while creating datastore drive."
      Write-Error $_.exception.Message  -ErrorAction Stop
    }
  
    Write-DebugLog -Message  "Generate folder name" 
     
    Write-DebugLog -Message  "Folder name generated" 
  
    $CbsFolderName = "NetAppCBSUpgradeISOFileFolder" 
    Write-DebugLog -Message  "Test-Path -Path ${ds}:\${CbsFolderName}"
    $isIsoFolderEXist = Test-Path -Path "${ds}:\${CbsFolderName}"
    Write-DebugLog -Message  "isIsoFolderEXist = $isIsoFolderEXist"
    if ($isIsoFolderEXist -eq $false) {
      try {
        Write-DebugLog -Message  "New-Item -Type Directory -Path ${ds}:\${CbsFolderName} | Out-Null"
        New-Item -Type Directory -Path ${ds}:\${CbsFolderName}  | Out-Null
      }
      catch {
        Write-DebugLog -Message  $_.exception | Out-String
        Write-DebugLog -Message "Error while creating datastore folder ${ds}:\${CbsFolderName}."
      }
    }
    else {
      try {
        Write-DebugLog -Message  "Removing 0.iso."
        Remove-Item ${ds}:\${CbsFolderName}\0.iso -Force -ErrorAction SilentlyContinue | Out-Null 
      }
      catch {
        Write-DebugLog -Message  "Error while deleting ISO file."
        Write-DebugLog -Message   $_.exception.message | Out-String
      }
    }
      
    try {
      $GetLocation = Get-Location
      Write-DebugLog -Message "ISO path: $GetLocation"
      Write-DebugLog -Message "Source path: $GetLocation/$ISOName"
      Write-DebugLog -Message "Copy-DatastoreItem -Item -Destination -Force"
      $NewDatastoreDrive = Copy-DatastoreItem -Item "$GetLocation/$ISOName" -Destination ${ds}:\${CbsFolderName}\0.iso -Force | Out-Null 
    }
    catch {
      Write-DebugLog  -Message $_.exception | Out-String
      Write-Error  -ErrorId "upgrade-copydatastore-failed" -Message  $_.exception.Message -ErrorAction Stop 
    }
      
    Start-Sleep 10
    try {
      Write-DebugLog -Message "Mount datastore is in progress..."
      Stop-VM -VM $ApplianceVirtualMachine -Confirm:$false | Out-Null 
      Start-Sleep 60
      Get-VM -Name $ApplianceVirtualMachine | Get-CDDrive | Set-CDDrive -NoMedia -Confirm:$false
      PowerOffOnVM -ApplianceVirtualMachine $ApplianceVirtualMachine
      Write-DebugLog -Message "Get-VM -Name $ApplianceVirtualMachine | Get-CDDrive | Set-CDDrive -IsoPath [$VmDatastore]${CbsFolderName}\0.iso -Confirm:$false -Connected $true "
      $CDDrive = Get-VM -Name $ApplianceVirtualMachine | Get-CDDrive | Set-CDDrive -IsoPath "[$VmDatastore]${CbsFolderName}\0.iso" -Confirm:$false -Connected $true
    }
    catch {
      Write-Error  -ErrorId "UPGRADE_MOUNT_FAILED" -Message  $_.exception.Message
      Write-DebugLog  -Message $_.exception  | Out-String 
    }
    
    Start-Sleep 10

    Test-Configuration -ApplianceIPAddress "" -ApplianceVirtualMachine $ApplianceVirtualMachine
        
    Write-DebugLog -Message "Verify appliance IP address execution is completed"
    
    Write-DebugLog -Message $ApplianceVirtualMachine
    $vmObject = Get-VM -Name  $ApplianceVirtualMachine
    Write-DebugLog -Message $vmObject.ExtensionData.Guest.IpAddress
    $ApplianceIPAddress = $vmObject.ExtensionData.Guest.IpAddress

    # Even if vm is up after power off, few services takes time to be started which is required to call rest api
    # so add a delay
    Start-Sleep 180
    $Body = @{
      username = $scvLogin
      password = $scvPwd
    }     
        
    $scvURL = "https://$ApplianceIPAddress"
    
    $JsonBody = $Body | ConvertTo-Json
    
    $response = ""
    for ($i = 0; $i -lt 10; $i++) {
      try {
        Write-DebugLog -Message "Check if rest api service is up ." 
        $response = Invoke-RestMethod -Uri $scvURL":8080/login" -Body $JsonBody -Method POST -ContentType "application/json" -SkipCertificateCheck
        Write-DebugLog -Message "Rest api service is up." 
        break
      }
      catch {
        Write-DebugLog -Message "Rest api service is down."
        Write-DebugLog -Message $_.exception.message
        Start-Sleep 120
      }
    }
      
    $token = $response.result.token
    $Header = @{ Authorization = "Bearer $token" }
        
    $currentVersion = Invoke-RestMethod -Uri $scvURL":8080/api/rest/v1/agentversion" -Headers $Header -ContentType "application/json" -SkipCertificateCheck
      
    if ($currentVersion) {
      Write-DebugLog -Message "currentVersion" 
      Write-DebugLog -Message $currentVersion  | Out-String 
      Write-DebugLog -Message "currentVersion.result"
      Write-DebugLog -Message $currentVersion.result | Out-String 
      Write-DebugLog -Message  "currentVersion.result.scv_build"
      Write-DebugLog -Message  $currentVersion.result.scv_build | Out-String     
    }
    else {
      Write-DebugLog -Message "currentVersion is empty"
    }
  
    try {
      $logFile = Invoke-RestMethod -Uri $scvURL":8080/api/rest/v1/upgrade" -Headers $Header -Method POST -ContentType "application/json" -SkipCertificateCheck
      if ($logFile) {
        Write-DebugLog -Message "logFile created"
      }
      else {
        Write-DebugLog -Message "logFile is empty" 
      }
      
      Write-DebugLog -Message "Upgrade is in progress..."
      # 10 minute delay
      Start-Sleep 600
      
      $response = ""
      for ($i = 0; $i -lt 10; $i++) {
        try {
          Write-DebugLog -Message "Check if rest api service is up ." 
          $response = Invoke-RestMethod -Uri $scvURL":8080/login" -Body $JsonBody -Method POST -ContentType "application/json" -SkipCertificateCheck
          Write-DebugLog -Message "Rest api service is up." 
          break
        }
        catch {
          Write-DebugLog -Message "Rest api service is down."
          Write-DebugLog -Message $_.exception.message
          Start-Sleep 120
        }
      }

      $token = $response.result.token
      $Header = @{ Authorization = "Bearer $token" }
      $upgradedVersion = Invoke-RestMethod -Uri $scvURL":8080/api/rest/v1/agentversion" -Headers $Header -ContentType "application/json" -SkipCertificateCheck
      
      if ($upgradedVersion) {
        Write-DebugLog -Message "currentVersion" 
        Write-DebugLog -Message $upgradedVersion  | Out-String 
        Write-DebugLog -Message "currentVersion.result"
        Write-DebugLog $upgradedVersion.result | Out-String 
        Write-DebugLog -Message  "currentVersion.result.scv_build"
        Write-DebugLog -Message  $upgradedVersion.result.scv_build | Out-String     
      }
      else {
        Write-DebugLog -Message "Upgraded Version is empty"
      }
  
      if ($currentVersion.result.scv_build -ne $upgradedVersion.result.scv_build -or $currentVersion.result.scv_version -ne $upgradedVersion.result.scv_version) {
        Write-DebugLog -Message  "Upgrade of virtual appliance is successful."
        
      }
      else {
        $Parameters = @{
          filePath = $logFile.result.logFileName
        }
  
        $logFileContent = Invoke-RestMethod -Uri $scvURL":8080/api/rest/v1/readlogfile" -Headers $Header -Body $Parameters -ContentType "application/json" -SkipCertificateCheck
        Write-Error -Message "Upgrade of virtual appliance is failed."
        Write-Error -ErrorId "upgrade-log-failed"  -Message $logFileContent.result.logFileContent 
        Write-DebugLog -Message "Upgrade of virtual appliance is failed."
        Write-DebugLog -Message $logFileContent.result.logFileContent  
      }  
    }
    catch {
      Write-DebugLog -Message  $_.exception | Out-String
      Write-Error -Message $_.exception.message
    }
  
    # Below code is to make sure if upgrade fails, cd drive should be disconnected before deleting temporary
    # cd drives and folders created during upgrade steps.
    try {
      #disconnect
      Stop-VM -VM $ApplianceVirtualMachine -Confirm:$false | Out-Null 
      Start-Sleep 60
      Get-VM -Name $ApplianceVirtualMachine | Get-CDDrive | Set-CDDrive -NoMedia -Confirm:$false
      PowerOffOnVM -ApplianceVirtualMachine $ApplianceVirtualMachine
    }
    catch {
      Write-DebugLog -Message  $_.exception | Out-String
    }
  
    try {
      Write-DebugLog -Message  "Removing ISO file."
      Remove-Item ${ds}:\${CbsFolderName}\0.iso -Force
    }
    catch {
      Write-DebugLog -Message  "Error while deleting iso file."
      Write-DebugLog -Message   $_.exception | Out-String
      Write-Error -ErrorId $_.exception.message
    }
  }

  END {
    Write-DebugLog -Message "Update-NetAppCBSAppliance execution is completed"
  }   
}