mirror of
https://github.com/retspen/webvirtcloud
synced 2024-12-24 23:25:24 +00:00
Merge pull request #344 from catborise/console_enrichments
vnc console options added
This commit is contained in:
commit
618d5ec7c1
24 changed files with 257 additions and 100 deletions
12
.github/workflows/linter.yml
vendored
12
.github/workflows/linter.yml
vendored
|
@ -17,7 +17,6 @@ jobs:
|
||||||
# The type of runner that the job will run on
|
# The type of runner that the job will run on
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|
||||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
steps:
|
steps:
|
||||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||||
|
@ -35,16 +34,21 @@ jobs:
|
||||||
python3 -m pip install --upgrade pip
|
python3 -m pip install --upgrade pip
|
||||||
if [ -f dev/requirements.txt ]; then pip3 install -r dev/requirements.txt; fi
|
if [ -f dev/requirements.txt ]; then pip3 install -r dev/requirements.txt; fi
|
||||||
- name: Super-Linter
|
- name: Super-Linter
|
||||||
uses: docker://github/super-linter:v2.2.0
|
uses: docker://github/super-linter:v3.3.2
|
||||||
env:
|
env:
|
||||||
VALIDATE_ANSIBLE: false
|
VALIDATE_ANSIBLE: false
|
||||||
VALIDATE_CLOJURE: false
|
VALIDATE_CLOJURE: false
|
||||||
VALIDATE_COFFEE: false
|
VALIDATE_COFFEE: false
|
||||||
|
VALIDATE_DART: false
|
||||||
VALIDATE_GO: false
|
VALIDATE_GO: false
|
||||||
VALIDATE_POWERSHELL: false
|
VALIDATE_JSX: false
|
||||||
VALIDATE_KOTLIN: false
|
VALIDATE_KOTLIN: false
|
||||||
VALIDATE_RUBY: false
|
VALIDATE_POWERSHELL: false
|
||||||
VALIDATE_PERL: false
|
VALIDATE_PERL: false
|
||||||
VALIDATE_PHP: false
|
VALIDATE_PHP: false
|
||||||
|
VALIDATE_RAKU: false
|
||||||
|
VALIDATE_RUBY: false
|
||||||
|
VALIDATE_TSX: false
|
||||||
VALIDATE_TERRAFORM: false
|
VALIDATE_TERRAFORM: false
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ language: python
|
||||||
python:
|
python:
|
||||||
- "3.6"
|
- "3.6"
|
||||||
env:
|
env:
|
||||||
- DJANGO=2.2.12
|
- DJANGO=2.2.14
|
||||||
install:
|
install:
|
||||||
- pip install -r dev/requirements.txt
|
- pip install -r dev/requirements.txt
|
||||||
script:
|
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 \
|
console create datasource instances interfaces \
|
||||||
logs networks nwfilters secrets storages
|
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
|
nwfilters networks secrets storages logs
|
||||||
- python manage.py migrate
|
- python manage.py migrate
|
||||||
- python manage.py test --settings=webvirtcloud.settings-dev
|
- python manage.py test --settings=webvirtcloud.settings-dev
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
## WebVirtCloud
|
## WebVirtCloud
|
||||||
###### Python3 & Django 2.2.12
|
###### Python3 & Django 2.2
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* QEMU/KVM Hypervisor Management
|
* QEMU/KVM Hypervisor Management
|
||||||
|
@ -301,7 +301,7 @@ datasource:
|
||||||
```
|
```
|
||||||
|
|
||||||
### Reverse-Proxy
|
### 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
|
WS_PUBLIC_PORT = 80
|
||||||
```
|
```
|
||||||
|
@ -330,7 +330,7 @@ pip install -r conf/requirements.txt
|
||||||
```
|
```
|
||||||
Run tests
|
Run tests
|
||||||
```bash
|
```bash
|
||||||
python menage.py test
|
python manage.py test
|
||||||
```
|
```
|
||||||
|
|
||||||
### Screenshots
|
### Screenshots
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from instances.models import Instance
|
from instances.models import Instance
|
||||||
|
|
||||||
|
|
||||||
class UserInstanceManager(models.Manager):
|
class UserInstanceManager(models.Manager):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().select_related('instance', 'user')
|
return super().get_queryset().select_related('instance', 'user')
|
||||||
|
|
35
appsettings/migrations/0004_auto_20200716_0637.py
Normal file
35
appsettings/migrations/0004_auto_20200716_0637.py
Normal file
|
@ -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),
|
||||||
|
]
|
|
@ -112,10 +112,5 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block script %}
|
{% block script %}
|
||||||
<script src="{% static "js/sortable.min.js" %}"></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>
|
<script src="{% static 'js/filter-table.js' %}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -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
|
|
|
@ -1,13 +1,13 @@
|
||||||
beautifulsoup4==4.9.1
|
beautifulsoup4==4.9.1
|
||||||
Django==2.2.13
|
Django==2.2.14
|
||||||
django-bootstrap4==2.0.1
|
django-bootstrap4==2.2.0
|
||||||
django-icons==2.0.0
|
django-icons==2.1.1
|
||||||
django-login-required-middleware==0.5.0
|
django-login-required-middleware==0.5.0
|
||||||
gunicorn==20.0.4
|
gunicorn==20.0.4
|
||||||
libsass==0.20.0
|
libsass==0.20.0
|
||||||
libvirt-python==6.3.0
|
libvirt-python==6.4.0
|
||||||
lxml==4.5.0
|
lxml==4.5.2
|
||||||
numpy==1.18.4
|
numpy==1.18.5
|
||||||
pytz==2020.1
|
pytz==2020.1
|
||||||
rwlock==0.0.7
|
rwlock==0.0.7
|
||||||
six==1.15.0
|
six==1.15.0
|
||||||
|
|
|
@ -199,7 +199,11 @@
|
||||||
<label for="port">{% trans 'Port' %}:</label>
|
<label for="port">{% trans 'Port' %}:</label>
|
||||||
<input type='text' id='port' value='{{ ws_port }}'>
|
<input type='text' id='port' value='{{ ws_port }}'>
|
||||||
<label for="password">{% trans 'Password' %}:</label>
|
<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>
|
<label for="show_console">{% trans 'Show console' %}</label>
|
||||||
<input type="checkbox" id="show_console" value="1" onchange="toggle_console()" checked>
|
<input type="checkbox" id="show_console" value="1" onchange="toggle_console()" checked>
|
||||||
<button id="connectButton">{% trans 'Start' %}</button>
|
<button id="connectButton">{% trans 'Start' %}</button>
|
||||||
|
|
|
@ -93,7 +93,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password === undefined) {
|
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 }}';
|
//password = '{{ console_passwd | safe }}';
|
||||||
}
|
}
|
||||||
if (password === 'None') password = '';
|
if (password === 'None') password = '';
|
||||||
|
|
|
@ -297,7 +297,11 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<label>Password:</label>
|
<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>
|
||||||
<li>
|
<li>
|
||||||
<input id="noVNC_password_button" type="submit" value="Send Password" class="noVNC_submit" />
|
<input id="noVNC_password_button" type="submit" value="Send Password" class="noVNC_submit" />
|
||||||
|
|
|
@ -167,7 +167,13 @@
|
||||||
// By default, use the host and port of server that served this file
|
// By default, use the host and port of server that served this file
|
||||||
const host = readQueryVariable('host', '{{ ws_host }}');
|
const host = readQueryVariable('host', '{{ ws_host }}');
|
||||||
let port = readQueryVariable('port', '{{ ws_port }}');
|
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', 'websockify');
|
||||||
const path = readQueryVariable('path', '{{ ws_path }}');
|
const path = readQueryVariable('path', '{{ ws_path }}');
|
||||||
|
|
||||||
|
@ -202,10 +208,10 @@
|
||||||
rfb.addEventListener("capabilities", function () { updatePowerButtons(); });
|
rfb.addEventListener("capabilities", function () { updatePowerButtons(); });
|
||||||
|
|
||||||
// Set parameters that can be changed on an active connection
|
// Set parameters that can be changed on an active connection
|
||||||
rfb.viewOnly = readQueryVariable('view_only', {{ view_only }});
|
rfb.scaleViewport = {{ scale }};
|
||||||
rfb.scaleViewport = readQueryVariable('scale', {{ scale }});
|
rfb.viewOnly = {{ view_only }};
|
||||||
rfb.resizeSession = readQueryVariable('resize', {{ resize_session }});
|
rfb.resizeSession = {{ resize_session }};
|
||||||
rfb.clipViewport = readQueryVariable('clip_viewport', {{ clip_viewport }});
|
rfb.clipViewport = {{ clip_viewport }};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from libvirt import libvirtError
|
from libvirt import libvirtError
|
||||||
|
|
||||||
|
from appsettings.settings import app_settings
|
||||||
from instances.models import Instance
|
from instances.models import Instance
|
||||||
from vrtManager.instance import wvmInstance
|
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):
|
def console(request):
|
||||||
|
@ -16,10 +20,10 @@ def console(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
token = request.GET.get('token', '')
|
token = request.GET.get('token', '')
|
||||||
view_type = request.GET.get('view', 'lite')
|
view_type = request.GET.get('view', 'lite')
|
||||||
view_only = request.GET.get('view_only', 0)
|
view_only = request.GET.get('view_only', app_settings.CONSOLE_VIEW_ONLY.lower())
|
||||||
scale = request.GET.get('scale', 0)
|
scale = request.GET.get('scale', app_settings.CONSOLE_SCALE.lower())
|
||||||
resize_session = request.GET.get('resize_session', 0)
|
resize_session = request.GET.get('resize_session', app_settings.CONSOLE_RESIZE_SESSION.lower())
|
||||||
clip_viewport = request.GET.get('clip_viewport', 0)
|
clip_viewport = request.GET.get('clip_viewport', app_settings.CONSOLE_CLIP_VIEWPORT.lower())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
temptoken = token.split('-', 1)
|
temptoken = token.split('-', 1)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
-r ../conf/requirements.txt
|
-r ../conf/requirements.txt
|
||||||
coverage==5.1
|
coverage==5.2
|
||||||
pycodestyle
|
django-debug-toolbar==2.2
|
||||||
|
pycodestyle==2.6.0
|
||||||
pyflakes==2.2.0
|
pyflakes==2.2.0
|
||||||
pylint==2.5.2
|
pylint==2.5.3
|
||||||
|
yapf==0.30.0
|
||||||
|
|
|
@ -22,6 +22,18 @@ def migrate_can_clone_instances(sender, **kwargs):
|
||||||
user.user_permissions.add(permission)
|
user.user_permissions.add(permission)
|
||||||
break
|
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):
|
class InstancesConfig(AppConfig):
|
||||||
name = 'instances'
|
name = 'instances'
|
||||||
|
@ -29,3 +41,4 @@ class InstancesConfig(AppConfig):
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
post_migrate.connect(migrate_can_clone_instances, sender=self)
|
post_migrate.connect(migrate_can_clone_instances, sender=self)
|
||||||
|
post_migrate.connect(apply_passwordless_console, sender=self)
|
||||||
|
|
17
instances/migrations/0009_auto_20200717_0524.py
Normal file
17
instances/migrations/0009_auto_20200717_0524.py
Normal file
|
@ -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')]},
|
||||||
|
),
|
||||||
|
]
|
|
@ -211,6 +211,8 @@ class PermissionSet(models.Model):
|
||||||
"""
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
permissions = (('clone_instances', _('Can clone instances')), )
|
permissions = [('clone_instances', 'Can clone instances'),
|
||||||
|
('passwordless_console', _('Can access console without password')),
|
||||||
|
]
|
||||||
|
|
||||||
managed = False
|
managed = False
|
||||||
|
|
|
@ -38,11 +38,6 @@
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{% block script %}
|
{% block script %}
|
||||||
<script src="{% static "js/sortable.min.js" %}"></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>
|
<script src="{% static 'js/filter-table.js' %}"></script>
|
||||||
{% if request.user.is_superuser %}
|
{% if request.user.is_superuser %}
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -166,11 +166,6 @@
|
||||||
input.val(editor.getSession().getValue());
|
input.val(editor.getSession().getValue());
|
||||||
});
|
});
|
||||||
</script>
|
</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>
|
<script>
|
||||||
function random_mac(net) {
|
function random_mac(net) {
|
||||||
$.getJSON('{% url 'instances:random_mac_address' %}', function (data) {
|
$.getJSON('{% url 'instances:random_mac_address' %}', function (data) {
|
||||||
|
|
|
@ -42,4 +42,12 @@
|
||||||
<span class="fa fa-eye"></span>
|
<span class="fa fa-eye"></span>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
|
{% block script %}
|
||||||
|
<script>
|
||||||
|
function open_console(uuid) {
|
||||||
|
url = '{% url 'console' %}?token=' + uuid + '';
|
||||||
|
window.open(url, '', 'width=850,height=650')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock script %}
|
|
@ -4,13 +4,15 @@
|
||||||
<!-- Nav tabs -->
|
<!-- Nav tabs -->
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li class="nav-item">
|
<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" %}
|
{% trans "Console" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if app_settings.SHOW_ACCESS_ROOT_PASSWORD == 'True' %}
|
{% if app_settings.SHOW_ACCESS_ROOT_PASSWORD == 'True' %}
|
||||||
<li class="nav-item">
|
<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" %}
|
{% trans "Root Password" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -24,7 +26,8 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if instance.status == 1 %}
|
{% if instance.status == 1 %}
|
||||||
<li class="nav-item">
|
<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" %}
|
{% trans "VDI" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -33,38 +36,83 @@
|
||||||
<!-- Tab panes -->
|
<!-- Tab panes -->
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="vnconsole">
|
<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>
|
<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 %}
|
||||||
{% if instance.status == 1 %}
|
</p>
|
||||||
<!-- Split button -->
|
{% if instance.console_type == 'vnc' %}
|
||||||
<div class="btn-group float-right">
|
<div class="ml-3 form-row">
|
||||||
<button type="button" id="consoleBtnGroup" class="btn btn-lg btn-success" onclick="open_console('lite')">{% trans 'Console' %}</button>
|
<div class="custom-control custom-switch">
|
||||||
<button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<input class="custom-control-input" type="checkbox" name="scale"
|
||||||
<span class="sr-only">{% trans 'Toggle Dropdown' %}</span>
|
{% if app_settings.CONSOLE_SCALE == 'True' %} checked {% endif %}
|
||||||
</button>
|
id="scale">
|
||||||
<div class="dropdown-menu">
|
<label class="custom-control-label font-weight-bold" for="scale">{% trans "Scale" %}</label>
|
||||||
<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>
|
||||||
</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 %}
|
{% 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 %}
|
{% endif %}
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</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">
|
<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>
|
<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 %}
|
{% csrf_token %}
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="col-sm-12">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
{% if instance.status == 5 %}
|
{% 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 %}
|
{% 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 %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -73,25 +121,27 @@
|
||||||
{% if app_settings.SHOW_ACCESS_SSH_KEYS == 'True' %}
|
{% if app_settings.SHOW_ACCESS_SSH_KEYS == 'True' %}
|
||||||
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="sshkeys">
|
<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>
|
<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 %}
|
{% csrf_token %}
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<select name="sshkeyid" class="form-control-lg keyselect">
|
<select name="sshkeyid" class="form-control-lg keyselect">
|
||||||
{% if publickeys %}
|
{% if publickeys %}
|
||||||
{% for key in publickeys %}
|
{% for key in publickeys %}
|
||||||
<option value="{{ key.id }}">{{ key.keyname }}</option>
|
<option value="{{ key.id }}">{{ key.keyname }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<option value="None">{% trans "None" %}</option>
|
<option value="None">{% trans "None" %}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if instance.status == 5 %}
|
{% 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 %}
|
{% 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 %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -101,9 +151,9 @@
|
||||||
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="vdiconsole">
|
<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>
|
<p>{% trans "This action opens a remote viewer with a connection to the console of the instance." %}</p>
|
||||||
<div class="input-group">
|
<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">
|
<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>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -112,3 +162,15 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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 %}
|
|
@ -9,3 +9,20 @@ from webvirtcloud.settings import *
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
TEMPLATE_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,
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
SECRET_KEY = ''
|
SECRET_KEY = ''
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = False
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
from django.conf import settings
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
|
||||||
from instances.views import index
|
|
||||||
from console.views import console
|
|
||||||
from appsettings.views import appsettings
|
from appsettings.views import appsettings
|
||||||
|
from console.views import console
|
||||||
|
from instances.views import index
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', index, name='index'),
|
path('', index, name='index'),
|
||||||
|
@ -16,3 +17,10 @@ urlpatterns = [
|
||||||
path('i18n/', include('django.conf.urls.i18n')),
|
path('i18n/', include('django.conf.urls.i18n')),
|
||||||
path('logs/', include('logs.urls')),
|
path('logs/', include('logs.urls')),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
import debug_toolbar
|
||||||
|
|
||||||
|
urlpatterns += [
|
||||||
|
path('__debug__/', include(debug_toolbar.urls)),
|
||||||
|
]
|
||||||
|
|
Loading…
Reference in a new issue