Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: retspen/webvirtmgr
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.8.9
Choose a base ref
...
head repository: retspen/webvirtmgr
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on May 3, 2015

  1. Unified VNC/SPICE console interfaces with bootstrap

    Benjamin Renard committed May 3, 2015
    Copy the full SHA
    df48bfa View commit details
  2. Fix console local socket access on CONN_SOCKET host

    Benjamin Renard committed May 3, 2015
    Copy the full SHA
    81a42af View commit details

Commits on Oct 13, 2015

  1. Don't hide ISOs with uppercase names

    Most Microsoft ISOs are distributed by default with the extension being in upper-case, while most *nix ISOs are lower-case.  For a brief moment I thought the code was inhabited by an evil Microsoft-hating spirit...
    darkpixel committed Oct 13, 2015
    Copy the full SHA
    680c3d1 View commit details

Commits on Oct 15, 2015

  1. Merge pull request #580 from darkpixel/patch-1

    Don't hide ISOs with uppercase names
    retspen committed Oct 15, 2015
    Copy the full SHA
    b73cdaf View commit details

Commits on Nov 2, 2015

  1. Copy the full SHA
    202b73b View commit details
  2. Fixup an un-needed import

    Matt Hart committed Nov 2, 2015
    Copy the full SHA
    df3c5c1 View commit details

Commits on Nov 26, 2015

  1. Add support qed

    forumi0721 committed Nov 26, 2015
    Copy the full SHA
    f235421 View commit details

Commits on Nov 27, 2015

  1. Merge pull request #584 from mattface/master

    Properly parse the capabilities XML to confirm KVM support
    retspen committed Nov 27, 2015
    Copy the full SHA
    1be4e56 View commit details
  2. Merge pull request #588 from forumi0721/master

    Add support qed
    retspen committed Nov 27, 2015
    Copy the full SHA
    690a0d2 View commit details

Commits on Jan 4, 2016

  1. Update settings.py

    Add WS_KEY option to settings.py
    aaronbrooks-gh committed Jan 4, 2016
    Copy the full SHA
    5e8d944 View commit details
  2. Update webvirtmgr-console

    Add options for separate SSL key file (-k, --key) and SSL only operation (--ssl-only) for noVNC Websockets proxy, allowing better HTTPS support.
    aaronbrooks-gh committed Jan 4, 2016
    Copy the full SHA
    475cc28 View commit details

Commits on Jan 18, 2016

  1. RPM: support for rhel 7

    gsanchietti committed Jan 18, 2016
    Copy the full SHA
    ddc929c View commit details

Commits on Feb 18, 2016

  1. Copy the full SHA
    2a41cc6 View commit details
  2. Copy the full SHA
    e1c7abb View commit details

Commits on Apr 1, 2016

  1. Copy the full SHA
    385cd33 View commit details
  2. Copy the full SHA
    0e0bae2 View commit details
  3. Retreive all RBD hosts (and their port if defined) from pool definiti…

    …on during instance creation
    brenard committed Apr 1, 2016
    Copy the full SHA
    8517ba9 View commit details

Commits on Apr 3, 2016

  1. Fix pep8 error

    brenard committed Apr 3, 2016
    Copy the full SHA
    e94d0c3 View commit details
  2. Fix pep8 error (bis)

    brenard committed Apr 3, 2016
    Copy the full SHA
    1f9d6e1 View commit details

Commits on May 8, 2016

  1. Merge pull request #590 from promythyus/novnc-proxy-ssl-key-support

    Novnc proxy ssl key support
    retspen committed May 8, 2016
    Copy the full SHA
    d0a14f3 View commit details
  2. Merge pull request #605 from NethServer/master

    Fixes for RPM on EL 7
    retspen committed May 8, 2016
    Copy the full SHA
    b5cf49d View commit details
  3. Merge pull request #608 from brenard/master

    Some improvements on Console / HDD disk device
    retspen committed May 8, 2016
    Copy the full SHA
    79c8a8b View commit details

Commits on May 31, 2018

  1. Update README.rst

    retspen authored May 31, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0935747 View commit details

