# /etc/qemu-web-desktop/config.pl: Configuration for qemu-web-desktop
#
# It is recommended to overload specific configuration in separate *.pl files
# located in /etc/qemu-web-desktop/config.d/
#
# Think about editing the /usr/share/qemu-web-desktop/html/desktop/index.html
# to comment/un-comment sections (GPU, oneshot, user scripts, ...).
#
# This file contains the following sections:
# - WHERE THINGS ARE
# - MACHINE DEFAULT SETTINGS
# - SERVICE CONTRAINTS
# - USER AUTHENTICATION
# - WEB SERVICE APPEARANCE
#
# Full documentation at:
#   https://gitlab.com/soleil-data-treatment/soleil-software-projects/qemu-web-desktop
#
# When relevant, the equivalent OpenStack naming is indicated (as documented 
# in https://docs.openstack.org/nova/latest/configuration/config.html)




# SECTION: WHERE THINGS ARE ----------------------------------------------------
# adapt to Darwin/Apple macos (brew)
my $p="";
if ($^O eq 'darwin') {
    $p="/opt/homebrew"; # WARNING: brew is not available for www user/macos. Must add static path.
    $ENV{PATH} = "$p/bin:" . $ENV{PATH}; # add brew commands to search path
    # `brew --prefix`;
}

# Name of service, used as directory and e.g. http://127.0.0.1/qemu-web-desktop
$config{service}                  = "qemu-web-desktop"; # change if you move/rename the service

# Full path to service HTML root (e.g. landing page)
$config{dir_html}                 = "$p/usr/share/$config{service}/html";

# Full path to root of the service area (for data and VM)
$config{dir_service}              = "$p/var/lib/$config{service}";

# Full path to machines (ISO,VM)
$config{dir_machines}             = "$config{dir_service}/machines";

# Full path to snapshots and temporary files OpenStack DEFAULT.instances_path
$config{dir_snapshots}            = "$config{dir_service}/snapshots";

# Full path to snapshot config/lock files. Must NOT be accessible from http://
#   e.g. /tmp to store "desktop_XXXXXXXX.json" files
#
# NOTE: apache has a protection in:
#   /etc/systemd/system/multi-user.target.wants/apache2.service
#   PrivateTmp=true
# which creates a '/tmp' in e.g. /tmp/systemd-private-*-apache2.service-*/
$config{dir_cfg}                  = File::Spec->tmpdir();  # OpenStack DEFAULT.tempdir

# Full path to noVNC, e.g. "/usr/share/novnc". Must contain "vnc.html"
$config{dir_novnc}                = "$p/usr/share/novnc";

# Websockify command, e.g. "/usr/bin/websockify"
$config{dir_websockify}           = "websockify";

# LOG file (record START/STOP and errors). File must exist and be RW.
$config{service_logfile}          = "$p/var/log/$config{service}.log";


# SECTION: MACHINE DEFAULT SETTINGS --------------------------------------------

# Max session life time in sec. 1 day is 86400 s. Highly recommended.
#   Use 0 to disable (infinite). This value bounds the selectable life-time from the form.
$config{snapshot_lifetime}        = 86400*4; 

# Default nb of CPU per session.
$config{snapshot_alloc_cpu}       = 1; # QEMU -smp; OpenStack DEFAULT.initial_cpu_allocation_ratio

# Default nb of RAM per session (in GB).
$config{snapshot_alloc_mem}       = 4; # QEMU -m; OpenStack DEFAULT.initial_ram_allocation_ratio

# Default size of disk per session (in GB). Only for ISO machines.
$config{snapshot_alloc_disk}      = 30.0; # OpenStack DEFAULT.initial_disk_allocation_ratio

# Option to work on master images. When not writable, still use a backing snapshot.
$config{snapshot_use_master}      = 0;

# Default machine to run
$config{machine}                  = '-';

# QEMU executable. Default 'auto' is set from native host (only for arm64 and x86_64). 
#   Adapt to the architecture you run on.
#     qemu-system-x86_64    on x86_64 (intel/amd64)
#     qemu-system-aarch64   on ARM    (arm64, incl. Apple/Silicon)
$config{qemu_exec}                = "auto";

# QEMU options. Default 'auto' uses best settings. Otherwise, we suggest:
#   For native x86: "-M pc,accel=kvm -enable-kvm -cpu host,kvm=off -vga virtio -device virtio-gpu"
#   For native ARM  "-M virt -enable-kvm -cpu host -device virtio-gpu -bios $EFI"
#   For Apple/ARM:  "-M virt,accel=hvf   -cpu host -device virtio-gpu -bios $EFI"
#   Else use:       "-M virt" (may require an EFI file)
# EFI files are provided by e.g. qemu-efi-aarch64
$config{qemu_exec_options}        = "auto";

# Boot delay before displaying the connection URL [sec]
$config{boot_delay}               = 5;

# Set a list of mounts to export into VMs.
# These are tested for existence before mounting. The QEMU mount_tag is set to 
# The last word of mount path prepended with 'host_'.
# Use e.g. `mount -t 9p -o trans=virtio,access=client host_media /mnt/media` in guest.
my @mounts                        = ('/mnt','/media');
$config{dir_mounts}               = [@mounts];




# SECTION: SERVICE CONTRAINTS --------------------------------------------------

# Max amount [0-1] of CPU load. Deny service when above.
$config{service_max_load}         = 0.8  ;

# Max number of active sessions. Deny service when above.
$config{service_max_session_nb}   = 10; # OpenStack config DEFAULT.max_concurrent_snapshots ?

# Max number of active sessions per user. Deny service when above.
$config{service_max_session_nb_per_user}   = 3;

# Max number of active CPU fraction per user. Deny service when above.
$config{service_max_cpu_fraction_nb_per_user}= 0.3;

# Max number of active memory fraction per user. Deny service when above.
$config{service_max_mem_fraction_nb_per_user}= 0.3;

# Max number of gpu per user. Deny service when above.
$config{service_max_gpu_nb_per_user}   = 1;

# The base port for the VNC screen (on 127.0.0.1 loopback interface). 
# The VNC port is chosen randomly up to service_port_vnc+service_max_session_nb
$config{service_port_vnc}         = 5901; # OpenStack config vmware.vnc_port

# The port where the VNC screens are broadcasted (e.g. 6080 for websockify)
#   Use 0 to select a random base port
# If you tune the reverse proxy, make sure this port is the same as e.g.
#   'ProxyPass /alias ws://127.0.0.1:6080/' from the web server
#   in e.g. /etc/apache2/conf-available/qemu-web-desktop.conf
$config{service_port}             = 6080; # OpenStack vnc.novncproxy_port

# On RedHat-based systems, in case you update these, issue for each new PORT
#   semanage port -a -t http_port_t -p tcp PORT

# Use a single websockify port with tokens, or a port range.
#   0: websockify uses only one port (recommended, except when using 'oneshot' sessions)
#   1: the websockify port is chosen randomly up to service_port+service_max_session_nb
#      which is not possible if you use a reverse proxy.
$config{service_port_multiple}    = 0;    # when true, use one websockify per instance
  
# Prefer single-shot sessions. Only a single connection is allowed. 
#   Any disconnect immediately ends the session. This is NOT recommended.
#   When set, also un-comment the landing page section.
$config{oneshot}                  = 0;    # when true, all sessions are one-shot

# In case there is a reverse proxy for the generated VNC/websocket, specify it here.
#   You may use:
#     ""              use ":$session{port}" (forced when 'service_port_multiple=1')
#                     In this case the reverse proxy is not active.
#     ":service_port" fixed port
#     "/alias"        reverse proxy corresponding with e.g. 
#                     'ProxyPass /alias ws://127.0.0.1:6080/' from the web server
#                     in e.g. /etc/apache2/conf-available/qemu-web-desktop.conf
# The final session URL is shown as e.g.:
#   http://$session{server_name}$config{service_reverse_proxy}/vnc.html ...
# WARNING: not supported under macos
if ($^O eq 'darwin') {
  $config{service_reverse_proxy}    = "";   # reverse proxy not supported on MacOS
} else {
  $config{service_reverse_proxy}    = "/darts";   # "" or ":port" or "/alias"
}

# In case there is a proxy server to pass, specify it here
$config{service_proxy}            = "";   # "http://195.221.0.35:8080/";

# A list of other servers to be used when current one does not have enough resources
# Can be a server name, IP, including protocol (http, https). Indicate a 
#   comma-separated list. All of URL, server names and IP are allowed. 
#   e.g. 'https://grades-01.synchrotron-soleil.fr,https://re-grades-01.exp.synchrotron-soleil.fr';
$config{fallback_servers}         = ''; 

# The max length of user customization script (URL length)
$config{service_max_script_length}= 65535; # e.g. 65535

# Scripts to execute when any VM starts. Supports Linux and Windows guests.
# See: https://libguestfs.org/virt-customize.1.html --commands-from-file
# Can be specifyed as:
#   "http://some/url"
#   "/some/local/path/to/script"
#   "exec: some commands" separated with EOL or ';'
#   "virt-customize: commands" separated with EOL
# The symbols `@USER@` `@PW@` `@SESSION_NAME@` and `@VM@` are replaced by the user 
#   name, password, the session ID, and the virtual machine name. 
#
# In addition, when the above script description is preceded by `if(EXPR):` 
#   the given expression is evaluated with Perl and the script is only executed
#   when result is True. The `EXPR` condition may use the `@...@` symbols above.
#
# Scripts are executed at boot, in background, as root.
# It is possible to define as many scripts as needed. Strings are separated by ','
#
# WARNING: not supported under macos
my @config_scripts=("");
$config{config_script}            = [@config_scripts];

# A list of GPU PCI addresses NOT to be used, as returned by lspci e.g. 
# "06:05.0,00:1b.0". Items can be separated by spaces or commas.
# WARNING: not supported under macos (no GPU support)
$config{gpu_blacklist}            = "";




# SECTION: USER AUTHENTICATION -------------------------------------------------

# The name of the SMTP server, and optional port.
#   When empty, no email is needed
#   The SMTP server is used to send emails, and check user credentials.
$config{smtp_server}              = ''; # "smtp.synchrotron-soleil.fr"; 

# The SMTP port e.g. 25, 465, 587, or left blank
#   and indicate if SMTP uses encryption
$config{smtp_port}                = 587; 
$config{smtp_use_ssl}             = 'starttls'; # 'starttls' or blank

# The name of the IMAP server, and optional port.
#   When empty, no email is needed
#   The IMAP server is used to check user credentials.
$config{imap_server}              = ''; # 'smtp.synchrotron-soleil.fr'; 

# The IMAP port e.g. 143 or 993, or left blank
$config{imap_port}                = 993; 

# The name of the LDAP server.
#   The LDAP server is used to check user credentials.
$config{ldap_server}              = '';     # 195.221.10.1'; 
$config{ldap_port}                = 389;    # default is 389
$config{ldap_domain}              = 'EXP';  # DC

# The email address of the sender of the messages on the SMTP server. 
$config{email_from}               = ''; # 'luke.skywalker@synchrotron-soleil.fr';

# The password for the sender on the SMTP server, or left blank when none.
$config{email_passwd}             = "";

# The method to use for sending messages. Can be:
#   auto    use the provided smtp/email settings to decide what to do
#   SSL     use the SMTP server, port SSL, and email_from with email_passwd
#   port    just use the server with given SMTP port
#   simple  just use the server, and port 25
$config{email_method}             = "auto";

# ** How to check users **
# WARNING: WHEN NO AUTHENTICATION MECHANISM IS SET, ALL USERS CAN CONNECT. :WARNING

# The default authentication, must have openssh (apt install openssh-server)
$config{check_user_with_local}    = 0;  

# The email authentication is less secure. Use it with caution.
#   The only test is for an "email"-like input, but not actual valid / registered email.
#   When authenticated with email, only single-shot sessions can be launched.
$config{check_user_with_email}    = 0;  # send URL via email.
$config{check_user_with_imap}     = 0;  

# In case of IMAP error "Unable to connect to <server>: SSL connect attempt 
#   failed error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol.""
# See:
# https://stackoverflow.com/questions/53058362/openssl-v1-1-1-ssl-choose-client-version-unsupported-protocol

$config{check_user_with_smtp}     = 0;
$config{check_user_with_ldap}     = 0;

# Force to send information via email, which implies valid user email.
# The VNC token is sent only via email, not displayed in printed message.
# When activated you need to:
# - use any of 'check_user_with_email=1' or 'check_user_with_imap=1' or 'check_user_with_ldap=1' with valid email information
# - properly configure the 'smtp_server' and 'smtp_port'
$config{check_user_mfa}           = 0; # activate MFA/2FA

# Custom user authentication.
#   When defined, this authenticator is ALWAYS executed (whatever be the other 
#   authenticator results).
#
# First, specify a function that should get (user, pw, authenticated, session_ref) 
#   as arguments and return a string starting by "SUCCESS" or "FAILED". The default  
#   return value should be the previous authenticator results.
# Any "SUCCESS" in the returned string fully qualifies the authentication.
#
#  sub check_user_func {
#    my $user          = shift;
#    my $pw            = shift;
#    my $authenticated = shift; # previous authenticator results
#    my $session_ref   = shift;  
#    if (not $session_ref) { return $authenticated; }
#    my %session       = %{ $session_ref };
#    my $res           = "";
#
#    res = "SUCCESS: [Custom] $user authenticated.";
#
#    res = "FAILED: [Custom] $user failed authentication.";
#
#    return "$authenticated and $res";
#  }
#
# Then send its reference to the configuration:
#
#   $config{check_user_custom} = \&check_user_func;
#
# or directly as an anonymous function
#
#   $config{check_user_custom} = sub { };

$config{check_user_custom}   = "";


# Encryption (HTTPS). Set these to valid 'crt' and 'key' files with proper certificates
#   to allow secured encryption of websockify/novnc. The CRT and KEY should both be set.
# WARNING: after setting these, KILL any running websockify: sudo killall websockify
# OpenStack DEFAULT.key DEFAULT.cert
$config{certificate_crt} = ''; # '/etc/apache2/certificate/apache-certificate.crt';
$config{certificate_key} = ''; # '/etc/apache2/certificate/apache.key';

# Set the list of 'admin' users that can access the Monitoring pages.
# These must also be identified with their credentials.
my @admin = ('');              # ('admin1,'admin2')
$config{user_admin} = [@admin];




# SECTION: WEB SERVICE APPEARANCE -------------------------------------------------------

# The level of HTML generation.
#   0: minimalist level: nearly no information except the CONNECT, SHARE and STOP buttons.
#   1: normal level:     slightly more information, with some notes, and life-time.
#   2: verbose level:    a lot of technical information
$config{layout_level} = 1; # 0='minimalist', 1='normal', 2='verbose'

# The 'title' of the generated web page (h1 tag), also used for the footer
$config{layout_title} = 'Data Analysis Remote Treatment Service';

# A Header (top) web page for generated html content. Default is used when empty.
# Can be given as a file path or a string with HTML, e.g. a logo reference.
# The default is e.g. <a href=service_url><img src=DARTS_logo></a>
# The layout_title above is appended in a H1 tag when no H1 is specified.
$config{layout_header}='';  # e.g. /etc/qemu-web-desktop/config.d/header.html

# A Footer (bottom) web page for generated html content. Default is used when empty.
# Can be given as a file path or a string with HTML, e.g. a URL link.
# The default is e.g. <small><a href=service_url></small>
$config{layout_footer}='';  # e.g. /etc/qemu-web-desktop/config.d/footer.html

# noVNC Screen rescale/resize: can be 'scale' (fixed ratio) or 'remote' (scales to browser size)
$config{layout_resize}='remote';

# KEEP THIS LINE!
1;
