I was recently asked to vet some VMware cluster capacity numbers. It seemed like a task that might be repeated in the future and I really hate to manually transcribe the data and compare them. So that means I need to write a script to automate it. Fortunately, VMware has vSphere PowerCLI for this job. Unfortunately, the documentation for it was rather sparse. I also looked at the book VMware vSphere PowerCLI Reference: Automating vSphere Administration, but really did not want to script in PowerShell simply because I'm not that familiar with PowerShell. However, PowerCLI is accessible from .NET also, so I can write my script in F#.
The following lines of script simply drills down from
object to the
VirtualMachine object. Once you grab all the objects,
you can explore the properties of each object.
#r @"C:\pkg\VMware\Infrastructure\vSphere PowerCLI\VMware.Vim.dll" open System open VMware.Vim open System.Collections.Specialized let serviceUrl = "https://myVSphereHost/sdk" let userId = "someUserId" let password="somePassword" let client = new VimClient() let service = client.Connect(serviceUrl) // Must login to do anything - if you are getting null values, it means the session automatically timed out client.Login(userId,password) // Let us get all the datacenters let dataCenters = client.FindEntityViews(typeof<Datacenter>,null,null,null) // Drill down into the first datacenter let dc = dataCenters |> Seq.cast<Datacenter> |> Seq.head // Get a cluster let cluster = client.GetView(dc.Parent,null) :?> ClusterComputeResource // Get the first host in the cluster let host = client.GetView(cluster.Host |> Seq.head,null) :?> HostSystem // Get the first VM on the physical host let vm = client.GetView(host.Vm |> Seq.head,null) :?> VirtualMachine
Let's do something interesting with PowerCLI. In the following scripts, I wanted to grab the capacity information at the VMware cluster level and the combine allocation/utilization info of all the virtual machines hosted on the VMware cluster.
// Utility function to help use get vSphere Entities let getEntityViews viewType searchParams = match searchParams with | Some(searchParams0) -> let filters = new NameValueCollection() searchParams0 |> Seq.iter (fun (k,v) -> filters.Add(k,v)) client.FindEntityViews(viewType,null,filters,null) | None -> client.FindEntityViews(viewType,null,null,null) // Get vSphere Entities with specific properties (reduces returned data) // Don't know how to define a function with multiple arities in F# - clumsy workaround let getEntityViews2 viewType searchParams props = match searchParams with | Some(searchParams0) -> let filters = new NameValueCollection() searchParams0 |> Seq.iter (fun (k,v) -> filters.Add(k,v)) client.FindEntityViews(viewType,null,filters,props) | None -> client.FindEntityViews(viewType,null,null,props) // Get Cluster usage summary! let getUsageSummary clusterName = let clusterProps = [|"Summary"; "Host"|] let hostProps = [|"Vm";"Name";"Hardware";"Runtime"|] let vmProps = [|"Name";"Config";"Runtime";"Summary";"ResourceConfig"|] let toMB memoryInBytes = memoryInBytes / (1024L*1024L) // Get cluster - Expect only one result printfn "Getting cluster data..." let cluster = let filters = Some([("name",clusterName)]) getEntityViews2 typeof<ClusterComputeResource> filters clusterProps |> Seq.cast<ClusterComputeResource> |> Seq.head // Get all Hosts for this cluster printfn "Getting host list..." let hostList = cluster.Host |> Seq.map(fun moRef -> client.GetView(moRef,hostProps)) |> Seq.cast<HostSystem> |> Seq.cache printfn "Getting VM list..." let vmList = hostList |> Seq.map (fun host -> host.Vm) |> Seq.concat |> Seq.map (fun moRef -> client.GetView(moRef,vmProps)) |> Seq.cast<VirtualMachine> |> Seq.cache let clusterCores = cluster.Summary.NumCpuCores let clusterCPU = cluster.Summary.TotalCpu let clusterMemory = cluster.Summary.TotalMemory // Utility function to get summation results from selected fields let inline total (extractor:VirtualMachine -> Nullable<'b>) = vmList |> Seq.map extractor |> Seq.map (fun x -> x.GetValueOrDefault()) |> Seq.sum printfn "Getting Cluster Summary Info..." let cpuUsed = total (fun vm -> vm.Summary.Config.NumCpu) let memoryUsed = total (fun vm -> vm.Summary.Config.MemorySizeMB) let cpuReserved = total (fun vm -> vm.Summary.Config.CpuReservation) let memoryReserved = total (fun vm -> vm.Summary.Config.MemoryReservation) let maxMemoryUsage = total (fun vm -> vm.Runtime.MaxMemoryUsage) let maxCpuUsage = total (fun vm -> vm.Runtime.MaxCpuUsage) let cpuReservation = total (fun vm -> vm.ResourceConfig.CpuAllocation.Reservation) let cpuLimit = total (fun vm -> vm.ResourceConfig.CpuAllocation.Limit) let memoryReservation = total (fun vm -> vm.ResourceConfig.MemoryAllocation.Reservation) let memoryLimit = total (fun vm -> vm.ResourceConfig.MemoryAllocation.Limit) printfn "Cluster Name : %s" clusterName printfn "Number of Hosts in Cluster : %i" (Seq.length hostList) printfn "Number of VMs in Cluster : %i" (Seq.length vmList) printfn "Cluster Total Cores : %i" clusterCores printfn "Cluster Total CPU (MHz) : %i" clusterCPU printfn "Cluster Total Memory : %i" clusterMemory printfn "Cluster Total Memory (MB) : %i" (toMB clusterMemory) printfn "CPU Used by VMs : %i" cpuUsed printfn "Memory Used by VMs : %i" memoryUsed printfn "CPU Reserved by VMs : %i" cpuReserved printfn "Memory Reserved by VMs : %i" memoryReserved printfn "Max Memory Usage by VMs : %i" maxMemoryUsage printfn "Max CPU Usage by VMs (MHz) : %i" maxCpuUsage printfn "Total Allocated CPU Reservations : %i" cpuReservation printfn "Total Allocated CPU Limits : %i" cpuLimit printfn "Total Allocated Memory Reservations : %i" memoryReservation printfn "Total Allocated Memory Limits : %i" memoryLimit printfn "Memory Used / Cluster Total Memory : %f" (double(memoryUsed) / double(toMB clusterMemory)) printfn "vCPU Allocated / Cluster Total Cores : %f" (float(cpuUsed) / float(clusterCores)) printfn "Done!" // Invoke getUsageSummary to get the summary info on my cluster getUsageSummary "MyTestCluster"
Number of Hosts in Cluster : 5 Number of VMs in Cluster : 10 Cluster Total Cores : 120 Cluster Total CPU (MHz) : 276000 Cluster Total Memory : 1374369136640 Cluster Total Memory (MB) : 1310700 CPU Used by VMs : 38 Memory Used by VMs : 253952 CPU Reserved by VMs : 0 Memory Reserved by VMs : 0 Max Memory Usage by VMs : 253952 Max CPU Usage by VMs (MHz) : 87400 Total Allocated CPU Reservations : 0 Total Allocated CPU Limits : -10 Total Allocated Memory Reservations : 0 Total Allocated Memory Limits : -10 Memory Used / Cluster Total Memory : 0.193753 vCPU Allocated / Cluster Total Cores : 0.316667
I wish VMware had PowerCLI class documentation similar to those for the .NET library hosted on MSDN. If VMware does have those documentation, I can't seem to find them. Lack of documentation has forced me to interactively explore the PowerCLI with F#. Thankfully, I can do this in F# and shudder at the thought of exploring PowerCLI in C#.