Commits on Jul 20, 2018

  1. Fixed vulnerability

    retspen authored Jul 20, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e9b41b9 View commit details
  2. Fixed pip error

    retspen authored Jul 20, 2018

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    86bb20f View commit details
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
language: python
python:
- "2.6"
- "2.7"
env:
- DJANGO=1.5.5
install:
- pip install -r dev-requirements.txt --use-mirrors
- pip install -r dev-requirements.txt
script:
- pep8 --exclude=IPy.py --ignore=E501 console hostdetail instance networks servers storages vrtManager
- pyflakes console hostdetail instance networks servers storages vrtManager
4 changes: 0 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
@@ -54,7 +54,3 @@ License
*******

WebVirtMgr is licensed under the `Apache Licence, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0.html>`_.

.. image:: https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CEN82VLX7GD7S
:alt: Donate
9 changes: 9 additions & 0 deletions conf/init/webvirtmgr-console.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=WebVirtMgr NoVNC proxy

[Service]
ExecStart=/usr/lib/python2.7/site-packages/webvirtmgr/console/webvirtmgr-console
Type=simple

[Install]
WantedBy=multi-user.target
9 changes: 9 additions & 0 deletions conf/init/webvirtmgr.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=WebVirtMgr Gunicorn Server

[Service]
WorkingDirectory=/usr/lib/python2.7/site-packages/webvirtmgr
ExecStart=/usr/bin/python /usr/lib/python2.7/site-packages/webvirtmgr/manage.py run_gunicorn -c /usr/lib/python2.7/site-packages/webvirtmgr/conf/gunicorn.conf.py

[Install]
WantedBy=multi-user.target
26 changes: 20 additions & 6 deletions console/webvirtmgr-console
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ if ROOT_PATH not in sys.path:

import Cookie
import socket
from webvirtmgr.settings import WS_PORT, WS_HOST, WS_CERT
from webvirtmgr.settings import WS_PORT, WS_HOST, WS_CERT, WS_KEY

from vrtManager.connection import CONN_SSH, CONN_SOCKET

@@ -62,6 +62,20 @@ parser.add_option("-c",
action="store",
help="Certificate file path",
default=WS_CERT or CERT)

parser.add_option("-k",
"--key",
dest="key",
action="store",
help="Certificate key file path",
default=WS_KEY)

parser.add_option("--ssl-only",
dest="ssl_only",
action="store_true",
help="Deny non-ssl connections",
default=False)


(options, args) = parser.parse_args()

@@ -153,7 +167,7 @@ class CompatibilityMixIn(object):
self.msg('Try to open local socket %s' % console_socket)
tsock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
tsock.connect(console_socket)
elif console_socket or re.match('^127\.', console_host):
elif console_socket or re.match('^127\.', console_host) and conntype != CONN_SOCKET:
# Need tunnel to physical host
if conntype != CONN_SSH:
self.msg("Need a tunnel to access console but can't mount " +
@@ -242,8 +256,8 @@ if __name__ == '__main__':
source_is_ipv6=False,
verbose=options.verbose,
cert=options.cert,
key=None,
ssl_only=False,
key=options.key,
ssl_only=options.ssl_only,
daemon=False,
record=False,
web=False,
@@ -259,8 +273,8 @@ if __name__ == '__main__':
source_is_ipv6=False,
verbose=options.verbose,
cert=options.cert,
key=None,
ssl_only=False,
key=options.key,
ssl_only=options.ssl_only,
daemon=False,
record=False,
web=False,
1 change: 1 addition & 0 deletions create/forms.py
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ class NewVMForm(forms.Form):
storage = forms.CharField(max_length=20, required=False)
template = forms.CharField(required=False)
images = forms.CharField(required=False)
cache_mode = forms.CharField(error_messages={'required': _('Please select HDD cache mode')})
hdd_size = forms.IntegerField(required=False)
meta_prealloc = forms.BooleanField(required=False)
virtio = forms.BooleanField(required=False)
7 changes: 6 additions & 1 deletion create/views.py
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ def create(request, host_id):
networks = sorted(conn.get_networks())
instances = conn.get_instances()
get_images = sorted(conn.get_storages_images())
cache_modes = sorted(conn.get_cache_modes().items())
mac_auto = util.randomMAC()
except libvirtError as err:
errors.append(err)
@@ -121,11 +122,15 @@ def create(request, host_id):
volumes[path] = conn.get_volume_type(path)
except libvirtError as msg_error:
errors.append(msg_error.message)
if data['cache_mode'] not in conn.get_cache_modes():
msg = _("Invalid cache mode")
errors.append(msg)
if not errors:
uuid = util.randomUUID()
try:
conn.create_instance(data['name'], data['memory'], data['vcpu'], data['host_model'],
uuid, volumes, data['networks'], data['virtio'], data['mac'])
uuid, volumes, data['cache_mode'], data['networks'], data['virtio'],
data['mac'])
create_instance = Instance(compute_id=host_id, name=data['name'], uuid=uuid)
create_instance.save()
return HttpResponseRedirect(reverse('instance', args=[host_id, data['name']]))
92 changes: 78 additions & 14 deletions deploy/rpmbuild/webvirtmgr.spec
Original file line number Diff line number Diff line change
@@ -11,10 +11,30 @@ License: Apache Licence, Version 2.0
URL: http://github.com/retspen/webvirtmgr
Source0: https://github.com/retspen/webvirtmgr/archive/master.tar.gz

%if 0%{?rhel} >= 7 || 0%{?fedora}
%bcond_without systemd # enabled
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
BuildRequires: systemd
%else
%bcond_with systemd # disabled
Requires(post): chkconfig
Requires(postun): /sbin/service
Requires(preun): /sbin/service
Requires(preun): chkconfig
%endif

BuildArch: noarch
BuildRequires: python-setuptools

Requires: python-setuptools libvirt-python libxml2-python python-websockify python-django15 python-gunicorn python-lockfile
Requires: python-setuptools libvirt-python libxml2-python python-websockify python-gunicorn python-lockfile
%if 0%{?rhel} >= 7
Requires: python-django
%else
Requires: python-django15
%endif

Requires: libvirt qemu-kvm

%description
@@ -30,34 +50,78 @@ KVM is currently the only hypervisor supported.
%{__python} setup.py build

%install
%{__python} setup.py install --skip-build --install-lib=%{python_sitelib}/%{name} --root $RPM_BUILD_ROOT
cp -r templates $RPM_BUILD_ROOT%{python_sitelib}/%{name}/
cp -r webvirtmgr/static $RPM_BUILD_ROOT%{python_sitelib}/%{name}/
%{__python} setup.py install --skip-build --install-lib=%{python_sitelib}/%{name} --root %{buildroot}
cp -r templates %{buildroot}%{python_sitelib}/%{name}/
cp -r webvirtmgr/static %{buildroot}%{python_sitelib}/%{name}/

mkdir -p $RPM_BUILD_ROOT%{python_sitelib}/%{name}/conf
cp conf/gunicorn.conf.py $RPM_BUILD_ROOT%{python_sitelib}/%{name}/conf/gunicorn.conf.py
mkdir -p %{buildroot}%{python_sitelib}/%{name}/conf
cp conf/gunicorn.conf.py %{buildroot}%{python_sitelib}/%{name}/conf/gunicorn.conf.py

mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init
cp conf/init/webvirtmgr-redhat.conf $RPM_BUILD_ROOT%{_sysconfdir}/init/webvirtmgr.conf

mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d
cp conf/initd/webvirtmgr-console-redhat $RPM_BUILD_ROOT%{_sysconfdir}/init.d/webvirtmgr-console
%if %{with systemd}
mkdir -p %{buildroot}%{_unitdir}
install -m0644 conf/init/webvirtmgr-console.service %{buildroot}%{_unitdir}/webvirtmgr-console.service
install -m0644 conf/init/webvirtmgr.service %{buildroot}%{_unitdir}/webvirtmgr.service
%else
mkdir -p %{buildroot}%{_sysconfdir}/init
cp conf/init/webvirtmgr-redhat.conf %{buildroot}%{_sysconfdir}/init/webvirtmgr.conf
mkdir -p %{buildroot}%{_sysconfdir}/init.d
cp conf/initd/webvirtmgr-console-redhat %{buildroot}%{_sysconfdir}/init.d/webvirtmgr-console
%endif

cp manage.py $RPM_BUILD_ROOT%{python_sitelib}/%{name}/
rm -rf $RPM_BUILD_ROOT%{_bindir}/manage.py
cp manage.py %{buildroot}%{python_sitelib}/%{name}/
rm -rf %{buildroot}%{_bindir}/manage.py

%post
%if %{with systemd}
%systemd_post webvirtmgr.service
%systemd_post webvirtmgr-console.service
%else
/sbin/chkconfig --add webvirtmgr
/sbin/chkconfig --add webvirtmgr-console
%endif

%preun
%if %{with systemd}
%systemd_preun webvirtmgr.service
%systemd_preun webvirtmgr-console.service
%else
if [ $1 -eq 0 ]; then
/sbin/stop webvirtmgr >/dev/null 2>&1 || :
/sbin/chkconfig --del webvirtmgr
/sbin/service webvirtmgr stop >/dev/null 2>&1 || :
/sbin/chkconfig --del webvirtmgr-console
fi
%endif

%postun
%if %{with systemd}
%systemd_postun_with_restart webvirtmgr.service
%systemd_postun_with_restart webvirtmgr-console.service
%else
if [ $1 -ge 1 ]; then
/sbin/restart webvirtmgr >/dev/null 2>&1 || :
/sbin/service webvirtmgr-console restart >/dev/null 2>&1 || :
fi
%endif

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root)
%{python_sitelib}/*
%config %{python_sitelib}/%{name}/conf/gunicorn.conf.py
%if %{with systemd}
%{_unitdir}/webvirtmgr.service
%{_unitdir}/webvirtmgr-console.service
%else
%{_sysconfdir}/init/*
%{_sysconfdir}/init.d/*
%endif

%changelog
* Mon Jan 18 2016 Giacomo Sanchietti <giacomo.sanchietti@nethesis.it> - 4.8.9
- Support rhel 7
- Upgrade to 4.8.9

* Wed Jan 26 2015 Edoardo Spadoni <edoardo.spadoni@nethesis.it> - 4.8.8
- first version
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
django==1.5.5
gunicorn==18.0
gunicorn==19.5.0
# Utility Requirements
# for SECURE_KEY generation
lockfile>=0.9
2 changes: 2 additions & 0 deletions storages/forms.py
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ class AddImage(forms.Form):
name = forms.CharField(max_length=20)
format = forms.ChoiceField(required=True, choices=(('qcow2', 'qcow2 (recommended)'),
('qcow', 'qcow'),
('qed', 'qed'),
('raw', 'raw')))
size = forms.IntegerField()
meta_prealloc = forms.BooleanField(required=False)
@@ -75,6 +76,7 @@ class CloneImage(forms.Form):
convert = forms.BooleanField(required=False)
format = forms.ChoiceField(required=False, choices=(('qcow2', 'qcow2 (recommended)'),
('qcow', 'qcow'),
('qed', 'qed'),
('raw', 'raw')))
meta_prealloc = forms.BooleanField(required=False)

124 changes: 124 additions & 0 deletions templates/console-base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{% load i18n %}
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap.min.css">
<link href="{{ STATIC_URL }}css/webvirtmgr.css" rel="stylesheet">

<style>
body {
margin: 0;
padding: 0;
background-color:#494949;
}

.navbar {
margin-bottom: 2px;
}

#main_container {
margin: 0;
padding: 0;
border-bottom-right-radius: 800px 600px;
background-color: #313131;
height: 100%;
}

#main_container canvas {
padding-left: 0;
padding-right: 0;
margin-left: auto;
margin-right: auto;
display: block;
}

#status {
z-index: 10000;
width: 80%;
position: absolute;
top: 5px;
left: 10%;
text-align: center;
}
</style>

{% block head %}{% endblock %}

</head>

<body>
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand">{{ instance.name }}</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Send key(s) <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li onclick='sendCtrlAltDel();'><a href='#'>Ctrl+Alt+Del</a></li>
<li class="divider"></li>
<li onclick='sendCtrlAltFN(0);'><a href='#'>Ctrl+Alt+F1</a></li>
<li onclick='sendCtrlAltFN(1);'><a href='#'>Ctrl+Alt+F2</a></li>
<li onclick='sendCtrlAltFN(2);'><a href='#'>Ctrl+Alt+F3</a></li>
<li onclick='sendCtrlAltFN(3);'><a href='#'>Ctrl+Alt+F4</a></li>
<li onclick='sendCtrlAltFN(4);'><a href='#'>Ctrl+Alt+F5</a></li>
<li onclick='sendCtrlAltFN(5);'><a href='#'>Ctrl+Alt+F6</a></li>
<li onclick='sendCtrlAltFN(6);'><a href='#'>Ctrl+Alt+F7</a></li>
<li onclick='sendCtrlAltFN(7);'><a href='#'>Ctrl+Alt+F8</a></li>
<li onclick='sendCtrlAltFN(8);'><a href='#'>Ctrl+Alt+F9</a></li>
<li onclick='sendCtrlAltFN(9);'><a href='#'>Ctrl+Alt+F10</a></li>
<li onclick='sendCtrlAltFN(10);'><a href='#'>Ctrl+Alt+F11</a></li>
<li onclick='sendCtrlAltFN(11);'><a href='#'>Ctrl+Alt+F12</a></li>
</ul>
</li>
<li onclick='fullscreen()'><a href='#'>{% trans "Fullscreen" %}</a></li>
{% block navbarmenu %}{% endblock %}
</ul>
</div>
</div>
</nav>
<div id='main_container' class="container">
{% block content %}{% endblock %}
</div>
<script src="{{ STATIC_URL }}js/jquery-1.10.2.js"></script>
<script src="{{ STATIC_URL }}js/bootstrap.min.js"></script>

<script>
function log_message(msg,type) {
var exist=$('#status').is('div');
status_div=$('<div id="status" class="alert alert-'+type+' role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>'+msg+'</div>');
if (exist) {
$('#status').remove();
$('body').prepend(status_div);
}
else {
status_div.hide();
$('body').prepend(status_div);
status_div.fadeIn(200);
}
if (type!='danger') {
status_div.delay(3000).fadeOut(200);
}
}

function log_error(msg) {
log_message(msg,'danger');
}

function log_info(msg) {
log_message(msg,'info');
}
</script>

{% block foot %}{% endblock %}
</body>
</html>
488 changes: 174 additions & 314 deletions templates/console-spice.html

Large diffs are not rendered by default.

156 changes: 77 additions & 79 deletions templates/console-vnc.html
Original file line number Diff line number Diff line change
@@ -1,48 +1,37 @@
{% extends "console-base.html" %}
{% load i18n %}
<html>
<head>
<link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico">
<link rel="stylesheet" href="{{ STATIC_URL }}js/novnc/base.css" title="plain">
<!--
<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
-->
<script src="{{ STATIC_URL }}js/novnc/util.js"></script>
</head>
<body style="margin: 0px;">
<div id="noVNC_screen">
<div id="noVNC_status_bar" class="noVNC_status_bar" style="margin-top: 0px;">
<table border=0 width="100%">
<tr>
<td>
<div id="noVNC_status">{% trans "Loading..." %}</div>
</td>
<td width="32%" style="text-align:right;">
<div id="noVNC_buttons">
<!-- dirty fix for keyboard on iOS devices -->
<input type="button" id="showKeyboard" value="Keyboard" title="Show Keyboard"/>
<!-- 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 -->
<!-- TODO: check if this is needed on iOS -->
<textarea id="keyboardinput" autocapitalize="off"
autocorrect="off" autocomplete="off" spellcheck="false"
mozactionhint="Enter" onsubmit="return false;"
style="ime-mode: disabled;">
</textarea>

<input type=button value="Ctrl+Alt+Del" id="sendCtrlAltDelButton">
<input type=button value="Fullscreen" id="askFullscreen">
</div>
</td>
</tr>
</table>
</div>
{% load staticfiles %}
{% block head %}
<script src="{% static "js/novnc/util.js" %}"></script>

{% endblock %}

{% block navbarmenu %}
<!-- dirty fix for keyboard on iOS devices -->
<li id="showKeyboard"><a href='#'>{% trans "Show Keyboad" %}</a></li>
{% endblock %}

{% block content %}
<div id='noVNC_area'>
<canvas id="noVNC_canvas" width="640px" height="20px">
{% trans "Canvas not supported." %}
</canvas>
</div>
</div>

<!-- 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 -->
<!-- TODO: check if this is needed on iOS -->
<textarea id="keyboardinput" autocapitalize="off"
autocorrect="off" autocomplete="off" spellcheck="false"
mozactionhint="Enter" onsubmit="return false;"
style="display: none;">
</textarea>

{% endblock %}

{% block foot %}
<script>
/*jslint white: false */
/*global window, $, Util, RFB, */
@@ -60,25 +49,52 @@
var rfb;

function passwordRequired(rfb) {
var msg;
msg = '<form onsubmit="return setPassword();"';
msg += 'role="form"';
msg += ' style="margin-bottom: 0px">';
msg += 'Password Required: ';
msg += '<input type=password size=10 id="password_input" class="noVNC_status">';
msg += '<\/form>';
$D('noVNC_status_bar').setAttribute("class", "noVNC_status_warn");
$D('noVNC_status').innerHTML = msg;
var modal;
modal = '<div class="modal fade">';
modal += ' <div class="modal-dialog">';
modal += ' <div class="modal-content">';
modal += ' <div class="modal-header">';
modal += ' <h4 class="modal-title">{% trans "Password required" %}</h4>';
modal += ' </div>';
modal += ' <div class="modal-body">';
modal += ' <form id="password_form" onsubmit="return setPassword();">';
modal += ' <div class="form-group">';
modal += ' <label for="password_input">Password</label>';
modal += ' <input type="password" class="form-control" id="password_input" placeholder="Password"/>';
modal += ' </div>';
modal += ' </form>';
modal += ' </div>';
modal += ' <div class="modal-footer">';
modal += ' <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="return setPassword();">{% trans "OK" %}</button>';
modal += ' </div>';
modal += ' </div>';
modal += ' </div>';
modal += '</div>';
$('body').append(modal);
$('div.modal').modal();
}
function setPassword() {
rfb.sendPassword($D('password_input').value);
rfb.sendPassword($('#password_input').val());
return false;
}
function sendCtrlAltDel() {
rfb.sendCtrlAltDel();
return false;
}

