Install.ps1

function Install-Appliance {
  param(
    [Parameter(
      Mandatory = $true,
      HelpMessage = "Do you accept <a href='https://www.netapp.com/pdf.html?item=/media/14114-enduserlicenseagreementworldwide.pdf'>End User License Aggrement</a> ? Specify true to agree. In a interactive mode specify any value to agree and leave it blank to disagree.")]
    [ValidateNotNullOrEmpty()]
    [boolean]
    $AcceptNetAppEulaAggrement,

    [Parameter(
      Mandatory = $true,
      HelpMessage = 'Specify the virtual machine for the virtual appliance.')]
    [ValidateNotNullOrEmpty()]
    [string]
    $ApplianceVirtualMachine,

    [Parameter(
      Mandatory = $true,
      HelpMessage = 'Specify the destination ESXi hostname for the virtual appliance.')]
    [ValidateNotNullOrEmpty()]
    [string]
    $EsxHost,

    [Parameter(
      Mandatory = $true,
      HelpMessage = 'Specify the datastore to be used for the appliance')]
    [ValidateNotNullOrEmpty()]
    [string]
    $VmDatastore,

    [Parameter(
      Mandatory = $true,
      HelpMessage = 'Specify the destination network for each source network')]
    [ValidateNotNullOrEmpty()]
    [string]
    $NetworkMapping,

    [Parameter(
      Mandatory = $true,
      HelpMessage = 'Specify the network name of the virtual appliance.')]
    [string]
    $ApplianceNetworkName,

    [Parameter(
      HelpMessage = 'Specifies if Dhcp has to be used for the appliance instead of static IP address')]
    [boolean]
    $Dhcp,

    [Parameter(
      Mandatory = $false,
      HelpMessage = 'IPV4 address for the appliance')]
    [string]
    $ApplianceIPAddress,

    [Parameter(
      Mandatory = $false,
      HelpMessage = 'Subnet mask')]
    [string]
    $Netmask,

    [Parameter(
      Mandatory = $false,
      HelpMessage = 'Gateway on the deployed network')]
    [string]
    $Gateway,

    [Parameter(
      Mandatory = $false,
      HelpMessage = 'Primary DNS server IP address')]
    [string]
    $PrimaryDNS,

    [Parameter(Mandatory)]
    [System.Management.Automation.PSCredential]
    $scvcredential
  )

 
  BEGIN { 
  
    $ApplianceVirtualMachine = $ApplianceVirtualMachine.Trim()
    $EsxHost = $EsxHost.Trim()
    $VmDatastore = $VmDatastore.Trim()
    $NetworkMapping = $NetworkMapping.Trim()
    $ApplianceNetworkName = $ApplianceNetworkName.Trim()
    
    Write-DebugLog "In Begin block of cmdlet Install-NetAppCBSAppliance"
    Write-Verbose "In Begin block of cmdlet Install-NetAppCBSAppliance"

    $newUserName = "NetAppSCDPAdmin"
    $newUserFirstName = "SCDP Administrator"
    $newUserLastName = "vsphere.local"
    $Domain = "VSPHERE.LOCAL"
    $vra_user = $Domain + "\" + $newUserName
    $SCDPRole = "SCDP Administrator"

    $tagName = "AVS_ANF_CLOUD_ADMIN_VM_TAG"
    $tagCategoryName = "AVS_ANF_CLOUD_ADMIN_VM_TAG_CATEGORY"
  
    $OVAName = "scv-1.0.ova"
    $ContainerName = "ovaisocontainer" 
    $StorageAccountName = "netappavsanfaccount"   

  }

  PROCESS {
    
    Write-DebugLog -Message "Install-NetAppCBSAppliance execution is started"
    Write-Verbose -Message "Install-NetAppCBSAppliance execution is started"

    if ($AcceptNetAppEulaAggrement -ne $true) {
      Throw "You must accept the NetApp Eula Aggrement to install." 
    } 
    
    Invoke-PreflightNetAppCBSAVSCheck
    test-vc-address

    

    if ($Dhcp -eq $true) {
      $ApplianceIPAddress = "";
      $Netmask = "";
      $Gateway = "";
      $PrimaryDNS = "";
    }  
  
    $newUserPassword = Get-Password
    $vcSecurePass = ($newUserPassword | ConvertTo-SecureString -AsPlainText -Force)
    $vcNewUserCred = New-Object System.Management.Automation.PSCredential ($newUserName, $vcSecurePass)

    try {
      $tagAssignment = Get-TagAssignment -Tag $tagName -Category $tagCategoryName -ErrorAction SilentlyContinue          
    }
    catch {
      if ($tagAssignment) { 
        Write-DebugLog "Inside catch block but tagAssignment is not emptry"
        if ($tagAssignment.Entity.Name) {
          Write-DebugLog "Appliance name "$tagAssignment.Entity.Name | Out-String
        }
      }
      Write-DebugLog $_.exception.Message
    }
  
    if ($tagAssignment) {         
      Write-Verbose "Tag Present"
      Write-DebugLog "Tag Present"
      $VirtualMachine = $tagAssignment.Entity.Name  

      $CommandName = "Install-NetAppCBSAppliance"
      
      if ($Dhcp -eq $true) {
        $CommandName = "Install-NetAppCBSApplianceUsingDHCP"
      }

      if ($VirtualMachine) {
        Throw "Virtual machine appliance is already installed. Only one virtual machine appliance is supported. Use cmdlet UnInstall-NetAppCBSAppliance to uninstall the virtual machine appliance, and then install using cmdlet $CommandName."
      }
      else {
        Write-DebugLog "Empty entity"
      }
    }
    else {
      Write-DebugLog "Tag not found"
    }  
  
    $VMObject = Get-VM -Name $ApplianceVirtualMachine -ErrorAction SilentlyContinue -ErrorVariable CloudAdminVMError
  
    # Install when $CloudAdminVMError is not empty or $VMObject is empty
    if (($CloudAdminVMError -ne $null) -or ($null -eq $VMObject)) {
      if ($CloudAdminVMError) {
        Write-DebugLog -Message "CloudAdminVMError is not empty"
        Write-DebugLog -Message $CloudAdminVMError | Out-String
        if ($CloudAdminVMError.PSObject.Properties.Match('CategoryInfo').Count) {
          if ($CloudAdminVMError.CategoryInfo.Category -eq "ObjectNotFound") {
            Write-DebugLog -Message "VM not found : $CloudAdminVMError"
          }
          else {
            Write-DebugLog -Message "Unable to fetch details about $ApplianceVirtualMachine"
          }
        }      
      }
      if ($null -eq $VMObject) {
        Write-DebugLog -Message "VMObject is empty "
      }

      # Validate datastore
      Test-DataStore -VmDatastore $VmDatastore -FreeSapce 60

      $isValidApplianceIPAddress = Test-IpAddress $ApplianceIPAddress

      if ($isValidApplianceIPAddress -eq $false) {
        Throw "Invalid Appliance IP Address."
      }

      test-virtual-network -network $NetworkMapping
      test-stale-plugin
            
      $rc = ping_vm $PrimaryDNS 5
      if (!$rc) {
        Write-Error "ERROR: Dns server $PrimaryDNS not pingable."
        return
      }
      else {
        Write-Host "Dns server $PrimaryDNS is pingable"
      }


      try {        
        $BlobContent = Get-BlobContent -BlobName $OVAName -StorageAccountName $StorageAccountName -ContainerName $ContainerName -ErrorAction Stop
        Write-DebugLog $BlobContent | Out-String
        Write-DebugLog -Message "OVA file downloaded."
        Write-Verbose -Message "OVA file downloaded."
      }
      catch {
        Write-DebugLog -Message  $_.exception | Out-String
        Write-Error -ErrorId  "INSTALL_OVA_DOWNLOAD_FAILED" -Message  "Download failed"
        Throw $_.exception.Message
      }  
      
      Write-Host -Message "Installing..."
      Write-DebugLog -Message "Installing..."
      Write-DebugLog -Message "Add-SSOUser -Domain $Domain -vcUserCre -FirstName $newUserFirstName -LastName $newUserLastName"
      Add-SSOUser -Domain $Domain -vcUserCre $vcNewUserCred -FirstName $newUserFirstName -LastName $newUserLastName
      Write-DebugLog -Message "Add-Role -vra_user $vra_user -SCDPRole $SCDPRole"
      Add-Role -vra_user $vra_user -SCDPRole $SCDPRole
      Write-DebugLog -Message "Deploy-OVA -ApplianceVirtualMachine $ApplianceVirtualMachine -EsxHost $EsxHost -VmDatastore $VmDatastore -NetworkMapping $NetworkMapping -ApplianceNetworkName $ApplianceNetworkName -Dhcp -ApplianceIPAddress $ApplianceIPAddress -Netmask $Netmask -Gateway $Gateway -PrimaryDNS $PrimaryDNS -Domain $Domain"
      Deploy-OVA -ApplianceVirtualMachine $ApplianceVirtualMachine -EsxHost $EsxHost -VmDatastore $VmDatastore -NetworkMapping $NetworkMapping -ApplianceNetworkName $ApplianceNetworkName -Dhcp $Dhcp -ApplianceIPAddress $ApplianceIPAddress -Netmask $Netmask -Gateway $Gateway -PrimaryDNS $PrimaryDNS -Domain $Domain -scvCre $scvcredential -vcUserCredential $vcNewUserCred -OVAName $OVAName

      Add-TagToVM -ApplianceVirtualMachine $ApplianceVirtualMachine

      Mount-VmwareTools -ApplianceVirtualMachine $ApplianceVirtualMachine

      Show-Progress -TotalNoOfTimes 100 -SleepTime 4 -ActivityText 'Mount-VmwareTools' -ProgressText "percent complete"

      Test-VMWareToolInstallStatus -ApplianceVirtualMachine $ApplianceVirtualMachine
      
      Write-DebugLog "Vmware Tools installed"
      Restart-VMwareVM -ApplianceVirtualMachine $ApplianceVirtualMachine

      Write-DebugLog -Message "Wait for 15 minutes to ensure OVA deployment is completed."  
      Write-DebugLog -Message 'Show-Progress -TotalNoOfTimes 100 -SleepTime 4 -ActivityText 'Mount tools' -ProgressText "percent complete"'
      Show-Progress -TotalNoOfTimes 100 -SleepTime 4 -ActivityText 'Waiting for OVA deployment' -ProgressText "percent complete"
      
      Test-Installation -ApplianceIPAddress $ApplianceIPAddress -ApplianceVirtualMachine $ApplianceVirtualMachine
      
      Write-DebugLog -Message "Deploy-OVA execution is completed"
      Write-Verbose -Message "Deploy-OVA execution is completed"    
    }
    else {
      Write-DebugLog "CloudAdminVMError is empty"
      Write-DebugLog $VMObject | Out-String
      if ($VMObject -and ($VMObject.Name -eq $ApplianceVirtualMachine)) {
        Write-DebugLog -Message "VM with name $ApplianceVirtualMachine already present."
        Throw "Virtual Machine with name $ApplianceVirtualMachine already present."
      }
    }
  }
  end {
    Write-DebugLog -Message "Install-NetAppCBSAppliance execution is completed"
    Write-Verbose -Message "Install-NetAppCBSAppliance execution is completed"
  }  
}

