Commit 4ce5d3d5 by Kálmán Viktor

dashboard: add disk to instances

parent 0a3fc812
from datetime import timedelta
import uuid
from crispy_forms.helper import FormHelper
from crispy_forms.layout import (
......@@ -10,9 +11,10 @@ from django.forms.widgets import TextInput
from django.template import Context
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from sizefield.widgets import FileSizeWidget
from firewall.models import Vlan, Host
from storage.models import Disk
from storage.models import Disk, DataStore
from vm.models import InstanceTemplate, Lease, InterfaceTemplate, Node
......@@ -695,6 +697,45 @@ class LeaseForm(forms.ModelForm):
model = Lease
class DiskAddForm(forms.Form):
name = forms.CharField()
size = forms.CharField(widget=FileSizeWidget)
def clean_size(self):
size_in_bytes = self.cleaned_data.get("size")
if not size_in_bytes.isdigit():
raise forms.ValidationError(_("Invalid format, you can use "
" GB or MB!"))
return size_in_bytes
def save(self, vm, commit=True):
data = self.cleaned_data
d = Disk(
name=data['name'],
filename=str(uuid.uuid4()),
datastore=DataStore.objects.all()[0],
type="qcow2-norm",
size=data['size'],
dev_num="a",
)
d.save()
vm.disks.add(d)
return d
@property
def helper(self):
helper = FormHelper()
helper.form_show_labels = False
helper.layout = Layout(
Field("name", placeholder=_("Name")),
Field("size", placeholder=_("Disk size (for example: 20GB, "
"1500MB)")),
)
helper.add_input(Submit("submit", "Create new disk",
css_class="btn btn-success"))
return helper
class LinkButton(BaseInput):
"""
......
......@@ -145,6 +145,12 @@ $(function() {
$('input[name="new_network_managed"]').tooltip();
return false;
});
/* add disk button */
$("#vm-details-disk-add").click(function() {
$("#vm-details-disk-add-for-form").html($("#vm-details-disk-add-form").html());
return false;
});
});
......
......@@ -41,7 +41,7 @@
{% for message in messages %}
<div class="alert
{% if message.tags %} alert-{% if message.tags == "error" %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}">
{{ message }}
{{ message|safe }}
</div>
{% endfor %}
{% endif %}
......
{% load i18n %}
{% load sizefieldtags %}
{% load crispy_forms_tags %}
<form id="vm-details-resources-form" method="POST" action="">
{% csrf_token %}
<p class="row">
......@@ -36,8 +39,45 @@
</div>
</p>
</form>
<hr />
<div class="row">
<div class="col-sm-11">
<h3>
{% trans "Disks" %}
<div class="pull-right">
<a href="#" id="vm-details-disk-add" class="btn btn-success btn-xs">
<i class="icon-plus"></i> {% trans "Add new disk" %}
</a>
</div>
</h3>
<div class="row" id="vm-details-disk-add-for-form">
</div>
{% for d in instance.disks.all %}
<h4 class="list-group-item-heading dashboard-vm-details-network-h3">
<i class="icon-file"></i> {{ d.name }} - {{ d.size|filesize }}
</h4>
{% endfor %}
</div>
</div>
<div class="js-hidden row" id="vm-details-disk-add-form">
<div class="col-md-12">
<div>
<hr />
<form method="POST" action="" style="max-width: 300px;">
{% crispy forms.disk_add_form %}
</form>
<hr />
</div>
</div>
</div>
{% block extra_js %}
<style>
label {padding-top: 6px;}
.form-group {margin-bottom: 8px;}
</style>
{% endblock %}
......@@ -202,3 +202,25 @@ class VmDetailTest(TestCase):
# redirect to the login page
self.assertEqual(response.status_code, 302)
self.assertEqual(leases, Lease.objects.count())
def test_unpermitted_vm_disk_add(self):
c = Client()
self.login(c, "user2")
inst = Instance.objects.get(pk=1)
inst.set_level(self.u1, 'owner')
disks = inst.disks.count()
response = c.post("/dashboard/vm/1/", {'disk-name': "a",
'disk-size': 1})
self.assertEqual(response.status_code, 403)
self.assertEqual(disks, inst.disks.count())
def test_permitted_vm_disk_add(self):
c = Client()
self.login(c, "user1")
inst = Instance.objects.get(pk=1)
inst.set_level(self.u1, 'owner')
disks = inst.disks.count()
response = c.post("/dashboard/vm/1/", {'disk-name': "a",
'disk-size': 1})
self.assertEqual(response.status_code, 302)
self.assertEqual(disks + 1, inst.disks.count())
......@@ -19,12 +19,15 @@ from django.views.generic import (TemplateView, DetailView, View, DeleteView,
UpdateView, CreateView)
from django.contrib import messages
from django.utils.translation import ugettext as _
from django.template.defaultfilters import title
from django.forms.models import inlineformset_factory
from django_tables2 import SingleTableView
from braces.views import LoginRequiredMixin, SuperuserRequiredMixin
from .forms import VmCreateForm, TemplateForm, LeaseForm, NodeForm, HostForm
from .forms import (
VmCreateForm, TemplateForm, LeaseForm, NodeForm, HostForm, DiskAddForm,
)
from .tables import (VmListTable, NodeListTable, NodeVmListTable,
TemplateListTable, LeaseListTable, GroupListTable)
from vm.models import (Instance, InstanceTemplate, InterfaceTemplate,
......@@ -150,6 +153,9 @@ class VmDetailView(CheckedDetailView):
context['vlans'] = Vlan.get_objects_with_level(
'user', self.request.user).all()
context['acl'] = get_acl_data(instance)
context['forms'] = {
'disk_add_form': DiskAddForm(prefix="disk"),
}
return context
def post(self, request, *args, **kwargs):
......@@ -165,6 +171,7 @@ class VmDetailView(CheckedDetailView):
'port': self.__add_port,
'new_network_vlan': self.__new_network,
'save_as': self.__save_as,
'disk-name': self.__add_disk,
}
for k, v in options.iteritems():
......@@ -333,6 +340,24 @@ class VmDetailView(CheckedDetailView):
return redirect(reverse_lazy("dashboard.views.template-detail",
kwargs={'pk': template.pk}))
def __add_disk(self, request):
self.object = self.get_object()
if not self.object.has_level(request.user, 'owner'):
raise PermissionDenied()
form = DiskAddForm(request.POST, prefix="disk")
if form.is_valid():
messages.success(request, _("New disk successfully created!"))
form.save(self.object)
else:
error = "<br /> ".join(["<strong>%s</strong>: %s" %
(title(i[0]), i[1][0])
for i in form.errors.items()])
messages.error(request, error)
return redirect("%s#resources" % reverse_lazy(
"dashboard.views.detail", kwargs={'pk': self.object.pk}))
class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView):
template_name = "dashboard/node-detail.html"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment