mirror of
https://github.com/retspen/webvirtcloud
synced 2024-11-01 03:54:15 +00:00
commit
3f98aa2370
9 changed files with 80 additions and 7 deletions
|
@ -32,7 +32,7 @@ print(''.join([random.SystemRandom().choice(haystack) for _ in range(50)]))
|
|||
### Install WebVirtCloud panel (Ubuntu)
|
||||
|
||||
```bash
|
||||
sudo apt-get -y install git python-virtualenv python-dev python-lxml libvirt-dev zlib1g-dev nginx supervisor libsasl2-modules gcc pkg-config python-guestfs
|
||||
sudo apt-get -y install git python-virtualenv python-dev python-lxml libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python-guestfs
|
||||
git clone https://github.com/retspen/webvirtcloud
|
||||
cd webvirtcloud
|
||||
cp webvirtcloud/settings.py.template webvirtcloud/settings.py
|
||||
|
|
|
@ -56,6 +56,9 @@ def profile(request):
|
|||
if keypublic == key.keypublic:
|
||||
msg = _("Public key already exist")
|
||||
error_messages.append(msg)
|
||||
if '\n' in keypublic or '\r' in keypublic:
|
||||
msg = _("Invalid characters in public key")
|
||||
error_messages.append(msg)
|
||||
if not error_messages:
|
||||
addkeypublic = UserSSHKey(user_id=request.user.id, keyname=keyname, keypublic=keypublic)
|
||||
addkeypublic.save()
|
||||
|
|
|
@ -2,4 +2,6 @@ Django==1.11.14
|
|||
websockify==0.8.0
|
||||
gunicorn==19.9.0
|
||||
lxml==4.2.3
|
||||
libvirt-python==4.4.0
|
||||
libvirt-python==4.4.0
|
||||
pytz
|
||||
|
||||
|
|
|
@ -8,4 +8,6 @@ urlpatterns = [
|
|||
views.os_metadata_json, name='ds_openstack_metadata'),
|
||||
url(r'^openstack/(?P<version>[\w\-\.]+)/user_data$',
|
||||
views.os_userdata, name='ds_openstack_userdata'),
|
||||
url(r'^vdi/(?P<vname>[\w\-\.]+)/$',
|
||||
views.get_vdi_url, name='vdi_url'),
|
||||
]
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from django.shortcuts import render
|
||||
from django.http import HttpResponse, Http404
|
||||
from accounts.models import UserInstance, UserSSHKey
|
||||
from instances.models import Instance
|
||||
from vrtManager.instance import wvmInstance
|
||||
from libvirt import libvirtError
|
||||
import json
|
||||
import socket
|
||||
|
||||
|
@ -62,3 +65,24 @@ def get_client_ip(request):
|
|||
def get_hostname_by_ip(ip):
|
||||
addrs = socket.gethostbyaddr(ip)
|
||||
return addrs[0]
|
||||
|
||||
def get_vdi_url(request, vname):
|
||||
instance = Instance.objects.get(name=vname)
|
||||
compute = instance.compute
|
||||
data = {}
|
||||
try:
|
||||
conn = wvmInstance(compute.hostname,
|
||||
compute.login,
|
||||
compute.password,
|
||||
compute.type,
|
||||
instance.name)
|
||||
|
||||
fqdn = get_hostname_by_ip(compute.hostname)
|
||||
url = "{}://{}:{}".format(conn.get_console_type(), fqdn, conn.get_console_port())
|
||||
response = url
|
||||
return HttpResponse(response)
|
||||
|
||||
except libvirtError as lib_err:
|
||||
err = "Error getting vdi url for {}".format(vname)
|
||||
raise Http404(err)
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
{% endfor %}
|
||||
<a href="{% url 'instance' compute.id vname %}" type="button" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"></span></a>
|
||||
<em>on</em>
|
||||
<a href="{% url 'overview' compute.id %}"><span class="label label-primary">{{ compute.name}} - {{ compute.hostname }} </span></a>
|
||||
<a href="{% url 'overview' compute.id %}"><span class="label label-primary">{{ compute.name }}{% if compute.name != compute.hostname %} - {{ compute.hostname }}{% endif %} </span></a>
|
||||
</div>
|
||||
</div>
|
||||
{% if user_quota_msg %}
|
||||
|
@ -243,6 +243,13 @@
|
|||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% ifequal status 1 %}
|
||||
<li role="presentation">
|
||||
<a href="#vdiconsole" aria-controls="vdiconsole" role="tab" data-toggle="tab">
|
||||
{% trans "VDI" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endifequal %}
|
||||
</ul>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
|
@ -311,6 +318,13 @@
|
|||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% ifequal status 1 %}
|
||||
<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>
|
||||
<a href="#" class="btn btn-lg btn-success pull-right" id="vdi_url" >{% trans "VDI" %}</a>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% endifequal %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -860,6 +874,10 @@
|
|||
<button type="button" class="btn btn-sm btn-success pull-left" name="guess-clone-name"
|
||||
onclick="guess_clone_name()" style="margin-top: 2px;">{% trans "Guess" %}</button>
|
||||
</div>
|
||||
{% elif clone_instance_auto_name %}
|
||||
<div class="col-sm-4">
|
||||
<input id="clone_instance_auto_name" type="text" class="form-control" name="auto_name" value="Automatic" disabled/>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-sm-4">
|
||||
<select id="select_clone_name" class="form-control" name="name" size="1"/>
|
||||
|
@ -1027,7 +1045,7 @@
|
|||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">{% trans "Is template" %}</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="checkbox" name="is_template" value="true" id="is_template" {% if instance.is_template %}checked{% endif %} {% if not request.user.is_superuser %}disabled{% endif %}>
|
||||
<input type="checkbox" name="is_template" value="True" id="is_template" {% if instance.is_template %}checked{% endif %} {% if not request.user.is_superuser %}disabled{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
{% ifequal status 5 %}
|
||||
|
@ -1210,7 +1228,7 @@
|
|||
}
|
||||
</script>
|
||||
<script>
|
||||
function random_mac(net) {
|
||||
function random_mac(net) {
|
||||
$.getJSON('/instance/random_mac_address/', function(data) {
|
||||
$('input[name="clone-net-mac-'+net+'"]').val(data['mac']);
|
||||
});
|
||||
|
@ -1313,6 +1331,12 @@
|
|||
$("#console_select_listen_address option[value='" + console_listen_address + "']").prop('selected', true);
|
||||
}
|
||||
});
|
||||
$(document).ready(function () {
|
||||
// set vdi url
|
||||
$.get("/datasource/vdi/{{ vname }}/", function(data) {
|
||||
$("#vdi_url").attr("href", data);
|
||||
});
|
||||
});
|
||||
{% if request.user.is_superuser %}
|
||||
$(document).ready(function () {
|
||||
random_mac(0);
|
||||
|
|
|
@ -357,6 +357,7 @@ def instance(request, compute_id, vname):
|
|||
console_type = conn.get_console_type()
|
||||
console_port = conn.get_console_port()
|
||||
console_keymap = conn.get_console_keymap()
|
||||
console_listen_address = conn.get_console_listen_addr()
|
||||
snapshots = sorted(conn.get_snapshot(), reverse=True, key=lambda k:k['date'])
|
||||
inst_xml = conn._XMLDesc(VIR_DOMAIN_XML_SECURE)
|
||||
has_managed_save_image = conn.get_managed_save_image()
|
||||
|
@ -375,6 +376,7 @@ def instance(request, compute_id, vname):
|
|||
default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS
|
||||
show_access_root_password = settings.SHOW_ACCESS_ROOT_PASSWORD
|
||||
show_access_ssh_keys = settings.SHOW_ACCESS_SSH_KEYS
|
||||
clone_instance_auto_name = settings.CLONE_INSTANCE_AUTO_NAME
|
||||
|
||||
try:
|
||||
instance = Instance.objects.get(compute_id=compute_id, name=vname)
|
||||
|
@ -733,6 +735,21 @@ def instance(request, compute_id, vname):
|
|||
for post in request.POST:
|
||||
clone_data[post] = request.POST.get(post, '').strip()
|
||||
|
||||
if clone_instance_auto_name and not clone_data['name']:
|
||||
auto_vname = clone_free_names[0]
|
||||
clone_data['name'] = auto_vname
|
||||
clone_data['clone-net-mac-0'] = _get_dhcp_mac_address(auto_vname)
|
||||
for post in clone_data.keys():
|
||||
if post.startswith('disk-'):
|
||||
disk_name = clone_data[post]
|
||||
if "-" in disk_name:
|
||||
suffix = disk_name.split("-")[-1]
|
||||
disk_name = '-'.join((auto_vname, suffix))
|
||||
else:
|
||||
suffix = disk_name.split(".")[-1]
|
||||
disk_name = '.'.join((auto_vname, suffix))
|
||||
clone_data[post] = disk_name
|
||||
|
||||
if not request.user.is_superuser and quota_msg:
|
||||
msg = _("User %s quota reached, cannot create '%s'!" % (quota_msg, clone_data['name']))
|
||||
error_messages.append(msg)
|
||||
|
|
|
@ -275,9 +275,9 @@ class wvmInstance(wvmConnect):
|
|||
device = media.xpath('@device')[0]
|
||||
if device == 'cdrom':
|
||||
try:
|
||||
dev = media.xpath('target/@dev')
|
||||
dev = media.xpath('target/@dev')[0]
|
||||
try:
|
||||
src_fl = media.xpath('source/@file')
|
||||
src_fl = media.xpath('source/@file')[0]
|
||||
vol = self.get_volume_by_path(src_fl)
|
||||
volume = vol.name()
|
||||
stg = vol.storagePoolLookupByVolume()
|
||||
|
|
|
@ -133,6 +133,7 @@ LIBVIRT_KEEPALIVE_COUNT = 5
|
|||
ALLOW_INSTANCE_MULTIPLE_OWNER = True
|
||||
NEW_USER_DEFAULT_INSTANCES = []
|
||||
CLONE_INSTANCE_DEFAULT_PREFIX = 'instance'
|
||||
CLONE_INSTANCE_AUTO_NAME = False
|
||||
LOGS_PER_PAGE = 100
|
||||
QUOTA_DEBUG = True
|
||||
ALLOW_EMPTY_PASSWORD = True
|
||||
|
|
Loading…
Reference in a new issue