mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-09 11:46:49 +00:00
A VM defined with QEMU's own VNC websocket (graphics websocket='...', which the panel never sets) made the console page connect to that port on the panel's host name: the port is on the compute, so the console did not open unless the panel ran on that compute, and then it bypassed novncd and the panel's console token. Such a VM has its ordinary VNC port too, and novncd now reaches it there like any other VM.
381 lines
No EOL
18 KiB
HTML
Executable file
381 lines
No EOL
18 KiB
HTML
Executable file
{% extends "console-base.html" %}
|
|
{% load i18n %}
|
|
{% load static %}
|
|
|
|
{% block head %}
|
|
<!--
|
|
noVNC example: simple example using default UI
|
|
Copyright (C) 2018 The noVNC Authors
|
|
noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
|
|
This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
|
|
Connect parameters are provided in query string:
|
|
http://example.com/?host=HOST&port=PORT&encrypt=1
|
|
or the fragment:
|
|
http://example.com/#host=HOST&port=PORT&encrypt=1
|
|
-->
|
|
<title>WebVirtCloud - noVNC</title>
|
|
|
|
<meta charset="utf-8" />
|
|
|
|
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
|
|
Remove this if you use the .htaccess -->
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
|
|
<link rel="icon" type="image/x-icon" href="{% static "js/novnc/app/images/icons/novnc.ico" %}">
|
|
<link rel="icon" sizes="any" type="image/svg+xml" href="{% static "js/novnc/app/images/icons/novnc-icon.svg" %}">
|
|
|
|
<!-- Apple iOS Safari settings -->
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
|
|
<!-- iOS Home Screen Icons -->
|
|
<link rel="apple-touch-icon" sizes="40x40" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-40.png" %}">
|
|
<link rel="apple-touch-icon" sizes="58x58" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-58.png" %}">
|
|
<link rel="apple-touch-icon" sizes="60x60" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-60.png" %}">
|
|
<link rel="apple-touch-icon" sizes="76x76" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-76.png" %}">
|
|
<link rel="apple-touch-icon" sizes="80x80" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-80.png" %}">
|
|
<link rel="apple-touch-icon" sizes="87x87" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-87.png" %}">
|
|
<link rel="apple-touch-icon" sizes="120x120" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-120.png" %}">
|
|
<link rel="apple-touch-icon" sizes="152x152" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-152.png" %}">
|
|
<link rel="apple-touch-icon" sizes="167x167" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-167.png" %}">
|
|
<link rel="apple-touch-icon" sizes="180x180" type="image/png" href="{% static "js/novnc/app/images/icons/novnc-ios-180.png" %}">
|
|
|
|
<!-- Stylesheets -->
|
|
<link rel="stylesheet" href="{% static "js/novnc/app/styles/constants.css" %}">
|
|
<link rel="stylesheet" href="{% static "js/novnc/app/styles/base.css" %}">
|
|
<link rel="stylesheet" href="{% static "js/novnc/app/styles/input.css" %}">
|
|
|
|
<!-- Images that will later appear via CSS -->
|
|
<link rel="preload" as="image" href="{% static "js/novnc/app/images/info.svg" %}">
|
|
<link rel="preload" as="image" href="{% static "js/novnc/app/images/error.svg" %}">
|
|
<link rel="preload" as="image" href="{% static "js/novnc/app/images/warning.svg" %}">
|
|
|
|
<script type="module" crossorigin="anonymous" src="{% static "js/novnc/app/error-handler.js" %}"></script>
|
|
|
|
<!-- actual script modules -->
|
|
<script type="module" crossorigin="anonymous">
|
|
import UI from '{% static "js/novnc/app/ui.js" %}';
|
|
import { bindKeyAction, bindSendKeys } from '{% static "js/console_keys.js" %}';
|
|
|
|
bindKeyAction('fullscreen_button', () => {
|
|
if (typeof UI.fullscreen === 'function') {
|
|
UI.fullscreen();
|
|
}
|
|
});
|
|
|
|
bindSendKeys(() => UI.rfb);
|
|
|
|
// novncd behind the panel's own address (nginx's /novncd/)
|
|
let fullPath = 'novncd/';
|
|
const token = '{{ token|escapejs }}';
|
|
if (token) {
|
|
fullPath += (fullPath.includes('?') ? '&' : '?') + 'token=' + encodeURIComponent(token);
|
|
}
|
|
|
|
const defaults = {
|
|
autoconnect: true,
|
|
resize: '{% if resize_session %}remote{% elif scale %}scale{% else %}off{% endif %}',
|
|
view_only: {{ view_only|yesno:"true,false" }},
|
|
view_clip: {{ clip_viewport|yesno:"true,false" }},
|
|
{% if perms.instances.passwordless_console and console_passwd %}
|
|
password: '{{ console_passwd|escapejs }}',
|
|
{% endif %}
|
|
};
|
|
|
|
const https = window.location.protocol === 'https:';
|
|
const mandatory = {
|
|
host: window.location.hostname,
|
|
port: Number(window.location.port || (https ? 443 : 80)),
|
|
path: fullPath,
|
|
encrypt: https,
|
|
};
|
|
|
|
UI.start({ settings: { defaults, mandatory } });
|
|
</script>
|
|
<!-- end scripts -->
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div id="noVNC_fallback_error" class="noVNC_center">
|
|
<div>
|
|
<div>{% trans 'noVNC encountered an error' %}:</div>
|
|
<br>
|
|
<div id="noVNC_fallback_errormsg"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- noVNC Control Bar -->
|
|
<div id="noVNC_control_bar_anchor" class="noVNC_vcenter">
|
|
|
|
<div id="noVNC_control_bar">
|
|
<div id="noVNC_control_bar_handle" title="Hide/Show the control bar">
|
|
<div></div>
|
|
</div>
|
|
|
|
<div class="noVNC_scroll">
|
|
|
|
<h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>
|
|
|
|
<!-- Drag/Pan the viewport -->
|
|
<input type="image" alt="viewport drag" src="{% static "js/novnc/app/images/drag.svg" %}"
|
|
id="noVNC_view_drag_button" class="noVNC_button noVNC_hidden" title="Move/Drag Viewport" />
|
|
|
|
<!--noVNC Touch Device only buttons-->
|
|
<div id="noVNC_mobile_buttons">
|
|
<input type="image" alt="Keyboard" src="{% static "js/novnc/app/images/keyboard.svg" %}"
|
|
id="noVNC_keyboard_button" class="noVNC_button" title="Show Keyboard">
|
|
</div>
|
|
|
|
<!-- Extra manual keys -->
|
|
<input type="image" alt="Extra keys" src="{% static "js/novnc/app/images/toggleextrakeys.svg" %}"
|
|
id="noVNC_toggle_extra_keys_button" class="noVNC_button" title="Show Extra Keys" />
|
|
<div class="noVNC_vcenter">
|
|
<div id="noVNC_modifiers" class="noVNC_panel">
|
|
<input type="image" alt="Ctrl" src="{% static "js/novnc/app/images/ctrl.svg" %}"
|
|
id="noVNC_toggle_ctrl_button" class="noVNC_button" title="Toggle Ctrl" />
|
|
<input type="image" alt="Alt" src="{% static "js/novnc/app/images/alt.svg" %}"
|
|
id="noVNC_toggle_alt_button" class="noVNC_button" title="Toggle Alt" />
|
|
<input type="image" alt="Windows" src="{% static "js/novnc/app/images/windows.svg" %}"
|
|
id="noVNC_toggle_windows_button" class="noVNC_button" title="Toggle Windows">
|
|
<input type="image" alt="Tab" src="{% static "js/novnc/app/images/tab.svg" %}"
|
|
id="noVNC_send_tab_button" class="noVNC_button" title="Send Tab" />
|
|
<input type="image" alt="Esc" src="{% static "js/novnc/app/images/esc.svg" %}"
|
|
id="noVNC_send_esc_button" class="noVNC_button" title="Send Escape" />
|
|
<input type="image" alt="Ctrl+Alt+Del" src="{% static "js/novnc/app/images/ctrlaltdel.svg" %}"
|
|
id="noVNC_send_ctrl_alt_del_button" class="noVNC_button" title="Send Ctrl-Alt-Del" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Shutdown/Reboot -->
|
|
<input type="image" alt="Shutdown/Reboot" src="{% static "js/novnc/app/images/power.svg" %}"
|
|
id="noVNC_power_button" class="noVNC_button" title="Shutdown/Reboot..." />
|
|
<div class="noVNC_vcenter">
|
|
<div id="noVNC_power" class="noVNC_panel">
|
|
<div class="noVNC_heading">
|
|
<img src="{% static "js/novnc/app/images/power.svg" %}"> Power
|
|
</div>
|
|
<input type="button" id="noVNC_shutdown_button" value="Shutdown" />
|
|
<input type="button" id="noVNC_reboot_button" value="Reboot" />
|
|
<input type="button" id="noVNC_reset_button" value="Reset" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clipboard -->
|
|
<input type="image" alt="Clipboard" src="{% static "js/novnc/app/images/clipboard.svg" %}"
|
|
id="noVNC_clipboard_button" class="noVNC_button" title="Clipboard" />
|
|
<div class="noVNC_vcenter">
|
|
<div id="noVNC_clipboard" class="noVNC_panel">
|
|
<div class="noVNC_heading">
|
|
<img src="{% static "js/novnc/app/images/clipboard.svg" %}"> Clipboard
|
|
</div>
|
|
<textarea id="noVNC_clipboard_text"rows=5></textarea>
|
|
<br />
|
|
<input id="noVNC_clipboard_clear_button" type="button" value="Clear" class="noVNC_submit" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toggle fullscreen -->
|
|
<input type="image" alt="Fullscreen" src="{% static "js/novnc/app/images/fullscreen.svg" %}"
|
|
id="noVNC_fullscreen_button" class="noVNC_button noVNC_hidden" title="Fullscreen" />
|
|
|
|
<!-- Settings -->
|
|
<input type="image" alt="Settings" src="{% static "js/novnc/app/images/settings.svg" %}"
|
|
id="noVNC_settings_button" class="noVNC_button" title="Settings" />
|
|
<div class="noVNC_vcenter">
|
|
<div id="noVNC_settings" class="noVNC_panel">
|
|
<ul>
|
|
<li class="noVNC_heading">
|
|
<img src="{% static "js/novnc/app/images/settings.svg" %}"> Settings
|
|
</li>
|
|
<li>
|
|
<label><input id="noVNC_setting_shared" type="checkbox" /> Shared Mode</label>
|
|
</li>
|
|
<li>
|
|
<label><input id="noVNC_setting_view_only" type="checkbox" /> View Only</label>
|
|
</li>
|
|
<li>
|
|
<hr>
|
|
</li>
|
|
<li>
|
|
<label><input id="noVNC_setting_view_clip" type="checkbox" /> Clip to Window</label>
|
|
</li>
|
|
<li>
|
|
<label for="noVNC_setting_resize">Scaling Mode:</label>
|
|
<select id="noVNC_setting_resize" name="vncResize">
|
|
<option value="off">None</option>
|
|
<option value="scale">Local Scaling</option>
|
|
<option value="remote">Remote Resizing</option>
|
|
</select>
|
|
</li>
|
|
<li>
|
|
<hr>
|
|
</li>
|
|
<li>
|
|
<div class="noVNC_expander">Advanced</div>
|
|
<div><ul>
|
|
<li>
|
|
<label for="noVNC_setting_quality">Quality:</label>
|
|
<input id="noVNC_setting_quality" type="range" min="0" max="9" value="6">
|
|
</li>
|
|
<li>
|
|
<label for="noVNC_setting_compression">Compression level:</label>
|
|
<input id="noVNC_setting_compression" type="range" min="0" max="9" value="2">
|
|
</li>
|
|
<li><hr></li>
|
|
<li>
|
|
<label for="noVNC_setting_repeaterID">Repeater ID:</label>
|
|
<input id="noVNC_setting_repeaterID" type="text" value="">
|
|
</li>
|
|
<li>
|
|
<div class="noVNC_expander">WebSocket</div>
|
|
<div><ul>
|
|
<li>
|
|
<label><input id="noVNC_setting_encrypt" type="checkbox"> Encrypt</label>
|
|
</li>
|
|
<li>
|
|
<label for="noVNC_setting_host">Host:</label>
|
|
<input id="noVNC_setting_host" type="text">
|
|
</li>
|
|
<li>
|
|
<label for="noVNC_setting_port">Port:</label>
|
|
<input id="noVNC_setting_port" type="number">
|
|
</li>
|
|
<li>
|
|
<label for="noVNC_setting_path">Path:</label>
|
|
<!-- <input id="noVNC_setting_path" type="text" value="websockify"> -->
|
|
<input id="noVNC_setting_path" type="text">
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
<li><hr></li>
|
|
<li>
|
|
<label><input id="noVNC_setting_reconnect" type="checkbox"> Automatic Reconnect</label>
|
|
</li>
|
|
<li>
|
|
<label for="noVNC_setting_reconnect_delay">Reconnect Delay (ms):</label>
|
|
<input id="noVNC_setting_reconnect_delay" type="number">
|
|
</li>
|
|
<li><hr></li>
|
|
<li>
|
|
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No Cursor</label>
|
|
</li>
|
|
<li><hr></li>
|
|
<!-- Logging selection dropdown -->
|
|
<li>
|
|
<label>Logging:
|
|
<select id="noVNC_setting_logging" name="vncLogging">
|
|
</select>
|
|
</label>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
<li class="noVNC_version_separator"><hr></li>
|
|
<li class="noVNC_version_wrapper">
|
|
<span>Version:</span>
|
|
<span class="noVNC_version"></span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Connection Controls -->
|
|
<input type="image" alt="Disconnect" src="{% static "js/novnc/app/images/disconnect.svg" %}"
|
|
id="noVNC_disconnect_button" class="noVNC_button" title="Disconnect" />
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div> <!-- End of noVNC_control_bar -->
|
|
|
|
<div id="noVNC_hint_anchor" class="noVNC_vcenter">
|
|
<div id="noVNC_control_bar_hint">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Status Dialog -->
|
|
<div id="noVNC_status"></div>
|
|
|
|
<!-- Connect button -->
|
|
<div class="noVNC_center">
|
|
<div id="noVNC_connect_dlg">
|
|
<p class="noVNC_logo" translate="no"><span>no</span>VNC</p>
|
|
<div>
|
|
<button id="noVNC_connect_button">
|
|
<img alt="" src="{% static "js/novnc/app/images/connect.svg" %}"> {% trans 'Connect' %}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Server key verification dialog -->
|
|
<div class="noVNC_center noVNC_connect_layer">
|
|
<div id="noVNC_verify_server_dlg" class="noVNC_panel"><form>
|
|
<div class="noVNC_heading">
|
|
{% trans 'Server identity' %}
|
|
</div>
|
|
<div>
|
|
{% trans 'The server has provided the following identifying information:' %}
|
|
</div>
|
|
<div id="noVNC_fingerprint_block">
|
|
{% trans 'Fingerprint:' %}
|
|
<span id="noVNC_fingerprint"></span>
|
|
</div>
|
|
<div>
|
|
{% trans 'Please verify that the information is correct and press "Approve". Otherwise press "Reject".' %}
|
|
</div>
|
|
<div class="button_row">
|
|
<input id="noVNC_approve_server_button" type="submit" value="{% trans 'Approve' %}">
|
|
<input id="noVNC_reject_server_button" type="button" value="{% trans 'Reject' %}">
|
|
</div>
|
|
</form></div>
|
|
</div>
|
|
|
|
<!-- Password dialog -->
|
|
<div class="noVNC_center noVNC_connect_layer">
|
|
<div id="noVNC_credentials_dlg" class="noVNC_panel"><form>
|
|
<div class="noVNC_heading">
|
|
{% trans 'Credentials' %}
|
|
</div>
|
|
<div id="noVNC_username_block">
|
|
<label for="noVNC_username_input">{% trans 'Username' %}:</label>
|
|
<input id="noVNC_username_input">
|
|
</div>
|
|
<div id="noVNC_password_block">
|
|
<label for="noVNC_password_input">{% trans 'Password' %}:</label>
|
|
{% if perms.instances.passwordless_console %}
|
|
<input id="noVNC_password_input" type="password" value="{{ console_passwd|default_if_none:"" }}">
|
|
{% else %}
|
|
<input id="noVNC_password_input" type="password">
|
|
{% endif %}
|
|
</div>
|
|
<div class="button_row">
|
|
<input id="noVNC_credentials_button" type="submit" value="{% trans 'Send credentials' %}">
|
|
</div>
|
|
</form></div>
|
|
</div>
|
|
|
|
<!-- Transition Screens -->
|
|
<div id="noVNC_transition">
|
|
<div id="noVNC_transition_text"></div>
|
|
<div>
|
|
<input type="button" id="noVNC_cancel_reconnect_button" value="Cancel" class="noVNC_submit" />
|
|
</div>
|
|
<div class="noVNC_spinner"></div>
|
|
</div>
|
|
|
|
<!-- This is where the RFB elements will attach -->
|
|
<div id="noVNC_container">
|
|
<!-- Note that Google Chrome on Android doesn't respect any of these,
|
|
html attributes which attempt to disable text suggestions on the
|
|
on-screen keyboard. Let's hope Chrome implements the ime-mode
|
|
style for example -->
|
|
<textarea id="noVNC_keyboardinput" autocapitalize="off" autocomplete="off" spellcheck="false"
|
|
tabindex="-1"></textarea>
|
|
</div>
|
|
|
|
<audio id="noVNC_bell">
|
|
<source src="{% static "js/novnc/app/sounds/bell.oga" %}" type="audio/ogg">
|
|
<source src="{% static "js/novnc/app/sounds/bell.mp3" %}" type="audio/mpeg">
|
|
</audio>
|
|
{% endblock %} |