Previous page

Next page

Locate page in Contents

Performance Monitoring

To monitor the host or a virtual machine performance on a periodic basis, an event handler (callback function) is required. Within the event handler, first check the type of event. Events of type PET_DSP_EVT_HOST_STATISTICS_UPDATED indicate an event containing statistics data. To access the statistics handle (a handle of type PHT_SYSTEM_STATISTICS), first extract the event parameter using PrlEvent_GetParam, then convert the result (which will be a handle to an object of type PHT_EVENT_PARAMETER) to a handle using PrlEvtPrm_ToHandle. The functions that operate on PHT_SYSTEM_STATISTICS references can then be used to obtain statistics data.

For the event handler to be called, it is necessary to register it with PrlSrv_RegEventHandler. Before the event handler will receive statistics events, the application must subscribe to statistics events using PrlSrv_SubscribeToHostStatistics. When statistics data is no longer required, unsubscribe from statistics events using PrlSrv_UnsubscribeFromHostStatistics. When events are no longer required, unregister the event event handler using PrlSrv_UnregEventHandler.

The following is a complete example that demonstrates how to obtain statistics data asynchronously using PrlSrv_SubscribeToHostStatistics. Note that the same code could be used to receive statistics data for a virtual machine, instead of the host computer, by using PrlVm_SubscribeToGuestStatistics instead of PrlSrv_SubscribeToHostStatistics, and passing it a handle to a virtual machine that is running. This would also require using PrlVm_UnsubscribeFromGuestStatistics to stop receiving statistics data for the virtual machine.

#include "Parallels.h"

#include "Wrappers/SdkWrap/SdkWrap.h"

#include <stdio.h>

    

#ifdef _WIN_

#include <windows.h>

#else

#include <unistd.h>

#endif

    

const char *szServer = "123.123.123.123";

const char *szUsername = "Your Username";

const char *szPassword = "Your Password";

    

// -------------------------------------------------------------------------

// Event handler.

// -------------------------------------------------------------------------

// 1. Check for events of type PET_DSP_EVT_HOST_STATISTICS_UPDATES.

// 2. Display a header if first call to this event handler.

// 3. Get the event param (PHT_EVENT_PARAMETER) from the PHT_EVENT handle.

// 4. Convert event param to a handle (will be type PHT_SYSTEM_STATISTICS).

// 5. Use PHT_SYSTEM_STATISTICS handle to obtain CPU usage, memory usage,

//    and disk usage data.

// -------------------------------------------------------------------------

static PRL_RESULT OurCallback(PRL_HANDLE handle, void *pData)

{

    PRL_HANDLE_TYPE nHandleType;

    PRL_RESULT ret = PrlHandle_GetType(handle, &nHandleType);

    // Check for PrlHandle_GetType error here.

  

    if (nHandleType == PHT_EVENT)

    {

        PRL_EVENT_TYPE EventType;

        PrlEvent_GetType(handle, &EventType);

        

        // Check if the event type is a statistics update.

        if (EventType == PET_DSP_EVT_HOST_STATISTICS_UPDATED)

        {

            // Output a header if first call to this function.

            static PRL_BOOL bHeaderHasBeenPrinted = PRL_FALSE;

            if (!bHeaderHasBeenPrinted)

            {

                bHeaderHasBeenPrinted = PRL_TRUE;

                printf("CPU (%%) Used RAM (MB) Free RAM (MB) Used Disk Space (MB)"

                       " Free Disk Space (MB)\n");

                printf("---------------------------------------------------------"

                       "--------------------\n");

            }

              

            PRL_HANDLE hEventParameters = PRL_INVALID_HANDLE;

            PRL_HANDLE hServerStatistics = PRL_INVALID_HANDLE;

            // Get the event parameter (PHT_EVENT_PARAMETER) from the event handle.

            PrlEvent_GetParam(handle, 0, &hEventParameters);

            // Convert the event parameter to a handle (PHT_SYSTEM_STATISTICS).

            PrlEvtPrm_ToHandle(hEventParameters, &hServerStatistics);

            

            // Get CPU statistics (usage in %).

            PRL_HANDLE hCpuStatistics = PRL_INVALID_HANDLE;

            ret = PrlStat_GetCpuStat(hServerStatistics, 0, &hCpuStatistics);

            PRL_UINT32 nCpuUsage = 0;

            ret = PrlStatCpu_GetCpuUsage(hCpuStatistics, &nCpuUsage);

              

            // Get RAM statistics.

            PRL_UINT64 nUsedRam, nFreeRam;

            PrlStat_GetFreeRamSize(hServerStatistics, &nFreeRam);

            PrlStat_GetUsageRamSize(hServerStatistics, &nUsedRam);

            nUsedRam /= (1024 * 1024);

            nFreeRam /= (1024 * 1024);

                          

            // Get disk space statistics.

            PRL_UINT64 nFreeDiskSpace, nUsedDiskSpace;

            PRL_HANDLE hDiskStatistics = PRL_INVALID_HANDLE;

            PrlStat_GetDiskStat(hServerStatistics, 0, &hDiskStatistics);

            PrlStatDisk_GetFreeDiskSpace(hDiskStatistics, &nFreeDiskSpace);

            PrlStatDisk_GetUsageDiskSpace(hDiskStatistics, &nUsedDiskSpace);

            nUsedDiskSpace /= (1024 * 1024);

            nFreeDiskSpace /= (1024 * 1024);

            

            printf("%7d %10lld %13lld %20lld %20lld\n",

                nCpuUsage, nUsedRam, nFreeRam, nUsedDiskSpace, nFreeDiskSpace);

                  

            PrlHandle_Free(hDiskStatistics);

            PrlHandle_Free(hCpuStatistics);

            PrlHandle_Free(hServerStatistics);

            PrlHandle_Free(hEventParameters);

        }

    }

    

    PrlHandle_Free(handle);

    

    return PRL_ERR_SUCCESS;

}

    

    

// --------------------------------------------------------------------------

// Program entry point.

// --------------------------------------------------------------------------

// 1. Call SdkWrap_Load(SDK_LIB_NAME).

// 2. Call PrlApi_InitEx().

// 3. Create a PRL_SERVER handle using PrlSrv_Create.

// 4. Log in using PrlSrv_Login.

// 5. Register our event handler (OurCallback function).

// 6. Subscribe to host statistics events.

// 7. Keep receiving events until user presses <enter> key.

// 8. Unsubscribe from host statistics events.

// 9. Un-register our event handler.

// 10. Logoff using PrlSrv_Logoff.

// 11. Call PrlApi_Uninit.

// 12. Call SdkWrap_Unload.

// --------------------------------------------------------------------------

int main(int argc, char* argv[])

{

    PRL_HANDLE hServer = PRL_INVALID_HANDLE;

    PRL_RESULT ret;

    

    // Use the correct dynamic library depending on the platform.

    #ifdef _WIN_

    #define SDK_LIB_NAME "prl_sdk.dll"

    #elif defined(_LIN_)

    #define SDK_LIB_NAME "libprl_sdk.so"

    #elif defined(_MAC_)

    #define SDK_LIB_NAME "libprl_sdk.dylib"

    #endif

  

    // Try to load the SDK library, terminate on failure to do so.

    if (PRL_FAILED(SdkWrap_Load(SDK_LIB_NAME)) &&

        PRL_FAILED(SdkWrap_Load("./" SDK_LIB_NAME)))

    {

        fprintf(stderr, "Failed to load " SDK_LIB_NAME "\n");

        return -1;

    }

  

    // Initialize the Parallels API. In this example, we are initializing the

    // API for Parallels Server.

    // To initialize in the Parallels Desktop mode, pass PAM_DESKTOP

    // as the second parameter.

    // To initialize for Parallels Workstation, pass PAM_WORKSTATION.

    // See the PRL_APPLICATION_MODE enumeration for other options.

    ret = PrlApi_InitEx(PARALLELS_API_VER, PAM_SERVER, 0, 0);

    if (PRL_FAILED(ret))

    {

        fprintf(stderr, "PrlApi_InitEx returned with error: %s.\n",

            prl_result_to_string(ret));

        PrlApi_Deinit();

        SdkWrap_Unload();

        return ret;

    }

  

    // Create a PHP_SERVER handle.

    ret = PrlSrv_Create(&hServer);

    if (PRL_FAILED(ret))

    {

        fprintf(stderr, "PrlSvr_Create failed, error: %s",

            prl_result_to_string(ret));

        PrlHandle_Free(hServer);

        PrlApi_Deinit();

        SdkWrap_Unload();

        return -1;

    }

  

    // Log in (PrlSrv is asynchronous).

    PRL_HANDLE hJob = PrlSrv_Login(

            hServer,            // PRL_HANDLE of type PHT_SERVER.      

            szServer,           // Host name or IP address.

            szUsername,         // Username.

            szPassword,         // Password.

            0,                  // Deprecated - UUID of previous session.

            0,                  // Optional - port number (0 for default).

            0,                  // Optional - timeout value (0 for default).

            PSL_LOW_SECURITY);  // Security level (can be PSL_LOW_SECURITY,

                                   PSL_NORMAL_SECURITY, or PSL_HIGH_SECURITY).

  

    // Wait for a maximum of 10 seconds for

    // asynchronous function PrlSrv_Login to complete.

    ret = PrlJob_Wait(hJob, 1000);

    if (PRL_FAILED(ret))

    {

        fprintf(stderr, "PrlJob_Wait for PrlSrv_Login returned with error: %s\n",

            prl_result_to_string(ret));

        PrlHandle_Free(hJob);

        PrlHandle_Free(hServer);

        PrlApi_Deinit();

        SdkWrap_Unload();

        return -1;

    }

    

    // Analyze the result of PrlSrv_Login.

    PRL_RESULT nJobResult;

    ret = PrlJob_GetRetCode(hJob, &nJobResult);

    if (PRL_FAILED(nJobResult))

    {

        printf("Login job returned with error: %s\n",

            prl_result_to_string(nJobResult));

        PrlHandle_Free(hJob);

        PrlHandle_Free(hServer);

        PrlApi_Deinit();

        SdkWrap_Unload();

        return -1;

    }

    else

        printf("Login was successful.\n");

  

    // ----------------------------------------------------------------------------

    // 1. Register our event handler (OurCallback function).

    // 2. Subscribe to host statistics events.

    // 3. Keep receiving events until user presses <enter> key.

    // 4. Unsubscribe from host statistics events.

    // 5. Un-register out event handler.

    // ----------------------------------------------------------------------------

    

    PrlSrv_RegEventHandler(hServer, OurCallback, NULL);

    PrlSrv_SubscribeToHostStatistics(hServer);

    char c;

    scanf(&c, 1);

    PrlSrv_UnsubscribeFromHostStatistics(hServer);

    PrlSrv_UnregEventHandler(hServer, OurCallback, NULL);

    

    // ----------------------------------------------------------------------------

    

    // Log off.

    hJob = PrlSrv_Logoff(hServer);

    ret = PrlJob_Wait(hJob, 1000);

    if (PRL_FAILED(ret))

    {

        fprintf(stderr, "PrlJob_Wait for PrlSrv_Logoff returned error: %s\n",

            prl_result_to_string(ret));

        PrlHandle_Free(hJob);

        PrlHandle_Free(hServer);

        PrlApi_Deinit();

        SdkWrap_Unload();

        return -1;            

    }

    

    ret = PrlJob_GetRetCode(hJob, &nJobResult);

    if (PRL_FAILED(ret))

    {

        fprintf(stderr, "PrlJob_GetRetCode failed for PrlSrv_Logoff with error: %s\n",

            prl_result_to_string(ret));

        PrlHandle_Free(hJob);

        PrlHandle_Free(hServer);

        PrlApi_Deinit();

        SdkWrap_Unload();

        return -1;            

    }

    

    // Report success or failure of PrlSrv_Logoff.

    if (PRL_FAILED(nJobResult))

    {

        fprintf(stderr, "PrlSrv_Logoff failed with error: %s\n",

            prl_result_to_string(nJobResult));

        PrlHandle_Free(hJob);

        PrlHandle_Free(hServer);

        PrlApi_Deinit();

        SdkWrap_Unload();

        return -1;            

    }

    else

        printf("Logoff was successful.\n");

    

    // Free handles that are no longer required.

    PrlHandle_Free(hJob);

    PrlHandle_Free(hServer);

  

    // De-initialize the Parallels API, and unload the SDK.

    PrlApi_Deinit();

    SdkWrap_Unload();

    

    return 0;

}