Remote Dektop with GPU Acceleration (Admin Guide)

From HPC Wiki
Admin Guide Remote Dektop with GPU Acceleration
Jump to: navigation, search

Using GPUs for remote hardware acceleration

The goal is to enable HPC users to use hardware acceleration on GPU equipped compute nodes in an interactive environment.

TurboVNC + VirtualGL

  • TurboVNC functions as a high-speed virtual X server
  • VirtualGL adds hardware-accelerated OpenGL to TurboVNC

Example Setup (from an xcat postscript, modify to your needs)

yum install -y xorg-x11-server-Xorg

# INSTALL DRIVERS FROM BINARY (current centos 7.7 nvidia rpms do not run well with GTX2080Ti cards)
NVIDIA-Linux-x86_64-440.59.run -q --ui=none --install-libglvnd

# Configure X for VirtualGL
nvidia-xconfig -a --allow-empty-initial-configuration --virtual=1920x1200

# Unload nvidia drivers
modprobe -r nvidia_drm
modprobe -r nvidia_uvm

# Install VirtualGL
yum install -y VirtualGL-2.6.3.x86_64.rpm

# Configure VirtualGL (with these flags very unsecure!)
/opt/VirtualGL/bin/vglserver_config -config +s +f +t

# Load back nvidia drivers
modprobe nvidia_drm
modprobe nvidia_uvm

# Enabling Persistence Mode
nvidia-smi -pm 1

# Für constant clock frequencies
nvidia-smi -acp UNRESTRICTED

# Start an X server to handle 3D OpenGL rendering
nohup Xorg :0 > /root/xorg.0.log &

# Install WM, menubar, filemanager, terminal
yum install -y openbox
yum install -y tint2
yum install -y caja adwaita-gtk2-theme mate-terminal caja-open-terminal

# get custom config files
cp /Applic.HPC/visualisierung/vis-gpu/openbox/menu.xml /etc/xdg/openbox/menu.xml
cp /Applic.HPC/visualisierung/vis-gpu/openbox/rc.xml /etc/xdg/openbox/rc.xml
cp /Applic.HPC/visualisierung/vis-gpu/openbox/open_scratch.py /etc/xdg/openbox/open_scratch.py
cp /Applic.HPC/visualisierung/vis-gpu/tint2rc /etc/xdg/tint2/tint2rc

Desktop Environment

Try to keep the overall installed software for a functioning Desktop environment as minimal as possible. We went with a combination of:

  • Openbox Window Manager
  • tint2 menubar

and customized those for our needs. Copy customized config files to the nodes on startup:

  • Tint2:
tint2rc
#---- Generated by tint2conf 6517 ----
# See https://gitlab.com/o9000/tint2/wikis/Configure for 
# full documentation of the configuration options.
#-------------------------------------
# Gradients
#-------------------------------------
# Backgrounds
# Background 1: Active taskbar, Inactive taskbar, Launcher, Panel
rounded = 0
border_width = 0
border_sides = TBLR
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #ffffff 100
border_color = #ffffff 0
background_color_hover = #ffffff 100
border_color_hover = #ffffff 0
background_color_pressed = #ffffff 100
border_color_pressed = #ffffff 0

# Background 2: Active task
rounded = 0
border_width = 2
border_sides = B
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #ffffff 0
border_color = #0b7c9c 100
background_color_hover = #5c616c 5
border_color_hover = #0b7c9c 60
background_color_pressed = #5c616c 10
border_color_pressed = #0b7c9c 80

# Background 3: Default task, Iconified task
rounded = 0
border_width = 2
border_sides = B
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #ffffff 0
border_color = #5c616c 100
background_color_hover = #5c616c 5
border_color_hover = #5c616c 60
background_color_pressed = #5c616c 5
border_color_pressed = #5c616c 80

# Background 4: Urgent task
rounded = 0
border_width = 2
border_sides = B
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #ffffff 0
border_color = #dc143c 100
background_color_hover = #5c616c 15
border_color_hover = #dc143c 60
background_color_pressed = #5c616c 20
border_color_pressed = #000000 80

# Background 5: Inactive desktop name
rounded = 0
border_width = 0
border_sides = TBLR
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #ffffff 0
border_color = #ffffff 0
background_color_hover = #ffffff 0
border_color_hover = #ffffff 0
background_color_pressed = #ffffff 0
border_color_pressed = #ffffff 0

# Background 6: Active desktop name
rounded = 0
border_width = 0
border_sides = B
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #ffffff 0
border_color = #42a5f5 80
background_color_hover = #ffffff 0
border_color_hover = #42a5f5 70
background_color_pressed = #ffffff 0
border_color_pressed = #42a5f5 60

# Background 7: Tooltip
rounded = 0
border_width = 1
border_sides = TBLR
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #ffffff 100
border_color = #0b7c9c 80
background_color_hover = #ffffff 80
border_color_hover = #0b7c9c 80
background_color_pressed = #ffffff 80
border_color_pressed = #0b7c9c 80

# Background 8: Battery, Clock, Systray
rounded = 0
border_width = 0
border_sides = B
border_content_tint_weight = 0
background_content_tint_weight = 0
background_color = #0b7c9c 100
border_color = #ffffff 0
background_color_hover = #0b7c9c 100
border_color_hover = #ffffff 0
background_color_pressed = #0b7c9c 100
border_color_pressed = #ffffff 0

#-------------------------------------
# Panel
panel_items = LTSC
panel_size = 100% 32
panel_margin = 0 0
panel_padding = 0 0 0
panel_background_id = 1
wm_menu = 1
panel_dock = 0
panel_position = bottom center horizontal
panel_layer = top
panel_monitor = all
panel_shrink = 0
autohide = 0
autohide_show_timeout = 0.5
autohide_hide_timeout = 2
autohide_height = 1
strut_policy = follow_size
panel_window_name = tint2
disable_transparency = 0
mouse_effects = 1
font_shadow = 0
mouse_hover_icon_asb = 100 0 10
mouse_pressed_icon_asb = 100 0 0
scale_relative_to_dpi = 0
scale_relative_to_screen_height = 0

#-------------------------------------
# Taskbar
taskbar_mode = single_desktop
taskbar_hide_if_empty = 0
taskbar_padding = 0 0 4
taskbar_background_id = 1
taskbar_active_background_id = 1
taskbar_name = 0
taskbar_hide_inactive_tasks = 0
taskbar_hide_different_monitor = 0
taskbar_hide_different_desktop = 0
taskbar_always_show_all_desktop_tasks = 0
taskbar_name_padding = 8 8
taskbar_name_background_id = 5
taskbar_name_active_background_id = 6
taskbar_name_font = Ubuntu Condensed Bold 12
taskbar_name_font_color = #5c5c5c 100
taskbar_name_active_font_color = #353535 100
taskbar_distribute_size = 1
taskbar_sort_order = none
task_align = left

#-------------------------------------
# Task
task_text = 1
task_icon = 1
task_centered = 1
urgent_nb_of_blink = 20
task_maximum_size = 150 40
task_padding = 2 2 2
task_font = Ubuntu Condensed Regular 11
task_tooltip = 1
task_thumbnail = 0
task_thumbnail_size = 210
task_font_color = #5c616c 100
task_active_font_color = #008dff 100
task_urgent_font_color = #dc143c 100
task_iconified_font_color = #5c616c 88
task_icon_asb = 80 0 0
task_active_icon_asb = 100 0 10
task_urgent_icon_asb = 100 0 0
task_iconified_icon_asb = 80 0 0
task_background_id = 3
task_active_background_id = 2
task_urgent_background_id = 4
task_iconified_background_id = 3
mouse_left = toggle_iconify
mouse_middle = none
mouse_right = none
mouse_scroll_up = toggle
mouse_scroll_down = iconify

#-------------------------------------
# System tray (notification area)
systray_padding = 7 0 5
systray_background_id = 8
systray_sort = ascending
systray_icon_size = 24
systray_icon_asb = 100 0 10
systray_monitor = 1
systray_name_filter = 

#-------------------------------------
# Launcher
launcher_padding = 8 0 8
launcher_background_id = 1
launcher_icon_background_id = 0
launcher_icon_size = 24
launcher_icon_asb = 100 0 0
launcher_icon_theme_override = 1
startup_notifications = 1
launcher_tooltip = 1
launcher_item_app = /usr/share/applications/chromium-browser.desktop
launcher_item_app = /usr/share/applications/firefox.desktop
launcher_item_app = /usr/share/applications/exo-file-manager.desktop
launcher_item_app = /usr/share/applications/mate-terminal.desktop
launcher_item_app = /usr/share/applications/org.gnome.Nautilus.desktop
launcher_item_app = /usr/share/applications/caja-home.desktop

#-------------------------------------
# Clock
time1_format = %H:%M - %d.%m.%Y
time2_format = 
time1_font = Ubuntu Condensed Bold 13
time1_timezone = 
time2_timezone = 
time2_font = Ubuntu Condensed Bold 10
clock_font_color = #ffffff 100
clock_padding = 6 0
clock_background_id = 8
clock_tooltip = 
clock_tooltip_timezone = 
clock_lclick_command = gsimplecal
clock_rclick_command = gsimplecal
clock_mclick_command = 
clock_uwheel_command = 
clock_dwheel_command = 

