# Makefile to install qemu-web-desktop.
# just type: make install
#
# required:
#   apache2 libapache2-mod-perl2 novnc websockify qemu-kvm bridge-utils qemu
#   iptables dnsmasq libcgi-pm-perl liblist-moreutils-perl libsys-cpu-perl
#   libsys-cpuload-perl libsys-meminfo-perl libnet-dns-perl confget
#   libproc-background-perl libproc-processtable-perl libemail-valid-perl 
#   libnet-smtps-perl libmail-imapclient-perl libnet-ldap-perl 
#   libemail-valid-perl libjson-perl libwww-perl libguestfs-tools libapache2-mpm-itk
#   libtext-qrcode-perl
# on ARM64, an EFI boot is required (e.g. qemu-efi-aarch64)
#
# NOTES:
#   you may have to tune the path to /etc/apache2/conf-available/serve-cgi-bin.conf
#   or other locations. The current makefile works best on Debian-class systems.
#
# make install
#   install   qemu-web-desktop
# make config
#   configure qemu-web-desktop
# make deps
#   install dependencies (before make install)
# make test
#   test
# make deb
#   build debian package
# make help
#   build the documentation files (requires help2man pandoc librsvg2-bin texlive-latex-base  	texlive-latex-recommended)

# alt man generation: pandoc -s -o qwdctl.1 --to man -f markdown-smart qwdctl.md

ARCH=

# auto detect system type
ifneq ("$(wildcard /etc/debian_version)","")
  ARCH = Debian
  $(info Detected Debian-type system)
else ifneq ("$(wildcard /etc/redhat-release)","")
  ARCH = RedHat
  $(info Detected RedHat-type system)
else ifneq ("$(wildcard /etc/arch-release)","")
  ARCH = Arch
  $(info Detected Arch-type system)
else ifneq ("$(wildcard /etc/bashrc_Apple_Terminal)","")
  ARCH = Darwin
  $(info Detected Darwin-type system - Apple)
endif

# auto detect type of CPU (for installation)
uname_m := $(shell uname -m)
QEMU.i386    := qemu-system-x86
QEMU.x86_64  := qemu-system-x86
QEMU.aarch64 := qemu-system-arm
QEMU.arm64   := qemu-system-arm

QEMU ?= $(QEMU.$(uname_m))

ifeq ($(ARCH),Debian)
  DIR_CGI_BIN         = /usr/lib/cgi-bin
  DIR_APACHE_CONF_QWD = /etc/apache2/conf-available
  APACHE_CONF         =
  DIR_WWW             = /var/www/html
else ifeq ($(ARCH),RedHat)
  DIR_CGI_BIN         = /var/www/cgi-bin
  DIR_APACHE_CONF_QWD = /etc/httpd/conf.d/
  APACHE_CONF         = /etc/httpd/conf/httpd.conf
  DIR_WWW             = /var/www/html
else ifeq ($(ARCH),Arch)
  DIR_CGI_BIN         = /srv/http/cgi-bin
  DIR_APACHE_CONF_QWD = /etc/httpd/conf/extra/
  APACHE_CONF         = /etc/httpd/conf/httpd.conf
  DIR_WWW             = /srv/http
else ifeq ($(ARCH),Darwin)
  DESTDIR            ?= $(shell brew --prefix)
  PERLDIR             = $(shell brew --prefix perl)
  DIR_CGI_BIN         = /var/www/cgi-bin
  DIR_APACHE_CONF_QWD = /etc/httpd/extra/
  APACHE_CONF         = /etc/httpd/httpd.conf
  DIR_WWW             = /var/www
else
  $(error Undefined target. Set system type with: make install ARCH=Debian|RedHat|Arch)
endif

all:

help:
	@help2man -o qwdctl.1 --no-discard-stderr -n 'control qemu-web-desktop' bin/qwdctl || true
	@pandoc ../README.md --to pdf > README.pdf || echo "WARNING: skip pdf doc (missing pandoc)"
	@echo "Usage: install qemu-web-desktop"
	@echo "make deps"
	@echo "  install dependencies"
	@echo "make install"
	@echo "  install qemu-web-desktop"
	@echo "make deb"
	@echo "  create debian package"

# ------------------------------------------------------------------------------
# dependencies

deps:
	@echo "Installing $(ARCH)-class dependencies"
ifeq ($(ARCH),Debian)
	sudo apt install apache2 libapache2-mod-perl2 novnc websockify $(QEMU) qemu-utils bridge-utils iptables dnsmasq libcgi-pm-perl liblist-moreutils-perl libsys-cpu-perl libsys-cpuload-perl libsys-meminfo-perl libnet-dns-perl confget libproc-background-perl libproc-processtable-perl libemail-valid-perl  libnet-smtps-perl libmail-imapclient-perl libnet-ldap-perl libemail-valid-perl libjson-perl libwww-perl libguestfs-tools libapache2-mpm-itk libtext-qrcode-perl libnet-ssh2-perl
	if [ "$(uname_m)" = "aarch64" -o "$(uname_m)" = "arm64" ]; then sudo apt install qemu-efi-aarch64; fi
