Difference between revisions of "Script Extracts and Examples (PowerCLI)"

Jump to navigation Jump to search
→‎Virtual Machine: Added "VM's Recently Created"
(→‎ESX Host: Added "Display ESX hosts that are HA Primaries")
(→‎Virtual Machine: Added "VM's Recently Created")
Line 689: Line 689:
Log("All completed")
Log("All completed")
Stop-Transcript
Stop-Transcript
</source>
==== VM's Recently Created ====
I run the following script twice a week (via a scheduled task), to generate a report of VM's recently created, as a catch-all reminder to check VM backup's, monitoring, etc etc have been set-up as required.  The number of days history it searches through can either be altered in the script (the <code>$days</code> parameter), or passed as a command line parameter when run as a scheduled task.
The script borrows heavily from http://get-admin.com/blog/how-to/vmware/powercli-get-every-vm-added-to-vcenter-in-the-last-30-days/, which is where the real genius of the script comes from.
I use a username and password file for credentials, see [[#Store_Password_Securely|Store Password Securely]] for more info, plus a CSV with a list of vCentres in (one column with a heading of "vc").
<source lang="Powershell">
$UserFile = "User.fil"
$PassFile = "Pass.fil"                          # Encrypted file to store password in
$VC_List = "ESX-Check.csv"
$EmailTo = "you@domain.com"
$days = 2
$NotFoundText = "Not found/gone?"
# Library funcs
function Log ($text) {
    [int]$duration = (New-TimeSpan $start (Get-Date)).TotalSeconds
    Write-Host "$duration secs | $text"
}
$start = Get-Date
Start-Transcript -Path VMs-Created.log -Append
Log("Started script at $start hrs")
if (!$args[0]) {
    Log "No argument passed, using default of VM's created in last $days days."
} else {
    $days = $args[0]
    Log "Checking for VM's created in last $days days."
}
# Load VMware PS Snapin
Log("Loading VMware PowerShell Snapin...")
Add-PsSnapin *VMware*
# Functions ===================================================================================================================================
function Get-Container ($objVM) {
    # Returns either the containing vApp or Folder
    if ($objVM.VApp) {
        Return $objVM.VApp.Name
    } else {
        Return $objVM.Folder.Name
    }
}
   
function Get-VMsCreated ([int]$LastDays) {
    # Modified from http://get-admin.com/blog/how-to/vmware/powercli-get-every-vm-added-to-vcenter-in-the-last-30-days/
    $EventFilterSpecByTime = New-Object VMware.Vim.EventFilterSpecByTime
    if ($LastDays) {
        $EventFilterSpecByTime.BeginTime = (get-date).AddDays(-$($LastDays))
        $EventFilterSpecByTime.EndTime = get-date
    }
    $EventFilterSpec = New-Object VMware.Vim.EventFilterSpec
    $EventFilterSpec.Time = $EventFilterSpecByTime
    $EventFilterSpec.DisableFullMessage = $False
    $EventFilterSpec.Type = "VmCreatedEvent","VmDeployedEvent","VmClonedEvent","VmDiscoveredEvent","VmRegisteredEvent"
    $EventManager = Get-View EventManager
    $NewVmTasks = $EventManager.QueryEvents($EventFilterSpec)
   
    $VMs = @()
    Foreach ($Task in $NewVmTasks)
    {
        # If VM was deployed from a template/cloned from VM then record which template/VM.
        If ($Task.Template -and ($Task.SrcTemplate.Vm)) {
            $srcMachine = (Get-View $Task.SrcTemplate.Vm -Property name).Name
        } elseif ($Task.SourceVm.Vm) {
            $srcVM = Get-VM -Id $Task.SourceVm.Vm
            $srcMachine = (Get-Container $srcVM) + "\" + $srcVM.Name
        } Else {
            $srcMachine = $null
        }
       
        # Create output
        $vmCreated = "" | Select VC_Name, VM_Path, VM_Name, Created, ByUser, Method, Source
        $vmCreated.VC_Name = $vc.vc
        try {
            $vmCreated.VM_Path = Get-Container (Get-VM -Id $Task.Vm.Vm -errorAction stop)
            if ($vmCreated.VM_Path -eq "vm") {
                $vmCreated.VM_Path = "(root)"
            }
           
        } catch {
            Log("VM not found " + $Task.Vm.name)
            $vmCreated.VM_Path = $NotFoundText
        }
           
        #$vmCreated.VM_Path = Get-Container (Get-VM -Id $Task.Vm.Vm)
        $vmCreated.VM_Name = $Task.Vm.name
        $vmCreated.Created = $Task.CreatedTime
        $vmCreated.ByUser = [regex]::Replace($Task.UserName, "MPADGLOBAL\\", "")
        $vmCreated.Method = $Task.gettype().name    # VmDeployedEvent - from template, VmClonedEvent - from existing VM, VmCreatedEvent - from scratch/Convertor import
        $vmCreated.Source = $srcMachine
        $VMs += $vmCreated
    }
   
    $VMs
}
# Business =================================================================================================================================
# Load list of VC's
try {
    $VCs = Import-CSV $VC_List
} catch {
    Log("ERROR: Failed to load list of vC's")
    Exit
}
# Load password credential from encrypted file
$pass = Get-Content $PassFile | ConvertTo-SecureString
$user = Get-Content $UserFile
$cred = New-Object System.Management.Automation.PsCredential($user, $pass)
# Disconnect any existing VI Server sessions (otherwise you can end up with duplicate VM's)
if ($DefaultVIServers.Count) {
    Log("Disconnect existing vCentre server connections...")
    Disconnect-VIServer -Server * -Force -Confirm:$false
}
$VMsCreated = @()
# Get VM's from each VC
foreach ($vc in $VCs) {
    #if ($vc.vc -eq "lab-manager") {
    #    Log("Skipping " + $vc.vc)
    #    Continue
    #}
    Log("Checking for VMs on " + $vc.vc)
    try {
        $VCconn = Connect-VIServer -Server $vc.vc -Credential $cred -errorAction stop
    } catch [VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidLogin] {
        Log("ERROR: Unable to connect to " + $vc.vc + ", invalid logon error !!")
        Log("Abandoning further script processing in order to prevent potential account lockout.")
        Exit
    } catch {
        Log("ERROR: Unable to connect to " + $vc.vc)
        Log($_)
        Continue
    }
   
    $VMsCreated += Get-VMsCreated $days
    Log("VMs created count now " + $VMsCreated.Length)
    Disconnect-VIServer -Server $VCconn -Confirm:$false
}
$VMsCreated
# Create HTML for email
[string]$msgHTML = "<!-- Genenerated by $ScriptName at " + (Get-Date).ToString() + " hrs -->`n"
$msgHTML += "<html xmlns='http://www.w3.org/TR/REC-html40'>`n`n<head>`n<meta http-equiv=Content-Type content='text/html; charset=uk'`n>"
$msgHTML += "<meta name=Generator content='VMs Recently Created script'>`n<meta name=Author content='Simon Strutt'>`n</head>`n`n"
$msgHTML += "<body style='font-family: arial; font-size: 12;'>`n"
$msgHTML += "The following VM's have been created in the last $days days (ie since " + ((Get-Date).AddDays(-$days)).ToString("HH:mm \h\r\s\, ddd dd-MMM-yyyy") + "),"
$msgHTML += " and backup jobs may need to be updated as a result.<br><br>`n"
if (!$VMsCreated.Length) {
    $msgHTML += "None !!"
} else {
    $msgHTML += "<table border=1 style='border-width: 1px; border-spacing: 1; border-color: black; background-color: #faf0e6; font-family: arial; font-size: 11;'>`n"
    $msgHTML += "<tr style='border-width: 2px; border-color: black; background-color: #fcf7f8;'><th>vCentre<th title='vApp or parent folder'>Container<th>VM<th>Created<th>By User<th>Method<th>Source`n"
    foreach ($vm in $VMsCreated) {
        if ($vm.Created) {
            $msgHTML += "<tr><td>" + $vm.VC_Name
            if ($vm.VM_Path -eq $NotFoundText) {
                $msgHTML += "<td>" + $vm.VM_Path + "<td>" + $vm.VM_Name
            } else {
                $msgHTML += "<td style='font-weight: bold;'>" + $vm.VM_Path + "<td style='font-weight: bold;'>" + $vm.VM_Name
            }
            $msgHTML += "<td style='text-align: right;'>" + ($vm.Created).ToString("HH:mm ddd dd-MM-yy") + "<td>" + $vm.ByUser + "<td>" + $vm.Method + "<td>" + $vm.Source + "`n"
        }
    }
    $msgHTML += "</table><br><br>`n"
    $msgHTML += "Generated by script: " + ($MyInvocation.MyCommand.Name) + "<br>`n"
    $msgHTML += "Sent from machine  : $env:computername</body></html>"
}
# Send email
$smtp = New-Object Net.Mail.SmtpClient -arg "mailrelay.uk.michaelpage.local"
$msg = New-Object Net.Mail.MailMessage
       
$msg.From = "VI-Mgmt@sandfordit.com"
$msg.To.Add($EmailTo)
$msg.Subject = "VMs created in last $days days"
$msg.IsBodyHTML = $true
$msg.Body = $msgHTML
 
$smtp.Send($msg)
Stop-transcript
</source>
</source>


Navigation menu