1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2025-07-31 12:41:08 +00:00

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

Conflicts:
	instances/templates/instance.html
	instances/urls.py
	instances/views.py
This commit is contained in:
Ing. Jan KRCMAR 2018-08-21 09:50:29 +02:00
commit 01ace81c32
199 changed files with 34999 additions and 11154 deletions

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.13 on 2018-07-24 11:36
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('instances', '0003_instance_created'),
]
operations = [
migrations.AlterField(
model_name='instance',
name='name',
field=models.CharField(max_length=120),
),
]

View file

@ -3,8 +3,8 @@ from computes.models import Compute
class Instance(models.Model):
compute = models.ForeignKey(Compute)
name = models.CharField(max_length=20)
compute = models.ForeignKey(Compute, on_delete=models.CASCADE)
name = models.CharField(max_length=120)
uuid = models.CharField(max_length=36)
is_template = models.BooleanField(default=False)
created = models.DateField(auto_now_add=True)

View file

@ -13,7 +13,7 @@
<h4 class="modal-title">{% trans "Choose a compute for new instance" %}</h4>
</div>
<div class="modal-body">
<form class="form-horizontal" role="form">
<form class="form-horizontal" role="form"> {% csrf_token %}
<div class="form-group">
<label class="col-sm-4 control-label">{% trans "Compute" %}</label>
<div class="col-sm-6">

View file

