VMware documentation introduces you to the concept of the managed object and its handle, called a managed object reference (moRef). You might be tempted to get configuration and status information of managed objects using a piecemeal approach. This has the severe disadvantage of creating a lot of chatter over the server connection, so it is very slow. A mechanism has been created to provide status information efficiently: the
PropertyCollector, discussed in
PropertyCollector Data.
It is a characteristic of all managed objects that they have a moRef to the managed object that serves as the parent to the managed object. This parent
moRef allows you to reconstruct the object hierarchy exposed by the vSphere SDK. In general the hierarchy is a tree-like structure along the lines of:
A managed object reference (moRef) is actually a handle and not the managed object itself. While it is certain that a
moRef always contains a unique value, the unique value is only relative to the instance of vSphere to which you are connected. For example, if vCenter Server manages a cluster of ESXi hosts, each ESXi host maintains its own managed object reference namespace and the vCenter must maintain a managed object reference namespace representing all of its servers. So when an ESXi host is represented by a vCenter, the vCenter must ensure that the managed object references are unique. The vCenter accomplishes this by creating unique managed object reference names inside its own namespace, which differ from the names that ESXi uses for the same managed objects.
A vSphere instance (vCenter or ESXi) tries to keep the moRef for a virtual machine consistent across sessions, however consistency is not guaranteed. For example, unregistering and reregistering a virtual machine could result in a change to the
moRef for the virtual machine. Thus, it is a bad idea to store a
moRef and expect it to work correctly in future sessions, or with a different vCenter Server.
On one vCenter Server, the moRef uniquely identifies a virtual machine. If you need to track and inventory virtual machine backups across multiple vCenter Servers, you can use
moRef together with
instanceUuid. You can see the
instanceUuid at the following browser path:
For direct connections to ESXi, the host address and moRef uniquely identify a virtual machine. However this
moRef could be different from the one that vCenter Server returns, hence the fallback to
instanceUuid. The
instanceUuid was new in VMware vSphere 4.0. In previous releases, the fallback was to
Uuid.
The PropertyCollector is powerful but requires great attention to detail. Backup-related features of the
PropertyCollector are covered in
Low Level Backup Procedures of this document. The next section provides some background about
PropertyCollector.
The PropertyCollector requires two fairly complex arguments: the
PropertySpec and the
ObjectSpec. The
ObjectSpec contains instructions to the
PropertyCollector describing where to look for the desired data. Because configuration information in vSphere is organized like a directory tree, the
ObjectSpec must describe how to traverse the tree to obtain the desired information. The net result is a complex, nested, and recursive list of instructions. Fortunately, once you have determined the location of all the desired information, the
ObjectSpec needed to determine the layout of a vSphere object hierarchy can be a static unvarying object. See the code example in section
Understanding an ObjectSpec.
The PropertySpec is a list of desired property information. Formulating a list that includes all of the desired information can take some effort to compile, but once determined, this can be a static object also.
The data returned from the PropertyCollector is a container class called
PropertyFilterUpdate, which contains an
objectSet with an item-by-item list of changes to object properties. Every item in this container is identified with one of the following keys: enter (add), leave (delete), and modify. On the first data request, every data item is included, and “enter” is marked for every data item.
The PropertyCollector presents its results in what amounts to random order. Since all managed objects have a “parent” property, you can reconstruct the configuration hierarchy by building a tree in memory, using the
parent identification to organize. The root folder is identified as the only folder without a parent.
In the data returned from PropertyCollector, you can find most of the information that is useful for backup in the Virtual Machine managed object, including the following:
For more information about the Java APIs, read the first several chapters of the VMware vSphere Web Services SDK Programming Guide, and related pages of the Web-based
VMware vSphere API Reference Documentation. Both are available at
http://www.vmware.com/support/developer/vc-sdk. Examples in this chapter assume that you have set up the vSphere SDK as described in documentation.
The low-level procedure for creating a snapshot of a virtual machine is documented in the section Creating a Snapshot. Set the
quiesce flag True to make the file system quiescent, otherwise the snapshot might represent a transitional system state, with inconsistent data. Restoring such data might be destructive.
Another flag named memory allows you to include in the snapshot a dump of the powered on virtual machine's in-memory state. This is not needed for backup, so set this flag to False.
This feature, first available in vSphere 4, provides the foundation for incremental (or differential) backup of virtual disks. Your application can back up only changed data as indicated by the QueryChangedDiskAreas method. Virtual machines with virtual hardware version 7 and later support changed block tracking. These virtual machines contain
changeTrackingSupported in the
capability field of the
VirtualMachine managed object. See
Changed Block Tracking on Virtual Disks for details.
Associated with the snapshot you just created are “versions” of the virtual disks. To identify these disks, you obtain a moRef to the snapshot you just created. From this snapshot
moRef, you can extract the disk names and paths. How to do this is demonstrated in section
Backing Up a Virtual Disk.
To read the data in a virtual disk, it is necessary to use the VixDiskLib. This library isolates the programmer from the details of extracting data from a virtual disk and its redo logs. For example, when doing backup you call functions
VixDiskLib_Open() and
VixDiskLib_Read(), among others.
VixDiskLib allows access to disk data on sector boundaries only; the transfer size is some multiple of the disk sector size.
When accessing disks on ESXi hosts, VixDiskLib release 1.0 transferred virtual disk data over the network. Later
VixDiskLib releases contain API enhancements so you can request more efficient data paths, such as direct SAN access or HotAdding disks to a virtual backup appliance. These efficient data paths requires minor code changes, such as calling
VixDiskLib_ConnectEx() instead of plain connect.
The VixDiskLib API allows a backup application to perform a full backup of a virtual machine. The newer
VixMntapi library can extract information about a guest operating system from its virtual disks, so your backup application can determine the type of operating system that is involved. This allows mounting the volumes to device nodes, so your application can perform file-oriented backups and restores.
Run-state information is available from the PropertyCollector, and if you keep this information up-to-date, your application already knows the run-state of the virtual machine. To change the run-state you must have the
moRef of the virtual machine. Use this
moRef in a
PowerOnVM_Task call through the server connection. For virtual machine shutdown, call the
PowerOffVM_Task method.
Restoring disk data requires that you obtain the current names of virtual disks. This process is similar to the one described in Extract Backup Data from the Target Virtual Machine, except in this case you obtain this information directly from the virtual machine and not from a snapshot. The target for the saved disk data must be the actual disk name (including any sequence number) because the current incarnation of a virtual machine may be derived from one or more snapshots.
Restoring disk data requires use of VixDiskLib. The
VixDiskLib_Write() function opens the virtual disks so your program can write data.
VixDiskLib functions transfer data to even-sector boundaries only, and transfer length must be an even multiple of the sector size.
This process is similar to restoring the contents of virtual disks (Step 3 under
Restoring an Existing Virtual Machine to a Previous State) with the following exception: you must call the
VixDiskLib_WriteMetadata() function to write all the disk configuration key/value data into the virtual disk before restoring any backed-up data to the virtual disk. Then call
VixDiskLib_Write() to restore the virtual disk data, as described in
Step 3 above.
You can find the interfaces to accomplish this in the VixMntapi library associated with
VixDiskLib. The
VixMntapi library allows disks or volumes of a virtual machine to be mounted and examined as needed.
VixMntapi provides access at the file system level, whereas
VixDiskLib provides access at the sector level.
2
|
Call VixDiskLib_Open() to open all of these virtual disks. This gives you a number of VixDiskLib handles, which you should store in an array.
|
3
|
Call VixMntapi_OpenDiskSet() to create a VixDiskSetHandle, passing in the array of VixDiskLib handles that you created in step 2.
|
4
|
Pass VixDiskSetHandle as a parameter to VixMntapi_GetVolumeHandles() to obtain an array of VixVolumeHandle pointers to all volumes in the disk set.
|
5
|
Call VixMntapi_GetOsInfo() to determine what kind of operating system is involved, and decide where important pieces of information are to be found.
|
6
|
For important volumes, call VixMntapi_MountVolume() then VixMntapi_GetVolumeInfo(), which reveals how the volume is set up. (Unimportant volumes include swap partitions.)
|
Once you are done accessing files in a mounted volume, there are VixMntapi procedures for taking down the abstraction that you created. These calls are:
This leaves the VixDiskLib handles that you obtained in the beginning; you must dispose of them properly.