1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2025-02-03 02:55:18 +00:00

add Compute instances tab. Minimal invasion. minimal change. keep structure

This commit is contained in:
catborise 2018-09-28 13:33:21 +03:00
parent e44e01cad4
commit 25e6381fc9
21 changed files with 618 additions and 335 deletions

View file

@ -17,7 +17,7 @@
<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' %}">
<input name="next" id="next" type="hidden" value="{% url 'allinstances' %}">
<button class="btn btn-lg btn-success btn-block" type="submit">{% trans "Sign In" %}</button>
</form>
</div>

View file

@ -11,6 +11,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> {% trans "Overview" %}
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -1,9 +1,26 @@
from django.conf.urls import url
from . import views
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 computes.views import overview, compute_graph, computes
from instances.views import instances
from nwfilters.views import nwfilter, nwfilters
urlpatterns = [
url(r'^$', views.computes, name='computes'),
url(r'^overview/(?P<compute_id>[0-9]+)/$', views.overview, name='overview'),
url(r'^statistics/(?P<compute_id>[0-9]+)/$',
views.compute_graph, name='compute_graph'),
url(r'^/', computes, name='computes'),
url(r'^(?P<compute_id>[0-9]+)/$', overview, name='overview'),
url(r'^(?P<compute_id>[0-9]+)/statistics$', compute_graph, name='compute_graph'),
url(r'^(?P<compute_id>[0-9]+)/instances/$', instances, name='instances'),
url(r'^(?P<compute_id>[0-9]+)/storages/$', storages, name='storages'),
url(r'^(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/$', storage, name='storage'),
url(r'^(?P<compute_id>[0-9]+)/networks/$', networks, name='networks'),
url(r'^(?P<compute_id>[0-9]+)/network/(?P<pool>[\w\-\.]+)/$', network, name='network'),
url(r'^(?P<compute_id>[0-9]+)/interfaces/$', interfaces, name='interfaces'),
url(r'^(?P<compute_id>[0-9]+)/interface/(?P<iface>[\w\-\.\:]+)/$', interface, name='interface'),
url(r'^(?P<compute_id>[0-9]+)/nwfilters/$', nwfilters, name='nwfilters'),
url(r'^(?P<compute_id>[0-9]+)/nwfilter/(?P<nwfltr>[\w\-\.\:]+)/$', nwfilter, name='nwfilter'),
url(r'^(?P<compute_id>[0-9]+)/secrets/$', secrets, name='secrets'),
url(r'^(?P<compute_id>[0-9]+)/create/$', create_instance, name='create_instance'),
]

View file

