VBOX: Move common code to VBOX_BASE class, VBOX_VM derives from it by extending virtual functions calling Vboxmanage or Native API functions. Use ATL on Windows to wrap COM Objects and data types.

This commit is contained in:
Rom Walton 2014-11-23 12:46:28 -05:00
parent 72fd80a203
commit 810047d4eb
4 changed files with 110 additions and 2940 deletions

File diff suppressed because it is too large Load Diff

View File

@ -74,21 +74,19 @@ struct PORT_FORWARD {
int host_port; // 0 means assign dynamically
int guest_port;
bool is_remote;
bool web_application;
PORT_FORWARD() {
host_port = 0;
guest_port = 0;
is_remote = false;
web_application = false;
}
int get_host_port(); // assign host port
};
// represents a VirtualBox VM
class VBOX_VM {
class VBOX_BASE {
public:
VBOX_VM();
~VBOX_VM();
VBOX_BASE();
~VBOX_BASE();
std::string virtualbox_home_directory;
std::string virtualbox_install_directory;
@ -167,8 +165,6 @@ public:
// whether to use floppy io infrastructure
bool enable_remotedesktop;
// whether to enable remote desktop functionality
bool enable_gbac;
// whether to enable GBAC functionality
double job_duration;
// maximum amount of wall-clock time this VM is allowed to run before
// considering itself done.
@ -189,58 +185,35 @@ 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
/////////// END VBOX_JOB.XML ITEMS //////////////
int vm_pid;
int vboxsvc_pid;
#ifdef _WIN32
// the handle to the process for the VM
// NOTE: we get a handle to the pid right after we parse it from the
// log files so we can adjust the process priority and retrieve the process
// exit code in case it crashed or was terminated. Without an outstanding
// handle to the process, the OS is free to reuse the pid for some other
// executable.
HANDLE vm_pid_handle;
// the handle to the vboxsvc process created by us in the sandbox'ed environment
HANDLE vboxsvc_pid_handle;
#endif
int initialize();
void poll(bool log_state = true);
int create_vm();
int register_vm();
int deregister_vm(bool delete_media);
int deregister_stale_vm();
virtual int initialize();
virtual int create_vm();
virtual int register_vm();
virtual int deregister_vm(bool delete_media);
virtual int deregister_stale_vm();
virtual void poll(bool log_state = true);
virtual int start();
virtual int stop();
virtual int poweroff();
virtual int pause();
virtual int resume();
virtual int create_snapshot(double elapsed_time);
virtual int cleanup_snapshots(bool delete_active);
virtual int restore_snapshot();
int run(bool do_restore_snapshot);
void cleanup();
int start();
int stop();
int poweroff();
int pause();
int resume();
void check_trickle_triggers();
void check_intermediate_uploads();
int create_snapshot(double elapsed_time);
int cleanup_snapshots(bool delete_active);
int restore_snapshot();
void dump_hypervisor_logs(bool include_error_logs);
void dump_hypervisor_status_reports();
void dump_vmguestlog_entries();
void delete_temporary_exit_trigger_file();
void check_trickle_triggers();
void check_intermediate_uploads();
int is_registered();
bool is_system_ready(std::string& message);
@ -253,7 +226,6 @@ 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);
@ -282,9 +254,6 @@ public:
void lower_vm_process_priority();
void reset_vm_process_priority();
int launch_vboxsvc();
int launch_vboxvm();
void sanitize_output(std::string& output);
#ifndef _WIN32

View File

@ -48,6 +48,9 @@
#ifdef _WIN32
#include "boinc_win.h"
#include "win_util.h"
#include "atlcomcli.h"
#include "atlstr.h"
#include "mscom/VirtualBox.h"
#else
#include <vector>
#include <sys/wait.h>
@ -73,6 +76,12 @@
#include "vboxwrapper.h"
#include "vbox.h"
#ifdef _WIN32
#include "vbox_win.h"
#else
#include "vbox_unix.h"
#endif
using std::vector;
using std::string;
@ -126,38 +135,46 @@ char* vboxwrapper_msg_prefix(char* sbuf, int len) {
return sbuf;
}
int parse_port_forward(XML_PARSER& xp, VBOX_VM& vm) {
int parse_port_forward(VBOX_VM& vm, XML_PARSER& xp) {
char buf2[256];
int host_port=0, guest_port=0, nports=1;
bool is_remote = false, web_application = false;
char buf[256];
bool is_remote;
while (!xp.get_tag()) {
if (xp.match_tag("/port_forward")) {
if (!guest_port) {
fprintf(stderr, "%s parse_port_forward(): unspecified guest port\n",
vboxwrapper_msg_prefix(buf, sizeof(buf))
if (!host_port) {
fprintf(stderr,
"%s parse_port_forward(): unspecified host port\n",
vboxwrapper_msg_prefix(buf2, sizeof(buf2))
);
return ERR_XML_PARSE;
}
if (!guest_port) {
fprintf(stderr,
"%s parse_port_forward(): unspecified guest port\n",
vboxwrapper_msg_prefix(buf2, sizeof(buf2))
);
return ERR_XML_PARSE;
}
PORT_FORWARD pf;
pf.host_port = host_port;
pf.guest_port = guest_port;
pf.is_remote = is_remote;
pf.web_application = web_application;
for (int i=0; i<nports; i++) {
vm.port_forwards.push_back(pf);
pf.host_port++;
pf.guest_port++;
pf.web_application = false;
}
return 0;
}
else if (xp.parse_bool("web_application", web_application)) continue;
else if (xp.parse_bool("is_remote", is_remote)) continue;
else if (xp.parse_int("host_port", host_port)) continue;
else if (xp.parse_int("guest_port", guest_port)) continue;
else if (xp.parse_int("nports", nports)) continue;
else {
fprintf(stderr, "%s parse_port_forward(): unexpected tag %s\n",
vboxwrapper_msg_prefix(buf, sizeof(buf)), xp.parsed_tag
fprintf(stderr,
"%s parse_port_forward(): unparsed %s\n",
vboxwrapper_msg_prefix(buf2, sizeof(buf2)),
xp.parsed_tag
);
}
}
@ -167,7 +184,6 @@ int parse_port_forward(XML_PARSER& xp, VBOX_VM& vm) {
int parse_job_file(VBOX_VM& vm) {
INTERMEDIATE_UPLOAD iu;
MIOFILE mf;
int guest_port=0;
string str;
char buf[1024], buf2[256];
@ -210,16 +226,8 @@ int parse_job_file(VBOX_VM& vm) {
else if (xp.parse_bool("enable_cache_disk", vm.enable_cache_disk)) continue;
else if (xp.parse_bool("enable_isocontextualization", vm.enable_isocontextualization)) continue;
else if (xp.parse_bool("enable_remotedesktop", vm.enable_remotedesktop)) continue;
else if (xp.parse_bool("enable_gbac", vm.enable_gbac)) continue;
else if (xp.parse_int("pf_guest_port", guest_port)) {
PORT_FORWARD pf;
pf.host_port = 0;
pf.guest_port = guest_port;
pf.is_remote = false;
pf.web_application = true;
vm.port_forwards.push_back(pf);
continue;
}
else if (xp.parse_int("pf_guest_port", vm.pf_guest_port)) continue;
else if (xp.parse_int("pf_host_port", vm.pf_host_port)) continue;
else if (xp.parse_string("copy_to_shared", str)) {
vm.copy_to_shared.push_back(str);
continue;
@ -238,18 +246,12 @@ 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")) {
parse_port_forward(xp, vm);
}
else {
fprintf(stderr, "%s parse_job_file(): unexpected tag %s\n",
vboxwrapper_msg_prefix(buf, sizeof(buf)), xp.parsed_tag
);
parse_port_forward(vm, xp);
}
fprintf(stderr, "%s parse_job_file(): unexpected tag %s\n",
vboxwrapper_msg_prefix(buf, sizeof(buf)), xp.parsed_tag
);
}
fclose(f);
return ERR_XML_PARSE;
@ -335,29 +337,6 @@ 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) {
@ -446,14 +425,9 @@ void set_web_graphics_url(VBOX_VM& vm) {
char buf[256];
for (unsigned int i=0; i<vm.port_forwards.size(); i++) {
PORT_FORWARD& pf = vm.port_forwards[i];
if (pf.web_application) {
if (pf.guest_port == vm.pf_guest_port) {
sprintf(buf, "http://localhost:%d", pf.host_port);
boinc_web_graphics_url(buf);
fprintf(stderr, "%s Detected: Web Application Enabled (%s)\n",
vboxwrapper_msg_prefix(buf, sizeof(buf)), buf
);
break;
}
}
@ -616,7 +590,6 @@ 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];
@ -964,6 +937,7 @@ 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 =
@ -1140,6 +1114,7 @@ int main(int argc, char** argv) {
}
set_floppy_image(aid, vm);
//set_port_forwarding_info(aid, vm);
set_web_graphics_url(vm);
set_remote_desktop_info(aid, vm);
write_checkpoint(elapsed_time, current_cpu_time, vm);
@ -1189,30 +1164,6 @@ 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()) {

View File

@ -27,21 +27,25 @@
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<UseOfAtl>Static</UseOfAtl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<UseOfAtl>Static</UseOfAtl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<UseOfAtl>Static</UseOfAtl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<UseOfAtl>Static</UseOfAtl>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -89,10 +93,6 @@
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vboxwrapper_26108_windows_intelx86</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vboxwrapper_26110_windows_intelx86</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">vboxwrapper_26108_windows_x86_64</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">vboxwrapper_26110_windows_x86_64</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
@ -132,13 +132,13 @@
<AdditionalIncludeDirectories>..\..\boinc_depends_win_vs2010\wxwidgets\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libcmt.lib;libcpmt.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;wsock32.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\$(TargetFileName)</OutputFile>
<AdditionalDependencies>libcmt.lib;libcpmt.lib;atls.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;wsock32.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_26108_windows_intelx86.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\$(TargetName).pdb</ProgramDatabaseFile>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_26108_windows_intelx86.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
@ -182,13 +182,13 @@
<AdditionalIncludeDirectories>..\..\boinc_depends_win_vs2010\wxwidgets\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libcmt.lib;libcpmt.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;wsock32.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\$(TargetFileName)</OutputFile>
<AdditionalDependencies>libcmt.lib;libcpmt.lib;atls.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;wsock32.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_26108_windows_x86_64.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\$(TargetName).pdb</ProgramDatabaseFile>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_26108_windows_x86_64.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
@ -228,13 +228,13 @@
<AdditionalIncludeDirectories>..\..\boinc_depends_win_vs2010\wxwidgets\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libcmtd.lib;libcpmtd.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;psapi.lib;wsock32.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\$(TargetFileName)</OutputFile>
<AdditionalDependencies>libcmtd.lib;libcpmtd.lib;atlsd.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;psapi.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_6.1_windows_intelx86.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\$(TargetName).pdb</ProgramDatabaseFile>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_6.1_windows_intelx86.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
@ -274,13 +274,13 @@
<AdditionalIncludeDirectories>..\..\boinc_depends_win_vs2010\wxwidgets\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libcmtd.lib;libcpmtd.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;wsock32.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\$(TargetFileName)</OutputFile>
<AdditionalDependencies>libcmtd.lib;libcpmtd.lib;atlsd.lib;kernel32.lib;user32.lib;gdi32.lib;ole32.lib;wsock32.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_26063_windows_x86_64.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\$(TargetName).pdb</ProgramDatabaseFile>
<ProgramDatabaseFile>.\Build\$(Platform)\$(Configuration)\vboxwrapper_26063_windows_x86_64.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
@ -298,6 +298,7 @@
<ClInclude Include="..\samples\vboxwrapper\vbox.h" />
<ClInclude Include="..\samples\vboxwrapper\vboxwrapper.h" />
<ClInclude Include="..\samples\vboxwrapper\vboxwrapper_win.h" />
<ClInclude Include="..\samples\vboxwrapper\vbox_win.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libboincapi_staticcrt.vcxproj">