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