Maintenance électrique le 12 août, nos services, et y compris Gitlab, seront fortement impactés autour de cette date. Retour à un état normal prévu dans le milieu de la semaine prochaine.

Commit 2c9ff4ea authored by Gabriel Detraz's avatar Gabriel Detraz Committed by klafyvel

Module switch, model et fonctions basiques de modification

parent 02229983
......@@ -55,6 +55,7 @@ from .models import (
SwitchBay,
Building,
PortProfile,
ModuleSwitch
)
......@@ -269,3 +270,23 @@ class EditPortProfileForm(FormRevMixin, ModelForm):
prefix=prefix,
**kwargs)
class EditModuleForm(FormRevMixin, ModelForm):
"""Add and edit module instance"""
class Meta:
model = ModuleSwitch
fields = '__all__'
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(EditModuleForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['switchs'].queryset = (Switch.objects.filter(model__is_modular=True))
def save(self, commit=True):
# TODO : None of the parents of ServiceForm use the commit
# parameter in .save()
instance = super(EditModuleForm, self).save(commit=False)
if commit:
instance.save()
instance.process_link(self.cleaned_data.get('switchs'))
return instance
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-12-30 14:56
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import re2o.mixins
class Migration(migrations.Migration):
dependencies = [
('topologie', '0066_modelswitch_commercial_name'),
]
operations = [
migrations.CreateModel(
name='ModuleOnSwitch',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slot', models.CharField(help_text='Slot on switch', max_length=15, verbose_name='Slot')),
],
options={
'verbose_name': 'link between switchs and modules',
'permissions': (('view_moduleonswitch', 'Can view a moduleonswitch object'),),
},
bases=(re2o.mixins.AclMixin, re2o.mixins.RevMixin, models.Model),
),
migrations.CreateModel(
name='ModuleSwitch',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('reference', models.CharField(help_text='Reference of a module', max_length=255, verbose_name='Module reference')),
('comment', models.CharField(blank=True, help_text='Comment', max_length=255, null=True, verbose_name='Comment')),
('switchs', models.ManyToManyField(through='topologie.ModuleOnSwitch', to='topologie.Switch')),
],
options={
'verbose_name': 'Module of a switch',
'permissions': (('view_moduleswitch', 'Can view a module object'),),
},
bases=(re2o.mixins.AclMixin, re2o.mixins.RevMixin, models.Model),
),
migrations.AddField(
model_name='modelswitch',
name='is_itself_module',
field=models.BooleanField(default=False, help_text='Does the switch, itself, considered as a module'),
),
migrations.AddField(
model_name='modelswitch',
name='is_modular',
field=models.BooleanField(default=False, help_text='Is this switch model modular'),
),
migrations.AddField(
model_name='moduleonswitch',
name='module',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='topologie.ModuleSwitch'),
),
migrations.AddField(
model_name='moduleonswitch',
name='switch',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='topologie.Switch'),
),
]
......@@ -251,6 +251,7 @@ class Switch(AclMixin, Machine):
default=False,
help_text='Provision automatique de ce switch',
)
class Meta:
unique_together = ('stack', 'stack_member_id')
......@@ -389,6 +390,14 @@ class ModelSwitch(AclMixin, RevMixin, models.Model):
null=True,
blank=True
)
is_modular = models.BooleanField(
default=False,
help_text=_("Is this switch model modular"),
)
is_itself_module = models.BooleanField(
default=False,
help_text=_("Does the switch, itself, considered as a module"),
)
class Meta:
permissions = (
......@@ -404,6 +413,61 @@ class ModelSwitch(AclMixin, RevMixin, models.Model):
return str(self.constructor) + ' ' + self.reference
class ModuleSwitch(AclMixin, RevMixin, models.Model):
"""A module of a switch"""
reference = models.CharField(
max_length=255,
help_text=_("Reference of a module"),
verbose_name=_("Module reference")
)
comment = models.CharField(
max_length=255,
null=True,
blank=True,
help_text=_("Comment"),
verbose_name=_("Comment")
)
switchs = models.ManyToManyField('Switch', through='ModuleOnSwitch')
class Meta:
permissions = (
("view_moduleswitch", _("Can view a module object")),
)
verbose_name = _("Module of a switch")
def process_link(self, switchs):
"""Django can't create itself foreignkey with explicit through"""
ModuleOnSwitch.objects.bulk_create(
[ModuleOnSwitch(
module=self, switch=sw
) for sw in switchs.exclude(
pk__in=Switch.objects.filter(moduleswitch=self)
)]
)
ModuleOnSwitch.objects.filter(module=self).exclude(switch__in=switchs).delete()
return
def __str__(self):
return str(self.reference)
class ModuleOnSwitch(AclMixin, RevMixin, models.Model):
"""Link beetween module and switch"""
module = models.ForeignKey('ModuleSwitch', on_delete=models.CASCADE)
switch = models.ForeignKey('Switch', on_delete=models.CASCADE)
slot = models.CharField(
max_length=15,
help_text=_("Slot on switch"),
verbose_name=_("Slot")
)
class Meta:
permissions = (
("view_moduleonswitch", _("Can view a moduleonswitch object")),
)
verbose_name = _("link between switchs and modules")
class ConstructorSwitch(AclMixin, RevMixin, models.Model):
"""Un constructeur de switch"""
......
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load acl %}
{% load logs_extra %}
{% load i18n %}
{% if module_list.paginator %}
{% include "pagination.html" with list=module_list %}
{% endif %}
<table class="table table-striped">
<thead>
<tr>
<th>{% trans "Reference" %}</th>
<th>{% trans "Comment" %}</th>
<th>{% trans "Switchs" %}</th>
<th></th>
</tr>
</thead>
{% for module in module_list %}
<tr>
<td>{{ module.reference }}</td>
<td>{{ module.comment }}</td>
<td>{{ module.switchs.all }}</td>
<td class="text-right">
{% can_edit module %}
<a class="btn btn-primary btn-sm" role="button" title={% trans "Edit" %} href="{% url 'topologie:edit-module' module.id %}">
<i class="fa fa-edit"></i>
</a>
{% acl_end %}
{% history_button module %}
{% can_delete module %}
<a class="btn btn-danger btn-sm" role="button" title={% trans "Delete" %} href="{% url 'topologie:del-module' module.id %}">
<i class="fa fa-trash"></i>
</a>
{% acl_end %}
</td>
</tr>
{% endfor %}
</table>
{% if module_list.paginator %}
{% include "pagination.html" with list=module_list %}
{% endif %}
{% extends "topologie/sidebar.html" %}
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load bootstrap3 %}
{% load acl %}
{% load i18n %}
{% block title %}{% trans "Topology" %}{% endblock %}
{% block content %}
<h2>{% trans "Modules of switchs" %}</h2>
{% can_create ModuleSwitch %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'topologie:add-module' %}"><i class="fa fa-plus"></i>{% trans " Add a module" %}</a>
<hr>
{% acl_end %}
{% include "topologie/aff_modules.html" with module_list=module_list %}
<br />
<br />
<br />
{% endblock %}
......@@ -33,6 +33,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<a class="list-group-item list-group-item-info" href="{% url "topologie:index" %}">
<i class="fa fa-microchip"></i>
{% trans "Switches" %}
</a>
<a class="list-group-item list-group-item-info" href="{% url "topologie:index-module" %}">
<i class="fa fa-microchip"></i>
{% trans "Switches modules" %}
</a>
<a class="list-group-item list-group-item-info" href="{% url "topologie:index-port-profile" %}">
<i class="fa fa-cogs"></i>
......
......@@ -37,7 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% endif %}
<form class="form" method="post">
{% csrf_token %}
{% massive_bootstrap_form topoform 'room,related,machine_interface,members,vlan_tagged' %}
{% massive_bootstrap_form topoform 'room,related,machine_interface,members,vlan_tagged,switchs' %}
{% bootstrap_button action_name icon='ok' button_class='btn-success' %}
</form>
<br />
......
......@@ -123,4 +123,10 @@ urlpatterns = [
url(r'^edit_vlanoptions/(?P<vlanid>[0-9]+)$',
views.edit_vlanoptions,
name='edit-vlanoptions'),
]
url(r'^add_module/$', views.add_module, name='add-module'),
url(r'^edit_module/(?P<moduleid>[0-9]+)$',
views.edit_module,
name='edit-module'),
url(r'^del_module/(?P<moduleid>[0-9]+)$', views.del_module, name='del-module'),
url(r'^index_module/$', views.index_module, name='index-module'),
]
......@@ -86,6 +86,7 @@ from .models import (
Building,
Server,
PortProfile,
ModuleSwitch,
)
from .forms import (
EditPortForm,
......@@ -102,6 +103,7 @@ from .forms import (
EditSwitchBayForm,
EditBuildingForm,
EditPortProfileForm,
EditModuleForm
)
from subprocess import (
......@@ -316,6 +318,20 @@ def index_model_switch(request):
)
@login_required
@can_view_all(ModuleSwitch)
def index_module(request):
"""Display all modules of switchs"""
module_list = ModuleSwitch.objects.all()
pagination_number = GeneralOption.get_cached_value('pagination_number')
module_list = re2o_paginator(request, module_list, pagination_number)
return render(
request,
'topologie/index_module.html',
{'module_list': module_list}
)
@login_required
@can_edit(Vlan)
def edit_vlanoptions(request, vlan_instance, **_kwargs):
......@@ -1048,6 +1064,60 @@ def del_port_profile(request, port_profile, **_kwargs):
)
@can_create(ModuleSwitch)
def add_module(request):
""" View used to add a Module object """
module = EditModuleForm(request.POST or None)
if module.is_valid():
module.save()
messages.success(request, _("The module was created."))
return redirect(reverse('topologie:index-module'))
return form(
{'topoform': module, 'action_name': _("Create a module")},
'topologie/topo.html',
request
)
@login_required
@can_edit(ModuleSwitch)
def edit_module(request, module_instance, **_kwargs):
""" View used to edit a Module object """
module = EditModuleForm(request.POST or None, instance=module_instance)
if module.is_valid():
if module.changed_data:
module.save()
messages.success(request, _("The module was edited."))
return redirect(reverse('topologie:index-module'))
return form(
{'topoform': module, 'action_name': _("Edit")},
'topologie/topo.html',
request
)
@login_required
@can_delete(ModuleSwitch)
def del_module(request, module, **_kwargs):
"""Compleete delete a module"""
if request.method == "POST":
try:
module.delete()
messages.success(request, _("The module was deleted."))
except ProtectedError:
messages.error(
request,
(_("The module %s is used by another object, impossible to"
" deleted it.") % module)
)
return redirect(reverse('topologie:index-module'))
return form(
{'objet': module, 'objet_name': _("Module")},
'topologie/delete.html',
request
)
def make_machine_graph():
"""
Create the graph of switchs, machines and access points.
......
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 to comment