diff --git a/samples/vboxwrapper/vbox.cpp b/samples/vboxwrapper/vbox.cpp index 9a85c5b88d..85c7ddbbda 100644 --- a/samples/vboxwrapper/vbox.cpp +++ b/samples/vboxwrapper/vbox.cpp @@ -1796,6 +1796,12 @@ void VBOX_VM::dump_vmguestlog_entries() { } } +void VBOX_VM::delete_temporary_exit_trigger_file() { + char path[MAXPATHLEN]; + sprintf(path, "shared/%s", temporary_exit_trigger_file.c_str()); + boinc_delete_file(path); +} + int VBOX_VM::is_registered() { string command; string output; @@ -1984,6 +1990,13 @@ bool VBOX_VM::is_logged_completion_file_exists() { return false; } +bool VBOX_VM::is_logged_temporary_exit_file_exists() { + char path[MAXPATHLEN]; + sprintf(path, "shared/%s", temporary_exit_trigger_file.c_str()); + if (boinc_file_exists(path)) return true; + return false; +} + bool VBOX_VM::is_virtualbox_version_newer(int maj, int min, int rel) { int vbox_major = 0, vbox_minor = 0, vbox_release = 0; if (3 == sscanf(virtualbox_version.c_str(), "%d.%d.%d", &vbox_major, &vbox_minor, &vbox_release)) { diff --git a/samples/vboxwrapper/vbox.h b/samples/vboxwrapper/vbox.h index 175756b127..7f09df9845 100644 --- a/samples/vboxwrapper/vbox.h +++ b/samples/vboxwrapper/vbox.h @@ -186,6 +186,13 @@ public: std::string completion_trigger_file; // if find this file in shared/, task is over. // File can optionally contain exit code (first line) + // File can optionally contain is_notice bool (second line) + // and stderr text (subsequent lines). + // Addresses a problem where VM doesn't shut down properly + std::string temporary_exit_trigger_file; + // if find this file in shared/, task is restarted at a later date. + // File can optionally contain restart delay (first line) + // File can optionally contain is_notice bool (second line) // and stderr text (subsequent lines). // Addresses a problem where VM doesn't shut down properly @@ -232,6 +239,7 @@ public: void dump_hypervisor_logs(bool include_error_logs); void dump_hypervisor_status_reports(); void dump_vmguestlog_entries(); + void delete_temporary_exit_trigger_file(); int is_registered(); bool is_system_ready(std::string& message); @@ -244,6 +252,7 @@ public: bool is_logged_failure_host_out_of_memory(); bool is_logged_failure_guest_job_out_of_memory(); bool is_logged_completion_file_exists(); + bool is_logged_temporary_exit_file_exists(); bool is_virtualbox_version_newer(int maj, int min, int rel); bool is_virtualbox_error_recoverable(int retval); diff --git a/samples/vboxwrapper/vboxwrapper.cpp b/samples/vboxwrapper/vboxwrapper.cpp index 1d8f84dbe7..d9b90e2b47 100644 --- a/samples/vboxwrapper/vboxwrapper.cpp +++ b/samples/vboxwrapper/vboxwrapper.cpp @@ -226,6 +226,10 @@ int parse_job_file(VBOX_VM& vm) { vm.completion_trigger_file = str; continue; } + else if (xp.parse_string("temporary_exit_trigger_file", str)) { + vm.temporary_exit_trigger_file = str; + continue; + } else if (xp.match_tag("port_forward")) { vm.parse_port_forward(xp); } @@ -317,6 +321,29 @@ void read_completion_file_info(unsigned long& exit_code, bool& is_notice, string } } +void read_temporary_exit_file_info(int& temp_delay, bool& is_notice, string& message, VBOX_VM& vm) { + char path[MAXPATHLEN]; + char buf[1024]; + + temp_delay = 0; + message = ""; + + sprintf(path, "shared/%s", vm.temporary_exit_trigger_file.c_str()); + FILE* f = fopen(path, "r"); + if (f) { + if (fgets(buf, 1024, f) != NULL) { + temp_delay = atoi(buf); + } + if (fgets(buf, 1024, f) != NULL) { + is_notice = atoi(buf); + } + while (fgets(buf, 1024, f) != NULL) { + message += buf; + } + fclose(f); + } +} + // set CPU and network throttling if needed // void set_throttles(APP_INIT_DATA& aid, VBOX_VM& vm) { @@ -570,6 +597,7 @@ int main(int argc, char** argv) { int vm_image = 0; unsigned long vm_exit_code = 0; bool is_notice = false; + int temp_delay = 86400; string message; char buf[256]; @@ -917,7 +945,6 @@ int main(int argc, char** argv) { bool do_dump_hypervisor_logs = false; string error_reason; const char* temp_reason = ""; - int temp_delay = 86400; if (VBOXWRAPPER_ERR_RECOVERABLE == retval) { error_reason = @@ -1144,6 +1171,30 @@ int main(int argc, char** argv) { boinc_finish(vm_exit_code); } } + if (vm.is_logged_temporary_exit_file_exists()) { + vm.reset_vm_process_priority(); + vm.stop(); + fprintf( + stderr, + "%s VM Temporary Exit File Detected.\n", + vboxwrapper_msg_prefix(buf, sizeof(buf)) + ); + read_temporary_exit_file_info(temp_delay, is_notice, message, vm); + if (message.size()) { + fprintf( + stderr, + "%s VM Temporary Exit Message: %s.\n", + vboxwrapper_msg_prefix(buf, sizeof(buf)), + message.c_str() + ); + } + vm.delete_temporary_exit_trigger_file(); + if (is_notice) { + boinc_temporary_exit(temp_delay, message.c_str(), is_notice); + } else { + boinc_temporary_exit(temp_delay); + } + } if (!vm.online) { // Is this a type of event we can recover from? if (vm.is_logged_failure_host_out_of_memory()) {