Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
re2o
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nounous
re2o
Commits
eefa0b4a
Commit
eefa0b4a
authored
Jul 11, 2018
by
Hugo LEVY-FALK
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PEP8 mon amour + typos
parent
a07e0d92
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
172 additions
and
118 deletions
+172
-118
freeradius_utils/auth.py
freeradius_utils/auth.py
+9
-9
topologie/models.py
topologie/models.py
+73
-42
topologie/templates/topologie/aff_port_profile.html
topologie/templates/topologie/aff_port_profile.html
+2
-2
topologie/views.py
topologie/views.py
+88
-65
No files found.
freeradius_utils/auth.py
View file @
eefa0b4a
...
...
@@ -355,7 +355,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
port
=
port_number
)
.
first
())
# Si le port est inconnu, on place sur le vlan defaut
# Aucune information particulière ne permet de déterminer quelle
# politique à appliquer sur ce port
...
...
@@ -363,12 +363,12 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
return
(
sw_name
,
"Chambre inconnue"
,
u
'Port inconnu'
,
VLAN_OK
)
# On récupère le profil du port
port_profil
=
port
.
get_port_profil
port_profil
e
=
port
.
get_port_profile
# Si un vlan a été précisé dans la config du port,
# Si un vlan a été précisé dans la config du port,
# on l'utilise pour VLAN_OK
if
port_profil
.
vlan_untagged
:
DECISION_VLAN
=
int
(
port_profil
.
vlan_untagged
.
vlan_id
)
if
port_profil
e
.
vlan_untagged
:
DECISION_VLAN
=
int
(
port_profil
e
.
vlan_untagged
.
vlan_id
)
extra_log
=
u
"Force sur vlan "
+
str
(
DECISION_VLAN
)
else
:
DECISION_VLAN
=
VLAN_OK
...
...
@@ -378,7 +378,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
return
(
sw_name
,
port
.
room
,
u
'Port desactivé'
,
VLAN_NOK
)
# Si radius est désactivé, on laisse passer
if
port_profil
.
radius_type
==
'NO'
:
if
port_profil
e
.
radius_type
==
'NO'
:
return
(
sw_name
,
""
,
u
"Pas d'authentification sur ce port"
+
extra_log
,
...
...
@@ -386,7 +386,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
# Si le 802.1X est activé sur ce port, cela veut dire que la personne a été accept précédemment
# Par conséquent, on laisse passer sur le bon vlan
if
nas_type
.
port_access_mode
==
'802.1X'
and
port_profil
.
radius_type
==
'802.1X'
:
if
nas_type
.
port_access_mode
==
'802.1X'
and
port_profil
e
.
radius_type
==
'802.1X'
:
room
=
port
.
room
or
"Chambre/local inconnu"
return
(
sw_name
,
room
,
u
'Acceptation authentification 802.1X'
,
DECISION_VLAN
)
...
...
@@ -395,7 +395,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
# rattachés à ce port sont bien à jour de cotisation. Sinon on rejette (anti squattage)
# Il n'est pas possible de se connecter sur une prise strict sans adhérent à jour de cotis
# dedans
if
port_profil
.
radius_mode
==
'STRICT'
:
if
port_profil
e
.
radius_mode
==
'STRICT'
:
room
=
port
.
room
if
not
room
:
return
(
sw_name
,
"Inconnue"
,
u
'Chambre inconnue'
,
VLAN_NOK
)
...
...
@@ -411,7 +411,7 @@ def decide_vlan_and_register_switch(nas_machine, nas_type, port_number,
# else: user OK, on passe à la verif MAC
# Si on fait de l'auth par mac, on cherche l'interface via sa mac dans la bdd
if
port_profil
.
radius_mode
==
'COMMON'
or
port_profil
.
radius_mode
==
'STRICT'
:
if
port_profil
e
.
radius_mode
==
'COMMON'
or
port_profile
.
radius_mode
==
'STRICT'
:
# Authentification par mac
interface
=
(
Interface
.
objects
.
filter
(
mac_address
=
mac_address
)
...
...
topologie/models.py
View file @
eefa0b4a
...
...
@@ -40,7 +40,7 @@ from __future__ import unicode_literals
import
itertools
from
django.db
import
models
from
django.db.models.signals
import
p
re_save
,
p
ost_save
,
post_delete
from
django.db.models.signals
import
post_save
,
post_delete
from
django.utils.functional
import
cached_property
from
django.dispatch
import
receiver
from
django.core.exceptions
import
ValidationError
...
...
@@ -52,11 +52,6 @@ from reversion import revisions as reversion
from
machines.models
import
Machine
,
regen
from
re2o.mixins
import
AclMixin
,
RevMixin
from
os.path
import
isfile
from
os
import
remove
class
Stack
(
AclMixin
,
RevMixin
,
models
.
Model
):
"""Un objet stack. Regrouppe des switchs en foreign key
...
...
@@ -123,7 +118,10 @@ class AccessPoint(AclMixin, Machine):
)
def
building
(
self
):
"""Return the building of the AP/Server (building of the switchs connected to...)"""
"""
Return the building of the AP/Server (building of the switchs
connected to...)
"""
return
Building
.
objects
.
filter
(
switchbay__switch
=
self
.
switch
()
)
...
...
@@ -135,14 +133,18 @@ class AccessPoint(AclMixin, Machine):
@
classmethod
def
all_ap_in
(
cls
,
building_instance
):
"""Get a building as argument, returns all ap of a building"""
return
cls
.
objects
.
filter
(
interface__port__switch__switchbay__building
=
building_instance
)
return
cls
.
objects
.
filter
(
interface__port__switch__switchbay__building
=
building_instance
)
def
__str__
(
self
):
return
str
(
self
.
interface_set
.
first
())
class
Server
(
Machine
):
"""Dummy class, to retrieve servers of a building, or get switch of a server"""
"""
Dummy class, to retrieve servers of a building, or get switch of a server
"""
class
Meta
:
proxy
=
True
...
...
@@ -160,7 +162,10 @@ class Server(Machine):
)
def
building
(
self
):
"""Return the building of the AP/Server (building of the switchs connected to...)"""
"""
Return the building of the AP/Server
(building of the switchs connected to...)
"""
return
Building
.
objects
.
filter
(
switchbay__switch
=
self
.
switch
()
)
...
...
@@ -172,7 +177,9 @@ class Server(Machine):
@
classmethod
def
all_server_in
(
cls
,
building_instance
):
"""Get a building as argument, returns all server of a building"""
return
cls
.
objects
.
filter
(
interface__port__switch__switchbay__building
=
building_instance
).
exclude
(
accesspoint__isnull
=
False
)
return
cls
.
objects
.
filter
(
interface__port__switch__switchbay__building
=
building_instance
).
exclude
(
accesspoint__isnull
=
False
)
def
__str__
(
self
):
return
str
(
self
.
interface_set
.
first
())
...
...
@@ -200,7 +207,7 @@ class Switch(AclMixin, Machine):
blank
=
True
,
null
=
True
,
on_delete
=
models
.
SET_NULL
)
)
stack_member_id
=
models
.
PositiveIntegerField
(
blank
=
True
,
null
=
True
,
...
...
@@ -238,7 +245,7 @@ class Switch(AclMixin, Machine):
raise
ValidationError
(
{
'stack_member_id'
:
"L'id de ce switch est en
\
dehors des bornes permises pas la stack"
}
)
)
else
:
raise
ValidationError
({
'stack_member_id'
:
"L'id dans la stack
\
ne peut être nul"
})
...
...
@@ -378,25 +385,25 @@ class Port(AclMixin, RevMixin, models.Model):
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
)
machine_interface
=
models
.
ForeignKey
(
'machines.Interface'
,
on_delete
=
models
.
SET_NULL
,
blank
=
True
,
null
=
True
)
)
related
=
models
.
OneToOneField
(
'self'
,
null
=
True
,
blank
=
True
,
related_name
=
'related_port'
)
)
custom_profile
=
models
.
ForeignKey
(
'PortProfile'
,
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
)
state
=
models
.
BooleanField
(
default
=
True
,
help_text
=
'Port state Active'
,
...
...
@@ -411,32 +418,35 @@ class Port(AclMixin, RevMixin, models.Model):
)
@
cached_property
def
get_port_profil
(
self
):
"""Return the config profil for this port
def
get_port_profil
e
(
self
):
"""Return the config profil
e
for this port
:returns: the profile of self (port)"""
def
profil_or_nothing
(
profil
):
port_profil
=
PortProfile
.
objects
.
filter
(
profil_default
=
profil
).
first
()
if
port_profil
:
return
port_profil
def
profile_or_nothing
(
profile
):
port_profile
=
PortProfile
.
objects
.
filter
(
profile_default
=
profile
).
first
()
if
port_profile
:
return
port_profile
else
:
nothing
=
PortProfile
.
objects
.
filter
(
profil_default
=
'nothing'
).
first
()
if
not
nothing
:
nothing
=
PortProfile
.
objects
.
create
(
profil_default
=
'nothing'
,
name
=
'nothing'
,
radius_type
=
'NO'
)
return
nothing
nothing_profile
,
_created
=
PortProfile
.
objects
.
get_or_create
(
profile_default
=
'nothing'
,
name
=
'nothing'
,
radius_type
=
'NO'
)
return
nothing_profile
if
self
.
custom_profile
:
return
self
.
custom_profile
elif
self
.
related
:
return
profil_or_nothing
(
'uplink'
)
return
profil
e
_or_nothing
(
'uplink'
)
elif
self
.
machine_interface
:
if
hasattr
(
self
.
machine_interface
.
machine
,
'accesspoint'
):
return
profil_or_nothing
(
'access_point'
)
return
profil
e
_or_nothing
(
'access_point'
)
else
:
return
profil_or_nothing
(
'asso_machine'
)
return
profil
e
_or_nothing
(
'asso_machine'
)
elif
self
.
room
:
return
profil_or_nothing
(
'room'
)
return
profil
e
_or_nothing
(
'room'
)
else
:
return
profil_or_nothing
(
'nothing'
)
return
profil
e
_or_nothing
(
'nothing'
)
@
classmethod
def
get_instance
(
cls
,
portid
,
*
_args
,
**
kwargs
):
...
...
@@ -521,11 +531,11 @@ class PortProfile(AclMixin, RevMixin, models.Model):
(
'NO'
,
'NO'
),
(
'802.1X'
,
'802.1X'
),
(
'MAC-radius'
,
'MAC-radius'
),
)
)
MODES
=
(
(
'STRICT'
,
'STRICT'
),
(
'COMMON'
,
'COMMON'
),
)
)
SPEED
=
(
(
'10-half'
,
'10-half'
),
(
'100-half'
,
'100-half'
),
...
...
@@ -535,14 +545,14 @@ class PortProfile(AclMixin, RevMixin, models.Model):
(
'auto'
,
'auto'
),
(
'auto-10'
,
'auto-10'
),
(
'auto-100'
,
'auto-100'
),
)
PROFIL_DEFAULT
=
(
)
PROFIL_DEFAULT
=
(
(
'room'
,
'room'
),
(
'accespoint'
,
'accesspoint'
),
(
'uplink'
,
'uplink'
),
(
'asso_machine'
,
'asso_machine'
),
(
'nothing'
,
'nothing'
),
)
)
name
=
models
.
CharField
(
max_length
=
255
,
verbose_name
=
_
(
"Name"
))
profil_default
=
models
.
CharField
(
max_length
=
32
,
...
...
@@ -616,25 +626,36 @@ class PortProfile(AclMixin, RevMixin, models.Model):
default
=
False
,
help_text
=
'Protect against rogue ra'
,
verbose_name
=
_
(
"Ra guard"
)
)
)
loop_protect
=
models
.
BooleanField
(
default
=
False
,
help_text
=
'Protect again loop'
,
verbose_name
=
_
(
"Loop Protect"
)
)
)
class
Meta
:
permissions
=
(
(
"view_port_profile"
,
_
(
"Can view a port profile object"
)),
(
"view_port_profile"
,
_
(
"Can view a port profile object"
)),
)
verbose_name
=
_
(
"Port profile"
)
verbose_name_plural
=
_
(
"Port profiles"
)
security_parameters_fields
=
[
'loop_protect'
,
'ra_guard'
,
'arp_protect'
,
'dhcpv6_snooping'
,
'dhcp_snooping'
,
'flow_control'
]
security_parameters_fields
=
[
'loop_protect'
,
'ra_guard'
,
'arp_protect'
,
'dhcpv6_snooping'
,
'dhcp_snooping'
,
'flow_control'
]
@
cached_property
def
security_parameters_enabled
(
self
):
return
[
parameter
for
parameter
in
self
.
security_parameters_fields
if
getattr
(
self
,
parameter
)]
return
[
parameter
for
parameter
in
self
.
security_parameters_fields
if
getattr
(
self
,
parameter
)
]
@
cached_property
def
security_parameters_as_str
(
self
):
...
...
@@ -650,45 +671,55 @@ def ap_post_save(**_kwargs):
regen
(
'unifi-ap-names'
)
regen
(
"graph_topo"
)
@
receiver
(
post_delete
,
sender
=
AccessPoint
)
def
ap_post_delete
(
**
_kwargs
):
"""Regeneration des noms des bornes vers le controleur"""
regen
(
'unifi-ap-names'
)
regen
(
"graph_topo"
)
@
receiver
(
post_delete
,
sender
=
Stack
)
def
stack_post_delete
(
**
_kwargs
):
"""Vide les id des switches membres d'une stack supprimée"""
Switch
.
objects
.
filter
(
stack
=
None
).
update
(
stack_member_id
=
None
)
@
receiver
(
post_save
,
sender
=
Port
)
def
port_post_save
(
**
_kwargs
):
regen
(
"graph_topo"
)
@
receiver
(
post_delete
,
sender
=
Port
)
def
port_post_delete
(
**
_kwargs
):
regen
(
"graph_topo"
)
@
receiver
(
post_save
,
sender
=
ModelSwitch
)
def
modelswitch_post_save
(
**
_kwargs
):
regen
(
"graph_topo"
)
@
receiver
(
post_delete
,
sender
=
ModelSwitch
)
def
modelswitch_post_delete
(
**
_kwargs
):
regen
(
"graph_topo"
)
@
receiver
(
post_save
,
sender
=
Building
)
def
building_post_save
(
**
_kwargs
):
regen
(
"graph_topo"
)
@
receiver
(
post_delete
,
sender
=
Building
)
def
building_post_delete
(
**
_kwargs
):
regen
(
"graph_topo"
)
@
receiver
(
post_save
,
sender
=
Switch
)
def
switch_post_save
(
**
_kwargs
):
regen
(
"graph_topo"
)
@
receiver
(
post_delete
,
sender
=
Switch
)
def
switch_post_delete
(
**
_kwargs
):
regen
(
"graph_topo"
)
topologie/templates/topologie/aff_port_profile.html
View file @
eefa0b4a
...
...
@@ -29,9 +29,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% include "pagination.html" with list=port_profile_list %}
{% endif %}
<thead>
<table
class=
"table table-striped"
>
<thead>
<tr>
<th>
{% trans "Name" %}
</th>
<th>
{% trans "Default for" %}
</th>
...
...
@@ -49,7 +49,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>
{{port_profile.profil_default}}
</td>
<td>
{% if port_profile.vlan_untagged %}
<b>
Untagged :
</b>
{{port_profile.vlan_untagged}}
<b>
Untagged :
</b>
{{port_profile.vlan_untagged}}
<br>
{% endif %}
{% if port_profile.vlan_tagged.all %}
...
...
topologie/views.py
View file @
eefa0b4a
...
...
@@ -42,11 +42,7 @@ from django.contrib.auth.decorators import login_required
from
django.db
import
IntegrityError
from
django.db.models
import
ProtectedError
,
Prefetch
from
django.core.exceptions
import
ValidationError
from
django.contrib.staticfiles.storage
import
staticfiles_storage
from
django.template.loader
import
get_template
from
django.template
import
Context
,
Template
,
loader
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
django.utils.translation
import
ugettext
as
_
import
tempfile
...
...
@@ -105,8 +101,7 @@ from subprocess import (
PIPE
)
from
os.path
import
isfile
from
os
import
remove
from
os.path
import
isfile
@
login_required
...
...
@@ -128,13 +123,17 @@ def index(request):
SortTable
.
TOPOLOGIE_INDEX
)
pagination_number
=
GeneralOption
.
get_cached_value
(
'pagination_number'
)
switch_list
=
re2o_paginator
(
request
,
switch_list
,
pagination_number
)
if
any
(
service_link
.
need_regen
for
service_link
in
Service_link
.
objects
.
filter
(
service__service_type
=
'graph_topo'
)):
if
any
(
service_link
.
need_regen
for
service_link
in
Service_link
.
objects
.
filter
(
service__service_type
=
'graph_topo'
)
):
make_machine_graph
()
for
service_link
in
Service_link
.
objects
.
filter
(
service__service_type
=
'graph_topo'
):
for
service_link
in
Service_link
.
objects
.
filter
(
service__service_type
=
'graph_topo'
):
service_link
.
done_regen
()
if
not
isfile
(
"/var/www/re2o/media/images/switchs.png"
):
...
...
@@ -150,8 +149,10 @@ def index(request):
@
can_view_all
(
PortProfile
)
def
index_port_profile
(
request
):
pagination_number
=
GeneralOption
.
get_cached_value
(
'pagination_number'
)
port_profile_list
=
PortProfile
.
objects
.
all
().
select_related
(
'vlan_untagged'
)
port_profile_list
=
re2o_paginator
(
request
,
port_profile_list
,
pagination_number
)
port_profile_list
=
PortProfile
.
objects
.
all
().
select_related
(
'vlan_untagged'
)
port_profile_list
=
re2o_paginator
(
request
,
port_profile_list
,
pagination_number
)
return
render
(
request
,
'topologie/index_portprofile.html'
,
...
...
@@ -460,7 +461,7 @@ def new_switch(request):
)
domain
=
DomainForm
(
request
.
POST
or
None
,
)
)
if
switch
.
is_valid
()
and
interface
.
is_valid
():
user
=
AssoOption
.
get_cached_value
(
'utilisateur_asso'
)
if
not
user
:
...
...
@@ -530,7 +531,7 @@ def create_ports(request, switchid):
return
redirect
(
reverse
(
'topologie:index-port'
,
kwargs
=
{
'switchid'
:
switchid
}
))
))
return
form
(
{
'id_switch'
:
switchid
,
'topoform'
:
port_form
},
'topologie/switch.html'
,
...
...
@@ -548,16 +549,16 @@ def edit_switch(request, switch, switchid):
request
.
POST
or
None
,
instance
=
switch
,
user
=
request
.
user
)
)
interface_form
=
EditInterfaceForm
(
request
.
POST
or
None
,
instance
=
switch
.
interface_set
.
first
(),
user
=
request
.
user
)
)
domain_form
=
DomainForm
(
request
.
POST
or
None
,
instance
=
switch
.
interface_set
.
first
().
domain
)
)
if
switch_form
.
is_valid
()
and
interface_form
.
is_valid
():
new_switch_obj
=
switch_form
.
save
(
commit
=
False
)
new_interface_obj
=
interface_form
.
save
(
commit
=
False
)
...
...
@@ -601,7 +602,7 @@ def new_ap(request):
)
domain
=
DomainForm
(
request
.
POST
or
None
,
)
)
if
ap
.
is_valid
()
and
interface
.
is_valid
():
user
=
AssoOption
.
get_cached_value
(
'utilisateur_asso'
)
if
not
user
:
...
...
@@ -656,7 +657,7 @@ def edit_ap(request, ap, **_kwargs):
domain_form
=
DomainForm
(
request
.
POST
or
None
,
instance
=
ap
.
interface_set
.
first
().
domain
)
)
if
ap_form
.
is_valid
()
and
interface_form
.
is_valid
():
user
=
AssoOption
.
get_cached_value
(
'utilisateur_asso'
)
if
not
user
:
...
...
@@ -970,7 +971,7 @@ def del_constructor_switch(request, constructor_switch, **_kwargs):
return
form
({
'objet'
:
constructor_switch
,
'objet_name'
:
'Constructeur de switch'
},
'topologie/delete.html'
,
request
)
},
'topologie/delete.html'
,
request
)
@
login_required
...
...
@@ -993,7 +994,8 @@ def new_port_profile(request):
@
can_edit
(
PortProfile
)
def
edit_port_profile
(
request
,
port_profile
,
**
_kwargs
):
"""Edit a port profile"""
port_profile
=
EditPortProfileForm
(
request
.
POST
or
None
,
instance
=
port_profile
)
port_profile
=
EditPortProfileForm
(
request
.
POST
or
None
,
instance
=
port_profile
)
if
port_profile
.
is_valid
():
if
port_profile
.
changed_data
:
port_profile
.
save
()
...
...
@@ -1006,7 +1008,6 @@ def edit_port_profile(request, port_profile, **_kwargs):
)
@
login_required
@
can_delete
(
PortProfile
)
def
del_port_profile
(
request
,
port_profile
,
**
_kwargs
):
...
...
@@ -1014,25 +1015,26 @@ def del_port_profile(request, port_profile, **_kwargs):
if
request
.
method
==
'POST'
:
try
:
port_profile
.
delete
()
messages
.
success
(
request
,
_
(
"The port profile was successfully deleted"
))
messages
.
success
(
request
,
_
(
"The port profile was successfully deleted"
))
except
ProtectedError
:
messages
.
success
(
request
,
_
(
"Impossible to delete the port profile"
))
messages
.
success
(
request
,
_
(
"Impossible to delete the port profile"
))
return
redirect
(
reverse
(
'topologie:index'
))
return
form
(
{
'objet'
:
port_profile
,
'objet_name'
:
_
(
"Port profile"
)},
'topologie/delete.html'
,
request
{
'objet'
:
port_profile
,
'objet_name'
:
_
(
"Port profile"
)},
'topologie/delete.html'
,
request
)
def
make_machine_graph
():
"""
Create the graph of switchs, machines and access points.
"""
dico
=
{
'subs'
:
[],
'links'
:
[],
'links'
:
[],
'alone'
:
[],
'colors'
:
{
'head'
:
"#7f0505"
,
# Color parameters for the graph
...
...
@@ -1041,23 +1043,23 @@ def make_machine_graph():
'border_bornes'
:
"#02078e"
,
'head_bornes'
:
"#25771c"
,
'head_server'
:
"#1c3777"
}
}
}
missing
=
list
(
Switch
.
objects
.
all
())
detected
=
[]
for
building
in
Building
.
objects
.
all
():
# Visit all buildings
dico
[
'subs'
].
append
(
{
'bat_id'
:
building
.
id
,
'bat_name'
:
building
,
'switchs'
:
[],
'bornes'
:
[],
'machines'
:
[]
'bat_id'
:
building
.
id
,
'bat_name'
:
building
,
'switchs'
:
[],
'bornes'
:
[],
'machines'
:
[]
}
)
# Visit all switchs in this building
for
switch
in
Switch
.
objects
.
filter
(
switchbay__building
=
building
):
for
switch
in
Switch
.
objects
.
filter
(
switchbay__building
=
building
):
dico
[
'subs'
][
-
1
][
'switchs'
].
append
({
'name'
:
switch
.
main_interface
().
domain
.
name
,
'nombre'
:
switch
.
number
,
...
...
@@ -1067,7 +1069,7 @@ def make_machine_graph():
'ports'
:
[]
})
# visit all ports of this switch and add the switchs linked to it
for
port
in
switch
.
ports
.
filter
(
related__isnull
=
False
):
for
port
in
switch
.
ports
.
filter
(
related__isnull
=
False
):
dico
[
'subs'
][
-
1
][
'switchs'
][
-
1
][
'ports'
].
append
({
'numero'
:
port
.
port
,
'related'
:
port
.
related
.
switch
.
main_interface
().
domain
.
name
...
...
@@ -1085,50 +1087,58 @@ def make_machine_graph():
dico
[
'subs'
][
-
1
][
'machines'
].
append
({
'name'
:
server
.
short_name
,
'switch'
:
server
.
switch
()[
0
].
main_interface
().
domain
.
name
,
'port'
:
Port
.
objects
.
filter
(
machine_interface__machine
=
server
)[
0
].
port
'port'
:
Port
.
objects
.
filter
(
machine_interface__machine
=
server
)[
0
].
port
})
# While the list of forgotten ones is not empty
while
missing
:
if
missing
[
0
].
ports
.
count
():
# The switch is not empty
links
,
new_detected
=
recursive_switchs
(
missing
[
0
],
None
,
[
missing
[
0
]])
links
,
new_detected
=
recursive_switchs
(
missing
[
0
],
None
,
[
missing
[
0
]])
for
link
in
links
:
dico
[
'links'
].
append
(
link
)
# Update the lists of missings and already detected switchs
missing
=
[
i
for
i
in
missing
if
i
not
in
new_detected
]
missing
=
[
i
for
i
in
missing
if
i
not
in
new_detected
]
detected
+=
new_detected
else
:
# If the switch have no ports, don't explore it and hop to the next one
# If the switch have no ports, don't explore it and hop to the next one
else
:
del
missing
[
0
]
# Switchs that are not connected or not in a building
for
switch
in
Switch
.
objects
.
filter
(
switchbay__isnull
=
True
).
exclude
(
ports__related__isnull
=
False
):
for
switch
in
Switch
.
objects
.
filter
(
switchbay__isnull
=
True
).
exclude
(
ports__related__isnull
=
False
):
dico
[
'alone'
].
append
({
'id'
:
switch
.
id
,
'name'
:
switch
.
main_interface
().
domain
.
name
})
})
dot_data
=
generate_dot
(
dico
,
'topologie/graph_switch.dot'
)
# generate the dot file
# generate the dot file
dot_data
=
generate_dot
(
dico
,
'topologie/graph_switch.dot'
)
f
=
tempfile
.
NamedTemporaryFile
(
mode
=
'w+'
,
encoding
=
'utf-8'
,
delete
=
False
)
# Create a temporary file to store the dot data
# Create a temporary file to store the dot data
f
=
tempfile
.
NamedTemporaryFile
(
mode
=
'w+'
,
encoding
=
'utf-8'
,
delete
=
False
)
with
f
:
f
.
write
(
dot_data
)