Commit fda9c192 by Szabolcs Gelencser

implement network create, details

parent 327e7892
No preview for this file type
......@@ -13,7 +13,7 @@
<div class="list-group" id="vxlan-list-view">
<div id="dashboard-vxlan-list">
{% for vxlan in vxlans %}
<a href="{% url "network.vxlan" vni=vxlan.vni %}" class="list-group-item
<a href="{% url "network.vxlan" pk=vxlan.id %}" class="list-group-item
{% if forloop.last and vxlan|length < 5 %} list-group-item-last{% endif %}">
<span class="index-vxlan-list-name">
<i class="fa fa-sitemap"></i> {{ vxlan.name }}
......
......@@ -106,7 +106,7 @@ class IndexView(LoginRequiredMixin, TemplateView):
'operator', user, disregard_superuser=True).all()[:5]
# vxlan
#context['vxlans'] = Instance.list_from_os(self.request)[:5]
context['vxlans'] = Vxlan.list_from_os(self.request)[:5]
# toplist
if settings.STORE_URL:
......
......@@ -16,6 +16,7 @@
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.forms import ModelForm, widgets
from django import forms
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
......@@ -28,6 +29,7 @@ from firewall.models import (
SwitchPort, Firewall
)
from network.models import Vxlan
from openstack_api.neutron import Network
class LinkButton(BaseInput):
......@@ -372,21 +374,9 @@ class VxlanSuperUserForm(ModelForm):
)
)
class VxlanForm(ModelForm):
helper = FormHelper()
helper.layout = Layout(
Div(
Fieldset(
'',
'name',
'description',
'comment',
Field('vni', type='hidden'),
)
),
FormActions(
Submit('submit', _('Save')),
LinkButton('back', _('Back'), reverse_lazy(
'network.vxlan-list'))
)
)
class VxlanForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={
'class': "form-control",
'required': "",
}))
......@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import openstack_api
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.urlresolvers import reverse
......@@ -68,6 +68,10 @@ class Vxlan(models.Model):
class Meta:
app_label = 'network'
@classmethod
def list_from_os(cls, request):
return openstack_api.neutron.network_list_for_tenant(request, request.user.tenant_id)
def __unicode__(self):
return self.name
......
......@@ -5,18 +5,20 @@
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block title-page %}{% trans "Create" %} | {% trans "vxlan" %}{% endblock %}
{% block title-page %}{% trans "Create" %} | {% trans "network" %}{% endblock %}
{% block content %}
<div class="page-header">
<h2>{% trans "Create a new vxlan" %}</h2>
<h2>{% trans "Create a new network" %}</h2>
</div>
<div class="row">
<div class="col-sm-8">
{% crispy form %}
</div>
<div class="col-sm-4">
</div>
<form method="POST"">
{% csrf_token %}
{{ form.name|as_crispy_field }}
<button class="btn btn-success pull-right text-right" type="submit">
<i class="fa fa-plus"></i> {% trans "Create" %}
</button>
</form>
</div>
{% endblock %}
......@@ -9,8 +9,8 @@
{% block content %}
<div class="page-header">
<a href="{% url "network.vxlan-delete" vni=vxlan.vni %}" class="btn btn-danger pull-right"><i class="fa fa-times-circle"></i> {% trans "Delete this vxlan" %}</a>
<h2>{{ form.name.value }} <small>{% trans "details of vxlan" %}</small></h2>
<a href="{% url "network.vxlan-delete" pk=network.id %}" class="btn btn-danger pull-right"><i class="fa fa-times-circle"></i> {% trans "Delete this network" %}</a>
<h2>{{ form.name.value }} <small>{% trans "details of network" %}</small></h2>
</div>
<div class="row">
......@@ -21,12 +21,7 @@
<div class="page-header">
<h3>{% trans "Connected virtual machines" %}</h3>
</div>
{% render_table vm_list %}
<div class="page-header">
<h3>{% trans "Manage access" %}</h3>
</div>
{% include "dashboard/_manage_access.html" with table_id="vxlan-access-table" %}
{# {% render_table vm_list %}#}
</div>
</div>
{% endblock %}
......@@ -129,10 +129,11 @@ urlpatterns = [
# vxlan
url('^vxlans/$', VxlanList.as_view(), name='network.vxlan-list'),
url('^vxlans/create$', VxlanCreate.as_view(), name='network.vxlan-create'),
url('^vxlans/(?P<vni>\d+)/$', VxlanDetail.as_view(), name='network.vxlan'),
url('^vxlans/(?P<pk>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/$',
VxlanDetail.as_view(), name='network.vxlan'),
url('^vxlans/(?P<pk>\d+)/acl/$', VxlanAclUpdateView.as_view(),
name='network.vxlan-acl'),
url('^vxlans/delete/(?P<vni>\d+)/$', VxlanDelete.as_view(),
url('^vxlans/delete/(?P<pk>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/$', VxlanDelete.as_view(),
name="network.vxlan-delete"),
# editor
......
......@@ -20,10 +20,11 @@ import random
import json
from collections import OrderedDict
import openstack_api
from netaddr import IPNetwork
from django.views.generic import (
TemplateView, UpdateView, DeleteView, CreateView,
)
DetailView)
from django.core.exceptions import (
ValidationError, PermissionDenied, ImproperlyConfigured
)
......@@ -40,6 +41,8 @@ from firewall.models import (
SwitchPort, EthernetDevice, Firewall
)
from network.models import Vxlan, EditorElement
from numpy.distutils.from_template import template_name_re
from openstack_api.neutron import Network
from vm.models import Interface, Instance
from common.views import CreateLimitedResourceMixin
from .tables import (
......@@ -50,9 +53,7 @@ from .tables import (
)
from .forms import (
HostForm, VlanForm, DomainForm, GroupForm, RecordForm, BlacklistItemForm,
RuleForm, VlanGroupForm, SwitchPortForm, FirewallForm,
VxlanForm, VxlanSuperUserForm,
)
RuleForm, VlanGroupForm, SwitchPortForm, FirewallForm, VxlanForm)
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
......@@ -61,7 +62,7 @@ from django.utils.translation import ugettext_lazy as _
from braces.views import LoginRequiredMixin, SuperuserRequiredMixin
from operator import itemgetter
from itertools import chain
from dashboard.views import AclUpdateView
from dashboard.views import AclUpdateView, FormView
from dashboard.forms import AclUserOrGroupAddForm
try:
......@@ -94,14 +95,6 @@ class MagicMixin(object):
else:
return super(MagicMixin, self).get(*args, **kwargs)
class InitialOwnerMixin(FormMixin):
def get_initial(self):
initial = super(InitialOwnerMixin, self).get_initial()
initial['owner'] = self.request.user
return initial
class IndexView(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
template_name = "network/index.html"
......@@ -225,7 +218,7 @@ class DomainDetail(LoginRequiredMixin, SuperuserRequiredMixin,
class DomainCreate(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, InitialOwnerMixin, CreateView):
SuccessMessageMixin, CreateView):
model = Domain
template_name = "network/domain-create.html"
form_class = DomainForm
......@@ -356,7 +349,7 @@ class GroupList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
class GroupCreate(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, InitialOwnerMixin, CreateView):
SuccessMessageMixin, CreateView):
model = Group
template_name = "network/group-create.html"
form_class = GroupForm
......@@ -621,7 +614,7 @@ class RecordDetail(LoginRequiredMixin, SuperuserRequiredMixin,
class RecordCreate(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, InitialOwnerMixin, CreateView):
SuccessMessageMixin, CreateView):
model = Record
template_name = "network/record-create.html"
form_class = RecordForm
......@@ -708,7 +701,7 @@ class RuleDetail(LoginRequiredMixin, SuperuserRequiredMixin,
class RuleCreate(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, InitialOwnerMixin, CreateView):
SuccessMessageMixin, CreateView):
model = Rule
template_name = "network/rule-create.html"
form_class = RuleForm
......@@ -743,6 +736,22 @@ class SwitchPortList(LoginRequiredMixin, SuperuserRequiredMixin,
table_pagination = False
class RuleCreate(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, CreateView):
model = Rule
template_name = "network/rule-create.html"
form_class = RuleForm
success_message = _(u'Successfully created rule.')
def get_initial(self):
initial = super(RuleCreate, self).get_initial()
initial.update({
'host': self.request.GET.get('host'),
'hostgroup': self.request.GET.get('hostgroup')
})
return initial
class SwitchPortDetail(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, UpdateView):
model = SwitchPort
......@@ -829,7 +838,7 @@ class VlanDetail(VlanMagicMixin, LoginRequiredMixin, SuperuserRequiredMixin,
class VlanCreate(VlanMagicMixin, LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, InitialOwnerMixin, CreateView):
SuccessMessageMixin, CreateView):
model = Vlan
template_name = "network/vlan-create.html"
form_class = VlanForm
......@@ -909,7 +918,7 @@ class VlanGroupDetail(LoginRequiredMixin, SuperuserRequiredMixin,
class VlanGroupCreate(LoginRequiredMixin, SuperuserRequiredMixin,
SuccessMessageMixin, InitialOwnerMixin, CreateView):
SuccessMessageMixin, CreateView):
model = VlanGroup
template_name = "network/vlan-group-create.html"
form_class = VlanGroupForm
......@@ -963,107 +972,29 @@ class VxlanAclUpdateView(AclUpdateView):
model = Vxlan
class VxlanDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView): #TODO: check user
model = Vxlan
slug_field = 'vni'
slug_url_kwarg = 'vni'
class VxlanDetail(LoginRequiredMixin, SuccessMessageMixin, DetailView): #TODO: check user
# model = Network
success_message = _(u'Succesfully modified vlan %(name)s.')
success_url = reverse_lazy('network.vxlan-list')
template_name = 'network/vxlan-edit.html'
context_object_name = 'network'
def get_template_names(self):
if self.request.user.is_superuser:
return ["network/vxlan-superuser-edit.html"]
else:
return ["network/vxlan-edit.html"]
def get_form_class(self, is_post=False):
if self.request.user.is_superuser:
return VxlanSuperUserForm
return VxlanForm
def get_object(self, queryset=None):
return openstack_api.neutron.network_get(self.request, self.kwargs['pk'])
def get_context_data(self, **kwargs):
context = super(VxlanDetail, self).get_context_data(**kwargs)
context['vm_list'] = SmallVmTable(self.object.vm_interface.all())
context['acl'] = AclUpdateView.get_acl_data(
self.object, self.request.user, 'network.vxlan-acl')
context['aclform'] = AclUserOrGroupAddForm()
context['vm_list'] = () #SmallVmTable(self.object.vm_interface.all())
context['form'] = VxlanForm
return context
def post(self, *args, **kwargs):
if not self.object.has_level(self.request.user, 'owner'):
raise PermissionDenied()
return super(VxlanDetail, self).post(*args, **kwargs)
class VxlanCreate(LoginRequiredMixin, SuccessMessageMixin, InitialOwnerMixin, CreateView):
model = Vxlan
profile_attribute = 'network_limit'
resource_name = _('Virtual network')
success_message = _(u'Successfully created vxlan %(name)s.')
def get_template_names(self):
if self.request.user.is_superuser:
return ["network/vxlan-superuser-create.html"]
else:
return ["network/vxlan-create.html"]
def get_form_class(self, is_post=False):
if self.request.user.is_superuser:
return VxlanSuperUserForm
return VxlanForm
def get_initial(self):
initial = super(VxlanCreate, self).get_initial()
initial['vni'] = self._generate_vni()
return initial
def get_default_vlan(self):
vlan = Vlan.objects.filter(
name=settings.DEFAULT_USERNET_VLAN_NAME).first()
if vlan is None:
msg = (_('Cannot find server vlan: %s') %
settings.DEFAULT_USERNET_VLAN_NAME)
if self.request.user.is_superuser:
messages.error(self.request, msg)
logger.error(msg)
raise ImproperlyConfigured()
return vlan
class VxlanCreate(LoginRequiredMixin, FormView):
form_class = VxlanForm
template_name = 'network/vxlan-create.html'
def form_valid(self, form):
obj = form.save(commit=False)
obj.vlan = self.get_default_vlan()
try:
obj.full_clean()
obj.save()
obj.set_level(obj.owner, 'owner')
self.object = obj
except Exception as e:
msg = _('Unexpected error occured. '
'Please try again or contact administrator!')
messages.error(self.request, msg)
logger.exception(e)
return redirect(self.get_success_url())
def form_invalid(self, form):
# When multiple client get same VNI value
if 'vni' in form.errors.as_data():
messages.error(self.request, _('Cannot create virtual network.'
' Please try again.'))
return redirect('network.vxlan-create')
return super(VxlanCreate, self).form_invalid(form)
def _generate_vni(self):
if Vxlan.objects.count() == settings.USERNET_MAX:
msg = _('Cannot find unused VNI value. '
'Please contact administrator!')
messages.error(self.request, msg)
logger.error(msg)
else:
full_range = set(range(0, settings.USERNET_MAX))
used_values = {vni[0] for vni in Vxlan.objects.values_list('vni')}
free_values = full_range - used_values
return random.choice(list(free_values))
network_created = openstack_api.neutron.network_create(self.request, name=form.cleaned_data['name'])
return redirect(reverse_lazy('network.vxlan', kwargs={'pk': network_created.id}))
class VxlanDelete(LoginRequiredMixin, DeleteView): #TODO: check user
model = Vlan
......
......@@ -508,7 +508,7 @@ def keypair_get(request, name):
def server_create(request, name, image, flavor, key_name=None, user_data=None,
security_groups=None, block_device_mapping=None,
block_device_mapping_v2=None, nics="auto",
block_device_mapping_v2=None, nics="none",
availability_zone=None, instance_count=1, admin_pass=None,
disk_config=None, config_drive=None, meta=None,
scheduler_hints=None, description=None):
......
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