Code:
#import <ParallelsVirtualizationSDK/Parallels.h>
#import <ParallelsVirtualizationSDK/PrlApiMacro.h>
#import <ParallelsVirtualizationSDK/PrlApiCore.h>
#import <assert.h>
#import <iostream>
#import <libgen.h>
namespace
{
void CheckPrlResult(PRL_RESULT result)
{
if (result == PRL_ERR_SUCCESS)
return;
std::cout << "Error: " << prl_result_to_string(result) << std::endl;
assert(false);
}
PRL_RESULT WaitJobResult(PRL_HANDLE job, PRL_HANDLE_PTR jobResult)
{
CheckPrlResult(PrlJob_Wait(job, 60000));
CheckPrlResult(PrlJob_GetResult(job, jobResult));
PRL_RESULT jobResultCode;
CheckPrlResult(PrlJob_GetRetCode(job, &jobResultCode));
return jobResultCode;
}
std::string MachineStateToString(VIRTUAL_MACHINE_STATE state)
{
switch (state)
{
case VMS_UNKNOWN: return "Unknown";
case VMS_STOPPED: return "Stopped";
case VMS_STARTING: return "Starting";
case VMS_RESTORING: return "Restoring";
case VMS_RUNNING: return "Running";
case VMS_PAUSED: return "Paused";
case VMS_SUSPENDING: return "Suspending";
case VMS_STOPPING: return "Stopping";
case VMS_COMPACTING: return "Compacting";
case VMS_SUSPENDED: return "Suspended";
case VMS_SNAPSHOTING: return "Snapshoting";
case VMS_RESETTING: return "Resetting";
case VMS_PAUSING: return "Pausing";
case VMS_CONTINUING: return "Continuing";
case VMS_MIGRATING_OBSOLETE: return "Migrating";
case VMS_DELETING_STATE: return "Deleting";
case VMS_RESUMING: return "Resuming";
case VMS_SUSPENDING_SYNC: return "Suspending sync";
case VMS_RECONNECTING_OBSOLETE: return "Reconnecting";
case VMS_MOUNTED_OBSOLETE: return "Mounted";
}
}
}
int main(int argc, const char * argv[])
{
CheckPrlResult(PrlApi_InitEx(PARALLELS_API_VER_5, PAM_DESKTOP, 0, 0));
PRL_HANDLE server;
CheckPrlResult(PrlSrv_Create(&server));
auto loginJob = PrlSrv_LoginLocal(server, nullptr, 0, PSL_NORMAL_SECURITY);
PRL_HANDLE loginResult;
CheckPrlResult(WaitJobResult(loginJob, &loginResult));
PRL_HANDLE loginResultParam;
CheckPrlResult(PrlResult_GetParam(loginResult, &loginResultParam));
PRL_UINT32 bufSize = 0;
CheckPrlResult(PrlLoginResponse_GetProductVersion(loginResultParam, nullptr, &bufSize));
char version[bufSize];
CheckPrlResult(PrlLoginResponse_GetProductVersion(loginResultParam, version, &bufSize));
std::cout << "Version: " << version << std::endl;
PrlHandle_Free(loginResultParam);
PrlHandle_Free(loginResult);
PrlHandle_Free(loginJob);
PRL_HANDLE listJob = PrlSrv_GetBackupVmList(server, 0);
PRL_HANDLE listResult;
CheckPrlResult(WaitJobResult(listJob, &listResult));
PRL_UINT32 machineCount;
CheckPrlResult(PrlResult_GetParamsCount(listResult, &machineCount));
std::cout << "Machines: " << machineCount << std::endl;
for (PRL_UINT32 i = 0; i < machineCount; i++)
{
std::cout << "Getting machine..." << std::endl;
PRL_HANDLE machineHandle;
CheckPrlResult(PrlResult_GetParamByIndex(listResult, i, &machineHandle));
std::cout << "Getting backup info..." << std::endl;
PRL_HANDLE backupInfo;
CheckPrlResult(PrlBackup_GetInfo(machineHandle, &backupInfo));
std::cout << "Getting machine state..." << std::endl;
VIRTUAL_MACHINE_STATE machineState;
CheckPrlResult(PrlBackupInfo_GetState(backupInfo, &machineState));
std::cout << "Machine state: " << MachineStateToString(machineState) << std::endl;
if (machineState == VMS_RUNNING)
{
std::cout << "Setting up backup..." << std::endl;
PRL_HANDLE params;
CheckPrlResult(PrlBackup_GetParams(machineHandle, ¶ms));
CheckPrlResult(PrlBackupParam_SetChangeMonitoring(params, PRL_TRUE));
CheckPrlResult(PrlBackupParam_SetLevel(params, PBL_FULL));
PRL_UINT32 options = PBOPT_DISABLE_GUEST_FS_SUSPEND;
CheckPrlResult(PrlBackupParam_SetOptions(params, options));
CheckPrlResult(PrlBackup_SetParams(machineHandle, params));
std::cout << "Starting backup..." << std::endl;
PRL_HANDLE backupJob = PrlBackup_Begin(machineHandle, 0);
PRL_HANDLE backupJobResult;
CheckPrlResult(WaitJobResult(backupJob, &backupJobResult));
PrlHandle_Free(backupJobResult);
PrlHandle_Free(backupJob);
PRL_HANDLE fileList;
CheckPrlResult(PrlBackup_GetFilesList(machineHandle, &fileList));
PRL_UINT32 fileCount;
CheckPrlResult(PrlHndlList_GetItemsCount(fileList, &fileCount));
std::cout << "Files in backup: " << fileCount << std::endl;
for (PRL_UINT32 j = 0; j < fileCount; j++)
{
PRL_HANDLE file;
CheckPrlResult(PrlHndlList_GetItem(fileList, j, &file));
PRL_UINT32 filePathSize = 0;
CheckPrlResult(PrlBackupFile_GetPath(file, nullptr, &filePathSize));
char filePath[filePathSize];
CheckPrlResult(PrlBackupFile_GetPath(file, filePath, &filePathSize));
std::cout << filePath << std::endl;
PrlHandle_Free(file);
}
std::cout << "Rolling back..." << std::endl;
PRL_HANDLE rollbackJob = PrlBackup_Rollback(machineHandle, 0);
PRL_HANDLE rollbackJobResult;
CheckPrlResult(WaitJobResult(rollbackJob, &rollbackJobResult));
PrlHandle_Free(rollbackJobResult);
PrlHandle_Free(rollbackJob);
}
else
{
std::cout << "Skipping..." << std::endl;
}
PrlHandle_Free(backupInfo);
PrlHandle_Free(machineHandle);
}
PrlHandle_Free(listResult);
PrlHandle_Free(listJob);
PrlHandle_Free(server);
return 0;
}