Commit 8fd80cf1 by Oláh István Gergely

dashboard: add node create form

parent e029a56b
from datetime import timedelta
from django import forms
from vm.models import InstanceTemplate, Lease, InterfaceTemplate
from vm.models import InstanceTemplate, Lease, InterfaceTemplate, Node
from storage.models import Disk
from firewall.models import Vlan
# from django.core.urlresolvers import reverse_lazy
from firewall.models import Vlan, Host
from crispy_forms.helper import FormHelper
from crispy_forms.layout import (Layout, Div, BaseInput,
Field, HTML, Submit, Fieldset)
......@@ -13,8 +11,12 @@ from crispy_forms.utils import render_field
from django.template import Context
from django.template.loader import render_to_string
from django.forms.widgets import TextInput
from django.forms import ModelForm
from crispy_forms.bootstrap import FormActions
from django.forms.models import BaseInlineFormSet
from django.utils.translation import ugettext as _
# from crispy_forms.bootstrap import FormActions
VLANS = Vlan.objects.all()
......@@ -292,6 +294,169 @@ class VmCreateForm(forms.Form):
)
class HostForm(forms.ModelForm):
def setowner(self, user):
self.instance.owner = user
def __init__(self, *args, **kwargs):
super(HostForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper.form_tag = False
self.helper.layout = Layout(
Div(
Div( # host
Div(
AnyTag(
'h3',
HTML(_("Host")),
),
css_class="col-sm-3",
),
css_class="row",
),
Div( # host data
Div( # hostname
HTML('<label for="node-hostname-box">'
'Name'
'</label>'),
css_class="col-sm-3",
),
Div( # hostname
'hostname',
css_class="col-sm-9",
),
Div( # mac
HTML('<label for="node-mac-box">'
'MAC'
'</label>'),
css_class="col-sm-3",
),
Div(
'mac',
css_class="col-sm-9",
),
Div( # ip
HTML('<label for="node-ip-box">'
'IP'
'</label>'),
css_class="col-sm-3",
),
Div(
'ipv4',
css_class="col-sm-9",
),
Div( # vlan
HTML('<label for="node-vlan-box">'
'VLAN'
'</label>'),
css_class="col-sm-3",
),
Div(
'vlan',
css_class="col-sm-9",
),
css_class="row",
),
),
)
class Meta:
model = Host
fields = ['hostname', 'vlan', 'mac', 'ipv4', ]
class NodeForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(NodeForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper.layout = Layout(
Div(
Div(
Div(
Div(
AnyTag(
'h3',
HTML(_("Node")),
),
css_class="col-sm-3",
),
css_class="row",
),
Div(
Div( # nodename
HTML('<label for="node-nodename-box">'
'Name'
'</label>'),
css_class="col-sm-3",
),
Div(
'name',
css_class="col-sm-9",
),
css_class="row",
),
Div(
Div( # priority
HTML('<label for="node-nodename-box">'
'Priority'
'</label>'),
css_class="col-sm-3",
),
Div(
'priority',
css_class="col-sm-9",
),
css_class="row",
),
Div(
Div( # enabled
HTML('<label for="node-nodename-box">'
'Enabled'
'</label>'),
css_class="col-sm-3",
),
Div(
'enabled',
css_class="col-sm-9",
),
css_class="row",
),
Div( # nested host
HTML("""{% load crispy_forms_tags %}
{% crispy hostform %}
""")
),
Div(
Div(
AnyTag( # tip: don't try to use Button class
"button",
AnyTag(
"i",
css_class="icon-play"
),
HTML("Start"),
css_id="node-create-submit",
css_class="btn btn-success",
),
css_class="col-sm-12 text-right",
),
css_class="row",
),
css_class="col-sm-11",
),
css_class="row",
),
)
class Meta:
model = Node
fields = ['name', 'priority', 'enabled', ]
class TemplateForm(forms.ModelForm):
managed_networks = forms.ModelMultipleChoiceField(
queryset=VLANS, required=False)
......
......@@ -7,9 +7,9 @@ $(function () {
$('body').append(data);
vmCreateLoaded();
addSliderMiscs();
$('#vm-create-modal').modal('show');
$('#vm-create-modal').on('hidden.bs.modal', function() {
$('#vm-create-modal').remove();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
});
}
});
......@@ -24,9 +24,9 @@ $(function () {
$('body').append(data);
nodeCreateLoaded();
addSliderMiscs();
$('#node-create-modal').modal('show');
$('#node-create-modal').on('hidden.bs.modal', function() {
$('#node-create-modal').remove();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
});
}
});
......
......@@ -181,13 +181,13 @@ function vmCreateLoaded() {
window.location.replace(data.redirect + '#activity');
}
else {
var r = $('#vm-create-modal'); r.next('div').remove(); r.remove();
var r = $('#create-modal'); r.next('div').remove(); r.remove();
$('body').append(data);
vmCreateLoaded();
addSliderMiscs();
$('#vm-create-modal').modal('show');
$('#vm-create-modal').on('hidden.bs.modal', function() {
$('#vm-create-modal').remove();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
});
}
},
......
<div class="modal fade" id="vm-create-modal" tabindex="-1" role="dialog">
<div class="modal fade" id="create-modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
......
{% load crispy_forms_tags %}
<style>
.row {
margin-bottom: 15px;
}
</style>
<form method="POST" action="/dashboard/vm/create/">
{% csrf_token %}
<div class="row">
<div class="col-sm-5">
<a class="btn btn-info vm-create-advanced-btn">Advanced <i class="vm-create-advanced-icon icon-caret-down"></i></a>
</div>
<div class="col-sm-5 text-right">
<button id="vm-create-submit" type="submit" class="btn btn-success "><i class="icon-play"></i> Start</button>
</div>
</div>
<div class="vm-create-advanced">
<div class="row">
<div class="col-sm-12">
<h2>Resources</h2>
</div>
<p class="row">
<div class="col-sm-3">
<label for="vm-cpu-priority-slider"><i class="icon-trophy"></i> CPU priority</label>
</div>
<div class="col-sm-9">
<input name="cpu-priority" type="text" id="vm-cpu-priority-slider" class="vm-slider" value="20" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="20" data-slider-orientation="horizontal" data-slider-handle="square" data-slider-tooltip="hide"/>
</div>
</p>
<p class="row">
<div class="col-sm-3">
<label for="cpu-count-slider"><i class="icon-cogs"></i> CPU count</label>
</div>
<div class="col-sm-9">
<input name="cpu-count" type="text" id="vm-cpu-count-slider" class="vm-slider" value="2" data-slider-min="0" data-slider-max="8" data-slider-step="1" data-slider-value="2" data-slider-orientation="horizontal" data-slider-handle="square" data-slider-tooltip="hide"/>
</div>
</p>
<p class="row">
<div class="col-sm-3">
<label for="ram-slider"><i class="icon-ticket"></i> RAM amount</label>
</div>
<div class="col-sm-9">
<input name="ram-size" type="text" id="vm-ram-size-slider" class="vm-slider" value="512" data-slider-min="128" data-slider-max="4096" data-slider-step="128" data-slider-value="512" data-slider-orientation="horizontal" data-slider-handle="square" data-slider-tooltip="hide"/> MiB
</div>
</p>
</div>
<!-- disk -->
<div class="row">
<div class="col-sm-4">
<h2>Disks</h2>
</div>
<div class="col-sm-8" style="padding-top: 3px;">
<div class="js-hidden" style="padding-top: 15px; max-width: 450px;">
<select class="form-control" id="vm-create-disk-add-form" multiple name="disks">
{% for d in disks %}
<option value="{{ d.pk }}">{{ d.name }}</option>
{% endfor %}
</select>
</div>
<div class="no-js-hidden">
<h3 id="vm-create-disk-list">
No disks are added!
</h3>
<h3 id="vm-create-disk-add">
<div class="input-group" style="max-width: 330px;">
<select class="form-control" id="vm-create-disk-add-select">
<!-- options should be copied via js from above -->
</select>
<div class="input-group-btn">
<!--<input type="submit" value="Add to network" class="btn btn-success"/>-->
<a href="#" id="vm-create-disk-add-button" class="btn btn-success"><i class="icon-plus-sign"></i></a>
</div>
</div>
</h3>
</div>
</div>
</div>
<!-- network -->
<div class="row">
<div class="col-sm-4">
<h2>Network</h2>
</div>
<style>
/* temporary inline css for dev */
a.hover-black {
color:white;
}
.hover-black:hover {
color: black /*#d9534f*/;
text-decoration: none;
}
.no-js-hidden {
display: none;
}
</style>
<div class="col-sm-8" style="padding-top: 3px;">
<div class="js-hidden" style="padding-top: 15px; max-width: 450px;">
<h4>Managed networks</h4>
<select class="form-control" id="vm-create-network-add-managed" multiple name="managed-vlans">
{% for v in vlans %}
<option value="{{ v.pk }}">{{ v.name }}</option>
{% endfor %}
</select>
<h4>Unmanaged networks</h4>
<select class="form-control" id="vm-create-network-add-unmanaged" multiple name="unmanaged-vlans">
{% for v in vlans %}
<option value="{{ v.pk }}">{{ v.name }}</option>
{% endfor %}
</select>
</div>
<div class="no-js-hidden">
<h3 id="vm-create-network-list">
Not added to any network!
</h3>
<h3 id="vm-create-network-add">
<div class="input-group" style="max-width: 330px;">
<select class="form-control" id="vm-create-network-add-select">
<!-- options should be copied via js from above -->
</select>
<span class="input-group-addon">
<input id="vm-create-network-add-checkbox-managed" type="checkbox" title data-original-title="Managed network?" style="-webkit-transform: scale(1.4, 1.4); margin-top: 4px;" checked/>
</span>
<div class="input-group-btn">
<!--<input type="submit" value="Add to network" class="btn btn-success"/>-->
<a href="#" id="vm-create-network-add-button" class="btn btn-success"><i class="icon-plus-sign"></i></a>
</div>
</div>
</h3>
</div>
</div>
</div>
</div>
<form method="POST" action="/dashboard/node/create/">
{% csrf_token %}
{% crispy formset formset.form.helper %}
</form>
......@@ -19,10 +19,11 @@ from django.views.generic import (TemplateView, DetailView, View, DeleteView,
from django.contrib import messages
from django.utils.translation import ugettext as _
from django.forms.models import inlineformset_factory
from django_tables2 import SingleTableView
from braces.views import LoginRequiredMixin, SuperuserRequiredMixin
from .forms import VmCreateForm, TemplateForm, LeaseForm
from .forms import VmCreateForm, TemplateForm, LeaseForm, NodeForm, HostForm
from .tables import (VmListTable, NodeListTable, NodeVmListTable,
TemplateListTable, LeaseListTable)
from vm.models import (Instance, InstanceTemplate, InterfaceTemplate,
......@@ -517,17 +518,30 @@ class VmCreate(LoginRequiredMixin, TemplateView):
class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
form_class = HostForm
hostform = None
formset_class = inlineformset_factory(Host, Node, form=NodeForm, extra=1)
formset = None
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/modal-wrapper.html']
else:
return ['dashboard/nojs-wrapper.html']
def get(self, request, *args, **kwargs):
def get(self, request, hostform=None, formset=None, *args, **kwargs):
if hostform is None:
hostform = self.form_class()
if formset is None:
formset = self.formset_class(instance=Host())
context = self.get_context_data(**kwargs)
context.update({
'template': 'dashboard/node-create.html',
'box_title': 'Create a Node'
'box_title': 'Create a Node',
'hostform': hostform,
'formset': formset,
})
return self.render_to_response(context)
......@@ -535,60 +549,34 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
context = super(NodeCreate, self).get_context_data(**kwargs)
# TODO acl
context.update({
'templates': InstanceTemplate.objects.all(),
'vlans': Vlan.objects.all(),
'disks': Disk.objects.exclude(type="qcow2-snap")
})
return context
# TODO handle not ajax posts
def post(self, request, *args, **kwargs):
if self.request.user.is_authenticated():
user = self.request.user
else:
user = None
resp = {}
try:
ikwargs = {
'num_cores': int(request.POST.get('cpu-count')),
'ram_size': int(request.POST.get('ram-size')),
'priority': int(request.POST.get('cpu-priority')),
}
networks = [InterfaceTemplate(vlan=Vlan.objects.get(pk=l),
managed=True)
for l in request.POST.getlist('managed-vlans')
]
networks.extend([InterfaceTemplate(vlan=Vlan.objects.get(pk=l),
managed=False)
for l in request.POST.getlist('unmanaged-vlans')
])
disks = Disk.objects.filter(pk__in=request.POST.getlist('disks'))
template = InstanceTemplate.objects.get(
pk=request.POST.get('template-pk'))
inst = Instance.create_from_template(template=template,
owner=user, networks=networks,
disks=disks, **ikwargs)
inst.deploy_async(user=request.user)
resp['pk'] = inst.pk
messages.success(request, _('Node successfully created!'))
except InstanceTemplate.DoesNotExist:
resp['error'] = True
except Exception, e:
print e
resp['error'] = True
if not self.request.user.is_authenticated():
raise PermissionDenied()
hostform = self.form_class(request.POST)
formset = self.formset_class(request.POST, Host())
if not hostform.is_valid():
return self.get(request, hostform, formset, *args, **kwargs)
hostform.setowner(request.user)
savedform = hostform.save(commit=False)
formset = self.formset_class(request.POST, instance=savedform)
if not formset.is_valid():
return self.get(request, hostform, formset, *args, **kwargs)
savedform.save()
nodemodel = formset.save()
messages.success(request, _('Node successfully created!'))
path = nodemodel[0].get_absolute_url()
if request.is_ajax():
return HttpResponse(json.dumps(resp),
content_type="application/json",
status=500 if resp.get('error') else 200)
return HttpResponse(json.dumps({'redirect': path}),
content_type="application/json")
else:
return redirect(reverse_lazy('dashboard.views.detail', resp))
return redirect(path)
class VmDelete(LoginRequiredMixin, DeleteView):
......
......@@ -3,7 +3,7 @@ from logging import getLogger
from django.db.models import (
CharField, IntegerField, ForeignKey, BooleanField, ManyToManyField,
FloatField,
FloatField, permalink,
)
from django.utils.translation import ugettext_lazy as _
......@@ -143,3 +143,10 @@ class Node(TimeStampedModel):
def get_state_count(cls, online, enabled):
return len([1 for i in cls.objects.filter(enabled=enabled).all()
if i.online == online])
@permalink
def get_absolute_url(self):
return ('dashboard.views.node-detail', None, {'pk': self.id})
def pr():
print "irdki"
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