Parallels Virtualization SDK
ContentsIndex
Example
PrlSrv_SubscribeToHostStatistics Function

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_HANDLE hServerStatistics;

            // 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;
            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;
            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.
// -------------------------------

int main(int argc, char* argv[])
{
    PRL_HANDLE hServer;
    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

    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.
    ret = PrlApi_Init(PARALLELS_API_VER);
    if (PRL_FAILED(ret))
    {
        fprintf(stderr, "PrlApi_Init returned with error: %s.\n",
            PRL_RESULT_TO_STRING(ret));
        PrlApi_Deinit();
        SdkWrap_Unload();
        return ret;
    }

    // Create a 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, // Server hostname 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

    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 machine statistics events.
    // 3. Keep receiving events until user presses <enter> key.
    // 4. Unsubscribe from 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;
}
© 2021 Parallels International GmbH. All rights reserved.