Commit df4f36a3 by Kálmán Viktor

dashboard: rework disk adding

parent 2fc3ff12
......@@ -17,7 +17,9 @@ from sizefield.widgets import FileSizeWidget
from firewall.models import Vlan, Host
from storage.models import Disk, DataStore
from vm.models import InstanceTemplate, Lease, InterfaceTemplate, Node
from vm.models import (
InstanceTemplate, Lease, InterfaceTemplate, Node, Instance
)
VLANS = Vlan.objects.all()
DISKS = Disk.objects.exclude(type="qcow2-snap")
......@@ -725,27 +727,59 @@ class LeaseForm(forms.ModelForm):
class DiskAddForm(forms.Form):
name = forms.CharField()
size = forms.CharField(widget=FileSizeWidget)
size = forms.CharField(widget=FileSizeWidget, required=False)
url = forms.CharField(required=False)
add_to = forms.CharField()
object_pk = forms.CharField()
def __init__(self, *args, **kwargs):
self.add_to = kwargs.pop("add_to")
self.object_pk = kwargs.pop("object_pk")
super(DiskAddForm, self).__init__(*args, **kwargs)
self.initial['add_to'] = self.add_to
self.initial['object_pk'] = self.object_pk
def clean_size(self):
size_in_bytes = self.cleaned_data.get("size")
if not size_in_bytes.isdigit():
if not size_in_bytes.isdigit() and len(size_in_bytes) > 0:
raise forms.ValidationError(_("Invalid format, you can use "
" GB or MB!"))
return size_in_bytes
def save(self, vm, commit=True):
def clean(self):
cleaned_data = self.cleaned_data
size = cleaned_data.get("size")
url = cleaned_data.get("url")
if not size and not url:
msg = _("You have to either specify size or URL")
self._errors[_("Global")] = self.error_class([msg])
return cleaned_data
def save(self, 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)
if data['size']:
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()
else:
# TODO
d = None
if self.add_to == "template":
vm_or_temp = InstanceTemplate.objects.get(pk=self.object_pk)
else:
vm_or_temp = Instance.objects.get(pk=self.object_pk)
vm_or_temp.disks.add(d)
return d
@property
......@@ -753,11 +787,23 @@ class DiskAddForm(forms.Form):
helper = FormHelper()
helper.form_show_labels = False
helper.layout = Layout(
Field("add_to", type="hidden"),
Field("object_pk", type="hidden"),
Field("name", placeholder=_("Name")),
Field("size", placeholder=_("Disk size (for example: 20GB, "
"1500MB)")),
Field("url", placeholder=_("URL to an ISO image")),
AnyTag(
"div",
HTML(
_("Either specify the size for an empty disk or a URL "
"to an ISO image!")
),
css_class="alert alert-info",
style="padding: 5px; text-align: justify;",
),
)
helper.add_input(Submit("submit", "Create new disk",
helper.add_input(Submit("submit", _("Add"),
css_class="btn btn-success"))
return helper
......
......@@ -64,8 +64,19 @@
</form>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="no-margin"><i class="icon-file"></i> {% trans "Create new disk" %}</h3>
</div>
<div class="panel-body">
<form action="{% url "dashboard.views.disk-add" %}" method="POST">
{% crispy disk_add_form %}
</form>
</div>
</div>
</div><!-- .col-md-4 -->
</div><!-- .row -->
<style>
......
......@@ -52,9 +52,12 @@
</a>
</div>
</h3>
<div class="row" id="vm-details-disk-add-for-form">
</div>
<div class="row" id="vm-details-disk-add-for-form"></div>
{% if not instance.disks.all %}
{% trans "No disks are added!" %}
{% endif %}
{% 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.id }}) - {{ d.size|filesize }}
......@@ -67,7 +70,7 @@
<div class="col-md-12">
<div>
<hr />
<form method="POST" action="" style="max-width: 300px;">
<form method="POST" action="{% url "dashboard.views.disk-add" %}" style="max-width: 350px;">
{% crispy forms.disk_add_form %}
</form>
<hr />
......
......@@ -9,7 +9,7 @@ from .views import (
FavouriteView, NodeStatus, GroupList, TemplateDelete, LeaseDelete,
VmGraphView, TemplateAclUpdateView, GroupDetailView, GroupDelete,
GroupAclUpdateView, GroupUserDelete, NotificationView, NodeGraphView,
VmMigrateView,
VmMigrateView, DiskAddView
)
urlpatterns = patterns(
......@@ -87,4 +87,7 @@ urlpatterns = patterns(
url(r'^notifications/$', NotificationView.as_view(),
name="dashboard.views.notifications"),
url(r'^disk/add$', DiskAddView.as_view(),
name="dashboard.views.disk-add"),
)
......@@ -20,7 +20,7 @@ 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.template.defaultfilters import title as title_filter
from django.template.loader import render_to_string
from django.forms.models import inlineformset_factory
......@@ -180,7 +180,9 @@ class VmDetailView(CheckedDetailView):
).all()
context['acl'] = get_vm_acl_data(instance)
context['forms'] = {
'disk_add_form': DiskAddForm(prefix="disk"),
'disk_add_form': DiskAddForm(
add_to="instance", object_pk=self.get_object().pk,
prefix="disk"),
}
context['os_type_icon'] = instance.os_type.replace("unknown",
"question")
......@@ -199,7 +201,6 @@ class VmDetailView(CheckedDetailView):
'port': self.__add_port,
'new_network_vlan': self.__new_network,
'save_as': self.__save_as,
'disk-name': self.__add_disk,
'shut_down': self.__shut_down,
'sleep': self.__sleep,
'wake_up': self.__wake_up,
......@@ -374,24 +375,6 @@ 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}))
def __shut_down(self, request):
self.object = self.get_object()
if not self.object.has_level(request.user, 'owner'):
......@@ -749,6 +732,11 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
def get_context_data(self, **kwargs):
context = super(TemplateDetail, self).get_context_data(**kwargs)
context['acl'] = get_vm_acl_data(self.get_object())
context['disk_add_form'] = DiskAddForm(
add_to="template",
object_pk=self.get_object().pk,
prefix="disk",
)
return context
def get_success_url(self):
......@@ -1718,3 +1706,31 @@ class VmMigrateView(SuperuserRequiredMixin, TemplateView):
messages.error(self.request, _("You didn't select a node!"))
return redirect("%s#activity" % vm.get_absolute_url())
class DiskAddView(SuperuserRequiredMixin, TemplateView):
def post(self, *args, **kwargs):
add_to = self.request.POST.get("disk-add_to")
object_pk = self.request.POST.get("disk-object_pk")
form = DiskAddForm(
self.request.POST,
add_to=add_to, object_pk=object_pk,
prefix="disk"
)
if form.is_valid():
messages.success(self.request, _("Disk successfully added!"))
form.save()
else:
error = "<br /> ".join(["<strong>%s</strong>: %s" %
(title_filter(i[0]), i[1][0])
for i in form.errors.items()])
messages.error(self.request, error)
if add_to == "template":
r = InstanceTemplate.objects.get(pk=object_pk).get_absolute_url()
else:
r = Instance.objects.get(pk=object_pk).get_absolute_url()
r = "%s#resources" % r
return redirect(r)
......@@ -152,6 +152,10 @@ class InstanceTemplate(AclBase, VirtualMachineDescModel, TimeStampedModel):
if is_new:
self.set_level(self.owner, 'owner')
@permalink
def get_absolute_url(self):
return ('dashboard.views.template-detail', None, {'pk': self.pk})
class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel):
......
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