diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 01ceee7e..74c2b8e4 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -50,10 +50,17 @@ jobs: - name: Install Required packages run: | - sudo apt-get install -y libvirt-dev python3-lxml zlib1g-dev libxslt1-dev + sudo apt-get install -y python3-virtualenv libvirt-dev python3-lxml zlib1g-dev libxslt1-dev + + - name: Create & Activate VENV + run: | + python3 -m venv venv + source venv/bin/activate + - name: Install dependencies run: | python3 -m pip install --upgrade pip + pip3 install wheel if [ -f dev/requirements.txt ]; then pip3 install -r dev/requirements.txt; else pip3 install -r conf/requirements.txt; fi ################################ # Run Linter against code base # @@ -61,6 +68,7 @@ jobs: - name: Lint Code Base uses: docker://github/super-linter:latest env: + FILTER_REGEX_EXCLUDE: .*(static|scss|venv|locale)/.* DEFAULT_BRANCH: master GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VALIDATE_ANSIBLE: false diff --git a/Dockerfile b/Dockerfile index 0349facb..91f9f129 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,52 +9,53 @@ CMD ["/sbin/my_init"] RUN echo 'APT::Get::Clean=always;' >> /etc/apt/apt.conf.d/99AutomaticClean -RUN apt-get update -qqy -RUN DEBIAN_FRONTEND=noninteractive apt-get -qyy install \ - -o APT::Install-Suggests=false \ +RUN apt-get update -qqy \ + && DEBIAN_FRONTEND=noninteractive apt-get -qyy install \ + --no-install-recommends \ git \ - python3-virtualenv \ + python3-venv \ python3-dev \ python3-lxml \ - virtualenv \ libvirt-dev \ zlib1g-dev \ nginx \ - libsasl2-modules + pkg-config \ + gcc \ + libsasl2-modules \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -ADD . /srv/webvirtcloud +COPY . /srv/webvirtcloud RUN chown -R www-data:www-data /srv/webvirtcloud # Setup webvirtcloud -RUN cd /srv/webvirtcloud && \ - virtualenv --python=python3 venv && \ +WORKDIR /srv/webvirtcloud +RUN python3 -m venv venv && \ . venv/bin/activate && \ pip3 install -U pip && \ + pip3 install wheel && \ pip3 install -r conf/requirements.txt && \ chown -R www-data:www-data /srv/webvirtcloud -RUN cd /srv/webvirtcloud && . venv/bin/activate && \ - python3 manage.py migrate && \ +RUN . venv/bin/activate && \ + python3 manage.py migrate && \ chown -R www-data:www-data /srv/webvirtcloud # Setup Nginx -RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf && \ +RUN printf "\n%s" "daemon off;" >> /etc/nginx/nginx.conf && \ rm /etc/nginx/sites-enabled/default && \ chown -R www-data:www-data /var/lib/nginx -ADD conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/ +COPY conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/ # Register services to runit RUN mkdir /etc/service/nginx && \ mkdir /etc/service/nginx-log-forwarder && \ mkdir /etc/service/webvirtcloud && \ mkdir /etc/service/novnc -ADD conf/runit/nginx /etc/service/nginx/run -ADD conf/runit/nginx-log-forwarder /etc/service/nginx-log-forwarder/run -ADD conf/runit/novncd.sh /etc/service/novnc/run -ADD conf/runit/webvirtcloud.sh /etc/service/webvirtcloud/run +COPY conf/runit/nginx /etc/service/nginx/run +COPY conf/runit/nginx-log-forwarder /etc/service/nginx-log-forwarder/run +COPY conf/runit/novncd.sh /etc/service/novnc/run +COPY conf/runit/webvirtcloud.sh /etc/service/webvirtcloud/run # Define mountable directories. #VOLUME [] diff --git a/accounts/forms.py b/accounts/forms.py index 12d754d8..cbd34256 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -1,6 +1,6 @@ from appsettings.settings import app_settings from django.contrib.auth import get_user_model -from django.forms import ModelForm, ValidationError +from django.forms import EmailField, Form, ModelForm, ValidationError from django.utils.translation import gettext_lazy as _ from .models import UserInstance, UserSSHKey @@ -69,3 +69,7 @@ def save(self, commit=True): class Meta: model = UserSSHKey fields = ('keyname', 'keypublic') + + +class EmailOTPForm(Form): + email = EmailField(label=_('Email')) diff --git a/accounts/templates/account.html b/accounts/templates/account.html index 3775a63f..b44aa8ec 100644 --- a/accounts/templates/account.html +++ b/accounts/templates/account.html @@ -8,7 +8,15 @@ {% block page_heading %}{% trans "User Profile" %}: {{ user }}{% endblock page_heading %} {% block page_heading_extra %} - +{% if otp_enabled %} + + {% icon 'qrcode' %} + +{% endif %} + + {% icon 'pencil' %} + + {% icon 'plus' %} {% endblock page_heading_extra %} @@ -21,11 +29,6 @@ - {% if totp_url %} - - {% endif %}
@@ -82,12 +85,5 @@
- {% if totp_url %} -
-
- {% qr_from_text totp_url image_format="png" %} -
-
- {% endif %} {% endblock content %} diff --git a/accounts/templates/accounts/email/otp.html b/accounts/templates/accounts/email/otp.html new file mode 100644 index 00000000..2833194c --- /dev/null +++ b/accounts/templates/accounts/email/otp.html @@ -0,0 +1,7 @@ +{% load i18n %} +{% load qr_code %} +{% blocktrans %} +Scan this QR code to get OTP for account '{{ user }}' +{% endblocktrans %} +
+{% qr_from_text totp_url %} \ No newline at end of file diff --git a/accounts/templates/accounts/email_otp_form.html b/accounts/templates/accounts/email_otp_form.html new file mode 100644 index 00000000..03fa06d2 --- /dev/null +++ b/accounts/templates/accounts/email_otp_form.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} +{% load bootstrap4 %} +{% load icons %} +{% load i18n %} + +{% block title %}{{ title }}{% endblock %} + +{% block page_heading %}{{ title }}{% endblock page_heading %} + +{% block content %} +
+ {% blocktrans %} + Enter email address OTP QR code will be sent to. + {% endblocktrans %} +
+
+
+
+ {% csrf_token %} + {% bootstrap_form form layout='horizontal' %} +
+
+ +
+{% endblock content %} \ No newline at end of file diff --git a/accounts/templates/accounts/otp_login.html b/accounts/templates/accounts/otp_login.html index 0b3cacb2..d75678c1 100644 --- a/accounts/templates/accounts/otp_login.html +++ b/accounts/templates/accounts/otp_login.html @@ -1,62 +1,30 @@ +{% extends 'base.html' %} {% load i18n %} {% load static %} {% load bootstrap4 %} - - - - - - - - - - - {% trans "WebVirtCloud" %} - {% trans "Sign In" %} - - - - - - - - - - - -
-
- -
-
-
-
- {% if form.errors %} - {% bootstrap_form_errors form %} - {% endif %} - -
-
-
+{% block title %}WebVirtCloud{% endblock title %} + +{% block page_heading %}WebVirtCloud{% endblock page_heading %} + +{% block content %} +
+
+
+
+ {% if form.errors %} + {% bootstrap_form_errors form %} + {% endif %} +
- - - - - - - - \ No newline at end of file +
+{% endblock content %} \ No newline at end of file diff --git a/accounts/templates/base_auth.html b/accounts/templates/base_auth.html deleted file mode 100644 index d484ef15..00000000 --- a/accounts/templates/base_auth.html +++ /dev/null @@ -1,41 +0,0 @@ -{% load static %} - - - - - - - - - - - - {% block title %}{% endblock %} - - - - - - - - - - - - - - -
- {% block content %}{% endblock %} -
- - - - - - - - \ No newline at end of file diff --git a/accounts/templates/login.html b/accounts/templates/login.html index 6fdc9ddb..1972f8e9 100644 --- a/accounts/templates/login.html +++ b/accounts/templates/login.html @@ -1,25 +1,30 @@ -{% extends "base_auth.html" %} +{% extends "base.html" %} {% load i18n %} +{% load static %} + {% block title %}{% trans "WebVirtCloud" %} - {% trans "Sign In" %}{% endblock %} + +{% block style %} + +{% endblock style %} + {% block content %} -
- {% endblock %} \ No newline at end of file diff --git a/accounts/urls.py b/accounts/urls.py index e7a0d135..d98e75ad 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -20,10 +20,14 @@ ] if settings.OTP_ENABLED: - urlpatterns += path( - 'login/', - LoginView.as_view(template_name='accounts/otp_login.html', authentication_form=OTPAuthenticationForm), - name='login', - ), + urlpatterns += [ + path( + 'login/', + LoginView.as_view(template_name='accounts/otp_login.html', authentication_form=OTPAuthenticationForm), + name='login', + ), + path('email_otp/', views.email_otp, name='email_otp'), + path('admin_email_otp//', views.admin_email_otp, name='admin_email_otp'), + ] else: urlpatterns += path('login/', LoginView.as_view(template_name='login.html'), name='login'), diff --git a/accounts/utils.py b/accounts/utils.py index 12cf2c10..d089ecd6 100644 --- a/accounts/utils.py +++ b/accounts/utils.py @@ -2,6 +2,9 @@ import binascii import struct +from django.core.mail import send_mail +from django.template.loader import render_to_string +from django.utils.translation import gettext as _ from django_otp import devices_for_user from django_otp.plugins.otp_totp.models import TOTPDevice @@ -12,6 +15,9 @@ def get_user_totp_device(user): if isinstance(device, TOTPDevice): return device + device = user.totpdevice_set.create() + return device + def validate_ssh_key(key): array = key.encode().split() @@ -37,3 +43,20 @@ def validate_ssh_key(key): return True else: return False + + +def send_email_with_otp(user, device): + send_mail( + _('OTP QR Code'), + _('Please view HTML version of this message.'), + None, + [user.email], + html_message=render_to_string( + 'accounts/email/otp.html', + { + 'totp_url': device.config_url, + 'user': user, + }, + ), + fail_silently=False, + ) diff --git a/accounts/views.py b/accounts/views.py index 7226f458..fa207bf9 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,7 +1,7 @@ from admin.decorators import superuser_only from django.conf import settings from django.contrib import messages -from django.contrib.auth import update_session_auth_hash +from django.contrib.auth import get_user_model, update_session_auth_hash from django.contrib.auth.decorators import permission_required from django.contrib.auth.forms import PasswordChangeForm from django.shortcuts import get_object_or_404, redirect, render @@ -9,11 +9,11 @@ from django.utils.translation import gettext_lazy as _ from instances.models import Instance -from accounts.forms import ProfileForm, UserSSHKeyForm +from accounts.forms import EmailOTPForm, ProfileForm, UserSSHKeyForm from accounts.models import * from . import forms -from .utils import get_user_totp_device +from .utils import get_user_totp_device, send_email_with_otp def profile(request): @@ -65,13 +65,15 @@ def account(request, user_id): user_insts = UserInstance.objects.filter(user_id=user_id) instances = Instance.objects.all().order_by("name") publickeys = UserSSHKey.objects.filter(user_id=user_id) - if settings.OTP_ENABLED: - device = get_user_totp_device(user) - if not device: - device = user.totpdevice_set.create() - totp_url = device.config_url - return render(request, "account.html", locals()) + return render( + request, "account.html", { + 'user': user, + 'user_insts': user_insts, + 'instances': instances, + 'publickeys': publickeys, + 'otp_enabled': settings.OTP_ENABLED, + }) @permission_required("accounts.change_password", raise_exception=True) @@ -141,3 +143,36 @@ def user_instance_delete(request, pk): "common/confirm_delete.html", {"object": user_instance}, ) + + +def email_otp(request): + form = EmailOTPForm(request.POST or None) + if form.is_valid(): + UserModel = get_user_model() + try: + user = UserModel.objects.get(email=form.cleaned_data['email']) + except UserModel.DoesNotExist: + pass + else: + device = get_user_totp_device(user) + send_email_with_otp(user, device) + + messages.success(request, _('OTP Sent to %s') % form.cleaned_data['email']) + return redirect('accounts:login') + + return render(request, 'accounts/email_otp_form.html', { + 'form': form, + 'title': _('Email OTP'), + }) + + +@superuser_only +def admin_email_otp(request, user_id): + user = get_object_or_404(get_user_model(), pk=user_id) + device = get_user_totp_device(user) + if user.email != '': + send_email_with_otp(user, device) + messages.success(request, _('OTP QR code was emailed to user %s') % user) + else: + messages.error(request, _('User email not set, failed to send QR code')) + return redirect('accounts:account', user.id) diff --git a/admin/views.py b/admin/views.py index df2e3544..b441d853 100644 --- a/admin/views.py +++ b/admin/views.py @@ -120,12 +120,12 @@ def user_update(request, pk): user = get_object_or_404(User, pk=pk) attributes = UserAttributes.objects.get(user=user) user_form = forms.UserForm(request.POST or None, instance=user) - attributes_form = forms.UserAttributesForm( - request.POST or None, instance=attributes) + attributes_form = forms.UserAttributesForm(request.POST or None, instance=attributes) if user_form.is_valid() and attributes_form.is_valid(): user_form.save() attributes_form.save() - return redirect("admin:user_list") + next = request.GET.get('next') + return redirect(next or "admin:user_list") return render( request, @@ -146,8 +146,7 @@ def user_update_password(request, pk): if form.is_valid(): user = form.save() update_session_auth_hash(request, user) # Important! - messages.success(request, _( - "User password changed: {}".format(user.username))) + messages.success(request, _("User password changed: {}".format(user.username))) return redirect("admin:user_list") else: messages.error(request, _("Wrong Data Provided")) @@ -159,8 +158,8 @@ def user_update_password(request, pk): "accounts/change_password_form.html", { "form": form, - "user": user.username - } + "user": user.username, + }, ) diff --git a/computes/templates/computes/instances.html b/computes/templates/computes/instances.html index d5a02b36..f69143fb 100644 --- a/computes/templates/computes/instances.html +++ b/computes/templates/computes/instances.html @@ -6,7 +6,7 @@ {% block style %} {% endblock %} -{% block page_heading %}{{ compute.name }}{% endblock page_heading %} +{% block page_heading %}{{ compute.name }} - {% trans "Instances" %}{% endblock page_heading %} {% block page_heading_extra %} > /var/log/webvirtcloud.log 2>&1 diff --git a/dev/libvirt-bootstrap.sh b/dev/libvirt-bootstrap.sh index 3d0b0032..67ef6e23 100644 --- a/dev/libvirt-bootstrap.sh +++ b/dev/libvirt-bootstrap.sh @@ -5,14 +5,14 @@ # # FILE: libvirt-bootstrap.sh # -# DESCRIPTION: Bootstrap webvirtmgr installation for various distributions +# DESCRIPTION: Bootstrap webvirtcloud installation for various distributions # -# BUGS: https://github.com/retspen/webvirtmgr/issues +# BUGS: https://github.com/retspen/webvirtcloud/issues # -# COPYRIGHT: (c) 2015 by the WebVirtMgr Team +# COPYRIGHT: (c) 2015 by the WebVirtCloud Team # # LICENSE: Apache 2.0 -# ORGANIZATION: WebVirtMgr (webvirtmgr.net) +# ORGANIZATION: WebVirtCloud (webvirtcloud.net) # CREATED: 11/11/2013 11:00:00 EET #=============================================================================== @@ -21,7 +21,7 @@ # DESCRIPTION: Echo errors to stderr. #------------------------------------------------------------------------------- echoerror() { - printf "${RC} * ERROR${EC}: $@\n" 1>&2; + printf "${RC} * ERROR${EC}: %s\n" "$@" 1>&2; } #--- FUNCTION ---------------------------------------------------------------- @@ -45,7 +45,7 @@ echowarn() { # DESCRIPTION: Echo debug information to stdout. #------------------------------------------------------------------------------- echodebug() { - if [ $_ECHO_DEBUG -eq $BS_TRUE ]; then + if [ "$_ECHO_DEBUG" -eq "$BS_TRUE" ]; then printf "${BC} * DEBUG${EC}: %s\n" "$@"; fi } @@ -68,7 +68,7 @@ __test_distro_arch # DESCRIPTION: Strip duplicate strings #------------------------------------------------------------------------------- __strip_duplicates() { - echo $@ | tr -s '[:space:]' '\n' | awk '!x[$0]++' + echo "$@" | tr -s '[:space:]' '\n' | awk '!x[$0]++' } #--- FUNCTION ---------------------------------------------------------------- @@ -79,7 +79,7 @@ __strip_duplicates() { #------------------------------------------------------------------------------- __function_defined() { FUNC_NAME=$1 - if [ "$(command -v $FUNC_NAME)x" != "x" ]; then + if [ "$(command -v "$FUNC_NAME")x" != "x" ]; then echoinfo "Found function $FUNC_NAME" return 0 fi @@ -95,14 +95,14 @@ __function_defined() { __parse_version_string() { VERSION_STRING="$1" PARSED_VERSION=$( - echo $VERSION_STRING | + echo "$VERSION_STRING" | sed -e 's/^/#/' \ -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\)\(\.[0-9][0-9]*\).*$/\1/' \ -e 's/^#[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/' \ -e 's/^#[^0-9]*\([0-9][0-9]*\).*$/\1/' \ -e 's/^#.*$//' ) - echo $PARSED_VERSION + echo "$PARSED_VERSION" } #--- FUNCTION ---------------------------------------------------------------- @@ -117,8 +117,8 @@ __sort_release_files() { primary_release_files="" secondary_release_files="" # Sort know VS un-known files first - for release_file in $(echo $@ | sed -r 's:[[:space:]]:\n:g' | sort --unique --ignore-case); do - match=$(echo $release_file | egrep -i ${KNOWN_RELEASE_FILES}) + for release_file in $(echo "$@" | sed -r 's:[[:space:]]:\n:g' | sort --unique --ignore-case); do + match=$(echo "$release_file" | grep -E -i "${KNOWN_RELEASE_FILES}") if [ "x${match}" != "x" ]; then primary_release_files="${primary_release_files} ${release_file}" else @@ -129,15 +129,15 @@ __sort_release_files() { # Now let's sort by know files importance, max important goes last in the max_prio list max_prio="redhat-release centos-release" for entry in $max_prio; do - if [ "x$(echo ${primary_release_files} | grep $entry)" != "x" ]; then - primary_release_files=$(echo ${primary_release_files} | sed -e "s:\(.*\)\($entry\)\(.*\):\2 \1 \3:g") + if [ "x$(echo "${primary_release_files}" | grep "$entry")" != "x" ]; then + primary_release_files=$(echo "${primary_release_files}" | sed -e "s:\(.*\)\($entry\)\(.*\):\2 \1 \3:g") fi done # Now, least important goes last in the min_prio list min_prio="lsb-release" - for entry in $max_prio; do - if [ "x$(echo ${primary_release_files} | grep $entry)" != "x" ]; then - primary_release_files=$(echo ${primary_release_files} | sed -e "s:\(.*\)\($entry\)\(.*\):\1 \3 \2:g") + for entry in $min_prio; do + if [ "x$(echo "${primary_release_files}" | grep "$entry")" != "x" ]; then + primary_release_files=$(echo "${primary_release_files}" | sed -e "s:\(.*\)\($entry\)\(.*\):\1 \3 \2:g") fi done @@ -183,24 +183,24 @@ __gather_linux_system_info() { return fi - for rsource in $(__sort_release_files $( - cd /etc && /bin/ls *[_-]release *[_-]version 2>/dev/null | env -i sort | \ + for rsource in $(__sort_release_files "$( + cd /etc && find ./*[_-]release ./*[_-]version -printf "%f\n" 2>/dev/null | env -i sort | \ sed -e '/^redhat-release$/d' -e '/^lsb-release$/d'; \ echo redhat-release lsb-release - )); do + )"); do [ -L "/etc/${rsource}" ] && continue # Don't follow symlinks [ ! -f "/etc/${rsource}" ] && continue # Does not exist - n=$(echo ${rsource} | sed -e 's/[_-]release$//' -e 's/[_-]version$//') - rv=$( (grep VERSION /etc/${rsource}; cat /etc/${rsource}) | grep '[0-9]' | sed -e 'q' ) + n=$(echo "${rsource}" | sed -e 's/[_-]release$//' -e 's/[_-]version$//') + rv=$( (grep VERSION /etc/"${rsource}"; cat /etc/"${rsource}") | grep '[0-9]' | sed -e 'q' ) [ "${rv}x" = "x" ] && continue # There's no version information. Continue to next rsource v=$(__parse_version_string "$rv") - case $(echo ${n} | tr '[:upper:]' '[:lower:]') in + case $(echo "${n}" | tr '[:upper:]' '[:lower:]') in redhat ) - if [ ".$(egrep 'CentOS' /etc/${rsource})" != . ]; then + if [ ".$(grep -E 'CentOS' /etc/"${rsource}")" != . ]; then n="CentOS" - elif [ ".$(egrep 'Red Hat Enterprise Linux' /etc/${rsource})" != . ]; then + elif [ ".$(grep -E 'Red Hat Enterprise Linux' /etc/"${rsource}")" != . ]; then n="ed at nterprise inux" else n="ed at inux" @@ -220,13 +220,13 @@ __gather_linux_system_info() { n="Amazon Linux AMI" break esac - done < /etc/${rsource} + done < /etc/"${rsource}" ;; os ) nn=$(grep '^ID=' /etc/os-release | sed -e 's/^ID=\(.*\)$/\1/g') rv=$(grep '^VERSION_ID=' /etc/os-release | sed -e 's/^VERSION_ID=\(.*\)$/\1/g') [ "${rv}x" != "x" ] && v=$(__parse_version_string "$rv") || v="" - case $(echo ${nn} | tr '[:upper:]' '[:lower:]') in + case $(echo "${nn}" | tr '[:upper:]' '[:lower:]') in arch ) n="Arch Linux" v="" # Arch Linux does not provide a version. @@ -257,9 +257,9 @@ __gather_linux_system_info() { __gather_linux_system_info # Simplify distro name naming on functions -DISTRO_NAME_L=$(echo $DISTRO_NAME | tr '[:upper:]' '[:lower:]' | sed 's/[^a-zA-Z0-9_ ]//g' | sed -re 's/([[:space:]])+/_/g') -DISTRO_MAJOR_VERSION="$(echo $DISTRO_VERSION | sed 's/^\([0-9]*\).*/\1/g')" -DISTRO_MINOR_VERSION="$(echo $DISTRO_VERSION | sed 's/^\([0-9]*\).\([0-9]*\).*/\2/g')" +DISTRO_NAME_L=$(echo "$DISTRO_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-zA-Z0-9_ ]//g' | sed -re 's/([[:space:]])+/_/g') +DISTRO_MAJOR_VERSION="$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).*/\1/g')" +DISTRO_MINOR_VERSION="$(echo "$DISTRO_VERSION" | sed 's/^\([0-9]*\).\([0-9]*\).*/\2/g')" PREFIXED_DISTRO_MAJOR_VERSION="_${DISTRO_MAJOR_VERSION}" if [ "${PREFIXED_DISTRO_MAJOR_VERSION}" = "_" ]; then PREFIXED_DISTRO_MAJOR_VERSION="" @@ -278,7 +278,7 @@ __check_end_of_life_versions() { case "${DISTRO_NAME_L}" in debian) # Debian versions bellow 6 are not supported - if [ $DISTRO_MAJOR_VERSION -lt 6 ]; then + if [ "$DISTRO_MAJOR_VERSION" -lt 6 ]; then echoerror "End of life distributions are not supported." echoerror "Please consider upgrading to the next stable. See:" echoerror " https://wiki.debian.org/DebianReleases" @@ -293,10 +293,10 @@ __check_end_of_life_versions() { # = 10.10 # = 11.04 # = 11.10 - if ([ $DISTRO_MAJOR_VERSION -eq 10 ] && [ $DISTRO_MINOR_VERSION -eq 10 ]) || \ - ([ $DISTRO_MAJOR_VERSION -eq 11 ] && [ $DISTRO_MINOR_VERSION -eq 04 ]) || \ - ([ $DISTRO_MAJOR_VERSION -eq 11 ] && [ $DISTRO_MINOR_VERSION -eq 10 ]) || \ - [ $DISTRO_MAJOR_VERSION -lt 10 ]; then + if { [ "$DISTRO_MAJOR_VERSION" -eq 10 ] && [ "$DISTRO_MINOR_VERSION" -eq 10 ]; } || \ + { [ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$DISTRO_MINOR_VERSION" -eq 04 ]; } || \ + { [ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$DISTRO_MINOR_VERSION" -eq 10 ]; } || \ + [ "$DISTRO_MAJOR_VERSION" -lt 10 ]; then echoerror "End of life distributions are not supported." echoerror "Please consider upgrading to the next stable. See:" echoerror " https://wiki.ubuntu.com/Releases" @@ -308,7 +308,7 @@ __check_end_of_life_versions() { # openSUSE versions not supported # # <= 12.1 - if ([ $DISTRO_MAJOR_VERSION -eq 12 ] && [ $DISTRO_MINOR_VERSION -eq 1 ]) || [ $DISTRO_MAJOR_VERSION -lt 12 ]; then + if { [ "$DISTRO_MAJOR_VERSION" -eq 12 ] && [ "$DISTRO_MINOR_VERSION" -eq 1 ]; } || [ "$DISTRO_MAJOR_VERSION" -lt 12 ]; then echoerror "End of life distributions are not supported." echoerror "Please consider upgrading to the next stable. See:" echoerror " http://en.opensuse.org/Lifetime" @@ -324,7 +324,7 @@ __check_end_of_life_versions() { if [ "x${SUSE_PATCHLEVEL}" = "x" ]; then SUSE_PATCHLEVEL="00" fi - if ([ $DISTRO_MAJOR_VERSION -eq 11 ] && [ $SUSE_PATCHLEVEL -lt 02 ]) || [ $DISTRO_MAJOR_VERSION -lt 11 ]; then + if { [ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$SUSE_PATCHLEVEL" -lt 02 ]; } || [ "$DISTRO_MAJOR_VERSION" -lt 11 ]; then echoerror "Versions lower than SuSE 11 SP2 are not supported." echoerror "Please consider upgrading to the next stable" exit 1 @@ -333,7 +333,7 @@ __check_end_of_life_versions() { fedora) # Fedora lower than 18 are no longer supported - if [ $DISTRO_MAJOR_VERSION -lt 18 ]; then + if [ "$DISTRO_MAJOR_VERSION" -lt 18 ]; then echoerror "End of life distributions are not supported." echoerror "Please consider upgrading to the next stable. See:" echoerror " https://fedoraproject.org/wiki/Releases" @@ -343,7 +343,7 @@ __check_end_of_life_versions() { centos) # CentOS versions lower than 5 are no longer supported - if ([ $DISTRO_MAJOR_VERSION -eq 6 ] && [ $DISTRO_MINOR_VERSION -lt 3 ]) || [ $DISTRO_MAJOR_VERSION -lt 5 ]; then + if { [ "$DISTRO_MAJOR_VERSION" -eq 6 ] && [ "$DISTRO_MINOR_VERSION" -lt 3 ]; } || [ "$DISTRO_MAJOR_VERSION" -lt 5 ]; then echoerror "End of life distributions are not supported." echoerror "Please consider upgrading to the next stable. See:" echoerror " http://wiki.centos.org/Download" @@ -353,7 +353,7 @@ __check_end_of_life_versions() { red_hat*linux) # Red Hat (Enterprise) Linux versions lower than 5 are no longer supported - if ([ $DISTRO_MAJOR_VERSION -eq 6 ] && [ $DISTRO_MINOR_VERSION -lt 3 ]) || [ $DISTRO_MAJOR_VERSION -lt 5 ]; then + if { [ "$DISTRO_MAJOR_VERSION" -eq 6 ] && [ "$DISTRO_MINOR_VERSION" -lt 3 ]; } || [ "$DISTRO_MAJOR_VERSION" -lt 5 ]; then echoerror "End of life distributions are not supported." echoerror "Please consider upgrading to the next stable. See:" echoerror " https://access.redhat.com/support/policy/updates/errata/" @@ -374,7 +374,7 @@ __check_end_of_life_versions # CentOS Install Functions # install_centos() { - if [ $DISTRO_MAJOR_VERSION -ge 6 ]; then + if [ "$DISTRO_MAJOR_VERSION" -ge 6 ]; then yum -y install qemu-kvm libvirt bridge-utils python-libguestfs libguestfs-tools supervisor cyrus-sasl-md5 epel-release || return 1 fi return 0 @@ -409,7 +409,7 @@ install_centos_post() { echoerror "/etc/sasl2/libvirt.conf not found. Exiting..." exit 1 fi - if [ $DISTRO_MAJOR_VERSION -lt 7 ]; then + if [ "$DISTRO_MAJOR_VERSION" -lt 7 ]; then if [ -f /etc/supervisord.conf ]; then curl https://raw.githubusercontent.com/retspen/webvirtcloud/master/conf/daemon/gstfsd > /usr/local/bin/gstfsd chmod +x /usr/local/bin/gstfsd @@ -593,7 +593,7 @@ daemons_running_opensuse() { # install_ubuntu() { apt-get update || return 1 - if [ $DISTRO_MAJOR_VERSION -lt 18 ]; then + if [ "$DISTRO_MAJOR_VERSION" -lt 18 ]; then apt-get -y install kvm libvirt-bin bridge-utils sasl2-bin python-guestfs supervisor || return 1 else apt install -y qemu-kvm libvirt-bin bridge-utils virt-manager sasl2-bin python3-guestfs supervisor || return 1 @@ -663,7 +663,7 @@ daemons_running_ubuntu() { # install_debian() { apt-get update || return 1 - if [ $DISTRO_MAJOR_VERSION -lt 10 ]; then + if [ "$DISTRO_MAJOR_VERSION" -lt 10 ]; then apt-get -y install qemu-kvm libvirt-bin bridge-utils sasl2-bin python-guestfs supervisor || return 1 else apt-get -y install qemu qemu-kvm qemu-system qemu-utils libvirt-clients libvirt-daemon-system sasl2-bin virtinst supervisor || return 1 @@ -672,14 +672,14 @@ install_debian() { } install_debian_post() { - if [ $DISTRO_MAJOR_VERSION -ge 8 ]; then + if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then LIBVIRTSVC=libvirtd else LIBVIRTSVC=libvirt-bin fi if [ -f /etc/default/$LIBVIRTSVC ]; then if [ "$( grep -c '^libvirtd_opts *=' /etc/default/$LIBVIRTSVC )" -gt 0 ]; then - if [ $( grep -c '^libvirtd_opts *=.*-l' /etc/default/$LIBVIRTSVC ) -eq 0 ]; then + if [ "$( grep -c '^libvirtd_opts *=.*-l' /etc/default/$LIBVIRTSVC )" -eq 0 ]; then sed -i 's/^libvirtd_opts="\([^"]*\)"/libvirtd_opts="\1 -l"/g' /etc/default/$LIBVIRTSVC fi else @@ -723,7 +723,7 @@ install_debian_post() { } daemons_running_debian() { - if [ $DISTRO_MAJOR_VERSION -ge 8 ]; then + if [ "$DISTRO_MAJOR_VERSION" -ge 8 ]; then LIBVIRTSVC=libvirtd else LIBVIRTSVC=libvirt-bin @@ -750,15 +750,15 @@ daemons_running_debian() { INSTALL_FUNC_NAMES="install_${DISTRO_NAME_L}" INSTALL_FUNC="null" -for FUNC_NAME in $(__strip_duplicates $INSTALL_FUNC_NAMES); do - if __function_defined $FUNC_NAME; then +for FUNC_NAME in $(__strip_duplicates "$INSTALL_FUNC_NAMES"); do + if __function_defined "$FUNC_NAME"; then INSTALL_FUNC=$FUNC_NAME break fi done echodebug "INSTALL_FUNC=${INSTALL_FUNC}" -if [ $INSTALL_FUNC = "null" ]; then +if [ "$INSTALL_FUNC" = "null" ]; then echoerror "No installation function found. Exiting..." exit 1 else @@ -774,15 +774,15 @@ fi POST_FUNC_NAMES="install_${DISTRO_NAME_L}_post" POST_INSTALL_FUNC="null" -for FUNC_NAME in $(__strip_duplicates $POST_FUNC_NAMES); do - if __function_defined $FUNC_NAME; then +for FUNC_NAME in $(__strip_duplicates "$POST_FUNC_NAMES"); do + if __function_defined "$FUNC_NAME"; then POST_INSTALL_FUNC=$FUNC_NAME break fi done echodebug "POST_INSTALL_FUNC=${POST_INSTALL_FUNC}" -if [ $POST_INSTALL_FUNC = "null" ]; then +if [ "$POST_INSTALL_FUNC" = "null" ]; then echoerror "No installation function found. Exiting..." exit 1 else @@ -798,15 +798,15 @@ fi DAEMONS_RUNNING_FUNC_NAMES="daemons_running_${DISTRO_NAME_L}" DAEMONS_RUNNING_FUNC="null" -for FUNC_NAME in $(__strip_duplicates $DAEMONS_RUNNING_FUNC_NAMES); do - if __function_defined $FUNC_NAME; then +for FUNC_NAME in $(__strip_duplicates "$DAEMONS_RUNNING_FUNC_NAMES"); do + if __function_defined "$FUNC_NAME"; then DAEMONS_RUNNING_FUNC=$FUNC_NAME break fi done echodebug "DAEMONS_RUNNING_FUNC=${DAEMONS_RUNNING_FUNC}" -if [ $DAEMONS_RUNNING_FUNC = "null" ]; then +if [ "$DAEMONS_RUNNING_FUNC" = "null" ]; then echoerror "No installation function found. Exiting..." exit 1 else diff --git a/instances/utils.py b/instances/utils.py index c4f20b86..7624bab8 100644 --- a/instances/utils.py +++ b/instances/utils.py @@ -144,7 +144,10 @@ def migrate_instance( compress, postcopy, ) + finally: + conn_migrate.close() + try: conn_new = wvmInstance( new_compute.hostname, new_compute.login, @@ -156,7 +159,6 @@ def migrate_instance( if autostart: conn_new.set_autostart(1) finally: - conn_migrate.close() conn_new.close() instance.compute = new_compute diff --git a/interfaces/templates/interfaces.html b/interfaces/templates/interfaces.html index c103de63..413691f9 100644 --- a/interfaces/templates/interfaces.html +++ b/interfaces/templates/interfaces.html @@ -4,7 +4,7 @@ {% block title %}{% trans "Interfaces" %} - {{ compute.name }}{% endblock %} -{% block page_heading%}{% trans "Interfaces" %} - {{ compute.name }}{% endblock page_heading %} +{% block page_heading %}{{ compute.name }} - {% trans "Interfaces" %}{% endblock page_heading %} {% block page_heading_extra %}{% include 'create_iface_block.html' %}{% endblock page_heading_extra %} diff --git a/networks/templates/networks.html b/networks/templates/networks.html index 5415acd6..b8477491 100644 --- a/networks/templates/networks.html +++ b/networks/templates/networks.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% load i18n %} -{% block title %}{{ compute.name }} - {% trans "Networks" %}{% endblock %} +{% block title %}{% trans "Networks" %} - {{ compute.name }}{% endblock %} {% block page_heading %}{{ compute.name }} - {% trans "Networks" %}{% endblock page_heading %} diff --git a/nwfilters/templates/nwfilters.html b/nwfilters/templates/nwfilters.html index d4110af0..eac9c968 100644 --- a/nwfilters/templates/nwfilters.html +++ b/nwfilters/templates/nwfilters.html @@ -2,7 +2,7 @@ {% load i18n %} {% load staticfiles %} -{% block title %}{{ compute.name }} - {% trans "NWFilters" %}{% endblock %} +{% block title %}{% trans "NWFilters" %} - {{ compute.name }}{% endblock %} {% block page_heading %}{{ compute.name }} - {% trans "NWFilters" %}{% endblock page_heading %} diff --git a/secrets/templates/secrets.html b/secrets/templates/secrets.html index b5e21bad..7536032c 100644 --- a/secrets/templates/secrets.html +++ b/secrets/templates/secrets.html @@ -14,7 +14,6 @@ {% block content %}
-
+
{% if not storages %}
diff --git a/templates/base.html b/templates/base.html index 0d71065d..52d30cd6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -34,22 +34,23 @@ + {% if request.user.is_authenticated %} {% include 'navbar.html' %} + {% endif %}
-
+
{% block page_heading_extra %} {% endblock page_heading_extra %}
-
-
{% bootstrap_messages %} {% block content %}{% endblock %}
diff --git a/webvirtcloud.sh b/webvirtcloud.sh index 68eaafbf..04d415ec 100644 --- a/webvirtcloud.sh +++ b/webvirtcloud.sh @@ -183,6 +183,7 @@ run_as_app_user () { activate_python_environment () { cd "$APP_PATH" || exit virtualenv -p "$PYTHON" venv + # shellcheck disable=SC1091 source venv/bin/activate } @@ -203,7 +204,7 @@ install_webvirtcloud () { echo "* Configuring settings.py file." cp "$APP_PATH/webvirtcloud/settings.py.template" "$APP_PATH/webvirtcloud/settings.py" - local secret_key=$(generate_secret_key) + secret_key=$(generate_secret_key) echo "* Secret for Django generated: $secret_key" #TODO escape SED delimiter in variables diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 1dc1a879..6dd0b2a7 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -183,3 +183,5 @@ SHOW_PROFILE_EDIT_PASSWORD = True OTP_ENABLED = False +LOGIN_REQUIRED_IGNORE_VIEW_NAMES = ['accounts:email_otp'] +