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

Volumes list allocation info added. While creating image files it is recommended username and group name info. Storage.html does not show messages. messages section added

This commit is contained in:
catborise 2018-07-25 09:35:35 +03:00
parent 2585e64cfd
commit 4126ad2591
2 changed files with 218 additions and 210 deletions

View file

@ -6,220 +6,223 @@
<link rel="stylesheet" href="{% static "css/sortable-theme-bootstrap.css" %}" /> <link rel="stylesheet" href="{% static "css/sortable-theme-bootstrap.css" %}" />
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<!-- Page Heading --> <!-- Page Heading -->
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
{% include 'create_stg_vol_block.html' %} {% include 'create_stg_vol_block.html' %}
<h1 class="page-header">{% trans "Storage:" %} {{ pool }}</h1> <h1 class="page-header">{% trans "Storage:" %} {{ pool }}</h1>
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="active"> <li class="active">
<i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a> <i class="fa fa-dashboard"></i> <a href="{% url 'overview' compute.id %}">{% trans "Overview" %}</a>
</li> </li>
<li> <li>
<i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a> <i class="fa fa-hdd-o"></i> <a href="{% url 'storages' compute.id %}">{% trans "Storages" %}</a>
</li> </li>
<li> <li>
<i class="fa fa-sitemap"></i> <a href="{% url 'networks' compute.id %}">{% trans "Networks" %}</a> <i class="fa fa-sitemap"></i> <a href="{% url 'networks' compute.id %}">{% trans "Networks" %}</a>
</li> </li>
<li> <li>
<i class="fa fa-wifi"></i> <a href="{% url 'interfaces' compute.id %}">{% trans "Interfaces" %}</a> <i class="fa fa-wifi"></i> <a href="{% url 'interfaces' compute.id %}">{% trans "Interfaces" %}</a>
</li> </li>
<li> <li>
<i class="fa fa-key"></i> <a href="{% url 'secrets' compute.id %}">{% trans "Secrets" %}</a> <i class="fa fa-key"></i> <a href="{% url 'secrets' compute.id %}">{% trans "Secrets" %}</a>
</li> </li>
</ol> </ol>
</div> </div>
</div>
<!-- /.row -->
{% include 'errors_block.html' %}
{% include 'messages_block.html' %}
<div class="row">
<div class="col-xs-6 col-sm-6">
<p>{% trans "Pool name:" %}</p>
<p>{% trans "Pool type:" %}</p>
<p>{% trans "Pool path:" %}</p>
<p>{% trans "Pool status:" %}</p>
<p>{% trans "Size:" %} ({{ size|filesizeformat }} / {{ used|filesizeformat }})</p>
<p>{% trans "State:" %}</p>
<p>{% trans "Autostart:" %}</p>
</div>
<div class="col-xs-6 col-sm-6">
<p>{{ pool }}</p>
<p>{% if not type %}{% trans "None" %}{% else %}{{ type }}{% endif %}</p>
<p>{% if not path %}{% trans "None" %}{% else %}{{ path }}{% endif %}</p>
<p>{% if not status %}{% trans "None" %}{% else %}{{ status }}{% endif %}</p>
<p>{% trans "Usage:" %} {{ percent }}%</p>
<p>
<form action="" method="post" role="form">{% csrf_token %}
{% ifequal state 0 %}
<input type="submit" class="btn btn-xs btn-default" name="start" value="{% trans "Start" %}">
<input type="submit" class="btn btn-xs btn-default" name="delete" value="{% trans "Delete" %}"
onclick="return confirm('{% trans "Are you sure?" %}')">
{% else %}
<input type="submit" class="btn btn-xs btn-default" name="stop" value="{% trans "Stop" %}"
onclick="return confirm('{% trans "Are you sure?" %}')">
{% endifequal %}
</form>
</p>
<p>
<form action="" method="post" role="form">{% csrf_token %}
{% ifequal autostart 0 %}
<input type="submit" class="btn btn-xs btn-default" name="set_autostart"
value="{% trans "Enable" %}">
{% else %}
<input type="submit" class="btn btn-xs btn-default" name="unset_autostart"
onclick="return confirm('{% trans "Are you sure?" %}')" value="{% trans "Disable" %}">
{% endifequal %}
</form>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-12">
{% if state %}
<div class="row">
<div class="pull-right">
<input id="filter" class="form-control" type="text" placeholder="Search">
</div> </div>
<!-- /.row --> <h3 class="page-header">{% trans "Volumes" %}</h3>
{% include 'errors_block.html' %} </div>
{% if volumes %}
<div class="row"> <div class="table-responsive">
<div class="col-xs-6 col-sm-6"> <table class="table table-striped sortable-theme-bootstrap" data-sortable>
<p>{% trans "Pool name:" %}</p> <thead>
<p>{% trans "Pool type:" %}</p> <tr>
<p>{% trans "Pool path:" %}</p> <th style="width: 45px;">#</th>
<p>{% trans "Pool status:" %}</p> <th>{% trans "Name" %}</th>
<p>{% trans "Size:" %} ({{ size|filesizeformat }} / {{ used|filesizeformat }})</p> <th>{% trans "Allocated" %}</th>
<p>{% trans "State:" %}</p> <th>{% trans "Size" %}</th>
<p>{% trans "Autostart:" %}</p> <th>{% trans "Format" %}</th>
</div> <th data-sortable="false" colspan="2">{% trans "Action" %}</th>
<div class="col-xs-6 col-sm-6"> </tr>
<p>{{ pool }}</p> </thead>
<p>{% if not type %}{% trans "None" %}{% else %}{{ type }}{% endif %}</p> <tbody class="searchable">
<p>{% if not path %}{% trans "None" %}{% else %}{{ path }}{% endif %}</p> {% for volume in volumes %}
<p>{% if not status %}{% trans "None" %}{% else %}{{ status }}{% endif %}</p> <tr>
<p>{% trans "Usage:" %} {{ percent }}%</p> <td>{{ forloop.counter }}</td>
<p> <td>{{ volume.name }}</td>
<form action="" method="post" role="form">{% csrf_token %} <td>{{ volume.allocation|filesizeformat }}</td>
{% ifequal state 0 %} <td>{{ volume.size|filesizeformat }}</td>
<input type="submit" class="btn btn-xs btn-default" name="start" value="{% trans "Start" %}"> <td>{{ volume.type }}</td>
<input type="submit" class="btn btn-xs btn-default" name="delete" value="{% trans "Delete" %}" <td style="width:30px;">
onclick="return confirm('{% trans "Are you sure?" %}')"> <!-- Modal Clone -->
{% else %} <div class="modal fade" id="Clone{{ forloop.counter }}" tabindex="-1" role="dialog"
<input type="submit" class="btn btn-xs btn-default" name="stop" value="{% trans "Stop" %}" aria-labelledby="addHostLabel" aria-hidden="true">
onclick="return confirm('{% trans "Are you sure?" %}')"> <div class="modal-dialog">
{% endifequal %} <div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">{% trans "Clone image" %} <span class="text-danger">{{ volume.name }}</span></h4>
</div>
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="modal-body">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" required pattern="[a-zA-Z0-9\.\-_]+">
<input type="hidden" name="image" value="{{ volume.name }}">
</div>
<label class="col-sm-1 control-label">.img</label>
</div>
<div class="form-group" id="image_format">
<label class="col-sm-3 control-label">{% trans "Convert" %}</label>
<div class="col-sm-6">
<input class="volume-convert" type="checkbox" name="convert" value="true">
</div>
</div>
<div class="form-group format-convert">
<label class="col-sm-3 control-label">{% trans "Format" %}</label>
<div class="col-sm-6">
<select name="format" class="form-control image-format">
<option value="raw">{% trans "raw" %}</option>
<option value="qcow">{% trans "qcow" %}</option>
<option value="qcow2">{% trans "qcow2" %}</option>
</select>
</div>
</div>
<div class="form-group meta-prealloc" style="display: none;">
<label class="col-sm-3 control-label">{% trans "Metadata" %}</label>
<div class="col-sm-6">
<input type="checkbox" name="meta_prealloc" value="true">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
<button type="submit" class="btn btn-primary" name="cln_volume">{% trans "Clone" %}</button>
</div>
</form>
</div> <!-- /.modal-content -->
</div> <!-- /.modal-dialog -->
</div> <!-- /.modal -->
{% ifnotequal volume.type "iso" %}
<a data-toggle="modal" href="#Clone{{ forloop.counter }}" class="btn btn-sm btn-default" title="{% trans "Clone" %}"><i class="fa fa-files-o"></i></a>
{% else %}
<a class="btn btn-sm btn-default disabled"><i class="fa fa-files-o"></i></a>
{% endifnotequal %}
</td>
<td style="width:30px;">
<form action="" method="post" style="height:10px" role="form">{% csrf_token %}
<input type="hidden" name="volname" value="{{ volume.name }}">
<button type="submit" class="btn btn-sm btn-default" name="del_volume" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
<i class="fa fa-trash"></i>
</button>
</form> </form>
</p> </td>
<p> </tr>
<form action="" method="post" role="form">{% csrf_token %} {% endfor %}
{% ifequal autostart 0 %} </tbody>
<input type="submit" class="btn btn-xs btn-default" name="set_autostart" </table>
value="{% trans "Enable" %}"> </div>
{% else %} {% else %}
<input type="submit" class="btn btn-xs btn-default" name="unset_autostart" <div class="col-lg-12">
onclick="return confirm('{% trans "Are you sure?" %}')" value="{% trans "Disable" %}"> <div class="alert alert-warning alert-dismissable">
{% endifequal %} <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
</form> <i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "Hypervisor doesn't have any Volumes" %}
</p>
</div>
</div>
<div class="row">
<div class="col-lg-12">
{% if state %}
<div class="row">
<div class="pull-right">
<input id="filter" class="form-control" type="text" placeholder="Search">
</div>
<h3 class="page-header">{% trans "Volumes" %}</h3>
</div>
{% if volumes %}
<div class="table-responsive">
<table class="table table-striped sortable-theme-bootstrap" data-sortable>
<thead>
<tr>
<th style="width: 45px;">#</th>
<th>{% trans "Name" %}</th>
<th>{% trans "Size" %}</th>
<th>{% trans "Format" %}</th>
<th data-sortable="false" colspan="2">{% trans "Action" %}</th>
</tr>
</thead>
<tbody class="searchable">
{% for volume in volumes %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ volume.name }}</td>
<td>{{ volume.size|filesizeformat }}</td>
<td>{{ volume.type }}</td>
<td style="width:30px;">
<!-- Modal Clone -->
<div class="modal fade" id="Clone{{ forloop.counter }}" tabindex="-1" role="dialog"
aria-labelledby="addHostLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">{% trans "Clone image" %} <span class="text-danger">{{ volume.name }}</span></h4>
</div>
<div class="modal-body">
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" required pattern="[a-zA-Z0-9\.\-_]+">
<input type="hidden" name="image" value="{{ volume.name }}">
</div>
<label class="col-sm-1 control-label">.img</label>
</div>
<div class="form-group" id="image_format">
<label class="col-sm-3 control-label">{% trans "Convert" %}</label>
<div class="col-sm-6">
<input class="volume-convert" type="checkbox" name="convert" value="true">
</div>
</div>
<div class="form-group format-convert">
<label class="col-sm-3 control-label">{% trans "Format" %}</label>
<div class="col-sm-6">
<select name="format" class="form-control image-format">
<option value="raw">{% trans "raw" %}</option>
<option value="qcow">{% trans "qcow" %}</option>
<option value="qcow2">{% trans "qcow2" %}</option>
</select>
</div>
</div>
<div class="form-group meta-prealloc" style="display: none;">
<label class="col-sm-3 control-label">{% trans "Metadata" %}</label>
<div class="col-sm-6">
<input type="checkbox" name="meta_prealloc" value="true">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
<button type="submit" class="btn btn-primary" name="cln_volume">{% trans "Clone" %}</button>
</div>
</form>
</div> <!-- /.modal-content -->
</div> <!-- /.modal-dialog -->
</div> <!-- /.modal -->
{% ifnotequal volume.type "iso" %}
<a data-toggle="modal" href="#Clone{{ forloop.counter }}" class="btn btn-sm btn-default" title="{% trans "Clone" %}"><i class="fa fa-files-o"></i></a>
{% else %}
<a class="btn btn-sm btn-default disabled"><i class="fa fa-files-o"></i></a>
{% endifnotequal %}
</td>
<td style="width:30px;">
<form action="" method="post" style="height:10px" role="form">{% csrf_token %}
<input type="hidden" name="volname" value="{{ volume.name }}">
<button type="submit" class="btn btn-sm btn-default" name="del_volume" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
<i class="fa fa-trash"></i>
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="col-lg-12">
<div class="alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<i class="fa fa-exclamation-triangle"></i> <strong>{% trans "Warning:" %}</strong> {% trans "Hypervisor doesn't have any Volumes" %}
</div>
</div>
{% endif %}
{% endif %}
</div>
</div> </div>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% endblock %} {% endblock %}
{% block script %} {% block script %}
<script src="{% static "js/sortable.min.js" %}"></script> <script src="{% static "js/sortable.min.js" %}"></script>
<script> <script>
$('.format-convert').hide(); $('.format-convert').hide();
$(document).on('change', '.volume-convert', function () { $(document).on('change', '.volume-convert', function () {
if ($(this).prop('checked')) { if ($(this).prop('checked')) {
$('.format-convert').show(); $('.format-convert').show();
if ($('.image-format').val() == 'qcow2') { if ($('.image-format').val() == 'qcow2') {
$('.meta-prealloc').show(); $('.meta-prealloc').show();
}
} else {
$('.format-convert').hide();
$('.meta-prealloc').hide();
} }
} else { });
$('.format-convert').hide(); $(document).on('change', '.image-format', function () {
$('.meta-prealloc').hide(); if ($(this).val() == "qcow2") {
} $('.meta-prealloc').show();
}); } else {
$(document).on('change', '.image-format', function () { $('.meta-prealloc').hide();
if ($(this).val() == "qcow2") { }
$('.meta-prealloc').show(); });
} else { </script>
$('.meta-prealloc').hide(); <script>
} $(document).ready(function () {
}); (function ($) {
</script> $('#filter').keyup(function () {
<script> var rex = new RegExp($(this).val(), 'i');
$(document).ready(function () { $('.searchable tr').hide();
(function ($) { $('.searchable tr').filter(function () {
$('#filter').keyup(function () { return rex.test($(this).text());
var rex = new RegExp($(this).val(), 'i'); }).show();
$('.searchable tr').hide(); })
$('.searchable tr').filter(function () { }(jQuery));
return rex.test($(this).text()); });
}).show(); </script>
})
}(jQuery));
});
</script>
{% endblock %} {% endblock %}

