diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index bcf66c1..4bc6f7f 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -17,7 +17,6 @@ jobs: # The type of runner that the job will run on runs-on: ubuntu-latest - # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it @@ -35,16 +34,21 @@ jobs: python3 -m pip install --upgrade pip if [ -f dev/requirements.txt ]; then pip3 install -r dev/requirements.txt; fi - name: Super-Linter - uses: docker://github/super-linter:v2.2.0 + uses: docker://github/super-linter:v3.3.2 env: VALIDATE_ANSIBLE: false VALIDATE_CLOJURE: false VALIDATE_COFFEE: false + VALIDATE_DART: false VALIDATE_GO: false - VALIDATE_POWERSHELL: false + VALIDATE_JSX: false VALIDATE_KOTLIN: false - VALIDATE_RUBY: false + VALIDATE_POWERSHELL: false VALIDATE_PERL: false VALIDATE_PHP: false + VALIDATE_RAKU: false + VALIDATE_RUBY: false + VALIDATE_TSX: false VALIDATE_TERRAFORM: false + diff --git a/.travis.yml b/.travis.yml index 8a017cb..01d56bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,14 +2,14 @@ language: python python: - "3.6" env: - - DJANGO=2.2.12 + - DJANGO=2.2.14 install: - pip install -r dev/requirements.txt script: - - pep8 --exclude=IPy.py --ignore=E501 vrtManager accounts computes \ + - pep8 --exclude=IPy.py --ignore=E501 vrtManager accounts admin appsettings computes \ console create datasource instances interfaces \ logs networks nwfilters secrets storages - - pyflakes vrtManager accounts computes console create datasource instances interfaces \ + - pyflakes vrtManager accounts admin appsettings computes console create datasource instances interfaces \ nwfilters networks secrets storages logs - python manage.py migrate - python manage.py test --settings=webvirtcloud.settings-dev diff --git a/README.md b/README.md index b7e7640..22cabd2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## WebVirtCloud -###### Python3 & Django 2.2.12 +###### Python3 & Django 2.2 ## Features * QEMU/KVM Hypervisor Management @@ -301,7 +301,7 @@ datasource: ``` ### Reverse-Proxy -Edit WS_PUBLIC_PORT at settings.py file to expose redirect to 80. Default: 6080 +Edit WS_PUBLIC_PORT at settings.py file to expose redirect to 80 or 443. Default: 6080 ``` WS_PUBLIC_PORT = 80 ``` @@ -330,7 +330,7 @@ pip install -r conf/requirements.txt ``` Run tests ```bash -python menage.py test +python manage.py test ``` ### Screenshots diff --git a/accounts/models.py b/accounts/models.py index 1369158..afc1960 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -6,6 +6,7 @@ from django.utils.translation import ugettext_lazy as _ from instances.models import Instance + class UserInstanceManager(models.Manager): def get_queryset(self): return super().get_queryset().select_related('instance', 'user') diff --git a/appsettings/migrations/0004_auto_20200716_0637.py b/appsettings/migrations/0004_auto_20200716_0637.py new file mode 100644 index 0000000..5feffa3 --- /dev/null +++ b/appsettings/migrations/0004_auto_20200716_0637.py @@ -0,0 +1,35 @@ +# Generated by Django 2.2.13 on 2020-07-16 06:37 + +from django.db import migrations +from django.utils.translation import ugettext_lazy as _ + + +def add_default_settings(apps, schema_editor): + setting = apps.get_model("appsettings", "AppSettings") + db_alias = schema_editor.connection.alias + setting.objects.using(db_alias).bulk_create([ + setting(27, _("Console Scale"), "CONSOLE_SCALE", "False", "True,False", _("Allow console to scaling view")), + setting(28, _("Console View-Only"), "CONSOLE_VIEW_ONLY", "False", "True,False", _("Allow only view not modify")), + setting(29, _("Console Resize Session"), "CONSOLE_RESIZE_SESSION", "False", "True,False", _("Allow to resize session for console")), + setting(30, _("Console Clip Viewport"), "CONSOLE_CLIP_VIEWPORT", "False", "True,False", _("Clip console viewport")), + ]) + + +def del_default_settings(apps, schema_editor): + setting = apps.get_model("appsettings", "AppSettings") + db_alias = schema_editor.connection.alias + setting.objects.using(db_alias).filter(key="CONSOLE_SCALE").delete() + setting.objects.using(db_alias).filter(key="CONSOLE_VIEW_ONLY").delete() + setting.objects.using(db_alias).filter(key="CONSOLE_RESIZE_SESSION").delete() + setting.objects.using(db_alias).filter(key="CONSOLE_CLIP_VIEWPORT").delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('appsettings', '0003_auto_20200615_0637'), + ] + + operations = [ + migrations.RunPython(add_default_settings, del_default_settings), + ] diff --git a/computes/templates/computes/instances.html b/computes/templates/computes/instances.html index d72ecbd..342d53d 100644 --- a/computes/templates/computes/instances.html +++ b/computes/templates/computes/instances.html @@ -112,10 +112,5 @@ {% endblock %} {% block script %} <script src="{% static "js/sortable.min.js" %}"></script> -<script> - function open_console(uuid) { - window.open("{% url 'console' %}?token=" + uuid, "", "width=850,height=685"); - } -</script> <script src="{% static 'js/filter-table.js' %}"></script> {% endblock %} \ No newline at end of file diff --git a/conf/requirements-dev.txt b/conf/requirements-dev.txt deleted file mode 100644 index de27d31..0000000 --- a/conf/requirements-dev.txt +++ /dev/null @@ -1,19 +0,0 @@ -beautifulsoup4==4.9.1 -coverage==5.1 -Django==2.2.13 -django-bootstrap4==2.0.1 -django-debug-toolbar==2.2 -django-icons==2.0.0 -django-login-required-middleware==0.5.0 -gunicorn==20.0.4 -libsass==0.20.0 -libvirt-python==6.3.0 -lxml==4.5.0 -numpy==1.18.4 -pytz==2020.1 -rwlock==0.0.7 -six==1.15.0 -soupsieve==2.0.1 -sqlparse==0.3.1 -websockify==0.9.0 -yapf==0.30.0 diff --git a/conf/requirements.txt b/conf/requirements.txt index f55bd1f..73313b0 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -1,13 +1,13 @@ beautifulsoup4==4.9.1 -Django==2.2.13 -django-bootstrap4==2.0.1 -django-icons==2.0.0 +Django==2.2.14 +django-bootstrap4==2.2.0 +django-icons==2.1.1 django-login-required-middleware==0.5.0 gunicorn==20.0.4 libsass==0.20.0 -libvirt-python==6.3.0 -lxml==4.5.0 -numpy==1.18.4 +libvirt-python==6.4.0 +lxml==4.5.2 +numpy==1.18.5 pytz==2020.1 rwlock==0.0.7 six==1.15.0 diff --git a/console/templates/console-spice-full.html b/console/templates/console-spice-full.html index d9a7f89..29e52f9 100644 --- a/console/templates/console-spice-full.html +++ b/console/templates/console-spice-full.html @@ -199,7 +199,11 @@ <label for="port">{% trans 'Port' %}:</label> <input type='text' id='port' value='{{ ws_port }}'> <label for="password">{% trans 'Password' %}:</label> - <input type='password' id='password'> + {% if perms.instances.passwordless_console %} + <input type='password' id='password' value='{{ console_passwd }}'> + {% else %} + <input type='password' id='password'> + {% endif %} <label for="show_console">{% trans 'Show console' %}</label> <input type="checkbox" id="show_console" value="1" onchange="toggle_console()" checked> <button id="connectButton">{% trans 'Start' %}</button> diff --git a/console/templates/console-spice-lite.html b/console/templates/console-spice-lite.html index 6e4dc9b..8a359b7 100644 --- a/console/templates/console-spice-lite.html +++ b/console/templates/console-spice-lite.html @@ -93,7 +93,11 @@ } if (password === undefined) { - password = spice_query_var('password', ''); + {% if perms.instances.passwordless_console %} + password = '{{ console_passwd }}'; + {% else %} + password = prompt('{% trans "Password" %}'); + {% endif %} //password = '{{ console_passwd | safe }}'; } if (password === 'None') password = ''; diff --git a/console/templates/console-vnc-full.html b/console/templates/console-vnc-full.html index 35f4be1..5eccba8 100755 --- a/console/templates/console-vnc-full.html +++ b/console/templates/console-vnc-full.html @@ -297,7 +297,11 @@ <ul> <li> <label>Password:</label> - <input id="noVNC_password_input" type="password" /> + {% if perms.instances.passwordless_console %} + <input id="noVNC_password_input" type="password" value='{{ console_passwd }}' /> + {% else %} + <input id="noVNC_password_input" type="password" /> + {% endif %} </li> <li> <input id="noVNC_password_button" type="submit" value="Send Password" class="noVNC_submit" /> diff --git a/console/templates/console-vnc-lite.html b/console/templates/console-vnc-lite.html index e3cad63..ab40e8a 100755 --- a/console/templates/console-vnc-lite.html +++ b/console/templates/console-vnc-lite.html @@ -167,7 +167,13 @@ // By default, use the host and port of server that served this file const host = readQueryVariable('host', '{{ ws_host }}'); let port = readQueryVariable('port', '{{ ws_port }}'); - const password = readQueryVariable('password'); + + {% if perms.instances.passwordless_console %} + const password = '{{ console_passwd }}'; + {% else %} + const password = readQueryVariable('password'); + {% endif %} + //const path = readQueryVariable('path', 'websockify'); const path = readQueryVariable('path', '{{ ws_path }}'); @@ -202,10 +208,10 @@ rfb.addEventListener("capabilities", function () { updatePowerButtons(); }); // Set parameters that can be changed on an active connection - rfb.viewOnly = readQueryVariable('view_only', {{ view_only }}); - rfb.scaleViewport = readQueryVariable('scale', {{ scale }}); - rfb.resizeSession = readQueryVariable('resize', {{ resize_session }}); - rfb.clipViewport = readQueryVariable('clip_viewport', {{ clip_viewport }}); + rfb.scaleViewport = {{ scale }}; + rfb.viewOnly = {{ view_only }}; + rfb.resizeSession = {{ resize_session }}; + rfb.clipViewport = {{ clip_viewport }}; </script> {% endblock %} diff --git a/console/views.py b/console/views.py index e1df4f2..8251526 100644 --- a/console/views.py +++ b/console/views.py @@ -1,9 +1,13 @@ import re + from django.shortcuts import render from libvirt import libvirtError + +from appsettings.settings import app_settings from instances.models import Instance from vrtManager.instance import wvmInstance -from webvirtcloud.settings import WS_PUBLIC_PATH, WS_PUBLIC_PORT, WS_PUBLIC_HOST +from webvirtcloud.settings import (WS_PUBLIC_HOST, WS_PUBLIC_PATH, + WS_PUBLIC_PORT) def console(request): @@ -16,10 +20,10 @@ def console(request): if request.method == 'GET': token = request.GET.get('token', '') view_type = request.GET.get('view', 'lite') - view_only = request.GET.get('view_only', 0) - scale = request.GET.get('scale', 0) - resize_session = request.GET.get('resize_session', 0) - clip_viewport = request.GET.get('clip_viewport', 0) + view_only = request.GET.get('view_only', app_settings.CONSOLE_VIEW_ONLY.lower()) + scale = request.GET.get('scale', app_settings.CONSOLE_SCALE.lower()) + resize_session = request.GET.get('resize_session', app_settings.CONSOLE_RESIZE_SESSION.lower()) + clip_viewport = request.GET.get('clip_viewport', app_settings.CONSOLE_CLIP_VIEWPORT.lower()) try: temptoken = token.split('-', 1) diff --git a/dev/requirements.txt b/dev/requirements.txt index 8cdffcc..eb2abf6 100644 --- a/dev/requirements.txt +++ b/dev/requirements.txt @@ -1,5 +1,7 @@ -r ../conf/requirements.txt -coverage==5.1 -pycodestyle +coverage==5.2 +django-debug-toolbar==2.2 +pycodestyle==2.6.0 pyflakes==2.2.0 -pylint==2.5.2 +pylint==2.5.3 +yapf==0.30.0 diff --git a/instances/apps.py b/instances/apps.py index 8b67b98..4c5563d 100644 --- a/instances/apps.py +++ b/instances/apps.py @@ -22,6 +22,18 @@ def migrate_can_clone_instances(sender, **kwargs): user.user_permissions.add(permission) break +def apply_passwordless_console(sender, **kwargs): + ''' + Apply new passwordless_console permission for all users + ''' + from django.conf import settings + from django.contrib.auth.models import User, Permission + + print('\033[92mApplying permission passwordless_console for all users\033[0m') + users = User.objects.all() + permission = Permission.objects.get(codename='passwordless_console') + for user in users: + user.user_permissions.add(permission) class InstancesConfig(AppConfig): name = 'instances' @@ -29,3 +41,4 @@ class InstancesConfig(AppConfig): def ready(self): post_migrate.connect(migrate_can_clone_instances, sender=self) + post_migrate.connect(apply_passwordless_console, sender=self) diff --git a/instances/migrations/0009_auto_20200717_0524.py b/instances/migrations/0009_auto_20200717_0524.py new file mode 100644 index 0000000..bf3f6b0 --- /dev/null +++ b/instances/migrations/0009_auto_20200717_0524.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.13 on 2020-07-17 05:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('instances', '0008_auto_20200708_0950'), + ] + + operations = [ + migrations.AlterModelOptions( + name='permissionset', + options={'default_permissions': (), 'managed': False, 'permissions': [('clone_instances', 'Can clone instances'), ('passwordless_console', 'Can access console without password')]}, + ), + ] diff --git a/instances/models.py b/instances/models.py index 3272322..34d7e19 100644 --- a/instances/models.py +++ b/instances/models.py @@ -211,6 +211,8 @@ class PermissionSet(models.Model): """ class Meta: default_permissions = () - permissions = (('clone_instances', _('Can clone instances')), ) + permissions = [('clone_instances', 'Can clone instances'), + ('passwordless_console', _('Can access console without password')), + ] managed = False diff --git a/instances/templates/allinstances.html b/instances/templates/allinstances.html index d8c5a14..caaa932 100644 --- a/instances/templates/allinstances.html +++ b/instances/templates/allinstances.html @@ -38,11 +38,6 @@ {% endblock content %} {% block script %} <script src="{% static "js/sortable.min.js" %}"></script> - <script> - function open_console(uuid) { - window.open("{% url 'console' %}?token=" + uuid, "", "width=850,height=485"); - } - </script> <script src="{% static 'js/filter-table.js' %}"></script> {% if request.user.is_superuser %} <script> diff --git a/instances/templates/instance.html b/instances/templates/instance.html index 5562ac5..3739391 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -166,11 +166,6 @@ input.val(editor.getSession().getValue()); }); </script> -<script> - function open_console(view_style) { - window.open('{% url 'console' %}?token={{ compute.id }}-{{ instance.get_uuid }}&view=' + view_style +'', '', 'width=850,height=600') - } -</script> <script> function random_mac(net) { $.getJSON('{% url 'instances:random_mac_address' %}', function (data) { diff --git a/instances/templates/instance_actions.html b/instances/templates/instance_actions.html index 06cfe43..f67dc1d 100644 --- a/instances/templates/instance_actions.html +++ b/instances/templates/instance_actions.html @@ -42,4 +42,12 @@ <span class="fa fa-eye"></span> </button> {% endif %} -</form> \ No newline at end of file +</form> +{% block script %} +<script> + function open_console(uuid) { + url = '{% url 'console' %}?token=' + uuid + ''; + window.open(url, '', 'width=850,height=650') + } +</script> +{% endblock script %} \ No newline at end of file diff --git a/instances/templates/instances/access_tab.html b/instances/templates/instances/access_tab.html index f5b4579..b32046e 100644 --- a/instances/templates/instances/access_tab.html +++ b/instances/templates/instances/access_tab.html @@ -4,13 +4,15 @@ <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li class="nav-item"> - <a class="nav-link text-secondary active" href="#vnconsole" aria-controls="vnconsole" role="tab" data-toggle="tab"> + <a class="nav-link text-secondary active" href="#vnconsole" aria-controls="vnconsole" role="tab" + data-toggle="tab"> {% trans "Console" %} </a> </li> {% if app_settings.SHOW_ACCESS_ROOT_PASSWORD == 'True' %} <li class="nav-item"> - <a class="nav-link text-secondary" href="#rootpasswd" aria-controls="rootpasswd" role="tab" data-toggle="tab"> + <a class="nav-link text-secondary" href="#rootpasswd" aria-controls="rootpasswd" role="tab" + data-toggle="tab"> {% trans "Root Password" %} </a> </li> @@ -24,7 +26,8 @@ {% endif %} {% if instance.status == 1 %} <li class="nav-item"> - <a class="nav-link text-secondary" href="#vdiconsole" aria-controls="vdiconsole" role="tab" data-toggle="tab"> + <a class="nav-link text-secondary" href="#vdiconsole" aria-controls="vdiconsole" role="tab" + data-toggle="tab"> {% trans "VDI" %} </a> </li> @@ -33,38 +36,83 @@ <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane tab-pane-bordered active" id="vnconsole"> - <p>{% trans "This action opens a new window with a VNC connection to the console of the instance." %}</p> - {% if instance.status == 1 %} - <!-- Split button --> - <div class="btn-group float-right"> - <button type="button" id="consoleBtnGroup" class="btn btn-lg btn-success" onclick="open_console('lite')">{% trans 'Console' %}</button> - <button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - <span class="sr-only">{% trans 'Toggle Dropdown' %}</span> - </button> - <div class="dropdown-menu"> - <a class="dropdown-item" href="#" title="{% trans "Console port" %}: {{ instance.console_port }}" onclick="open_console('lite')">{% trans "Console" %} - {% trans "Lite" %}</a> - <a class="dropdown-item" href="#" title="{% trans "Console port" %}: {{ instance.console_port }}" onclick="open_console('full')">{% trans "Console" %} - {% trans "Full" %}</a> + <p>{% blocktrans with type=instance.console_type|upper %} This action opens a new window with a {{ type }} connection to the console of the instance.{% endblocktrans %} + </p> + {% if instance.console_type == 'vnc' %} + <div class="ml-3 form-row"> + <div class="custom-control custom-switch"> + <input class="custom-control-input" type="checkbox" name="scale" + {% if app_settings.CONSOLE_SCALE == 'True' %} checked {% endif %} + id="scale"> + <label class="custom-control-label font-weight-bold" for="scale">{% trans "Scale" %}</label> </div> </div> + <div class="ml-3 form-row"> + <div class="custom-control custom-switch"> + <input class="custom-control-input" type="checkbox" name="view_only" + {% if app_settings.CONSOLE_VIEW_ONLY == 'True' %} checked {% endif %} + id="view_only"> + <label class="custom-control-label font-weight-bold" for="view_only">{% trans "View Only" %}</label> + </div> + </div> + <div class="ml-3 form-row"> + <div class="custom-control custom-switch"> + <input class="custom-control-input" type="checkbox" name="resize_session" + {% if app_settings.CONSOLE_RESIZE_SESSION == 'True' %} checked {% endif %} + id="resize_session"> + <label class="custom-control-label font-weight-bold" for="resize_session">{% trans "Resize Session" %}</label> + </div> + </div> + <div class="ml-3 form-row"> + <div class="custom-control custom-switch"> + <input class="custom-control-input" type="checkbox" name="clip_viewport" + {% if app_settings.CONSOLE_CLIP_VIEWPORT == 'True' %} checked {% endif %} + id="clip_viewport"> + <label class="custom-control-label font-weight-bold" for="clip_viewport">{% trans "View Clipboard" %}</label> + </div> + </div> + {% endif %} + {% if instance.status == 1 %} + <!-- Split button --> + <div class="btn-group float-right"> + <button type="button" id="consoleBtnGroup" class="btn btn-lg btn-success" + onclick="open_console('lite')">{% trans 'Console' %}</button> + <button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split" + data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + <span class="sr-only">{% trans 'Toggle Dropdown' %}</span> + </button> + <div class="dropdown-menu"> + <a class="dropdown-item" href="#" + title="{% trans "Console port" %}: {{ instance.console_port }}" + onclick="open_console('lite')">{% trans "Console" %} - {% trans "Lite" %}</a> + <a class="dropdown-item" href="#" + title="{% trans "Console port" %}: {{ instance.console_port }}" + onclick="open_console('full')">{% trans "Console" %} - {% trans "Full" %}</a> + </div> + </div> {% else %} - <button class="btn btn-lg btn-success float-right disabled">{% trans "Console" %}</button> + <button class="btn btn-lg btn-success float-right disabled">{% trans "Console" %}</button> {% endif %} <div class="clearfix"></div> </div> - {% if app_settings.SHOW_ACCESS_SSH_KEYS == 'True' %} + {% if app_settings.SHOW_ACCESS_ROOT_PASSWORD == 'True' %} <div role="tabpanel" class="tab-pane tab-pane-bordered" id="rootpasswd"> <p>{% trans "You need shut down your instance and enter a new root password." %}</p> - <form action="{% url 'instances:rootpasswd' instance.id %}" class="form-inline" method="post" role="form" aria-label="Add root password to instance form"> + <form action="{% url 'instances:rootpasswd' instance.id %}" class="form-inline" method="post" + role="form" aria-label="Add root password to instance form"> {% csrf_token %} <div class="form-group row"> <div class="col-sm-12"> - <input type="text" class="form-control-lg" name="passwd" placeholder="{% trans "Enter Password" %}" maxlength="24"> + <input type="text" class="form-control-lg" name="passwd" + placeholder="{% trans "Enter Password" %}" maxlength="24"> </div> </div> {% if instance.status == 5 %} - <input type="submit" class="btn btn-lg btn-success float-right" name="rootpasswd" value="{% trans "Reset Root Password" %}"> + <input type="submit" class="btn btn-lg btn-success float-right" name="rootpasswd" + value="{% trans "Reset Root Password" %}"> {% else %} - <button class="btn btn-lg btn-success float-right disabled">{% trans "Reset Root Password" %}</button> + <button + class="btn btn-lg btn-success float-right disabled">{% trans "Reset Root Password" %}</button> {% endif %} </form> <div class="clearfix"></div> @@ -73,25 +121,27 @@ {% if app_settings.SHOW_ACCESS_SSH_KEYS == 'True' %} <div role="tabpanel" class="tab-pane tab-pane-bordered" id="sshkeys"> <p>{% trans "You need shut down your instance and choose your public key." %}</p> - <form action="{% url 'instances:add_public_key' instance.id %}" class="form-inline" method="post" role="form" aria-label="Add public key to instance form"> + <form action="{% url 'instances:add_public_key' instance.id %}" class="form-inline" method="post" + role="form" aria-label="Add public key to instance form"> {% csrf_token %} <div class="form-group row"> <div class="col-sm-12"> <select name="sshkeyid" class="form-control-lg keyselect"> {% if publickeys %} - {% for key in publickeys %} - <option value="{{ key.id }}">{{ key.keyname }}</option> - {% endfor %} + {% for key in publickeys %} + <option value="{{ key.id }}">{{ key.keyname }}</option> + {% endfor %} {% else %} - <option value="None">{% trans "None" %}</option> + <option value="None">{% trans "None" %}</option> {% endif %} </select> </div> </div> {% if instance.status == 5 %} - <input type="submit" class="btn btn-lg btn-success float-right" name="addpublickey" value="{% trans "Add Public Key" %}"> + <input type="submit" class="btn btn-lg btn-success float-right" name="addpublickey" + value="{% trans "Add Public Key" %}"> {% else %} - <button class="btn btn-lg btn-success float-right disabled">{% trans "Add Public Key" %}</button> + <button class="btn btn-lg btn-success float-right disabled">{% trans "Add Public Key" %}</button> {% endif %} </form> <div class="clearfix"></div> @@ -101,9 +151,9 @@ <div role="tabpanel" class="tab-pane tab-pane-bordered" id="vdiconsole"> <p>{% trans "This action opens a remote viewer with a connection to the console of the instance." %}</p> <div class="input-group"> - <input type="text" class="input-lg disabled form-control" disabled id="vdi_url_input"/> + <input type="text" class="input-lg disabled form-control" disabled id="vdi_url_input" /> <span class="input-group-append"> - <a href="#" class="btn btn-success" id="vdi_url" >{% trans "VDI" %}</a> + <a href="#" class="btn btn-success" id="vdi_url">{% trans "VDI" %}</a> </span> </div> <div class="clearfix"></div> @@ -112,3 +162,15 @@ </div> </div> </div> +{% block script %} +<script> + function open_console(view_style) { + const sc = $("#scale").is(':checked'); + const vo = $("#view_only").is(':checked'); + const rs = $("#resize_session").is(':checked'); + const cv = $("#clip_viewport").is(':checked'); + url = '{% url 'console' %}?token={{ compute.id }}-{{ instance.get_uuid }}&view=' + view_style + '' + '&view_only=' + vo + '' + '&scale=' + sc + '' + '&clip_viewport=' + cv + '' + '&resize_session=' + rs + ''; + window.open(url, '', 'width=850,height=600') + } +</script> +{% endblock %} \ No newline at end of file diff --git a/webvirtcloud/settings-dev.py b/webvirtcloud/settings-dev.py index dec7522..5f0b595 100644 --- a/webvirtcloud/settings-dev.py +++ b/webvirtcloud/settings-dev.py @@ -9,3 +9,20 @@ from webvirtcloud.settings import * DEBUG = True TEMPLATE_DEBUG = True + + +INSTALLED_APPS += [ + 'debug_toolbar', +] + +MIDDLEWARE += [ + 'debug_toolbar.middleware.DebugToolbarMiddleware', +] + +# DebugToolBar +INTERNAL_IPS = ( + '127.0.0.1', +) +DEBUG_TOOLBAR_CONFIG = { + 'INTERCEPT_REDIRECTS': False, +} \ No newline at end of file diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 4606cac..f31e7dd 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -10,7 +10,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = '' -DEBUG = True +DEBUG = False ALLOWED_HOSTS = ['*'] diff --git a/webvirtcloud/urls.py b/webvirtcloud/urls.py index b32eb36..a2e14a8 100644 --- a/webvirtcloud/urls.py +++ b/webvirtcloud/urls.py @@ -1,8 +1,9 @@ +from django.conf import settings from django.urls import include, path -from instances.views import index -from console.views import console from appsettings.views import appsettings +from console.views import console +from instances.views import index urlpatterns = [ path('', index, name='index'), @@ -16,3 +17,10 @@ urlpatterns = [ path('i18n/', include('django.conf.urls.i18n')), path('logs/', include('logs.urls')), ] + +if settings.DEBUG: + import debug_toolbar + + urlpatterns += [ + path('__debug__/', include(debug_toolbar.urls)), + ]