A Quick VMWare Server Vix Primer

A Quick VMWare Server Vix Primer

Excerpted from Professional VMWare Server

by Eric Hammersley

Brand new with the VMware Server release comes the Programming API, also known as Vix. The Vix API offers a decent amount of additional functionality over its older counterparts. Limiting it is the fact that you can only develop against it in C; this will make it difficult to adopt in some shops. The Vix API currently supports only VMware Server. This means you will not be able to leverage any existing virtual machines not residing on a VMware Server host in your shop with this API. Later releases of Vix may lift this limitation and open up to supporting more VMware platforms.

Because this API is so new, I highly advise you to review the release notes for the Programming API if you have trouble. The release notes for version 1.0, which I use here, are available at the following page.

Unlike the Perl and COM APIs, Vix is rather multilayered. There are several things that you must be aware of before you start poking and prodding your way through the first script. Though I’m not implying that poking and prodding is your normal method of coding, I nevertheless, want to cover some basics to help you fully understand how Vix works.

Handles

Those of you familiar with C will undoubtedly have heard of a handle. A handle is little more than a pseudo-pointer, if you will. Without getting into when and why you might use a handle over a simple pointer, I’ll just say the Vix API requires the use of handles of type VixHandle to reference almost all objects within the API.

The handles as they are used in Vix are more of what some might call a “magic cookie.” This isn’t some super secret programmer speak but a simple way of describing its use. The magic cookie gets passed around the code allowing you to uniquely identify and locate a specific object. In most cases this is done to mask operations performed against the handle, like any specific detail changes to the handle. This may be a difficult concept to grasp without specifics. The easiest generality to take away from this paragraph is that you need to use a handle to reference your objects in Vix. Take the following as a specific example:

VixHandle jobHandle = VIX_INVALID_HANDLE;
jobHandle = VixHost_Connect(
    VIX_API_VERSION,
    VIX_SERVICEPROVIDER_VMWARE_SERVER,
    NULL,                  // *hostName,
    0,                     // hostPort,
    NULL,                  // *userName,
    NULL,                  // *password,
    0,                     // options,
    VIX_INVALID_HANDLE,    // propertyListHandle,
    NULL,                  // *callbackProc,
    NULL);                 // *clientData);

The handle jobHandle in this case represents the object VixHost_Connect. Depending upon the type of object the handle represents, it will morph in a sense to certain properties and methods for that object. The actual content of the handle is nothing more than an integer. Internally Vix knows that the integer assigned to the handle refers to a specific object.

One last point on handles — every handle is reference counted. This means that when you created the VixHost_Connect object in the preceding code, the handle jobHandle received a reference count of 1. The importance of this is that because you have to manually release each and every handle you create, you must make sure the number of releases equals the reference count. A handle can be released by calling Vix_ReleaseHandle(<handle name>). Take the following as an example:

VixHandle handle1;
handle1 = Vix_Host_Connect( stuff goes here )
// The handle now represents the Vix_Host_Connect object
// The handle has a reference count of 1
// Implement code to utilize the handle
//Release the handle
Vix_ReleaseHandle(handle1);

With that in mind if you assign more than one handle to the same object, only the first handle maintains the reference count because the second one merely refers to the first one. If that seems confusing, try this as an example:

VixHandle handle1;
VixHandle handle2;
handle1 = Vix_Host_Connect( parameters to connect )
//handle1 has a reference count of 1
Handle2 = Vix_Host_Connect ( same parameters as above )
	//same host is connected
//handle2 has the same value as handle1 (It represents the same object)
//handle1's reference count is now at 2
//since there are two references to the
//object it represents.
// Handle2 doesn't have a reference count since technically
//it's the same as handle1.
//Now, to release the handles you actually
// have to do it twice, once for each //reference count
Vix_ReleaseHandle(handle1);
//At this point a valid handle still
// exists to the object so you can still use
//handle1.  Its reference count is now 1 again.
Vix_ReleaseHandle(handle1);
//Now the handle is gone.

Although this concept may seem a bit strange, it is an important concept to grasp. Any function that returns a handle can increase its reference count by one. Tracking this is important, as you will see in later examples.

Handle Types

There are four different types of handles that you will see throughout this article. Each handle type has a unique set of properties relating to the object they reference. Here’s a quick list of the different types of handles you will encounter.

VIX_HOST_HANDLE The host handle represents a host server running VMware Server. This kind of handle is commonly returned by the VixHost_Open() function.
VIX_JOB_HANDLE The job handle comes about during any asynchronous operation in Vix. Because almost all the functions in the API are asynchronous in nature, you will find the job handle in almost everything you do.
VIX_SNAPSHOT_HANDLE The snapshot handle is used to refer to a snapshot contained within a virtual machine. Currently the Vix API is very limited when it comes to snapshot handling.
VIX_VM_HANDLE The virtual machine handle is used to refer to a specific virtual machine. The VixVM_Open() function provides you with this type of handle.

Handle Properties

As you can probably deduce, a handle can refer to many different types of objects within Vix. For instance, when a virtual machine object is referenced by a handle, that handle contains specific properties relating to that type of object. These properties are typed name/value pairs that can be any of the following types:

  • 32-bit integer
  • 64-bit integer
  • String
  • Boolean
  • Handle

Handle properties are the way you modify and work with your object, regardless of their type. Their use ensures compatibility through any future version of the API. It’s simply a layer of abstraction that you are most likely already familiar with.

The tables in the following short sections list for you the properties available for each type of handle. Unfortunately at this stage of release for Vix the descriptions of each property are not defined so I cannot provide you with more specific information on each one. You will see a few of these properties used throughout the rest of this article and Chapter 10, “Working with the API,” of the book “Professional VMWare Server.(ISBN: 978-0-470-07988-1, Wrox, 2006) Several in the following lists, however, have yet to be defined.

Virtual Machine Properties

Property
VIX_PROPERTY_VM_NUM_VCPUS
VIX_PROPERTY_VM_VMX_PATHNAME
VIX_PROPERTY_VM_MEMORY_SIZE
VIX_PROPERTY_VM_POWER_STATE
VIX_PROPERTY_VM_TOOLS_STATE
VIX_PROPERTY_VM_IS_RUNNING

Event Info Property

This property is present only during the VixHost_FindItems() function call.

Property
VIX_PROPERTY_FOUND_ITEM_LOCATION

Job Properties

These properties are available with handles of type VIX_JOB_HANDLE.

Property
VIX_PROPERTY_JOB_RESULT_ERROR_CODE
VIX_PROPERTY_JOB_RESULT_VM_IN_GROUP
VIX_PROPERTY_JOB_RESULT_USER_MESSAGE
VIX_PROPERTY_JOB_RESULT_LINE_NUM
VIX_PROPERTY_JOB_RESULT_EXIT_CODE
VIX_PROPERTY_JOB_RESULT_COMMAND_OUTPUT
VIX_PROPERTY_JOB_RESULT_HANDLE

Snapshot Properties

These properties are available with handles of type VIX_SNAPSHOT_HANDLE.

Property
VIX_SNAPSHOT_DISPLAYNAME_PROPERTY
VIX_SNAPSHOT_DESCRIPTION_PROPERTY
VIX_SNAPSHOT_POWERSTATE_PROPERTY

The GetProperties() Function

Vix provides one function that allows you to retrieve properties from any handle. The GetProperties() function utilizes a varargs type signature that allows you to pass any number of arguments as long as you terminate the arguments with a special property, VIX_PROPERTY_NONE. Consider the following example:

VixError err;
VixHandle handle1;
int property1;
char* property2;
handle1 = <function that returns a handle>
err = Vix_GetProperties(handle1,
  FIRST_PROPERTY_NAME,
  &property1,
  SECOND_PROPERTY_NAME,
  &property2,
  VIX_PROPERTY_NONE);
Vix_ReleaseHandle(handle1);

Sure that’s a pretty generic example but the signature of the Vix_GetProperties() function is the important point here. You provide the handle followed by sets of name/value pairs and terminate it with the special VIX_PROPERTY_NONE property.

Error Codes

All Vix functions return an error code. The time in which it is returned is dependent upon the type of operation performed, synchronous or asynchronous. The error codes returned are of type VixError and are made up of a 64-bit value. If a function completes successfully, it returns an error code of VIX_OK, which is what you will find yourself checking for most often.

Now, the 64-bit error value that is returned comes with a bit of a catch. VIX_OK is the only error that you can check against the entire 64-bit value because it simply returns all zeros. All other errors only correspond to the least significant 16 bits of the error value, which are defined in a global type. In other words, the following code is valid:

VixError err;
err = VixJob_GetError(jobHandle);
if (VIX_OK == err) {
  // Success
}

This works because success is always all zeros. The least significant 16 bits do not need to be masked off from the rest of the code. That being said, the following is not valid:

VixError err;
err = VixJob_GetError(jobHandle);
if (VIX_E_INVALID_ARG == err) {
  // This doesn't work
}

Only success can be determined against the entire unmasked error code. So, you ask, how can you determine the error code if it’s not success? Well, you can either mask the error code yourself or use one of three built-in functions to do it for you:

  • First is VIX_ERROR_CODE(). This will mask the 64-bit value down to its least significant 16 bits for you. Using the preceding invalid bit of code let’s make it valid:
VixError err;
err = VixJob_GetError(jobHandle);
if (VIX_E_INVALID_ARG == VIX_ERROR_CODE(err)) {
  // Works!  Handle the error code here
}
  • Now instead of evaluating against the entire 64-bit error value you use VIX_ERROR_CODE() to chop off everything but the 16 least significant bits. If you want to perform the masking yourself try the following:
VixError err;
err = VixJob_GetError(jobHandle);
if (VIX_E_INVALID_ARG == (err & 0xFFFF)) {
  // Works!  Performs the same masking that VIX_ERROR_CODE() does
  // for you
}

Personally I prefer the built-in function; however, you can perform the masking manually if you wish.

  • Next is the VIX_SUCCEEDED() function. This function performs the masking automatically and returns a Boolean of true if the error code is VIX_OK. Basically it says (VIX_OK == err) for you. Take the following example:
VixError err;
err = VixJob_GetError(jobHandle);
if (VIX_SUCCEEDED(err)) {
  // Handle successful return here
}

It’s simple and perhaps a little cleaner and easier to read than the drawn out VIX_OK == err.

  • Finally there’s VIX_FAILED(). This function performs the bit masking and returns true if there is in fact an error. It’s basically (VIX_OK != err) when you get down to it. The following example shows its usage:
VixError err;
err = VixJob_GetError(jobHandle);
if (VIX_FAILED(err)) {
  // Handle failure here
  // If you need to test against a specific
  // failure this will not help you much.
}

One could argue their actual usefulness but I tend to use the built-in functions for evaluation when at all possible. That way if the error code structure is changed later I can be sure VIX_SUCCESS() and VIX_FAILED() will always work. If you peek inside the vix.h header file you’ll see that these are nothing more than built-in evaluations against VIX_OK. It’s nothing more than a shortcut.

There are numerous error values defined within the global type. I cover them in Appendix C, “Vix Error Codes,” in the book “Professional VMWare Server.(ISBN: 978-0-470-07988-1, Wrox, 2006).

More by Author

Must Read