- VBOX: Remove attempts to remove the floppy image from the media registry.

Apparently when the VM is removed from the VirtualBox server process
        it automatically deletes the floppy image from the media registry.
    - VBOX: If a VM crashes for one reason or another, append the VM execution
        log file to the stderr.txt file.  I believe this is what is going on with
        Richard Mitnick's computer.  At the very least we should be able to give
        this to the VirtualBox guys.
    - VBOX: Introduce a way to re-execute commands when a session lock
        event is detected.  A session lock event happens when a volunteer is
        tweaking something about the VM while vboxwrapper is attempting to query
        state information.
        
    samples/vboxwrapper/
        vbox.cpp, .h
        vboxwrapper.cpp, .h

svn path=/trunk/boinc/; revision=24887
This commit is contained in:
Rom Walton 2011-12-25 03:57:56 +00:00
parent eaddebab61
commit 59f2739cc5
4 changed files with 124 additions and 24 deletions

View File

@ -9410,3 +9410,20 @@ David 23 Dec 2011
user/
pm.php
moderation.php
Rom 23 Dec 2011
- VBOX: Remove attempts to remove the floppy image from the media registry.
Apparently when the VM is removed from the VirtualBox server process
it automatically deletes the floppy image from the media registry.
- VBOX: If a VM crashes for one reason or another, append the VM execution
log file to the stderr.txt file. I believe this is what is going on with
Richard Mitnick's computer. At the very least we should be able to give
this to the VirtualBox guys.
- VBOX: Introduce a way to re-execute commands when a session lock
event is detected. A session lock event happens when a volunteer is
tweaking something about the VM while vboxwrapper is attempting to query
state information.
samples/vboxwrapper/
vbox.cpp, .h
vboxwrapper.cpp, .h

View File