function   test-virtual-network {
  param(
    [Parameter(Mandatory = $true)]
    $network
  )
  # Check if provided network exists in the datacenter
  $nw_obj = Get-VirtualNetwork $network -ErrorAction SilentlyContinue
  if ($null -eq $nw_obj) {
    Write-Error "Specified network name $network not found in the datacenter. Please provide a correct network name"
  }
  else {
    $AVSModule = Get-Module -Name Microsoft.AVS.Management
    $AVSProtectedNWS = & $AVSModule { Get-ProtectedNetworks }
    if ($AVSProtectedNWS.Name.ToLower() -Contains $network.ToLower()) {
      Write-Error "Network $network is one of AVS protected networks. Please provide a different network for MSA deployment"
    }
    else {
      Write-Host "SUCCESS: Network provided for MSA is not an AVS protected network."
    }
  }
}

function test-stale-plugin {
  
  $scvExtension1 = "com.netapp.aegis"
  $scvExtension2 = "com.netapp.scvm.webclient"
  $em = Get-View ExtensionManager
  $extensionList = $em.ExtensionList.Key
  if (($extensionList -contains $scvExtension1) -or (($extensionList -contains $scvExtension2))) {
    Write-Error "VCenter already has Cloud Backup Service plugin. Please unregister vCenter or cleanup any stale plugins before continuing."
  }
}

function test-vc-address {
  $vc_up = ping_vm $VC_ADDRESS 5
  if (!$vc_up) {
    Write-Error "vCenter IP adress $VC_ADDRESS is not pingable." -ErrorAction Stop
    return
  }
  else {
    Write-Host "vCenter IP adress $VC_ADDRESS is pingable."
  }
}
function Test-VMWareToolInstallStatus () {
     param(
    [Parameter(Mandatory = $true)]
    $ApplianceVirtualMachine
  )
  $Count = 20
  :verifyvmwaretoolsstatus For ($i = 0; $i -le $Count; $i++) {
    $VMGuestObject = Get-VMToolsStatus -ApplianceVirtualMachine $ApplianceVirtualMachine
    Write-DebugLog $VMGuestObject | Out-String
    $IsStatusPropertyExist = [bool]($VMGuestObject -match "Status")
    $IsGuestStatePropertyExist = [bool]($VMGuestObject -match "GuestState")
    if ($IsStatusPropertyExist -and $IsGuestStatePropertyExist) {
      if (($VMGuestObject.Status -eq "toolsOk") -and ($IsGuestStatePropertyExist -eq "Running")) {
        break 'verifyvmwaretoolsstatus'
      }
      else {
        Start-Sleep 10
      }
    }
            
             $PercentComplete = ($i / $Count) * 100
             
    Write-Progress -Activity "Fetching VMware install status" -Status "$i/$count : $PercentComplete % Complete" -PercentComplete $PercentComplete
  }
}

function ShowEULAText {
  $modulePath = Split-Path -Path (Get-Module -Name NetApp.SC-preview).Path
  $eulaFilePath = $modulePath + "/EULA.txt"
  foreach ($line in [System.IO.File]::ReadLines($eulaFilePath)) {
    Write-Host $line -ForegroundColor Yellow
  }
}

function Add-SSOUser () {

  [CmdletBinding()]
  param(
    [Parameter(Mandatory)]
    [string]$Domain,
    [Parameter(Mandatory)]
    [System.Management.Automation.PSCredential]$vcUserCre,
    [Parameter()]
    [string]$FirstName,
    [Parameter()]
    [string]$LastName
  )

  PROCESS {
    Write-DebugLog -Message "Add-SSOUser execution is started"
    Write-Verbose -Message "Add-SSOUser execution is started"
  
    $userName = $vcUserCre.UserName
    $vcPwd = $vcUserCre.GetNetworkCredential().Password
    Write-DebugLog -Message "Get-SsoPersonUser -Domain $Domain -Name $userName"
    $SCDPAdminObject = Get-SsoPersonUser -Domain $Domain -Name $userName
    Write-DebugLog -Message "SCDPAdminObject"
  
    if ($null -eq $SCDPAdminObject) {
      Write-DebugLog -Message "SCDPAdminObject empty"
      Write-DebugLog -Message "New-SsoPersonUser -UserName $userName -Password -FirstName $FirstName -LastName $LastName"
      New-SsoPersonUser -UserName $userName -Password $vcPwd -FirstName $FirstName -LastName $LastName -Description "NetApp CBS appliance user" | Out-Null
      Write-DebugLog -Message "User created"
    }
    else {  
      #Change NetAppSCDPAdmin password
      $vcSecurePass = ($vcPwd | ConvertTo-SecureString -AsPlainText -Force)
      $vcNewUserCred = New-Object System.Management.Automation.PSCredential ($userName, $vcSecurePass)
  
      Set-Password -vcUserCre $vcNewUserCred
      Write-DebugLog -Message "User $userName is present in domain $Domain "
    }
  }
  
  END {
    Write-DebugLog -Message "Add-SSOUser execution is completed"
    Write-Verbose -Message "Add-SSOUser execution is completed"
  }  
}
function Add-Role () {

  [CmdletBinding()]
  param(
    [Parameter(Mandatory)]
    [string]$vra_user,
    [Parameter()]
    [string]$SCDPRole
  )
  
  BEGIN {

    Write-DebugLog -Message "In begin block of Add-Role"
    Write-Verbose -Message "In begin block of Add-Role"
  
    $SCDPAdmin_Privileges = @(
      "System.Anonymous"
      "System.View"
      "System.Read"
      "Datastore.Rename"
      "Datastore.Move"
      "Datastore.Delete"
      "Datastore.Browse"
      "Datastore.FileManagement"
      "Datastore.AllocateSpace"
      "Network.Assign"
      "Host.Config.Storage"
      "Host.Config.AdvancedConfig"
      "Host.Config.Resources"
      "Host.Config.Settings"
      "Host.Local.CreateVM"
      "Host.Local.ReconfigVM"
      "Host.Local.DeleteVM"
      "VirtualMachine.Inventory.Create"
      "VirtualMachine.Inventory.CreateFromExisting"
      "VirtualMachine.Inventory.Register"
      "VirtualMachine.Inventory.Delete"
      "VirtualMachine.Inventory.Unregister"
      "VirtualMachine.Inventory.Move"
      "VirtualMachine.Interact.PowerOn"
      "VirtualMachine.Interact.PowerOff"
      "VirtualMachine.GuestOperations.Query"
      "VirtualMachine.GuestOperations.Modify"
      "VirtualMachine.GuestOperations.Execute"
      "VirtualMachine.Config.AddExistingDisk"
      "VirtualMachine.Config.AddNewDisk"
      "VirtualMachine.Config.RemoveDisk"
      "VirtualMachine.Config.Resource"
      "VirtualMachine.Config.AdvancedConfig"
      "VirtualMachine.Config.ReloadFromPath"
      "VirtualMachine.State.CreateSnapshot"
      "VirtualMachine.State.RevertToSnapshot"
      "VirtualMachine.State.RemoveSnapshot"
      "Resource.AssignVMToPool"
      "Resource.ApplyRecommendation"
      "Resource.HotMigrate"
      "Resource.ColdMigrate"
      "Resource.QueryVMotion"
      "Task.Create"
      "Task.Update"
      "Extension.Register"
      "Extension.Update"
      "Extension.Unregister"
    )
  
  }
  
  PROCESS {
    
    Write-DebugLog -Message "Add-Role execution is started"
    Write-Verbose -Message "Add-Role execution is started"

    Write-DebugLog -Message "Creating Role $SCDPRole"

    Write-DebugLog -Message "New-VIRole -Name $SCDPRole -Privilege (Get-VIPrivilege -Id $SCDPAdmin_Privileges) -ErrorAction SilentlyContinue -ErrorVariable SCDPRoleError"
    $NewVIRole = New-VIRole -Name $SCDPRole -Privilege (Get-VIPrivilege -Id $SCDPAdmin_Privileges) -ErrorAction SilentlyContinue -ErrorVariable SCDPRoleError
    Write-DebugLog -Message "SCDPRoleError"
  
    if ($SCDPRoleError) {
      Write-DebugLog -Message "SCDPRoleError is not empty"
      if ($SCDPRoleError.exception.GetType().Name -eq "DuplicateName") {
        Write-DebugLog -Message "A Role with name $SCDPRole already exists on server"
      }
      else {
        Write-Error Error-Id "install-create-role-failed" -Message "Could not create role."
        Write-DebugLog -Message $SCDPRoleError.exception | Out-String
      }
    }
  
    Write-DebugLog -Message "Assigning privilege"
    $rootFolder = Get-Folder -NoRecursion
    Write-DebugLog -Message "Get-VIRole -Name $SCDPRole"
    $SCDPRoleObject = Get-VIRole -Name $SCDPRole
    Write-DebugLog -Message "New-VIPermission -entity $rootFolder -Principal $vra_user -Role $SCDPRoleObject -ErrorAction SilentlyContinue -ErrorVariable VIPermissionError" | Out-String
    New-VIPermission -entity $rootFolder -Principal $vra_user -Role $SCDPRoleObject -ErrorAction SilentlyContinue -ErrorVariable VIPermissionError | Out-Null
  }
  
  END {
    Write-DebugLog -Message "Add-Role execution is completed"
    Write-Verbose -Message "Add-Role execution is completed"
  }  
}

function Add-TagToVM {
  param(
    [Parameter(Mandatory = $true)]
    $ApplianceVirtualMachine
  )

  BEGIN {
    Write-DebugLog -Message "In begin block of Add-TagToVM"
    Write-Verbose -Message "In begin block of Add-TagToVM"

    $newTagName = "AVS_ANF_CLOUD_ADMIN_VM_TAG"
    $newTagDescription = "Tag to identify VMs created using AVS-ANF script "
    $newTagCategoryName = "AVS_ANF_CLOUD_ADMIN_VM_TAG_CATEGORY"
    $newTagCategoryDescription = "TagCategory for the tag CloudAdminVmTag"
  }

  PROCESS {

    Write-DebugLog -Message "Add-TagToVM execution is started"
    Write-Verbose -Message "Add-TagToVM execution is started"
    Write-DebugLog -Message "Inside Add-TagToVM " |  Out-String

    Try {
      #Assign Tag to VM
      $GetVMTag = Get-Tag -Name $newTagName -ErrorAction Stop
      Write-DebugLog -Message "TagName $newTagName found"  | Out-String
      Get-VM $ApplianceVirtualMachine | New-TagAssignment -Tag $GetVMTag  | Out-Null 
      Write-DebugLog "Tag Assignment completed"
    }
    Catch {
      Try {
        $GetVMTagCat = Get-TagCategory -Name $newTagCategoryName -ErrorAction Stop
        Write-DebugLog "TagCategory found"
        New-Tag -Name $newTagName -Category $GetVMTagCat -Description $newTagDescription | Out-Null
      }
      Catch {
        Write-DebugLog "TagCategory with name CloudAdminVmTagCategory not found. Creat one"
        New-TagCategory -Name $newTagCategoryName -Description $newTagCategoryDescription | Out-Null
        Write-DebugLog "Now, let's create a new Tag under TagCategory:" $newTagCategoryName
        New-Tag -Name $newTagName -Category $newTagCategoryName -Description $newTagDescription | Out-Null
      }
      #Assign Tag to VM
      $GetVMTag = Get-Tag -Name $newTagName -ErrorAction Stop
       
      Get-VM -Name $ApplianceVirtualMachine | New-TagAssignment -Tag $GetVMTag   | Out-Null  
    
      Write-Host "Tag Assignment completed"
    }
  }

  END {
    Write-DebugLog -Message "Add-TagToVM execution is completed"
    Write-Verbose -Message "Add-TagToVM execution is completed"
  }

}

function Deploy-OVA () {

  param(
    [Parameter(Mandatory)]
    [string]$ApplianceVirtualMachine,
    [Parameter(Mandatory)]
    [string]$EsxHost,
    [Parameter(Mandatory)]
    [string]$VmDatastore,
    [Parameter(Mandatory)]
    [string]$NetworkMapping,
    [Parameter(Mandatory)]
    [string]$ApplianceNetworkName,
    [boolean]$Dhcp,
    [Parameter()]
    [string]$ApplianceIPAddress,
    [Parameter()]
    [string]$Netmask,
    [Parameter()]
    [string]$Gateway,
    [Parameter()]
    [string]$PrimaryDNS,
    [Parameter(Mandatory)]
    [string]$Domain,
    [Parameter(Mandatory)]
    [string]$OVAName,
    [Parameter(Mandatory)]
    [System.Management.Automation.PSCredential]$scvCre,
    [Parameter(Mandatory)]
    [System.Management.Automation.PSCredential]$vcUserCredential
  )

  PROCESS {    
 
    Write-DebugLog -Message "Deploy-OVA execution is started"
    Write-Verbose -Message "Deploy-OVA execution is started"

    $vcenterLogin = $vcUserCredential.UserName
    $vcPwd = $vcUserCredential.GetNetworkCredential().Password
    $scvLogin = $scvCre.UserName
    $scvPwd = $scvCre.GetNetworkCredential().Password
    $ovfConfig = Get-OvfConfiguration -Ovf $OVAName
    Write-DebugLog -Message "ovfConfig.NetworkMapping.nat.Value = $NetworkMapping"
    $ovfConfig.NetworkMapping.nat.Value = $NetworkMapping
    $ovfconfig.vplatform.Vendor_Provider_Appliance.auth.UserName.Value = $scvLogin
    $ovfconfig.vplatform.Vendor_Provider_Appliance.auth.passwd.Value = $scvPwd
    Write-DebugLog -Message "ovfconfig.vplatform.Vendor_Provider_Appliance.vcenter.register.ipAddress.Value = $VC_ADDRESS"
    $ovfconfig.vplatform.Vendor_Provider_Appliance.vcenter.register.ipAddress.Value = $VC_ADDRESS
    $ovfconfig.vplatform.Vendor_Provider_Appliance.vcenter.register.UserName.Value = "$vcenterLogin@$Domain"
    $ovfconfig.vplatform.Vendor_Provider_Appliance.vcenter.register.passwd.Value = $vcPwd
    Write-DebugLog -Message "ovfconfig.vplatform.Vendor_Provider_Appliance.hostName.Value = $ApplianceNetworkName"
    $ovfconfig.vplatform.Vendor_Provider_Appliance.hostName.Value = $ApplianceNetworkName

    if ($Dhcp -eq $false) {
      Write-DebugLog -Message "ovfconfig.vplatform.Vendor_Provider_Appliance.ipAddress.Value = $ApplianceIPAddress"
      $ovfconfig.vplatform.Vendor_Provider_Appliance.ipAddress.Value = $ApplianceIPAddress
      Write-DebugLog -Message "ovfconfig.vplatform.Vendor_Provider_Appliance.netMask.Value = $Netmask"
      $ovfconfig.vplatform.Vendor_Provider_Appliance.netMask.Value = $Netmask
      Write-DebugLog -Message "ovfconfig.vplatform.Vendor_Provider_Appliance.gateway.Value = $Gateway"
      $ovfconfig.vplatform.Vendor_Provider_Appliance.gateway.Value = $Gateway
      Write-DebugLog -Message "ovfconfig.vplatform.Vendor_Provider_Appliance.primaryDNS.Value = $PrimaryDNS"
      $ovfconfig.vplatform.Vendor_Provider_Appliance.primaryDNS.Value = $PrimaryDNS
    }

    Write-DebugLog -Message "ovfconfig.vplatform.Vendor_Provider_Appliance.searchDomains.Value = $Domain"
    $ovfconfig.vplatform.Vendor_Provider_Appliance.searchDomains.Value = $Domain

    Write-DebugLog -Message "Import-VApp -Name $ApplianceVirtualMachine -VMHOST $EsxHost -Datastore $VmDatastore -DiskStorageFormat thin -Confirm:$false -Force" | Out-String
  
    try {
      Import-VApp -Source $OVAName -OvfConfiguration $ovfconfig -Name $ApplianceVirtualMachine -VMHOST $EsxHost -Datastore $VmDatastore -DiskStorageFormat thin -Confirm:$false -Force | Out-Null
    }
    catch {
      Write-Error -ErrorId "INSTALL-IMPORT-FAILED" -Message "Import failed during installation"
      Throw $_.exception.Message
    } 

    Write-DebugLog -Message "Show-Progress -TotalNoOfTimes 100 -SleepTime 1 -ActivityText 'Deploying' -ProgressText "percent complete""
    Show-Progress -TotalNoOfTimes 100 -SleepTime 1 -ActivityText 'Deploying' -ProgressText "percent complete" 
  }

  END {
    Write-DebugLog -Message "Deploy-OVA execution is completed"
    Write-Verbose -Message "Deploy-OVA execution is completed"
  }
}

function Mount-VmwareTools {
  param(
    [Parameter(Mandatory = $true)]
    $ApplianceVirtualMachine
  )

  PROCESS {
    Write-Verbose -Message "Mount-VmwareTools execution is started"
    Write-DebugLog -Message "Mount-VmwareTools execution is started"

    StopStartVMWareVM -ApplianceVirtualMachine  $ApplianceVirtualMachine
  
    Write-DebugLog -Message "Waiting for configuration to prompt for mounting VmWare Tools......"
    Write-DebugLog -Message "Show-Progress -TotalNoOfTimes 100 -SleepTime 1 -ActivityText Start-VM -ProgressText percent complete"
    Show-Progress -TotalNoOfTimes 100 -SleepTime 1 -ActivityText "Start-VM" -ProgressText "percent complete"
  
    Write-DebugLog -Message "Mounting tools..."
    Write-DebugLog -Message "Mount-Tools -VM $ApplianceVirtualMachine | Out-Null"
  
    try {
      Mount-Tools -VM $ApplianceVirtualMachine  -ErrorAction Stop | Out-Null
    }
    catch {
      Write-DebugLog -Message  $_.exception | Out-String
      Write-Error -ErrorId "INSTALL-MOUNT-FAILED" -Message "Mount failed"
      Throw $_.exception.Message
    }
  
  }
 
  END {
    Write-Verbose -Message "Mount-VmwareTools execution is completed"
    Write-DebugLog -Message "Mount-VmwareTools execution is completed"
  }

}

