mirror of
https://github.com/retspen/webvirtcloud
synced 2024-12-24 15:15:22 +00:00
Add users and users VMs
;
This commit is contained in:
parent
29b05745ad
commit
55e93a9087
11 changed files with 213 additions and 21 deletions
|
@ -2,6 +2,8 @@ from django.http import HttpResponseRedirect
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from computes.models import Compute
|
from computes.models import Compute
|
||||||
|
from instances.models import Instance
|
||||||
|
from users.models import UserInstance
|
||||||
from vrtManager.hostdetails import wvmHostDetails
|
from vrtManager.hostdetails import wvmHostDetails
|
||||||
from vrtManager.connection import connection_manager
|
from vrtManager.connection import connection_manager
|
||||||
from libvirt import libvirtError
|
from libvirt import libvirtError
|
||||||
|
@ -30,16 +32,38 @@ def instances(request):
|
||||||
|
|
||||||
error_messages = []
|
error_messages = []
|
||||||
all_host_vms = {}
|
all_host_vms = {}
|
||||||
computes = Compute.objects.filter()
|
all_user_vms = {}
|
||||||
|
computes = Compute.objects.all()
|
||||||
|
|
||||||
for compute in computes:
|
if not request.user.is_superuser:
|
||||||
if connection_manager.host_is_up(compute.type, compute.hostname):
|
user_instances = UserInstance.objects.all()
|
||||||
try:
|
for usr_inst in user_instances:
|
||||||
conn = wvmHostDetails(compute, compute.login, compute.password, compute.type)
|
if connection_manager.host_is_up(usr_inst.instance.compute.type,
|
||||||
all_host_vms[compute.id, compute.name] = conn.get_host_instances()
|
usr_inst.instance.compute.hostname):
|
||||||
conn.close()
|
conn = wvmHostDetails(usr_inst.instance.compute,
|
||||||
except libvirtError as lib_err:
|
usr_inst.instance.compute.login,
|
||||||
error_messages.append(lib_err)
|
usr_inst.instance.compute.password,
|
||||||
|
usr_inst.instance.compute.type)
|
||||||
|
all_user_vms[usr_inst.instance.compute.id,
|
||||||
|
usr_inst.instance.compute.name] = conn.get_user_instances(usr_inst.instance.name)
|
||||||
|
else:
|
||||||
|
for compute in computes:
|
||||||
|
if connection_manager.host_is_up(compute.type, compute.hostname):
|
||||||
|
try:
|
||||||
|
conn = wvmHostDetails(compute, compute.login, compute.password, compute.type)
|
||||||
|
all_host_vms[compute.id, compute.name] = conn.get_host_instances()
|
||||||
|
for vm, info in conn.get_host_instances().items():
|
||||||
|
try:
|
||||||
|
check_uuid = Instance.objects.get(compute_id=compute.id, name=vm)
|
||||||
|
if check_uuid.uuid != info['uuid']:
|
||||||
|
check_uuid.save()
|
||||||
|
except Instance.DoesNotExist:
|
||||||
|
check_uuid = Instance(compute_id=compute.id, name=vm, uuid=info['uuid'])
|
||||||
|
check_uuid.save()
|
||||||
|
conn.close()
|
||||||
|
except libvirtError as lib_err:
|
||||||
|
print 'Error'
|
||||||
|
error_messages.append(lib_err)
|
||||||
|
|
||||||
return render(request, 'instances.html', locals())
|
return render(request, 'instances.html', locals())
|
||||||
|
|
||||||
|
@ -53,4 +77,4 @@ def instance(request, comptes_id, vname):
|
||||||
if not request.user.is_authenticated():
|
if not request.user.is_authenticated():
|
||||||
return HttpResponseRedirect(reverse('index'))
|
return HttpResponseRedirect(reverse('index'))
|
||||||
|
|
||||||
return render(request, 'instances.html', locals())
|
return render(request, 'instance.html', locals())
|
22
templates/instance.html
Normal file
22
templates/instance.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Instance" %} - {{ vname }}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
{% include 'sidebar.html' %}
|
||||||
|
|
||||||
|
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
|
||||||
|
{% if request.user.is_superuser %}
|
||||||
|
<button type="button" class="btn btn-success pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
|
||||||
|
{% endif %}
|
||||||
|
<h1 class="page-header">{{ vname }}</h1>
|
||||||
|
|
||||||
|
{% include 'errors.html' %}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -13,12 +13,16 @@
|
||||||
|
|
||||||
{% include 'errors.html' %}
|
{% include 'errors.html' %}
|
||||||
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
{% if request.user.is_superuser %}
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="active">
|
<tr class="active">
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Host</th>
|
<th>Host</th>
|
||||||
|
<th>VCPU</th>
|
||||||
|
<th>Memory</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th style="width:164px;">Actions</th>
|
<th style="width:164px;">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -33,6 +37,8 @@
|
||||||
<td>
|
<td>
|
||||||
<span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> <a href="{% url 'compute' host.0 %}">{{ host.1 }}</a>
|
<span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> <a href="{% url 'compute' host.0 %}">{{ host.1 }}</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td>{{ info.vcpu }}</td>
|
||||||
|
<td>{{ info.memory }}</td>
|
||||||
<td>{% ifequal info.status 1 %}
|
<td>{% ifequal info.status 1 %}
|
||||||
<span class="label label-success">{% trans "Running" %}</span>
|
<span class="label label-success">{% trans "Running" %}</span>
|
||||||
{% endifequal %}
|
{% endifequal %}
|
||||||
|
@ -99,6 +105,94 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr class="active">
|
||||||
|
<th>Name</th>
|
||||||
|
<th>VCPU</th>
|
||||||
|
<th>Memory</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th style="width:164px;">Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for host, vm in all_user_vms.items %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> <a href="{% url 'instance' host.0 vm.name %}">{{ vm.name }}</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ vm.vcpu }}</td>
|
||||||
|
<td>{{ vm.memory }} {% trans "MB" %}</td>
|
||||||
|
<td>{% ifequal vm.status 1 %}
|
||||||
|
<span class="label label-success">{% trans "Running" %}</span>
|
||||||
|
{% endifequal %}
|
||||||
|
{% ifequal vm.status 5 %}
|
||||||
|
<span class="label label-danger">{% trans "Shutoff" %}</span>
|
||||||
|
{% endifequal %}
|
||||||
|
{% ifequal vm.status 3 %}
|
||||||
|
<span class="label label-warning">{% trans "Suspend" %}</span>
|
||||||
|
{% endifequal %}
|
||||||
|
</td>
|
||||||
|
<td><form action="" method="post" role="form">{% csrf_token %}
|
||||||
|
<input type="hidden" name="name" value="{{ vm.name }}"/>
|
||||||
|
<input type="hidden" name="compute" value="{{ host.0 }}"/>
|
||||||
|
{% ifequal vm.status 5 %}
|
||||||
|
<button class="btn btn-sm btn-default" type="submit" name="start" title="Start">
|
||||||
|
<span class="glyphicon glyphicon-play"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default disabled" title="{% trans "Suspend" %}">
|
||||||
|
<span class="glyphicon glyphicon-pause"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default disabled" title="{% trans "Destroy" %}">
|
||||||
|
<span class="glyphicon glyphicon-stop"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default disabled" title="{% trans "Console" %}">
|
||||||
|
<span class="glyphicon glyphicon-eye-open"></span>
|
||||||
|
</button>
|
||||||
|
{% endifequal %}
|
||||||
|
{% ifequal vm.status 3 %}
|
||||||
|
<button class="btn btn-sm btn-default" type="submit" name="resume"
|
||||||
|
title="{% trans "Resume" %}">
|
||||||
|
<span class="glyphicon glyphicon-play"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default disabled" title="{% trans "Suspend" %}">
|
||||||
|
<span class="glyphicon glyphicon-pause"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default disabled" title="{% trans "Destroy" %}">
|
||||||
|
<span class="glyphicon glyphicon-stop"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default disabled" title="{% trans "Console" %}">
|
||||||
|
<span class="glyphicon glyphicon-eye-open"></span>
|
||||||
|
</button>
|
||||||
|
{% endifequal %}
|
||||||
|
{% ifequal vm.status 1 %}
|
||||||
|
<button class="btn btn-sm btn-default disabled" title="{% trans "Start" %}">
|
||||||
|
<span class="glyphicon glyphicon-play"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default" type="submit" name="suspend"
|
||||||
|
title="{% trans "Suspend" %}">
|
||||||
|
<span class="glyphicon glyphicon-pause"></span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm btn-default" type="submit" name="destroy"
|
||||||
|
title="{% trans "Destroy" %}" onclick="return confirm('Are you sure?')">
|
||||||
|
<span class="glyphicon glyphicon-stop"></span>
|
||||||
|
</button>
|
||||||
|
<a href="#" class="btn btn-sm btn-default"
|
||||||
|
onclick='open_console("{{ host.0 }}-{{ vm.uuid }}")' title="{% trans "Console" %}">
|
||||||
|
<span class="glyphicon glyphicon-eye-open"></span>
|
||||||
|
</a>
|
||||||
|
{% endifequal %}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
23
templates/login.html
Normal file
23
templates/login.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Sign In" %}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12" role="main">
|
||||||
|
{% if form.errors %}
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||||
|
{% trans "Incorrect username or password." %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<form class="form-signin" method="post" role="form">{% csrf_token %}
|
||||||
|
<h2 class="form-signin-heading">{% trans "Sign In" %}</h2>
|
||||||
|
<input type="text" class="form-control" name="username" placeholder="Login" autocapitalize="none"
|
||||||
|
autocorrect="off" autofocus>
|
||||||
|
<input type="password" class="form-control" name="password" placeholder="Password">
|
||||||
|
<input name="next" id="next" type="hidden" value="{% url 'instances' %}">
|
||||||
|
<button class="btn btn-lg btn-success btn-block" type="submit">{% trans "Sign In" %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
12
templates/logout.html
Normal file
12
templates/logout.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Sign Out" %}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12" role="main">
|
||||||
|
<div class="logout">
|
||||||
|
<h1>{% trans "Successful log out" %}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -5,8 +5,10 @@
|
||||||
<hr>
|
<hr>
|
||||||
<ul class="nav nav-sidebar">
|
<ul class="nav nav-sidebar">
|
||||||
<li {% active request "^/instance" %}><a href="{% url 'instances' %}"><span class="glyphicon glyphicon-th" aria-hidden="true"></span></a></li>
|
<li {% active request "^/instance" %}><a href="{% url 'instances' %}"><span class="glyphicon glyphicon-th" aria-hidden="true"></span></a></li>
|
||||||
<li {% active request "^/compute" %}><a href="{% url 'computes' %}"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span></a></li>
|
{% if request.user.is_superuser %}
|
||||||
<li {% active request "^/user" %}><a href="{% url 'users' %}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></a></li>
|
<li {% active request "^/compute" %}><a href="{% url 'computes' %}"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span></a></li>
|
||||||
|
<li {% active request "^/user" %}><a href="{% url 'users' %}"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></a></li>
|
||||||
|
{% endif %}
|
||||||
<li class="bottom-sticky">
|
<li class="bottom-sticky">
|
||||||
<a href="#"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span></a>
|
<a href="#"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span></a>
|
||||||
<a href="{% url 'logout' %}"><span class="glyphicon glyphicon-log-out" aria-hidden="true"></span></a>
|
<a href="{% url 'logout' %}"><span class="glyphicon glyphicon-log-out" aria-hidden="true"></span></a>
|
||||||
|
|
|
@ -17,6 +17,8 @@ class Migration(migrations.Migration):
|
||||||
name='UserInstance',
|
name='UserInstance',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('is_change', models.BooleanField(default=False)),
|
||||||
|
('is_delete', models.BooleanField(default=False)),
|
||||||
('instance', models.ForeignKey(to='instances.Instance')),
|
('instance', models.ForeignKey(to='instances.Instance')),
|
||||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
|
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,13 +13,7 @@ class Migration(migrations.Migration):
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='userinstance',
|
model_name='userinstance',
|
||||||
name='is_change',
|
name='is_block',
|
||||||
field=models.BooleanField(default=False),
|
|
||||||
preserve_default=True,
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='userinstance',
|
|
||||||
name='is_delete',
|
|
||||||
field=models.BooleanField(default=False),
|
field=models.BooleanField(default=False),
|
||||||
preserve_default=True,
|
preserve_default=True,
|
||||||
),
|
),
|
|
@ -8,6 +8,7 @@ class UserInstance(models.Model):
|
||||||
instance = models.ForeignKey(Instance)
|
instance = models.ForeignKey(Instance)
|
||||||
is_change = models.BooleanField(default=False)
|
is_change = models.BooleanField(default=False)
|
||||||
is_delete = models.BooleanField(default=False)
|
is_delete = models.BooleanField(default=False)
|
||||||
|
is_block = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.instance.name
|
return self.instance.name
|
|
@ -435,9 +435,27 @@ class wvmConnect(object):
|
||||||
vname = {}
|
vname = {}
|
||||||
for name in self.get_instances():
|
for name in self.get_instances():
|
||||||
dom = self.get_instance(name)
|
dom = self.get_instance(name)
|
||||||
vname[dom.name()] = {'status': dom.info()[0], 'uuid': dom.UUIDString()}
|
mem = util.get_xml_path(dom.XMLDesc(0), "/domain/currentMemory")
|
||||||
|
mem = int(mem) * 1024
|
||||||
|
cur_vcpu = util.get_xml_path(dom.XMLDesc(0), "/domain/vcpu/@current")
|
||||||
|
if cur_vcpu:
|
||||||
|
vcpu = cur_vcpu
|
||||||
|
else:
|
||||||
|
vcpu = util.get_xml_path(dom.XMLDesc(0), "/domain/vcpu")
|
||||||
|
vname[dom.name()] = {'status': dom.info()[0], 'uuid': dom.UUIDString(), 'vcpu': vcpu, 'memory': mem}
|
||||||
return vname
|
return vname
|
||||||
|
|
||||||
|
def get_user_instances(self, name):
|
||||||
|
dom = self.get_instance(name)
|
||||||
|
mem = util.get_xml_path(dom.XMLDesc(0), "/domain/currentMemory")
|
||||||
|
mem = int(mem) / 1024
|
||||||
|
cur_vcpu = util.get_xml_path(dom.XMLDesc(0), "/domain/vcpu/@current")
|
||||||
|
if cur_vcpu:
|
||||||
|
vcpu = cur_vcpu
|
||||||
|
else:
|
||||||
|
vcpu = util.get_xml_path(dom.XMLDesc(0), "/domain/vcpu")
|
||||||
|
return {'name': dom.name(), 'status': dom.info()[0], 'uuid': dom.UUIDString(), 'vcpu': vcpu, 'memory': mem}
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Close connection"""
|
"""Close connection"""
|
||||||
# to-do: do not close connection ;)
|
# to-do: do not close connection ;)
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.conf.urls import patterns, include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
# url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name='login'),
|
url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name='login'),
|
||||||
url(r'^logout/$', 'django.contrib.auth.views.logout', {'template_name': 'logout.html'}, name='logout'),
|
url(r'^logout/$', 'django.contrib.auth.views.logout', {'template_name': 'logout.html'}, name='logout'),
|
||||||
|
|
||||||
url(r'^login/$', 'django.contrib.auth.views.login'),
|
url(r'^login/$', 'django.contrib.auth.views.login'),
|
||||||
|
|
Loading…
Reference in a new issue