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

move add new disk to instance disk tab. add existing disk option to attach disk. Small typo fixes

This commit is contained in:
catborise 2018-10-24 12:04:05 +03:00
parent ea5e9cfead
commit 03ffa3a295
5 changed files with 252 additions and 117 deletions

View file

@ -12,79 +12,150 @@
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">{% trans "Add Instance Volume" %}</h4> <h4 class="modal-title">{% trans "Add Instance Volume" %}</h4>
</div> </div>
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="modal-body">
<p style="font-weight:bold;">{% trans "Volume parameters" %}</p>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Storage" %}</label>
<div class="col-sm-4">
<select name="storage" class="form-control image-format">
{% for storage in storages %}
<option value="{{ storage }}">{{ storage }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Name" %}</label>
<div class="col-sm-4">
<input type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Format" %}</label>
<div class="col-sm-4">
<select name="format" 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 "Size" %}</label>
<div class="col-sm-4">
<input type="text" class="form-control" name="size" value="10" maxlength="3" required pattern="[0-9]+">
</div>
<label class="col-sm-1 control-label">{% trans "GB" %}</label>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Bus" %}</label>
<div class="col-sm-4">
<select name="bus" class="form-control image-format">
{% for bus in busses %}
<option value="{{ bus }}" {% if bus == default_bus %}selected{% endif %}>{% trans bus %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Cache" %}</label>
<div class="col-sm-4">
<select name="cache" class="form-control image-format">
{% for mode, name in cache_modes %}
<option value="{{ mode }}" {% if mode == default_cache %}selected{% endif %}>{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group meta-prealloc">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Metadata" %}</label>
<div class="col-sm-4">
<input type="checkbox" name="meta_prealloc" value="true">
</div>
</div>
</div>
<div class="modal-footer">
{% ifequal status 5 %}
<button type="submit" class="btn btn-lg btn-success pull-right" name="addvolume">{% trans "Add volume" %}</button>
{% else %}
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Add volume" %}</button>
{% endifequal %}
</div>
</form>
<div class="modal-body">
<div class="row">
<ul class="nav nav-tabs">
<li role="presentation" class="active"><a href="#NewDisk" data-toggle="tab">{% trans 'New Disk' %}</a></li>
<li role="presentation"><a href="#ExistingDisk" data-toggle="tab">{% trans 'Existing Disk' %}</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="NewDisk">
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<p style="font-weight:bold;">{% trans "Volume parameters" %}</p>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Storage" %}</label>
<div class="col-sm-4">
<select name="storage" class="form-control image-format">
{% for storage in storages %}
<option value="{{ storage }}">{{ storage }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Name" %}</label>
<div class="col-sm-4">
<input type="text" class="form-control" name="name" placeholder="{% trans "Name" %}" required pattern="[a-zA-Z0-9\.\-_]+">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Format" %}</label>
<div class="col-sm-4">
<select name="format" 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 "Size" %}</label>
<div class="col-sm-4">
<input type="text" class="form-control" name="size" value="10" maxlength="3" required pattern="[0-9]+">
</div>
<label class="col-sm-1 control-label">{% trans "GB" %}</label>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Bus" %}</label>
<div class="col-sm-4">
<select name="bus" class="form-control image-format">
{% for bus in busses %}
<option value="{{ bus }}" {% if bus == default_bus %}selected{% endif %}>{% trans bus %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Cache" %}</label>
<div class="col-sm-4">
<select name="cache" class="form-control image-format">
{% for mode, name in cache_modes %}
<option value="{{ mode }}" {% if mode == default_cache %}selected{% endif %}>{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group meta-prealloc">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Metadata" %}</label>
<div class="col-sm-4">
<input type="checkbox" name="meta_prealloc" value="true">
</div>
</div>
<div class="modal-footer">
{% ifequal status 5 %}
<button type="submit" class="btn btn-lg btn-success pull-right" name="addnewvol">{% trans "Add Volume" %}</button>
{% else %}
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Add Volume" %}</button>
{% endifequal %}
</div>
</form>
</div>
<div class="tab-pane" id="ExistingDisk">
<form class="form-horizontal" method="post" role="form">{% csrf_token %}
<div class="modal-body">
<p style="font-weight:bold;">{% trans "Volume parameters" %}</p>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Storage" %}</label>
<div class="col-sm-4">
<div class="dropdown">
<button class="btn dropdown-toggle" type="button" data-toggle="dropdown">{% trans 'Select Pool...' %}
<span class="caret"></span></button>
<ul class="dropdown-menu">
{% for storage in storages %}
<li><a href="#" onclick="get_volumes({{ compute_id }}, '{{ storage }}')">{{ storage }}</a></li>
{% endfor %}
</ul>
<input id="selected_storage" name="selected_storage" type="hidden" value=""/>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Volume" %}</label>
<div class="col-sm-4">
<select id="vols" name="vols" class="form-control" disabled>
<option value="" selected>{% trans 'None' %}</option>
<!-- populate with javascript -->
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Bus" %}</label>
<div class="col-sm-4">
<select name="bus" class="form-control image-format">
{% for bus in busses %}
<option value="{{ bus }}" {% if bus == default_bus %}selected{% endif %}>{% trans bus %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Cache" %}</label>
<div class="col-sm-4">
<select name="cache" class="form-control image-format">
{% for mode, name in cache_modes %}
<option value="{{ mode }}" {% if mode == default_cache %}selected{% endif %}>{% trans name %}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="modal-footer">
{% ifequal status 5 %}
<button type="submit" class="btn btn-lg btn-success pull-right" name="addexistingvol">{% trans "Add Volume" %}</button>
{% else %}
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Add Volume" %}</button>
{% endifequal %}
</div>
</form>
</div>
</div>
</div> <!-- row -->
</div> <!-- /.modal-body -->
</div> <!-- /.modal-content --> </div> <!-- /.modal-content -->
</div> <!-- /.modal-dialog --> </div> <!-- /.modal-dialog -->
</div> <!-- /.modal --> </div> <!-- /.modal -->

View file

@ -631,8 +631,8 @@
</div> </div>
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="disks"> <div role="tabpanel" class="tab-pane tab-pane-bordered" id="disks">
<p style="font-weight:bold;"> <p style="font-weight:bold;">
{% trans "Instance Volumes" %} {% trans "Instance Volumes" %}
{% include 'add_instance_volume.html' %} {% include 'add_instance_volume.html' %}
</p> </p>
<div class="col-xs-12 col-sm-12"> <div class="col-xs-12 col-sm-12">
@ -648,38 +648,39 @@
<th style="width:100px;">{% trans "Action" %}</th> <th style="width:100px;">{% trans "Action" %}</th>
</thead> </thead>
<tbody> <tbody>
{% for disk in disks %} {% for disk in disks %}
<tr> <tr>
<td>{{ disk.dev }}<br>{{ disk.target }}</td>
<td>{{ disk.format }}</td> <td>{{ disk.dev }}<br>{{ disk.target }}</td>
<td>{{ disk.used | filesizeformat}}</td> <td>{{ disk.format }}</td>
<td>{{ disk.size | filesizeformat }}</td> <td>{{ disk.used | filesizeformat}}</td>
<td>{{ disk.bus }}</td> <td>{{ disk.size | filesizeformat }}</td>
<td>{{ disk.storage }}</td> <td>{{ disk.bus }}</td>
<td>{{ disk.path }}</td> <td>{{ disk.storage }}</td>
<td style="width:30px;"> <td>{{ disk.path }}</td>
<form action="" method="post" style="height:10px" role="form">{% csrf_token %} <td style="width:30px;">
<input type="hidden" name="path" value="{{ disk.path }}"> <form action="" method="post" style="height:10px" role="form">{% csrf_token %}
<input type="hidden" name="dev" value="{{ disk.dev }}"> <input type="hidden" name="path" value="{{ disk.path }}">
{% ifequal status 5 %} <input type="hidden" name="dev" value="{{ disk.dev }}">
<button type="submit" class="btn btn-sm btn-default" name="detachvolume" title="{% trans "Detach" %}" onclick="return confirm('{% trans "Are you sure?" %}')"> {% ifequal status 5 %}
<i class="fa fa-eject"></i> <button type="submit" class="btn btn-sm btn-default" name="detachvolume" title="{% trans "Detach" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
</button> <i class="fa fa-eject"></i>
<button type="submit" class="btn btn-sm btn-default" name="delvolume" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')"> </button>
<i class="fa fa-trash"></i> <button type="submit" class="btn btn-sm btn-default" name="delvolume" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
</button> <i class="fa fa-trash"></i>
{% else %} </button>
<button class="btn btn-sm btn-default disabled" name="detachvolume" title="{% trans "Detach" %}"> {% else %}
<i class="fa fa-eject"></i> <button class="btn btn-sm btn-default disabled" name="detachvolume" title="{% trans "Detach" %}">
</button> <i class="fa fa-eject"></i>
<button class="btn btn-sm btn-default disabled" name="delvolume" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')"> </button>
<i class="fa fa-trash"></i> <button class="btn btn-sm btn-default disabled" name="delvolume" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')">
</button> <i class="fa fa-trash"></i>
{% endifequal %} </button>
</form> {% endifequal %}
</td> </form>
</tr> </td>
{% endfor %} </tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
@ -1227,6 +1228,39 @@
{% endblock %} {% endblock %}
{% block script %} {% block script %}
<script src="{% static "js/ace.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% static "js/ace.js" %}" type="text/javascript" charset="utf-8"></script>
<script>
function get_volumes(comp_id, pool) {
vol_params = comp_id + " " + pool;
vol_url = "/computes/" + comp_id + "/storage/" + pool + "/?get_volumes";
var select = document.getElementById("vols");
while (select.options.length){
select.removeChild(select.options[0]);
}
var input_sto = document.getElementById('selected_storage');
input_sto.value = pool;
$.getJSON(vol_url, function(data) {
if (data.length > 0) {
select.disabled = false;
}
var opt = document.createElement('option');
opt.value = '';
opt.innerHTML = 'None';
select.appendChild(opt);
for (i = 0; i < data.length; i++){
var opt = document.createElement('option');
opt.value = data[i]['name'];
opt.innerHTML = data[i]['name'];
select.appendChild(opt);
}
});
}
</script>
<script> <script>
var editor = ace.edit("editor"); var editor = ace.edit("editor");
editor.getSession().setMode("ace/mode/xml"); editor.getSession().setMode("ace/mode/xml");
@ -1238,13 +1272,13 @@
</script> </script>
<script> <script>
function open_console(view_style) { function open_console(view_style) {
window.open('{% url 'console' %}?token={{ compute_id }}-{{ uuid }}&view=' +view_style +'', '', 'width=850,height=600') window.open('{% url 'console' %}?token={{ compute_id }}-{{ uuid }}&view=' + view_style +'', '', 'width=850,height=600')
} }
</script> </script>
<script> <script>
function random_mac(net) { function random_mac(net) {
$.getJSON('{% url 'random_mac_address' %}', function (data) { $.getJSON('{% url 'random_mac_address' %}', function (data) {
$('input[name="'+net+'"]').val(data['mac']); $('input[name="' + net + '"]').val(data['mac']);
}); });
}; };
</script> </script>

View file

@ -20,6 +20,7 @@ from vrtManager.hostdetails import wvmHostDetails
from vrtManager.instance import wvmInstance, wvmInstances from vrtManager.instance import wvmInstance, wvmInstances
from vrtManager.connection import connection_manager from vrtManager.connection import connection_manager
from vrtManager.create import wvmCreate from vrtManager.create import wvmCreate
from vrtManager.storage import wvmStorage
from vrtManager.util import randomPasswd from vrtManager.util import randomPasswd
from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE
from logs.views import addlogmsg from logs.views import addlogmsg
@ -171,7 +172,7 @@ def instance(request, compute_id, vname):
usr_inst.instance.name) usr_inst.instance.name)
cpu += int(conn.get_vcpu()) cpu += int(conn.get_vcpu())
memory += int(conn.get_memory()) memory += int(conn.get_memory())
for disk in conn.get_disk_device(): for disk in conn.get_disk_devices():
if disk['size']: if disk['size']:
disk_size += int(disk['size']) >> 30 disk_size += int(disk['size']) >> 30
@ -255,8 +256,8 @@ def instance(request, compute_id, vname):
cur_memory = conn.get_cur_memory() cur_memory = conn.get_cur_memory()
title = conn.get_title() title = conn.get_title()
description = conn.get_description() description = conn.get_description()
disks = conn.get_disk_device() disks = conn.get_disk_devices()
media = conn.get_media_device() media = conn.get_media_devices()
if len(media) != 0: if len(media) != 0:
media_iso = sorted(conn.get_iso_media()) media_iso = sorted(conn.get_iso_media())
else: else:
@ -439,7 +440,7 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg) addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#resize') return HttpResponseRedirect(request.get_full_path() + '#resize')
if 'addvolume' in request.POST and (request.user.is_superuser or userinstance.is_change): if 'addnewvol' in request.POST and (request.user.is_superuser or userinstance.is_change):
connCreate = wvmCreate(compute.hostname, connCreate = wvmCreate(compute.hostname,
compute.login, compute.login,
compute.password, compute.password,
@ -459,6 +460,26 @@ def instance(request, compute_id, vname):
addlogmsg(request.user.username, instance.name, msg) addlogmsg(request.user.username, instance.name, msg)
return HttpResponseRedirect(request.get_full_path() + '#disks') return HttpResponseRedirect(request.get_full_path() + '#disks')
if 'addexistingvol' in request.POST and (request.user.is_superuser or userinstance.is_change):
storage = request.POST.get('selected_storage', '')
name = request.POST.get('vols', '')
bus = request.POST.get('bus', default_bus)
cache = request.POST.get('cache', default_cache)
connCreate = wvmStorage(compute.hostname,
compute.login,
compute.password,
compute.type,
storage)
format = connCreate.get_volume_type(name)
path = connCreate.get_target_path()
target = get_new_disk_dev(disks, bus)
source = path + "/" + name;
conn.attach_disk(source, target, subdriver=format, cache=cache, targetbus=bus)
return HttpResponseRedirect(request.get_full_path() + '#disks')
if 'delvolume' in request.POST and (request.user.is_superuser or userinstance.is_change): if 'delvolume' in request.POST and (request.user.is_superuser or userinstance.is_change):
connDelete = wvmCreate(compute.hostname, connDelete = wvmCreate(compute.hostname,
compute.login, compute.login,
@ -1056,7 +1077,7 @@ def _get_dhcp_mac_address(vname):
@login_required @login_required
def guess_mac_address(request, vname): def guess_mac_address(request, vname):
data = { 'vname': vname } data = {'vname': vname}
mac = _get_dhcp_mac_address(vname) mac = _get_dhcp_mac_address(vname)
if not mac: if not mac:
mac = _get_random_mac_address() mac = _get_random_mac_address()
@ -1100,7 +1121,7 @@ def guess_clone_name(request):
@login_required @login_required
def check_instance(request, vname): def check_instance(request, vname):
check_instance = Instance.objects.filter(name=vname) check_instance = Instance.objects.filter(name=vname)
data = { 'vname': vname, 'exists': False } data = {'vname': vname, 'exists': False}
if check_instance: if check_instance:
data['exists'] = True data['exists'] = True
return HttpResponse(json.dumps(data)) return HttpResponse(json.dumps(data))
@ -1119,6 +1140,7 @@ def get_clone_disk_name(disk, prefix, clone_name=''):
image = "{}-clone".format(disk['image']) image = "{}-clone".format(disk['image'])
return image return image
def _get_clone_disks(disks, vname=''): def _get_clone_disks(disks, vname=''):
clone_disks = [] clone_disks = []
for disk in disks: for disk in disks:
@ -1134,6 +1156,7 @@ def _get_clone_disks(disks, vname=''):
clone_disks.append(new_disk) clone_disks.append(new_disk)
return clone_disks return clone_disks
def sshkeys(request, vname): def sshkeys(request, vname):
""" """
:param request: :param request:

View file

@ -1,5 +1,5 @@
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect, HttpResponse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@ -8,6 +8,7 @@ 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 from django.contrib import messages
import json
@login_required @login_required
def storages(request, compute_id): def storages(request, compute_id):
@ -204,6 +205,12 @@ def storage(request, compute_id, pool):
else: else:
for msg_err in form.errors.values(): for msg_err in form.errors.values():
error_messages.append(msg_err.as_text()) error_messages.append(msg_err.as_text())
if request.method == 'GET':
if 'get_volumes' in request.GET:
conn.close()
return HttpResponse(json.dumps(sorted(volumes)))
conn.close() conn.close()
return render(request, 'storage.html', locals()) return render(request, 'storage.html', locals())

View file

@ -244,7 +244,7 @@ class wvmInstance(wvmConnect):
return util.get_xml_path(self._XMLDesc(0), func=networks) return util.get_xml_path(self._XMLDesc(0), func=networks)
def get_disk_device(self): def get_disk_devices(self):
def disks(doc): def disks(doc):
result = [] result = []
dev = None dev = None
@ -285,7 +285,7 @@ class wvmInstance(wvmConnect):
return util.get_xml_path(self._XMLDesc(0), func=disks) return util.get_xml_path(self._XMLDesc(0), func=disks)
def get_media_device(self): def get_media_devices(self):
def disks(doc): def disks(doc):
result = [] result = []
dev = None dev = None
@ -651,7 +651,7 @@ class wvmInstance(wvmConnect):
return iso return iso
def delete_all_disks(self): def delete_all_disks(self):
disks = self.get_disk_device() disks = self.get_disk_devices()
for disk in disks: for disk in disks:
vol = self.get_volume_by_path(disk.get('path')) vol = self.get_volume_by_path(disk.get('path'))
vol.delete(0) vol.delete(0)