#-------------------------------------
# Battery
battery_tooltip = 1
battery_low_status = 20
battery_low_cmd = notify-send "Battery Low !"
battery_full_cmd = 
bat1_font = Ubuntu Condensed Bold 12
bat2_font = Ubuntu Condensed Regular 0
battery_font_color = #ffffff 100
bat1_format = 
bat2_format = 
battery_padding = 5 5
battery_background_id = 8
battery_hide = 101
battery_lclick_command = xfce4-power-manager-settings
battery_rclick_command = xfce4-power-manager-settings
battery_mclick_command = 
battery_uwheel_command = 
battery_dwheel_command = 
ac_connected_cmd = 
ac_disconnected_cmd = 

#-------------------------------------
# Tooltip
tooltip_show_timeout = 0
tooltip_hide_timeout = 0
tooltip_padding = 5 3
tooltip_background_id = 7
tooltip_font_color = #353535 100
tooltip_font = Noto Sans 10


  • Openbox
menu.xml
<?xml version="1.0" encoding="UTF-8"?>

<openbox_menu xmlns="http://openbox.org/3.4/menu">

<menu id="root-menu" label="Openbox 3">
  <separator label="WWU-IT"/>
  <item label="Terminal">
    <action name="Execute">
      <command>/usr/bin/mate-terminal</command>
    </action>
  </item>
  <separator/>
  <item label="Home">
    <action name="Execute">
      <command>/usr/bin/caja --no-desktop</command>
    </action>
  </item>
  <item label="Scratch">
    <action name="Execute">
      <command>/etc/xdg/openbox/open_scratch.py</command>
    </action>
  </item>
  <separator/>
  <item label="Reconfigure">
    <action name="Reconfigure" />
  </item>
  <separator/>
</menu>

</openbox_menu>
rc.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file, it will be overwritten on install.
        Copy the file to $HOME/.config/openbox/ instead. -->
<openbox_config xmlns="http://openbox.org/3.4/rc" xmlns:xi="http://www.w3.org/2001/XInclude">
  <resistance>
    <strength>10</strength>
    <screen_edge_strength>20</screen_edge_strength>
  </resistance>
  <focus>
    <focusNew>yes</focusNew>
    <!-- always try to focus new windows when they appear. other rules do
       apply -->
    <followMouse>no</followMouse>
    <!-- move focus to a window when you move the mouse into it -->
    <focusLast>yes</focusLast>
    <!-- focus the last used window when changing desktops, instead of the one
       under the mouse pointer. when followMouse is enabled -->
    <underMouse>no</underMouse>
    <!-- move focus under the mouse, even when the mouse is not moving -->
    <focusDelay>200</focusDelay>
    <!-- when followMouse is enabled, the mouse must be inside the window for
       this many milliseconds (1000 = 1 sec) before moving focus to it -->
    <raiseOnFocus>no</raiseOnFocus>
    <!-- when followMouse is enabled, and a window is given focus by moving the
       mouse into it, also raise the window -->
  </focus>
  <placement>
    <policy>Smart</policy>
    <!-- 'Smart' or 'UnderMouse' -->
    <monitor>Primary</monitor>
    <!-- with Smart placement on a multi-monitor system, try to place new windows
       on: 'Any' - any monitor, 'Mouse' - where the mouse is, 'Active' - where
       the active window is, 'Primary' - only on the primary monitor -->
    <primaryMonitor>1</primaryMonitor>
    <!-- The monitor where Openbox should place popup dialogs such as the
       focus cycling popup, or the desktop switch popup.  It can be an index
       from 1, specifying a particular monitor.  Or it can be one of the
       following: 'Mouse' - where the mouse is, or
                  'Active' - where the active window is -->
  </placement>
  <theme>
    <name>WWU-IT</name>
    <titleLayout>NLIMC</titleLayout>
    <!--
      available characters are NDSLIMC, each can occur at most once.
      N: window icon
      L: window label (AKA title).
      I: iconify
      M: maximize
      C: close
      S: shade (roll up/down)
      D: omnipresent (on all desktops).
  -->
    <keepBorder>yes</keepBorder>
    <animateIconify>yes</animateIconify>
    <font place="ActiveWindow">
      <name>sans</name>
      <size>8</size>
      <!-- font size in points -->
      <weight>bold</weight>
      <!-- 'bold' or 'normal' -->
      <slant>normal</slant>
      <!-- 'italic' or 'normal' -->
    </font>
    <font place="InactiveWindow">
      <name>sans</name>
      <size>8</size>
      <!-- font size in points -->
      <weight>bold</weight>
      <!-- 'bold' or 'normal' -->
      <slant>normal</slant>
      <!-- 'italic' or 'normal' -->
    </font>
    <font place="MenuHeader">
      <name>sans</name>
      <size>9</size>
      <!-- font size in points -->
      <weight>normal</weight>
      <!-- 'bold' or 'normal' -->
      <slant>normal</slant>
      <!-- 'italic' or 'normal' -->
    </font>
    <font place="MenuItem">
      <name>sans</name>
      <size>9</size>
      <!-- font size in points -->
      <weight>normal</weight>
      <!-- 'bold' or 'normal' -->
      <slant>normal</slant>
      <!-- 'italic' or 'normal' -->
    </font>
    <font place="ActiveOnScreenDisplay">
      <name>sans</name>
      <size>9</size>
      <!-- font size in points -->
      <weight>bold</weight>
      <!-- 'bold' or 'normal' -->
      <slant>normal</slant>
      <!-- 'italic' or 'normal' -->
    </font>
    <font place="InactiveOnScreenDisplay">
      <name>sans</name>
      <size>9</size>
      <!-- font size in points -->
      <weight>bold</weight>
      <!-- 'bold' or 'normal' -->
      <slant>normal</slant>
      <!-- 'italic' or 'normal' -->
    </font>
  </theme>
  <desktops>
    <!-- this stuff is only used at startup, pagers allow you to change them
       during a session

       these are default values to use when other ones are not already set
       by other applications, or saved in your session

       use obconf if you want to change these without having to log out
       and back in -->
    <number>1</number>
    <firstdesk>1</firstdesk>
    <names>
      <!-- set names up here if you want to, like this:
    <name>desktop 1</name>
    <name>desktop 2</name>
    -->
    </names>
    <popupTime>875</popupTime>
    <!-- The number of milliseconds to show the popup for when switching
       desktops.  Set this to 0 to disable the popup. -->
  </desktops>
  <resize>
    <drawContents>yes</drawContents>
    <popupShow>Nonpixel</popupShow>
    <!-- 'Always', 'Never', or 'Nonpixel' (xterms and such) -->
    <popupPosition>Center</popupPosition>
    <!-- 'Center', 'Top', or 'Fixed' -->
    <popupFixedPosition>
      <!-- these are used if popupPosition is set to 'Fixed' -->
      <x>10</x>
      <!-- positive number for distance from left edge, negative number for
         distance from right edge, or 'Center' -->
      <y>10</y>
      <!-- positive number for distance from top edge, negative number for
         distance from bottom edge, or 'Center' -->
    </popupFixedPosition>
  </resize>
  <!-- You can reserve a portion of your screen where windows will not cover when
     they are maximized, or when they are initially placed.
     Many programs reserve space automatically, but you can use this in other
     cases. -->
  <margins>
    <top>0</top>
    <bottom>0</bottom>
    <left>0</left>
    <right>0</right>
  </margins>
  <dock>
    <position>TopLeft</position>
    <!-- (Top|Bottom)(Left|Right|)|Top|Bottom|Left|Right|Floating -->
    <floatingX>0</floatingX>
    <floatingY>0</floatingY>
    <noStrut>no</noStrut>
    <stacking>Above</stacking>
    <!-- 'Above', 'Normal', or 'Below' -->
    <direction>Vertical</direction>
    <!-- 'Vertical' or 'Horizontal' -->
    <autoHide>no</autoHide>
    <hideDelay>300</hideDelay>
    <!-- in milliseconds (1000 = 1 second) -->
    <showDelay>300</showDelay>
    <!-- in milliseconds (1000 = 1 second) -->
    <moveButton>Middle</moveButton>
    <!-- 'Left', 'Middle', 'Right' -->
  </dock>
  <keyboard>
    <chainQuitKey>C-g</chainQuitKey>
    <!-- Keybindings for desktop switching -->
    <keybind key="C-A-Left">
      <action name="GoToDesktop">
        <to>left</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="C-A-Right">
      <action name="GoToDesktop">
        <to>right</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="C-A-Up">
      <action name="GoToDesktop">
        <to>up</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="C-A-Down">
      <action name="GoToDesktop">
        <to>down</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="S-A-Left">
      <action name="SendToDesktop">
        <to>left</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="S-A-Right">
      <action name="SendToDesktop">
        <to>right</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="S-A-Up">
      <action name="SendToDesktop">
        <to>up</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="S-A-Down">
      <action name="SendToDesktop">
        <to>down</to>
        <wrap>no</wrap>
      </action>
    </keybind>
    <keybind key="W-F1">
      <action name="GoToDesktop">
        <to>1</to>
      </action>
    </keybind>
    <keybind key="W-F2">
      <action name="GoToDesktop">
        <to>2</to>
      </action>
    </keybind>
    <keybind key="W-F3">
      <action name="GoToDesktop">
        <to>3</to>
      </action>
    </keybind>
    <keybind key="W-F4">
      <action name="GoToDesktop">
        <to>4</to>
      </action>
    </keybind>
    <keybind key="W-d">
      <action name="ToggleShowDesktop"/>
    </keybind>
    <!-- Keybindings for windows -->
    <keybind key="A-F4">
      <action name="Close"/>
    </keybind>
    <keybind key="A-Escape">
      <action name="Lower"/>
      <action name="FocusToBottom"/>
      <action name="Unfocus"/>
    </keybind>
    <keybind key="A-space">
      <action name="ShowMenu">
        <menu>client-menu</menu>
      </action>
    </keybind>
    <!-- Keybindings for window switching -->
    <keybind key="A-Tab">
      <action name="NextWindow">
        <finalactions>
          <action name="Focus"/>
          <action name="Raise"/>
          <action name="Unshade"/>
        </finalactions>
      </action>
    </keybind>
    <keybind key="A-S-Tab">
      <action name="PreviousWindow">
        <finalactions>
          <action name="Focus"/>
          <action name="Raise"/>
          <action name="Unshade"/>
        </finalactions>
      </action>
    </keybind>
    <keybind key="C-A-Tab">
      <action name="NextWindow">
        <panels>yes</panels>
        <desktop>yes</desktop>
        <finalactions>
          <action name="Focus"/>
          <action name="Raise"/>
          <action name="Unshade"/>
        </finalactions>
      </action>
    </keybind>
    <!-- Keybindings for window switching with the arrow keys -->
    <keybind key="W-S-Right">
      <action name="DirectionalCycleWindows">
        <direction>right</direction>
      </action>
    </keybind>
    <keybind key="W-S-Left">
      <action name="DirectionalCycleWindows">
        <direction>left</direction>
      </action>
    </keybind>
    <keybind key="W-S-Up">
      <action name="DirectionalCycleWindows">
        <direction>up</direction>
      </action>
    </keybind>
    <keybind key="W-S-Down">
      <action name="DirectionalCycleWindows">
        <direction>down</direction>
      </action>
    </keybind>
    <!-- Keybindings for running applications -->
    <keybind key="W-e">
      <action name="Execute">
        <startupnotify>
          <enabled>true</enabled>
          <name>Konqueror</name>
        </startupnotify>
        <command>kfmclient openProfile filemanagement</command>
      </action>
    </keybind>
  </keyboard>
  <mouse>
    <dragThreshold>1</dragThreshold>
    <!-- number of pixels the mouse must move before a drag begins -->
    <doubleClickTime>500</doubleClickTime>
    <!-- in milliseconds (1000 = 1 second) -->
    <screenEdgeWarpTime>400</screenEdgeWarpTime>
    <!-- Time before changing desktops when the pointer touches the edge of the
       screen while moving a window, in milliseconds (1000 = 1 second).
       Set this to 0 to disable warping -->
    <screenEdgeWarpMouse>false</screenEdgeWarpMouse>
    <!-- Set this to TRUE to move the mouse pointer across the desktop when
       switching due to hitting the edge of the screen -->
    <context name="Frame">
      <mousebind button="A-Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
      <mousebind button="A-Left" action="Click">
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="A-Left" action="Drag">
        <action name="Move"/>
      </mousebind>
      <mousebind button="A-Right" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="A-Right" action="Drag">
        <action name="Resize"/>
      </mousebind>
      <mousebind button="A-Middle" action="Press">
        <action name="Lower"/>
        <action name="FocusToBottom"/>
        <action name="Unfocus"/>
      </mousebind>
      <mousebind button="A-Up" action="Click">
        <action name="GoToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="A-Down" action="Click">
        <action name="GoToDesktop">
          <to>next</to>
        </action>
      </mousebind>
      <mousebind button="C-A-Up" action="Click">
        <action name="GoToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="C-A-Down" action="Click">
        <action name="GoToDesktop">
          <to>next</to>
        </action>
      </mousebind>
      <mousebind button="A-S-Up" action="Click">
        <action name="SendToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="A-S-Down" action="Click">
        <action name="SendToDesktop">
          <to>next</to>
        </action>
      </mousebind>
    </context>
    <context name="Titlebar">
      <mousebind button="Left" action="Drag">
        <action name="Move"/>
      </mousebind>
      <mousebind button="Left" action="DoubleClick">
        <action name="ToggleMaximize"/>
      </mousebind>
      <mousebind button="Up" action="Click">
        <action name="if">
          <shaded>no</shaded>
          <then>
            <action name="Shade"/>
            <action name="FocusToBottom"/>
            <action name="Unfocus"/>
            <action name="Lower"/>
          </then>
        </action>
      </mousebind>
      <mousebind button="Down" action="Click">
        <action name="if">
          <shaded>yes</shaded>
          <then>
            <action name="Unshade"/>
            <action name="Raise"/>
          </then>
        </action>
      </mousebind>
    </context>
    <context name="Titlebar Top Right Bottom Left TLCorner TRCorner BRCorner BLCorner">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="Middle" action="Press">
        <action name="Lower"/>
        <action name="FocusToBottom"/>
        <action name="Unfocus"/>
      </mousebind>
      <mousebind button="Right" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="ShowMenu">
          <menu>client-menu</menu>
        </action>
      </mousebind>
    </context>
    <context name="Top">
      <mousebind button="Left" action="Drag">
        <action name="Resize">
          <edge>top</edge>
        </action>
      </mousebind>
    </context>
    <context name="Left">
      <mousebind button="Left" action="Drag">
        <action name="Resize">
          <edge>left</edge>
        </action>
      </mousebind>
    </context>
    <context name="Right">
      <mousebind button="Left" action="Drag">
        <action name="Resize">
          <edge>right</edge>
        </action>
      </mousebind>
    </context>
    <context name="Bottom">
      <mousebind button="Left" action="Drag">
        <action name="Resize">
          <edge>bottom</edge>
        </action>
      </mousebind>
      <mousebind button="Right" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="ShowMenu">
          <menu>client-menu</menu>
        </action>
      </mousebind>
    </context>
    <context name="TRCorner BRCorner TLCorner BLCorner">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="Left" action="Drag">
        <action name="Resize"/>
      </mousebind>
    </context>
    <context name="Client">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
      <mousebind button="Middle" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
      <mousebind button="Right" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
    </context>
    <context name="Icon">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
        <action name="ShowMenu">
          <menu>client-menu</menu>
        </action>
      </mousebind>
      <mousebind button="Right" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="ShowMenu">
          <menu>client-menu</menu>
        </action>
      </mousebind>
    </context>
    <context name="AllDesktops">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="Left" action="Click">
        <action name="ToggleOmnipresent"/>
      </mousebind>
    </context>
    <context name="Shade">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
      <mousebind button="Left" action="Click">
        <action name="ToggleShade"/>
      </mousebind>
    </context>
    <context name="Iconify">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
      <mousebind button="Left" action="Click">
        <action name="Iconify"/>
      </mousebind>
    </context>
    <context name="Maximize">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="Middle" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="Right" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="Left" action="Click">
        <action name="ToggleMaximize"/>
      </mousebind>
      <mousebind button="Middle" action="Click">
        <action name="ToggleMaximize">
          <direction>vertical</direction>
        </action>
      </mousebind>
      <mousebind button="Right" action="Click">
        <action name="ToggleMaximize">
          <direction>horizontal</direction>
        </action>
      </mousebind>
    </context>
    <context name="Close">
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
        <action name="Unshade"/>
      </mousebind>
      <mousebind button="Left" action="Click">
        <action name="Close"/>
      </mousebind>
    </context>
    <context name="Desktop">
      <mousebind button="Up" action="Click">
        <action name="GoToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="Down" action="Click">
        <action name="GoToDesktop">
          <to>next</to>
        </action>
      </mousebind>
      <mousebind button="A-Up" action="Click">
        <action name="GoToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="A-Down" action="Click">
        <action name="GoToDesktop">
          <to>next</to>
        </action>
      </mousebind>
      <mousebind button="C-A-Up" action="Click">
        <action name="GoToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="C-A-Down" action="Click">
        <action name="GoToDesktop">
          <to>next</to>
        </action>
      </mousebind>
      <mousebind button="Left" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
      <mousebind button="Right" action="Press">
        <action name="Focus"/>
        <action name="Raise"/>
      </mousebind>
    </context>
    <context name="Root">
      <!-- Menus -->
      <mousebind button="Middle" action="Press">
        <action name="ShowMenu">
          <menu>client-list-combined-menu</menu>
        </action>
      </mousebind>
      <mousebind button="Right" action="Press">
        <action name="ShowMenu">
          <menu>root-menu</menu>
        </action>
      </mousebind>
    </context>
    <context name="MoveResize">
      <mousebind button="Up" action="Click">
        <action name="GoToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="Down" action="Click">
        <action name="GoToDesktop">
          <to>next</to>
        </action>
      </mousebind>
      <mousebind button="A-Up" action="Click">
        <action name="GoToDesktop">
          <to>previous</to>
        </action>
      </mousebind>
      <mousebind button="A-Down" action="Click">
        <action name="GoToDesktop">
          <to>next</to>
        </action>
      </mousebind>
    </context>
  </mouse>
  <menu>
    <!-- You can specify more than one menu file in here and they are all loaded,
       just don't make menu ids clash or, well, it'll be kind of pointless -->
    <!-- default menu file (or custom one in $HOME/.config/openbox/) -->
    <file>menu.xml</file>
    <hideDelay>200</hideDelay>
    <!-- if a press-release lasts longer than this setting (in milliseconds), the
       menu is hidden again -->
    <middle>no</middle>
    <!-- center submenus vertically about the parent entry -->
    <submenuShowDelay>100</submenuShowDelay>
    <!-- time to delay before showing a submenu after hovering over the parent
       entry.
       if this is a negative value, then the delay is infinite and the
       submenu will not be shown until it is clicked on -->
    <submenuHideDelay>400</submenuHideDelay>
    <!-- time to delay before hiding a submenu when selecting another
       entry in parent menu
       if this is a negative value, then the delay is infinite and the
       submenu will not be hidden until a different submenu is opened -->
    <showIcons>yes</showIcons>
    <!-- controls if icons appear in the client-list-(combined-)menu -->
    <manageDesktops>yes</manageDesktops>
    <!-- show the manage desktops section in the client-list-(combined-)menu -->
  </menu>
  <applications>
    <!--
  # this is an example with comments through out. use these to make your
  # own rules, but without the comments of course.
  # you may use one or more of the name/class/role/title/type rules to specify
  # windows to match

  <application name="the window's _OB_APP_NAME property (see obxprop)"
              class="the window's _OB_APP_CLASS property (see obxprop)"
          groupname="the window's _OB_APP_GROUP_NAME property (see obxprop)"
         groupclass="the window's _OB_APP_GROUP_CLASS property (see obxprop)"
               role="the window's _OB_APP_ROLE property (see obxprop)"
              title="the window's _OB_APP_TITLE property (see obxprop)"
               type="the window's _OB_APP_TYPE property (see obxprob)..
                      (if unspecified, then it is 'dialog' for child windows)">
  # you may set only one of name/class/role/title/type, or you may use more
  # than one together to restrict your matches.

  # the name, class, role, and title use simple wildcard matching such as those
  # used by a shell. you can use * to match any characters and ? to match
  # any single character.

  # the type is one of: normal, dialog, splash, utility, menu, toolbar, dock,
  #    or desktop

  # when multiple rules match a window, they will all be applied, in the
  # order that they appear in this list


    # each rule element can be left out or set to 'default' to specify to not 
    # change that attribute of the window

    <decor>yes</decor>
    # enable or disable window decorations

    <shade>no</shade>
    # make the window shaded when it appears, or not

    <position force="no">
      # the position is only used if both an x and y coordinate are provided
      # (and not set to 'default')
      # when force is "yes", then the window will be placed here even if it
      # says you want it placed elsewhere.  this is to override buggy
      # applications who refuse to behave
      <x>center</x>
      # a number like 50, or 'center' to center on screen. use a negative number
      # to start from the right (or bottom for <y>), ie -50 is 50 pixels from
      # the right edge (or bottom). use 'default' to specify using value
      # provided by the application, or chosen by openbox, instead.
      <y>200</y>
      <monitor>1</monitor>
      # specifies the monitor in a xinerama setup.
      # 1 is the first head, or 'mouse' for wherever the mouse is
    </position>

    <size>
      # the size to make the window.
      <width>20</width>
      # a number like 20, or 'default' to use the size given by the application.
      # you can use fractions such as 1/2 or percentages such as 75% in which
      # case the value is relative to the size of the monitor that the window
      # appears on.
      <height>30%</height>
    </size>

    <focus>yes</focus>
    # if the window should try be given focus when it appears. if this is set
    # to yes it doesn't guarantee the window will be given focus. some
    # restrictions may apply, but Openbox will try to

    <desktop>1</desktop>
    # 1 is the first desktop, 'all' for all desktops

    <layer>normal</layer>
    # 'above', 'normal', or 'below'

    <iconic>no</iconic>
    # make the window iconified when it appears, or not

    <skip_pager>no</skip_pager>
    # asks to not be shown in pagers

    <skip_taskbar>no</skip_taskbar>
    # asks to not be shown in taskbars. window cycling actions will also
    # skip past such windows

    <fullscreen>yes</fullscreen>
    # make the window in fullscreen mode when it appears

    <maximized>true</maximized>
    # 'Horizontal', 'Vertical' or boolean (yes/no)
  </application>

  # end of the example
-->
  </applications>
</openbox_config>
open_scratch.py
#!/bin/python

import getpass
import subprocess

user = getpass.getuser()

work = "/scratch/tmp/%s/" % user

pid = subprocess.Popen(['/usr/bin/caja', '--no-desktop', work])


Desktop view

SLURM Integration

We added a module vis-gpu which gives access to a vnc_gpu.sh script. The script automatially reserves one of the dedicated GPU nodes with a fixed amount of CPUs, one GPU and a limited time of 12h. It then starts the turbovnc server and prints instructions to the terminal on how to create an ssh tunnel and conntect to the VNC server.

#!/bin/bash

# List of tunnable ports
ports=( "5910" "5911" "5912" "5913" "5914" "5915" "0" )

function get_vnc_display() {
    /Applic.HPC/TurboVNC/bin/vncserver -list | \
    sed --quiet --regexp-extended \
    '/X DISPLAY/{n; s/^[[:space:]]*:([[:digit:]]+)[[:space:]]+.*$/\1/p}'
}

function get_tunnel_port(){
for port in "${ports[@]}"
do
    if [ $port = "0" ];
    then
        echo $port
        break
    fi
    if [ ! -f /Applic.HPC/visualisierung/ports/$port ] && [ ! -f /Applic.HPC/visualisierung/ports/$port.bak ];
    then
        touch /Applic.HPC/visualisierung/ports/$port
        echo $port
        break
    fi
done
}

TUNNEL_PORT=$(get_tunnel_port)
if [ $TUNNEL_PORT = '0' ]; then
    echo "Too many connections, no port available, aborting..."
    exit
fi

# Allocate nodes with slurm
function allocate_nodes_with_slurm() {
    rm /Applic.HPC/visualisierung/ports/$TUNNEL_PORT
    # Submit command
    local -a SUBMIT_COMMAND=()
    SUBMIT_COMMAND+=( "salloc" )
    SUBMIT_COMMAND+=( "--job-name=start_vnc_desktop" )
    SUBMIT_COMMAND+=( "--time=12:00:00" )
    SUBMIT_COMMAND+=( "--partition=vis-gpu" )
    SUBMIT_COMMAND+=( "--gres=gpu:1" )
    SUBMIT_COMMAND+=( "--cpus-per-task=6")
    SUBMIT_COMMAND+=( "srun" "--propagate=" "--pty" "/Applic.HPC/visualisierung/vis-gpu/vnc_gpu.sh" )

    exec "${SUBMIT_COMMAND[@]}"
}

# Check if we are in batch environment
if [[ -z "${SLURM_JOBID}" ]]; then
    allocate_nodes_with_slurm
fi

# Signalhandler
trap terminate_vncserver 0 1 2 3 6 9 11 15 16 20

function start_vncserver() {
    running=$(get_vnc_display)
    if [[ ! -z  "$running" ]];then
        echo "#### You can't have more than one session"
        exit
    fi  
    /Applic.HPC/TurboVNC/bin/vncserver -xstartup /Applic.HPC/visualisierung/vis-gpu/xstartup.turbovnc 
}

function terminate_vncserver() {
    local VNC_DISPLAY=$(get_vnc_display)
    if [[ -z "${VNC_DISPLAY}" ]]; then
        return
    fi  
    /Applic.HPC/TurboVNC/bin/vncserver -kill :${VNC_DISPLAY}
    mv /Applic.HPC/visualisierung/ports/$TUNNEL_PORT /Applic.HPC/visualisierung/ports/$TUNNEL_PORT.bak
}

function stop_already_running_vncserver() {
    local VNC_DISPLAY
    while VNC_DISPLAY=$(get_vnc_display) && [[ -n "${VNC_DISPLAY}" ]]
    do
        echo "Stopping VNC desktop already running on display :${VNC_DISPLAY}"
        ${VNC_SERVER} -kill :${VNC_DISPLAY}
        sleep 5
    done
}

function report_connect_info() {
    local VNC_DISPLAY=$(get_vnc_display)
    local VNC_PORT=$((5900 + ${VNC_DISPLAY}))
    local VNC_HOST="$(hostname -s)"
    local VNC_USER="$(whoami)"

    if [[ -z "${VNC_DISPLAY}" ]]; then
        echo "No VNC display found"
        exit 7
    fi  
    cat <<-EOF
##########################

Your Session is ready:

        On Linux, run:
        ssh -L ${VNC_PORT}:localhost:${TUNNEL_PORT} ${VNC_USER}@palma.uni-muenster.de 'ssh -L ${TUNNEL_PORT}:localhost:${VNC_PORT} ${VNC_HOST}'

        On Windows:
        plink -L ${VNC_PORT}:localhost:${TUNNEL_PORT} ${VNC_USER}@palma.uni-muenster.de ssh -L ${TUNNEL_PORT}:localhost:${VNC_PORT} ${VNC_HOST}
    
        in your terminal and just keep it open, then connect your VNC client to localhost:${VNC_PORT}

        Password: ${VNC_PASSWORD}

##########################

        To end your session, press CTRL + C, once in this terminal and once in your local ssh terminal.

##########################

EOF
}

function exec_interactive_shell() {
    local PPID_COMMAND_NAME=$(ps --no-headers -o comm= --pid "${PPID}")
    if [[ "${PPID_COMMAND_NAME}" =~ slurmstepd ]]; then
        bash -i
        exit
    fi
}

function set_vncpasswd() {
    local PASSWORD="$(    openssl rand -base64 8)"
    local VIEWPASSWORD="$(openssl rand -base64 8)"

    VNC_PASSWORD="${PASSWORD:0:8}"
    VNC_VIEWPASSWORD="${VIEWPASSWORD:0:8}"

    local VNC_PASSWD_FILE="${HOME}/.vnc/passwd"
#    install -D --mode="u=rw,og=" /dev/null "${VNC_PASSWD_FILE}" 
    /Applic.HPC/TurboVNC/bin/vncpasswd -f > "${VNC_PASSWD_FILE}" <<-EOF
${VNC_PASSWORD}
${VNC_PASSWORD}
${VNC_VIEWPASSWORD}
EOF
}

set_vncpasswd
start_vncserver
report_connect_info
sleep 12h