else ifeq ($(ARCH),Arch)
	@echo "NOTE: You need 'yay' to be installed, and the AUR to be available."
	yay -Sy python-numpy python-setuptools mod_itk apache qemu-desktop bridge-utils qemu-img dnsmasq guestfs-tools perl-cgi perl-list-moreutils perl-sys-cpu perl-sys-meminfo perl-net-dns perl-proc-processtable perl-mail-imapclient perl-ldap perl-json perl-libwww mod_perl novnc websockify perl-proc-background perl-email-valid perl-net-smtps perl-text-qrcode perl-net-ssh2 confget
else ifeq ($(ARCH),RedHat)
	@echo "NOTE: This system-type is not fully supported"
	sudo dnf install mod_perl novnc python3-websockify crudini guestfs-tools perl-CGI perl-List-MoreUtils perl-Sys-CPU perl-Sys-MemInfo perl-Net-DNS perl-Proc-ProcessTable perl-Email-Valid perl-Net-SMTPS perl-Mail-IMAPClient perl-LDAP perl-JSON perl-libwww-perl perl-Text-QRCode perl-Net-SSH2 perl-Net-Ping perl-CPAN
	sudo cpan Proc::Background
else ifeq ($(ARCH),Darwin)
	@echo "NOTE: This system-type is not properly supported"
	brew install apache2 qemu perl python3 python-setuptools grep wget gnu-sed nano
	# install PERL CPAN modules
	# WARNING: Net::SMTPS fails installation on Mac
	PERL_MM_OPT="INSTALL_BASE=$(PERLDIR)/lib/perl5/site_perl" cpan CGI Cwd File::Temp File::Path File::Basename File::Copy List::MoreUtils
	PERL_MM_OPT="INSTALL_BASE=$(PERLDIR)/lib/perl5/site_perl" cpan List::Util IO::Socket::INET IO::Socket::IP JSON Proc::Background
	PERL_MM_OPT="INSTALL_BASE=$(PERLDIR)/lib/perl5/site_perl" cpan Proc::ProcessTable Proc::Killfam System::CPU Sys::MemInfo Email::Valid
	PERL_MM_OPT="INSTALL_BASE=$(PERLDIR)/lib/perl5/site_perl" cpan Mail::IMAPClient LWP::UserAgent Net::Ping Net::LDAP Net::SSH2 URI
	# install websockify
	$(cd /tmp; wget https://github.com/novnc/websockify/archive/refs/tags/v0.13.0.tar.gz; tar xzf v0.13.0.tar.gz; cd websockify-0.13.0; python3 setup.py build; python3 setup.py build; )
	# install novnc
	if [ ! -d "$(DESTDIR)/share/novnc" ]; then bash -c "cd /tmp; wget https://github.com/novnc/noVNC/archive/refs/tags/v1.6.0.tar.gz; tar xzf v1.6.0.tar.gz; cp -r noVNC-1.6.0 $(DESTDIR)/share/novnc"; fi
endif
	@echo "[OK] Dependencies installed for $(ARCH)"
	@echo "You may now proceed with: make install"

# ------------------------------------------------------------------------------
# install

install: copy config

copy:
	@echo "Installing QWD files for $(ARCH)-type system"
ifeq ($(ARCH),Darwin)
	# create directories (install command is broken - we use mkdir/cp)
	mkdir -p                            $(DESTDIR)$(prefix)/etc/qemu-web-desktop
	mkdir -p                            $(DESTDIR)$(prefix)/etc/qemu-web-desktop/config.d
	mkdir -p                            $(DESTDIR)$(prefix)/bin
	mkdir -p                            $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop
	mkdir -p                            $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop/images
	mkdir -p                            $(DESTDIR)$(prefix)/usr/share/doc/qemu-web-desktop
	mkdir -p                            $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines
	mkdir -p                            $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/snapshots
	# common install
	cp         machines.conf            $(DESTDIR)$(prefix)/etc/qemu-web-desktop/
	cp         config.pl                $(DESTDIR)$(prefix)/etc/qemu-web-desktop/
	cp         html/desktop/index.html  $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop
	cp         html/desktop/style.css   $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop
	cp         html/desktop/images/*    $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop/images
	# cp         qwdctl.1                 $(DESTDIR)$(prefix)/usr/share/man/man1/qwdctl.1
	cp         README.pdf               $(DESTDIR)$(prefix)/usr/share/doc/qemu-web-desktop
	cp         bin/qwdctl               $(DESTDIR)$(prefix)/bin/
	cp         html/desktop/machines/*  $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines
	# system specific locations
	mkdir -p                            $(DESTDIR)$(prefix)$(DIR_WWW)
	# mkdir -p                            $(DESTDIR)$(prefix)$(DIR_APACHE_CONF_QWD)
	# cp apache.conf                      $(DESTDIR)$(prefix)$(DIR_APACHE_CONF_QWD)/qemu-web-desktop.conf
	mkdir -p                            $(DESTDIR)$(prefix)$(DIR_CGI_BIN)
	cp cgi-bin/qemu-web-desktop.pl      $(DESTDIR)$(prefix)$(DIR_CGI_BIN)/qemu-web-desktop.pl
else
	# create directories
	install -D -d                       $(DESTDIR)$(prefix)/etc/qemu-web-desktop
	install -D -d                       $(DESTDIR)$(prefix)/usr/bin
	install -D -d                       $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop
	install -D -d                       $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop/images
	install -D -d                       $(DESTDIR)$(prefix)/usr/share/doc/qemu-web-desktop
	install -D -d                       $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines
	install -D -d                       $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/snapshots
	# common install
	install -D machines.conf            $(DESTDIR)$(prefix)/etc/qemu-web-desktop/
	install -D config.pl                $(DESTDIR)$(prefix)/etc/qemu-web-desktop/
	install -D html/desktop/index.html  $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop
	install -D html/desktop/style.css   $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop
	install -D html/desktop/images/*    $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop/images
	install -D qwdctl.1                 $(DESTDIR)$(prefix)/usr/share/man/man1/qwdctl.1
	install -D README.pdf               $(DESTDIR)$(prefix)/usr/share/doc/qemu-web-desktop
	install -D bin/qwdctl               $(DESTDIR)$(prefix)/usr/bin/
	install -D html/desktop/machines/*  $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines
	# system specific locations
	install -D -d                          $(DESTDIR)$(prefix)$(DIR_WWW)
	install -D -d                          $(DESTDIR)$(prefix)$(DIR_APACHE_CONF_QWD)
	install apache.conf                    $(DESTDIR)$(prefix)$(DIR_APACHE_CONF_QWD)/qemu-web-desktop.conf
	install -D -d                          $(DESTDIR)$(prefix)$(DIR_CGI_BIN)
	install -D cgi-bin/qemu-web-desktop.pl $(DESTDIR)$(prefix)$(DIR_CGI_BIN)/qemu-web-desktop.pl
	# system specific actions
ifneq ($(ARCH),Debian)
	sed -i 's|Alias /qemu-web-desktop|#Alias /qemu-web-desktop|'  $(DESTDIR)$(prefix)$(DIR_APACHE_CONF_QWD)/qemu-web-desktop.conf
	sed -i 's/config{service_port_multiple}    = 0/config{service_port_multiple}    = 1/' $(DESTDIR)$(prefix)/etc/qemu-web-desktop//config.pl
	sed -i 's/machines_insert=no/machines_insert=yes/'            $(DESTDIR)$(prefix)/usr/bin/qwdctl
endif
endif
	-mv $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop/machines/* $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines/
	chmod a+wxr                         $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop
	chmod a+xrw                         $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines
	chmod u+xrw                         $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/snapshots
	find                                $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html -type f -exec chmod a+r {} +
	find                                $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html -type d -exec chmod a+rx {} +
	chmod 755                           $(DESTDIR)$(prefix)$(DIR_CGI_BIN)/qemu-web-desktop.pl
	@echo "[OK] QWD Installation complete for $(ARCH)."
	@echo "You may now proceed with: make config"

# ------------------------------------------------------------------------------
# post-install/auto configure

config:
	@echo "Post QWD installation steps (auto-configure) for $(ARCH)"
	ln -sf $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop  $(DESTDIR)$(prefix)$(DIR_WWW)/
	ln -sf $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines        $(DESTDIR)$(prefix)$(DIR_WWW)/desktop/
ifeq ($(ARCH),Debian)
	-adduser --system --home     $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop --force-badname _qemu-web-desktop
	-chown -R _qemu-web-desktop: $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop
	systemctl enable  apache2
	a2enconf qemu-web-desktop
	a2enmod  cgi
	a2enmod  include
	systemctl restart apache2
	chmod 755 /etc/qemu-ifup
endif
ifeq ($(ARCH),Arch)
	useradd --system -m --home-dir         $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop --badname _qemu-web-desktop
	chown -R _qemu-web-desktop             $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop
	ln -sf $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop  $(DESTDIR)$(prefix)$(DIR_WWW)/qemu-web-desktop
	sed -i 's|/usr/share/novnc|$(DESTDIR)$(prefix)/usr/share/webapps/novnc|' $(DESTDIR)$(prefix)/etc/qemu-web-desktop/config.pl
	# MPM ITK requires prefork, that conflicts with mpm_event
	sed -i 's/LoadModule mpm_event/#LoadModule mpm_event/'              $(DESTDIR)$(prefix)$(APACHE_CONF)
	sed -i 's/#LoadModule mpm_prefork/LoadModule mpm_prefork/'          $(DESTDIR)$(prefix)$(APACHE_CONF)
	grep -q "mpm_itk"          $(DESTDIR)$(prefix)$(APACHE_CONF) || echo "LoadModule mpm_itk_module modules/mpm_itk.so" >> $(DESTDIR)$(prefix)$(APACHE_CONF)
	grep -q "qemu-web-desktop" $(DESTDIR)$(prefix)$(APACHE_CONF) || echo "Include conf/extra/qemu-web-desktop.conf" >> $(DESTDIR)$(prefix)$(APACHE_CONF)
	systemctl enable httpd
	systemctl daemon-reload
	systemctl restart httpd
endif
ifeq ($(ARCH),RedHat)
	# There is no available MPM ITK module :-(
	chown -R apache                                                        $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop
	ln -sf $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop     $(DESTDIR)$(prefix)$(DIR_WWW)/qemu-web-desktop
	usermod -a -G kvm apache
	systemctl enable  httpd
	systemctl daemon-reload
	systemctl restart httpd
	# SElinux permissions: allow port 6080 (update if config.pl changes).
	# Currently this does not work: we get a KVM error from httpd daemon
	semanage port -a -t http_port_t -p tcp 6080 || true
	semanage port -a -t http_port_t -p tcp 5901 || true
	setsebool -P httpd_can_network_relay   1
	setsebool -P httpd_can_network_connect 1
	setsebool -P httpd_read_user_content 1
	@echo "WARNING: $(ARCH): the web service will probably not work. Use: qwdctl start VM|ISO"
endif
ifeq ($(ARCH),Darwin)
	ln -sf $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop  $(DESTDIR)$(prefix)$(DIR_WWW)/qemu-web-desktop
	gsed -i 's|/usr/share/novnc|$(DESTDIR)$(prefix)/share/novnc|' $(DESTDIR)$(prefix)/etc/qemu-web-desktop/config.pl
	@echo "WARNING: $(ARCH): the web service will NOT work. Use: qwdctl start VM|ISO"
endif
	ln -sf $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/machines.html   $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop/html/desktop
	@echo " "
	@echo "[OK] QWD Configuration complete for $(ARCH)."
ifneq ($(ARCH),Darwin)
	qwdctl download # can not be used on Mac OSX as confget/crudini is not on brew
	@echo "Now connect to       http://localhost/qemu-web-desktop for immediate use."
endif
	@echo "or launch a VM with: qwdctl start VM"
	@echo "or refer to          https://gitlab.com/soleil-data-treatment/soleil-software-projects/qemu-web-desktop"
	@echo "to configure the service."

# ------------------------------------------------------------------------------

test:
	qwdctl stop
	if timeout 10 perl cgi-bin/qemu-web-desktop.pl --dir_snapshots=/tmp --dir_cfg=/tmp --dir_machines=html/desktop/machines/ --oneshot=1 --machine=TinyCore-current.iso = 124; then echo "OK"; fi
	@echo Test OK

uninstall:
	-rm -rf $(DESTDIR)$(prefix)/etc/qemu-web-desktop/
	-rm -rf $(DESTDIR)$(prefix)/usr/share/qemu-web-desktop
	-rm -rf $(DESTDIR)$(prefix)/usr/share/doc/qemu-web-desktop
	-rm -f  $(DESTDIR)$(prefix)/usr/share/man/man1/qwdctl.*
	-rm -f  $(DESTDIR)$(prefix)/usr/bin/qwdctl
	-rm -rf $(DESTDIR)$(prefix)/var/lib/qemu-web-desktop/
	-rm -rf $(DESTDIR)$(prefix)$(DIR_WWW)/qemu-web-desktop
	-rm -rf $(DESTDIR)$(prefix)$(DIR_WWW)/desktop
	-rm -f  $(DESTDIR)$(prefix)$(DIR_APACHE_CONF_QWD)/qemu-web-desktop.conf
	-rm -f  $(DESTDIR)$(prefix)$(DIR_CGI_BIN)/qemu-web-desktop.pl
	if [ -e $(DESTDIR)$(prefix)/etc/httpd/conf/httpd.conf ]; then \
	  sed -i 's|Include conf/extra/qemu-web-desktop.conf|#Include conf/extra/qemu-web-desktop.conf|' $(DESTDIR)$(prefix)$(APACHE_CONF); \
	fi
	-apachectl restart
	-killall -9 websockify
	-deluser _qemu-web-desktop || userdel _qemu-web-desktop || true
	@echo "[OK] QWD uninstalled."

.PHONY: all install uninstall
.NOTPARALLEL: copy config

