In this chapter, you will learn to:
Although the PowerCLI product has grown over the various releases, there still will come a time when you won’t find a cmdlet to do the task you have in mind. That’s when you have to start looking at the vSphere APIs. These APIs give you full access to all the vSphere management components. Working with the vSphere APIs might appear to be an obscure black art, but rest assured, once you find your way around, you will find them easy to use.
Now, why would a book on PowerCLI bother with the vSphere API? The answer is simple. With the help of the vSphere API, your scripts can go that extra mile. The PowerCLI cmdlets cover a large part of the functionality that’s available in a vSphere environment, but not everything. There are, for example, some properties that you cannot retrieve or change through the PowerCLI cmdlets. And that’s where the vSphere API comes in. Luckily, the PowerCLI developers realized from day one that it would be difficult to offer a product that could only do part of the job. That is why they provided access to the vSphere API through specialized cmdlets called Get-View
and Get-VIObject
.
This chapter will show you how to use the vSphere API to perform functions that would otherwise not be available to you.
The full name of this beast is the vSphere Web Services SDK, but most of the time we will refer to it as the vSphere SDK or even just the SDK. While the SDK is a collection of documents, Web Service Definition Language (WSDL) files, Java libraries, and sample code, we will most of the time refer to one specific document, the vSphere API Reference. This reference document provides all the information concerning the data structures that are available through the vSphere API. This section provides a short summary of how the vSphere Web Services are implemented and how you can use them from within your PowerCLI scripts.
The vSphere API is exposed as a web service that runs on vSphere servers. These servers can be the vCenter Server or a VMware vSphere Hypervisor server (formerly known as an ESXi server). In other words, you use the same API for the vCenter Server as for the ESXi server. So far, so good—as a theory. As you might have guessed, this rule doesn’t hold true in some cases. For example, to download a screenshot of a guest’s console you need to connect directly to the vSphere Hypervisor server. And to retrieve tasks and events information, you have to connect to the vCenter Server.
Because the API is exposed as a web service, it is language independent from a client perspective. The requests and responses that your application sends and receives from the vSphere servers use the XML format. The protocol that is used to send and receive these requests and responses is the Simple Object Access Protocol (SOAP). The underlying network protocol used is HTTPS but can be configured as HTTP. The object model that is used contains the three major types of objects listed in Table 18-1.
Table 18-1: vSphere API object model
Object type | Description |
Managed objects | These are server-side objects and represent a vSphere entity (host, guest, datastore, etc.) or a vSphere service (LicenseManager , PerformanceManager , etc.). |
Data objects | These contain information about the managed objects. They can contain: Managed object properties (number of vCPUs in a guest, mount information about an NFS datastore, etc.). Method parameters (for example, the HostVirtualNicSpec , which is a parameter object to the AddVirtualNic method).Return values (for example, the GetAlarm method returns an array of Alarm object references). |
Fault objects | These are objects that are returned when a method could not be executed correctly. They contain information about the error that has occurred. |
An important concept you should understand at this point is that you do not access these vSphere objects directly. The client, the PowerCLI session in our context, has a copy of these vSphere objects. These copies are called the .NET VIObjects, or .NET objects for short. These .NET objects are asynchronous copies of the vSphere objects. That means that when a property in one of the vSphere objects changes, that change will not appear automatically in the .NET object. It is up to the client to refresh its copy, the .NET object!
The vSphere API Reference can be quite intimidating at first view. But rest assured; it all clicks together nicely once you get the hang of it.
You access the vSphere API Reference with a web browser (Figure 18-1).
The layout of the vSphere API Reference has four distinct areas, as described in Table 18-2.
The Table of Contents (ToC) is logic itself if you understand the different object types that live in vSphere. (We described them in the section “Work with the vSphere SDK.”) The ToC includes a list of all the managed objects. As of this writing, there are more than 120 managed objects. Some of the entries in the ToC could in fact have been listed together. The enumerated types are just a special type of data object. An enumerated type is a data object with a specific set of predefined values. A good example is the DayOfWeek type, which, as you might have guessed, can only contain the names of the weekdays (Monday, Tuesday, and so on). There are more than 1,800 data objects and more than 290 enumeration types. You will also find a Fault Type entry in the ToC. Fault types are used to pass error information from the server to your application. There are more than 680 fault types.
Table 18-2: vSphere API Reference
Area | Description |
Table of Contents | Located on the left-hand pane, the Table of Contents shows the topics that are available in the reference. |
Index | The Index provides an alphabetical list of all the elements available under a subject selected in the Table of Contents. |
Search | The Search field allows you to specify the full or partial name of the element you are looking for. The results of the search are displayed in a pop-up list below the Search field. When there is more than one hit, you will be able to select a specific element with the help of the cursor keys and the Enter key. |
Content | The Content for a specific element is shown in the right-side frame of the browser. |
The following entries in the ToC are there to make your life as an API user a lot easier. Instead of wading through the vSphere objects, these entries (listed in Table 18-3) provide indexes to commonly used concepts in the vSphere objects.
Table 18-3: vSphere object concepts
Object concept | Description |
All Types | Lists all known object types (managed objects, data objects, enumeration types, and fault objects). There are more than 2,990 entries here. |
All Methods | Lists all methods available in the API. There are currently more than 720 available methods for you to call. |
All Properties | Lists all the properties and the object(s) where you can find the property. This is the longest list of them all, with more than 6,150 entries. |
All Enumerations | Lists all the possible values you can find in the enumerated types. There are more than 1,390 entries in this list. |
There are several ways to use the SDK Reference, and which you choose depends on what you are trying to find. To be truly proficient, you’ll need to acquire a lot of hands-on-experience. The next sections provide some use cases to get you started.
One common task is to set a host into Maintenance mode. Let’s look to see if there is a method that does this. Enter maintenance in the Quick Index field for the All Methods entry. Bingo, you have a winner (Figure 18-2)!
Just like PowerShell scripts, there is no single correct solution for a problem. You can arrive at the same result via the All Properties entry. Enter maintenance in the Quick Index field (Figure 18-3).
There is a property called inMaintenanceMode
that looks promising. Let’s investigate the data object that contains the property (Figure 18-4).
In the description of the property, you can see a link to EnterMaintenanceMode_Task
.
As you learned in Chapter 17, “Alarms,” you can set up alarms in the vCenter Server that will fire when a specific event occurs in your vSphere environment. As a result, the alarm will execute one or more actions. One type of action that is used often for monitoring is to fire an SNMP trap. This SNMP trap will be transmitted to a monitoring server where you can take appropriate action for the event that occurred.
But what if you’re pretty sure the event occurred and you never see the SNMP trap arriving at your monitoring server?
Now this is, perhaps, a question you would not expect to find an answer to in a section on the vSphere API Reference. We include it here to show you that the vSphere API Reference can also be useful even when you do not intend to use the API. All the events that can be created in a vSphere environment are documented under the Data Object Types entry. Let’s take a look. Type snmp in the Quick Index field (Figure 18-5).
Two of the entries that appear are obviously related to SNMP traps that are fired by an alarm. Since we want to find out what went wrong, we will have to look for the AlarmSnmpFailedEvent
. With the techniques you learned in Chapter 15, “Reporting and Auditing,” it is quite easy to use AlarmSnmpFailedEvent
as a filter after the Get-VIEvent
cmdlet. Doing so lets you investigate whether the problem is due to a failure of the vCenter Server to send out the SNMP trap.
When you want to collect statistical data on your thin provisioning, you should know which of many available metrics to use. The vSphere API Reference documents them well. First, select the PerformanceManager
object in the Managed Objects entry, and under the Performance Counters heading you will find the available performance counters (Figure 18-6).
Under the Storage Capacity category, select the Datastore / Virtual Machine entry. You can now see all the available metrics (Figure 18-7).
You can compile your report on thin provisioning based on the provisioned
and used
metrics. See Chapter 16, “Using Statistical Data,” for further details on working with metrics and statistical data.
In the vSphere client, you get a message when a vMotion operation is not possible. The Move-VM
cmdlet does not have this functionality. So, how does the vSphere client do this? Type migrate in the Quick Index field in the All Methods text box, as shown in Figure 18-8.
Notice the CheckMigrate_Task
. That looks promising; let’s take a look at the method (Figure 18-9).
Let’s take a closer look at the parameters this method requires. (On screen, optional parameters have a red asterisk behind their name.) Instead of passing an actual object, you can pass the $null
value.
The testType
parameter requires an array of strings with the names of the tests that should be executed. But where can you find the test names? For such questions, it’s always good to start with the enumeration types. Type test in the Quick Index field of the Enumerated Types entry (Figure 18-10).
That enumeration seems to hold the different tests you can use in the testType
property (Figure 18-11).
But wait. There was a second entry in the index query result. If you go to the ValidateMigrationTestType
enumeration (Figure 18-12), you will see that this is a deprecated type and that in API 4.0 you should use CheckTestType
. The small print is important in the vSphere API Reference!
Now that we’ve solved the mystery of the testType
parameter, let’s return our focus to the CheckMigrate_Task
method (see Figure 18-9). Attentive readers might have noticed that the CheckMigrate_Task
method apparently only handles vMotion. This seems to be confirmed by the reference to the MigrateVM_Task
method. But what about SVMotion?
In the first line of the parameters for the CheckMigrate_Task
method, you notice the _this
entry, which, in fact, points to the managed object on which the method is called, VirtualMachineProvisioningChecker
. When you go to the VirtualMachineProvisioningChecker
object (Figure 18-13), you can see that it provides several other methods. One is the CheckRelocate_Task
method (Figure 18-14). That method seems to be intended to test the feasibility of the RelocateVM_Task
—in other words, the SVMotion task.
Walking the SDK documentation might seem complex, but rest assured it all links nicely together and, after your first few scripts that use vSphere API, it will become a natural exercise.
As we explained in the beginning of this chapter, a managed object is a server-side object that represents a vSphere object or a vSphere service as they exist inside vSphere. These objects contain all the information vSphere needs to work with these entities. The information present in these objects includes properties (the data objects) or methods (functions you can execute). In your PowerCLI scripts, you cannot access these server-side objects directly. Your scripts will work, as we explained earlier, with an asynchronous copy of the server-side objects. These copies are generally referred to as .NET View objects.
A PowerCLI object, on the other hand, is an object that is returned by a PowerCLI cmdlet. This object is a selection of properties and methods as selected by the PowerCLI Development Team. It is not a 1-to-1 copy of the underlying vSphere object.
The naming convention for these two types of objects in the PowerCLI documentation is as follows:
Let’s look at some examples so that you can see the difference more clearly.
The Get-Datastore
cmdlet returns an object for each datastore that is known in the vSphere server your session is connected to. Take a look at the VIObject
that the cmdlet returns. The object is a derived type off the base DatastoreImpl
type. Most of the VIObject
s will have a type name that ends with Impl
. That allows a script to recognize where an object comes from. You’ll find yourself type-casting parameters on a function, but it also allows you to interpret the results returned by the GetType
method (Table 18-4).
$dsImpl = Get-Datastore -Name DS1
$dsImpl.GetType()
Table 18-4: Results returned by the GetType
method
Characteristic | Return value |
IsPublic | True |
IsSerial | False |
Name | NasDatastoreImpl |
BaseType | VMware.VimAutomation.ViCore.Impl.V1.DatastoreMan… |
Now, let’s use the Get-View
cmdlet to get the vSphere object. Notice that the object returned is a Datastore
type. This object is documented in the vSphere API Reference under the Managed Object Types. (You’ll remember that a VIObject only contains a subset of all the available properties. The subset is a selection made by the developers.)
$ds = Get-Datastore -Name DS1 | Get-View
$ds.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False Datastore VMware.Vim.ManagedEntity
As we said earlier, the VIObjects have a selection (defined by the PowerCLI Development Team) of properties and methods attached. You can use the Get-Member
method to view their selection. Let’s take a closer look at the properties and methods that are attached to the VIObject that represents a Datastore
:
$dsImpl | Get-Member
TypeName:
VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.NasDatastoreImpl
Name MemberType Definition
---- ---------- ----------
ConvertToVersion Method T VersionedObjectInterop.Conv...
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
IsConvertableTo Method bool VersionedObjectInterop.I...
LockUpdates Method void ExtensionData.LockUpdates()
ToString Method string ToString()
UnlockUpdates Method void ExtensionData.UnlockUpda...
Accessible Property bool Accessible {get;}
CapacityGB Property decimal CapacityGB {get;}
CapacityMB Property decimal CapacityMB {get;}
Client Property VMware.VimAutomation.ViCore.I...
CongestionThresholdMillisecond Property System.Nullable[int] Congesti...
Datacenter Property VMware.VimAutomation.ViCore.T...
DatacenterId Property string DatacenterId {get;}
DatastoreBrowserPath Property string DatastoreBrowserPath {...
ExtensionData Property System.Object ExtensionData {...
FreeSpaceGB Property decimal FreeSpaceGB {get;}
FreeSpaceMB Property decimal FreeSpaceMB {get;}
Id Property string Id {get;}
Name Property string Name {get;}
ParentFolder Property VMware.VimAutomation.ViCore.T...
ParentFolderId Property string ParentFolderId {get;}
RemoteHost Property string RemoteHost {get;}
RemotePath Property string RemotePath {get;}
State Property VMware.VimAutomation.ViCore.T...
StorageIOControlEnabled Property bool StorageIOControlEnabled ...
Type Property string Type {get;}
Uid Property string Uid {get;}
UserName Property string UserName {get;}
The vSphere objects typically have a lot more properties and methods attached to them, as the following closer look at a managed object that represents a Datastore
reveals:
$ds | Get-Member
TypeName: VMware.Vim.Datastore
Name MemberType Definition
---- ---------- ----------
DatastoreEnterMaintenanceMode Method VMware.Vim.StoragePlacemen...
DatastoreExitMaintenanceMode Method void DatastoreExitMaintena...
DatastoreExitMaintenanceMode_Task Method VMware.Vim.ManagedObjectRe...
Destroy Method void Destroy()
DestroyDatastore Method void DestroyDatastore()
Destroy_Task Method VMware.Vim.ManagedObjectRe...
Equals Method bool Equals(System.Object ...
GetAllEventsView Method VMware.Vim.EventHistoryCol...
GetAllTasksView Method VMware.Vim.TaskHistoryColl...
GetEntityOnlyEventsCollectorView Method VMware.Vim.EventHistoryCol...
GetEntityOnlyTasksCollectorView Method VMware.Vim.TaskHistoryColl...
GetEventCollectorView Method VMware.Vim.EventHistoryCol...
GetHashCode Method int GetHashCode()
GetTaskCollectorView Method VMware.Vim.TaskHistoryColl...
GetType Method type GetType()
RefreshDatastore Method void RefreshDatastore()
RefreshDatastoreStorageInfo Method void RefreshDatastoreStora...
Reload Method void Reload()
Rename Method void Rename(string newName)
RenameDatastore Method void RenameDatastore(strin...
Rename_Task Method VMware.Vim.ManagedObjectRe...
setCustomValue Method void setCustomValue(string...
SetViewData Method void SetViewData(VMware.Vi...
ToString Method string ToString()
UpdateViewData Method void UpdateViewData(Params...
UpdateVirtualMachineFiles Method VMware.Vim.UpdateVirtualMa...
UpdateVirtualMachineFiles_Task Method VMware.Vim.ManagedObjectRe...
WaitForTask Method System.Object WaitForTask(...
AlarmActionsEnabled Property bool AlarmActionsEnabled {...
AvailableField Property VMware.Vim.CustomFieldDef[...
Browser Property VMware.Vim.ManagedObjectRe...
Capability Property VMware.Vim.DatastoreCapabi...
Client Property VMware.Vim.VimClient Clien...
ConfigIssue Property VMware.Vim.Event[] ConfigI...
ConfigStatus Property VMware.Vim.ManagedEntitySt...
CustomValue Property VMware.Vim.CustomFieldValu...
DeclaredAlarmState Property VMware.Vim.AlarmState[] De...
DisabledMethod Property string[] DisabledMethod {g...
EffectiveRole Property int[] EffectiveRole {get;}
Host Property VMware.Vim.DatastoreHostMo...
Info Property VMware.Vim.DatastoreInfo I...
IormConfiguration Property VMware.Vim.StorageIORMInfo...
LinkedView Property VMware.Vim.Datastore_Linke...
MoRef Property VMware.Vim.ManagedObjectRe...
Name Property string Name {get;}
OverallStatus Property VMware.Vim.ManagedEntitySt...
Parent Property VMware.Vim.ManagedObjectRe...
Permission Property VMware.Vim.Permission[] Pe...
RecentTask Property VMware.Vim.ManagedObjectRe...
Summary Property VMware.Vim.DatastoreSummar...
Tag Property VMware.Vim.Tag[] Tag {get;}
TriggeredAlarmState Property VMware.Vim.AlarmState[] Tr...
Value Property VMware.Vim.CustomFieldValu...
Vm Property VMware.Vim.ManagedObjectRe...
All the properties in a managed object contain data objects. The data objects can be simple types—for example, the Name
property, which is a String
type—or they can be other data objects—like the AvailableField
property, which is a CustomFieldDef
type.
The methods in the managed objects are, simply said, functions you can invoke on these objects. For example, the RenameDatastore
method on the Datastore
managed object obviously renames a datastore. You can find all the details on this method in the vSphere API Reference if you select the Datastore
object in the Managed Object Types entry.
The documentation for each managed object follows a similar layout in the vSphere API Reference. First there is a section that lists the following:
The next section contains a description of the managed object. This is a must-read section if you are serious about working with managed objects. The description is followed by a tabular list of all the properties of the managed object and a list of all the methods available for the managed object. The API reference also includes a detailed description of all the methods.
If you look in the list of methods for the Datastore
object in the vSphere API Reference, you will notice that there are a number of methods that are marked as being inherited. Let’s take the inherited method called Rename
that exists in addition to the more specific RenameDatastore
method. Most managed objects are based on a parent class. Class inheritance ensures that common properties and methods can be defined for a parent class instead of for each of the managed objects.
In the case of the Datastore
object, you can see (Figure 18-15) that a Rename_
Task method was inherited from the ManagedEntity
object, which is itself also a managed object.
So what’s the deal here? We seem to have two different methods—one called DatastoreRename
and another called Rename_Task
. And both seem to be doing the same thing: renaming a datastore. The explanation for this can be found in the vSphere API Reference. The RenameDatastor
e method is marked as Deprecated, and it says that you should use the Rename_Task
method. This is obviously something that the vSphere API developers introduced with version 4.0 of the API. Historically most of the managed objects had their own rename method; in our example, that would be the RenameDatastore
method.
With API 4.0 it was apparently deemed wiser to use a unified renaming method, and so the developers created a Rename_Task
method on the ManagedEntity
object. Since most of the important managed objects are derived from this ManagedEntity
object, they all inherit this unified Rename_Task
method.
The following code uses the synchronous Rename
method from the Datastore
managed object. The prompt only comes back when the actual rename is finished. Don’t forget that the Rename
method is not a method that you will find in the vSphere API Reference. The method was added by the PowerCLI Development Team to the .NET Framework to give you a synchronous version of what an asynchronous method is.
[vSphere PowerCLI] C:> $ds.Rename("DS22")
[vSphere PowerCLI] C:>
Let’s verify that the rename was done correctly:
$ds.Name
DS1
It looks as if the method call didn’t work! Rest assured, the method call did work. You just have to remember that you’re using a client-side copy of the actual managed object that exists on the vSphere server.
One method of checking that the name change actually happened would be to get a fresh copy of the Datastore
managed object like this:
$ds = Get-Datastore -Name DS22 | Get-View
$ds.Name
DS22
Another method to verify that the rename of the datastore was done is to refresh part of the copy that you have. To do that, use the UpdateViewData
method that the PowerCLI Development Team added to most managed objects. The UpdateViewData
method allows you to refresh either the complete managed object or specific properties of the object. The ability to specify the properties you wish to refresh can be a significant time-saver if the property itself is a complex data object. It saves even more time if you need to refresh properties on thousands of managed object copies!
$ds.UpdateViewData("Name")
$ds.Name
DS22
The other major type of managed objects consists of the service managers. Service managers are special objects that provide services in the virtual environment. Some examples of such services are EventManager
, LicenseManager
, and PerfManager
.
To access the service managers, start from the ServiceInstance
managed object, which is the root object of the inventory. In the Content
property, you will find a MoRef for most of the service managers:
Get-View ServiceInstance
ServerClock : 4/28/2015 3:00:42 PM
Capability : VMware.Vim.Capability
Content : VMware.Vim.ServiceContent
MoRef : ServiceInstance-ServiceInstance
Client : VMware.Vim.VimClientImpl
Get-View ServiceInstance | Select -ExpandProperty Content
RootFolder : Folder-group-d1
PropertyCollector : PropertyCollector-propertyCollector
ViewManager : ViewManager-ViewManager
About : VMware.Vim.AboutInfo
Setting : OptionManager-VpxSettings
UserDirectory : UserDirectory-UserDirectory
SessionManager : SessionManager-SessionManager
AuthorizationManager : AuthorizationManager-AuthorizationManager
ServiceManager : ServiceManager-ServiceMgr
PerfManager : PerformanceManager-PerfMgr
ScheduledTaskManager : ScheduledTaskManager-ScheduledTaskManager
AlarmManager : AlarmManager-AlarmManager
EventManager : EventManager-EventManager
TaskManager : TaskManager-TaskManager
ExtensionManager : ExtensionManager-ExtensionManager
CustomizationSpecManager : CustomizationSpecManager-CustomizationSpec…
CustomFieldsManager : CustomFieldsManager-CustomFieldsManager
AccountManager :
DiagnosticManager : DiagnosticManager-DiagMgr
LicenseManager : LicenseManager-LicenseManager
SearchIndex : SearchIndex-SearchIndex
FileManager : FileManager-FileManager
DatastoreNamespaceManager : DatastoreNamespaceManager-DatastoreNamespa…
VirtualDiskManager : VirtualDiskManager-virtualDiskManager
VirtualizationManager :
SnmpSystem : HostSnmpSystem-SnmpSystem
VmProvisioningChecker : VirtualMachineProvisioningChecker-ProvChecker
VmCompatibilityChecker : VirtualMachineCompatibilityChecker-CompatC…
OvfManager : OvfManager-OvfManager
IpPoolManager : IpPoolManager-IpPoolManager
DvSwitchManager : DistributedVirtualSwitchManager-DVSManager
HostProfileManager : HostProfileManager-HostProfileManager
ClusterProfileManager : ClusterProfileManager-ClusterProfileManager
ComplianceManager : ProfileComplianceManager-MoComplianceManager
LocalizationManager : LocalizationManager-LocalizationManager
StorageResourceManager : StorageResourceManager-StorageResourceManager
GuestOperationsManager : GuestOperationsManager-guestOperationsManager
OverheadMemoryManager : OverheadMemoryManager-OverheadMemoryManger
CertificateManager : CertificateManager-certificateManager
IoFilterManager : IoFilterManager-IoFilterManager
LinkedView :
Now what is a MoRef? The acronym stands for managed object reference. A MoRef is a data object that is used as a kind of pointer or link to a managed object. You can use the Get-View
cmdlet to retrieve a copy of the managed object from the MoRef. All managed objects have a property called MoRef
, which points to the object itself.
The following code shows how to retrieve a service manager through a MoRef
pointer. First we use the predefined shortcut to get the ServiceInstance
data object with the Get-View
cmdlet. And then, as an example, we retrieve the data object that represents the AlarmManager
. This time we use the Get-View
cmdlet with the MoRef we retrieved from the ServiceInstance
, and the Config.AlarmManager
property.
$si = Get-View ServiceInstance
$si.Content.AlarmManager
Type Value
---- -----
AlarmManager AlarmManager
Get-View $si.Content.AlarmManager
DefaultExpression Description MoRef Client
----------------- ----------- ----- ------
{VMware.Vim.Stat.. VMware.Vim.Alarm.. AlarmManager-Ala.. VMwa...
When you have the service manager’s object, you can access all of its properties and call all its methods:
$alarmMgr = Get-View $si.Content.AlarmManager
$alarmMgr | Get-Member
TypeName: VMware.Vim.AlarmManager
Name MemberType Definition
---- ---------- ----------
AcknowledgeAlarm Method void AcknowledgeAlarm(VMware.Vim.Mana...
AreAlarmActionsEnabled Method bool AreAlarmActionsEnabled(VMware.Vi...
CreateAlarm Method VMware.Vim.ManagedObjectReference Cre...
EnableAlarmActions Method void EnableAlarmActions(VMware.Vim.Ma...
Equals Method bool Equals(System.Object obj)
GetAlarm Method VMware.Vim.ManagedObjectReference[] G...
GetAlarmState Method VMware.Vim.AlarmState[] GetAlarmState...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
SetViewData Method void SetViewData(VMware.Vim.ObjectCon...
ToString Method string ToString()
UpdateViewData Method void UpdateViewData(Params string[] p...
WaitForTask Method System.Object WaitForTask(VMware.Vim....
Client Property VMware.Vim.VimClient Client {get;}
DefaultExpression Property VMware.Vim.AlarmExpression[] DefaultE...
Description Property VMware.Vim.AlarmDescription Descripti...
MoRef Property VMware.Vim.ManagedObjectReference MoR...
This example with the AlarmManager
shows us that there is a method, called GetAlarm
. This GetAlarm
method will return an array of MoRef
s and each MoRef
points to an actual Alarm
managed object. We know this by examining the definition field for the GetAlarm
method. The format used in the default formatter shows the type retuned and the parameter overload for each method. Obtain more details by drilling into the object itself.
The GetAlarm
method has one parameter, where you can pass the MoRef
of a vSphere entity. A vSphere entity is a managed object, such as a host, a virtual machine, or a folder. When you call GetAlarm
this way, the method will return all alarms defined on that specific entity and all the entity’s child objects.
$alarmMgr.GetAlarm($null)
Type Value
---- -----
Alarm alarm-1
Alarm alarm-10
Alarm alarm-11
Alarm alarm-12
Alarm alarm-15
Alarm alarm-16
Alarm alarm-17
Alarm alarm-18
Alarm alarm-19
Alarm alarm-2
Alarm alarm-20
Alarm alarm-21
Alarm alarm-22
Alarm alarm-23
Alarm alarm-24
Alarm alarm-27
Alarm alarm-28
Alarm alarm-29
Alarm alarm-30
Alarm alarm-31
Alarm alarm-32
Alarm alarm-33
Alarm alarm-34
Alarm alarm-388
Alarm alarm-4
Alarm alarm-481
Alarm alarm-482
Alarm alarm-483
Alarm alarm-5
Alarm alarm-582
Alarm alarm-6
Alarm alarm-681
Alarm alarm-7
Alarm alarm-72
Alarm alarm-73
Alarm alarm-74
Alarm alarm-75
Alarm alarm-76
Alarm alarm-77
Alarm alarm-78
Alarm alarm-8
Alarm alarm-81
Alarm alarm-82
Alarm alarm-83
Alarm alarm-84
Alarm alarm-85
Alarm alarm-9
If you pass $null
to an entity instead of a MoRef
, the GetAlarm
method will return all of the alarms defined in your vSphere environment:
$cluster = Get-Cluster CLUS1
$alarmMgr.GetAlarm($cluster.ExtensionData.MoRef)
Type Value
---- -----
Alarm alarm-681
Notice how we used the ExtensionData
property to get to the MoRef
of the cluster. This avoids the use of the Get-View
cmdlet to get to the managed object that represents the cluster—a real time-saver if you need to run this in a somewhat bigger vSphere environment.
As we said earlier, the GetAlarm
method returns an array of MoRef
s to Alarm
objects. That means you have to use the Get-View
cmdlet to get a copy of the managed object that represents an Alarm
itself. The Get-View
cmdlet takes the MoRef
and returns the managed object. And again, once you have the managed object, you will have access to all its methods and properties, as shown by the output of the Get-Member
cmdlet:
$al = $alarmMgr.GetAlarm($cluster.ExtensionData.MoRef)
Get-View $al | Get-Member
TypeName: VMware.Vim.Alarm
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ReconfigureAlarm Method System.Void ReconfigureAlarm(VMwa...
RemoveAlarm Method System.Void RemoveAlarm()
setCustomValue Method System.Void setCustomValue(string...
SetViewData Method System.Void SetViewData(VMware.Vi...
ToString Method string ToString()
UpdateViewData Method System.Void UpdateViewData(Params...
WaitForTask Method System.Object WaitForTask(VMware....
AvailableField Property VMware.Vim.CustomFieldDef[] Avail…
Client Property VMware.Vim.VimClient Client {get;}
Info Property VMware.Vim.AlarmInfo Info {get;}
MoRef Property VMware.Vim.ManagedObjectReference…
Value Property VMware.Vim.CustomFieldValue[] Val…
Get-View $al
Info : VMware.Vim.AlarmInfo
Value : {}
AvailableField : {}
MoRef : Alarm-alarm-681
Client : VMware.Vim.VimClient
Get to know the available service managers. They will allow you to access the services that are available in the vSphere environment, and are key to automating some of the more critical core services in vSphere.
Most of the methods you encounter will need one or more parameters. These parameters are (most of the time) data objects of a specific type themselves. How do you create these data objects? Luckily the PowerCLI Development Team included all the vSphere object types in the PowerCLI binding. This allows you to use the constructor of these data objects, via the New-Object
cmdlet, to create an instance of a specific type.
On the New-Object
cmdlet, you pass the Typename
of the object you want to create. Do so by appending the Typename
to the VMware.Vim
instance:
$spec = New-Object -TypeName VMware.Vim.AlarmSpec
$spec | Get-Member
TypeName: VMware.Vim.AlarmSpec
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Action Property VMware.Vim.AlarmAction Action {get…
ActionFrequency Property System.Nullable`1[[System.Int32, m...
Description Property System.String Description {get;set;}
DynamicProperty Property VMware.Vim.DynamicProperty[] Dynam...
DynamicType Property System.String DynamicType {get;set;}
Enabled Property System.Boolean Enabled {get;set;}
Expression Property VMware.Vim.AlarmExpression Expressi…
Name Property System.String Name {get;set;}
Setting Property VMware.Vim.AlarmSetting Setting {g…
If a property of the data object is another data object, use the New-Object
cmdlet again to create this nested data object. Continue this way until all the required properties of the parameter object are present. (Consult the vSphere SDK Reference or investigate the error that the method will produce when there are properties missing or of the wrong type.)
$spec.Action = New-Object VMware.Vim.AlarmAction
Just like with a PowerShell script, you will find there is no single correct solution for determining the method you need to use. A lot depends on your experience with the vSphere environment, but an analytical mind and some experience with the vSphere API Reference can help you a lot.
In this section, you’ll see examples of using the vSphere API. Each example illustrates a specific aspect of using the vSphere API and shows how you can find the method or property you are looking for to do what you want to accomplish with your script.
To change the boot delay of a VM, it is clear you need to look at the VirtualMachine
managed object. But the Reference Guide has documented an enormous number of properties. Which one to use? In a case like this, it is easier to go to the All Properties entries and type a word that describes the property you’re looking for (for this example, we began entering bootdelay
) in the Quick Index field, as shown in Figure 18-16.
The first entry, bootDelay
(VirtualMachineBootOptions
), in the returned list looks promising. If you follow the link, you arrive at the VirtualMachineBootOptions
data object. In the Property Of section, you see that the bootDelay
data object is referenced in two other data objects: VirtualMachineConfigInfo
and VirtualMachineConfigSpec
. Now, you have a property that seems to do what you are looking for. If you follow a trail through the vSphere API Reference, you can find the method that will allow you to change that property. But which one to choose? In cases where you want to change something on a vSphere entity, it is always the data object that contains the Spec
suffix you need. The Info
suffix indicates that this is a data object that can be used to retrieve information from a vSphere entity. That brings you to inspecting the VirtualMachineConfigSpec
data object, where you can see that the object is used as a parameter in the ReconfigVM_Task
. Bringing everything you’ve learned thus far all together, you can use this small script to change the boot delay of a virtual machine:
$vmName = "PC1"
$delayMS = "5000" # Boot delay in milliseconds
$vm = Get-VM -Name $vmName
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.bootOptions = New-Object VMware.Vim.VirtualMachineBootOptions
$spec.bootOptions.bootDelay = $delayMS
$vm.Extensiondata.ReconfigVM_Task($spec)
Remember that we briefly discussed the New-Object
cmdlet and how you can use it to create it objects in the section “Code Parameter Objects.” You’ll learn more about the creation of data objects and their properties in Appendix: Example Reports.
To find the patches installed on an ESXi host, you can start from the Managed Object Types entry. Enter a common term like the word patch in the Quick Index field and you will see only an entry called HostPatchManager
in the results.
On the HostPatchManager
page, there is a method called QueryHostPatch_
Task in the Methods section. This method requires a single parameter, a data object of the HostPatchManagerPatchManagerOperationSpec
type. On the reference page for that object, you will find that all the properties are optional. Remember those red asterisks? They mean that no properties are required, which ultimately means that you can pass $null
as the parameter to the method, as we did here:
$esx = Get-VMHost esx1.test.local
$pmMoRef = $esx.ExtensionData.ConfigManager.PatchManager
$pm = Get-View $pmMoRef
$pm.QueryHostPatch()
Cannot find an overload for "QueryHostPatch" and the argument
count: "0".
At line:1 char:19
+ $pm.QueryHostPatch <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Notice that the method returned an error. You can’t leave out the parameter, even though you don’t pass any information. Whenever you want to pass an empty parameter, pass the $null
value. Let’s try again:
$pm.QueryHostPatch($null) | Format-List
Version : 1.40
Status :
XmlResult : <esxupdate-response>
<version>1.40</version>
</esxupdate-response>
Suppose you want to know how long the hardware hosting one of your ESX hosts has been powered on. If you enter uptime in the All Methods entry, you will find the RetrieveHardwareUptime
method. From the entry in the SDK Reference, you find out that the method is available on a HostSystem
managed object, that the method has no required parameters, and that the time is returned as the number of seconds. Using the method, calculating the HWuptime
is now rather straightforward:
$esx = Get-VMHost esx1.test.local
$esx.ExtensionData.RetrieveHardwareUptime()
301248
By now, you’re probably thinking that the SDK Reference is the ultimate resource, but not all information you will ever require while you’re working with vSphere is so readily available in the SDK Reference. Let’s look at another example.
In the Managed Object Types, you will find the OptionManager
, which is obviously what you would look for if you wanted to change vCenter Server options. But if you further investigate the UpdateOptions
method, you will find that the OptionValue
parameter is required. Now, here’s the problem: There seems to be no list of accepted values for the Key
and Value
fields.
A closer look at the OptionManager
object entry provides the solution. The OptionManager
object has two properties that hold the answer: the Setting
property and the SupportedOption
property. When you check those, you’ll find that the Setting
property holds all the Key-Value
pairs for current settings and the SupportedOption
property holds the accepted Key-Value
pairs. Let’s use Get-View
to see if you can find the information you need:
$si = Get-View ServiceInstance
$optMgr = Get-View $si.Content.Setting
$optMgr.SupportedOption | Where {$_.Key -like "*log*"} | fl Key, Label
Key : DBProc.Log.Level.Stats.Purge1
Label : Log level for daily stats purge
Key : DBProc.Log.Level.Stats.Purge2
Label : Log level for weekly stats purge
Key : DBProc.Log.Level.Stats.Purge3
Label : Log level for monthly and yearly stats purge
Key : DBProc.Log.Level.Stats.Rollup1
Label : Log level for daily stats rollup
Key : DBProc.Log.Level.Stats.Rollup2
Label : Log level for weekly stats rollup
Key : DBProc.Log.Level.Stats.Rollup3
Label : Log level for monthly stats rollup
Key : DBProc.Log.Level.Topn.Calc1
Label : Log level for topn rank of daily stats
Key : DBProc.Log.Level.Topn.Calc2
Label : Log level for topn rank of weekly stats
Key : DBProc.Log.Level.Topn.Calc3
Label : Log level for topn rank of monthly stats
Key : DBProc.Log.Level.Topn.Calc4
Label : Log level for topn rank of yearly stats
Key : DBProc.Log.Level.Topn.Purge1
Label : Log level for purge of daily topns
Key : DBProc.Log.Level.Topn.Purge2
Label : Log level for purge of weekly topns
Key : DBProc.Log.Level.Topn.Purge3
Label : Log level for purge of monthly topns
Key : DBProc.Log.Level.Topn.Purge4
Label : Log level for purge of yearly topns
Key : log.level
Label : Logging level
The last option returned seems to be the one you are after. Using the following code, you can now obtain the permitted values:
$ll = $optMgr.SupportedOption | here {$_.Key -like "log.level"}
$ll.OptionType.ChoiceInfo | ft -AutoSize
Key Label Summary
--- ----- -------
none None Disable logging
error Error Errors only
warning Warning Errors and warnings
info Information Normal logging
verbose Verbose Verbose
trivia Trivia Trivia
After you have retrieved the permitted values, you are ready to call the method. Here’s how we did it:
$opt = New-Object VMware.Vim.OptionValue
$opt.Key = "log.level"
$opt.Value = "verbose"
$optMgr.UpdateOptions($opt)
Earlier in the chapter, we introduced the Task
object. Task
managed objects allow you to verify the state of a particular task, check the result of that task, and determine whether any faults occurred. Let’s use the PatchManager
and see how this works:
$esx = Get-VMHost esx1.test.local
$pmMoRef = $esx.ExtensionData.ConfigManager.PatchManager
$pm = Get-View $pmMoRef
$taskMoRef = $pm.QueryHostPatch_Task($null)
Notice in the last code line that the method ends with the _Task
suffix; it is an asynchronous task and will return a MoRef to a Task
object. With the help of the Get-View
cmdlet, you can get a local copy of the Task
object. We used the following code:
$task = Get-View $taskMoRef
In the Task
object, you can find the current state of the task. The returned state can be queued
, running
, success
, or error
, as shown next:
$task.Info.State
success
In this case, the method call completed successfully. You can find more information about the results of the call to the method in the Task
object by using $task.Info.Result
:
$task.Info.Result
Version Status XmlResult
------- ------ ---------
1.40 <esxupdate-response>...
Now, let’s see what happens when an error occurs. In this example, we used a VMHost
profile and the API extension to check the current compliance status of a vSphere host. To do so, we leveraged the CheckProfileCompliance_Task
method on the VMHostProfile
object. This method does have a strongly typed parameter, but the parameter is calling for a MoRef
. (This is a common occurrence throughout the API;
the EVC mode configuration passes an invalid EVC mode.) Here’s the code we used:
$esx = Get-VMHost -Name esx1.test.local
$vm = Get-VM -Name VM001
$hProf = Get-VMHostProfile -Name Prod
# Mistake, pass the VM MoRef to the method
$taskMoRef = `
$hprof.ExtensionData.CheckProfileCompliance_Task($vm.ExtensionData.MoRef)
$task = Get-View -Id $taskMoRef
while($task.Info.State -eq [VMware.Vim.TaskInfoState]::running){
sleep 2
$task.UpdateViewData('Info')
}
You can see that we provoked a method failure by passing an incorrect parameter to the CheckProfileCompliance_Task
method.
$task = Get-View $taskMoRef
$task.Info.State
Error
As expected, the method returned an error. Let’s see what other information we can get using $task.Info.Error.Fault.GetType()
:
$task.Info.Error.Fault.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False InvalidType VMware.Vim.InvalidRequest
The information returned tells us that fault is an InvalidType
type, which is a kind of catchall fault. You can investigate further through the LocalizedMessage
and the Fault
properties. Here’s how we did that:
$task.Info.Error.LocalizedMessage
The request refers to an unexpected or unknown type.
$task.Info.Error.Fault
Argument FaultCause FaultMessage
-------- ---------- ------------
entity
As you can see, the faults that are returned are often cryptic. But, when you investigate the return code and display some of the Error
properties, it will become a lot clearer to the script users (yourself included) that something went wrong. In this instance, we supplied the MoRef for the incorrect Type of Managed Object
to the entity property of the method. A quick review would reveal our mistake and a simple update to pass in the vSphere host’s MoRef would result in a successful invocation.
The more you work with the vSphere API, the more you’ll find the same script elements appearing again and again. It is useful to keep these code snippets for easy reuse in your scripts. This section illustrates some of these general code snippets.
In your scripts you can construct a simple loop to wait for the completion of asynchronous tasks. The following script shows one way of doing this:
$taskMoRef = <any_call_to_an_asynchronous_method>
$task = Get-View $taskMoRef
while("running","queued" -contains $task.Info.State){
$task.UpdateViewData("Info")
Start-Sleep -Seconds 1
}
The script loops until the status of the task is no longer queued
(waiting to run) or running
. Since the script looks at a copy of the Task
object, we had to refresh the Task
object contents periodically. We used the UpdateViewData
method and specified that only the Info
property needed to be refreshed.
The ability of your scripts to intercept errors and produce meaningful error messages will improve their user friendliness. The following code snippet, which you can insert immediately after a wait loop, will check whether a call to an asynchronous method completed successfully. If the call to the method failed, the script displays an error message and then exits.
if($task.Info.State -eq "error"){
$task.UpdateViewData("Info.Error")
$task.Info.Error.Fault.faultMessage | % {
$_.Message
}
exit
}
As we mentioned earlier, the Get-View
cmdlet has shortcuts for several of the service managers that you would normally access via the ServiceInstance
object. But how can you find out which shortcuts are recognized by Get-View
? The following short function returns a list of the shortcuts you can use with Get-View
:
function Get-GVShortcut {
Write-Verbose -Verbose "Shortcuts supported by Get-View"
$si = Get-View ServiceInstance
$si.content | Get-Member -MemberType Property | Foreach-Object {
if($_.Name -match "Manager"){
$t = Get-View $_.Name -ErrorAction SilentlyContinue
if($t -ne $null){
Write-Output $_.Name
}
}
}
}
When writing scripts against truly massive environments, you may need to optimize your code by filtering the response server size, as well as pruning the properties returned. When these two techniques are paired with the UpdateViewData
method, you can minimize the amount of data being parsed by the system to the absolute bare minimum. This in turn will result in lower memory utilization and faster processing speed. However, be forewarned: When using PowerCLI in this manner, it is possible to overrun the vCenter Server by sending more requests and subsequent tasks than the web services can handle. It is inconveniently easy to DDOS vCenter with PowerCLI. You will find that in the long run this low-level micromanagement can lead to drastic improvements in performance. For example, consider the task of quickly counting all the Server 2008 VMs currently running in an environment.
# a simple one liner using the PowerCLI cmdlets
Measure-Command -Expression {
$vmsByVIObj = Get-VM |
Where {$_.Guest.GuestId -eq 'windows7Server64Guest'}
}
Days : 0
Hours : 0
Minutes : 0
Seconds : 13
Milliseconds : 527
Ticks : 135278784
TotalDays : 0.000156572666666667
TotalHours : 0.003757744
TotalMinutes : 0.22546464
TotalSeconds : 13.5278784
TotalMilliseconds : 13527.8784
# a direct query into the vSphere API for only the information requested
Measure-Command -Expression {
$vmsByView = Get-View -ViewType VirtualMachine `
-Filter @{'Guest.GuestId'='windows7Server64Guest'} -Property Name
}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 132
Ticks : 1328241
TotalDays : 1.53731597222222E-06
TotalHours : 3.68955833333333E-05
TotalMinutes : 0.002213735
TotalSeconds : 0.1328241
TotalMilliseconds : 132.8241
As you can see, the performance gains are dramatic. This isn’t due to any flaw in the cmdlets; it’s simply due to the fact that PowerShell is given less data to process. Pruning the data being returned to only the name of the VM benefits vCenter as well. It reduces the data that vCenter has to look up and return, and it physically lowers the impact all around. This doesn’t reduce your ability to perform more complex tasks, because any missing properties can be dynamically loaded in as needed with UpdateViewData
.
Finally, the -Filter
parameter accepts a simple hash table where the key is the name of the property and the value is the value. However, the Value field accepts a regular expression, meaning it is possible to create sophisticated queries. For example, to find all the VMs with either Windows 2008 or Ubuntu Linux and one or two vCPUs, use the following statement:
Get-View -ViewType VirtualMachine -Filter @{
'Guest.GuestId'='windows7Server64Guest|ubuntu64Guest'
'Config.Hardware.NumCPU'='[1-2]'
} -Property Name
In this instance, we’re searching for any object with the ViewType
of VirtualMachine
that matches either windows7Server64Guest
or ubuntu64Guest
in the GuestId
property with one or two vCPUs. As you can see, when you know exactly what you want it is rather easy to build an extremely performant and scalable script.