- VBOX: Checkpoint, Re-implement the registering and un-registering of the

vm using the vboxmanage app.

    samples/vboxwrapper/
        vbox.cpp, .h
        vm.cpp, .h

svn path=/trunk/boinc/; revision=23485
This commit is contained in:
Rom Walton 2011-04-30 00:26:05 +00:00
parent 4a5c418b43
commit 602f972292
5 changed files with 373 additions and 20 deletions

View File

@ -2705,3 +2705,11 @@ David 29 Apr 2011
lib/
gui_rpc_client.cpp
Rom 29 Apr 2011
- VBOX: Checkpoint, Re-implement the registering and un-registering of the
vm using the vboxmanage app.
samples/vboxwrapper/
vbox.cpp, .h
vm.cpp, .h

View File

@ -43,6 +43,7 @@
#include "procinfo.h"
#include "boinc_api.h"
#include "vbox.h"
#include "vm.h"
// Execute the vbox manage application and copy the output to the
@ -61,9 +62,8 @@ int virtualbox_vbm_popen(std::string& arguments, std::string& output) {
if (fp == NULL){
fprintf(
stderr,
"%s vbm_popen popen failed! cmd = '%s', errno = %d\n",
"%s vbm_popen popen failed! errno = %d\n",
boinc_msg_prefix(buf, sizeof(buf)),
command.c_str(),
errno
);
return VBOX_POPEN_ERROR;
@ -84,7 +84,7 @@ int virtualbox_vbm_popen(std::string& arguments, std::string& output) {
// Returns the current directory in which the executable resides.
//
int virtualbox_generate_vm_root_dir( std::string& dir ) {
TCHAR root_dir[256];
char root_dir[256];
#ifdef _WIN32
_getcwd(root_dir, (sizeof(root_dir)*sizeof(TCHAR)));
@ -127,6 +127,48 @@ 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;
@ -140,7 +182,23 @@ bool virtualbox_vm_is_registered() {
return true;
}
}
return false;
}
bool virtualbox_vm_is_hdd_uuid_registered() {
std::string command;
std::string output;
std::string virtual_hdd_uuid;
virtualbox_generate_medium_uuid(0, virtual_hdd_uuid);
command = "showhdinfo " + virtual_hdd_uuid;
if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) {
if (output.find("VBOX_E_FILE_ERROR") != std::string::npos) {
return true;
}
}
return false;
}
@ -173,9 +231,13 @@ 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,
@ -183,14 +245,247 @@ int virtualbox_register_vm() {
boinc_msg_prefix(buf, sizeof(buf))
);
//command = "startvm " + virtual_machine_name + " --type headless";
//virtualbox_vbm_popen(command, output);
// Create and register the VM
//
command = "createvm ";
command += "--name \"" + virtual_machine_name + "\" ";
command += "--basefolder \"" + virtual_machine_root_dir + "\" ";
command += "--settingsfile \"" + virtual_machine_root_dir + "/" + virtual_machine_name + "\" ";
command += "--ostype \"" + vm.vm_os_name + "\" ";
command += "--register";
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error registering 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;
}
// Tweak the VM from it's default configuration
//
command = "modifyvm \"" + virtual_machine_name + "\" ";
command += "--memory " + vm.vm_memory_size + " ";
command += "--acpi on ";
command += "--ioapic on ";
command += "--boot1 disk ";
command += "--boot2 none ";
command += "--boot3 none ";
command += "--boot4 none ";
command += "--nic1 nat ";
command += "--natdnsproxy1 on ";
command += "--cableconnected1 off ";
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error modifing 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;
}
// Add storage controller to VM
//
command = "storagectl \"" + virtual_machine_name + "\" ";
command += "--name \"IDE Controller\" ";
command += "--add ide ";
command += "--controller PIIX4 ";
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error adding storage controller 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 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 + "\" ";
command += "--storagectl \"IDE Controller\" ";
command += "--port 0 ";
command += "--device 0 ";
command += "--type hdd ";
command += "--medium " + 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;
}
// Enable the network adapter if a network connection is required.
// NOTE: Network access should never be allowed if the code running in a
// shared directory or the VM itself is NOT signed. Doing so opens up
// the network behind the firewall to attack.
//
if (vm.enable_network) {
command = "modifyvm \"" + virtual_machine_name + "\" ";
command += "--cableconnected1 on ";
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error enabling network access for 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;
}
}
// Enable the shared folder if a shared folder is specified.
//
if (vm.enable_shared_directory) {
command = "sharedfolder add \"" + virtual_machine_name + "\" ";
command += "--name \"" + vm.vm_shared_folder_name + "\" ";
command += "--hostpath \"" + virtual_machine_root_dir + "/" + vm.vm_shared_folder_dir_name + "\" ";
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error enabling shared directory for 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;
}
}
return VBOX_SUCCESS;
}
int virtualbox_deregister_vm() {
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))
);
// First step in deregistering a VM is to delete its storage controller
//
command = "storagectl \"" + virtual_machine_name + "\" ";
command += "--name \"IDE Controller\" ";
command += "--remove ";
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error removing storage controller from 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;
}
// Next delete VM
//
command = "unregistervm \"" + virtual_machine_name + "\" ";
command += "--delete ";
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error removing virtual machine 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;
}
// Lastly delete medium from Virtual Box Media Registry
//
command = "closemedium \"" + virtual_hdd_uuid + "\" ";
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;
}
@ -204,10 +499,24 @@ int virtualbox_startvm() {
std::string command;
std::string output;
std::string virtual_machine_name;
char buf[256];
int retval;
virtualbox_generate_vm_name(virtual_machine_name);
command = "startvm " + virtual_machine_name + " --type headless";
return virtualbox_vbm_popen(command, output);
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error starting 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;
}
return VBOX_SUCCESS;
}
@ -215,10 +524,24 @@ int virtualbox_stopvm() {
std::string command;
std::string output;
std::string virtual_machine_name;
char buf[256];
int retval;
virtualbox_generate_vm_name(virtual_machine_name);
command = "controlvm " + virtual_machine_name + " savestate";
return virtualbox_vbm_popen(command, output);
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error stopping 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;
}
return VBOX_SUCCESS;
}
@ -226,10 +549,24 @@ int virtualbox_pausevm() {
std::string command;
std::string output;
std::string virtual_machine_name;
char buf[256];
int retval;
virtualbox_generate_vm_name(virtual_machine_name);
command = "controlvm " + virtual_machine_name + " pause";
return virtualbox_vbm_popen(command, output);
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error pausing 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;
}
return VBOX_SUCCESS;
}
@ -237,10 +574,24 @@ int virtualbox_resumevm() {
std::string command;
std::string output;
std::string virtual_machine_name;
char buf[256];
int retval;
virtualbox_generate_vm_name(virtual_machine_name);
command = "controlvm " + virtual_machine_name + " resume";
return virtualbox_vbm_popen(command, output);
retval = virtualbox_vbm_popen(command, output);
if (retval) {
fprintf(
stderr,
"%s Error resuming 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;
}
return VBOX_SUCCESS;
}

View File

@ -28,8 +28,10 @@
// 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_running();
extern int virtualbox_initialize();

View File

@ -47,10 +47,8 @@ VM::VM() {
stdout_filename.clear();
stderr_filename.clear();
vm_os_name.clear();
vm_os_version.clear();
vm_memory_size = 0;
vm_memory_size.clear();
vm_disk_image_name.clear();
vm_disk_image_type.clear();
vm_shared_folder_name.clear();
vm_shared_folder_dir_name.clear();
suspended = false;
@ -79,10 +77,8 @@ int VM::parse(XML_PARSER& xp) {
else if (xp.parse_string(tag, "stdout_filename", stdout_filename)) continue;
else if (xp.parse_string(tag, "stderr_filename", stderr_filename)) continue;
else if (xp.parse_string(tag, "vm_os_name", vm_os_name)) continue;
else if (xp.parse_string(tag, "vm_os_version", vm_os_version)) continue;
else if (xp.parse_int(tag, "vm_memory_size", vm_memory_size)) continue;
else if (xp.parse_string(tag, "vm_memory_size", vm_memory_size)) continue;
else if (xp.parse_string(tag, "vm_disk_image_name", vm_disk_image_name)) continue;
else if (xp.parse_string(tag, "vm_disk_image_type", vm_disk_image_type)) continue;
else if (xp.parse_string(tag, "vm_shared_folder_name", vm_shared_folder_name)) continue;
else if (xp.parse_string(tag, "vm_shared_folder_dir_name", vm_shared_folder_dir_name)) continue;
else if (xp.parse_bool(tag, "enable_network", enable_network)) continue;

View File

@ -31,14 +31,10 @@ public:
std::string stderr_filename;
// name of the OS the VM runs
std::string vm_os_name;
// name of the version of the VM the OS runs
std::string vm_os_version;
// size of the memory allocation for the VM
int vm_memory_size;
std::string vm_memory_size;
// name of the virtual machine disk image file
std::string vm_disk_image_name;
// name of the virtual machine disk image type
std::string vm_disk_image_type;
// name of shared folder
std::string vm_shared_folder_name;
// shared folder directory name