function Test-Installation {

  param(
    [Parameter()]
    [string]
    $ApplianceIPAddress,

    [Parameter()]
    [string]
    $ApplianceVirtualMachine
  )

  BEGIN {
    Write-Verbose -Message "In begin block of Test-Installation"
    Write-DebugLog -Message "In begin block of Test-Installation"
  
    $scvExtension1 = "com.netapp.aegis"
    $scvExtension2 = "com.netapp.scvm.webclient"
    
    $maxNoOfTimesToLoop = 28
  }  

  PROCESS {

    Write-Verbose -Message "Test-Installation execution is started"
    Write-DebugLog -Message "Test-Installation execution is started"

    $em = Get-View ExtensionManager
    $extensionList = $em.ExtensionList.Key
    $IsRegistered = $false
    $IsIPInExtensionData = $false
    $IsVMRestartedOnce = $false
    for ($Counter = 1; $Counter -lt $maxNoOfTimesToLoop; $Counter++) {
      ## unregistering from GUI
      $em = Get-View ExtensionManager
      $extensionList = $em.ExtensionList.Key
      if ($extensionList -contains $scvExtension1 -and $extensionList -contains $scvExtension2) {      
        # In case of static ip address
        if ($ApplianceIPAddress -eq "" -or $null -eq $ApplianceIPAddress) {
          # If already one vm is presnt and new vm is created then we need to make sure that the extension is updated with new appliance ip address.
          $ApplianceIPAddress = (Get-VM | Select-Object Name, @{N = "IP Address"; E = { @($_.guest.IPAddress[0]) } } | Where-Object { $_.Name -Match $ApplianceVirtualMachine }).'IP Address'
        }
        
        $IsRegistered = (Get-View ExtensionManager | Select-Object -ExpandProperty ExtensionList | Select-Object Key, @{N = 'Server'; E = { $_.Server.url } } |  Where-Object { $_.Key -eq "com.netapp.aegis" }).Server -Match $ApplianceIPAddress
        Write-DebugLog -Message "isRegistered : $IsRegistered"
        $vmObject = Get-VM -Name  $ApplianceVirtualMachine
        $IsIPInExtensionData = $vmObject.ExtensionData.Guest.IpAddress -eq $ApplianceIPAddress
        
        Write-DebugLog "$IsIPInExtensionData : $$IsIPInExtensionData"
        
        if (($IsRegistered -eq $true) -and $IsIPInExtensionData -eq $true) {
          Write-DebugLog "inside vmObject.ExtensionData.Guest.IpAddress"                
          Write-Host "Installation is successful"
          Write-Progress -Activity "Verifying Virtual Machine's IP address" -Status "Done" -completed
          break
        }
      }    
      
     
      <#
      If this is end of the loop but installation is still not completed,
      then restart the VM and again start the verification cycle.
      #>

      if ($Counter -eq 15) {
        
        Write-DebugLog "IsVMRestartedOnce : $IsVMRestartedOnce" 
        if ($IsVMRestartedOnce -eq $false) {
          Write-DebugLog -Message "Inside IsVMRestartedOnce is false"            
          Write-DebugLog -Message "IsVMRestartedOnce : $IsVMRestartedOnce"                 
          Write-DebugLog -Message "Restart-VMwareVM -ApplianceVirtualMachine $ApplianceVirtualMachine"            
          Restart-VMwareVM -ApplianceVirtualMachine $ApplianceVirtualMachine                
          $IsVMRestartedOnce = $true  
          Start-Sleep 30                       
          Write-DebugLog -Message "Verifying Virtual Machine's IP address"  
        }
        else {
          Throw "Registration failed"
        }   
      }
      else {
        Write-DebugLog "Start-Sleep 3"
        Start-Sleep 30
      }  
        
      $PercentComplete = ($Counter / $maxNoOfTimesToLoop) * 100
             
      Write-Progress -Activity "Verifying Virtual Machine's IP address" -Status "$Counter/$maxNoOfTimesToLoop : $PercentComplete % Complete" -PercentComplete $PercentComplete
        
    }

    if ($IsRegistered -eq $false) {
      Write-DebugLog "Could not register cloud backup service."                
      Throw "Could not register cloud backup service."
    }

    if ($IsIPInExtensionData -eq $false) {
      Write-DebugLog "Could not assign IP address for virtual machine appliance."                
      Throw "Could not assign IP address for virtual machine appliance."
    }
  }
  END {
    Write-Verbose -Message "Test-Installation execution is completed"
    Write-DebugLog -Message "Test-Installation execution is completed"
  }
}

function StopStartVMWareVM {
  param(
    [Parameter()]
    [string]
    $ApplianceVirtualMachine
  )
  Write-DebugLog -Message "Get-VM -Name $ApplianceVirtualMachine -ErrorAction SilentlyContinue -ErrorVariable SCDPRoleError"
  $VMObject = Get-VM -Name $ApplianceVirtualMachine -ErrorAction SilentlyContinue -ErrorVariable GetVMError

  if ($GetVMError) {
    Write-DebugLog $GetVMError | Out-String
  }

  if ($VMObject) {
    $VMPowerState = $VMObject.PowerState
    Write-DebugLog -Message "VMPowerState: $VMPowerState"
    if ($VMPowerState -ne "PoweredOn") {
      Start-VM -VM $ApplianceVirtualMachine | Out-Null
      $Count = 10
      For ($i = 0; $i -le $Count; $i++) {
            
        $VMObject = Get-VM -Name $ApplianceVirtualMachine
        $VMPowerState = $VMObject.PowerState
        if ($VMPowerState -eq "PoweredOn") {
          break
        }
        else {
          Start-Sleep 10
        }
        $PercentComplete = ($i / $Count) * 100
        Write-Progress -Activity "Start-VM" -Status "$i/$count : $PercentComplete % Complete" -PercentComplete $PercentComplete
      }
      Write-Progress -Activity "Start-VM"  -Status "Done" -complete
    }
    else {
      Write-DebugLog -Message "VM is already powered on"
    }
  }
}