View file

@ -7,7 +7,7 @@ from computes.models import Compute
from storages.forms import AddStgPool, AddImage, CloneImage from storages.forms import AddStgPool, AddImage, CloneImage
from vrtManager.storage import wvmStorage, wvmStorages from vrtManager.storage import wvmStorage, wvmStorages
from libvirt import libvirtError from libvirt import libvirtError
from django.contrib import messages
@login_required @login_required
def storages(request, compute_id): def storages(request, compute_id):
@ -155,6 +155,7 @@ def storage(request, compute_id, pool):
meta_prealloc = True meta_prealloc = True
try: try:
conn.create_volume(data['name'], data['size'], data['format'], meta_prealloc) conn.create_volume(data['name'], data['size'], data['format'], meta_prealloc)
messages.success("Image file {} is created successfully".format(data['name']+".img"))
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
except libvirtError as lib_err: except libvirtError as lib_err:
error_messages.append(lib_err) error_messages.append(lib_err)
@ -166,6 +167,7 @@ def storage(request, compute_id, pool):
try: try:
vol = conn.get_volume(volname) vol = conn.get_volume(volname)
vol.delete(0) vol.delete(0)
messages.success(request,_('Volume: {} is deleted.'.format(volname)))
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
except libvirtError as lib_err: except libvirtError as lib_err:
error_messages.append(lib_err.message) error_messages.append(lib_err.message)
@ -175,6 +177,7 @@ def storage(request, compute_id, pool):
error_messages.append(error_msg) error_messages.append(error_msg)
else: else:
handle_uploaded_file(path, request.FILES['file']) handle_uploaded_file(path, request.FILES['file'])
messages.success(request, _('ISO: {} is uploaded.'.format(request.FILES['file'])))
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
if 'cln_volume' in request.POST: if 'cln_volume' in request.POST:
form = CloneImage(request.POST) form = CloneImage(request.POST)
@ -194,6 +197,8 @@ def storage(request, compute_id, pool):
format = None format = None
try: try:
conn.clone_volume(data['image'], data['name'], format, meta_prealloc) conn.clone_volume(data['image'], data['name'], format, meta_prealloc)
messages.success(request, _("{} image cloned as {} successfully".format(data['image'],
data['name'] + ".img")))
return HttpResponseRedirect(request.get_full_path()) return HttpResponseRedirect(request.get_full_path())
except libvirtError as lib_err: except libvirtError as lib_err:
error_messages.append(lib_err) error_messages.append(lib_err)