[[PageOutline]]
= Running apps in VirtualBox virtual machines =
== Introduction ==
BOINC supports "VM apps" - applications that run in !VirtualBox virtual machines.
This provides several benefits:
* You don't need to build app versions for different platforms.
You can develop your app in your environment of choice (say, Debian Linux),
and then bundle the resulting executable with
a virtual machine image containing an appropriate runtime environment.
The application can then be run on all platforms
(Windows, Mac OS X, all versions of Linux)
with no additional work on your part.
* Virtual machines provide the strongest available security sandbox;
a VM app cannot access or modify the host system.
This makes it feasible to deploy untrusted applications.
* VM apps don't need to have their own checkpoint/restart mechanism;
BOINC provides one.
VM apps have the following limitations:
* Commercial operating systems like Windows and Mac OS X
have a per-user license, so in general you can't use them
(or other pay-per-user software such as Matlab) in the VM image.
* !VirtualBox runs only on Intel-compatible processors.
If you want to support other processors (such as ARM, SPARC, etc.),
you'll need to use non-VM app versions.
* Currently you can't run GPU applications in !VirtualBox VMs.
=== 32/64 bit issues ===
A VM image is called 32- or 64-bit depending on the operating system it contains.
The BOINC host population includes 32-bit and 64-bit hosts.
64-bit hosts can run 32-bit VMs, but not conversely.
You can choose to provide 32- or 64-bit VM images, or both.
Possible reasons for using 64-bit VM images:
* The 64-bit version of your app runs significantly faster than the 32-bit version.
* Your app uses more than 3 GB of virtual address space.
If you provide only 32-bit VM images,
you must still create separate 32- and 64-bit app versions,
using the same VM image but different '''vboxwrapper''' executables.
'''vboxwrapper''', supplied by BOINC, interfaces between the BOINC client and the !VirtualBox system;
it's a C++ program and has different executables
for each platform, include 32- and 64-bit; these are available below.
The 32-bit vboxwrapper will generally not work on a 64-bit machine.
=== Packaging options ===
There are two ways to package VM apps.
NOTE: in the following, we use '''application''' and '''application version'''
with their [AppVersion BOINC-specific meanings];
we'll use '''executable''' to refer to the program that runs within the VM.
* '''Single-purpose app''': Include the executable with the application version.
Create a separate application for each executable you want to run.
* '''Multi-purpose app''': Include the executable in each workunit.
This allows you to use a single application for as many executables as you like.
In this case, consider making the executable file
[JobSubmission sticky]; that way, clients will download it only once.
== Creating app versions ==
You must [AppVersionNew create app versions] for each platform you want to support;
the app versions differ in which '''vboxwrapper''' executable they use.
If you use both 32- and 64-bit VMs,
the versions will also differ in the VM image and the application executable.
You must associate a [AppPlan plan class] with each app version,
such as "vbox32" (for 32-bit machines) or "vbox64" (for 64-bit machines).
To enable multiple cores use the plan classes "vbox32_mt" and "vbox64_mt".
By default it will cause the server to assign 2 threads (virtual cores) per VM task.
For single-purpose apps, an app version includes the following files:
* The VM image, in !VirtualBox format.
* Must have logical name "vm_image.vdi".
* Must have the '''copy_file''' attribute.
* Should have the '''gzip''' attribute for faster download to 7.0+ clients.
* The application executable to be run in the VM image.
* This may be a shell script or a binary program.
* The logical name must be '''shared/boinc_app'''.
* Other files needed by the application, all with logical names starting with '''shared/'''.
* An XML '''Vbox job description file''' with logical name '''vbox_job.xml''' (see below)
* '''vboxwrapper''', compiled for the platform (executables are available below).
* All scripts and executables must have the execute permission set.
For multi-purpose apps, any of these files except '''vboxwrapper''' may
be included in the workunit instead of the app version.
Include '''''' in the [AppVersionNew#Theversiondescriptionfile version.xml file];
!VirtualBox does its own CPU throttling.
Typically you can use the same VM image for multiple applications.
This reduces network traffic and client disk usage.
=== The Vbox job description file ===
The VBox job description file has logical name '''vbox_job.xml'''
(its physical name should include a version number and other info).
It has following structure:
{{{
N
name
[ filename ]
[ filename ]
[ 0|1 ]
[ 0|1 ]
[ 0|1 ]
[ 0|1 ]
[ ]
[ 0|1 ]
[ ]
[ ]
[ filename ]
[ X ]
[ N ]
[ ]
[ N ]
[
H
G
[0|1]
[N ]
[ filename ]
[ LSILogic|LSILogicSAS|BusLogic|IntelAHCI|PIIX3|PIIX4|ICH6|I82078 ]
[ ide|sata|scsi|floppy|sas ]
}}}
Required elements:
'''memory_size_mb''':: the amount of physical memory allocated to the VM, in megabytes.
'''os_name''':: the name of the guest OS as defined by !VirtualBox,
e.g. "Linux26", "Linux26_64", "Linux24", etc.
To see a list of all available OS names, install !VirtualBox on a system,
and type "vboxmanage list ostypes".
Optional elements:
'''completion_trigger_file'''::
This provides a more bulletproof way for VM apps to exit;
sometimes VMs fail to shut down, and the task hangs indefinitely.
When the VM app is done, it writes a file of this name in the shared directory;
the file can optionally contain an integer exit code (first line) a bool value
for whether it should bubble up to the volunteer (second line)
and stderr text (subsequent lines).
If vboxwrapper finds this file,
it cleans up the VM and exits with the given code (default 0).
'''copy_to_shared''':: copy the given file from the slot directory the shared directory before launch.
For example, you can use to copy '''init_data.xml''' into the VM.
This directive can be used more than once.
'''enable_cache_disk''':: Mount a virtual disk in the VM.
The virtual disk is described by a VDI file in the app version
with logical name '''vm_cache.vdi''' and the '''copy_file''' attribute.
'''enable_cern_dataformat''':: if '''enable_floppyio''' is used (see below)
initialize the floppy disk image to contain user and host ID and credit
as name=value pairs.
'''enable_isocontextualization''':: the VM image is an ISO file named '''vm_isocontext.iso''',
rather than a VDI file.
Also, vboxwrapper will mount the host's guest additions ISO (VBoxGuestAdditions.iso)
as a DVD in the VM.
'''enable_floppyio''':: create a floppy disk image in the VM,
containing the contents of init_data.xml.
'''enable_network''':: if present, allow the VM to do network access.
'''enable_remotedesktop''':: If the Oracle VirtualBox Extension are installed, it'll enable
the use of a remote desktop client to view the console of the VM.
'''enable_shared_directory''':: if present, create a directory that is shared
between the host OS and the guest OS.
Must be set if your application has input or output files.
'''enable_graphics_support''':: if present, creates and updates a [BasicApi#GraphicsStatus graphics status] file.
This is used by [http://boinc.berkeley.edu/trac/wiki/HTMLGfx HTMLGfx]. (v26155+)
'''fraction_done_filename''':: the name of a file to which the app will
periodically write its fraction done (0 to 1).
This is used by the wrapper to report overall fraction done.
'''intermediate_upload_file'''::: specifies the name of an output file that,
when present, should be uploaded as soon as possible.
'''job_duration''':: this specifies the maximum elapsed time of the job,
after which vboxwrapper will kill the VM and exit normally.
'''minimum_checkpoint_interval''':: minimum number of seconds before a checkpoint/snapshot can be created.
Defaults to 10 minutes. (v26086+)
'''network_bridged_mode''':: if '''enable_network''' is set, use bridged mode; default is NAT mode.
'''pf_guest_port''':: enable port forwarding to port N within the VM.
This is assumed to be a web server providing application graphics.
'''port_forward''':: defines a port forwarding between the given host and guest ports.
If '''nports''' is specified, N ports will be forwarded:
H to G, H+1 to G+1, ... H+N-1 to G+N-1.
If '''is_remote''' is set, the host ports can be accessed from other computers;
otherwise they can be accessed only from processes on this computer.
There may be more than one of these elements.
'''temporary_exit_trigger_file''':: specifies the name of a file that, if present,
causes the wrapper to temporarily exit.
'''trickle_trigger_file''':: provides a mechanism for the VM to send trickle-up messages.
If a file of the given name appears in the shared directory,
vboxwrapper sends a [TrickleApi trickle-up message] whose variety is the filename
and whose contents is the contents of the file, then deletes the file.
'''vm_disk_controller_model''':: which disk controller model to emulate.
'''vm_disk_controller_type''':: which disk controller type to emulate.
== Vboxwrapper command-line options ==
--trickle X :: Send a trickle message reporting elapsed time every X seconds.
Use might this for incremental credit granting,
or as a "heartbeat" mechanism.
-- nthreads N :: Create a virtual machine that will use N cores.
--vmimage N:: Use '''vm_image_N.vdi''' as the VM image, rather than '''vm_image.vdi'''.
This lets you create an app version with several images,
and the app_plan function can decide which one to use for the particular host.
-- register_only :: Register the VM but don't run it. For debugging; see below.
== Creating jobs for VM apps ==
The input and output files of a VM app must
* Have logical names starting with '''shared/'''.
* Have the '''copy_file''' attribute.
This causes the BOINC client to copy them to and from the '''slot/x/shared/''' directory.
== Debugging VM apps ==
To debug a VM within the BOINC/VboxWrapper framework:
* Launch BOINC with --exit_before_start
* When BOINC exits, launch vboxwrapper with the --register_only option.
* Set the VBOX_USER_HOME environment variable to the vbox directory
under the slot directory.
This changes where the VirtualBox applications look for the
root VirtualBox configuration files.
It may or may not apply to your installation of VirtualBox.
It depends on where your copy of VirtualBox came from
and what type of system it is installed on.
* Now Launch the VM using the VirtualBox UI.
You should now be able to interact with your VM.
=== Debugging Guest VM scripts ===
To debug what is going on within the guest VM you can use '''vboxmonitor''' which writes whatever
is received in stdin to the VM guest log (VBox.log).
This in turn is read and rewritten to stderr.txt in the slot directory by '''vboxwrapper'''.
To use you must either use the premade vboxmonitor or build your own.
Once on the guest VM you must execute setuid on it so that it runs with root permissions.
Usage:
{{{
[root@localhost vboxmonitor]# echo this is a test | ./vboxmonitor
this is a test
}}}
Log Output:
{{{
01:08:57.938896 Guest Log: this is a test
}}}
Usage:
{{{
[root@localhost vboxmonitor]# ls -la ../vboxwrapper | ./vboxmonitor
total 37052
drwxrwxr-x 5 boincadm boincadm 4096 Jun 2 12:36 .
drwxrwxr-x 18 boincadm boincadm 4096 Oct 3 2013 ..
-rw-rw-r-- 1 boincadm boincadm 3831 Apr 24 2013 BuildMacVboxWrapper.sh
drwxrwxr-x 2 boincadm boincadm 4096 Apr 24 2013 cernvm
drwxrwxr-x 3 boincadm boincadm 4096 Apr 24 2013 deprecated
-rw-rw-r-- 1 boincadm boincadm 11585 Apr 24 2013 floppyio.cpp
-rw-rw-r-- 1 boincadm boincadm 5910 Apr 24 2013 floppyio.h
-rw-rw-r-- 1 boincadm boincadm 71444 May 21 20:01 floppyio.o
lrwxrwxrwx 1 boincadm boincadm 48 May 21 20:01 libstdc++.a -> /usr/lib/gcc/i386-redhat-linux/4.1.2/libstdc++.a
-rw-rw-r-- 1 boincadm boincadm 927 May 29 2013 Makefile
-rw-rw-r-- 1 boincadm boincadm 1135 Apr 24 2013 Makefile_mac
-rw-rw-r-- 1 boincadm boincadm 90494 Jun 2 12:33 vbox.cpp
-rw-rw-r-- 1 boincadm boincadm 7573 Jun 2 12:33 vbox.h
-rw-rw-r-- 1 boincadm boincadm 249892 Jun 2 12:35 vbox.o
-rw-rw-r-- 1 boincadm boincadm 43848 Jun 2 12:33 vboxwrapper.cpp
-rw-rw-r-- 1 boincadm boincadm 1458 Dec 9 19:21 vboxwrapper.h
-rw-rw-r-- 1 boincadm boincadm 178548 Jun 2 12:35 vboxwrapper.o
-rw-rw-r-- 1 boincadm boincadm 438 May 21 19:56 vboxwrapper_win.h
-rw-rw-r-- 1 boincadm boincadm 2127 May 21 19:56 vboxwrapper_win.rc
drwxrwxr-x 2 boincadm boincadm 4096 Apr 24 2013 vboxwrapper.xcodeproj
}}}
Log Output:
{{{
01:09:25.148427 Guest Log: total 37052
01:09:25.148762 Guest Log: drwxrwxr-x 5 boincadm boincadm 4096 Jun 2 12:36 .
01:09:25.149071 Guest Log: drwxrwxr-x 18 boincadm boincadm 4096 Oct 3 2013 ..
01:09:25.149445 Guest Log: -rw-rw-r-- 1 boincadm boincadm 3831 Apr 24 2013 BuildMacVboxWrapper.sh
01:09:25.149729 Guest Log: drwxrwxr-x 2 boincadm boincadm 4096 Apr 24 2013 cernvm
01:09:25.150070 Guest Log: drwxrwxr-x 3 boincadm boincadm 4096 Apr 24 2013 deprecated
01:09:25.150374 Guest Log: -rw-rw-r-- 1 boincadm boincadm 11585 Apr 24 2013 floppyio.cpp
01:09:25.150700 Guest Log: -rw-rw-r-- 1 boincadm boincadm 5910 Apr 24 2013 floppyio.h
01:09:25.151029 Guest Log: -rw-rw-r-- 1 boincadm boincadm 71444 May 21 20:01 floppyio.o
01:09:25.151573 Guest Log: lrwxrwxrwx 1 boincadm boincadm 48 May 21 20:01 libstdc++.a -> /usr/lib/gcc/i386-redhat-linux/4.1.2/libstdc++.a
01:09:25.151864 Guest Log: -rw-rw-r-- 1 boincadm boincadm 927 May 29 2013 Makefile
01:09:25.152190 Guest Log: -rw-rw-r-- 1 boincadm boincadm 1135 Apr 24 2013 Makefile_mac
01:09:25.152476 Guest Log: -rw-rw-r-- 1 boincadm boincadm 90494 Jun 2 12:33 vbox.cpp
01:09:25.152757 Guest Log: -rw-rw-r-- 1 boincadm boincadm 7573 Jun 2 12:33 vbox.h
01:09:25.153045 Guest Log: -rw-rw-r-- 1 boincadm boincadm 249892 Jun 2 12:35 vbox.o
01:09:25.199092 Guest Log: -rw-rw-r-- 1 boincadm boincadm 43848 Jun 2 12:33 vboxwrapper.cpp
01:09:25.199479 Guest Log: -rw-rw-r-- 1 boincadm boincadm 1458 Dec 9 19:21 vboxwrapper.h
01:09:25.199806 Guest Log: -rw-rw-r-- 1 boincadm boincadm 178548 Jun 2 12:35 vboxwrapper.o
01:09:25.200147 Guest Log: -rw-rw-r-- 1 boincadm boincadm 438 May 21 19:56 vboxwrapper_win.h
01:09:25.200490 Guest Log: -rw-rw-r-- 1 boincadm boincadm 2127 May 21 19:56 vboxwrapper_win.rc
01:09:25.201024 Guest Log: drwxrwxr-x 2 boincadm boincadm 4096 Apr 24 2013 vboxwrapper.xcodeproj
}}}
== Premade vboxwrapper executables ==
Windows:
x86: [http://boinc.berkeley.edu/dl/vboxwrapper_26175_windows_intelx86.zip vboxwrapper_26175_windows_intelx86.zip]
x64: [http://boinc.berkeley.edu/dl/vboxwrapper_26175_windows_x86_64.zip vboxwrapper_26175_windows_x86_64.zip]
Mac OS X:
x86: [http://boinc.berkeley.edu/dl/vboxwrapper_26175_i686-apple-darwin.zip vboxwrapper_26175_i686-apple-darwin.zip]
x64: [http://boinc.berkeley.edu/dl/vboxwrapper_26175_x86_64-apple-darwin.zip vboxwrapper_26175_x86_64-apple-darwin.zip]
Linux:
x86: [http://boinc.berkeley.edu/dl/vboxwrapper_26175_i686-pc-linux-gnu.zip vboxwrapper_26175_i686-pc-linux-gnu.zip]
x64: [http://boinc.berkeley.edu/dl/vboxwrapper_26175_x86_64-pc-linux-gnu.zip vboxwrapper_26175_x86_64-pc-linux-gnu.zip]
== Premade vboxmonitor executables ==
Linux:
x86: [http://boinc.berkeley.edu/dl/vboxmonitor_26086_i686-pc-linux-gnu.zip vboxmonitor_26086_i686-pc-linux-gnu.zip]
x64: [http://boinc.berkeley.edu/dl/vboxmonitor_26086_x86_64-pc-linux-gnu.zip vboxmonitor_26086_x86_64-pc-linux-gnu.zip]
== Premade Linux VM Images ==
These VM images were built using the above instructions for creating VM images.
They contain Debian 4.0, without GCC or any build tools installed.
They contain the example startup script.
x86: [http://boinc.berkeley.edu/dl/vmimage_x86.zip vmimage_x86.zip]
x64: [http://boinc.berkeley.edu/dl/vmimage_x64.zip vmimage_x64.zip]
In most cases, you can use these VM images with no modifications.
If your application uses libraries not on the VM images,
you can add them as follows:
* Run !VirtualBox, and open the VM image
* Hit CTRL-C when see "BOINC VM starting" in the console window
* Install whatever you want (can use '''apt-get install''' to
install Debian packages).
* when you're done, type
{{{
shutdown -hP 0
}}}
The VM image now has the additional libraries.
Rename it to avoid confusion with the original version.
== Creating your own VM images ==
=== Requirements of the VM ===
The VM, when booted, must do the following:
* If the applications has input or output files, mount the shared directory using
{{{
mount -t vboxsf shared /root/shared
}}}
where `/root/shared` is the path where the shared directory is to be mounted.
In this case the VM must contain the !VirtualBox "guest additions".
Guest additions are required for shared folders to work.
* Run the application.
* When the application is finished, shut down the VM
(e.g., by running '''shutdown''' on Linux).
These steps are typically done by a '''startup script''' in the VM image.
An example startup script is given below.
This script runs the application by doing the following:
* cd into the shared directory
* execute '''boinc_app''', and wait for it to exit.
Using this script,
your application executable must have logical name '''share/boinc_app'''.
Doing things this way, the VM image is independent of the application.
You can use the a single VM image for many applications.
'''Attention:''' If your '''boinc_app''' is a bash or perl script you may get problems when the VM is restored from a snapshot.
To circumvent this you have to change your startup script to copy the contents of the shared/ directory
to another directory 'inside' the VM and execute it there.
For example:
{{{
echo -- Launching boinc_app
if [ -f /root/shared/boinc_app ]; then
mkdir /root/worker
cp -r /root/shared/* /root/worker/
cd /root/worker/
./boinc_app
cd /root/
rm -rf /root/worker
shutdown -hP 0
else
}}}
This way you can still reuse the VM for other applications but have to make sure
that your '''boinc_app''' control script is copying the output files of the application to ´/root/shared/´ before exiting.
This may take some time, so you should do something like:
{{{
cp outfile1.zip /root/shared/out1.zip.tmp
cp outfile2.zip /root/shared/out2.zip.tmp
{...}
mv /root/shared/out1.zip.tmp /root/shared/out1.zip
mv /root/shared/out2.zip.tmp /root/shared/out2.zip
}}}
=== Example startup script ===
The example startup script follows.
You can deploy it by appending to '''/root/.bashrc''' in the VM image.
{{{
echo --- BOINC VM starting
sleep 5
}}}
The "sleep 5" gives you time to break into a console session via CTRL-C
if you need to make changes to the VM in the future.
{{{
echo --- Mounting shared directory
mount -t vboxsf shared /root/shared
if [ $? -ne 0 ]; then
echo --- Failed to mount shared directory
sleep 5
shutdown -hP 0
fi
echo -- Launching boinc_app
if [ -f /root/shared/boinc_app ]; then
cd /root/shared
./boinc_app
shutdown -hP 0
else
echo --- Failed to launch script
sleep 5
fi
shutdown -hP 0
}}}
=== How it works ===
Using the example startup script, the steps in running a vboxwrapper app are:
1. BOINC client
* Create slot directory, say `slot/0`
* Create '''slot/0/shared''', and copy input files there
* Execute '''vboxwrapper''' in the slot directory
1. vboxwrapper
* Create and run virtual machine
1. Virtual machine
* Startup script
* mounts '''shared''' directory
* cd into shared directory
* execute boinc_app
* when boinc_app exits, shut down virtual machine
1. vboxwrapper
* delete virtual machine
* call boinc_finish()
1. BOINC client
* copy output files from `slot/0/shared` to project directory
=== Creating base VM images ===
The VM image that you distribute need contain only the
runtime environment for your applications.
In particular, it need not contain:
* Development tools such as gcc
* GUI software such as X11, gtk etc.
Reducing the VM image size reduces the network load
on your server and on volunteer hosts, and the disk usage on volunteer hosts.
The easiest way to make a "small" Linux VM is to install the network install of Debian within the VM.
You can find the netinst images [http://www.debian.org/distrib/netinst here].
Such VMs have !VirtualBox and guest additions installed by default.
They have the runtime libraries needed to run C and C++ applications.
==== Role Selection ====
During install you'll be asked what role should this Linux machine be configured for.
Make sure all roles are unselected before continuing.
==== Cleaning the Debian VM ====
First step is to remove non-critical packages that are essential ([https://wiki.debian.org/ReduceDebian source]).
For Debian Wheezy 7.6 that are:
{{{
acpi acpid busybox debconf-i18n eject groff-base iamerican ibritish info ispell laptop-detect logrotate installation-report manpages man-db net-tools os-prober rsyslog tasksel tasksel-data traceroute usbutils wamerican
}}}
Use aptitude to also remove `linux-headers-*` packages but don't remove `dkms` or `virtualbox-guest-dkms`! Run `apt-get autoremove` after this to get rid of now unused packages. `apt-get autoclean` and `apt-get clean` should remove downloaded archives to free up space.
In order to really purge all files from previously removed packages this command is helpful
as it purges all configuration files from uninstalled packages:
{{{
dpkg --purge `dpkg --get-selections | grep deinstall | cut -f1`
}}}
Now, we can remove the contents of the following folders:
1. /usr/share/locale/ - since we don't need all locales.
2. /usr/share/doc/ - since we don't need the documentation.
3. /usr/share/man/ - since we don't need the manuals and we've removed the man program.
4. /var/log/ - since we won't be needing all that logging.
5. /var/cache/debconf/ - since that cache is disposable.
6. /var/lib/apt/lists/ - since those lists are huge and can quickly be recreated with apt-get update.
==== Updating Grub ====
If you want to speed up the boot process,
change the default timeout for grub by modifying `/etc/default/grub`:
{{{
GRUB_TIMEOUT = 0
}}}
After saving the update run:
{{{
update-grub
}}}
==== Updating Inittab ====
To configure Linux for automatic login you'll need to install a different terminal handler.
mingetty works well for our purposes.
To install mingetty:
{{{
root@boinc-vm-image:/etc/default# apt-get install mingetty
}}}
Next you'll need to change the terminal handler assigned to the first virtual terminal by modifying `/etc/inittab`.
Change line:
{{{
1:2345:respawn:/sbin/getty 38400 tty1
}}}
To:
{{{
1:2345:respawn:/sbin/mingetty --autologin root --noclear tty1
}}}
==== Disabling periodic fsck ====
This will disable the periodic fsck run that occurs every 30 times the VM is turned on: `tune2fs -c -1 /dev/sda1`.
==== Compact the VDI container ====
To get a better compression ratio you may install and run the '''zerofree''' tool
to overwrite all empty space on the VDI with zeros.
{{{
apt-get install zerofree
telinit 1
{enter root password}
mount -o remount,ro /dev/sda1
zerofree -v /dev/sda1
shutdown -hP 0
}}}
Now open a terminal on the host System and compact the VDI file:
{{{
vboxmanage modifyhd FILENAME.vdi --compact
}}}
== Runtime State Information ==
TODO - EXPLAIN THE FOLLOWING
=== WebAPI state file ===
The state file has the name of '''vbox_webapi.xml'''.
It has following structure:
{{{
X
}}}
Required elements:
'''host_port'''::
The port, if configured for it, vboxwrapper has assigned to the task for WebAPI requests.
(HTTP, XML-RPC, JSON)
=== Remote Desktop state file ===
The state file has the name of '''vbox_remote_desktop.xml'''.
It has following structure:
{{{
X
}}}
Required elements:
'''host_port'''::
The port, if configured for it, vboxwrapper has assigned to the task for Remote Desktop requests. (RDP)