@ -0,0 +1,184 @@
{% extends "base.html" %}
{% load i18n %}
{% load staticfiles %}
{% block title %}{% trans "Instances" %}{% endblock %}
{% block style %}
<link rel="stylesheet" href="{% static "css/sortable-theme-bootstrap.css" %}" />
{% endblock %}
{% block content %}
<!-- Page Heading -->
<div class="row">
<div class="col-lg-12">
{% if request.user.is_superuser %}
{% include 'create_inst_block.html' %}
{% endif %}
{% if all_host_vms or all_user_vms %}
<div class="pull-right search">
<input id="filter" class="form-control" type="text" placeholder="Search">
</div>
{% endif %}
<h1 class="page-header">{% trans "Instances" %}</h1>
</div>
</div>
<!-- /.row -->
{% include 'errors_block.html' %}
<div class="row">
<div class="col-lg-12">
<div class="table-responsive">
{% if request.user.is_superuser %}
{% if not all_host_vms %}
<div class="col-lg-12">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instance" %}
</div>
</div>
{% else %}
{% ifequal view_style "nongrouped" %}
{% include 'allinstances_index_nongrouped.html' %}
{% endifequal %}
{% ifequal view_style "grouped" %}
{% include 'allinstances_index_grouped.html' %}
{% endifequal %}
{% endif %}
{% else %}
{% if not all_user_vms %}
<div class="col-lg-12">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instance" %}
</div>
</div>
{% else %}
<table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th>VCPU</th>
<th>Memory</th>
<th data-sortable="false" style="width: 165px;">Actions</th>
</tr>
</thead>
<tbody class="searchable">
{% for inst, vm in all_user_vms.items %}
<tr>
<td><a href="{% url 'instance' vm.compute_id vm.name %}">{{ vm.name }}</a><br><small><em>{{ vm.title }}</em></small></td>
<td>{% ifequal vm.status 1 %}
<span class="text-success">{% trans "Active" %}</span>
{% endifequal %}
{% ifequal vm.status 5 %}
<span class="text-danger">{% trans "Off" %}</span>
{% endifequal %}
{% ifequal vm.status 3 %}
<span class="text-warning">{% trans "Suspend" %}</span>
{% endifequal %}
</td>
<td>{{ vm.vcpu }}</td>
<td>{{ vm.memory }} {% trans "MB" %}</td>
<td><form action="" method="post" role="form">{% csrf_token %}
<input type="hidden" name="name" value="{{ vm.name }}"/>
<input type="hidden" name="compute_id" value="{{ vm.compute_id }}"/>
{% ifequal vm.status 5 %}
{% if inst.instance.is_template %}
<button class="btn btn-sm btn-default" type="button" name="clone" title="{% trans "Clone" %}" onclick="goto_instance_clone({{ vm.compute_id }}, '{{ vm.name }}');">
<span class="glyphicon glyphicon-duplicate"></span>
</button>
{% else %}
<button class="btn btn-sm btn-default" type="submit" name="poweron" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
{% endif %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal vm.status 3 %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC/Spice Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal vm.status 1 %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="poweroff" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="powercycle" title="{% trans "Power Cycle" %}" onclick="return confirm('Are you sure?')">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<a href="#" class="btn btn-sm btn-default" onclick='open_console("{{ vm.compute_id }}-{{ vm.uuid }}")' title="{% trans "Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
{% endifequal %}
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endif %}
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="{% static "js/sortable.min.js" %}"></script>
<script>
function open_console(uuid) {
window.open("{% url 'console' %}?token=" + uuid, "", "width=850,height=485");
}
</script>
<script>
function filter_table() {
var rex = new RegExp($(this).val(), 'i');
$('.searchable tr').hide();
$('.searchable tr').filter(function () {
return rex.test($(this).text());
}).show();
Cookies.set("instances_filter", $(this).val(), { expires: 1 });
}
$(document).ready(function () {
instances_filter_cookie = Cookies.get("instances_filter");
if (instances_filter_cookie) {
$('#filter').val(instances_filter_cookie);
$('#filter').each(filter_table);
}
(function ($) {
$('#filter').keyup(filter_table)
}(jQuery));
});
</script>
<script>
function goto_instance_clone(compute, instance) {
window.location = "/instance/" + compute + "/" + instance + "/#clone";
}
</script>
{% if request.user.is_superuser %}
<script>
function goto_compute() {
var compute = $("#compute_select").val();
window.location = "/compute/" + compute + "/create/";
}
</script>
{% endif %}
{% endblock %}

View file

@ -1,12 +1,12 @@
{% extends "base.html" %}
{% load i18n %}
{% load staticfiles %}
{% block title %}{% trans "Instances" %}{% endblock %}
{% block title %}{% trans "Instances" %} - {{ compute.name }}{% endblock %}
{% block style %}
<link rel="stylesheet" href="{% static "css/sortable-theme-bootstrap.css" %}" />
{% endblock %}
{% block content %}
<!-- Page Heading -->
<!-- Page Heading -->
<div class="row">
<div class="col-lg-12">
{% if request.user.is_superuser %}
@ -17,129 +17,144 @@
<input id="filter" class="form-control" type="text" placeholder="Search">
</div>
{% endif %}
<h1 class="page-header">{% trans "Instances" %}</h1>
<h1 class="page-header">{{ compute.name }}</h1>
</div>
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
{% include 'errors_block.html' %}
<ol class="breadcrumb">
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> {% trans "Instances" %}
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>
<li>
<i class="fa fa-sitemap"></i> <a href="{% url 'networks' compute.id %}">{% trans "Networks" %}</a>
</li>
<li>
<i class="fa fa-wifi"></i> <a href="{% url 'interfaces' compute.id %}">{% trans "Interfaces" %}</a>
</li>
<li>
<i class="fa fa-filter"></i> <a href="{% url 'nwfilters' compute.id %}">{% trans "NWFilters" %}</a>
</li>
<li>
<i class="fa fa-key"></i> <a href="{% url 'secrets' compute.id %}">{% trans "Secrets" %}</a>
</li>
</ol>
</div>
</div>
<!-- /.row -->
<div class="row">
{% include 'errors_block.html' %}
<div class="row">
{% if not all_host_vms %}
<div class="col-lg-12">
<div class="table-responsive">
{% if request.user.is_superuser %}
{% if not all_host_vms %}
<div class="col-lg-12">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instance" %}
</div>
</div>
{% else %}
{% ifequal view_style "nongrouped" %}
{% include 'instances_nongrouped.html' %}
{% endifequal %}
{% ifequal view_style "grouped" %}
{% include 'instances_grouped.html' %}
{% endifequal %}
{% endif %}
{% else %}
{% if not all_user_vms %}
<div class="col-lg-12">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "You don't have any Instance" %}
</div>
</div>
{% else %}
<table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th>VCPU</th>
<th>Memory</th>
<th data-sortable="false" style="width: 165px;">Actions</th>
</tr>
</thead>
<tbody class="searchable">
{% for inst, vm in all_user_vms.items %}
<tr>
<td><a href="{% url 'instance' vm.compute_id vm.name %}">{{ vm.name }}</a><br><small><em>{{ vm.title }}</em></small></td>
<td>{% ifequal vm.status 1 %}
<span class="text-success">{% trans "Active" %}</span>
{% endifequal %}
{% ifequal vm.status 5 %}
<span class="text-danger">{% trans "Off" %}</span>
{% endifequal %}
{% ifequal vm.status 3 %}
<span class="text-warning">{% trans "Suspend" %}</span>
{% endifequal %}
</td>
<td>{{ vm.vcpu }}</td>
<td>{{ vm.memory }} {% trans "MB" %}</td>
<td><form action="" method="post" role="form">{% csrf_token %}
<input type="hidden" name="name" value="{{ vm.name }}"/>
<input type="hidden" name="compute_id" value="{{ vm.compute_id }}"/>
{% ifequal vm.status 5 %}
{% if inst.instance.is_template %}
<button class="btn btn-sm btn-default" type="button" name="clone" title="{% trans "Clone" %}" onclick="goto_instance_clone({{ vm.compute_id }}, '{{ vm.name }}');">
<span class="glyphicon glyphicon-duplicate"></span>
</button>
{% else %}
<button class="btn btn-sm btn-default" type="submit" name="poweron" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
{% endif %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal vm.status 3 %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC/Spice Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal vm.status 1 %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="poweroff" title="{% trans "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="powercycle" title="{% trans "Power Cycle" %}" onclick="return confirm('Are you sure?')">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<a href="#" class="btn btn-sm btn-default" onclick='open_console("{{ vm.compute_id }}-{{ vm.uuid }}")' title="{% trans "Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
{% endifequal %}
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endif %}
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "Hypervisor doesn't have any instances" %}
</div>
</div>
</div>
{% else %}
<div class="col-lg-12">
<table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable>
<thead>
<tr>
<th>Name<br>Description</th>
<th>Host<br>User</th>
<th>Status</th>
<th>VCPU</th>
<th>Memory</th>
<th data-sortable="false" style="width:205px;">Actions</th>
</tr>
</thead>
<tbody class="searchable">
{% for host, inst in all_host_vms.items %}
{% for vm, info in inst.items %}
<tr>
<td><a href="{% url 'instance' host.0 vm %}">{{ vm }}</a><br><small><em>{{ info.title }}</em></small></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>
{% ifequal info.status 1 %}<span class="text-success">{% trans "Active" %}</span>{% endifequal %}
{% ifequal info.status 5 %}<span class="text-danger">{% trans "Off" %}</span>{% endifequal %}
{% ifequal info.status 3 %}<span class="text-warning">{% trans "Suspend" %}</span>{% endifequal %}
</td>
<td>{{ info.vcpu }}</td>
<td>{{ info.memory|filesizeformat }}</td>
<td><form action="" method="post" role="form">{% csrf_token %}
<input type="hidden" name="name" value="{{ vm }}"/>
<input type="hidden" name="compute_id" value="{{ host.0 }}"/>
{% ifequal info.status 5 %}
{% if info.is_template %}
<button class="btn btn-sm btn-default" type="button" name="clone" title="{% trans "Clone" %}" onclick="goto_instance_clone({{ host.0 }}, '{{ vm }}');">
<span class="glyphicon glyphicon-duplicate"></span>
</button>
{% else %}
<button class="btn btn-sm btn-default" type="submit" name="poweron" title="{% trans "Power On" %}">
<span class="glyphicon glyphicon-play"></span>
</button>
{% endif %}
<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 "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal info.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 "Power Off" %}">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "Power Cycle" %}">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<button class="btn btn-sm btn-default disabled" title="{% trans "VNC Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</button>
{% endifequal %}
{% ifequal info.status 1 %}
<button class="btn btn-sm btn-default disabled" title="{% trans "Power On" %}">
<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="poweroff" title="{% trans "Power Off" %}" onclick="return confirm('Are you sure?')">
<span class="glyphicon glyphicon-off"></span>
</button>
<button class="btn btn-sm btn-default" type="submit" name="powercycle" title="{% trans "Power Cycle" %}" onclick="return confirm('Are you sure?')">
<span class="glyphicon glyphicon-refresh"></span>
</button>
<a href="#" class="btn btn-sm btn-default" onclick='open_console("{{ host.0 }}-{{ info.uuid }}")' title="{% trans "Console" %}">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
{% endifequal %}
</form>
</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
{% endblock %}
{% block script %}
<script src="{% static "js/sortable.min.js" %}"></script>

View file

@ -2,6 +2,7 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.allinstances, name='allinstances'),
url(r'^(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.instance, name='instance'),
url(r'^statistics/(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.inst_graph, name='inst_graph'),
url(r'^status/(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.inst_status, name='inst_status'),

View file

@ -26,175 +26,72 @@ from logs.views import addlogmsg
from django.conf import settings
from django.contrib import messages
@login_required
def index(request):
"""
:param request:
:return:
"""
return HttpResponseRedirect(reverse('instances'))
return HttpResponseRedirect(reverse('allinstances'))
@login_required
def instances(request):
def allinstances(request):
"""
INSTANCES LIST FOR ALL HOSTS
:param request:
:return:
"""
all_host_vms = {}
error_messages = []
computes = Compute.objects.all().order_by("name")
if not request.user.is_superuser:
all_user_vms = get_user_instances(request)
else:
for comp in computes:
try:
all_host_vms.update(get_host_instances(request,comp))
except libvirtError as lib_err:
error_messages.append(lib_err)
if request.method == 'POST':
try:
instances_actions(request)
except libvirtError as lib_err:
error_messages.append(lib_err)
addlogmsg(request.user.username, instance.name, lib_err.message)
view_style = settings.VIEW_INSTANCES_LIST_STYLE
return render(request, 'allinstances.html', locals())
@login_required
def instances(request, compute_id):
"""
:param request:
:return:
"""
error_messages = []
all_host_vms = {}
all_user_vms = {}
computes = Compute.objects.all().order_by("name")
def get_userinstances_info(instance):
info = {}
uis = UserInstance.objects.filter(instance=instance)
info['count'] = uis.count()
if info['count'] > 0:
info['first_user'] = uis[0]
else:
info['first_user'] = None
return info
def refresh_instance_database(comp, vm, info):
instances = Instance.objects.filter(name=vm)
if instances.count() > 1:
for i in instances:
user_instances_count = UserInstance.objects.filter(instance=i).count()
if user_instances_count == 0:
addlogmsg(request.user.username, i.name, _("Deleting due to multiple records."))
i.delete()
try:
check_uuid = Instance.objects.get(compute_id=comp["id"], name=vm)
if check_uuid.uuid != info['uuid']:
check_uuid.save()
all_host_vms[comp["id"],
comp["name"],
comp["status"],
comp["cpu"],
comp["mem_size"],
comp["mem_perc"]][vm]['is_template'] = check_uuid.is_template
all_host_vms[comp["id"],
comp["name"],
comp["status"],
comp["cpu"],
comp["mem_size"],
comp["mem_perc"]][vm]['userinstances'] = get_userinstances_info(check_uuid)
except Instance.DoesNotExist:
check_uuid = Instance(compute_id=comp["id"], name=vm, uuid=info['uuid'])
check_uuid.save()
compute = get_object_or_404(Compute, pk=compute_id)
if not request.user.is_superuser:
user_instances = UserInstance.objects.filter(user_id=request.user.id)
for usr_inst in user_instances:
if connection_manager.host_is_up(usr_inst.instance.compute.type,
usr_inst.instance.compute.hostname):
conn = wvmHostDetails(usr_inst.instance.compute,
usr_inst.instance.compute.login,
usr_inst.instance.compute.password,
usr_inst.instance.compute.type)
all_user_vms[usr_inst] = conn.get_user_instances(usr_inst.instance.name)
all_user_vms[usr_inst].update({'compute_id': usr_inst.instance.compute.id})
all_user_vms = get_user_instances(request)
else:
for comp in computes:
status = connection_manager.host_is_up(comp.type, comp.hostname)
if status:
try:
conn = wvmHostDetails(comp, comp.login, comp.password, comp.type)
comp_node_info = conn.get_node_info()
comp_mem = conn.get_memory_usage()
comp_instances = conn.get_host_instances(True)
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()
except libvirtError as lib_err:
error_messages.append(lib_err)
try:
all_host_vms = get_host_instances(request, compute)
except libvirtError as lib_err:
error_messages.append(lib_err)
if request.method == 'POST':
name = request.POST.get('name', '')
compute_id = request.POST.get('compute_id', '')
instance = Instance.objects.get(compute_id=compute_id, name=name)
try:
conn = wvmInstances(instance.compute.hostname,
instance.compute.login,
instance.compute.password,
instance.compute.type)
if 'poweron' in request.POST:
msg = _("Power On")
addlogmsg(request.user.username, instance.name, msg)
conn.start(name)
return HttpResponseRedirect(request.get_full_path())
if 'poweroff' in request.POST:
msg = _("Power Off")
addlogmsg(request.user.username, instance.name, msg)
conn.shutdown(name)
return HttpResponseRedirect(request.get_full_path())
if 'powercycle' in request.POST:
msg = _("Power Cycle")
conn.force_shutdown(name)
conn.start(name)
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path())
if 'getvvfile' in request.POST:
msg = _("Send console.vv file")
addlogmsg(request.user.username, instance.name, msg)
response = HttpResponse(content='', content_type='application/x-virt-viewer', status=200, reason=None, charset='utf-8')
response.writelines('[virt-viewer]\n')
response.writelines('type=' + conn.graphics_type(name) + '\n')
response.writelines('host=' + conn.graphics_listen(name) + '\n')
response.writelines('port=' + conn.graphics_port(name) + '\n')
response.writelines('title=' + conn.domain_name(name) + '\n')
response.writelines('password=' + conn.graphics_passwd(name) + '\n')
response.writelines('enable-usbredir=1\n')
response.writelines('disable-effects=all\n')
response.writelines('secure-attention=ctrl+alt+ins\n')
response.writelines('release-cursor=ctrl+alt\n')
response.writelines('fullscreen=1\n')
response.writelines('delete-this-file=1\n')
response['Content-Disposition'] = 'attachment; filename="console.vv"'
return response
if request.user.is_superuser:
if 'suspend' in request.POST:
msg = _("Suspend")
addlogmsg(request.user.username, instance.name, msg)
conn.suspend(name)
return HttpResponseRedirect(request.get_full_path())
if 'resume' in request.POST:
msg = _("Resume")
addlogmsg(request.user.username, instance.name, msg)
conn.resume(name)
return HttpResponseRedirect(request.get_full_path())
instances_actions(request)
except libvirtError as lib_err:
error_messages.append(lib_err)
addlogmsg(request.user.username, instance.name, lib_err.message)
view_style = settings.VIEW_INSTANCES_LIST_STYLE
return render(request, 'instances.html', locals())
@ -206,7 +103,7 @@ def instance(request, compute_id, vname):
"""
error_messages = []
#messages = []
# messages = []
compute = get_object_or_404(Compute, pk=compute_id)
computes = Compute.objects.all().order_by('name')
computes_count = computes.count()
@ -217,8 +114,8 @@ def instance(request, compute_id, vname):
console_listen_addresses = settings.QEMU_CONSOLE_LISTEN_ADDRESSES
try:
userinstance = UserInstance.objects.get(instance__compute_id=compute_id,
instance__name=vname,
user__id=request.user.id)
instance__name=vname,
user__id=request.user.id)
except UserInstance.DoesNotExist:
userinstance = None
@ -231,15 +128,15 @@ def instance(request, compute_id, vname):
return 0
size_str = size_str.encode('ascii', 'ignore').upper().translate(None, " B")
if 'K' == size_str[-1]:
return long(float(size_str[:-1]))<<10
return long(float(size_str[:-1])) << 10
elif 'M' == size_str[-1]:
return long(float(size_str[:-1]))<<20
return long(float(size_str[:-1])) << 20
elif 'G' == size_str[-1]:
return long(float(size_str[:-1]))<<30
return long(float(size_str[:-1])) << 30
elif 'T' == size_str[-1]:
return long(float(size_str[:-1]))<<40
return long(float(size_str[:-1])) << 40
elif 'P' == size_str[-1]:
return long(float(size_str[:-1]))<<50
return long(float(size_str[:-1])) << 50
else:
return long(float(size_str))
@ -268,15 +165,15 @@ def instance(request, compute_id, vname):
if connection_manager.host_is_up(usr_inst.instance.compute.type,
usr_inst.instance.compute.hostname):
conn = wvmInstance(usr_inst.instance.compute,
usr_inst.instance.compute.login,
usr_inst.instance.compute.password,
usr_inst.instance.compute.type,
usr_inst.instance.name)
usr_inst.instance.compute.login,
usr_inst.instance.compute.password,
usr_inst.instance.compute.type,
usr_inst.instance.name)
cpu += int(conn.get_vcpu())
memory += int(conn.get_memory())
for disk in conn.get_disk_device():
if disk['size']:
disk_size += int(disk['size'])>>30
disk_size += int(disk['size']) >> 30
if ua.max_instances > 0 and instance > ua.max_instances:
msg = "instance"
@ -301,7 +198,7 @@ def instance(request, compute_id, vname):
dev_base = "vd"
else:
dev_base = "sd"
existing_devs = [ disk['dev'] for disk in disks ]
existing_devs = [disk['dev'] for disk in disks]
for l in string.lowercase:
dev = dev_base + l
if dev not in existing_devs:
@ -379,7 +276,7 @@ def instance(request, compute_id, vname):
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'])
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()
console_passwd = conn.get_console_passwd()
@ -453,7 +350,8 @@ def instance(request, compute_id, vname):
instance.delete()
try:
del_userinstance = UserInstance.objects.filter(instance__compute_id=compute_id, instance__name=vname)
del_userinstance = UserInstance.objects.filter(instance__compute_id=compute_id,
instance__name=vname)
del_userinstance.delete()
except UserInstance.DoesNotExist:
pass
@ -507,7 +405,8 @@ def instance(request, compute_id, vname):
msg = _("Please shutdown down your instance and then try again")
error_messages.append(msg)
if 'resize' in request.POST and (request.user.is_superuser or request.user.is_staff or userinstance.is_change):
if 'resize' in request.POST and (
request.user.is_superuser or request.user.is_staff or userinstance.is_change):
new_vcpu = request.POST.get('vcpu', '')
new_cur_vcpu = request.POST.get('cur_vcpu', '')
new_memory = request.POST.get('memory', '')
@ -521,12 +420,12 @@ def instance(request, compute_id, vname):
disks_new = []
for disk in disks:
input_disk_size = filesizefstr(request.POST.get('disk_size_' + disk['dev'], ''))
if input_disk_size > disk['size']+(64<<20):
if input_disk_size > disk['size'] + (64 << 20):
disk['size_new'] = input_disk_size
disks_new.append(disk)
disk_sum = sum([disk['size']>>30 for disk in disks_new])
disk_new_sum = sum([disk['size_new']>>30 for disk in disks_new])
quota_msg = check_user_quota(0, int(new_vcpu)-vcpu, int(new_memory)-memory, disk_new_sum-disk_sum)
disk_sum = sum([disk['size'] >> 30 for disk in disks_new])
disk_new_sum = sum([disk['size_new'] >> 30 for disk in disks_new])
quota_msg = check_user_quota(0, int(new_vcpu) - vcpu, int(new_memory) - memory, disk_new_sum - disk_sum)
if not request.user.is_superuser and quota_msg:
msg = _("User %s quota reached, cannot resize '%s'!" % (quota_msg, instance.name))
error_messages.append(msg)
@ -542,9 +441,9 @@ def instance(request, compute_id, vname):
if 'addvolume' in request.POST and (request.user.is_superuser or userinstance.is_change):
connCreate = wvmCreate(compute.hostname,
compute.login,
compute.password,
compute.type)
compute.login,
compute.password,
compute.type)
storage = request.POST.get('storage', '')
name = request.POST.get('name', '')
format = request.POST.get('format', default_format)
@ -705,7 +604,8 @@ def instance(request, compute_id, vname):
conn.change_network(network_data)
addlogmsg(request.user.username, instance.name, msg)
if conn.get_status() != 5: messages.success(request, _("Network Devices are changed. Please reboot instance to activate."))
msg = _("Network Devices are changed. Please reboot instance to activate.")
if conn.get_status() != 5: messages.success(request, msg)
return HttpResponseRedirect(request.get_full_path() + '#network')
if 'add_network' in request.POST:
@ -717,7 +617,9 @@ def instance(request, compute_id, vname):
conn.add_network(mac, source, source_type, nwfilter=nwfilter)
addlogmsg(request.user.username, instance.name, msg)
if conn.get_status() != 5: messages.success(request, _("Network Device is added. Please reboot instance to activate."))
msg = _("Network Device is added. Please reboot instance to activate.")
if conn.get_status() != 5: messages.success(request, msg)
return HttpResponseRedirect(request.get_full_path() + '#network')
if 'delete_network' in request.POST:
@ -726,7 +628,8 @@ def instance(request, compute_id, vname):
conn.delete_network(mac_address)
addlogmsg(request.user.username, instance.name, msg)
if conn.get_status() != 5: messages.success(request, _("Network Device is deleted. Please reboot instance to activate."))
msg = _("Network Device is deleted. Please reboot instance to activate.")
if conn.get_status() != 5: messages.success(request, msg)
return HttpResponseRedirect(request.get_full_path() + '#network')
if 'add_owner' in request.POST:
@ -755,13 +658,12 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#users')
if request.user.is_superuser or request.user.userattributes.can_clone_instances:
if 'clone' in request.POST:
clone_data = {}
clone_data['name'] = request.POST.get('name', '')
disk_sum = sum([disk['size']>>30 for disk in disks])
disk_sum = sum([disk['size'] >> 30 for disk in disks])
quota_msg = check_user_quota(1, vcpu, memory, disk_sum)
check_instance = Instance.objects.filter(name=clone_data['name'])
@ -786,14 +688,16 @@ def instance(request, compute_id, vname):
elif not re.match(r'^[a-zA-Z0-9-]+$', clone_data['name']):
msg = _("Instance name '%s' contains invalid characters!" % clone_data['name'])
error_messages.append(msg)
elif not re.match(r'^([0-9A-F]{2})(\:?[0-9A-F]{2}){5}$', clone_data['clone-net-mac-0'], re.IGNORECASE):
elif not re.match(r'^([0-9A-F]{2})(\:?[0-9A-F]{2}){5}$', clone_data['clone-net-mac-0'],
re.IGNORECASE):
msg = _("Instance mac '%s' invalid format!" % clone_data['clone-net-mac-0'])
error_messages.append(msg)
else:
new_uuid = conn.clone_instance(clone_data)
new_instance = Instance(compute_id=compute_id, name=clone_data['name'], uuid=new_uuid)
new_instance.save()
userinstance = UserInstance(instance_id=new_instance.id, user_id=request.user.id, is_delete=True)
userinstance = UserInstance(instance_id=new_instance.id, user_id=request.user.id,
is_delete=True)
userinstance.save()
msg = _("Clone of '%s'" % instance.name)
@ -801,7 +705,8 @@ def instance(request, compute_id, vname):
if settings.CLONE_INSTANCE_AUTO_MIGRATE:
new_compute = Compute.objects.order_by('?').first()
migrate_instance(new_compute, new_instance, xml_del=True, offline=True)
return HttpResponseRedirect(reverse('instance', args=[new_instance.compute.id, new_instance.name]))
return HttpResponseRedirect(
reverse('instance', args=[new_instance.compute.id, new_instance.name]))
if 'change_options' in request.POST:
instance.is_template = request.POST.get('is_template', False)
@ -851,6 +756,154 @@ def inst_status(request, compute_id, vname):
return response
def get_host_instances(request,comp):
def refresh_instance_database(comp, inst_name, info):
def get_userinstances_info(instance):
info = {}
uis = UserInstance.objects.filter(instance=instance)
info['count'] = uis.count()
if info['count'] > 0:
info['first_user'] = uis[0]
else:
info['first_user'] = None
return info
instances = Instance.objects.filter(name=inst_name)
if instances.count() > 1:
for i in instances:
user_instances_count = UserInstance.objects.filter(instance=i).count()
if user_instances_count == 0:
addlogmsg(request.user.username, i.name, _("Deleting due to multiple records."))
i.delete()
try:
inst_on_db = Instance.objects.get(compute_id=comp["id"], name=inst_name)
if inst_on_db.uuid != info['uuid']:
inst_on_db.save()
all_host_vms[comp["id"],
comp["name"],
comp["status"],
comp["cpu"],
comp["mem_size"],
comp["mem_perc"]][inst_name]['is_template'] = inst_on_db.is_template
all_host_vms[comp["id"],
comp["name"],
comp["status"],
comp["cpu"],
comp["mem_size"],
comp["mem_perc"]][inst_name]['userinstances'] = get_userinstances_info(inst_on_db)
except Instance.DoesNotExist:
inst_on_db = Instance(compute_id=comp["id"], name=inst_name, uuid=info['uuid'])
inst_on_db.save()
all_host_vms = {}
status = connection_manager.host_is_up(comp.type, comp.hostname)
if status:
conn = wvmHostDetails(comp, comp.login, comp.password, comp.type)
comp_node_info = conn.get_node_info()
comp_mem = conn.get_memory_usage()
comp_instances = conn.get_host_instances(True)
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()
return all_host_vms
def get_user_instances(request):
all_user_vms = {}
user_instances = UserInstance.objects.filter(user_id=request.user.id)
for usr_inst in user_instances:
if connection_manager.host_is_up(usr_inst.instance.compute.type,
usr_inst.instance.compute.hostname):
conn = wvmHostDetails(usr_inst.instance.compute,
usr_inst.instance.compute.login,
usr_inst.instance.compute.password,
usr_inst.instance.compute.type)
all_user_vms[usr_inst] = conn.get_user_instances(usr_inst.instance.name)
all_user_vms[usr_inst].update({'compute_id': usr_inst.instance.compute.id})
return all_user_vms
def instances_actions(request):
name = request.POST.get('name', '')
compute_id = request.POST.get('compute_id', '')
instance = Instance.objects.get(compute_id=compute_id, name=name)
conn = wvmInstances(instance.compute.hostname,
instance.compute.login,
instance.compute.password,
instance.compute.type)
if 'poweron' in request.POST:
msg = _("Power On")
addlogmsg(request.user.username, instance.name, msg)
conn.start(name)
return HttpResponseRedirect(request.get_full_path())
if 'poweroff' in request.POST:
msg = _("Power Off")
addlogmsg(request.user.username, instance.name, msg)
conn.shutdown(name)
return HttpResponseRedirect(request.get_full_path())
if 'powercycle' in request.POST:
msg = _("Power Cycle")
conn.force_shutdown(name)
conn.start(name)
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path())
if 'getvvfile' in request.POST:
msg = _("Send console.vv file")
addlogmsg(request.user.username, instance.name, msg)
response = HttpResponse(content='', content_type='application/x-virt-viewer', status=200, reason=None,
charset='utf-8')
response.writelines('[virt-viewer]\n')
response.writelines('type=' + conn.graphics_type(name) + '\n')
response.writelines('host=' + conn.graphics_listen(name) + '\n')
response.writelines('port=' + conn.graphics_port(name) + '\n')
response.writelines('title=' + conn.domain_name(name) + '\n')
response.writelines('password=' + conn.graphics_passwd(name) + '\n')
response.writelines('enable-usbredir=1\n')
response.writelines('disable-effects=all\n')
response.writelines('secure-attention=ctrl+alt+ins\n')
response.writelines('release-cursor=ctrl+alt\n')
response.writelines('fullscreen=1\n')
response.writelines('delete-this-file=1\n')
response['Content-Disposition'] = 'attachment; filename="console.vv"'
return response
if request.user.is_superuser:
if 'suspend' in request.POST:
msg = _("Suspend")
addlogmsg(request.user.username, instance.name, msg)
conn.suspend(name)
return HttpResponseRedirect(request.get_full_path())
if 'resume' in request.POST:
msg = _("Resume")
addlogmsg(request.user.username, instance.name, msg)
conn.resume(name)
return HttpResponseRedirect(request.get_full_path())
@login_required
def inst_graph(request, compute_id, vname):
"""

View file

@ -10,6 +10,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -12,6 +12,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -10,6 +10,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -11,6 +11,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -12,6 +12,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -12,6 +12,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -15,6 +15,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -16,6 +16,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li>

View file

@ -11,6 +11,9 @@
<li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li>
<li>
<i class="fa fa-server"></i> <a href="{% url 'instances' compute.id %}">{% trans "Instances" %}</a>
</li>
<li>
<i class="fa fa-hdd-o"></i> {% trans "Storages" %}
</li>

View file

@ -15,7 +15,7 @@
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li {% class_active request "^/instance" %}>
<a href="{% url 'instances' %}"><i class="fa fa-fw fa-desktop"></i> {% trans "Instances" %}</a>
<a href="{% url 'allinstances' %}"><i class="fa fa-fw fa-desktop"></i> {% trans "Instances" %}</a>
</li>
{% if request.user.is_superuser %}
<li {% class_active request "^/compute" %}{% class_active request "^/create" %}>

View file

@ -19,6 +19,7 @@ INSTALLED_APPS = (
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'dashboards',
'computes',
'console',
'networks',

View file

@ -1,36 +1,18 @@
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 instances.views import index
from console.views import console
from nwfilters.views import nwfilters, nwfilter
# from django.contrib import admin
urlpatterns = [
url(r'^$', index, name='index'),
url(r'^instances/$', instances, name='instances'),
url(r'^instance/', include('instances.urls')),
url(r'^instances/', include('instances.urls')),
url(r'^accounts/', include('accounts.urls')),
url(r'^computes/', include('computes.urls')),
url(r'^logs/', include('logs.urls')),
url(r'^datasource/', include('datasource.urls')),
url(r'^compute/(?P<compute_id>[0-9]+)/storages/$', 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]+)/networks/$', networks, name='networks'),
url(r'^compute/(?P<compute_id>[0-9]+)/network/(?P<pool>[\w\-\.]+)/$', network, name='network'),
url(r'^compute/(?P<compute_id>[0-9]+)/interfaces/$', interfaces, name='interfaces'),
url(r'^compute/(?P<compute_id>[0-9]+)/interface/(?P<iface>[\w\-\.\:]+)/$', interface, name='interface'),
url(r'^compute/(?P<compute_id>[0-9]+)/nwfilters/$', nwfilters, name='nwfilters'),
url(r'^compute/(?P<compute_id>[0-9]+)/nwfilter/(?P<nwfltr>[\w\-\.\:]+)/$', nwfilter, name='nwfilter'),
url(r'^compute/(?P<compute_id>[0-9]+)/secrets/$', secrets, name='secrets'),
url(r'^compute/(?P<compute_id>[0-9]+)/create/$', create_instance, name='create_instance'),
url(r'^console/$', console, name='console'),
# (r'^admin/', include(admin.site.urls)),