1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-25 15:45:23 +00:00

Merge remote-tracking branch 'retspen/master' into upgrade_django

This commit is contained in:
Ing. Jan KRCMAR 2018-07-26 12:44:22 +02:00
commit b909b9d0f1
28 changed files with 378 additions and 156 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@ console/cert.pem*
tags tags
dhcpd.* dhcpd.*
webvirtcloud/settings.py webvirtcloud/settings.py
*migrations/*

View file

@ -2,9 +2,9 @@ language: python
python: python:
- "2.7" - "2.7"
env: env:
- DJANGO=1.8 - DJANGO=1.11.14
install: install:
- pip install -r dev/requirements.txt --use-mirrors - 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 computes \
console create instances interfaces \ console create instances interfaces \

View file

@ -6,7 +6,7 @@ RUN echo 'APT::Get::Clean=always;' >> /etc/apt/apt.conf.d/99AutomaticClean
RUN apt-get update -qqy RUN apt-get update -qqy
RUN DEBIAN_FRONTEND=noninteractive apt-get -qyy install \ RUN DEBIAN_FRONTEND=noninteractive apt-get -qyy install \
-o APT::Install-Suggests=false \ -o APT::Install-Suggests=false \
git python-virtualenv python-dev libxml2-dev libvirt-dev zlib1g-dev nginx libsasl2-modules git python-virtualenv python-dev python-lxml libvirt-dev zlib1g-dev nginx libsasl2-modules
ADD . /srv/webvirtcloud ADD . /srv/webvirtcloud
RUN chown -R www-data:www-data /srv/webvirtcloud RUN chown -R www-data:www-data /srv/webvirtcloud

View file

@ -32,7 +32,7 @@ print(''.join([random.SystemRandom().choice(haystack) for _ in range(50)]))
### Install WebVirtCloud panel (Ubuntu) ### Install WebVirtCloud panel (Ubuntu)
```bash ```bash
sudo apt-get -y install git python-virtualenv python-dev libxml2-dev libvirt-dev zlib1g-dev nginx supervisor libsasl2-modules gcc pkg-config 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
git clone https://github.com/retspen/webvirtcloud git clone https://github.com/retspen/webvirtcloud
cd webvirtcloud cd webvirtcloud
cp webvirtcloud/settings.py.template webvirtcloud/settings.py cp webvirtcloud/settings.py.template webvirtcloud/settings.py
@ -67,7 +67,7 @@ wget -O - https://clck.ru/9V9fH | sudo sh
### Install WebVirtCloud panel (CentOS) ### Install WebVirtCloud panel (CentOS)
```bash ```bash
sudo yum -y install python-virtualenv python-devel libvirt-devel glibc gcc nginx supervisor libxml2 libxml2-devel git sudo yum -y install python-virtualenv python-devel libvirt-devel glibc gcc nginx supervisor python-lxml git python-libguestfs
``` ```
#### Creating directories and cloning repo #### Creating directories and cloning repo
@ -230,7 +230,10 @@ datasource:
### How To Update ### How To Update
```bash ```bash
sudo virtualenv venv
sudo source venv/bin/activate
git pull git pull
pip install -U -r conf/requirements.txt
python manage.py migrate python manage.py migrate
sudo service supervisor restart sudo service supervisor restart
``` ```

2
Vagrantfile vendored
View file

@ -10,7 +10,7 @@ Vagrant.configure(2) do |config|
sudo sed -i 's/auth_tcp = \"sasl\"/auth_tcp = \"none\"/g' /etc/libvirt/libvirtd.conf sudo sed -i 's/auth_tcp = \"sasl\"/auth_tcp = \"none\"/g' /etc/libvirt/libvirtd.conf
sudo service libvirt-bin restart sudo service libvirt-bin restart
sudo adduser vagrant libvirtd sudo adduser vagrant libvirtd
sudo apt-get -y install python-virtualenv python-dev libxml2-dev libvirt-dev zlib1g-dev sudo apt-get -y install python-virtualenv python-dev python-lxml libvirt-dev zlib1g-dev
virtualenv /vagrant/venv virtualenv /vagrant/venv
source /vagrant/venv/bin/activate source /vagrant/venv/bin/activate
pip install -r /vagrant/dev/requirements.txt pip install -r /vagrant/dev/requirements.txt

View file

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.13 on 2018-06-25 12:36
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0009_auto_20171026_0805'),
]
operations = [
migrations.AlterField(
model_name='userattributes',
name='max_cpus',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value'),
),
migrations.AlterField(
model_name='userattributes',
name='max_disk_size',
field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value'),
),
migrations.AlterField(
model_name='userattributes',
name='max_instances',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value'),
),
migrations.AlterField(
model_name='userattributes',
name='max_memory',
field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value'),
),
]

View file

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.13 on 2018-06-25 13:13
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0010_auto_20180625_1236'),
]
operations = [
migrations.AlterField(
model_name='userattributes',
name='max_cpus',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]),
),
migrations.AlterField(
model_name='userattributes',
name='max_disk_size',
field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]),
),
migrations.AlterField(
model_name='userattributes',
name='max_instances',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]),
),
migrations.AlterField(
model_name='userattributes',
name='max_memory',
field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]),
),
]

View file

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.13 on 2018-06-25 13:31
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
import re
class Migration(migrations.Migration):
dependencies = [
('accounts', '0011_auto_20180625_1313'),
]
operations = [
migrations.AlterField(
model_name='userattributes',
name='max_cpus',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]),
),
migrations.AlterField(
model_name='userattributes',
name='max_disk_size',
field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]),
),
migrations.AlterField(
model_name='userattributes',
name='max_instances',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]),
),
migrations.AlterField(
model_name='userattributes',
name='max_memory',
field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]),
),
]

View file

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.13 on 2018-06-25 13:58
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
import re
class Migration(migrations.Migration):
dependencies = [
('accounts', '0012_auto_20180625_1331'),
]
operations = [
migrations.AlterField(
model_name='userattributes',
name='max_cpus',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]),
),
migrations.AlterField(
model_name='userattributes',
name='max_disk_size',
field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]),
),
migrations.AlterField(
model_name='userattributes',
name='max_instances',
field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]),
),
migrations.AlterField(
model_name='userattributes',
name='max_memory',
field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]),
),
]

View file

@ -2,6 +2,7 @@ from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from instances.models import Instance from instances.models import Instance
from django.core.validators import integer_validator, MinValueValidator
class UserInstance(models.Model): class UserInstance(models.Model):
@ -26,10 +27,10 @@ class UserSSHKey(models.Model):
class UserAttributes(models.Model): class UserAttributes(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE) user = models.OneToOneField(User, on_delete=models.CASCADE)
can_clone_instances = models.BooleanField(default=True) can_clone_instances = models.BooleanField(default=True)
max_instances = models.IntegerField(default=1) max_instances = models.IntegerField(default=1, help_text="-1 for unlimited. Any integer value", validators=[integer_validator,MinValueValidator(-1),])
max_cpus = models.IntegerField(default=1) max_cpus = models.IntegerField(default=1, help_text="-1 for unlimited. Any integer value", validators=[integer_validator,MinValueValidator(-1)])
max_memory = models.IntegerField(default=2048) max_memory = models.IntegerField(default=2048, help_text="-1 for unlimited. Any integer value", validators=[integer_validator,MinValueValidator(-1)])
max_disk_size = models.IntegerField(default=20) max_disk_size = models.IntegerField(default=20, help_text="-1 for unlimited. Any integer value", validators=[integer_validator,MinValueValidator(-1)])
@staticmethod @staticmethod
def create_missing_userattributes(user): def create_missing_userattributes(user):

View file

@ -92,25 +92,25 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Max instances" %}</label> <label class="col-sm-4 control-label">{% trans "Max instances" %}</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input type="text" name="userattributes_max_instances" class="form-control" value="{{ user.userattributes.max_instances }}"> <input type="text" name="userattributes_max_instances" class="form-control" value="{{ user.userattributes.max_instances}}" required="True" >
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Max cpus" %}</label> <label class="col-sm-4 control-label">{% trans "Max cpus" %}</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input type="text" name="userattributes_max_cpus" class="form-control" value="{{ user.userattributes.max_cpus }}"> <input type="text" name="userattributes_max_cpus" class="form-control" value="{{ user.userattributes.max_cpus }}" required="True">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Max memory (MB)" %}</label> <label class="col-sm-4 control-label">{% trans "Max memory (MB)" %}</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input type="text" name="userattributes_max_memory" class="form-control" value="{{ user.userattributes.max_memory }}"> <input type="text" name="userattributes_max_memory" class="form-control" value="{{ user.userattributes.max_memory}}" required="True">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">{% trans "Max disk size (GB)" %}</label> <label class="col-sm-4 control-label">{% trans "Max disk size (GB)" %}</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input type="text" name="userattributes_max_disk_size" class="form-control" value="{{ user.userattributes.max_disk_size }}"> <input type="text" name="userattributes_max_disk_size" class="form-control" value="{{ user.userattributes.max_disk_size }}" required="True">
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,12 +1,10 @@
from django.conf.urls import url from django.conf.urls import url
from django.contrib.auth import views as auth_views
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^login/$', 'django.contrib.auth.views.login', url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
{'template_name': 'login.html'}, name='login'), url(r'^logout/$', auth_views.LogoutView.as_view(template_name='logout.html'), name='logout'),
url(r'^logout/$', 'django.contrib.auth.views.logout', url(r'^profile/$', views.profile, name='profile'), url(r'^$', views.accounts, name='accounts'),
{'template_name': 'logout.html'}, name='logout'),
url(r'^profile/$', views.profile, name='profile'),
url(r'^$', views.accounts, name='accounts'),
url(r'^profile/(?P<user_id>[0-9]+)/$', views.account, name='account'), url(r'^profile/(?P<user_id>[0-9]+)/$', views.account, name='account'),
] ]

View file

@ -8,6 +8,8 @@ from accounts.models import *
from instances.models import Instance from instances.models import Instance
from accounts.forms import UserAddForm from accounts.forms import UserAddForm
from django.conf import settings from django.conf import settings
from django.core.validators import ValidationError
@login_required @login_required
@ -95,22 +97,31 @@ def accounts(request):
UserAttributes.configure_user(new_user) UserAttributes.configure_user(new_user)
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
if 'edit' in request.POST: if 'edit' in request.POST:
CHECKBOX_MAPPING = {'on': True, 'off': False, }
user_id = request.POST.get('user_id', '') user_id = request.POST.get('user_id', '')
user_pass = request.POST.get('user_pass', '') user_pass = request.POST.get('user_pass', '')
user_edit = User.objects.get(id=user_id) user_edit = User.objects.get(id=user_id)
user_edit.set_password(user_pass)
user_edit.is_staff = request.POST.get('user_is_staff', False) if user_pass != '': user_edit.set_password(user_pass)
user_edit.is_superuser = request.POST.get('user_is_superuser', False) user_edit.is_staff = CHECKBOX_MAPPING.get(request.POST.get('user_is_staff', 'off'))
user_edit.is_superuser = CHECKBOX_MAPPING.get(request.POST.get('user_is_superuser', 'off'))
user_edit.save() user_edit.save()
userattributes = user_edit.userattributes UserAttributes.create_missing_userattributes(user_edit)
userattributes.can_clone_instances = request.POST.get('userattributes_can_clone_instances', False) user_edit.userattributes.can_clone_instances = CHECKBOX_MAPPING.get(request.POST.get('userattributes_can_clone_instances', 'off'))
userattributes.max_instances = request.POST.get('userattributes_max_instances', 0) user_edit.userattributes.max_instances = request.POST.get('userattributes_max_instances', 0)
userattributes.max_cpus = request.POST.get('userattributes_max_cpus', 0) user_edit.userattributes.max_cpus = request.POST.get('userattributes_max_cpus', 0)
userattributes.max_memory = request.POST.get('userattributes_max_memory', 0) user_edit.userattributes.max_memory = request.POST.get('userattributes_max_memory', 0)
userattributes.max_disk_size = request.POST.get('userattributes_max_disk_size', 0) user_edit.userattributes.max_disk_size = request.POST.get('userattributes_max_disk_size', 0)
userattributes.save()
return HttpResponseRedirect(request.get_full_path()) try:
user_edit.userattributes.clean_fields()
except ValidationError as exc:
error_messages.append(exc)
else:
user_edit.userattributes.save()
return HttpResponseRedirect(request.get_full_path())
if 'block' in request.POST: if 'block' in request.POST:
user_id = request.POST.get('user_id', '') user_id = request.POST.get('user_id', '')
user_block = User.objects.get(id=user_id) user_block = User.objects.get(id=user_id)

View file

@ -123,7 +123,7 @@ def computes(request):
compute_edit.hostname = data['hostname'] compute_edit.hostname = data['hostname']
compute_edit.login = data['login'] compute_edit.login = data['login']
compute_edit.password = data['password'] compute_edit.password = data['password']
compute.edit_details = data['details'] #compute_edit.details = data['details']
compute_edit.save() compute_edit.save()
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
else: else:

View file

@ -1,5 +1,5 @@
Django==1.8.11 Django==1.11.14
websockify==0.8.0 websockify==0.8.0
gunicorn==19.3.0 gunicorn==19.9.0
libvirt-python==3.10 lxml==4.2.3
libxml2-python3==2.9.5 libvirt-python==4.4.0

View file

@ -1,4 +1,4 @@
-r ../conf/requirements.txt -r ../conf/requirements.txt
pep8==1.6.2 pep8==1.7.1
pyflakes==0.8.1 pyflakes==2.0.0
pylint==1.4.3 pylint==1.9.2

View file

@ -32,27 +32,47 @@
<div class="col-lg-12"> <div class="col-lg-12">
<div class="alert alert-warning alert-dismissable"> <div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instace" %} <i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instance" %}
</div> </div>
</div> </div>
{% else %} {% else %}
<table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable> <table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable>
<thead> <thead >
<tr> <tr>
<th>#</th>
<th>Name<br>Description</th> <th>Name<br>Description</th>
<th>Host<br>User</th> <th>User</th>
<th>Status</th> <th>Status</th>
<th>VCPU</th> <th>VCPU</th>
<th>Memory<br>({% trans "MB" %})</th> <th>Memory</th>
<th data-sortable="false" style="width:205px;">Actions</th> <th data-sortable="false" style="width:205px;">Actions & Mem Usage</th>
</tr> </tr>
</thead> </thead>
<tbody class="searchable"> <tbody class="searchable">
{% for host, inst in all_host_vms.items %} {% for host, inst in all_host_vms.items %}
<tr class="success" style="font-size:16px">
<td>{{ forloop.counter }}</td>
<td><a href="{% url 'overview' host.0 %}">{{ host.1 }}</a></td>
<td></td>
<td>{% ifequal host.2 1 %}<span class="label label-success">{% trans "Active" %}
</span>{% endifequal %}
{% ifequal host.2 2 %}<span class="label label-danger">{% trans "Not Active" %}
</span>{% endifequal %}
{% ifequal host.2 3 %}<span class="label label-danger">{% trans "Connection Failed" %}
</span>{% endifequal %}
</td>
<td style="text-align:center;">{{ host.3 }}</td>
<td style="text-align:right;">{{ host.4|filesizeformat }}</td>
<td style="text-align:left;">
<div class="progress-bar-success" role="progressbar" style="width: {{ host.5 }}%" aria-valuenow="{{ host.5 }}" aria-valuemin="0" aria-valuemax="100">{{ host.5 }}%</div>
</td>
</tr>
{% for vm, info in inst.items %} {% for vm, info in inst.items %}
<tr> <tr>
<td><a href="{% url 'instance' host.0 vm %}">{{ vm }}</a><br><small><em>{{ info.title }}</em></small></td> <td></td>
<td><a href="{% url 'overview' host.0 %}">{{ host.1 }}</a><br><small><em>{% if info.userinstances.count > 0 %}{{ info.userinstances.first_user.user.username }}{% if info.userinstances.count > 1 %} (+{{ info.userinstances.count|add:"-1" }}){% endif %}{% endif %}</em></small></td> <td>{{ forloop.counter }} &emsp; <a href="{% url 'instance' host.0 vm %}">{{ vm }}</a><br><small><em>{{ info.title }}</em></small></td>
<td><small><em>{% if info.userinstances.count > 0 %}{{ info.userinstances.first_user.user.username }}{% if info.userinstances.count > 1 %} (+{{ info.userinstances.count|add:"-1" }}){% endif %}{% endif %}</em></small></td>
<td>{% ifequal info.status 1 %} <td>{% ifequal info.status 1 %}
<span class="text-success">{% trans "Active" %}</span> <span class="text-success">{% trans "Active" %}</span>
{% endifequal %} {% endifequal %}
@ -63,8 +83,8 @@
<span class="text-warning">{% trans "Suspend" %}</span> <span class="text-warning">{% trans "Suspend" %}</span>
{% endifequal %} {% endifequal %}
</td> </td>
<td>{{ info.vcpu }}</td> <td style="text-align:center;">{{ info.vcpu }}</td>
<td>{{ info.memory }}</td> <td style="text-align:right;">{{ info.memory |filesizeformat }}</td>
<td><form action="" method="post" role="form">{% csrf_token %} <td><form action="" method="post" role="form">{% csrf_token %}
<input type="hidden" name="name" value="{{ vm }}"/> <input type="hidden" name="name" value="{{ vm }}"/>
<input type="hidden" name="compute_id" value="{{ host.0 }}"/> <input type="hidden" name="compute_id" value="{{ host.0 }}"/>
@ -138,7 +158,7 @@
<div class="col-lg-12"> <div class="col-lg-12">
<div class="alert alert-warning alert-dismissable"> <div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instace" %} <i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instance" %}
</div> </div>
</div> </div>
{% else %} {% else %}

View file

@ -68,13 +68,24 @@ def instances(request):
i.delete() i.delete()
try: try:
check_uuid = Instance.objects.get(compute_id=comp.id, name=vm) check_uuid = Instance.objects.get(compute_id=comp["id"], name=vm)
if check_uuid.uuid != info['uuid']: if check_uuid.uuid != info['uuid']:
check_uuid.save() check_uuid.save()
all_host_vms[comp.id, comp.name][vm]['is_template'] = check_uuid.is_template
all_host_vms[comp.id, comp.name][vm]['userinstances'] = get_userinstances_info(check_uuid) all_host_vms[comp_info["id"],
comp_info["name"],
comp_info["status"],
comp_info["cpu"],
comp_info["mem_size"],
comp_info["mem_perc"]][vm]['is_template'] = check_uuid.is_template
all_host_vms[comp_info["id"],
comp_info["name"],
comp_info["status"],
comp_info["cpu"],
comp_info["mem_size"],
comp_info["mem_perc"]][vm]['userinstances'] = get_userinstances_info(check_uuid)
except Instance.DoesNotExist: except Instance.DoesNotExist:
check_uuid = Instance(compute_id=comp.id, name=vm, uuid=info['uuid']) check_uuid = Instance(compute_id=comp["id"], name=vm, uuid=info['uuid'])
check_uuid.save() check_uuid.save()
if not request.user.is_superuser: if not request.user.is_superuser:
@ -90,14 +101,27 @@ def instances(request):
all_user_vms[usr_inst].update({'compute_id': usr_inst.instance.compute.id}) all_user_vms[usr_inst].update({'compute_id': usr_inst.instance.compute.id})
else: else:
for comp in computes: for comp in computes:
if connection_manager.host_is_up(comp.type, comp.hostname): status = connection_manager.host_is_up(comp.type, comp.hostname)
if status:
try: try:
conn = wvmHostDetails(comp, comp.login, comp.password, comp.type) conn = wvmHostDetails(comp, comp.login, comp.password, comp.type)
host_instances = conn.get_host_instances() comp_node_info = conn.get_node_info()
if host_instances: comp_mem = conn.get_memory_usage()
all_host_vms[comp.id, comp.name] = host_instances comp_instances = conn.get_host_instances(True)
for vm, info in host_instances.items():
refresh_instance_database(comp, vm, info) if comp_instances:
comp_info= {
"id": comp.id,
"name": comp.name,
"status": status,
"cpu": comp_node_info[3],
"mem_size": comp_node_info[2],
"mem_perc": comp_mem['percent']
}
all_host_vms[comp_info["id"], comp_info["name"], comp_info["status"], comp_info["cpu"],
comp_info["mem_size"], comp_info["mem_perc"]] = comp_instances
for vm, info in comp_instances.items():
refresh_instance_database(comp_info, vm, info)
conn.close() conn.close()
except libvirtError as lib_err: except libvirtError as lib_err:
@ -343,7 +367,6 @@ def instance(request, compute_id, vname):
default_cache = settings.INSTANCE_VOLUME_DEFAULT_CACHE default_cache = settings.INSTANCE_VOLUME_DEFAULT_CACHE
default_format = settings.INSTANCE_VOLUME_DEFAULT_FORMAT default_format = settings.INSTANCE_VOLUME_DEFAULT_FORMAT
formats = conn.get_image_formats() formats = conn.get_image_formats()
default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS
busses = conn.get_busses() busses = conn.get_busses()
default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS
show_access_root_password = settings.SHOW_ACCESS_ROOT_PASSWORD show_access_root_password = settings.SHOW_ACCESS_ROOT_PASSWORD

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

7
static/js/bootstrap.min.js_332 Executable file

File diff suppressed because one or more lines are too long

View file

@ -444,8 +444,8 @@ class wvmConnect(object):
def get_net_device(self): def get_net_device(self):
netdevice = [] netdevice = []
def get_info(ctx): def get_info(ctx):
dev_type = util.get_xpath(ctx, '/device/capability/@type') dev_type = util.get_xpath('/device/capability/@type')
interface = util.get_xpath(ctx, '/device/capability/interface') interface = util.get_xpath('/device/capability/interface')
return (dev_type, interface) return (dev_type, interface)
for dev in self.wvm.listAllDevices(0): for dev in self.wvm.listAllDevices(0):
xml = dev.XMLDesc(0) xml = dev.XMLDesc(0)
@ -454,19 +454,21 @@ class wvmConnect(object):
netdevice.append(interface) netdevice.append(interface)
return netdevice return netdevice
def get_host_instances(self): def get_host_instances(self, raw_mem_size=False):
vname = {} vname = {}
def get_info(ctx): def get_info(doc):
mem = util.get_xpath(ctx, "/domain/currentMemory") mem = util.get_xpath(doc, "/domain/currentMemory")
mem = int(mem) / 1024 mem = int(mem) / 1024
cur_vcpu = util.get_xpath(ctx, "/domain/vcpu/@current") if raw_mem_size:
mem = int(mem) * (1024*1024)
cur_vcpu = util.get_xpath(doc, "/domain/vcpu/@current")
if cur_vcpu: if cur_vcpu:
vcpu = cur_vcpu vcpu = cur_vcpu
else: else:
vcpu = util.get_xpath(ctx, "/domain/vcpu") vcpu = util.get_xpath(doc, "/domain/vcpu")
title = util.get_xpath(ctx, "/domain/title") title = util.get_xpath(doc, "/domain/title")
title = title if title else '' title = title if title else ''
description = util.get_xpath(ctx, "/domain/description") description = util.get_xpath(doc, "/domain/description")
description = description if description else '' description = description if description else ''
return (mem, vcpu, title, description) return (mem, vcpu, title, description)
for name in self.get_instances(): for name in self.get_instances():

View file

@ -3,11 +3,11 @@ from vrtManager.connection import wvmConnect
from vrtManager.util import get_xml_path from vrtManager.util import get_xml_path
def cpu_version(ctx): def cpu_version(doc):
for info in ctx.xpathEval('/sysinfo/processor/entry'): for info in doc.xpath('/sysinfo/processor/entry'):
elem = info.xpathEval('@name')[0].content elem = info.xpath('@name')[0]
if elem == 'version': if elem == 'version':
return info.content return info.text
return 'Unknown' return 'Unknown'
@ -59,12 +59,12 @@ class wvmHostDetails(wvmConnect):
Function return host server information: hostname, cpu, memory, ... Function return host server information: hostname, cpu, memory, ...
""" """
info = [] info = []
info.append(self.wvm.getHostname()) info.append(self.wvm.getHostname()) # hostname
info.append(self.wvm.getInfo()[0]) info.append(self.wvm.getInfo()[0]) # architecture
info.append(self.wvm.getInfo()[1] * 1048576) info.append(self.wvm.getInfo()[1] * 1048576) # memory
info.append(self.wvm.getInfo()[2]) info.append(self.wvm.getInfo()[2]) # cpu core count
info.append(get_xml_path(self.wvm.getSysinfo(0), func=cpu_version)) info.append(get_xml_path(self.wvm.getSysinfo(0), func=cpu_version)) # cpu version
info.append(self.wvm.getURI()) info.append(self.wvm.getURI()) #uri
return info return info
def hypervisor_type(self): def hypervisor_type(self):

View file

@ -203,10 +203,10 @@ class wvmInstance(wvmConnect):
def get_net_device(self): def get_net_device(self):
def get_mac_ipaddr(net, mac_host): def get_mac_ipaddr(net, mac_host):
def fixed(ctx): def fixed(doc):
for net in ctx.xpathEval('/network/ip/dhcp/host'): for net in doc.xpath('/network/ip/dhcp/host'):
mac = net.xpathEval('@mac')[0].content mac = net.xpath('@mac')[0]
host = net.xpathEval('@ip')[0].content host = net.xpath('@ip')[0]
if mac == mac_host: if mac == mac_host:
return host return host
return None return None
@ -215,9 +215,9 @@ class wvmInstance(wvmConnect):
def networks(ctx): def networks(ctx):
result = [] result = []
for net in ctx.xpathEval('/domain/devices/interface'): for net in ctx.xpath('/domain/devices/interface'):
mac_host = net.xpathEval('mac/@address')[0].content mac_host = net.xpath('mac/@address')[0]
nic_host = net.xpathEval('source/@network|source/@bridge|source/@dev|target/@dev')[0].content nic_host = net.xpath('source/@network|source/@bridge|source/@dev|target/@dev')[0]
try: try:
net = self.get_network(nic_host) net = self.get_network(nic_host)
ip = get_mac_ipaddr(net, mac_host) ip = get_mac_ipaddr(net, mac_host)
@ -229,7 +229,7 @@ class wvmInstance(wvmConnect):
return util.get_xml_path(self._XMLDesc(0), func=networks) return util.get_xml_path(self._XMLDesc(0), func=networks)
def get_disk_device(self): def get_disk_device(self):
def disks(ctx): def disks(doc):
result = [] result = []
dev = None dev = None
volume = None volume = None
@ -237,13 +237,14 @@ class wvmInstance(wvmConnect):
src_fl = None src_fl = None
disk_format = None disk_format = None
disk_size = None disk_size = None
for disk in ctx.xpathEval('/domain/devices/disk'):
device = disk.xpathEval('@device')[0].content for disk in doc.xpath('/domain/devices/disk'):
device = disk.xpath('@device')[0]
if device == 'disk': if device == 'disk':
try: try:
dev = disk.xpathEval('target/@dev')[0].content dev = disk.xpath('target/@dev')[0]
src_fl = disk.xpathEval('source/@file|source/@dev|source/@name|source/@volume')[0].content src_fl = disk.xpath('source/@file|source/@dev|source/@name|source/@volume')[0]
disk_format = disk.xpathEval('driver/@type')[0].content disk_format = disk.xpath('driver/@type')[0]
try: try:
vol = self.get_volume_by_path(src_fl) vol = self.get_volume_by_path(src_fl)
volume = vol.name() volume = vol.name()
@ -263,19 +264,19 @@ class wvmInstance(wvmConnect):
return util.get_xml_path(self._XMLDesc(0), func=disks) return util.get_xml_path(self._XMLDesc(0), func=disks)
def get_media_device(self): def get_media_device(self):
def disks(ctx): def disks(doc):
result = [] result = []
dev = None dev = None
volume = None volume = None
storage = None storage = None
src_fl = None src_fl = None
for media in ctx.xpathEval('/domain/devices/disk'): for media in doc.xpath('/domain/devices/disk'):
device = media.xpathEval('@device')[0].content device = media.xpath('@device')[0]
if device == 'cdrom': if device == 'cdrom':
try: try:
dev = media.xpathEval('target/@dev')[0].content dev = media.xpath('target/@dev')
try: try:
src_fl = media.xpathEval('source/@file')[0].content src_fl = media.xpath('source/@file')
vol = self.get_volume_by_path(src_fl) vol = self.get_volume_by_path(src_fl)
volume = vol.name() volume = vol.name()
stg = vol.storagePoolLookupByVolume() stg = vol.storagePoolLookupByVolume()
@ -487,8 +488,7 @@ class wvmInstance(wvmConnect):
return socket return socket
def get_console_type(self): def get_console_type(self):
console_type = util.get_xml_path(self._XMLDesc(0), console_type = util.get_xml_path(self._XMLDesc(0),"/domain/devices/graphics/@type")
"/domain/devices/graphics/@type")
return console_type return console_type
def set_console_type(self, console_type): def set_console_type(self, console_type):

View file

@ -166,11 +166,11 @@ class wvmNetwork(wvmConnect):
return bool(util.get_xml_path(xml, "/network/ip/dhcp/bootp/@file")) return bool(util.get_xml_path(xml, "/network/ip/dhcp/bootp/@file"))
def get_mac_ipaddr(self): def get_mac_ipaddr(self):
def network(ctx): def network(doc):
result = [] result = []
for net in ctx.xpathEval('/network/ip/dhcp/host'): for net in doc.xpath('/network/ip/dhcp/host'):
host = net.xpathEval('@ip')[0].content host = net.xpath('@ip')[0]
mac = net.xpathEval('@mac')[0].content mac = net.xpath('@mac')[0]
result.append({'host': host, 'mac': mac}) result.append({'host': host, 'mac': mac})
return result return result

View file

@ -1,5 +1,5 @@
import random import random
import libxml2 import lxml.etree as etree
import libvirt import libvirt
import string import string
@ -86,42 +86,44 @@ def get_xml_path(xml, path=None, func=None):
of a passed function (receives xpathContext as its only arg) of a passed function (receives xpathContext as its only arg)
""" """
doc = None doc = None
ctx = None #ctx = None
result = None result = None
try: #try:
doc = libxml2.parseDoc(xml) doc = etree.fromstring(xml)
ctx = doc.xpathNewContext() #ctx = doc.xpathNewContext()
if path:
result = get_xpath(doc, path)
if path: elif func:
result = get_xpath(ctx, path) result = func(doc)
elif func: else:
result = func(ctx) raise ValueError("'path' or 'func' is required.")
#finally:
else: #if doc:
raise ValueError("'path' or 'func' is required.") # doc.freeDoc()
finally: #if ctx:
if doc: # ctx.xpathFreeContext()
doc.freeDoc()
if ctx:
ctx.xpathFreeContext()
return result return result
def get_xpath(ctx, path): def get_xpath(doc, path):
result = None result = None
ret = ctx.xpathEval(path)
ret = doc.xpath(path)
if ret is not None: if ret is not None:
if type(ret) == list: if type(ret) == list:
if len(ret) >= 1: if len(ret) >= 1:
result = ret[0].content if hasattr(ret[0],'text'):
result = ret[0].text
else:
result = ret[0]
else: else:
result = ret result = ret
return result return result
def pretty_mem(val): def pretty_mem(val):
val = int(val) val = int(val)
if val > (10 * 1024 * 1024): if val > (10 * 1024 * 1024):

View file

@ -83,7 +83,15 @@ TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ os.path.join(BASE_DIR, 'templates'), ], 'DIRS': [ os.path.join(BASE_DIR, 'templates'), ],
'APP_DIRS': True, 'APP_DIRS': True,
} 'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
] ]
## WebVirtCloud settings ## WebVirtCloud settings

View file

@ -1,9 +1,17 @@
from django.conf.urls import patterns, include, url from django.conf.urls import include, url
from instances.views import instances, instance, index
from storages.views import storages, storage
from networks.views import networks, network
from secrets.views import secrets
from create.views import create_instance
from interfaces.views import interfaces, interface
from console.views import console
# from django.contrib import admin # from django.contrib import admin
urlpatterns = patterns('', urlpatterns = [
url(r'^$', 'instances.views.index', name='index'), url(r'^$', index, name='index'),
url(r'^instances/$', 'instances.views.instances', name='instances'), url(r'^instances/$', instances, name='instances'),
url(r'^instance/', include('instances.urls')), url(r'^instance/', include('instances.urls')),
url(r'^accounts/', include('accounts.urls')), url(r'^accounts/', include('accounts.urls')),
@ -11,23 +19,15 @@ urlpatterns = patterns('',
url(r'^logs/', include('logs.urls')), url(r'^logs/', include('logs.urls')),
url(r'^datasource/', include('datasource.urls')), url(r'^datasource/', include('datasource.urls')),
url(r'^compute/(?P<compute_id>[0-9]+)/storages/$', url(r'^compute/(?P<compute_id>[0-9]+)/storages/$', storages, name='storages'),
'storages.views.storages', name='storages'), url(r'^compute/(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/$', storage, name='storage'),
url(r'^compute/(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/$', url(r'^compute/(?P<compute_id>[0-9]+)/networks/$', networks, name='networks'),
'storages.views.storage', name='storage'), url(r'^compute/(?P<compute_id>[0-9]+)/network/(?P<pool>[\w\-\.]+)/$', network, name='network'),
url(r'^compute/(?P<compute_id>[0-9]+)/networks/$', url(r'^compute/(?P<compute_id>[0-9]+)/interfaces/$', interfaces, name='interfaces'),
'networks.views.networks', name='networks'), url(r'^compute/(?P<compute_id>[0-9]+)/interface/(?P<iface>[\w\-\.\:]+)/$', interface, name='interface'),
url(r'^compute/(?P<compute_id>[0-9]+)/network/(?P<pool>[\w\-\.]+)/$', url(r'^compute/(?P<compute_id>[0-9]+)/secrets/$', secrets, name='secrets'),
'networks.views.network', name='network'), url(r'^compute/(?P<compute_id>[0-9]+)/create/$', create_instance, name='create_instance'),
url(r'^compute/(?P<compute_id>[0-9]+)/interfaces/$',
'interfaces.views.interfaces', name='interfaces'),
url(r'^compute/(?P<compute_id>[0-9]+)/interface/(?P<iface>[\w\-\.\:]+)/$',
'interfaces.views.interface', name='interface'),
url(r'^compute/(?P<compute_id>[0-9]+)/secrets/$',
'secrets.views.secrets', name='secrets'),
url(r'^compute/(?P<compute_id>[0-9]+)/create/$',
'create.views.create_instance', name='create_instance'),
url(r'^console/$', 'console.views.console', name='console'), url(r'^console/$', console, name='console'),
# (r'^admin/', include(admin.site.urls)), # (r'^admin/', include(admin.site.urls)),
) ]