piercj2's Posts

deleted
deleted
deleted
you were right Luc, was using a Windows AD Account. after some googling i found this “You cannot use Windows Authentication with another account unless the PowerShell window is RunAs anothe... See more...
you were right Luc, was using a Windows AD Account. after some googling i found this “You cannot use Windows Authentication with another account unless the PowerShell window is RunAs another user.  You can use RunAs and make the PowerShell window or the Management Studio window run as that other Windows user and then connect with integrated security. Windows users cannot be used with UserId and Password statements in the connection string or SQL Connection.  The only way to use Windows Authentication is to use Integrated Security=SSPI and it will take the currently logged on user.  Otherwise if you use a Username and Password it uses SQL Authentication.  ” If i run  Powershell as the Windows AD user, the connection to the SQL DB establishes. Passing the Windows AD Credentials within the script, the connection fails. Time for me to go get a local SQL account created thanks again, Jason
an error Exception calling "Open" with "0" argument(s): "Login failed for user 'jpierce'." At line:18 char:5 +     $Connection.Open() +     ~~~~~~~~~~~~~~~~~~     + CategoryInfo          :... See more...
an error Exception calling "Open" with "0" argument(s): "Login failed for user 'jpierce'." At line:18 char:5 +     $Connection.Open() +     ~~~~~~~~~~~~~~~~~~     + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException     + FullyQualifiedErrorId : SqlException
HI Guys, i've searched for a PowerCLI SQL forum on here but can't find one. Please remove this it it's not the right forum but, i'm hoping someone on here may have tried this before. I'm tr... See more...
HI Guys, i've searched for a PowerCLI SQL forum on here but can't find one. Please remove this it it's not the right forum but, i'm hoping someone on here may have tried this before. I'm trying to connect to a SQL Database to verify some info before proceeding with an action. the account i'm using has access to the DB but, connection attempts are failing. here's what i'm trying [string]$servername="MyDBServer.corp.com" [string]$database="myDatabase" [string]$sqluser="myUsername.corp.com" [string]$sqlpassword="notMyPassword!" $dbConnection = New-Object System.Data.SQLClient.SQLConnection $dbConnection.ConnectionString = "server='$servername';database='$database';trusted_connection=true; user id = '$sqluser'; Password = '$sqlpassword'; integrated security='False'" $dbConnection.Open() Write-Verbose 'Connection established'
Thanks Luc, That was a great help. I added in a few more VM Properties and a progress bar. I needed to change some more variables but, it's working as expected now (but for one error that do... See more...
Thanks Luc, That was a great help. I added in a few more VM Properties and a progress bar. I needed to change some more variables but, it's working as expected now (but for one error that doesn't seem to impact the results) sometimes, i get an error about removing a PSDrive, but the script still works. the error is Remove-PSDrive : Cannot find drive. A drive with the name 'LogCollect-103617767' does not exist. At C:\Temp\Remove-VMs.ps1:140 char:9 +         Remove-PSDrive -Name $drvName -Confirm:$false | Out-Null +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     + CategoryInfo          : ObjectNotFound: (LogCollect-103617767:String) [Remove-PSDrive], DriveNotFoundException     + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.RemovePSDriveCommand The updated code is below <# .SYNOPSIS Retrieve the virtual machine logs to identify how long they are Powered down Query external DB to verify safe to delete VM .DESCRIPTION The function retrieves the logs from one or more virtual machines and stores them in a local folder Date of last Log entry is captured .NOTES Credits:  Luc Dekens #> Set-PowerCLIConfiguration -DefaultVIServerMode Single -InvalidCertificateAction Ignore -Scope Session -Confirm:$False | Out-Null function Install-PowerCLI {     If (!(Get-Module -Name VMware.VimAutomation.Cis.Core)) {         find-Module -Name VMware.VimAutomation.Cis.Core | Install-Module -Scope CurrentUser -Confirm:$false     } } function Login-VCSA {     Disconnect-VIServer * -Confirm:$False -WarningAction SilentlyContinue     $targetVC = Read-Host "Enter the FQDN of the vCenter you want to connect to"     Connect-VIServer $targetVC | Out-Null -ErrorAction SilentlyContinue     if($DefaultVIServer -eq $null) {         Write-Host -ForegroundColor Red "Error: You need to connect to your vSphere environment before running this. Please do so now and try again"         exit     } } # Create folder to store results function Create-Directory {     $Script:directory = $null     $Script:directory = Read-Host "Enter local directory to store results"     if ( !(Test-Path -LiteralPath $Script:directory)) {         try {             New-Item -Path $Script:directory -ItemType Directory -ErrorAction Stop | Out-Null         }         catch {             Write-Error -Message "Unable to create directory '$Script:directory'. Error was: $_" -ErrorAction Stop         }         Write-Host -ForegroundColor Green "Successfully created directory '$Script:directory'."         } else {             Write-Host -ForegroundColor Yellow "Directory '$Script:directory' already exists - not creating it again"         } } # Create text file that contains VM Names function Create-File {     $Script:file  = $null     $Script:file = $Script:directory + "\" + "vmList.txt"     if ( !(Test-Path -LiteralPath $Script:file -PathType Leaf)) {         Set-Content -Encoding UTF8 -LiteralPath $Script:file -Value ""         Write-Host -ForegroundColor Green "Successfully created '$Script:file'."     } else {         Write-Host -ForegroundColor Yellow "File '$Script:file' already exists - not creating it again"     }     Write-Host "Enter VM Names into the text file and save it. Opening File for you now."     start-sleep -Seconds 3     Invoke-Item $Script:file } # install ImportExcel module if not already installed and prepare layout #function global:Prepare-Excel { function script:Prepare-Excel {     If (!(Get-module -ListAvailable "ImportExcel")) {         Find-Module -Name ImportExcel | Install-Module -Scope CurrentUser     }     $cannotBeDeleted = New-ConditionalText -Text PoweredOn -BackgroundColor Yellow -ConditionalTextColor Red     $Script:excelHash = @{         Path = $Script:directory + "\DecomList-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".xlsx"         Show = $true;         AutoSize = $true;         AutoFilter = $true;         ConditionalText = $cannotBeDeleted         ShowPercent = $true;         HideSheet = "Sheet1";     } } function Get-CIStatus {     # Placeholder for when read-only access to CMDB is available     # $ciStatus = identify CI Status from Asset Management SQL DB } function Get-Details {     Start-Sleep -Seconds 5     Read-Host "When you have saved the text file, press ENTER to continue..."     $Script:decomReport = @()     $dir = $Script:directory     #$Script:dir = $Script:directory     $VMList = Get-VM (Get-Content $Script:file) | Sort-Object     $count = $VMList.count     $i = 1     foreach($vm in $VMList){         Write-Progress -Activity "Collecting details on provided VMs" -Status "Working on $vm" -PercentComplete (($i*100)/$count)         $ip = $vm.guest.IPAddress[0]         $powerState = $vm.PowerState         $memory = $vm.memoryGB         $hddSize = [math]::Round(((Get-HardDisk -VM $vm).CapacityGB | Measure-Object -Sum).Sum)         $vmProperty = [ordered] @{             'vCenter' = $global:DefaultVIServer.Name             'VM Name' = $vm.Name             'IP Address' = $ip             'PowerState' = $powerState             'Memory (GB)' = $memory             'Disk Capacity (GB)' = $hddSize         }         # If VM Powered off Get the vmware.log file for the VM         if ($powerState -eq "PoweredOff") {         $logPath = $vm.Extensiondata.Config.Files.LogDirectory         $dsName = $logPath.Split(']')[0].Trim('[')         $vmPath = $logPath.Split(']')[1].Trim(' ')         $ds = Get-Datastore -Name $dsName         $drvName = "LogCollect-" + (Get-Random)         New-PSDrive -Location $ds -Name $drvName -PSProvider VimDatastore -Root '\' | Out-Null             Copy-DatastoreItem -Item ($drvName + ":" + $vmPath + "vmware.log") -Destination ($dir + "\" + $vm.Name + "\") -Force:$true             #Copy-DatastoreItem -Item ($drvName + ":" + $vmPath + "vmware.log") -Destination ($Script:dir + "\" + $vm.Name + "\") -Force:$true             $lastLine = Get-Content ($dir + "\" + $vm.Name + "\" + "vmware.log") -Tail 1             #$lastLine = Get-Content ($Script:dir + "\" + $vm.Name + "\" + "vmware.log") -Tail 1             [datetime]$LastLogDate = $lastLine.Split("|")[0]             $vmProperty.Add("Date of last Log entry",$LastLogDate)             $vmProperty.Add("Can be deleted","If all criteria met")             $vmProperty.Add("Removed from Inventory",(Get-Date -Format yyyy-MMM-dd-HHmm))         }         else {             $vmProperty.Add("Date of last Log entry",$LastLogDate)             $vmProperty.Add("Can be deleted","NO")             $vmProperty.Add("Removed from Inventory","NO - Notify Decom Team - Not Powered Off")         }         Remove-PSDrive -Name $drvName -Confirm:$false | Out-Null         #$decomReport += New-Object -TypeName psobject -Property $vmProperty         $Script:decomReport += New-Object -TypeName psobject -Property $vmProperty         $i++     }     #$decomReport |     $Script:decomReport |         Sort-Object -Property 'VM Name' |          Export-Excel @Script:excelHash          #Export-Csv ($Script:directory + "\TempCSV.csv") -NoTypeInformation } function Remove-Decom {     # Placeholder to delete Decommissioned VM's once pre-req's are met     <#     if ($ciStatus -eq "Decommissioned") {}     #>     <#     # AND if (Has the VM been powered down for more than 30 days) {         $target = (Get-Date).AddDays(-30)         if ($LastLogDate -le $target) {             Write-Host -ForegroundColor Red "'$vm.Name' has neen powered for more than 30 days"         }         else {             Write-Host "$vm not powered down long enough, staying"         }     #>     # Delete VM From Inventory } Install-PowerCLI Login-VCSA Create-Directory Create-File Script:Prepare-Excel Get-CIStatus Get-Details
Thank you Luc, i'll give this a go when back in the office tomorrow. Regards, Jason
I found the following in this forum in the past, should hopefully work for you to backup the .vmx files foreach($Computer in $content){     $view = Get-View -ViewType VirtualMachine -Filter @... See more...
I found the following in this forum in the past, should hopefully work for you to backup the .vmx files foreach($Computer in $content){     $view = Get-View -ViewType VirtualMachine -Filter @{"Name"=$Computer.name}     $vmxfile = $view.Config.Files.VmPathName     $dsname = $vmxfile.split(" ")[0].TrimStart("[").TrimEnd("]")     $ds = Get-Datastore -Name $dsname     New-PSDrive -Name ds -PSProvider VimDatastore -Root '/' -Location $ds     Copy-DatastoreItem -Item "ds:\$($vmxfile.split(']')[1].TrimStart(' '))" -Destination $VmxBackupFolder      Remove-PSDrive -Name ds     } to get the vmdk sizes, try something like $report=@() foreach($Computer in $content){        $hdd = 1        $Computer | Get-HardDisk | foreach {             $GeneralProp.Add("HDD$($hdd) Name",$_.Name)             $GeneralProp.Add("HDD$($hdd) Datastore",$_.FileName.split(" ")[0].TrimStart("[").TrimEnd("]"))             $GeneralProp.Add("HDD$($hdd) Path",$_.FileName.split(" ")[1].TrimStart("[").TrimEnd("]"))             $GeneralProp.Add("HDD$($hdd) Capacity",$_.CapacityGb)             $dsname = $_.Filename.split(" ")[0].TrimStart("[").TrimEnd("]")             $DataStoreReport += $_ | Add-Member -MemberType NoteProperty -Name DatastoreName -Value $dsname -PassThru             $hdd++        } $report += New-Object -TypeName psobject -Property $GeneralProp }     $report |         Sort-Object -Property {($_ | Get-Member -MemberType NoteProperty).Count } -Descending |         Export-Csv $outputfile -NoTypeInformation
I'm trying to write something that 1) verifies a VM is powered off (for more that 30 days) 2) queries an external DB to make sure it's safe to delete the VM 3) output the results to a differe... See more...
I'm trying to write something that 1) verifies a VM is powered off (for more that 30 days) 2) queries an external DB to make sure it's safe to delete the VM 3) output the results to a different DB (don't have this DB yet so outputting to Excel for now) I found Luc Deken's "Get-VMLog" code and, it has formed the basis for what i'm trying to do. To keep the code understandable, I've broken it into various functions, i'm hoping this will also allow me add to it in time as needed. I'm having trouble with scoped of Variables as a result and, don't understand scopes well enough to correct the issues i'm having. any help would be appreciated. Here's what i've come up with so far <# .SYNOPSIS Retrieve the virtual machine logs to identify how long they are Powered down Query external DB to verify safe to delete VM .DESCRIPTION The function retrieves the logs from one or more virtual machines and stores them in a local folder Date of last Log entry is captured .NOTES Credits:  Luc Dekens #> Set-PowerCLIConfiguration -DefaultVIServerMode Single -InvalidCertificateAction Ignore -Scope Session -Confirm:$False function Install-PowerCLI {     If (!(Get-Module -Name VMware.VimAutomation.Cis.Core)) {         find-Module -Name VMware.VimAutomation.Cis.Core | Install-Module -Scope CurrentUser -Confirm:$false     } } function Login-VCSA {     Disconnect-VIServer * -Confirm:$False -ErrorAction SilentlyContinue | Out-Null     $targetVC = Read-Host "Enter the FQDN of the vCenter you want to connect to"     Connect-VIServer $targetVC | Out-Null -ErrorAction SilentlyContinue     if($DefaultVIServer -eq $null) {         Write-Host -ForegroundColor Red "Error: You need to connect to your vSphere environment before running this. Please do so now and try again"         exit     } } # Create folder to store results function Create-Directory {     $Global:directory = $null     $Global:directory = Read-Host "Enter local directory to store results"     if ( !(Test-Path -LiteralPath $directory)) {         try {             New-Item -Path $directory -ItemType Directory -ErrorAction Stop | Out-Null         }         catch {             Write-Error -Message "Unable to create directory '$directory'. Error was: $_" -ErrorAction Stop         }         Write-Host -ForegroundColor Green "Successfully created directory '$directory'."         } else {             Write-Host -ForegroundColor Yellow "Directory '$directory' already exists - not creating it again"         } } # Create text file that contains VM Names function Create-File {     $Global:file  = $null     $Global:file = $directory + "\" + "vmList.txt"     if ( !(Test-Path -LiteralPath $file -PathType Leaf)) {         Set-Content -Encoding UTF8 -LiteralPath $file -Value ""         Write-Host -ForegroundColor Green "Successfully created '$file'."     } else {         Write-Host -ForegroundColor Yellow "File '$file' already exists - not creating it again"     }     Write-Host "Enter VM Names into the text file and save it"     start-sleep -Seconds 3     ii $file } # install ImportExcel module if not already installed and prepare layout function global:Prepare-Excel {     If (!(Get-module -ListAvailable "ImportExcel")) {         Find-Module -Name ImportExcel | Install-Module -Scope CurrentUser     }     $ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks     $excelHash = @{         Path = $directory + "\DecomList-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".xlsx"         Show = $true;         AutoSize = $true;         AutoFilter = $true;         ConditionalText = $ContainsBlanks         ShowPercent = $true;         HideSheet = "Sheet1";     } } function Get-CIStatus {     # Placeholder for when read-only access to CMDB is available     # $ciStatus = identify CI Status from Asset Management SQL DB } function Get-Details {     Read-Host "When you have saved the text file, press ENTER to continue..."     $global:decomReport = @()     $global:dir = $directory     $VMList = get-vm (Get-Content $file)     foreach($vm in $VMList){         $powerState = $vm.PowerState         $vmProperty = [ordered] @{             'vCenter' = $global:DefaultVIServer.Name             'VM Name' = $vm.Name             'PowerState' = $powerState         }         # If VM Powered off Get the vmware.log file for the VM         if ($powerState -eq "PoweredOff") {         $logPath = $vm.Extensiondata.Config.Files.LogDirectory         $dsName = $logPath.Split(']')[0].Trim('[')         $vmPath = $logPath.Split(']')[1].Trim(' ')         $ds = Get-Datastore -Name $dsName         $drvName = "LogCollect-" + (Get-Random)         New-PSDrive -Location $ds -Name $drvName -PSProvider VimDatastore -Root '\' | Out-Null             Copy-DatastoreItem -Item ($drvName + ":" + $vmPath + "vmware.log") -Destination ($dir + "\" + $vm.Name + "\") -Force:$true             $lastLine = Get-Content ($dir + "\" + $vm.Name + "\" + "vmware.log") -Tail 1             [datetime]$LastLogDate = $lastLine.Split("|")[0]             $vmProperty.Add("Date of last Log entry",$LastLogDate)             $vmProperty.Add("Can be deleted","")             $vmProperty.Add("Removed from Inventory",(Get-Date -Format yyyy-MMM-dd-HHmm))         }         else {             $vmProperty.Add("Date of last Log entry",$LastLogDate)             $vmProperty.Add("Can be deleted","NO")             $vmProperty.Add("Removed from Inventory","NO - Notify Decom Team - Not Powered Off")         }                     Remove-PSDrive -Name $drvName -Confirm:$false         $decomReport += New-Object -TypeName psobject -Property $vmProperty     }     $decomReport |         Sort-Object -Property 'VM Name' |          Export-Excel @excelHash          #Export-Csv ($directory + "\TempCSV.csv") -NoTypeInformation } function Remove-Decom {     # Placeholder to delete Decommissioned VM's once pre-req's are met     <#     if ($ciStatus -eq "Decommissioned") {}     #>     <#     # AND if (Has the VM been powered down for more than 30 days) {         $target = (Get-Date).AddDays(-30)         if ($LastLogDate -le $target) {             Write-Host -ForegroundColor Red "'$vm.Name' has neen powered for more than 30 days"         }         else {             Write-Host "$vm not powered down long enough, staying"         }     #>     # Delete VM From Inventory } Install-PowerCLI Login-VCSA Create-Directory Create-File Prepare-Excel Get-CIStatus Get-Details
Try this, it's worked for me # Clear initial variables $vCenters = $null $vc = $null $logfolder = $null $outputfile = $null $srmDailyReport = $null # set location of output data $lo... See more...
Try this, it's worked for me # Clear initial variables $vCenters = $null $vc = $null $logfolder = $null $outputfile = $null $srmDailyReport = $null # set location of output data $logfolder = "C:\Temp\SRM_PGs" if (!(Test-Path -Path $logFolder)) {     New-Item -ItemType Directory -Path $logFolder } Set-Location -Path $logFolder $outputfile = (Get-Date -Format yyyy-MMM-dd-HHmm) + ".csv" $srmDailyReport=@() # Create array with vCenter Names, add/change vCenters as necessary [string[]] $vCenters = "vcsa1.comp.com", "vcsa2.comp.com" foreach ($vc in $vCenters) {                # Clear variables     $srmConnection = $null     $srmApi = $null     $protectionGroupInfo = $null     $protectionGroups = $null     $protectionGroup = $null     $protectedVms = $null     $associatedVms = $null     $vm = $null     $VmNeedsSrmConfig = $null     $RecoveryPlan = $null     $view = $null         Connect-VIServer $vc -username "comp\USERNAME" -password "notThisPassword!"     Connect-SrmServer -User "comp\USERNAME" -Password "notThisPassword!" -OutVariable srmConnection     $srmIP = $srmConnection.Name     $srmServerName = ([System.Net.dns]::GetHostEntry($srmIP)).HostName         $srmApi = $srmConnection.ExtensionData     $protectionGroups = $srmApi.Protection.ListProtectionGroups()         # Begin TEST BLOCK     # To run script on an individual Protection Group, uncomment two lines below (comment out line 72 if testing)     #$TestProtectionGroup = $protectionGroups | where {$_.GetInfo().Name -eq "Archer" }     #$TestProtectionGroup | where {$_.GetProtectionState() -ne "Shadowing" } | % {     # End TEST BLOCK         # If a Protection Group has a status of Shadowing, no data exists within this local SRM Server. Connect to alternate SRM Server and proceed     # If a Protection Group has a status of Recovered or Ready, proceed to collect local data     # Comment out the below line when testing using individual Protection Groups     $protectionGroups | where {$_.GetProtectionState() -ne "Shadowing" } | % {                     $protectionGroup = $_             $protectionGroupInfo = $protectionGroup.GetInfo()             $RecoveryPlan = $protectionGroup.ListRecoveryPlans()                         # If a Protection Group has a status of Recovered, update available fields         if ($protectionGroup.GetProtectionState() -eq "Recovered") {             $GeneralProp = [ordered]@{                 'Production Cluster'=""                 'Protection Group' = $protectionGroupInfo.Name                 'Recovery Plan Name' = $RecoveryPlan.GetInfo().Name                 'Needs SRM Config' = 'Reprotect Needed'             }             $srmDailyReport += New-Object -TypeName psobject -Property $GeneralProp         }         # If a Protection Group has a status of Ready, update available fields         else{                # To get all VM's in the Protected Datastore, this should be all VM's associated with Protection Group             $associatedVms = $protectionGroup.ListProtectedDatastores() | Get-VIObjectByVIView | Get-VM             # The following lists the virtual machines protected by a Protection Group             $protectedVms = $protectionGroup.ListProtectedVms()             # The result of the above call is an array of references to the virtual machines at the vSphere API             # To populate the data from the vSphere connection, call the UpdateViewData method on each virtual machine view object             $protectedVms | % { $_.Vm.UpdateViewData() }                                         foreach ($vm in $associatedVms) {                 $GeneralProp = [ordered]@{}                 $GeneralProp.Add('Production Cluster',$vm.VMHost.Parent.Name)                 $GeneralProp.Add('Protection Group',$protectionGroupInfo.Name)                 $GeneralProp.Add('Recovery Plan Name' , $RecoveryPlan.GetInfo().Name)                                   $VmNeedsSrmConfig = $protectedVms | where {$protectedVms.vm.name -eq $vm.Name}                 if ($VmNeedsSrmConfig.needsconfiguration){                     $GeneralProp.Add('Needs SRM Config','')                 }                 else{                     $GeneralProp.Add('Needs SRM Config','VM Needs Config')                 }                 $GeneralProp.Add('Vm Name' , $vm.name)                 $GeneralProp.Add('Guest O/S' , $vm.GuestId)                        $view = $vm | Get-View                     $vmxfile = $view.Config.Files.VmPathName                     $vmxLocation = $vmxfile.split(" ")[0].TrimStart("[").TrimEnd("]")                     $GeneralProp.Add(".vmx Location", $vmxLocation)                     $GeneralProp.Add("Tools Recommendation", $view.Guest.ToolsVersionStatus)                                $srmDailyReport += New-Object -TypeName psobject -Property $GeneralProp                } # close "foreach ($vm in $associatedVms)"         } # close else     } # close "$protectionGroups | where {$_.GetProtectionState() -ne "Shadowing" }"         Disconnect-VIServer -Server $vc -Confirm:$false -Force } # close "foreach ($vc in $vCenters)" # Create the .csv file $srmDailyReport |     Sort-Object -Property 'Protection Group', 'Vm Name' |     Export-Csv $outputfile -NoTypeInformation     Invoke-Item $outputfile
so i found my first mistake, using connect-CIServer instead of connect-cisServer now getting new errors, time to keep troubleshooting...
I've also tried foreach ($item in $Global:DefaultVIServers) {     Write-Host $item.name     Connect-CIServer -Server $item.name -User $vcsauser -Password $vcsapasswd    .... But i get... See more...
I've also tried foreach ($item in $Global:DefaultVIServers) {     Write-Host $item.name     Connect-CIServer -Server $item.name -User $vcsauser -Password $vcsapasswd    .... But i get the same error as before
First off, thanks to Brian Graf for creating the Backup-VCSAToFile function. I'm trying to create a script that will connect to multiple VCSA's in a single SSO domain and create a backup for e... See more...
First off, thanks to Brian Graf for creating the Backup-VCSAToFile function. I'm trying to create a script that will connect to multiple VCSA's in a single SSO domain and create a backup for each VCSA. If I declare a variable for one of the VCSA's, connect-cisserver to that variable, the script works and backups are created on an FTP Site as expected. that is Connect-CisServer -Server $vcsa -User $vcsauser -Password $vcsapasswd works I'm trying to connect to multiple VCSA's at one time (in the same SSO Domain) and connect to the CisServer for each with the following $cred = Get-Credential -Message "  ***********  Enter vCenter Credentials  ***********" $vCenters = @(     "vcsa1.mydomain.com"     "vcsa2.mydomain.com"     ) $selectedVC = $vCenters | Out-GridView -Title "  ***  vCenter Listing - Select required vCenter(s)  ***" -OutputMode Multiple Connect-VIServer -Server $selectedVC -Credential $cred -ErrorAction SilentlyContinue $vcsauser="Administrator@vsphere.local"    $vcsapasswd="Password123isbad" If (!(Get-Module -Name VMware.VimAutomation.Cis.Core)) {     find-Module -Name VMware.VimAutomation.Cis.Core | Install-Module -Scope CurrentUser -Confirm:$false     } Connect-CIServer -Server $global:DefaultVIServers -User $vcsauser -Password $vcsapasswd The above returns the following error Connect-CIServer : 16/04/2020 12:29:50    Connect-CIServer   No Cloud server was found on https://vcsa1.mydomain.com:443/api/.    At C:\Users\piercj2\Documents\SCRIPTS\Get-VCSABackup2.ps1:157 char:2 +  Connect-CIServer -Server $global:DefaultVIServers -User $vcsauser -P ... +  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo      : NotSpecified: (:) [Connect-CIServer], CIException + FullyQualifiedErrorId : Cloud_ConnectivityServiceImpl_ConnectCloudServer_ConnectError,VMware.VimAutomation.Cloud.Commands.Cmdlets.ConnectCIServer Connect-CIServer : 16/04/2020 12:29:51    Connect-CIServer   No Cloud server was found on https://vcsa2.mydomain.com:443/api/.    At C:\Users\piercj2\Documents\SCRIPTS\Get-VCSABackup2.ps1:157 char:2 +  Connect-CIServer -Server $global:DefaultVIServers -User $vcsauser -P ... +  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo      : NotSpecified: (:) [Connect-CIServer], CIException + FullyQualifiedErrorId : Cloud_ConnectivityServiceImpl_ConnectCloudServer_ConnectError,VMware.VimAutomation.Cloud.Commands.Cmdlets.ConnectCIServer Is there a way of connecting to more than one SDK Servers at a time or, is there a need to ? Thanks
<#         ===========================================         Created By:   Jason Pierce         Created on:   31/Jan/2020         Version:         3.0 (Final)         NOTE:           The $... See more...
<#         ===========================================         Created By:   Jason Pierce         Created on:   31/Jan/2020         Version:         3.0 (Final)         NOTE:           The $vCenters and $vmHostModelEolMapping variables need to be edited to include your environment details before running the script         =========================================== #> # login to vCenter(s) - use CTRL to select multiple vCenters $cred = Get-Credential -Message "  ***********  Enter vCenter Credentials  ***********" $vCenters = @(     "vc1.company.com"     "vc2.company.com"     "vc3.company.com"     "vc4.company.com"     "vc5.company.com"     ) $selectedVC = $vCenters | Out-GridView -Title "  ***  vCenter Listing - Select required vCenter(s)  ***" -OutputMode Multiple Connect-VIServer -Server $selectedVC -Credential $cred -ErrorAction SilentlyContinue # Server model to EOL date mappings, edit to add/correct dates $vmHostModelEolMapping = @{     # Cisco Servers     "B230-BASE-M2"      = "2020/Jun"     "C260-BASE-2646"    = "2020/Jun"     "UCSB-B200-M4"      = "2024/Feb"     "UCSC-BASE-M2-C460" = "2020/Apr"     # Dell Servers     "PowerEdge R630"    = "2018/May"     "PowerEdge R640"    = "No EOL Published"     "PowerEdge R710"    = "2016/May"     # VxRails     "VxRail E460"       = "2023/05"     "VxRail P570F"      = "No EOL Published"     } # Install the ImportExcel module if not already installed and prepare Excel layout@@ If (!(Get-module -ListAvailable "ImportExcel")) {     Find-Module -Name ImportExcel | Install-Module -Scope CurrentUser     } $ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks $hash = @{     Path = "C:\Temp\EOLreport.xlsx"     Show = $true;     AutoSize = $true;     AutoFilter = $true;     ConditionalText = $ContainsBlanks     ShowPercent = $true;     #HideSheet = "Sheet1";     } Remove-Item $hash.Path -ErrorAction Ignore # Collect ESXi Host details for EOL Report $vmHostAll = Get-VMHost $i = 1 $vmHostAll | ForEach-Object -PipelineVariable vmhost -Process {     Write-Progress -PercentComplete ($i / $vmHostAll.count * 100) -Activity "Generating Server End Of Life Report" -Status "Getting info on $_"     $i++     try {         $esxcli = Get-EsxCli -vmhost $_ -V2 -ErrorAction Stop         $platform = $esxcli.hardware.platform.get.invoke()         }     catch {         Write-Host -ForegroundColor red  "Get-EsxCli failed for $($_.Name)"         }     [pscustomobject] @{         vCenter          = [System.Net.Dns]::GetHostEntry((Get-View $_ -ErrorAction SilentlyContinue).summary.managementserverip).HostName         "ESXi Host Name" = $_.Name         Vendor           = $platform.VendorName         Model            = $platform.ProductName         Serial           = $platform.SerialNumber         EOL              = $vmHostModelEolMapping[$platform.ProductName] -replace "^$", 'Unknown'         } } | Sort-Object vCenter, "ESXi Host Name" | Export-Excel @hash
Thanks Luc, Running your last iteration of the code, i was still getting errors. Through a process of trial and error i spotted that the when using $vmhost variable,the following calls were fa... See more...
Thanks Luc, Running your last iteration of the code, i was still getting errors. Through a process of trial and error i spotted that the when using $vmhost variable,the following calls were failing Get-EsxCli was returning nothing Get-View was complaining about a null or empty argument Get-EsxCli failed for Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At line:138 char:69 + ... r          = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorA ... +                                                           ~~~~~~~     + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException     + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView I changed the code to the below (replacing the $vmhost with $_ in the "try" statement and in the [pscustomobject]) $vmHostAll = Get-VMHost $i = 1 $vmHostAll | ForEach-Object -PipelineVariable vmhost -Process {     Write-Progress -PercentComplete ($i / $vmHostAll.count * 100) -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost"     read-host "Press ENTER to Continue..."     $i++     try {         $esxcli = Get-EsxCli -vmhost $_ -V2 -ErrorAction Stop         $platform = $esxcli.hardware.platform.get.invoke()         }     catch {         Write-Host -ForegroundColor red  "Get-EsxCli failed for $($_.Name)"         }     [pscustomobject] @{         vCenter          = [System.Net.Dns]::GetHostEntry((Get-View $_ -ErrorAction SilentlyContinue).summary.managementserverip).HostName         "ESXi Host Name" = $_.Name         Vendor           = $platform.VendorName         Model            = $platform.ProductName         Serial           = $platform.SerialNumber         EOL              = $vmHostModelEolMapping[$platform.ProductName] -replace "^$", 'Unknown'         } } | Sort-Object vCenter, "ESXi Host Name" | Export-Excel @hash The output was now correct except for the Progress Bar, the Status was now reading "Getting info on @{vCenter=vc1.company.com; ESXi Host Name=Host1.company.com; Vendor=Dell; Model=Poweredge R910; Serial =123abc; EOL=2015/Mar/29}" I switched the Status from "Getting info on $vmHost" to "Getting info on $_", ran the code again and it worked 100% I haven't used pscustomobjects before so don't understand what's happening here but, wanted to post it in case it helps others. To keep this comment clean, i'm attaching the working code with your optimizations Thanks again !
Getting an error (and looks like i don't fully understand your optimizations) $vmHostAll = Get-VMHost = 1 | ForEach-Object -PipelineVariable vmhost -Process { Write-Progress -P... See more...
Getting an error (and looks like i don't fully understand your optimizations) $vmHostAll = Get-VMHost = 1 | ForEach-Object -PipelineVariable vmhost -Process { Write-Progress -PercentComplete ($i/$vmHostAll.count*100) -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost" $i++ try { $esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop $platform = $esxcli.hardware.platform.get.invoke() catch { Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)" the above returns Get-EsxCli failed for Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At line:135 char:69 + ... r          = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorA ... +                                                           ~~~~~~~     + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException     + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView
Thanks Luc, Those optimizations are great, really helpful. One question with them though. Previously i was using a count of the Hosts to generate a status bar # Status Bar Variables $vmH... See more...
Thanks Luc, Those optimizations are great, really helpful. One question with them though. Previously i was using a count of the Hosts to generate a status bar # Status Bar Variables $vmHosts = Get-VMHost $count = $vmHosts.count $i = 1 # Collect Server details $results = @() foreach ($vmHost in $vmHosts) {     Write-Progress -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost" -PercentComplete (($i*100)/$count) Using a pipeline variable, how do i now count the total Hosts ? Should i do something like $vmHosts = Get-VMHost $count = $vmHosts.count $i = 1 Get-VMHost -PipelineVariable $vmhosts | ForEach-Object -Process {
I've re-worked this to make it a bit more user friendly :smileygrin: The script can take a long time to run, depending on quantity of VC's and Hosts so i've also added a progress bar. If anyone... See more...
I've re-worked this to make it a bit more user friendly :smileygrin: The script can take a long time to run, depending on quantity of VC's and Hosts so i've also added a progress bar. If anyone thinks this can be optimized in any way, please feel free to post comments # login to vCenter(s) - use CTRL to select multiple vCenters $cred = Get-Credential -Message "  ***********  Enter vCenter Credentials  ***********" $vCenters = @(     "vc1.company.com"     "vc2.company.com"     "vc3.company.com"     "vc4.company.com"     "vc5.company.com"     ) $selectedVC = $vCenters | Out-GridView -Title "  ***  vCenter Listing - Select required vCenter(s)  ***" -OutputMode Multiple Connect-VIServer -Server $selectedVC -Credential $cred -ErrorAction SilentlyContinue # Server model to EOL date mappings, edit to add/correct dates $vmHostModelEolMapping = @{     # Cisco Servers     "B230-BASE-M2" = "2020/Jun"     "C260-BASE-2646" = "2020/Jun"     "UCSB-B200-M4" = "2024/Feb"     "UCSC-BASE-M2-C460" = "2020/Apr"     # Dell Servers     "PowerEdge R630" = "2018/May"     "PowerEdge R640" = " "     "PowerEdge R710" = "2016/May"     # VxRails     "VxRail E460" = "2023/05"     "VxRail P570F"= " "     } # Status Bar Variables $vmHosts = Get-VMHost $count = $vmHosts.count $i = 1 # Collect Server details $results = @() foreach ($vmHost in $vmHosts) {     Write-Progress -Activity "Generating Server End Of Life Report" -Status "Getting info on $vmHost" -PercentComplete (($i*100)/$count)     $vcName = [System.Net.Dns]::GetHostEntry((Get-View $vmHost -ErrorAction SilentlyContinue).summary.managementserverip).HostName     $vmHostName = $vmHost.Name     $EolDate = "Unknown"     $vmHostVendor = ''     $vmHostModel = ''     $vmHostSerial = ''     try {         $esxcli = $null         $esxcli = Get-EsxCli -vmhost $vmHost -V2 -ErrorAction Stop         $vmHostVendor = $esxcli.hardware.platform.get.invoke().VendorName         $vmHostModel = $esxcli.hardware.platform.get.invoke().ProductName         $vmHostSerial = $esxcli.hardware.platform.get.invoke().SerialNumber         if ($vmHostModelEolMapping.ContainsKey($vmHostModel)) {             $EolDate = $vmHostModelEolMapping[$vmHostModel]             }         }     catch {         Write-Host -ForegroundColor red  "Get-EsxCli failed for $($vmHost.Name)"         }     $prop = [pscustomobject] @{         vCenter          = $vcName         "ESXi Host Name" = $vmHostName         Vendor           = $vmHostVendor         Model            = $vmHostModel         Serial           = $vmHostSerial         EOL              = $EolDate         }         $i++     $results += $prop } <#     requirement: ImportExcel module     Verify that ImportExcel is installed with 'Get-Module -ListAvailable ImportExcel'     If not installed, install with 'Find-Module ImportExcel | Install-Module'     Get available commands with 'Get-Command -Module ImportExcel' #> If (!(Get-module -ListAvailable "ImportExcel")) {     Find-Module -Name ImportExcel | Install-Module     } $ContainsBlanks = New-ConditionalText -ConditionalType ContainsBlanks $hash = @{     Path = "C:\Temp\EOLreport.xlsx"     Show = $true;     AutoSize = $true;     AutoFilter = $true;     ConditionalText = $ContainsBlanks     ShowPercent = $true;     #PivotTableName = "ESXi Version Detail";     #IncludePivotTable = $true;     #PivotRows = 'Version';     #PivotData = @{'Version' = 'Count'};     #IncludePivotChart = $true;     #ChartType = "PieExploded";     HideSheet = "Sheet1";     } Remove-Item $hash.Path -ErrorAction Ignore $results | Sort-Object vCenter,"ESXi Host Name" | Export-Excel @hash