@ -35,6 +35,8 @@
{{ disk.size|filesizeformat }} {% trans "Disk" %} |
{% endfor %}
<a href="{% url 'instance' compute.id vname %}" type="button" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"></span></a>
<em>on</em>
<a href="{% url 'overview' compute.id %}"><span class="label label-primary">{{ compute.name}} - {{ compute.hostname }} </span></a>
</div>
</div>
{% if user_quota_msg %}
@ -254,7 +256,19 @@
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="vnconsole">
<p>{% trans "This action opens a new window with a VNC connection to the console of the instance." %}</p>
{% ifequal status 1 %}
<a href="#" class="btn btn-lg btn-success pull-right" title="Console port: {{ console_port }}" onclick="open_console()">{% trans "Console" %}</a>
<!-- Split button -->
<div class="btn-group pull-right">
<button type="button" class="btn btn-lg btn-success " onclick="open_console('lite')">Console</button>
<button type="button" class="btn btn-lg btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a href="#" title="Console port: {{ console_port }}" onclick="open_console('lite')">{% trans "Console - Lite" %}</a></li>
<li><a href="#" title="Console port: {{ console_port }}" onclick="open_console('full')">{% trans "Console - Full" %}</a></li>
</ul>
</div>
{% else %}
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Console" %}</button>
{% endifequal %}
@ -332,7 +346,7 @@
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="resizevm">
{% if request.user.is_superuser or request.user.is_staff or userinstace.is_change %}
{% if request.user.is_superuser or request.user.is_staff or userinstance.is_change %}
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<p style="font-weight:bold;">{% trans "Logical host CPUs:" %} {{ vcpu_host }}</p>
<div class="form-group">
@ -410,7 +424,7 @@
<div class="clearfix"></div>
</div>
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="addvolume">
{% if request.user.is_superuser or userinstace.is_change %}
{% if request.user.is_superuser or userinstance.is_change %}
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<p style="font-weight:bold;">{% trans "Volume parameters" %}</p>
<div class="form-group">
@ -428,13 +442,6 @@
<div class="col-sm-4">
<input type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
<div class="col-sm-2">
<select name="extension" class="form-control image-format">
{% for format in formats %}
<option value="{{ format }}" {% if format == default_format %}selected{% endif %}>{% trans format %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Format" %}</label>
@ -602,7 +609,7 @@
</a>
</li>
{% endif %}
{% if request.user.is_superuser or userinstace.is_vnc %}
{% if request.user.is_superuser or userinstance.is_vnc %}
<li role="presentation">
<a href="#vncsettings" aria-controls="vncsettings" role="tab" data-toggle="tab">
{% trans "VNC" %}
@ -703,7 +710,7 @@
<div class="clearfix"></div>
</div>
{% endif %}
{% if request.user.is_superuser or userinstace.is_vnc %}
{% if request.user.is_superuser or userinstance.is_vnc %}
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="vncsettings">
<p>{% trans "To set console's type, shutdown the instance." %}</p>
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
@ -825,19 +832,29 @@
<p style="font-weight:bold;">{% trans "Network devices" %}</p>
{% for network in networks %}
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">eth{{ forloop.counter0 }}</label>
<div class="col-sm-4">
<label class="col-sm-3 control-label" style="font-weight:normal;">eth{{ forloop.counter0 }}({{ network.target|default:"no target" }})</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}"/>
</div>
<div class="col-sm-3">
<input type="text" class="form-control" name="net-source-{{ forloop.counter0 }}" value="{{ network.nic }}"/>
<input type="text" class="form-control" name="net-source-{{ forloop.counter0 }}" value="{{ network.nic }}" disabled/>
</div>
<div class="col-sm-3">
<select name="net-source-{{ forloop.counter0 }}" class="form-control" id="network_select" onchange="network_select_enable()">
{% for c_nets in compute_networks %}
{% if forloop.counter0 == 0 %}
<option value="{{ network.nic }}" selected hidden>{% trans "to Change" %}</option>
{% endif %}
<option value="{{ c_nets }}">{{ c_nets }}</option>
{% endfor %}
</select>
</div>
</div>
{% endfor %}
{% ifequal status 5 %}
<button type="submit" class="btn btn-lg btn-success pull-right" name="change_network">{% trans "Change" %}</button>
<button type="submit" class="btn btn-lg btn-success pull-right" id="ali" name="change_network" disabled>{% trans "Change" %}</button>
{% else %}
<button class="btn btn-lg btn-success pull-right disabled" name="change_network">{% trans "Change" %}</button>
<button type="submit"class="btn btn-lg btn-success pull-right" id="ali" name="change_network" disabled>{% trans "Change" %}</button>
{% endifequal %}
</form>
<div class="clearfix"></div>
@ -1167,7 +1184,7 @@
<div class="tab-content">
<div role="tabpanel" class="tab-pane tab-pane-bordered active" id="destroy">
<p>{% trans "Delete storage for instance?" %}</p>
{% if request.user.is_superuser or userinstace.is_delete %}
{% if request.user.is_superuser or userinstance.is_delete %}
{% ifequal status 3 %}
<button class="btn btn-lg btn-success disabled pull-right" name="delete">{% trans "Destroy" %}</button>
{% else %}
@ -1206,8 +1223,8 @@
});
</script>
<script>
function open_console() {
window.open('{% url 'console' %}?token={{ compute_id }}-{{ uuid }}', '', 'width=850,height=485')
function open_console(view_style) {
window.open('{% url 'console' %}?token={{ compute_id }}-{{ uuid }}&view=' +view_style +'', '', 'width=850,height=600')
}
</script>
<script>
@ -1344,6 +1361,16 @@
});
});
</script>
<script>
function network_select_enable(){
// set network button enabled
var selected = $('network_select').val();
if (selected != "to Change") {
$('button[name="change_network"]').removeAttr('disabled');
}
}
</script>
<script src="{% static "js/Chart.min.js" %}"></script>
<script>
$('#chartgraphs').on('shown.bs.tab', function (event) {

View file

@ -31,133 +31,23 @@
{% 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">×</button>
<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>#</th>
<th>Name<br>Description</th>
<th>User</th>
<th>Status</th>
<th>VCPU</th>
<th>Memory</th>
<th data-sortable="false" style="width:205px;">Actions & Mem Usage</th>
</tr>
</thead>
<tbody class="searchable">
{% 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 %}
<tr>
<td></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 %}
<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 style="text-align:center;">{{ info.vcpu }}</td>
<td style="text-align:right;">{{ 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>
{% 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">×</button>
<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>

View file

@ -0,0 +1,122 @@
{% load i18n %}
<table class="table table-hover table-striped sortable-theme-bootstrap">
<thead>
<tr>
<th>#</th>
<th>{% trans "Name" %}<br>{% trans "Description" %}</th></th>
<th>{% trans "User"%}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "VCPU" %}</th>
<th>{% trans "Memory" %}</th>
<th data-sortable="false" style="width:205px;">{% trans "Actions & Mem Usage" %}</th>
</tr>
</thead>
<tbody class="searchable">
{% for host, inst in all_host_vms.items %}
<tr class="active" style="font-weight: bold;border-bottom: 2px solid darkgray;border-top: 2px solid darkgray;">
<td><span class="fa fa-server"></span> </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 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 %}
<tr>
<td style="text-align: right">{{ forloop.counter }} </td>
<td>&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 %}<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 style="text-align:center;">{{ info.vcpu }}</td>
<td style="text-align:right;">{{ 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>

View file

@ -0,0 +1,92 @@
{% load i18n %}
<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>

View file

@ -2,20 +2,12 @@ from django.conf.urls import url
from . import views
urlpatterns = [
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'),
url(r'^random_mac_address/$',
views.random_mac_address, name='random_mac_address'),
url(r'^guess_mac_address/(?P<vname>[\w\-\.]+)/$',
views.guess_mac_address, name='guess_mac_address'),
url(r'^guess_clone_name/$',
views.guess_clone_name, name='guess_clone_name'),
url(r'^check_instance/(?P<vname>[\w\-\.]+)/$',
views.check_instance, name='check_instance'),
url(r'^sshkeys/(?P<vname>[\w\-\.]+)/$',
views.sshkeys, name='sshkeys'),
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'),
url(r'^guess_mac_address/(?P<vname>[\w\-\.]+)/$', views.guess_mac_address, name='guess_mac_address'),
url(r'^guess_clone_name/$', views.guess_clone_name, name='guess_clone_name'),
url(r'^random_mac_address/$', views.random_mac_address, name='random_mac_address'),
url(r'^check_instance/(?P<vname>[\w\-\.]+)/$', views.check_instance, name='check_instance'),
url(r'^sshkeys/(?P<vname>[\w\-\.]+)/$', views.sshkeys, name='sshkeys'),
]

View file

@ -24,6 +24,7 @@ from vrtManager.util import randomPasswd
from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE
from logs.views import addlogmsg
from django.conf import settings
from django.contrib import messages
@login_required
@ -46,7 +47,7 @@ def instances(request):
error_messages = []
all_host_vms = {}
all_user_vms = {}
computes = Compute.objects.all()
computes = Compute.objects.all().order_by("name")
def get_userinstances_info(instance):
info = {}
@ -72,18 +73,18 @@ def instances(request):
if check_uuid.uuid != info['uuid']:
check_uuid.save()
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)
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()
@ -192,6 +193,8 @@ def instances(request):
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())
@ -203,7 +206,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()
@ -213,14 +216,14 @@ def instance(request, compute_id, vname):
console_types = settings.QEMU_CONSOLE_TYPES
console_listen_addresses = settings.QEMU_CONSOLE_LISTEN_ADDRESSES
try:
userinstace = UserInstance.objects.get(instance__compute_id=compute_id,
userinstance = UserInstance.objects.get(instance__compute_id=compute_id,
instance__name=vname,
user__id=request.user.id)
except UserInstance.DoesNotExist:
userinstace = None
userinstance = None
if not request.user.is_superuser:
if not userinstace:
if not userinstance:
return HttpResponseRedirect(reverse('index'))
def show_clone_disk(disks, vname=''):
@ -325,7 +328,7 @@ def instance(request, compute_id, vname):
compute.password,
compute.type,
vname)
compute_networks = sorted(conn.get_networks())
status = conn.get_status()
autostart = conn.get_autostart()
vcpu = conn.get_vcpu()
@ -367,6 +370,8 @@ def instance(request, compute_id, vname):
default_cache = settings.INSTANCE_VOLUME_DEFAULT_CACHE
default_format = settings.INSTANCE_VOLUME_DEFAULT_FORMAT
formats = conn.get_image_formats()
busses = conn.get_busses()
default_bus = settings.INSTANCE_VOLUME_DEFAULT_BUS
show_access_root_password = settings.SHOW_ACCESS_ROOT_PASSWORD
@ -410,7 +415,7 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#powerforce')
if 'delete' in request.POST and (request.user.is_superuser or userinstace.is_delete):
if 'delete' in request.POST and (request.user.is_superuser or userinstance.is_delete):
if conn.get_status() == 1:
conn.force_shutdown()
if request.POST.get('delete_disk', ''):
@ -449,7 +454,7 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg)
if result['return'] == 'success':
messages.append(msg)
messages.success(request, msg)
else:
error_messages.append(msg)
else:
@ -471,14 +476,14 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg)
if result['return'] == 'success':
messages.append(msg)
messages.success(request, msg)
else:
error_messages.append(msg)
else:
msg = _("Please shutdow 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 userinstace.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', '')
@ -511,14 +516,13 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#resize')
if 'addvolume' in request.POST and (request.user.is_superuser or userinstace.is_change):
if 'addvolume' in request.POST and (request.user.is_superuser or userinstance.is_change):
connCreate = wvmCreate(compute.hostname,
compute.login,
compute.password,
compute.type)
storage = request.POST.get('storage', '')
name = request.POST.get('name', '')
extension = request.POST.get('extension', '')
format = request.POST.get('format', '')
size = request.POST.get('size', 0)
meta_prealloc = request.POST.get('meta_prealloc', False)
@ -526,7 +530,7 @@ def instance(request, compute_id, vname):
cache = request.POST.get('cache', '')
target = get_new_disk_dev(disks, bus)
path = connCreate.create_volume(storage, name, size, format, meta_prealloc, extension)
path = connCreate.create_volume(storage, name, size, format, meta_prealloc)
conn.attach_disk(path, target, subdriver=format, cache=cache, targetbus=bus)
msg = _('Attach new disk')
addlogmsg(request.user.username, instance.name, msg)
@ -567,7 +571,7 @@ def instance(request, compute_id, vname):
conn.snapshot_revert(snap_name)
msg = _("Successful revert snapshot: ")
msg += snap_name
messages.append(msg)
messages.success(request, msg)
msg = _("Revert snapshot")
addlogmsg(request.user.username, instance.name, msg)
@ -604,7 +608,7 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#xmledit')
if request.user.is_superuser or userinstace.is_vnc:
if request.user.is_superuser or userinstance.is_vnc:
if 'set_console_passwd' in request.POST:
if request.POST.get('auto_pass', ''):
passwd = randomPasswd()
@ -688,6 +692,8 @@ def instance(request, compute_id, vname):
conn.change_network(network_data)
msg = _("Edit network")
addlogmsg(request.user.username, instance.name, msg)
msg = _("Network Devices are changed. Please reboot instance to activate.")
messages.success(request, msg)
return HttpResponseRedirect(request.get_full_path() + '#network')
if 'add_owner' in request.POST:
@ -922,6 +928,7 @@ def inst_graph(request, compute_id, vname):
response.write(data)
return response
def _get_dhcp_mac_address(vname):
dhcp_file = '/srv/webvirtcloud/dhcpd.conf'
mac = ''
@ -936,6 +943,7 @@ def _get_dhcp_mac_address(vname):
break
return mac
@login_required
def guess_mac_address(request, vname):
data = { 'vname': vname }
@ -945,6 +953,7 @@ def guess_mac_address(request, vname):
data['mac'] = mac
return HttpResponse(json.dumps(data))
def _get_random_mac_address():
mac = '52:54:00:%02x:%02x:%02x' % (
random.randint(0x00, 0xff),
@ -953,12 +962,14 @@ def _get_random_mac_address():
)
return mac
@login_required
def random_mac_address(request):
data = {}
data['mac'] = _get_random_mac_address()
return HttpResponse(json.dumps(data))
@login_required
def guess_clone_name(request):
dhcp_file = '/srv/webvirtcloud/dhcpd.conf'
@ -975,6 +986,7 @@ def guess_clone_name(request):
return HttpResponse(json.dumps({'name': hostname}))
return HttpResponse(json.dumps({}))
@login_required
def check_instance(request, vname):
check_instance = Instance.objects.filter(name=vname)
@ -983,6 +995,7 @@ def check_instance(request, vname):
data['exists'] = True
return HttpResponse(json.dumps(data))
def sshkeys(request, vname):
"""
:param request:
@ -1004,6 +1017,7 @@ def sshkeys(request, vname):
response = json.dumps(instance_keys)
return HttpResponse(response)
def delete_instance(instance, delete_disk=False):
compute = instance.compute
instance_name = instance.name