function sendCtrlAltFN(f) {
var keys_code=[0xFFBE,0xFFBF,0xFFC0,0xFFC1,0xFFC2,0xFFC3,0xFFC4,0xFFC5,0xFFC6,0xFFC7,0xFFC8,0xFFC9];
if (keys_code[f]==undefined) {
return;
}
rfb.sendKey(0xFFE3, 'down');
rfb.sendKey(0xFFE9, 'down');
rfb.sendKey(keys_code[f], 'down');
rfb.sendKey(keys_code[f], 'up');
rfb.sendKey(0xFFE9, 'up');
rfb.sendKey(0xFFE3, 'up');
};

// dirty fix for keyboard on iOS devices
function showKeyboard() {
var kbi, skb, l;
@@ -103,48 +119,36 @@

function updateState(rfb, state, oldstate, msg) {
var s, sb, cad, af, level;
s = $D('noVNC_status');
sb = $D('noVNC_status_bar');
cad = $D('sendCtrlAltDelButton');
af = $D('askFullscreen');
switch (state) {
case 'failed':
level = "error";
level = "danger";
break;
case 'fatal':
level = "error";
level = "danger";
break;
case 'normal':
level = "normal";
level = "info";
break;
case 'disconnected':
level = "normal";
level = "info";
break;
case 'loaded':
level = "normal";
level = "info";
break;
default:
level = "warn";
level = "warning";
break;
}

if (state === "normal") {
cad.disabled = false;
af.disabled = false;
}
else {
cad.disabled = true;
af.disabled = true;
}

if (typeof(msg) !== 'undefined') {
sb.setAttribute("class", "noVNC_status_" + level);
s.innerHTML = msg;
log_message(msg,level);
}
}

function fullscreen() {
var screen=document.getElementById('noVNC_canvas');
var screen=document.getElementById('main_container');
if(screen.requestFullscreen) {
screen.requestFullscreen();
} else if(screen.mozRequestFullScreen) {
@@ -159,11 +163,6 @@
window.onscriptsload = function () {
var host, port, password, path, token;

$D('sendCtrlAltDelButton').style.display = "inline";
$D('sendCtrlAltDelButton').onclick = sendCtrlAltDel;
$D('askFullscreen').style.display = "inline";
$D('askFullscreen').onclick = fullscreen;

// dirty fix for keyboard on iOS devices
if (isTouchDevice) {
$D('showKeyboard').onclick = showKeyboard;
@@ -188,7 +187,7 @@
return;
}

rfb = new RFB({'target': $D('noVNC_canvas'),
rfb = new RFB({'target': document.getElementById('noVNC_canvas'),
'encrypt': WebUtil.getQueryVar('encrypt',
(window.location.protocol === "https:")),
'repeaterID': WebUtil.getQueryVar('repeaterID', ''),
@@ -201,5 +200,4 @@
rfb.connect(host, port, password, path);
};
</script>
</body>
</html>
{% endblock %}
22 changes: 22 additions & 0 deletions templates/create.html
Original file line number Diff line number Diff line change
@@ -264,6 +264,17 @@ <h4 class="modal-title">{% trans "Create Custom Instance" %}</h4>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "HDD cache mode" %}</label>

<div class="col-sm-6">
<select id="cache_mode" name="cache_mode" class="form-control">
{% for mode, name in cache_modes %}
<option value="{{ mode }}">{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Network" %}</label>

@@ -416,6 +427,17 @@ <h4 class="modal-title">{% trans "Create Instance From Template Image" %}</h4>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "HDD cache mode" %}</label>

<div class="col-sm-6">
<select id="cache_mode" name="cache_mode" class="form-control">
{% for mode, name in cache_modes %}
<option value="{{ mode }}">{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group meta-prealloc">
<label class="col-sm-3 control-label">{% trans "Metadata" %}</label>

2 changes: 2 additions & 0 deletions templates/storage.html
Original file line number Diff line number Diff line change
@@ -196,6 +196,7 @@ <h4 class="modal-title">{% trans "Clone image" %} <span
<option value="raw">{% trans "raw" %}</option>
<option value="qcow">{% trans "qcow" %}</option>
<option value="qcow2">{% trans "qcow2" %}</option>
<option value="qed">{% trans "qed" %}</option>
</select>
</div>
</div>
@@ -274,6 +275,7 @@ <h4 class="modal-title">{% trans "Add New Image" %}</h4>
<select name="format" class="form-control image-format">
<option value="qcow2">{% trans "qcow2" %}</option>
<option value="qcow">{% trans "qcow" %}</option>
<option value="qed">{% trans "qed" %}</option>
<option value="raw">{% trans "raw" %}</option>
</select>
</div>
49 changes: 38 additions & 11 deletions vrtManager/create.py
Original file line number Diff line number Diff line change
@@ -11,9 +11,17 @@
def get_rbd_storage_data(stg):
xml = stg.XMLDesc(0)
ceph_user = util.get_xml_path(xml, "/pool/source/auth/@username")
ceph_host = util.get_xml_path(xml, "/pool/source/host/@name")
secrt_uuid = util.get_xml_path(xml, "/pool/source/auth/secret/@uuid")
return ceph_user, secrt_uuid, ceph_host

def get_ceph_hosts(ctx):
hosts = []
for host in ctx.xpathEval("/pool/source/host"):
name = host.prop("name")
if name:
hosts.append({'name': name, 'port': host.prop("port")})
return hosts
ceph_hosts = util.get_xml_path(xml, func=get_ceph_hosts)
secret_uuid = util.get_xml_path(xml, "/pool/source/auth/secret/@uuid")
return ceph_user, secret_uuid, ceph_hosts


class wvmCreate(wvmConnect):
@@ -44,6 +52,17 @@ def get_host_arch(self):
"""Get guest capabilities"""
return util.get_xml_path(self.get_cap_xml(), "/capabilities/host/cpu/arch")

def get_cache_modes(self):
"""Get cache available modes"""
return {
'default': 'Default',
'none': 'Disabled',
'writethrough': 'Write through',
'writeback': 'Write back',
'directsync': 'Direct sync', # since libvirt 0.9.5
'unsafe': 'Unsafe', # since libvirt 0.9.7
}

def create_volume(self, storage, name, size, format='qcow2', metadata=False):
size = int(size) * 1073741824
stg = self.get_storage(storage)
@@ -125,7 +144,7 @@ def delete_volume(self, path):
vol = self.get_volume_by_path(path)
vol.delete()

def create_instance(self, name, memory, vcpu, host_model, uuid, images, networks, virtio, mac=None):
def create_instance(self, name, memory, vcpu, host_model, uuid, images, cache_mode, networks, virtio, mac=None):
"""
Create VM function
"""
@@ -166,19 +185,27 @@ def create_instance(self, name, memory, vcpu, host_model, uuid, images, networks
stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type")

if stg_type == 'rbd':
ceph_user, secrt_uuid, ceph_host = get_rbd_storage_data(stg)
ceph_user, secret_uuid, ceph_hosts = get_rbd_storage_data(stg)
xml += """<disk type='network' device='disk'>
<driver name='qemu' type='%s'/>
<driver name='qemu' type='%s' cache='%s'/>
<auth username='%s'>
<secret type='ceph' uuid='%s'/>
</auth>
<source protocol='rbd' name='%s'>
<host name='%s' port='6789'/>
</source>""" % (img_type, ceph_user, secrt_uuid, image, ceph_host)
<source protocol='rbd' name='%s'>""" % (img_type, cache_mode, ceph_user, secret_uuid, image)
if isinstance(ceph_hosts, list):
for host in ceph_hosts:
if host.get('port'):
xml += """
<host name='%s' port='%s'/>""" % (host.get('name'), host.get('port'))
else:
xml += """
<host name='%s'/>""" % host.get('name')
xml += """
</source>"""
else:
xml += """<disk type='file' device='disk'>
<driver name='qemu' type='%s'/>
<source file='%s'/>""" % (img_type, image)
<driver name='qemu' type='%s' cache='%s'/>
<source file='%s'/>""" % (img_type, cache_mode, image)

if virtio:
xml += """<target dev='vd%s' bus='virtio'/>""" % (disk_letters.pop(0),)
2 changes: 1 addition & 1 deletion vrtManager/instance.py
Original file line number Diff line number Diff line change
@@ -532,7 +532,7 @@ def get_iso_media(self):
except:
pass
for img in stg.listVolumes():
if img.endswith('.iso'):
if img.lower().endswith('.iso'):
iso.append(img)
return iso

5 changes: 2 additions & 3 deletions vrtManager/util.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#
# Copyright (C) 2013 Webvirtmgr.
#
import re
import random
import libxml2
import libvirt


def is_kvm_available(xml):
capabilites = re.search('kvm', xml)
if capabilites:
kvm_domains = get_xml_path(xml, "//domain/@type='kvm'")
if kvm_domains > 0:
return True
else:
return False
1 change: 1 addition & 0 deletions webvirtmgr/settings.py
Original file line number Diff line number Diff line change
@@ -148,6 +148,7 @@
WS_HOST = '0.0.0.0'
WS_PUBLIC_HOST = None
WS_CERT = None
WS_KEY = None

# keepalive interval and count for libvirt connections
#