@ -63,6 +63,8 @@ VBOX_VM::VBOX_VM() {
max_elapsed_time = 0.0;
suspended = false;
network_suspended = false;
online = false;
crashed = false;
enable_cern_dataformat = false;
enable_shared_directory = false;
enable_floppyio = false;
@ -119,9 +121,61 @@ void VBOX_VM::cleanup() {
boinc_sleep(5.0);
}
// Execute the vbox manage application and copy the output to the buffer.
// If there are errors we can recover from, process them here.
//
int VBOX_VM::vbm_popen(string& arguments, string& output, const char* item, bool log_error) {
int retval = 0;
int retry_count = 0;
string retry_notes;
do
{
retval = vbm_popen_raw(arguments, output, item, log_error);
if (retval) {
// VirtualBox designed the concept of sessions to prevent multiple applications using
// the VirtualBox COM API (virtualbox.exe, vboxmanage.exe) from modifying the same VM
// at the same time.
//
// The problem here is that vboxwrapper uses vboxmanage.exe to modify and control the
// VM. Vboxmanage.exe can only maintain the session lock for as long as it takes it
// to run. So that means 99% of the time that a VM is running under BOINC technology
// it is running without a session lock.
//
// If a volunteer opens another VirtualBox management application and goes poking around
// that application can aquire the session lock and not give it up for some time.
//
// If we detect that condition retry the desired command.
//
if ((output.find("VBOX_E_INVALID_OBJECT_STATE") != string::npos) &&
(output.find("already locked") != string::npos))
{
if (retry_notes.find("already locked") == string::npos) {
retry_notes += "Virtual Machine session already locked.\n";
}
}
// Timeout?
if (retry_count >= 6) break;
retry_count++;
boinc_sleep(5.0);
}
}
while (retval);
// Add all relivent notes to the output string
//
if (retval) {
output += "\nNotes:\n" + retry_notes;
}
return retval;
}
// Execute the vbox manage application and copy the output to the buffer.
//
int VBOX_VM::vbm_popen_raw(string& arguments, string& output, const char* item, bool log_error) {
char buf[256];
string command;
int retval = 0;
@ -363,6 +417,9 @@ void VBOX_VM::poll() {
online = true;
} else if (vmstate == "restoring") {
online = true;
} else if (vmstate == "gurumeditation") {
online = false;
crashed = true;
} else {
online = false;
}
@ -865,17 +922,6 @@ int VBOX_VM::deregister_vm() {
command = "closemedium disk \"" + virtual_machine_slot_directory + "/" + image_filename + "\" ";
vbm_popen(command, output, "remove virtual disk");
if (enable_floppyio) {
fprintf(
stderr,
"%s Removing virtual disk drive from VirtualBox.\n",
boinc_msg_prefix(buf, sizeof(buf))
);
command = "closemedium floppy \"" + virtual_machine_slot_directory + "/" + floppy_image_filename + "\" ";
vbm_popen(command, output, "remove virtual floppy disk");
}
return 0;
}
@ -922,11 +968,6 @@ int VBOX_VM::deregister_stale_vm() {
// just remove the medium.
command = "closemedium disk \"" + virtual_machine_slot_directory + "/" + image_filename + "\" ";
vbm_popen(command, output, "remove virtual disk ", false);
if (enable_floppyio) {
command = "closemedium floppy \"" + virtual_machine_slot_directory + "/" + floppy_image_filename + "\" ";
vbm_popen(command, output, "remove virtual floppy disk", false);
}
}
return 0;
}
@ -1214,6 +1255,22 @@ int VBOX_VM::get_network_bytes_sent(double& sent) {
return 0;
}
int VBOX_VM::get_vm_log(string& log) {
string command;
string output;
int retval;
command = "showvminfo \"" + vm_name + "\" ";
command += "--log 0 ";
retval = vbm_popen(command, output, "get vm log");
if (retval) return retval;
log = output;
return 0;
}
int VBOX_VM::read_floppy(std::string& data) {
if (enable_floppyio && pFloppy) {
data = pFloppy->receive();

View File

@ -53,6 +53,8 @@ struct VBOX_VM {
bool network_suspended;
// is VM even online?
bool online;
// Has the VM crashed?
bool crashed;
// whether to use CERN specific data structures
bool enable_cern_dataformat;
// whether to use shared directory infrastructure at all
@ -90,6 +92,7 @@ struct VBOX_VM {
int get_process_id(int& process_id);
int get_network_bytes_sent(double& sent);
int get_network_bytes_received(double& received);
int get_vm_log(std::string& log);
int read_floppy(std::string& data);
int write_floppy(std::string& data);
@ -99,6 +102,9 @@ struct VBOX_VM {
static int vbm_popen(
std::string& command, std::string& output, const char* item, bool log_error = true
);
static int vbm_popen_raw(
std::string& command, std::string& output, const char* item, bool log_error = true
);
};
#endif

View File

@ -353,15 +353,35 @@ int main(int argc, char** argv) {
boinc_finish(EXIT_ABORTED_BY_CLIENT);
}
if (!vm.online) {
fprintf(
stderr,
"%s Virtual machine is no longer running, it must have completed its work.\n"
"%s NOTE: If this is in error, check the vboxwrapper source code for additional steps to debug this issue.\n",
boinc_msg_prefix(buf, sizeof(buf)),
boinc_msg_prefix(buf, sizeof(buf))
);
vm.cleanup();
write_checkpoint(checkpoint_cpu_time);
if (vm.crashed) {
std::string log;
vm.get_vm_log(log);
fprintf(
stderr,
"%s VM Crash Detected!!!\n\n"
"%s NOTE: This is like a blue-screen event in Windows, the rest of the information in this file\n"
"%s is diagnostic information generated by VirtualBox.\n"
"%s VM Crash Log:\n\n"
"%s\n",
boinc_msg_prefix(buf, sizeof(buf)),
boinc_msg_prefix(buf, sizeof(buf)),
boinc_msg_prefix(buf, sizeof(buf)),
boinc_msg_prefix(buf, sizeof(buf)),
log.c_str()
);
} else {
fprintf(
stderr,
"%s Virtual machine is no longer running, it must have completed its work.\n"
"%s NOTE: If this is in error, check the vboxwrapper source code for additional steps to debug this issue.\n",
boinc_msg_prefix(buf, sizeof(buf)),
boinc_msg_prefix(buf, sizeof(buf))
);
}
boinc_finish(0);
}
if (boinc_status.suspended) {