- VBOX: Enable remote desktop functionality for a VM that has

<enable_remotedesktop/> specified in its vbox_job.xml file.
        
      NOTE: It does require the VirtualBox extension pack, but that
        is freely available on the VirtualBox download page.
        
    samples/vboxwrapper
        vbox.cpp, .h
        vboxwrapper.cpp, .h

svn path=/trunk/boinc/; revision=25034
This commit is contained in:
Rom Walton 2012-01-12 15:54:28 +00:00
parent d4a91e5877
commit fea602b6e6
5 changed files with 237 additions and 148 deletions

View File

@ -391,3 +391,14 @@ David 12 Jan 2012
boinc_db.inc
user/
lammps.php
Rom 12 Jan 2012
- VBOX: Enable remote desktop functionality for a VM that has
<enable_remotedesktop/> specified in its vbox_job.xml file.
NOTE: It does require the VirtualBox extension pack, but that
is freely available on the VirtualBox download page.
samples/vboxwrapper
vbox.cpp, .h
vboxwrapper.cpp, .h

View File

@ -648,6 +648,35 @@ int VBOX_VM::get_port_forwarding_port() {
return 0;
}
int VBOX_VM::get_remote_desktop_port() {
struct sockaddr_in addr;
BOINC_SOCKLEN_T addrsize;
int sock;
int retval;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addrsize = sizeof(addr);
retval = boinc_socket(sock);
if (retval) return retval;
retval = bind(sock, (struct sockaddr *)&addr, addrsize);
if (retval < 0) {
boinc_close_socket(sock);
return ERR_BIND;
}
getsockname(sock, (struct sockaddr *)&addr, &addrsize);
rd_host_port = addr.sin_port;
boinc_close_socket(sock);
return 0;
}
int VBOX_VM::register_vm() {
string command;
string output;
@ -839,18 +868,55 @@ int VBOX_VM::register_vm() {
//
if (enable_network) {
set_network_access(true);
// If the VM wants to open up a port through the VirtualBox virtual
// network firewall/nat do that here.
//
if (pf_guest_port) {
if (!pf_host_port) {
retval = get_port_forwarding_port();
if (retval) return retval;
}
fprintf(
stderr,
"%s Enabling virtual machine firewall rules.\n",
boinc_msg_prefix(buf, sizeof(buf))
);
// Add new firewall rule
//
sprintf(buf, "vboxwrapper,tcp,127.0.0.1,%d,,%d", pf_host_port, pf_guest_port);
command = "modifyvm \"" + vm_name + "\" ";
command += "--natpf1 \"" + string(buf) + "\" ";
retval = vbm_popen(command, output, "add updated port forwarding rule");
if(retval) return retval;
}
}
// If the app wants to open up a port through the VirtualBox virtual
// network firewall/nat do that here.
// If the VM wants to enable remote desktop for the VM do it here
//
if (pf_guest_port) {
if (!pf_host_port) {
retval = get_port_forwarding_port();
if (retval) return retval;
}
retval = register_vm_firewall_rules();
if (enable_remotedesktop) {
retval = get_remote_desktop_port();
if (retval) return retval;
fprintf(
stderr,
"%s Enabling remote desktop for virtual machine.\n",
boinc_msg_prefix(buf, sizeof(buf))
);
sprintf(buf, "%d", rd_host_port);
command = "modifyvm \"" + vm_name + "\" ";
command += "--vrde on ";
command += "--vrdeextpack default ";
command += "--vrdeauthlibrary default ";
command += "--vrdeauthtype null ";
command += "--vrdeport " + string(buf) + " ";
retval = vbm_popen(command, output, "remote desktop");
if(retval) return retval;
}
// Enable the shared folder if a shared folder is specified.
@ -872,33 +938,6 @@ int VBOX_VM::register_vm() {
return 0;
}
int VBOX_VM::register_vm_firewall_rules() {
string command;
string output;
string virtual_machine_slot_directory;
char buf[256];
int retval;
get_slot_directory(virtual_machine_slot_directory);
fprintf(
stderr,
"%s Registering virtual machine firewall rules.\n",
boinc_msg_prefix(buf, sizeof(buf))
);
// Add new firewall rule
//
sprintf(buf, "vboxwrapper,tcp,127.0.0.1,%d,,%d", pf_host_port, pf_guest_port);
command = "modifyvm \"" + vm_name + "\" ";
command += "--natpf1 \"" + string(buf) + "\" ";
retval = vbm_popen(command, output, "add updated port forwarding rule");
if(retval) return retval;
return 0;
}
int VBOX_VM::deregister_vm() {
string command;
string output;

View File

@ -1,114 +1,119 @@
// This file is part of BOINC.
// http://boinc.berkeley.edu
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2010-2012 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Provide cross-platform interfaces for making changes to VirtualBox
#ifndef _VBOX_H_
#define _VBOX_H_
// raw floppy drive device
class FloppyIO;
// represents a VirtualBox VM
struct VBOX_VM {
VBOX_VM();
~VBOX_VM();
// Floppy IO abstraction
FloppyIO* pFloppy;
// name of the OS the VM runs
std::string os_name;
// size of the memory allocation for the VM, in megabytes
std::string memory_size_mb;
// name of the virtual machine disk image file
std::string image_filename;
// name of the virtual machine floppy disk image file
std::string floppy_image_filename;
// unique name for the VM
std::string vm_name;
// required CPU core count
std::string vm_cpu_count;
// maximum amount of wall-clock time this VM is allowed to run before
// considering itself done.
double job_duration;
// is the VM suspended?
bool suspended;
// is network access temporarily suspended?
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
bool enable_shared_directory;
// whether to use floppy io infrastructure at all
bool enable_floppyio;
// whether we were instructed to only register the VM.
// useful for debugging VMs.
bool register_only;
// whether to allow network access at all
bool enable_network;
// the following for optional port forwarding
int pf_host_port;
// specified in config file
int pf_guest_port;
// specified in config file
int run();
int stop();
int pause();
int resume();
void cleanup();
void poll(bool log_state = true);
bool is_running();
bool is_paused();
int register_vm();
int register_vm_firewall_rules();
bool is_hdd_registered();
bool is_registered();
int deregister_stale_vm();
int deregister_vm();
int start();
int set_network_access(bool enabled);
int set_cpu_usage_fraction(double);
int set_network_max_bytes_sec(double);
int get_process_id(int& process_id);
int get_network_bytes_sent(double& sent);
int get_network_bytes_received(double& received);
int get_system_log(std::string& log);
int get_vm_log(std::string& log);
int read_floppy(std::string& data);
int write_floppy(std::string& data);
int get_port_forwarding_port();
int initialize();
int get_install_directory(std::string& dir);
int get_slot_directory(std::string& dir);
int vbm_popen(
std::string& command, std::string& output, const char* item, bool log_error = true, bool retry_failures = true
);
int vbm_popen_raw(
std::string& command, std::string& output
);
};
#endif
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Provide cross-platform interfaces for making changes to VirtualBox
#ifndef _VBOX_H_
#define _VBOX_H_
// raw floppy drive device
class FloppyIO;
// represents a VirtualBox VM
struct VBOX_VM {
VBOX_VM();
~VBOX_VM();
// Floppy IO abstraction
FloppyIO* pFloppy;
// name of the OS the VM runs
std::string os_name;
// size of the memory allocation for the VM, in megabytes
std::string memory_size_mb;
// name of the virtual machine disk image file
std::string image_filename;
// name of the virtual machine floppy disk image file
std::string floppy_image_filename;
// unique name for the VM
std::string vm_name;
// required CPU core count
std::string vm_cpu_count;
// maximum amount of wall-clock time this VM is allowed to run before
// considering itself done.
double job_duration;
// is the VM suspended?
bool suspended;
// is network access temporarily suspended?
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
bool enable_shared_directory;
// whether to use floppy io infrastructure at all
bool enable_floppyio;
// whether to enable remote desktop functionality
bool enable_remotedesktop;
// whether we were instructed to only register the VM.
// useful for debugging VMs.
bool register_only;
// whether to allow network access at all
bool enable_network;
// the following for optional port forwarding
int pf_host_port;
// specified in config file
int pf_guest_port;
// specified in config file
// the following for optional remote desktop
int rd_host_port;
// dynamically assigned
int run();
int stop();
int pause();
int resume();
void cleanup();
void poll(bool log_state = true);
bool is_running();
bool is_paused();
int register_vm();
bool is_hdd_registered();
bool is_registered();
int deregister_stale_vm();
int deregister_vm();
int start();
int set_network_access(bool enabled);
int set_cpu_usage_fraction(double);
int set_network_max_bytes_sec(double);
int get_process_id(int& process_id);
int get_network_bytes_sent(double& sent);
int get_network_bytes_received(double& received);
int get_system_log(std::string& log);
int get_vm_log(std::string& log);
int read_floppy(std::string& data);
int write_floppy(std::string& data);
int get_port_forwarding_port();
int get_remote_desktop_port();
int initialize();
int get_install_directory(std::string& dir);
int get_slot_directory(std::string& dir);
int vbm_popen(
std::string& command, std::string& output, const char* item, bool log_error = true, bool retry_failures = true
);
int vbm_popen_raw(
std::string& command, std::string& output
);
};
#endif

View File

@ -109,6 +109,7 @@ int parse_job_file(VBOX_VM& vm) {
else if (xp.parse_bool("enable_network", vm.enable_network)) continue;
else if (xp.parse_bool("enable_shared_directory", vm.enable_shared_directory)) continue;
else if (xp.parse_bool("enable_floppyio", vm.enable_floppyio)) continue;
else if (xp.parse_bool("enable_remotedesktop", vm.enable_remotedesktop)) 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;
fprintf(stderr, "%s parse_job_file(): unexpected tag %s\n",
@ -238,6 +239,37 @@ void set_port_forwarding_info(APP_INIT_DATA& /* aid */, VBOX_VM& vm) {
}
}
// set remote desktop information if needed
//
void set_remote_desktop_info(APP_INIT_DATA& /* aid */, VBOX_VM& vm) {
char buf[256];
if (vm.rd_host_port) {
fprintf(
stderr,
"%s remote desktop enabled on port '%d'.\n",
boinc_msg_prefix(buf, sizeof(buf)), vm.rd_host_port
);
// Write info to disk
//
MIOFILE mf;
FILE* f = boinc_fopen(REMOTEDESKTOP_FILENAME, "w");
mf.init_file(f);
mf.printf(
"<remote_desktop>\n"
" <rule>\n"
" <host_port>%d</host_port>\n"
" </rule>\n"
"</remote_desktop>\n",
vm.rd_host_port
);
fclose(f);
}
}
int main(int argc, char** argv) {
int retval;
BOINC_OPTIONS boinc_options;
@ -446,6 +478,7 @@ int main(int argc, char** argv) {
set_floppy_image(aid, vm);
set_port_forwarding_info(aid, vm);
set_remote_desktop_info(aid, vm);
set_throttles(aid, vm);
while (1) {

View File

@ -29,6 +29,7 @@
#define JOB_FILENAME "vbox_job.xml"
#define CHECKPOINT_FILENAME "vbox_checkpoint.txt"
#define PORTFORWARD_FILENAME "vbox_port_forward.xml"
#define REMOTEDESKTOP_FILENAME "vbox_remote_desktop.xml"
#define POLL_PERIOD 1.0
#endif