Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
allworldit
python
birdclient
Commits
6ff9fc56
Commit
6ff9fc56
authored
Sep 08, 2019
by
Nigel Kukard
Browse files
Merge branch 'nkupdates' into 'master'
Added tests See merge request
!1
parents
3d5c6631
6707b24b
Pipeline
#4503
passed with stage
in 27 seconds
Changes
12
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
6ff9fc56
...
...
@@ -11,7 +11,6 @@ test_job:
-
pacman -Syu --noconfirm
-
pacman -S --noconfirm grep python
-
pacman -S --noconfirm python-pytest python-pytest-runner python-pytest-cov python-pylint python-isort mypy pylama python-mccabe
-
pacman -S --noconfirm iproute2 bird exabgp
# Run tests
-
python setup.py test
# Artifacts
...
...
src/birdclient/__init__.py
View file @
6ff9fc56
...
...
@@ -25,8 +25,10 @@ import socket
from
typing
import
Any
,
Dict
,
List
,
Optional
__version__
=
'0.0.1'
class
Birdc
:
class
BirdClient
:
"""BIRD client class."""
# Socket file
...
...
@@ -34,7 +36,7 @@ class Birdc:
# Ending lines for bird control channel
_ending_lines
:
List
[
bytes
]
def
__init__
(
self
,
socket_file
:
str
):
def
__init__
(
self
,
socket_file
:
Optional
[
str
]
=
None
):
"""Initialize the object."""
# Set socket file
...
...
@@ -44,13 +46,6 @@ class Birdc:
def
show_status
(
self
,
data
:
Optional
[
List
[
str
]]
=
None
)
->
Dict
[
str
,
str
]:
"""Return parsed BIRD status."""
# 0001 BIRD 2.0.4 ready.
# 1000-BIRD 2.0.4
# 1011-Router ID is 172.16.10.1
# Current server time is 2019-08-15 12:42:51.638
# Last reboot on 2019-08-15 12:42:47.592
# Last reconfiguration on 2019-08-15 12:42:47.592
# 0013 Daemon is up and running
# Grab status
if
not
data
:
...
...
@@ -92,22 +87,6 @@ class Birdc:
def
show_protocols
(
self
,
data
:
Optional
[
List
[
str
]]
=
None
)
->
Dict
[
str
,
Any
]:
"""Return parsed BIRD protocols."""
# 0001 BIRD 2.0.4 ready.
# 2002-Name Proto Table State Since Info
# 1002-device1 Device --- up 13:13:28.641
# kernel4 Kernel t_kernel4 up 13:13:28.641
# kernel6 Kernel t_kernel6 up 13:13:28.641
# static4 Static t_static4 up 13:13:28.641
# static6 Static t_static6 up 13:13:28.641
# p_static4_to_kernel4 Pipe --- up 13:13:28.641 t_static4 <=> t_kernel4
# p_static6_to_kernel6 Pipe --- up 13:13:28.641 t_static6 <=> t_kernel6
# ospf4 OSPF t_ospf4 up 13:13:28.641 Alone
# ospf6 OSPF t_ospf6 up 13:13:28.641 Running
# p_ospf4_to_kernel4 Pipe --- up 13:13:28.641 t_ospf4 <=> t_kernel4
# p_ospf6_to_kernel6 Pipe --- up 13:13:28.641 t_ospf6 <=> t_kernel6
# p_ospf4_to_static4 Pipe --- up 13:13:28.641 t_ospf4 <=> t_static4
# p_ospf6_to_static6 Pipe --- up 13:13:28.641 t_ospf6 <=> t_static6
# 0000
# Grab protocols
if
not
data
:
...
...
@@ -142,92 +121,6 @@ class Birdc:
# pylama: ignore=R0915,C901
def
show_route_table
(
self
,
table
:
str
,
data
:
Optional
[
List
[
str
]]
=
None
)
->
List
:
"""Return parsed BIRD routing table."""
# 0001 BIRD 2.0.4 ready.
# 1007-Table t_static4:
# 10.0.1.0/24 unicast [static4 13:36:14.198] * (200)
# via 192.168.0.4 on eth0
# 1008- Type: static univ
# 1007-10.0.2.0/24 unicast [static4 13:36:14.198] * (200)
# via 192.168.0.5 on eth0
# 1008- Type: static univ
# 0000
# 0001 BIRD 2.0.4 ready.
# 1007-Table t_kernel4:
# 172.16.100.0/24 unicast [kernel4 13:36:14.199] (10)
# via 172.16.10.10 on eth9
# 1008- Type: inherit univ
# 1007-10.0.1.0/24 unicast [static4 13:36:14.199] * (200)
# via 192.168.0.4 on eth0
# 1008- Type: static univ
# 1007-10.0.2.0/24 unicast [static4 13:36:14.199] * (200)
# via 192.168.0.5 on eth0
# 1008- Type: static univ
# 0000
# 0001 BIRD 2.0.4 ready.
# 1007-Table t_ospf4:
# 172.16.100.0/24 unicast [kernel4 13:36:14.199] (10)
# via 172.16.10.10 on eth9
# 1008- Type: inherit univ
# 1007-10.0.1.0/24 unicast [static4 13:36:14.199] * (200)
# via 192.168.0.4 on eth0
# 1008- Type: static univ
# 1007-10.0.2.0/24 unicast [static4 13:36:14.199] * (200)
# via 192.168.0.5 on eth0
# 1008- Type: static univ
# 0000
# 0001 BIRD 2.0.4 ready.
# 1007-Table t_static6:
# fec0:20::/64 unicast [static6 13:36:14.708] * (200)
# via fec0::5 on eth0
# 1008- Type: static univ
# 1007-fec0:10::/64 unicast [static6 13:36:14.708] * (200)
# via fec0::4 on eth0
# 1008- Type: static univ
# 0000
# 0001 BIRD 2.0.4 ready.
# 1007-Table t_kernel6:
# fec0:20::/64 unicast [static6 13:36:14.708] * (200)
# via fec0::5 on eth0
# 1008- Type: static univ
# 1007-fec0:10::/64 unicast [static6 13:36:14.708] * (200)
# via fec0::4 on eth0
# 1008- Type: static univ
# 0000
# 0001 BIRD 2.0.4 ready.
# 1007-Table t_ospf6:
# fec0:20::/64 unicast [static6 13:36:14.708] * (200)
# via fec0::5 on eth0
# 1008- Type: static univ
# 1007-fec0:10::/64 unicast [static6 13:36:14.708] * (200)
# via fec0::4 on eth0
# 1008- Type: static univ
# 0000
# 0001 BIRD 2.0.4 ready.
# 1007-Table t_ospf6:
# fec0:20::/64 unicast [ospf6 14:20:00.666] E2 (150/20/10000) [172.16.10.1]
# via fe80::8c84:28ff:fe6c:40ae on eth0
# 1008- Type: OSPF-E2 univ
# 1007-fec0:10::/64 unicast [ospf6 14:20:00.666] E2 (150/20/10000) [172.16.10.1]
# via fe80::8c84:28ff:fe6c:40ae on eth0
# 1008- Type: OSPF-E2 univ
# 1007-fec0::/64 unicast [ospf6 14:19:58.660] I (150/20) [172.16.10.1]
# via fe80::8c84:28ff:fe6c:40ae on eth0
# 1008- Type: OSPF univ
# 1007-fefe::/64 unicast [ospf6 14:20:00.666] I (150/30) [172.16.10.1]
# via fe80::8c84:28ff:fe6c:40ae on eth0
# 1008- Type: OSPF univ
# 1007-fec0:1::/64 unicast [ospf6 14:19:58.660] I (150/10) [0.0.0.3]
# dev eth0
# 1008- Type: OSPF univ
# 1007-fefe:1::/64 unicast [ospf6 14:20:00.666] E2 (150/30/10000) [172.16.10.1]
# via fe80::8c84:28ff:fe6c:40ae on eth0
# 1008- Type: OSPF-E2 univ
# Grab routes
if
not
data
:
...
...
tests/test_birdclient.py
0 → 100644
View file @
6ff9fc56
"""Tests for the Python BirdClient class."""
from
typing
import
List
from
birdclient
import
BirdClient
class
TestBirdClient
():
"""Test the BirdClient class."""
def
_load_file
(
self
,
filename
:
str
)
->
List
[
str
]:
"""Read in a file and return the lines."""
with
open
(
f
'tests/
{
filename
}
'
,
'r'
)
as
datafile
:
data
=
datafile
.
read
()
return
data
.
splitlines
()
def
test_show_status
(
self
):
"""Test show_status."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_status
(
self
.
_load_file
(
'test_show_status.txt'
))
correct_result
=
{
'last_reboot'
:
'2019-08-15 12:42:47.592'
,
'last_reconfiguration'
:
'2019-08-15 12:42:47.592'
,
'router_id'
:
'172.16.10.1'
,
'server_time'
:
'2019-08-15 12:42:51.638'
,
'version'
:
'2.0.4'
}
assert
result
==
correct_result
,
'The show_status() result does not match what it should be'
def
test_show_protocols
(
self
):
"""Test show_protocols."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_protocols
(
self
.
_load_file
(
'test_show_protocols.txt'
))
correct_result
=
{
'ospf4'
:
{
'info'
:
'Alone'
,
'name'
:
'ospf4'
,
'proto'
:
'OSPF'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
't_ospf4'
},
'ospf6'
:
{
'info'
:
'Running'
,
'name'
:
'ospf6'
,
'proto'
:
'OSPF'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
't_ospf6'
},
'p_ospf4_to_kernel4'
:
{
'info'
:
't_ospf4 <=> t_kernel4'
,
'name'
:
'p_ospf4_to_kernel4'
,
'proto'
:
'Pipe'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
'---'
},
'p_ospf4_to_static4'
:
{
'info'
:
't_ospf4 <=> t_static4'
,
'name'
:
'p_ospf4_to_static4'
,
'proto'
:
'Pipe'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
'---'
},
'p_ospf6_to_kernel6'
:
{
'info'
:
't_ospf6 <=> t_kernel6'
,
'name'
:
'p_ospf6_to_kernel6'
,
'proto'
:
'Pipe'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
'---'
},
'p_ospf6_to_static6'
:
{
'info'
:
't_ospf6 <=> t_static6'
,
'name'
:
'p_ospf6_to_static6'
,
'proto'
:
'Pipe'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
'---'
},
'p_static4_to_kernel4'
:
{
'info'
:
't_static4 <=> t_kernel4'
,
'name'
:
'p_static4_to_kernel4'
,
'proto'
:
'Pipe'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
'---'
},
'p_static6_to_kernel6'
:
{
'info'
:
't_static6 <=> t_kernel6'
,
'name'
:
'p_static6_to_kernel6'
,
'proto'
:
'Pipe'
,
'since'
:
'13:13:28.641'
,
'state'
:
'up'
,
'table'
:
'---'
}
}
assert
result
==
correct_result
,
'The show_protocols() result does not match what it should be'
def
test_show_route_table_t_static4
(
self
):
"""Test show_route_table."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_route_table
(
't_static4'
,
self
.
_load_file
(
'test_show_route_table_t_static4.txt'
))
correct_result
=
[
{
'prefix'
:
'10.0.1.0/24'
,
'primary'
:
'*'
,
'proto'
:
'static4'
,
'since'
:
'13:36:14.198'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'192.168.0.4'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'10.0.2.0/24'
,
'primary'
:
'*'
,
'proto'
:
'static4'
,
'since'
:
'13:36:14.198'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'192.168.0.5'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
}
]
assert
result
==
correct_result
,
'The show_route_table() result does not match what it should be'
def
test_show_route_table_t_static6
(
self
):
"""Test show_route_table."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_route_table
(
't_static6'
,
self
.
_load_file
(
'test_show_route_table_t_static6.txt'
))
correct_result
=
[
{
'prefix'
:
'fec0:20::/64'
,
'primary'
:
'*'
,
'proto'
:
'static6'
,
'since'
:
'13:36:14.708'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'fec0::5'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'fec0:10::/64'
,
'primary'
:
'*'
,
'proto'
:
'static6'
,
'since'
:
'13:36:14.708'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'fec0::4'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
}
]
assert
result
==
correct_result
,
'The show_route_table() result does not match what it should be'
def
test_show_route_table_t_kernel4
(
self
):
"""Test show_route_table."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_route_table
(
't_kernel4'
,
self
.
_load_file
(
'test_show_route_table_t_kernel4.txt'
))
correct_result
=
[
{
'prefix'
:
'172.16.100.0/24'
,
'primary'
:
None
,
'proto'
:
'kernel4'
,
'since'
:
'13:36:14.199'
,
'type'
:
[
'inherit'
,
'univ'
],
'weight'
:
'10'
,
'nexthops'
:
[{
'gateway'
:
'172.16.10.10'
,
'interface'
:
'eth9'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'10.0.1.0/24'
,
'primary'
:
'*'
,
'proto'
:
'static4'
,
'since'
:
'13:36:14.199'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'192.168.0.4'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'10.0.2.0/24'
,
'primary'
:
'*'
,
'proto'
:
'static4'
,
'since'
:
'13:36:14.199'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'192.168.0.5'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
}
]
assert
result
==
correct_result
,
'The show_route_table() result does not match what it should be'
def
test_show_route_table_t_kernel6
(
self
):
"""Test show_route_table."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_route_table
(
't_kernel6'
,
self
.
_load_file
(
'test_show_route_table_t_kernel6.txt'
))
correct_result
=
[
{
'prefix'
:
'fec0:20::/64'
,
'primary'
:
'*'
,
'proto'
:
'static6'
,
'since'
:
'13:36:14.708'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'fec0::5'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'fec0:10::/64'
,
'primary'
:
'*'
,
'proto'
:
'static6'
,
'since'
:
'13:36:14.708'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'fec0::4'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
}
]
assert
result
==
correct_result
,
'The show_route_table() result does not match what it should be'
def
test_show_route_table_t_ospf4
(
self
):
"""Test show_route_table."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_route_table
(
't_ospf4'
,
self
.
_load_file
(
'test_show_route_table_t_ospf4.txt'
))
correct_result
=
[
{
'prefix'
:
'172.16.100.0/24'
,
'primary'
:
None
,
'proto'
:
'kernel4'
,
'since'
:
'13:36:14.199'
,
'type'
:
[
'inherit'
,
'univ'
],
'weight'
:
'10'
,
'nexthops'
:
[{
'gateway'
:
'172.16.10.10'
,
'interface'
:
'eth9'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'10.0.1.0/24'
,
'primary'
:
'*'
,
'proto'
:
'static4'
,
'since'
:
'13:36:14.199'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'192.168.0.4'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'10.0.2.0/24'
,
'primary'
:
'*'
,
'proto'
:
'static4'
,
'since'
:
'13:36:14.199'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'192.168.0.5'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
}
]
assert
result
==
correct_result
,
'The show_route_table() result does not match what it should be'
def
test_show_route_table_t_ospf6_1
(
self
):
"""Test show_route_table."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_route_table
(
't_ospf6'
,
self
.
_load_file
(
'test_show_route_table_t_ospf6-1.txt'
))
correct_result
=
[
{
'prefix'
:
'fec0:20::/64'
,
'primary'
:
'*'
,
'proto'
:
'static6'
,
'since'
:
'13:36:14.708'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'fec0::5'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'prefix'
:
'fec0:10::/64'
,
'primary'
:
'*'
,
'proto'
:
'static6'
,
'since'
:
'13:36:14.708'
,
'type'
:
[
'static'
,
'univ'
],
'weight'
:
'200'
,
'nexthops'
:
[{
'gateway'
:
'fec0::4'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
}
]
assert
result
==
correct_result
,
'The show_route_table() result does not match what it should be'
def
test_show_route_table_t_ospf6_2
(
self
):
"""Test show_route_table."""
birdclient
=
BirdClient
()
result
=
birdclient
.
show_route_table
(
't_ospf6'
,
self
.
_load_file
(
'test_show_route_table_t_ospf6-2.txt'
))
correct_result
=
[
{
'metric1'
:
'20'
,
'metric2'
:
'10000'
,
'ospf_type'
:
'E2'
,
'pref'
:
'150'
,
'prefix'
:
'fec0:20::/64'
,
'proto'
:
'ospf6'
,
'router_id'
:
'172.16.10.1'
,
'since'
:
'14:20:00.666'
,
'tag'
:
None
,
'type'
:
[
'OSPF-E2'
,
'univ'
],
'nexthops'
:
[{
'gateway'
:
'fe80::8c84:28ff:fe6c:40ae'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'metric1'
:
'20'
,
'metric2'
:
'10000'
,
'ospf_type'
:
'E2'
,
'pref'
:
'150'
,
'prefix'
:
'fec0:10::/64'
,
'proto'
:
'ospf6'
,
'router_id'
:
'172.16.10.1'
,
'since'
:
'14:20:00.666'
,
'tag'
:
None
,
'type'
:
[
'OSPF-E2'
,
'univ'
],
'nexthops'
:
[{
'gateway'
:
'fe80::8c84:28ff:fe6c:40ae'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'metric1'
:
'20'
,
'metric2'
:
None
,
'ospf_type'
:
'I'
,
'pref'
:
'150'
,
'prefix'
:
'fec0::/64'
,
'proto'
:
'ospf6'
,
'router_id'
:
'172.16.10.1'
,
'since'
:
'14:19:58.660'
,
'tag'
:
None
,
'type'
:
[
'OSPF'
,
'univ'
],
'nexthops'
:
[{
'gateway'
:
'fe80::8c84:28ff:fe6c:40ae'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None
}]
},
{
'metric1'
:
'30'
,
'metric2'
:
None
,
'ospf_type'
:
'I'
,
'pref'
:
'150'
,
'prefix'
:
'fefe::/64'
,
'proto'
:
'ospf6'
,
'router_id'
:
'172.16.10.1'
,
'since'
:
'14:20:00.666'
,
'tag'
:
None
,
'type'
:
[
'OSPF'
,
'univ'
],
'nexthops'
:
[{
'gateway'
:
'fe80::8c84:28ff:fe6c:40ae'
,
'interface'
:
'eth0'
,
'mpls'
:
None
,
'onlink'
:
None
,
'weight'
:
None