mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 11:16:47 +00:00
build: systemd runs the panel on hosts instead of supervisor
The installer and the manual installation install four systemd units (webvirt-cloud, webvirt-novncd, webvirt-socketiod, webvirt-worker) that run as the web server's user with absolute paths and read /etc/default/webvirtcloud. gunicorn, socketiod and the worker stop with KillMode=mixed, so they wind down their own children. supervisor, its installer code and the contributed systemd files go; the README gets the update, rollback and a one-time move from supervisor, and the installer refuses to run over a supervisor install. Docker keeps runit; novncd's runit script is the one-line form of the others.
This commit is contained in:
parent
fbef55fe2d
commit
837c5468ec
13 changed files with 129 additions and 343 deletions
117
README.md
117
README.md
|
|
@ -68,7 +68,7 @@ chmod 744 install.sh
|
|||
sudo ./install.sh
|
||||
```
|
||||
|
||||
The installer writes the server's names and IPs to `ALLOWED_HOSTS`. Running it again keeps `settings.py`, the database, the secret key and the main nginx config, but replaces `/etc/nginx/conf.d/webvirtcloud.conf` and the supervisor config; back up your own lines in those two (TLS, `environment=`) first.
|
||||
The installer writes the server's names and IPs to `ALLOWED_HOSTS`. Running it again keeps `settings.py`, the database, the secret key and the main nginx config, but replaces `/etc/nginx/conf.d/webvirtcloud.conf` and the systemd units; back up your own lines in the nginx config (TLS) first. Put your own service settings in `/etc/default/webvirtcloud` or in drop-ins (`systemctl edit webvirt-cloud`), which a re-run keeps.
|
||||
|
||||
### Docker
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ The virtualenv is created with `--system-site-packages`: `libvirt-python` and `p
|
|||
|
||||
```bash
|
||||
# 1. System packages
|
||||
apt-get update && apt-get -y install git python3-venv python3-dev python3-lxml python3-libvirt libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python3-guestfs libsasl2-dev libldap2-dev libssl-dev
|
||||
apt-get update && apt-get -y install git python3-venv python3-dev python3-lxml python3-libvirt libvirt-dev zlib1g-dev libxslt1-dev nginx libsasl2-modules gcc pkg-config python3-guestfs libsasl2-dev libldap2-dev libssl-dev
|
||||
|
||||
# 2. Code
|
||||
git clone https://github.com/retspen/webvirtcloud /srv/webvirtcloud
|
||||
|
|
@ -121,15 +121,16 @@ pip install -r conf/requirements.txt
|
|||
python3 manage.py migrate
|
||||
python3 manage.py collectstatic --noinput
|
||||
|
||||
# 6. Supervisor (gunicorn, novncd and the job worker) and nginx
|
||||
cp conf/supervisor/webvirtcloud.conf /etc/supervisor/conf.d/
|
||||
# 6. systemd units (gunicorn, novncd, socketiod and the job worker) and nginx
|
||||
cp conf/systemd/webvirt-{cloud,novncd,socketiod,worker}.service /etc/systemd/system/
|
||||
cp conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/
|
||||
rm -f /etc/nginx/sites-enabled/default
|
||||
|
||||
# 7. Ownership, private files, start
|
||||
chown -R www-data:www-data /srv/webvirtcloud
|
||||
chmod 700 data && chmod 600 webvirtcloud/settings.py db.sqlite3
|
||||
systemctl restart nginx supervisor
|
||||
systemctl daemon-reload && systemctl enable --now webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker
|
||||
nginx -t && systemctl restart nginx
|
||||
```
|
||||
|
||||
#### RHEL / Rocky Linux / AlmaLinux / Oracle Linux 10
|
||||
|
|
@ -137,7 +138,7 @@ systemctl restart nginx supervisor
|
|||
```bash
|
||||
# 1. System packages
|
||||
dnf -y install epel-release
|
||||
dnf -y install git python3-devel libvirt-devel python3-libvirt python3-ldap python3-lxml cyrus-sasl-devel cyrus-sasl-md5 openldap-devel openssl-devel glibc gcc nginx supervisor python3-libguestfs iproute-tc
|
||||
dnf -y install git python3-devel libvirt-devel python3-libvirt python3-ldap python3-lxml cyrus-sasl-devel cyrus-sasl-md5 openldap-devel openssl-devel glibc gcc nginx python3-libguestfs iproute-tc
|
||||
|
||||
# 2. Code
|
||||
git clone https://github.com/retspen/webvirtcloud /srv/webvirtcloud
|
||||
|
|
@ -157,8 +158,8 @@ pip install -r conf/requirements.txt
|
|||
python3 manage.py migrate
|
||||
python3 manage.py collectstatic --noinput
|
||||
|
||||
# 6. Supervisor (gunicorn, novncd and the job worker, as nginx) and nginx
|
||||
sed 's/^user=.*/user=nginx/' conf/supervisor/webvirtcloud.conf > /etc/supervisord.d/webvirtcloud.ini
|
||||
# 6. systemd units (gunicorn, novncd, socketiod and the job worker, as nginx) and nginx
|
||||
for u in cloud novncd socketiod worker; do sed 's/^\(User\|Group\)=.*/\1=nginx/' conf/systemd/webvirt-$u.service > /etc/systemd/system/webvirt-$u.service; done
|
||||
cp conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/
|
||||
# make sure the default server block in /etc/nginx/nginx.conf does not also listen on port 80
|
||||
|
||||
|
|
@ -171,8 +172,8 @@ setsebool -P httpd_can_network_connect on 2>/dev/null || true
|
|||
firewall-cmd --add-service=http --permanent 2>/dev/null || true
|
||||
firewall-cmd --add-port=6080/tcp --permanent 2>/dev/null || true
|
||||
firewall-cmd --reload 2>/dev/null || true
|
||||
systemctl enable nginx supervisord
|
||||
nginx -t && systemctl restart nginx supervisord
|
||||
systemctl daemon-reload && systemctl enable --now webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker
|
||||
systemctl enable nginx && nginx -t && systemctl restart nginx
|
||||
```
|
||||
|
||||
#### openSUSE Leap 15.x / Tumbleweed, SLES 15
|
||||
|
|
@ -180,7 +181,6 @@ nginx -t && systemctl restart nginx supervisord
|
|||
```bash
|
||||
# 1. System packages (Python 3.11 stack)
|
||||
zypper --non-interactive install -y git hostname python311 python311-base python311-devel python311-pip python311-libvirt-python python311-lxml python311-ldap libvirt-devel openldap2-devel cyrus-sasl-devel libopenssl-devel gcc pkg-config nginx
|
||||
zypper --non-interactive install -y python3-supervisor || zypper --non-interactive install -y supervisor
|
||||
|
||||
# 2. Code
|
||||
git clone https://github.com/retspen/webvirtcloud /srv/webvirtcloud
|
||||
|
|
@ -200,17 +200,15 @@ pip install -r conf/requirements.txt
|
|||
python3 manage.py migrate
|
||||
python3 manage.py collectstatic --noinput
|
||||
|
||||
# 6. Supervisor (gunicorn, novncd and the job worker, as nginx) and nginx
|
||||
mkdir -p /etc/supervisord.d
|
||||
sed 's/^user=.*/user=nginx/' conf/supervisor/webvirtcloud.conf > /etc/supervisord.d/webvirtcloud.ini
|
||||
# make sure /etc/supervisord.conf has: [include] files = /etc/supervisord.d/*.ini
|
||||
# 6. systemd units (gunicorn, novncd, socketiod and the job worker, as nginx) and nginx
|
||||
for u in cloud novncd socketiod worker; do sed 's/^\(User\|Group\)=.*/\1=nginx/' conf/systemd/webvirt-$u.service > /etc/systemd/system/webvirt-$u.service; done
|
||||
cp conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/
|
||||
|
||||
# 7. Ownership, private files, start
|
||||
chown -R nginx:nginx /srv/webvirtcloud
|
||||
chmod 700 data && chmod 600 webvirtcloud/settings.py db.sqlite3
|
||||
systemctl enable nginx supervisord
|
||||
nginx -t && systemctl restart nginx supervisord
|
||||
systemctl daemon-reload && systemctl enable --now webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker
|
||||
systemctl enable nginx && nginx -t && systemctl restart nginx
|
||||
```
|
||||
|
||||
### First login
|
||||
|
|
@ -296,15 +294,15 @@ If libvirt warns `Host SMBIOS information is not available`, install `dmidecode`
|
|||
Where to set them:
|
||||
|
||||
- **Docker:** the `environment:` list of `docker-compose.override.yml`; every process in the container gets it.
|
||||
- **Installer and manual installation:** edit `webvirtcloud/settings.py`, or put the same `environment=` line in `[program:webvirtcloud]`, `[program:novncd]` and `[program:webvirt-worker]` of the supervisor config (novncd and the worker read the database too; supervisor takes one `environment=` per program, so merge the worker's into its `WEBVIRTCLOUD_LOG_FILE` line) and export the variables before running `manage.py`.
|
||||
- **gunicorn** runs at most 8 workers (fewer on hosts with under 4 CPUs); to change it, set `GUNICORN_CMD_ARGS="--workers N"` in the `[program:webvirtcloud]` environment or in `docker-compose.override.yml`.
|
||||
- **Installer and manual installation:** edit `webvirtcloud/settings.py`, or put them in `/etc/default/webvirtcloud` (root, mode 600), one `NAME='value'` per line (single quotes: systemd and the shell then read the same value); all four services read it. Then `systemctl restart webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker`, and load the file before running `manage.py`: `set -a; . /etc/default/webvirtcloud; set +a`.
|
||||
- **gunicorn** runs at most 8 workers (fewer on hosts with under 4 CPUs); to change it, set `GUNICORN_CMD_ARGS=--workers N` in a drop-in of `webvirt-cloud` (`systemctl edit webvirt-cloud`: `[Service]` and `Environment="GUNICORN_CMD_ARGS=--workers N"`) or in `docker-compose.override.yml`.
|
||||
|
||||
### HTTPS and reverse proxy
|
||||
|
||||
For a panel served over HTTPS:
|
||||
|
||||
- set `WEBVIRTCLOUD_HTTPS=1`: session and CSRF cookies become HTTPS-only, HTTP is redirected to HTTPS (except `/datasource/`, which VMs fetch over HTTP), and HSTS is sent for one year;
|
||||
- add the HTTPS origin to `CSRF_TRUSTED_ORIGINS`, e.g. `environment=CSRF_TRUSTED_ORIGINS="https://wvc.example.com",WEBVIRTCLOUD_HTTPS="1"` in supervisor;
|
||||
- add the HTTPS origin to `CSRF_TRUSTED_ORIGINS`, e.g. `CSRF_TRUSTED_ORIGINS=https://wvc.example.com` and `WEBVIRTCLOUD_HTTPS=1` in `/etc/default/webvirtcloud`;
|
||||
- set the public noVNC port to the proxy's port (the bundled nginx config already proxies `/novncd/`): `WS_PUBLIC_PORT = 443` in `webvirtcloud/settings.py`, or `WS_PUBLIC_PORT=443` in `docker-compose.override.yml` for Docker;
|
||||
|
||||
TLS can end at the bundled nginx or at a proxy in front of it; such a proxy must send `X-Forwarded-Proto: https`. Failed logins are counted per client address, which the bundled nginx passes in `X-Real-IP`. A proxy that replaces the bundled nginx must set `X-Real-IP` itself, and its address must be in `LOGIN_TRUSTED_PROXIES` in `settings.py`. With a proxy in front of the bundled nginx, configure nginx's `set_real_ip_from` / `real_ip_header` for that proxy, or all clients share its address.
|
||||
|
|
@ -393,7 +391,7 @@ Set `OTP_ENABLED = True` in `settings.py` to ask for a one-time code at login. I
|
|||
|
||||
### Serial console
|
||||
|
||||
A VM without graphics (no `<graphics>` device, a `<console type='pty'>`) opens a serial console (xterm.js) instead of VNC. It is off by default. To turn it on, set `WEBVIRTCLOUD_SERIAL_CONSOLE=1` (Docker: in `docker-compose.override.yml`, then `docker compose -p webvirtcloud up -d`) or `SERIAL_CONSOLE_ENABLED = True` in `settings.py` and restart socketiod.
|
||||
A VM without graphics (no `<graphics>` device, a `<console type='pty'>`) opens a serial console (xterm.js) instead of VNC. It is off by default. To turn it on, set `WEBVIRTCLOUD_SERIAL_CONSOLE=1` (Docker: in `docker-compose.override.yml`, then `docker compose -p webvirtcloud up -d`) or `SERIAL_CONSOLE_ENABLED = True` in `settings.py` and `systemctl restart webvirt-cloud webvirt-socketiod`.
|
||||
|
||||
- The VM page's Settings → Console switches a shut-off VM between VNC and serial (Console type). A new VNC console takes the form's other fields; on a TCP or TLS compute it needs Listen on: All interfaces (only SSH computes reach a localhost console).
|
||||
- The guest must use its serial port: a login prompt needs `systemctl enable --now serial-getty@ttyS0`, boot messages need the kernel parameter `console=ttyS0,115200`. The console shows only what the guest writes after it opens; press Enter for a new prompt.
|
||||
|
|
@ -401,17 +399,6 @@ A VM without graphics (no `<graphics>` device, a `<console type='pty'>`) opens a
|
|||
- It accepts the console page's signed token, as noVNC does: whoever gets that token within 120 s gets the console, and an open console stays open after its user loses access to the VM.
|
||||
- One console per VM, at most 20 at a time; a second one shows "refused".
|
||||
|
||||
### Running novncd with runit (Debian)
|
||||
|
||||
Instead of Supervisor, `novncd` can run under `runit`. First set `autostart=false` for `[program:novncd]` in the supervisor config and run `sudo supervisorctl update`, so the two do not compete for the port:
|
||||
|
||||
```bash
|
||||
sudo apt install -y runit runit-systemd
|
||||
sudo mkdir -p /etc/service/novncd/
|
||||
sudo ln -s /srv/webvirtcloud/conf/runit/novncd.sh /etc/service/novncd/run
|
||||
sudo systemctl start runit.service
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
Every update starts with a backup in its own directory (mode 700, named by date) that holds the database, the commit it was taken from and, for installer and manual installations, `settings.py` and the nginx config. The database is copied with SQLite's backup API, which also finishes a write interrupted by a crash. This covers sqlite only; with PostgreSQL (`WEBVIRTCLOUD_DB_HOST`), back up that database yourself before updating.
|
||||
|
|
@ -434,6 +421,19 @@ docker compose run --rm --no-deps -T --entrypoint /srv/webvirtcloud/venv/bin/pyt
|
|||
docker compose up -d
|
||||
```
|
||||
|
||||
### Moving from supervisor to systemd
|
||||
|
||||
Versions up to v3.0.0 ran the panel under supervisor. Once, before the update steps below, stop it there, keep its config and remove it:
|
||||
|
||||
```bash
|
||||
supervisorctl stop webvirtcloud novncd socketiod webvirt-worker
|
||||
mv /etc/supervisor/conf.d/webvirtcloud.conf /root/webvirtcloud-supervisor.conf # Debian / Ubuntu
|
||||
mv /etc/supervisord.d/webvirtcloud.ini /root/webvirtcloud-supervisor.conf # RHEL / openSUSE
|
||||
supervisorctl update
|
||||
```
|
||||
|
||||
Move the `environment=` values of that config into `/etc/default/webvirtcloud` (root, mode 600), one `NAME='value'` per line; leave out the worker's `WEBVIRTCLOUD_LOG_FILE`. Step 4 installs and starts the systemd units. Remove supervisor once nothing else uses it (on a compute node, gstfsd may).
|
||||
|
||||
### Installer and manual installation
|
||||
|
||||
`git pull` never overwrites `webvirtcloud/settings.py` or `/etc/nginx/conf.d/webvirtcloud.conf`; steps 2 and 4 bring them up to date. Run the steps from a root shell; they use `$b`, so in a new shell set it again to the backup directory.
|
||||
|
|
@ -441,31 +441,22 @@ docker compose up -d
|
|||
1. Stop the panel, back up and pull:
|
||||
|
||||
```bash
|
||||
supervisorctl stop webvirtcloud novncd socketiod webvirt-worker
|
||||
systemctl stop webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker
|
||||
# once: root may use the repo, which belongs to the service user
|
||||
git config --global --add safe.directory /srv/webvirtcloud
|
||||
b=/root/webvirtcloud-backup-$(date +%Y%m%d-%H%M%S)
|
||||
cd /srv/webvirtcloud &&
|
||||
! supervisorctl status webvirtcloud novncd socketiod webvirt-worker | grep RUNNING &&
|
||||
! systemctl is-active --quiet webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker &&
|
||||
mkdir -m 700 "$b" &&
|
||||
venv/bin/python3 -c "import sqlite3,sys; sqlite3.connect('db.sqlite3').backup(sqlite3.connect(sys.argv[1]))" "$b/db.sqlite3" &&
|
||||
cp -p webvirtcloud/settings.py /etc/nginx/conf.d/webvirtcloud.conf "$b"/ &&
|
||||
{ [ ! -f /etc/default/webvirtcloud ] || cp -p /etc/default/webvirtcloud "$b"/; } &&
|
||||
git rev-parse HEAD > "$b/commit" &&
|
||||
git ls-files -z --others --exclude-standard -- '*/migrations/*.py' | tar --null -T - --remove-files -cf "$b/local-migrations.tar" &&
|
||||
git checkout -- static/css/wvc-main.min.css dev/scss/wvc-main.scss &&
|
||||
git checkout master && git pull
|
||||
```
|
||||
|
||||
Until step 4 installs the worker, `supervisorctl` reports "no such process" for `webvirt-worker` on a first update from a version without it. Then keep the supervisor config for step 4 and the restore (`supervisor.conf` in the backup directory):
|
||||
|
||||
```bash
|
||||
cp -p /etc/supervisor/conf.d/webvirtcloud.conf "$b/supervisor.conf" # Debian / Ubuntu
|
||||
```
|
||||
|
||||
```bash
|
||||
cp -p /etc/supervisord.d/webvirtcloud.ini "$b/supervisor.conf" # RHEL / openSUSE
|
||||
```
|
||||
|
||||
2. Rebuild `settings.py` from the template (the file keeps its owner and mode), then put back your own values; the `diff` lists them:
|
||||
|
||||
```bash
|
||||
|
|
@ -491,31 +482,29 @@ docker compose up -d
|
|||
|
||||
Installers from before September 2025 generated migrations of their own; step 1 moved them into `local-migrations.tar`. One of them has the name of a tracked migration, which `migrate` would skip; the second line marks it unapplied so that the tracked one runs.
|
||||
|
||||
4. Update the nginx config the same way as `settings.py`, and the supervisor config (it gains the `webvirt-worker` program):
|
||||
4. Update the nginx config the same way as `settings.py`:
|
||||
|
||||
```bash
|
||||
cp conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/webvirtcloud.conf
|
||||
diff "$b/webvirtcloud.conf" /etc/nginx/conf.d/webvirtcloud.conf
|
||||
```
|
||||
|
||||
Debian / Ubuntu:
|
||||
Put back your own lines (`server_name`, TLS, the noVNC port). Install the systemd units; your own service settings stay in `/etc/default/webvirtcloud` and in drop-ins. Debian / Ubuntu:
|
||||
|
||||
```bash
|
||||
cp conf/supervisor/webvirtcloud.conf /etc/supervisor/conf.d/
|
||||
diff "$b/supervisor.conf" /etc/supervisor/conf.d/webvirtcloud.conf
|
||||
cp conf/systemd/webvirt-{cloud,novncd,socketiod,worker}.service /etc/systemd/system/
|
||||
```
|
||||
|
||||
RHEL / openSUSE:
|
||||
|
||||
```bash
|
||||
sed 's/^user=.*/user=nginx/' conf/supervisor/webvirtcloud.conf > /etc/supervisord.d/webvirtcloud.ini
|
||||
diff "$b/supervisor.conf" /etc/supervisord.d/webvirtcloud.ini
|
||||
for u in cloud novncd socketiod worker; do sed 's/^\(User\|Group\)=.*/\1=nginx/' conf/systemd/webvirt-$u.service > /etc/systemd/system/webvirt-$u.service; done
|
||||
```
|
||||
|
||||
Put back your own lines (`server_name`, TLS, the noVNC port, supervisor `environment=` settings), then reload nginx and start the panel:
|
||||
Then reload nginx and start the panel:
|
||||
|
||||
```bash
|
||||
nginx -t && systemctl reload nginx && supervisorctl update && supervisorctl start webvirtcloud novncd socketiod webvirt-worker
|
||||
nginx -t && systemctl reload nginx && systemctl daemon-reload && systemctl enable --now webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker
|
||||
```
|
||||
|
||||
Older versions collected static files into `static/`; `git clean -n static/` lists the leftovers, which can be deleted.
|
||||
|
|
@ -541,9 +530,9 @@ Installer and manual installation, from a root shell (`nginx:nginx` on RHEL / op
|
|||
|
||||
```bash
|
||||
b=/root/webvirtcloud-backup-YYYYMMDD-HHMMSS
|
||||
supervisorctl stop webvirtcloud novncd socketiod webvirt-worker
|
||||
systemctl stop webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker
|
||||
cd /srv/webvirtcloud &&
|
||||
! supervisorctl status webvirtcloud novncd socketiod webvirt-worker | grep RUNNING &&
|
||||
! systemctl is-active --quiet webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker &&
|
||||
git checkout -- static/css/wvc-main.min.css dev/scss/wvc-main.scss &&
|
||||
git checkout "$(cat "$b/commit")" &&
|
||||
tar -xf "$b/local-migrations.tar" &&
|
||||
|
|
@ -556,26 +545,13 @@ chown -R www-data:www-data /srv/webvirtcloud &&
|
|||
chmod 600 db.sqlite3 webvirtcloud/settings.py
|
||||
```
|
||||
|
||||
Restore the supervisor config, Debian / Ubuntu:
|
||||
Put back `/etc/default/webvirtcloud` if the backup has it (`cp -p "$b/webvirtcloud" /etc/default/`), then reload nginx and start the panel:
|
||||
|
||||
```bash
|
||||
cp "$b/supervisor.conf" /etc/supervisor/conf.d/webvirtcloud.conf
|
||||
nginx -t && systemctl reload nginx && systemctl start webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker
|
||||
```
|
||||
|
||||
RHEL / openSUSE:
|
||||
|
||||
```bash
|
||||
cp "$b/supervisor.conf" /etc/supervisord.d/webvirtcloud.ini
|
||||
```
|
||||
|
||||
Then reload nginx and start the panel:
|
||||
|
||||
```bash
|
||||
nginx -t && systemctl reload nginx &&
|
||||
supervisorctl update && supervisorctl start webvirtcloud novncd socketiod webvirt-worker
|
||||
```
|
||||
|
||||
When the restored version predates the worker, `supervisorctl` reports that `webvirt-worker` does not exist; the other programs start. A rollback leaves the clone on a detached HEAD at the restored commit; the update steps record that commit before they switch back to `master`.
|
||||
A version from before v3.0.0 has no worker: `systemctl disable --now webvirt-worker`. A rollback keeps the systemd units. A rollback leaves the clone on a detached HEAD at the restored commit; the update steps record that commit before they switch back to `master`.
|
||||
|
||||
### Behavior changes
|
||||
|
||||
|
|
@ -624,6 +600,7 @@ When the restored version predates the worker, `supervisorctl` reports that `web
|
|||
- Manual installs that keep their own `settings.py` copy the SQLite `OPTIONS` and `TEST` entries from `settings.py.template` and add `"operations"` to `INSTALLED_APPS`.
|
||||
- The SQLite database must be on a local file system (WAL).
|
||||
- Outside compose, stop the Docker container with `docker stop -t 95` so the worker can finish running jobs.
|
||||
- Installer and manual installations run the panel as systemd units (`webvirt-cloud`, `webvirt-novncd`, `webvirt-socketiod`, `webvirt-worker`) instead of supervisor; see [Moving from supervisor to systemd](#moving-from-supervisor-to-systemd). Service settings go into `/etc/default/webvirtcloud`, service output into the journal (`journalctl -u webvirt-cloud`); the app log stays in `data/`.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
USER="www-data"
|
||||
DJANGO_PROJECT="/srv/webvirtcloud"
|
||||
PYTHON="$DJANGO_PROJECT/venv/bin/python3"
|
||||
NOVNCD="$DJANGO_PROJECT/console/novncd"
|
||||
LOG="/var/log/novncd.log"
|
||||
|
||||
cd "$DJANGO_PROJECT" || exit 1
|
||||
|
||||
# make novncd debug, verbose
|
||||
#PARAMS="-d -v"
|
||||
|
||||
if [ -x /sbin/setuser ]; then
|
||||
if [ -n "$PARAMS" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
exec /sbin/setuser "$USER" "$PYTHON" "$NOVNCD" $PARAMS >> "$LOG" 2>&1
|
||||
else
|
||||
exec /sbin/setuser "$USER" "$PYTHON" "$NOVNCD" >> "$LOG" 2>&1
|
||||
fi
|
||||
elif command -v su >/dev/null 2>&1; then
|
||||
if [ -n "$PARAMS" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
exec su -s /bin/sh "$USER" -c "exec \"$PYTHON\" \"$NOVNCD\" $PARAMS" >> "$LOG" 2>&1
|
||||
else
|
||||
exec su -s /bin/sh "$USER" -c "exec \"$PYTHON\" \"$NOVNCD\"" >> "$LOG" 2>&1
|
||||
fi
|
||||
fi
|
||||
cd /srv/webvirtcloud || exit 1
|
||||
exec /sbin/setuser www-data /srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/console/novncd >> /var/log/novncd.log 2>&1
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
[program:webvirtcloud]
|
||||
command=/srv/webvirtcloud/venv/bin/gunicorn webvirtcloud.wsgi:application -c /srv/webvirtcloud/gunicorn.conf.py
|
||||
directory=/srv/webvirtcloud
|
||||
user=www-data
|
||||
autostart=true
|
||||
autorestart=true
|
||||
redirect_stderr=true
|
||||
|
||||
[program:novncd]
|
||||
command=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/console/novncd
|
||||
directory=/srv/webvirtcloud
|
||||
user=www-data
|
||||
autostart=true
|
||||
autorestart=true
|
||||
redirect_stderr=true
|
||||
|
||||
# Serial console daemon; it refuses connections while SERIAL_CONSOLE_ENABLED
|
||||
# is off in settings.py.
|
||||
[program:socketiod]
|
||||
command=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/console/socketiod
|
||||
directory=/srv/webvirtcloud
|
||||
user=www-data
|
||||
autostart=true
|
||||
autorestart=true
|
||||
redirect_stderr=true
|
||||
|
||||
# The job worker: one per installation. It drains running jobs for 60 s on
|
||||
# stop; supervisor waits a little longer before killing it.
|
||||
[program:webvirt-worker]
|
||||
command=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/manage.py run_worker
|
||||
directory=/srv/webvirtcloud
|
||||
user=www-data
|
||||
environment=WEBVIRTCLOUD_LOG_FILE="/srv/webvirtcloud/data/webvirtcloud-worker.log"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopwaitsecs=90
|
||||
redirect_stderr=true
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
# Ubuntu Service Files
|
||||
|
||||
I choose to install this service on Ubuntu 22.04
|
||||
|
||||
The process is not fully documented but I wanted to contribute the service files
|
||||
|
||||
The file webvirt is beeing installed into /etc/default/webvirt and allows you to easily change the location of the webvirtcloud installation path
|
||||
|
||||
The PATH variable being set for these services includes /usr/bin which contains the ssh executable. That is being used by webvirt-cloud and webvirt-novncd
|
||||
|
||||
Should the executable be located in another location please adjust the path
|
||||
|
||||
The error you should be seeing is "ssh executable not found"
|
||||
|
||||
|
||||
Use one of the two service managers: the installer sets up supervisor (`conf/supervisor/webvirtcloud.conf` runs the worker); these units are for manual installs without supervisor. Enabling both starts two workers; the second waits for the lease and does nothing.
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
FILEPATH=$(readlink -f "$0");
|
||||
SCRIPTPATH=$(dirname "$FILEPATH");
|
||||
cd "$SCRIPTPATH"
|
||||
cp webvirt-* /lib/systemd/system/
|
||||
cp webvirt /etc/default/
|
||||
echo Run to start services \"systemctl daemon-reload\; systemctl enable --now $(ls webvirt-* | tr "\n" " ")\"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
WEBVIRT_PATH="/srv/webvirtcloud"
|
||||
PATH="$WEBVIRT_PATH/venv/bin:/usr/bin"
|
||||
|
|
@ -1,23 +1,19 @@
|
|||
[Unit]
|
||||
Description=Webvirt Cloud Webinterface
|
||||
Description=WebVirtCloud panel (gunicorn)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
User=www-data
|
||||
Group=www-data
|
||||
LimitNOFILE=64000
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
EnvironmentFile=/etc/default/webvirt
|
||||
|
||||
ExecStart=/bin/bash -c "cd ${WEBVIRT_PATH};${WEBVIRT_PATH}/venv/bin/gunicorn webvirtcloud.wsgi:application -c ${WEBVIRT_PATH}/gunicorn.conf.py"
|
||||
|
||||
# Make sure stderr/stdout is captured in the systemd journal.
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
WorkingDirectory=/srv/webvirtcloud
|
||||
EnvironmentFile=-/etc/default/webvirtcloud
|
||||
ExecStart=/srv/webvirtcloud/venv/bin/gunicorn webvirtcloud.wsgi:application -c /srv/webvirtcloud/gunicorn.conf.py
|
||||
# gunicorn stops its workers itself; the rest of the group is killed after the timeout
|
||||
KillMode=mixed
|
||||
TimeoutStopSec=90
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
|||
|
|
@ -1,23 +1,16 @@
|
|||
[Unit]
|
||||
Description=Webvirt Cloud NOVNCD
|
||||
Description=WebVirtCloud VNC console proxy (novncd)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
User=www-data
|
||||
Group=www-data
|
||||
LimitNOFILE=64000
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
EnvironmentFile=/etc/default/webvirt
|
||||
|
||||
ExecStart=/bin/bash -c "cd ${WEBVIRT_PATH};${WEBVIRT_PATH}/venv/bin/python3 ${WEBVIRT_PATH}/console/novncd"
|
||||
|
||||
# Make sure stderr/stdout is captured in the systemd journal.
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
WorkingDirectory=/srv/webvirtcloud
|
||||
EnvironmentFile=-/etc/default/webvirtcloud
|
||||
ExecStart=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/console/novncd
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
[Unit]
|
||||
Description=Webvirt Cloud serial console (socketiod; refuses connections unless SERIAL_CONSOLE_ENABLED = True)
|
||||
Description=WebVirtCloud serial console (socketiod; refuses connections unless SERIAL_CONSOLE_ENABLED)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
User=www-data
|
||||
Group=www-data
|
||||
LimitNOFILE=64000
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
EnvironmentFile=/etc/default/webvirt
|
||||
|
||||
ExecStart=/bin/bash -c "cd ${WEBVIRT_PATH};${WEBVIRT_PATH}/venv/bin/python3 ${WEBVIRT_PATH}/console/socketiod"
|
||||
|
||||
# Make sure stderr/stdout is captured in the systemd journal.
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
WorkingDirectory=/srv/webvirtcloud
|
||||
EnvironmentFile=-/etc/default/webvirtcloud
|
||||
ExecStart=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/console/socketiod
|
||||
# gunicorn stops its worker itself; the consoles end with their ptys
|
||||
KillMode=mixed
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
|||
|
|
@ -4,16 +4,17 @@ Wants=network-online.target
|
|||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
User=www-data
|
||||
Group=www-data
|
||||
EnvironmentFile=/etc/default/webvirt
|
||||
ExecStart=/bin/bash -c "cd ${WEBVIRT_PATH}; WEBVIRTCLOUD_LOG_FILE=${WEBVIRT_PATH}/data/webvirtcloud-worker.log ${WEBVIRT_PATH}/venv/bin/python3 manage.py run_worker"
|
||||
WorkingDirectory=/srv/webvirtcloud
|
||||
EnvironmentFile=-/etc/default/webvirtcloud
|
||||
Environment=WEBVIRTCLOUD_LOG_FILE=/srv/webvirtcloud/data/webvirtcloud-worker.log
|
||||
ExecStart=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/manage.py run_worker
|
||||
# the worker finishes its jobs for up to 60 s; its libvirt connections stay meanwhile
|
||||
KillMode=mixed
|
||||
TimeoutStopSec=90
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ The platform provides:
|
|||
| **Frontend** | Django Templates, Bootstrap 5, Bootstrap Icons, jQuery | Server-rendered responsive and dynamic user interface |
|
||||
| **Identity & Security** | Django Auth, `django-otp` (2FA/TOTP), `django-auth-ldap` | Role-based authorization, two-factor authentication, and optional LDAP/Active Directory support |
|
||||
| **Web / WSGI Server** | Nginx + Gunicorn + WhiteNoise | Static file delivery and reverse proxy architecture |
|
||||
| **Process Manager** | Supervisor / Runit / Systemd | Background service management for Gunicorn, novncd, and socketiod |
|
||||
| **Process Manager** | systemd (hosts), runit (Docker) | Service management for Gunicorn, novncd, socketiod and the job worker |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ Built on Django REST Framework with `drf-nested-routers`, providing a structured
|
|||
1. **Gunicorn**: WSGI application server running `webvirtcloud.wsgi:application` (binds to a Unix socket or port 8000).
|
||||
2. **novncd**: Background WebSockify daemon translating VNC TCP ports to WebSockets on port 6080.
|
||||
3. **Nginx**: Front-facing reverse proxy handling ports 80/443, serving static assets directly, proxying dynamic web requests to Gunicorn, and routing WebSocket console traffic to `novncd`.
|
||||
4. **Supervisor / Runit / Systemd**: Process supervision managing Gunicorn and novncd daemon lifecycles with automatic restarts.
|
||||
4. **systemd / runit**: systemd units on hosts (`conf/systemd/`) and runit services in the Docker image (`conf/runit/`) run Gunicorn, novncd, socketiod and the job worker with automatic restarts.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -176,9 +176,9 @@ WebVirtCloud leverages a hybrid pattern: it combines the relational strengths of
|
|||
|
||||
WebVirtCloud installer and runtime dependencies support modern enterprise Linux distributions:
|
||||
|
||||
| Distribution Family | Target Versions | Package Manager | Init / Supervisor |
|
||||
| Distribution Family | Target Versions | Package Manager | Services |
|
||||
|---|---|---|---|
|
||||
| **Ubuntu** | 20.04, 22.04 LTS, 24.04 LTS | `apt` | Systemd / Supervisor |
|
||||
| **Debian** | 10, 11, 12 (Bookworm) | `apt` | Systemd / Supervisor / Runit |
|
||||
| **RHEL / Rocky / Alma** | 9.x, 10.x | `dnf` | Systemd / Supervisord |
|
||||
| **openSUSE / SLES** | openSUSE Leap 15.x, Tumbleweed, SLES 15 | `zypper` | Systemd / Supervisord |
|
||||
| **Ubuntu** | 20.04, 22.04 LTS, 24.04 LTS | `apt` | systemd |
|
||||
| **Debian** | 10, 11, 12 (Bookworm) | `apt` | systemd |
|
||||
| **RHEL / Rocky / Alma** | 9.x, 10.x | `dnf` | systemd |
|
||||
| **openSUSE / SLES** | openSUSE Leap 15.x, Tumbleweed, SLES 15 | `zypper` | systemd |
|
||||
|
|
|
|||
153
webvirtcloud.sh
153
webvirtcloud.sh
|
|
@ -64,6 +64,11 @@ if [ "$(id -u)" != "0" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ -f /etc/supervisor/conf.d/webvirtcloud.conf ] || [ -f /etc/supervisord.d/webvirtcloud.ini ]; then
|
||||
echo "WebVirtCloud runs under supervisor here: move it to systemd first (README: Updating, Moving from supervisor to systemd)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clear
|
||||
|
||||
readonly APP_USER="wvcuser"
|
||||
|
|
@ -202,13 +207,14 @@ configure_nginx () {
|
|||
|
||||
}
|
||||
|
||||
configure_supervisor () {
|
||||
# Copy template supervisor service for gunicorn and novnc
|
||||
echo " * Copying supervisor configuration"
|
||||
mkdir -p "$supervisor_conf_path" > /dev/null 2>&1
|
||||
cp "$APP_PATH"/conf/supervisor/webvirtcloud.conf "$supervisor_conf_path"/"$supervisor_file_name"
|
||||
nginx_group_escape="$(echo -n "$nginx_group"|sed -e 's/[](){}<>=:\!\?\+\|\/\&$*.^[]/\\&/g')"
|
||||
sed -i "s|^\\(user=\\).*|\\1$nginx_group_escape|" "$supervisor_conf_path/$supervisor_file_name"
|
||||
configure_systemd () {
|
||||
# The panel's services run as the web server's user; a re-run restarts them.
|
||||
units="webvirt-cloud webvirt-novncd webvirt-socketiod webvirt-worker"
|
||||
for unit in $units; do
|
||||
sed "s/^\\(User\\|Group\\)=.*/\\1=$nginx_group/" "$APP_PATH/conf/systemd/$unit.service" > "/etc/systemd/system/$unit.service" || exit 1
|
||||
done
|
||||
# shellcheck disable=SC2086
|
||||
systemctl daemon-reload && systemctl enable $units && systemctl restart $units || exit 1
|
||||
}
|
||||
|
||||
create_user () {
|
||||
|
|
@ -386,14 +392,6 @@ set_hosts () {
|
|||
fi
|
||||
}
|
||||
|
||||
restart_supervisor () {
|
||||
echo "* Setting Supervisor to start on boot and restart."
|
||||
log "systemctl enable $supervisor_service"
|
||||
#systemctl enable $supervisor_service
|
||||
log "systemctl restart $supervisor_service"
|
||||
#systemctl restart $supervisor_service
|
||||
}
|
||||
|
||||
restart_nginx () {
|
||||
echo "* Setting Nginx to start on boot and starting Nginx."
|
||||
log "systemctl enable nginx.service"
|
||||
|
|
@ -449,36 +447,24 @@ case $distro in
|
|||
distro=ubuntu
|
||||
nginx_group=www-data
|
||||
nginxfile=/etc/nginx/conf.d/$APP_NAME.conf
|
||||
supervisor_service=supervisor
|
||||
supervisor_conf_path=/etc/supervisor/conf.d
|
||||
supervisor_file_name=webvirtcloud.conf
|
||||
;;
|
||||
*debian*)
|
||||
echo " The installer has detected $distro version $version codename $codename."
|
||||
distro=debian
|
||||
nginx_group=www-data
|
||||
nginxfile=/etc/nginx/conf.d/$APP_NAME.conf
|
||||
supervisor_service=supervisor
|
||||
supervisor_conf_path=/etc/supervisor/conf.d
|
||||
supervisor_file_name=webvirtcloud.conf
|
||||
;;
|
||||
*centos*|*redhat*|*ol*|*rhel*|*rocky*|*Rocky*|*alma*)
|
||||
echo " The installer has detected $distro version $version."
|
||||
distro=centos
|
||||
nginx_group=nginx
|
||||
nginxfile=/etc/nginx/conf.d/$APP_NAME.conf
|
||||
supervisor_service=supervisord
|
||||
supervisor_conf_path=/etc/supervisord.d
|
||||
supervisor_file_name=webvirtcloud.ini
|
||||
;;
|
||||
*opensuse*|*sles*|*sled*|*suse*)
|
||||
echo " The installer has detected $distro version $version."
|
||||
distro=suse
|
||||
nginx_group=nginx
|
||||
nginxfile=/etc/nginx/conf.d/$APP_NAME.conf
|
||||
supervisor_service=supervisord
|
||||
supervisor_conf_path=/etc/supervisord.d
|
||||
supervisor_file_name=webvirtcloud.ini
|
||||
;;
|
||||
*Uos*|*uos*)
|
||||
# codename may be fuyu, kongzi, eagle or empty string.
|
||||
|
|
@ -491,14 +477,8 @@ case $distro in
|
|||
nginxfile=/etc/nginx/conf.d/$APP_NAME.conf
|
||||
if test "${codename}" == "eagle"; then
|
||||
nginx_group=www-data
|
||||
supervisor_service=supervisor
|
||||
supervisor_conf_path=/etc/supervisor/conf.d
|
||||
supervisor_file_name=webvirtcloud.conf
|
||||
else
|
||||
nginx_group=nginx
|
||||
supervisor_service=supervisord
|
||||
supervisor_conf_path=/etc/supervisord.d
|
||||
supervisor_file_name=webvirtcloud.ini
|
||||
fi
|
||||
;;
|
||||
*OpenEuler*|*openEuler*)
|
||||
|
|
@ -506,9 +486,6 @@ case $distro in
|
|||
distro=openEuler
|
||||
nginx_group=nginx
|
||||
nginxfile=/etc/nginx/conf.d/$APP_NAME.conf
|
||||
supervisor_service=supervisord
|
||||
supervisor_conf_path=/etc/supervisord.d
|
||||
supervisor_file_name=webvirtcloud.ini
|
||||
;;
|
||||
*)
|
||||
if [[ "$id_like" =~ suse ]]; then
|
||||
|
|
@ -516,9 +493,6 @@ case $distro in
|
|||
distro=suse
|
||||
nginx_group=nginx
|
||||
nginxfile=/etc/nginx/conf.d/$APP_NAME.conf
|
||||
supervisor_service=supervisord
|
||||
supervisor_conf_path=/etc/supervisord.d
|
||||
supervisor_file_name=webvirtcloud.ini
|
||||
else
|
||||
echo " The installer was unable to determine your OS. Exiting for safety."
|
||||
exit 1
|
||||
|
|
@ -593,7 +567,7 @@ case $distro in
|
|||
progress
|
||||
|
||||
echo "* Installing OS requirements."
|
||||
PACKAGES="git python3-venv python3-virtualenv python3-pip python3-dev python3-lxml libvirt-dev zlib1g-dev libxslt1-dev libsasl2-dev libldap2-dev nginx supervisor smbios-utils libsasl2-modules gcc pkg-config python3-guestfs uuid"
|
||||
PACKAGES="git python3-venv python3-virtualenv python3-pip python3-dev python3-lxml libvirt-dev zlib1g-dev libxslt1-dev libsasl2-dev libldap2-dev nginx smbios-utils libsasl2-modules gcc pkg-config python3-guestfs uuid"
|
||||
|
||||
install_packages
|
||||
|
||||
|
|
@ -604,10 +578,9 @@ case $distro in
|
|||
echo "* Configuring Nginx."
|
||||
configure_nginx
|
||||
|
||||
echo "* Configuring Supervisor."
|
||||
configure_supervisor
|
||||
echo "* Configuring systemd."
|
||||
configure_systemd
|
||||
|
||||
restart_supervisor
|
||||
restart_nginx
|
||||
else
|
||||
echo "Unsupported Debian version. Version found: $version"
|
||||
|
|
@ -624,7 +597,7 @@ case $distro in
|
|||
progress
|
||||
|
||||
echo "* Installing OS requirements."
|
||||
PACKAGES="git python3-venv python3-virtualenv python3-pip python3-dev python3-lxml libvirt-dev zlib1g-dev libxslt1-dev libsasl2-dev libldap2-dev nginx supervisor libsasl2-modules gcc pkg-config python3-guestfs"
|
||||
PACKAGES="git python3-venv python3-virtualenv python3-pip python3-dev python3-lxml libvirt-dev zlib1g-dev libxslt1-dev libsasl2-dev libldap2-dev nginx libsasl2-modules gcc pkg-config python3-guestfs"
|
||||
install_packages
|
||||
|
||||
set_hosts
|
||||
|
|
@ -634,10 +607,9 @@ case $distro in
|
|||
echo "* Configuring Nginx."
|
||||
configure_nginx
|
||||
|
||||
echo "* Configuring Supervisor."
|
||||
configure_supervisor
|
||||
echo "* Configuring systemd."
|
||||
configure_systemd
|
||||
|
||||
restart_supervisor
|
||||
restart_nginx
|
||||
else
|
||||
echo "Unsupported Ubuntu version. Version found: $version"
|
||||
|
|
@ -657,8 +629,8 @@ case $distro in
|
|||
log "dnf config-manager --set-enabled crb"
|
||||
fi
|
||||
|
||||
echo "* Adding wget & epel-release & supervisor repository."
|
||||
log "yum -y install wget epel-release supervisor"
|
||||
echo "* Adding wget & epel-release repository."
|
||||
log "yum -y install wget epel-release"
|
||||
|
||||
echo "* Installing OS requirements."
|
||||
PACKAGES="git python3-virtualenv python3-devel libvirt-devel python3-libvirt python3-ldap glibc gcc nginx python3-lxml python3-libguestfs iproute-tc cyrus-sasl-md5 openldap-devel cyrus-sasl-devel openssl-devel"
|
||||
|
|
@ -673,17 +645,14 @@ case $distro in
|
|||
echo "* Configuring Nginx."
|
||||
configure_nginx
|
||||
|
||||
echo "* Configuring Supervisor."
|
||||
log "pip3 install supervisor "
|
||||
configure_supervisor
|
||||
|
||||
set_firewall
|
||||
|
||||
set_firewall
|
||||
|
||||
set_selinux
|
||||
|
||||
restart_supervisor
|
||||
echo "* Configuring systemd."
|
||||
configure_systemd
|
||||
|
||||
restart_nginx
|
||||
|
||||
else
|
||||
echo "Unsupported RHEL Based OS($distro) version. Version found: $version"
|
||||
exit 1
|
||||
|
|
@ -709,15 +678,13 @@ case $distro in
|
|||
echo "* Configuring Nginx."
|
||||
configure_nginx
|
||||
|
||||
echo "* Configuring Supervisor."
|
||||
log "pip install supervisor "
|
||||
configure_supervisor
|
||||
|
||||
set_firewall
|
||||
|
||||
set_selinux
|
||||
|
||||
restart_supervisor
|
||||
echo "* Configuring systemd."
|
||||
configure_systemd
|
||||
|
||||
restart_nginx
|
||||
fi
|
||||
;;
|
||||
|
|
@ -737,15 +704,13 @@ case $distro in
|
|||
echo "* Configuring Nginx."
|
||||
configure_nginx
|
||||
|
||||
echo "* Configuring Supervisor."
|
||||
log "pip install supervisor "
|
||||
configure_supervisor
|
||||
|
||||
set_firewall
|
||||
|
||||
set_selinux
|
||||
|
||||
restart_supervisor
|
||||
echo "* Configuring systemd."
|
||||
configure_systemd
|
||||
|
||||
restart_nginx
|
||||
fi
|
||||
;;
|
||||
|
|
@ -768,64 +733,16 @@ case $distro in
|
|||
|
||||
set_hosts
|
||||
|
||||
# Supervisor on SUSE (available as python3-supervisor, supervisor, or via pip)
|
||||
if ! command -v supervisord >/dev/null 2>&1; then
|
||||
if zypper --non-interactive install -y python3-supervisor >/dev/null 2>&1; then
|
||||
echo " * python3-supervisor installed via zypper"
|
||||
elif zypper --non-interactive install -y supervisor >/dev/null 2>&1; then
|
||||
echo " * supervisor installed via zypper"
|
||||
else
|
||||
echo " * Installing supervisor via pip3"
|
||||
log "pip3 install supervisor"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ensure /etc/supervisord.d directory exists and is included in supervisord.conf
|
||||
mkdir -p /etc/supervisord.d
|
||||
if [ ! -f /etc/supervisord.conf ] && [ ! -f /etc/supervisor/supervisord.conf ]; then
|
||||
if command -v echo_supervisord_conf >/dev/null 2>&1; then
|
||||
echo_supervisord_conf > /etc/supervisord.conf
|
||||
echo -e "\n[include]\nfiles = /etc/supervisord.d/*.ini\n" >> /etc/supervisord.conf
|
||||
fi
|
||||
elif [ -f /etc/supervisord.conf ] && ! grep -q "/etc/supervisord.d" /etc/supervisord.conf; then
|
||||
echo -e "\n[include]\nfiles = /etc/supervisord.d/*.ini\n" >> /etc/supervisord.conf
|
||||
fi
|
||||
|
||||
# Ensure systemd service for supervisord exists if installed via pip
|
||||
if [ ! -f /usr/lib/systemd/system/supervisord.service ] && [ ! -f /etc/systemd/system/supervisord.service ]; then
|
||||
supervisord_bin="$(command -v supervisord 2>/dev/null || echo "/usr/local/bin/supervisord")"
|
||||
supervisorctl_bin="$(command -v supervisorctl 2>/dev/null || echo "/usr/local/bin/supervisorctl")"
|
||||
cat > /etc/systemd/system/supervisord.service <<SVCEOF
|
||||
[Unit]
|
||||
Description=Process Monitoring and Control Daemon
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=${supervisord_bin} -c /etc/supervisord.conf
|
||||
ExecStop=${supervisorctl_bin} shutdown
|
||||
ExecReload=${supervisorctl_bin} reload
|
||||
KillMode=process
|
||||
Restart=on-failure
|
||||
RestartSec=42s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
SVCEOF
|
||||
systemctl daemon-reload >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
install_webvirtcloud
|
||||
|
||||
echo "* Configuring Nginx."
|
||||
configure_nginx
|
||||
|
||||
echo "* Configuring Supervisor."
|
||||
configure_supervisor
|
||||
|
||||
set_firewall
|
||||
|
||||
restart_supervisor
|
||||
echo "* Configuring systemd."
|
||||
configure_systemd
|
||||
|
||||
restart_nginx
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""Every install type runs the worker as www-data, with its own log file and
|
||||
a stop timeout above the worker's 60 s grace."""
|
||||
"""Every install type runs the worker as the web server's user (www-data, or
|
||||
nginx where the installer and README substitute it), with its own log file
|
||||
and a stop timeout above the worker's 60 s grace."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
|
|
@ -26,16 +26,9 @@ class WorkerInstallTestCase(SimpleTestCase):
|
|||
self.assertIn("webvirtcloud-data:/srv/webvirtcloud/data", compose)
|
||||
self.assertNotIn("hostname:", compose)
|
||||
|
||||
def test_supervisor(self):
|
||||
conf = (BASE / "conf/supervisor/webvirtcloud.conf").read_text()
|
||||
block = re.search(r"\[program:webvirt-worker\](.*?)(\n\[|\Z)", conf, re.S).group(1)
|
||||
for text in ("manage.py run_worker", "user=www-data", "webvirtcloud-worker.log", "autorestart=true"):
|
||||
self.assertIn(text, block)
|
||||
self.assertRegex(block, r"stopwaitsecs=9\d")
|
||||
|
||||
def test_systemd_is_an_alternative(self):
|
||||
def test_systemd(self):
|
||||
unit = (BASE / "conf/systemd/webvirt-worker.service").read_text()
|
||||
self.assertIn("run_worker", unit)
|
||||
self.assertIn("Restart=on-failure", unit)
|
||||
for text in ("manage.py run_worker", "User=www-data", "webvirtcloud-worker.log", "KillMode=mixed",
|
||||
"EnvironmentFile=-/etc/default/webvirtcloud", "Restart=on-failure"):
|
||||
self.assertIn(text, unit)
|
||||
self.assertRegex(unit, r"TimeoutStopSec=9\d")
|
||||
self.assertIn("one of the two", (BASE / "conf/systemd/README.md").read_text())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue