Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
GÉANT Service Orchestrator
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
GÉANT Orchestration and Automation Team
GAP
GÉANT Service Orchestrator
Commits
91fe5d65
Commit
91fe5d65
authored
1 year ago
by
JORGE SASIAIN
Browse files
Options
Downloads
Plain Diff
NAT-244
: Merge develop and adjust attach_interface_to_lag and its test
parents
3258b4a5
3ba2d249
No related branches found
No related tags found
1 merge request
!88
Feature/nat 244 lag deletion
Pipeline
#84291
passed
1 year ago
Stage: tox
Stage: documentation
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
gso/services/netbox_client.py
+8
-2
8 additions, 2 deletions
gso/services/netbox_client.py
test/services/test_netbox.py
+237
-1
237 additions, 1 deletion
test/services/test_netbox.py
with
245 additions
and
3 deletions
gso/services/netbox_client.py
+
8
−
2
View file @
91fe5d65
...
@@ -208,8 +208,13 @@ class NetboxClient:
...
@@ -208,8 +208,13 @@ class NetboxClient:
)
)
iface
.
lag
=
lag
.
id
iface
.
lag
=
lag
.
id
# Set description if provided
if
description
:
iface
.
description
=
description
# Update physical interface
# Update physical interface
return
self
.
netbox
.
dcim
.
interfaces
.
update
([
iface
])[
0
]
iface
.
save
()
return
iface
def
detach_interface_from_lag
(
self
,
device_name
:
str
,
lag_name
:
str
,
iface_name
:
str
)
->
Interfaces
:
def
detach_interface_from_lag
(
self
,
device_name
:
str
,
lag_name
:
str
,
iface_name
:
str
)
->
Interfaces
:
"""
Remove a given physical interface from a lag.
"""
Remove a given physical interface from a lag.
...
@@ -237,7 +242,8 @@ class NetboxClient:
...
@@ -237,7 +242,8 @@ class NetboxClient:
iface
.
lag
=
None
iface
.
lag
=
None
# Update physical interface
# Update physical interface
return
self
.
netbox
.
dcim
.
interfaces
.
update
([
iface
])[
0
]
iface
.
save
()
return
iface
def
reserve_interface
(
self
,
device_name
:
str
,
iface_name
:
str
)
->
Interfaces
:
def
reserve_interface
(
self
,
device_name
:
str
,
iface_name
:
str
)
->
Interfaces
:
"""
Reserve an interface by enabling it.
"""
"""
Reserve an interface by enabling it.
"""
...
...
This diff is collapsed.
Click to expand it.
test/services/test_netbox.py
+
237
−
1
View file @
91fe5d65
from
unittest.mock
import
patch
"""
Unit tests for testing the netbox client.
"""
import
uuid
from
os
import
PathLike
from
unittest.mock
import
Mock
,
patch
import
pytest
import
pytest
from
pynetbox.core.response
import
Record
from
pynetbox.core.response
import
Record
from
gso.products.product_blocks.site
import
SiteTier
from
gso.services.netbox_client
import
NetboxClient
from
gso.services.netbox_client
import
NetboxClient
from
gso.utils.exceptions
import
WorkflowStateError
from
gso.utils.exceptions
import
WorkflowStateError
...
@@ -58,6 +63,237 @@ def interface():
...
@@ -58,6 +63,237 @@ def interface():
return
Record
(
values
,
None
,
None
)
return
Record
(
values
,
None
,
None
)
@pytest.fixture
(
scope
=
"
module
"
)
def
lag
():
values
=
{
"
id
"
:
1
,
"
name
"
:
"
lag-1
"
,
"
type
"
:
"
lag
"
,
}
return
Record
(
values
,
None
,
None
)
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_create_device
(
mock_api
,
device
,
device_type
,
device_role
,
site
,
device_bay
,
card_type
,
data_config_filename
:
PathLike
):
device_name
=
"
mx1.lab.geant.net
"
device
.
name
=
device_name
site_tier
=
SiteTier
.
TIER1
# Define mock calls
mock_api
.
return_value
.
dcim
.
device_types
.
get
.
return_value
=
device_type
mock_api
.
return_value
.
dcim
.
device_roles
.
get
.
return_value
=
device_role
mock_api
.
return_value
.
dcim
.
sites
.
get
.
return_value
=
site
mock_api
.
return_value
.
dcim
.
devices
.
create
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
module_bays
.
filter
.
return_value
=
[
device_bay
]
mock_api
.
return_value
.
dcim
.
module_types
.
get
.
return_value
=
card_type
mock_api
.
return_value
.
dcim
.
module_types
.
create
.
return_value
=
card_type
new_device
=
NetboxClient
().
create_device
(
device_name
,
site_tier
)
assert
new_device
is
not
None
assert
new_device
.
name
==
device_name
@patch
(
"
gso.services.netbox_client.Router.from_subscription
"
)
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_get_available_lags
(
mock_api
,
mock_from_subscription
,
data_config_filename
:
PathLike
):
router_id
=
uuid
.
uuid4
()
feasible_lags
=
[
f
"
LAG-
{
i
}
"
for
i
in
range
(
1
,
11
)]
# Mock the pynetbox API instance
mock_netbox
=
mock_api
.
return_value
mock_filter
=
mock_netbox
.
dcim
.
interfaces
.
filter
mock_filter
.
return_value
=
[{
"
name
"
:
f
"
LAG-
{
i
}
"
,
"
type
"
:
"
lag
"
}
for
i
in
range
(
1
,
4
)]
# Mock the Router.from_subscription method
mock_subscription
=
mock_from_subscription
.
return_value
mock_router
=
mock_subscription
.
router
mock_router
.
router_fqdn
=
"
test_router
"
netbox_client
=
NetboxClient
()
result
=
netbox_client
.
get_available_lags
(
router_id
)
# Check the result of the function
assert
result
==
[
lag
for
lag
in
feasible_lags
if
lag
not
in
[
f
"
LAG-
{
i
}
"
for
i
in
range
(
1
,
4
)]]
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_create_interface
(
mock_api
,
device
,
interface
,
data_config_filename
:
PathLike
):
# Moch netbox calls
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
interfaces
.
create
.
return_value
=
interface
# Create new interface
new_interface
=
NetboxClient
().
create_interface
(
interface
.
name
,
interface
.
type
,
interface
.
speed
,
device
.
name
)
# Check result
assert
new_interface
is
not
None
assert
new_interface
.
name
==
interface
.
name
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_reserve_interface_exception
(
mock_api
,
device
,
interface
,
data_config_filename
:
PathLike
):
"""
Test for checking if interface is reserved.
If the interface is already reserved
the method should throw an exception
"""
# Change the interface to reserved
interface
.
enabled
=
True
# expected exception message
exception_message
=
f
"
The interface:
{
interface
.
name
}
on device:
{
device
.
name
}
is already reserved.
"
# Mock netbox api
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
interfaces
.
get
.
return_value
=
interface
# Check exception
with
pytest
.
raises
(
WorkflowStateError
)
as
test_exception
:
NetboxClient
().
reserve_interface
(
device
.
name
,
interface
.
name
)
assert
str
(
test_exception
.
value
)
==
exception_message
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_reserve_interface
(
mock_api
,
device
,
interface
,
data_config_filename
:
PathLike
):
"""
Test a normal reservation of a interface.
"""
# Set interface to not reserved
interface
.
enabled
=
False
# Mock netbox api
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
interfaces
.
get
.
return_value
=
interface
# mock save method
mock_save
=
Mock
()
mock_save
.
save
.
return_value
=
interface
interface
.
save
=
mock_save
# Check reservation of interface
updated_interface
=
NetboxClient
().
reserve_interface
(
device
.
name
,
interface
.
name
)
assert
updated_interface
is
not
None
assert
updated_interface
.
enabled
is
True
mock_save
.
assert_called_once
()
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_allocate_interface_exception
(
mock_api
,
device
,
interface
,
data_config_filename
:
PathLike
):
"""
Test to check exception during allocation.
If the interface is already allocated
the method should throw an exception
"""
# Change the interface to reserved
interface
.
enabled
=
True
# Change interface to allocated
interface
.
mark_connected
=
True
# expected exception message
exception_message
=
f
"
The interface:
{
interface
.
name
}
on device:
{
device
.
name
}
is already allocated.
"
# Mock netbox api
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
interfaces
.
get
.
return_value
=
interface
# Check exception
with
pytest
.
raises
(
WorkflowStateError
)
as
test_exception
:
NetboxClient
().
allocate_interface
(
device
.
name
,
interface
.
name
)
assert
str
(
test_exception
.
value
)
==
exception_message
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_allocation_interface
(
mock_api
,
device
,
interface
,
data_config_filename
:
PathLike
):
"""
Test a normal allocation of a interface.
"""
# Set interface to not allocated
interface
.
mark_connected
=
False
# Mock netbox api
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
interfaces
.
get
.
return_value
=
interface
# mock save method
mock_save
=
Mock
()
mock_save
.
save
.
return_value
=
interface
interface
.
save
=
mock_save
# Check allocation of interface
updated_interface
=
NetboxClient
().
allocate_interface
(
device
.
name
,
interface
.
name
)
assert
updated_interface
is
not
None
assert
updated_interface
.
mark_connected
is
True
mock_save
.
assert_called_once
()
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_delete_device
(
mock_api
,
device
,
data_config_filename
:
PathLike
):
"""
Test a delete of a device.
"""
# Mock netbox api
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
# mock delete method
mock_delete
=
Mock
()
device
.
delete
=
mock_delete
# Check delete of interface
NetboxClient
().
delete_device
(
device
.
name
)
mock_delete
.
assert_called_once
()
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_get_interfaces_by_device
(
mock_api
,
device
,
interface
,
data_config_filename
:
PathLike
):
"""
Test if a interface is returned for a device.
"""
# Setup interface speed
speed
=
1000
# Mock netbox api
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
interfaces
.
filter
.
return_value
=
[
interface
,
interface
]
# Call get interfaces by device
interfaces
=
NetboxClient
().
get_interfaces_by_device
(
device
.
name
,
speed
)
assert
interfaces
is
not
None
assert
len
(
interfaces
)
==
2
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_attach_interface_to_lag
(
mock_api
,
device
,
interface
,
lag
,
data_config_filename
:
PathLike
):
"""
Test if a interface is attached correctly to a lag interface.
"""
# Define site effect function
def
get_side_effect
(
**
kwargs
):
if
kwargs
.
get
(
"
device_id
"
)
==
1
and
kwargs
.
get
(
"
name
"
)
==
"
lag-1
"
:
return
lag
return
interface
# Define a description
description
=
"
test123
"
# At first the interface is not attached to a lag
interface
.
lag
=
None
# Mock netbox api
mock_api
.
return_value
.
dcim
.
devices
.
get
.
return_value
=
device
mock_api
.
return_value
.
dcim
.
interfaces
.
get
.
side_effect
=
get_side_effect
# mock save method
mock_save
=
Mock
()
mock_save
.
save
.
return_value
=
interface
interface
.
save
=
mock_save
# Check if interface attached to lag
lag_interface
=
NetboxClient
().
attach_interface_to_lag
(
device
.
name
,
lag
.
name
,
interface
.
name
,
description
)
assert
lag_interface
is
not
None
assert
lag_interface
.
lag
==
lag
.
id
assert
lag_interface
.
description
==
description
mock_save
.
assert_called_once
()
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
@patch
(
"
gso.services.netbox_client.pynetbox.api
"
)
def
test_free_interface
(
mock_api
,
device
,
interface
):
def
test_free_interface
(
mock_api
,
device
,
interface
):
device_name
=
"
mx1.lab.geant.net
"
device_name
=
"
mx1.lab.geant.net
"
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment