mirror of https://github.com/BOINC/boinc.git
- VBOX: Handle both abort scenarios
samples/vboxwrapper/ vbox.cpp, .h vm.cpp, .h svn path=/trunk/boinc/; revision=23493
This commit is contained in:
parent
c410e94eca
commit
a32054a434
|
@ -2734,3 +2734,10 @@ Charlie 1 May 2011
|
|||
|
||||
lib/
|
||||
cc_config.cpp
|
||||
|
||||
Rom 3 May 2011
|
||||
- VBOX: Handle both abort scenarios
|
||||
|
||||
samples/vboxwrapper/
|
||||
vbox.cpp, .h
|
||||
vm.cpp, .h
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
@ -31,6 +32,8 @@
|
|||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define popen _popen
|
||||
#define pclose _pclose
|
||||
#define getcwd _getcwd
|
||||
#define putenv _putenv
|
||||
#endif
|
||||
|
||||
#include "diagnostics.h"
|
||||
|
@ -86,12 +89,7 @@ int virtualbox_vbm_popen(std::string& arguments, std::string& output) {
|
|||
int virtualbox_generate_vm_root_dir( std::string& dir ) {
|
||||
char root_dir[256];
|
||||
|
||||
#ifdef _WIN32
|
||||
_getcwd(root_dir, (sizeof(root_dir)*sizeof(TCHAR)));
|
||||
#else
|
||||
getcwd(root_dir, (sizeof(root_dir)*sizeof(TCHAR)));
|
||||
#endif
|
||||
|
||||
getcwd(root_dir, (sizeof(root_dir)*sizeof(char)));
|
||||
dir = root_dir;
|
||||
|
||||
if (!dir.empty()) {
|
||||
|
@ -127,48 +125,6 @@ int virtualbox_generate_vm_name( std::string& name ) {
|
|||
}
|
||||
|
||||
|
||||
// Generate a deterministic yet unique UUID for a given medium (hard drive,
|
||||
// cd drive, hard drive image)
|
||||
// Rules:
|
||||
// 1. Must be unique
|
||||
// 2. Must identifity itself as being part of BOINC
|
||||
// 3. Must be based on the slot directory id
|
||||
// 4. Must be in the form of a GUID
|
||||
// 00000000-0000-0000-0000-000000000000
|
||||
//
|
||||
// Form/Meaning
|
||||
// A B C D E
|
||||
// 00000000-0000-0000-0000-000000000000
|
||||
//
|
||||
// A = Drive ID
|
||||
// B = Slot ID
|
||||
// C = Standalone Flag
|
||||
// D = Reserved
|
||||
// E = 'BOINC' ASCII converted to Hex
|
||||
//
|
||||
int virtualbox_generate_medium_uuid( int drive_id, std::string& uuid ) {
|
||||
APP_INIT_DATA aid;
|
||||
char medium_uuid[256];
|
||||
|
||||
boinc_get_init_data_p( &aid );
|
||||
|
||||
sprintf(
|
||||
medium_uuid,
|
||||
_T("%08d-%04d-%04d-0000-00424F494E43"),
|
||||
drive_id,
|
||||
aid.slot,
|
||||
boinc_is_standalone()
|
||||
);
|
||||
|
||||
uuid = medium_uuid;
|
||||
|
||||
if (!uuid.empty()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool virtualbox_vm_is_registered() {
|
||||
std::string command;
|
||||
std::string output;
|
||||
|
@ -186,13 +142,14 @@ bool virtualbox_vm_is_registered() {
|
|||
}
|
||||
|
||||
|
||||
bool virtualbox_vm_is_hdd_uuid_registered() {
|
||||
bool virtualbox_vm_is_hdd_registered() {
|
||||
std::string command;
|
||||
std::string output;
|
||||
std::string virtual_hdd_uuid;
|
||||
std::string virtual_machine_root_dir;
|
||||
|
||||
virtualbox_generate_medium_uuid(0, virtual_hdd_uuid);
|
||||
command = "showhdinfo " + virtual_hdd_uuid;
|
||||
virtualbox_generate_vm_root_dir(virtual_machine_root_dir);
|
||||
|
||||
command = "showhdinfo \"" + virtual_machine_root_dir + "/" + vm.vm_disk_image_name + "\" ";
|
||||
|
||||
if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) {
|
||||
if (output.find("VBOX_E_FILE_ERROR") != std::string::npos) {
|
||||
|
@ -220,8 +177,91 @@ bool virtualbox_vm_is_running() {
|
|||
return false;
|
||||
}
|
||||
|
||||
int virtualbox_get_install_directory( std::string& virtualbox_install_directory ) {
|
||||
#ifdef _WIN32
|
||||
LONG lReturnValue;
|
||||
HKEY hkSetupHive;
|
||||
LPTSTR lpszRegistryValue = NULL;
|
||||
DWORD dwSize = 0;
|
||||
|
||||
// change the current directory to the boinc data directory if it exists
|
||||
lReturnValue = RegOpenKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
_T("SOFTWARE\\Oracle\\VirtualBox"),
|
||||
0,
|
||||
KEY_READ,
|
||||
&hkSetupHive
|
||||
);
|
||||
if (lReturnValue == ERROR_SUCCESS) {
|
||||
// How large does our buffer need to be?
|
||||
lReturnValue = RegQueryValueEx(
|
||||
hkSetupHive,
|
||||
_T("InstallDir"),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&dwSize
|
||||
);
|
||||
if (lReturnValue != ERROR_FILE_NOT_FOUND) {
|
||||
// Allocate the buffer space.
|
||||
lpszRegistryValue = (LPTSTR) malloc(dwSize);
|
||||
(*lpszRegistryValue) = NULL;
|
||||
|
||||
// Now get the data
|
||||
lReturnValue = RegQueryValueEx(
|
||||
hkSetupHive,
|
||||
_T("InstallDir"),
|
||||
NULL,
|
||||
NULL,
|
||||
(LPBYTE)lpszRegistryValue,
|
||||
&dwSize
|
||||
);
|
||||
|
||||
virtualbox_install_directory = lpszRegistryValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (hkSetupHive) RegCloseKey(hkSetupHive);
|
||||
if (lpszRegistryValue) free(lpszRegistryValue);
|
||||
#endif
|
||||
return VBOX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int virtualbox_initialize() {
|
||||
std::string virtualbox_install_directory;
|
||||
std::string old_path;
|
||||
std::string new_path;
|
||||
char buf[256];
|
||||
|
||||
virtualbox_get_install_directory(virtualbox_install_directory);
|
||||
|
||||
// Prep the environment so we can execute the vboxmanage application
|
||||
if (!virtualbox_install_directory.empty()) {
|
||||
old_path = getenv("path");
|
||||
|
||||
new_path = "path=";
|
||||
|
||||
new_path += virtualbox_install_directory;
|
||||
|
||||
// Path environment variable seperator
|
||||
#ifdef _WIN32
|
||||
new_path += ";";
|
||||
#else
|
||||
new_path += ":";
|
||||
#endif
|
||||
|
||||
new_path += old_path;
|
||||
|
||||
if (putenv(new_path.c_str())) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s Failed to modify the search path.\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return VBOX_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -231,18 +271,17 @@ int virtualbox_register_vm() {
|
|||
std::string output;
|
||||
std::string virtual_machine_name;
|
||||
std::string virtual_machine_root_dir;
|
||||
std::string virtual_hdd_uuid;
|
||||
char buf[256];
|
||||
int retval;
|
||||
|
||||
virtualbox_generate_vm_name(virtual_machine_name);
|
||||
virtualbox_generate_vm_root_dir(virtual_machine_root_dir);
|
||||
virtualbox_generate_medium_uuid(0, virtual_hdd_uuid);
|
||||
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s Registering virtual machine.\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf))
|
||||
"%s Registering virtual machine. (%s) \n",
|
||||
boinc_msg_prefix(buf, sizeof(buf)),
|
||||
virtual_machine_name.c_str()
|
||||
);
|
||||
|
||||
|
||||
|
@ -318,26 +357,6 @@ int virtualbox_register_vm() {
|
|||
}
|
||||
|
||||
|
||||
// Adding virtual hard drive to Virtual Box Media Registry
|
||||
//
|
||||
command = "openmedium ";
|
||||
command += "disk \"" + virtual_machine_root_dir + "/" + vm.vm_disk_image_name + "\" ";
|
||||
command += "--uuid " + virtual_hdd_uuid + " ";
|
||||
|
||||
retval = virtualbox_vbm_popen(command, output);
|
||||
if (retval) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s Error adding virtual disk drive to virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf)),
|
||||
retval,
|
||||
command.c_str(),
|
||||
output.c_str()
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// Adding virtual hard drive to VM
|
||||
//
|
||||
command = "storageattach \"" + virtual_machine_name + "\" ";
|
||||
|
@ -345,7 +364,7 @@ int virtualbox_register_vm() {
|
|||
command += "--port 0 ";
|
||||
command += "--device 0 ";
|
||||
command += "--type hdd ";
|
||||
command += "--medium " + virtual_hdd_uuid + " ";
|
||||
command += "--medium \"" + virtual_machine_root_dir + "/" + vm.vm_disk_image_name + "\" ";
|
||||
|
||||
retval = virtualbox_vbm_popen(command, output);
|
||||
if (retval) {
|
||||
|
@ -410,23 +429,20 @@ int virtualbox_register_vm() {
|
|||
}
|
||||
|
||||
|
||||
int virtualbox_deregister_vm() {
|
||||
int virtualbox_deregister_vm_by_name( std::string virtual_machine_name ) {
|
||||
std::string command;
|
||||
std::string output;
|
||||
std::string virtual_machine_name;
|
||||
std::string virtual_machine_root_dir;
|
||||
std::string virtual_hdd_uuid;
|
||||
char buf[256];
|
||||
int retval;
|
||||
|
||||
virtualbox_generate_vm_name(virtual_machine_name);
|
||||
virtualbox_generate_vm_root_dir(virtual_machine_root_dir);
|
||||
virtualbox_generate_medium_uuid(0, virtual_hdd_uuid);
|
||||
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s Deregistering virtual machine.\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf))
|
||||
"%s Deregistering virtual machine. (%s)\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf)),
|
||||
virtual_machine_name.c_str()
|
||||
);
|
||||
|
||||
|
||||
|
@ -471,7 +487,7 @@ int virtualbox_deregister_vm() {
|
|||
|
||||
// Lastly delete medium from Virtual Box Media Registry
|
||||
//
|
||||
command = "closemedium \"" + virtual_hdd_uuid + "\" ";
|
||||
command = "closemedium \"" + virtual_machine_root_dir + "/" + vm.vm_disk_image_name + "\" ";
|
||||
|
||||
retval = virtualbox_vbm_popen(command, output);
|
||||
if (retval) {
|
||||
|
@ -490,6 +506,89 @@ int virtualbox_deregister_vm() {
|
|||
}
|
||||
|
||||
|
||||
int virtualbox_deregister_stale_vm() {
|
||||
std::string command;
|
||||
std::string output;
|
||||
std::string virtual_machine_root_dir;
|
||||
std::string virtual_machine_name;
|
||||
size_t uuid_location;
|
||||
size_t uuid_length;
|
||||
char buf[256];
|
||||
int retval;
|
||||
|
||||
virtualbox_generate_vm_root_dir(virtual_machine_root_dir);
|
||||
|
||||
// We need to determine what the name or uuid is of the previous VM which owns
|
||||
// this virtual disk
|
||||
//
|
||||
command = "showhdinfo \"" + virtual_machine_root_dir + "/" + vm.vm_disk_image_name + "\" ";
|
||||
|
||||
retval = virtualbox_vbm_popen(command, output);
|
||||
if (retval) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s Error retrieving virtual hard disk information from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf)),
|
||||
retval,
|
||||
command.c_str(),
|
||||
output.c_str()
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// Output should look a little like this:
|
||||
// UUID: c119acaf-636c-41f6-86c9-38e639a31339
|
||||
// Accessible: yes
|
||||
// Logical size: 10240 MBytes
|
||||
// Current size on disk: 0 MBytes
|
||||
// Type: normal (base)
|
||||
// Storage format: VDI
|
||||
// Format variant: dynamic default
|
||||
// In use by VMs: test2 (UUID: 000ab2be-1254-4c6a-9fdc-1536a478f601)
|
||||
// Location: C:\Users\romw\VirtualBox VMs\test2\test2.vdi
|
||||
//
|
||||
uuid_location = output.find("(UUID: ");
|
||||
if (uuid_location != std::string::npos) {
|
||||
// We can parse the virtual machine ID from the output
|
||||
|
||||
uuid_location += 7;
|
||||
uuid_length = output.find(")", uuid_location);
|
||||
|
||||
virtual_machine_name = output.substr(uuid_location, uuid_length);
|
||||
|
||||
// Deregister stale VM by UUID
|
||||
return virtualbox_deregister_vm_by_name(virtual_machine_name);
|
||||
} else {
|
||||
// Did the user delete the VM in VirtualBox and not the medium? If so,
|
||||
// just remove the medium.
|
||||
command = "closemedium \"" + virtual_machine_root_dir + "/" + vm.vm_disk_image_name + "\" ";
|
||||
|
||||
retval = virtualbox_vbm_popen(command, output);
|
||||
if (retval) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"%s Error removing virtual hdd from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n",
|
||||
boinc_msg_prefix(buf, sizeof(buf)),
|
||||
retval,
|
||||
command.c_str(),
|
||||
output.c_str()
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
return VBOX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int virtualbox_deregister_vm() {
|
||||
std::string virtual_machine_name;
|
||||
virtualbox_generate_vm_name(virtual_machine_name);
|
||||
return virtualbox_deregister_vm_by_name(virtual_machine_name);
|
||||
}
|
||||
|
||||
|
||||
int virtualbox_cleanup() {
|
||||
return VBOX_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -24,18 +24,19 @@
|
|||
// Return codes
|
||||
#define VBOX_SUCCESS 0x00000000
|
||||
#define VBOX_POPEN_ERROR 0x00000001
|
||||
#define VBOX_PARSER_ERROR 0x00000002
|
||||
|
||||
// Functions
|
||||
extern int virtualbox_generate_vm_root_dir( std::string& dir );
|
||||
extern int virtualbox_generate_vm_name( std::string& name );
|
||||
extern int virtualbox_generate_medium_uuid( int drive_id, std::string& uuid );
|
||||
|
||||
extern bool virtualbox_vm_is_registered();
|
||||
extern bool virtualbox_vm_is_hdd_uuid_registered();
|
||||
extern bool virtualbox_vm_is_hdd_registered();
|
||||
extern bool virtualbox_vm_is_running();
|
||||
|
||||
extern int virtualbox_initialize();
|
||||
extern int virtualbox_register_vm();
|
||||
extern int virtualbox_deregister_stale_vm();
|
||||
extern int virtualbox_deregister_vm();
|
||||
extern int virtualbox_cleanup();
|
||||
|
||||
|
|
|
@ -94,6 +94,13 @@ int VM::run() {
|
|||
if (retval) return retval;
|
||||
|
||||
if (!virtualbox_vm_is_registered()) {
|
||||
if (virtualbox_vm_is_hdd_registered()) {
|
||||
// Handle the case where a previous instance of the same projects VM
|
||||
// was already initialized for the current slot directory but aborted
|
||||
// while the task was suspended and unloaded from memory.
|
||||
retval = virtualbox_deregister_stale_vm();
|
||||
if (retval) return retval;
|
||||
}
|
||||
retval = virtualbox_register_vm();
|
||||
if (retval) return retval;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue