mirror of https://github.com/BOINC/boinc.git
Merge pull request #4843 from computezrmle/vboxwrapper_improvements
Vboxwrapper improvements
This commit is contained in:
commit
a5ca65590c
|
@ -1186,13 +1186,25 @@ int VBOX_BASE::vbm_popen(string& command, string& output, const char* item, bool
|
|||
// Error Code: VBOX_E_INVALID_OBJECT_STATE (0x80bb0007)
|
||||
//
|
||||
if (VBOX_E_INVALID_OBJECT_STATE == (unsigned int)retval) {
|
||||
if (retry_notes.find("Another VirtualBox management") == string::npos) {
|
||||
retry_notes += "Another VirtualBox management application has locked the session for\n";
|
||||
retry_notes += "this VM. BOINC cannot properly monitor this VM\n";
|
||||
retry_notes += "and so this job will be aborted.\n\n";
|
||||
}
|
||||
if (retry_count) {
|
||||
sleep_interval *= 2;
|
||||
if ((output.find("Cannot attach medium") != string::npos) &&
|
||||
(output.find("the media type") != string::npos) &&
|
||||
(output.find("MultiAttach") != string::npos) &&
|
||||
(output.find("can only be attached to machines that were created with VirtualBox 4.0 or later") != string::npos)) {
|
||||
// VirtualBox occasionally writes the 'MultiAttach' attribute to
|
||||
// the disk entry in VirtualBox.xml although this is not allowed there.
|
||||
// As a result all VMs trying to connect that disk fail.
|
||||
// Report the error back immediately without a retry.
|
||||
//
|
||||
break;
|
||||
} else {
|
||||
if (retry_notes.find("Another VirtualBox management") == string::npos) {
|
||||
retry_notes += "Another VirtualBox management application has locked the session for\n";
|
||||
retry_notes += "this VM. BOINC cannot properly monitor this VM\n";
|
||||
retry_notes += "and so this job will be aborted.\n\n";
|
||||
}
|
||||
if (retry_count) {
|
||||
sleep_interval *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1482,4 +1494,3 @@ VBOX_VM::VBOX_VM() {
|
|||
|
||||
VBOX_VM::~VBOX_VM() {
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <algorithm>
|
||||
#include "boinc_win.h"
|
||||
#include "win_util.h"
|
||||
#else
|
||||
#include <algorithm>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -543,53 +543,147 @@ namespace vboxmanage {
|
|||
// See: https://www.virtualbox.org/manual/ch05.html#hdimagewrites
|
||||
// https://www.virtualbox.org/manual/ch05.html#diffimages
|
||||
// the vdi file downloaded to the projects dir becomes the parent (read only)
|
||||
// "--setuid" must not be used
|
||||
// each task gets it's own differencing image (writable)
|
||||
// differencing images are written to the VM's snapshot folder
|
||||
//
|
||||
string medium_file = aid.project_dir;
|
||||
medium_file += "/" + multiattach_vdi_file;
|
||||
|
||||
#ifdef _WIN32
|
||||
replace(medium_file.begin(), medium_file.end(), '\\', '/');
|
||||
#endif
|
||||
|
||||
vboxlog_msg("Adding virtual disk drive to VM. (%s)", multiattach_vdi_file.c_str());
|
||||
command = "list hdds";
|
||||
|
||||
retval = vbm_popen(command, output, "check if parent hdd is registered", false, false);
|
||||
if (retval) return retval;
|
||||
int retry_count = 0;
|
||||
bool log_error = false;
|
||||
bool vbox_bug_mitigation = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
replace(output.begin(), output.end(), '\\', '/');
|
||||
#endif
|
||||
do {
|
||||
string set_new_uuid = "";
|
||||
string type_line = "";
|
||||
size_t type_start;
|
||||
size_t type_end;
|
||||
|
||||
if (output.find(medium_file) == string::npos) {
|
||||
// parent hdd is not registered
|
||||
// vdi files can't be registered and set to multiattach mode within 1 step.
|
||||
// They must first be attached to a VM in normal mode, then detached from the VM
|
||||
command = "showhdinfo \"" + medium_file + "\" ";
|
||||
|
||||
retval = vbm_popen(command, output, "check if parent hdd is registered", false);
|
||||
if (retval) {
|
||||
// showhdinfo implicitly registers unregistered hdds.
|
||||
// Hence, this has to be handled first.
|
||||
//
|
||||
if ((output.rfind("VBoxManage: error:", 0) != string::npos) &&
|
||||
(output.find("Cannot register the hard disk") != string::npos) &&
|
||||
(output.find("because a hard disk") != string::npos) &&
|
||||
(output.find("with UUID") != string::npos) &&
|
||||
(output.find("already exists") != string::npos)) {
|
||||
// May happen if the project admin didn't set a new UUID.
|
||||
set_new_uuid = "--setuuid \"\" ";
|
||||
|
||||
vboxlog_msg("Disk UUID conflicts with an already existing disk.\nWill set a new UUID for '%s'.\nThe project admin should be informed to do this server side running:\nvboxmanage clonemedium <inputfile> <outputfile>\n",
|
||||
multiattach_vdi_file.c_str()
|
||||
);
|
||||
} else {
|
||||
// other errors
|
||||
vboxlog_msg("Error in check if parent hdd is registered.\nCommand:\n%s\nOutput:\n%s",
|
||||
command.c_str(),
|
||||
output.c_str()
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
// Output from showhdinfo should look a little like this:
|
||||
// UUID: c119bcaf-636c-41f6-86c9-384739a31339
|
||||
// Parent UUID: base
|
||||
// State: created
|
||||
// Type: multiattach
|
||||
// Location: C:\Users\romw\VirtualBox VMs\test2\test2.vdi
|
||||
// Storage format: VDI
|
||||
// Format variant: dynamic default
|
||||
// Capacity: 2048 MBytes
|
||||
// Size on disk: 2 MBytes
|
||||
// Encryption: disabled
|
||||
// Property: AllocationBlockSize=1048576
|
||||
// Child UUIDs: dcb0daa5-3bf9-47cb-bfff-c65e74484615
|
||||
//
|
||||
command = command_fix_part;
|
||||
command += "--medium \"" + medium_file + "\" ";
|
||||
|
||||
retval = vbm_popen(command, output, "register parent hdd", false, false);
|
||||
if (retval) return retval;
|
||||
type_line = output;
|
||||
transform(type_line.cbegin(), type_line.cend(),
|
||||
type_line.begin(), [](unsigned char c) { return tolower(c); });
|
||||
type_start = type_line.find("\ntype: ") + 1;
|
||||
type_end = type_line.find("\n", type_start) - type_start;
|
||||
type_line = type_line.substr(type_start, type_end);
|
||||
|
||||
command = command_fix_part;
|
||||
command += "--medium none ";
|
||||
if (type_line.find("multiattach") == string::npos) {
|
||||
// Parent hdd is not (yet) of type multiattach.
|
||||
// Vdi files can't be registered and set to multiattach mode within 1 step.
|
||||
// They must first be attached to a VM in normal mode, then detached from the VM
|
||||
|
||||
retval = vbm_popen(command, output, "detach parent vdi", false, false);
|
||||
if (retval) return retval;
|
||||
// the vdi file is now registered and ready to be attached in multiattach mode
|
||||
//
|
||||
command = command_fix_part;
|
||||
command += set_new_uuid + "--medium \"" + medium_file + "\" ";
|
||||
|
||||
retval = vbm_popen(command, output, "register parent vdi");
|
||||
if (retval) return retval;
|
||||
|
||||
command = command_fix_part;
|
||||
command += "--medium none ";
|
||||
|
||||
retval = vbm_popen(command, output, "detach parent vdi");
|
||||
if (retval) return retval;
|
||||
// the vdi file is now registered and ready to be attached in multiattach mode
|
||||
//
|
||||
}
|
||||
|
||||
do {
|
||||
command = command_fix_part;
|
||||
command += "--mtype multiattach ";
|
||||
command += "--medium \"" + medium_file + "\" ";
|
||||
|
||||
retval = vbm_popen(command, output, "storage attach (fixed disk - multiattach mode)", log_error);
|
||||
if (retval) {
|
||||
// VirtualBox occasionally writes the 'MultiAttach' attribute to
|
||||
// the disk entry in VirtualBox.xml although this is not allowed there.
|
||||
// As a result all VMs trying to connect that disk fail.
|
||||
// The error needs to be cleaned here to allow vboxwrapper to
|
||||
// succeed even with uncorrected VirtualBox versions.
|
||||
//
|
||||
// After cleanup attaching the disk should be tried again.
|
||||
|
||||
if ((retry_count < 1) &&
|
||||
(output.find("Cannot attach medium") != string::npos) &&
|
||||
(output.find("the media type") != string::npos) &&
|
||||
(output.find("MultiAttach") != string::npos) &&
|
||||
(output.find("can only be attached to machines that were created with VirtualBox 4.0 or later") != string::npos)) {
|
||||
// try to deregister the medium from the global media store
|
||||
command = "closemedium \"" + medium_file + "\" ";
|
||||
|
||||
retval = vbm_popen(command, output, "deregister parent vdi");
|
||||
if (retval) return retval;
|
||||
|
||||
retry_count++;
|
||||
log_error = true;
|
||||
boinc_sleep(1.0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (retry_count >= 1) {
|
||||
// in case of other errors or if retry also failed
|
||||
vboxlog_msg("Error in storage attach (fixed disk - multiattach mode).\nCommand:\n%s\nOutput:\n%s",
|
||||
command.c_str(),
|
||||
output.c_str()
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
|
||||
retry_count++;
|
||||
log_error = true;
|
||||
boinc_sleep(1.0);
|
||||
|
||||
} else {
|
||||
vbox_bug_mitigation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
command = command_fix_part;
|
||||
command += "--mtype multiattach ";
|
||||
command += "--medium \"" + medium_file + "\" ";
|
||||
|
||||
retval = vbm_popen(command, output, "storage attach (fixed disk - multiattach mode)");
|
||||
if (retval) return retval;
|
||||
while (!vbox_bug_mitigation);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue