Skip to content

Commit b9ee849

Browse files
committed
extend main script to configure routes after LIFs
1 parent 05abb6d commit b9ee849

File tree

2 files changed

+93
-24
lines changed

2 files changed

+93
-24
lines changed

python/understack-workflows/tests/test_netapp_configure_net.py

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
from understack_workflows.main.netapp_configure_net import argument_parser
1414
from understack_workflows.main.netapp_configure_net import construct_device_name
1515
from understack_workflows.main.netapp_configure_net import execute_graphql_query
16-
from understack_workflows.main.netapp_configure_net import netapp_create_interfaces
16+
from understack_workflows.main.netapp_configure_net import (
17+
netapp_create_interfaces_and_routes,
18+
)
1719
from understack_workflows.main.netapp_configure_net import (
1820
validate_and_transform_response,
1921
)
@@ -1355,6 +1357,8 @@ def test_netapp_create_interfaces_with_single_interface(self):
13551357
"""Test creating NetApp interfaces with single interface configuration."""
13561358
# Mock NetAppManager
13571359
mock_netapp_manager = Mock()
1360+
# Mock route creation to return empty list
1361+
mock_netapp_manager.create_routes_for_project.return_value = []
13581362

13591363
# Create test data
13601364
interface = InterfaceInfo(name="N1-lif-A", address="100.127.0.21/29", vlan=2002)
@@ -1370,7 +1374,9 @@ def test_netapp_create_interfaces_with_single_interface(self):
13701374
mock_config_class.from_nautobot_response.return_value = [mock_config]
13711375

13721376
# Call the function
1373-
netapp_create_interfaces(mock_netapp_manager, vm_network_info, project_id)
1377+
netapp_create_interfaces_and_routes(
1378+
mock_netapp_manager, vm_network_info, project_id
1379+
)
13741380

13751381
# Verify NetappIPInterfaceConfig.from_nautobot_response was called
13761382
mock_config_class.from_nautobot_response.assert_called_once_with(
@@ -1382,10 +1388,16 @@ def test_netapp_create_interfaces_with_single_interface(self):
13821388
project_id, mock_config
13831389
)
13841390

1391+
# Verify create_routes_for_project was called with correct parameters
1392+
mock_netapp_manager.create_routes_for_project.assert_called_once_with(
1393+
project_id, [mock_config]
1394+
)
1395+
13851396
def test_netapp_create_interfaces_with_multiple_interfaces(self):
13861397
"""Test creating NetApp interfaces with multiple interface configurations."""
13871398
# Mock NetAppManager
13881399
mock_netapp_manager = Mock()
1400+
mock_netapp_manager.create_routes_for_project.return_value = []
13891401

13901402
# Create test data with multiple interfaces
13911403
interfaces = [
@@ -1410,7 +1422,9 @@ def test_netapp_create_interfaces_with_multiple_interfaces(self):
14101422
mock_config_class.from_nautobot_response.return_value = mock_configs
14111423

14121424
# Call the function
1413-
netapp_create_interfaces(mock_netapp_manager, vm_network_info, project_id)
1425+
netapp_create_interfaces_and_routes(
1426+
mock_netapp_manager, vm_network_info, project_id
1427+
)
14141428

14151429
# Verify NetappIPInterfaceConfig.from_nautobot_response was called
14161430
mock_config_class.from_nautobot_response.assert_called_once_with(
@@ -1425,10 +1439,16 @@ def test_netapp_create_interfaces_with_multiple_interfaces(self):
14251439
assert call.args[0] == project_id
14261440
assert call.args[1] == mock_configs[i]
14271441

1442+
# Verify create_routes_for_project was called with correct parameters
1443+
mock_netapp_manager.create_routes_for_project.assert_called_once_with(
1444+
project_id, mock_configs
1445+
)
1446+
14281447
def test_netapp_create_interfaces_with_empty_interfaces(self):
14291448
"""Test creating NetApp interfaces with empty interface list."""
14301449
# Mock NetAppManager
14311450
mock_netapp_manager = Mock()
1451+
mock_netapp_manager.create_routes_for_project.return_value = []
14321452

14331453
# Create test data with no interfaces
14341454
vm_network_info = VirtualMachineNetworkInfo(interfaces=[])
@@ -1441,7 +1461,9 @@ def test_netapp_create_interfaces_with_empty_interfaces(self):
14411461
mock_config_class.from_nautobot_response.return_value = []
14421462

14431463
# Call the function
1444-
netapp_create_interfaces(mock_netapp_manager, vm_network_info, project_id)
1464+
netapp_create_interfaces_and_routes(
1465+
mock_netapp_manager, vm_network_info, project_id
1466+
)
14451467

14461468
# Verify NetappIPInterfaceConfig.from_nautobot_response was called
14471469
mock_config_class.from_nautobot_response.assert_called_once_with(
@@ -1451,11 +1473,17 @@ def test_netapp_create_interfaces_with_empty_interfaces(self):
14511473
# Verify create_lif was not called
14521474
mock_netapp_manager.create_lif.assert_not_called()
14531475

1476+
# Verify create_routes_for_project was called with empty list
1477+
mock_netapp_manager.create_routes_for_project.assert_called_once_with(
1478+
project_id, []
1479+
)
1480+
14541481
def test_netapp_create_interfaces_propagates_netapp_manager_exceptions(self):
14551482
"""Test that NetAppManager exceptions are propagated correctly."""
14561483
# Mock NetAppManager that raises exception
14571484
mock_netapp_manager = Mock()
14581485
mock_netapp_manager.create_lif.side_effect = Exception("SVM Not Found")
1486+
mock_netapp_manager.create_routes_for_project.return_value = []
14591487

14601488
# Create test data
14611489
interface = InterfaceInfo(name="N1-lif-A", address="100.127.0.21/29", vlan=2002)
@@ -1472,7 +1500,7 @@ def test_netapp_create_interfaces_propagates_netapp_manager_exceptions(self):
14721500

14731501
# Call the function and expect exception to be propagated
14741502
with pytest.raises(Exception, match="SVM Not Found"):
1475-
netapp_create_interfaces(
1503+
netapp_create_interfaces_and_routes(
14761504
mock_netapp_manager, vm_network_info, project_id
14771505
)
14781506

@@ -1485,6 +1513,7 @@ def test_netapp_create_interfaces_logs_interface_creation(self):
14851513
"""Test that interface creation is properly logged."""
14861514
# Mock NetAppManager
14871515
mock_netapp_manager = Mock()
1516+
mock_netapp_manager.create_routes_for_project.return_value = []
14881517

14891518
# Create test data
14901519
interface = InterfaceInfo(
@@ -1506,19 +1535,28 @@ def test_netapp_create_interfaces_logs_interface_creation(self):
15061535
"understack_workflows.main.netapp_configure_net.logger"
15071536
) as mock_logger:
15081537
# Call the function
1509-
netapp_create_interfaces(
1538+
netapp_create_interfaces_and_routes(
15101539
mock_netapp_manager, vm_network_info, project_id
15111540
)
15121541

1513-
# Verify logging was called with correct message
1514-
mock_logger.info.assert_called_once_with(
1515-
"Creating LIF %s for project %s", "test-interface", project_id
1542+
# Verify logging was called with correct messages
1543+
expected_calls = [
1544+
(("Creating LIF %s for project %s", "test-interface", project_id),),
1545+
(("Creating routes for project %s", project_id),),
1546+
(("Successfully created %d routes for project %s", 0, project_id),),
1547+
]
1548+
mock_logger.info.assert_has_calls(expected_calls, any_order=False)
1549+
1550+
# Verify create_routes_for_project was called
1551+
mock_netapp_manager.create_routes_for_project.assert_called_once_with(
1552+
project_id, [mock_config]
15161553
)
15171554

15181555
def test_netapp_create_interfaces_with_realistic_data(self):
15191556
"""Test creating NetApp interfaces with realistic interface data."""
15201557
# Mock NetAppManager
15211558
mock_netapp_manager = Mock()
1559+
mock_netapp_manager.create_routes_for_project.return_value = []
15221560

15231561
# Load realistic test data from JSON sample
15241562
sample_data = load_json_sample("nautobot_graphql_vm_response_complex.json")
@@ -1541,7 +1579,9 @@ def test_netapp_create_interfaces_with_realistic_data(self):
15411579
mock_config_class.from_nautobot_response.return_value = mock_configs
15421580

15431581
# Call the function
1544-
netapp_create_interfaces(mock_netapp_manager, vm_network_info, project_id)
1582+
netapp_create_interfaces_and_routes(
1583+
mock_netapp_manager, vm_network_info, project_id
1584+
)
15451585

15461586
# Verify NetappIPInterfaceConfig.from_nautobot_response was called
15471587
mock_config_class.from_nautobot_response.assert_called_once_with(
@@ -1557,10 +1597,16 @@ def test_netapp_create_interfaces_with_realistic_data(self):
15571597
assert call_args.args[0] == project_id
15581598
assert call_args.args[1] == mock_configs[i]
15591599

1600+
# Verify create_routes_for_project was called with correct parameters
1601+
mock_netapp_manager.create_routes_for_project.assert_called_once_with(
1602+
project_id, mock_configs
1603+
)
1604+
15601605
def test_netapp_create_interfaces_return_value(self):
15611606
"""Test that netapp_create_interfaces returns None."""
15621607
# Mock NetAppManager
15631608
mock_netapp_manager = Mock()
1609+
mock_netapp_manager.create_routes_for_project.return_value = []
15641610

15651611
# Create test data
15661612
interface = InterfaceInfo(name="N1-lif-A", address="100.127.0.21/29", vlan=2002)
@@ -1576,11 +1622,16 @@ def test_netapp_create_interfaces_return_value(self):
15761622
mock_config_class.from_nautobot_response.return_value = [mock_config]
15771623

15781624
# Call the function and verify return value
1579-
result = netapp_create_interfaces(
1625+
result = netapp_create_interfaces_and_routes(
15801626
mock_netapp_manager, vm_network_info, project_id
15811627
)
15821628
assert result is None
15831629

1630+
# Verify create_routes_for_project was called
1631+
mock_netapp_manager.create_routes_for_project.assert_called_once_with(
1632+
project_id, [mock_config]
1633+
)
1634+
15841635

15851636
class TestArgumentParserNetappConfigPath:
15861637
"""Test cases for the --netapp-config-path argument."""
@@ -1683,6 +1734,7 @@ def test_main_function_initializes_netapp_manager_with_default_path(
16831734

16841735
# Mock NetAppManager
16851736
mock_netapp_manager_instance = Mock()
1737+
mock_netapp_manager_instance.create_routes_for_project.return_value = []
16861738
mock_netapp_manager_class.return_value = mock_netapp_manager_instance
16871739

16881740
# Mock sys.argv with default netapp config path
@@ -1739,6 +1791,7 @@ def test_main_function_initializes_netapp_manager_with_custom_path(
17391791

17401792
# Mock NetAppManager
17411793
mock_netapp_manager_instance = Mock()
1794+
mock_netapp_manager_instance.create_routes_for_project.return_value = []
17421795
mock_netapp_manager_class.return_value = mock_netapp_manager_instance
17431796

17441797
# Mock sys.argv with custom netapp config path
@@ -1811,18 +1864,20 @@ def test_main_function_handles_netapp_manager_initialization_error(
18111864
"/etc/netapp/netapp_nvme.conf"
18121865
)
18131866

1814-
@patch("understack_workflows.main.netapp_configure_net.netapp_create_interfaces")
1867+
@patch(
1868+
"understack_workflows.main.netapp_configure_net.netapp_create_interfaces_and_routes"
1869+
)
18151870
@patch("understack_workflows.main.netapp_configure_net.NetAppManager")
18161871
@patch("understack_workflows.main.netapp_configure_net.Nautobot")
18171872
@patch("understack_workflows.main.netapp_configure_net.credential")
18181873
@patch("understack_workflows.main.netapp_configure_net.setup_logger")
1819-
def test_main_function_calls_netapp_create_interfaces(
1874+
def test_main_function_calls_netapp_create_interfaces_and_routes(
18201875
self,
18211876
mock_setup_logger,
18221877
mock_credential,
18231878
mock_nautobot_class,
18241879
mock_netapp_manager_class,
1825-
mock_netapp_create_interfaces,
1880+
mock_netapp_create_interfaces_and_routes,
18261881
):
18271882
"""Test that main function calls netapp_create_interfaces through do_action."""
18281883
from understack_workflows.main.netapp_configure_net import main
@@ -1847,6 +1902,7 @@ def test_main_function_calls_netapp_create_interfaces(
18471902

18481903
# Mock NetAppManager
18491904
mock_netapp_manager_instance = Mock()
1905+
mock_netapp_manager_instance.create_routes_for_project.return_value = []
18501906
mock_netapp_manager_class.return_value = mock_netapp_manager_instance
18511907

18521908
# Mock sys.argv
@@ -1865,11 +1921,11 @@ def test_main_function_calls_netapp_create_interfaces(
18651921
# Verify successful execution
18661922
assert result == 0
18671923

1868-
# Verify netapp_create_interfaces was called
1869-
mock_netapp_create_interfaces.assert_called_once()
1870-
call_args = mock_netapp_create_interfaces.call_args
1924+
# Verify netapp_create_interfaces_and_routes was called
1925+
mock_netapp_create_interfaces_and_routes.assert_called_once()
1926+
call_args = mock_netapp_create_interfaces_and_routes.call_args
18711927

1872-
# Verify the arguments passed to netapp_create_interfaces
1928+
# Verify the arguments passed to netapp_create_interfaces_and_routes
18731929
assert (
18741930
call_args.args[0] == mock_netapp_manager_instance
18751931
) # NetAppManager instance

python/understack-workflows/understack_workflows/main/netapp_configure_net.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,25 +322,27 @@ def do_action(
322322
raise SystemExit(2) from e
323323

324324
if validated_data:
325-
netapp_create_interfaces(netapp_manager, validated_data[0], project_id)
325+
netapp_create_interfaces_and_routes(
326+
netapp_manager, validated_data[0], project_id
327+
)
326328

327329
# Return structured data objects
328330
return raw_response, validated_data
329331

330332

331-
def netapp_create_interfaces(
333+
def netapp_create_interfaces_and_routes(
332334
mgr: NetAppManager,
333335
nautobot_response: VirtualMachineNetworkInfo,
334336
project_id: str,
335337
) -> None:
336-
"""Create NetApp LIF interfaces based on Nautobot VM network configuration.
338+
"""Create NetApp LIF interfaces and routes based on Nautobot VM network config.
337339
338340
This function converts the validated Nautobot response into NetApp interface
339341
configurations and creates the corresponding LIF (Logical Interface) on the
340-
NetApp storage system.
342+
NetApp storage system, followed by creating routes for network connectivity.
341343
342344
Args:
343-
mgr: NetAppManager instance for creating LIF interfaces
345+
mgr: NetAppManager instance for creating LIF interfaces and routes
344346
nautobot_response: Validated virtual machine network information from
345347
Nautobot
346348
project_id: OpenStack project ID for logging and context
@@ -350,14 +352,25 @@ def netapp_create_interfaces(
350352
351353
Raises:
352354
Exception: If SVM for the project is not found
353-
NetAppRestError: If LIF creation fails on the NetApp system
355+
NetAppRestError: If LIF creation or route creation fails on the NetApp system
354356
"""
357+
# Create interface configurations
355358
configs = NetappIPInterfaceConfig.from_nautobot_response(
356359
nautobot_response, mgr.config
357360
)
361+
362+
# Create LIF interfaces (existing functionality)
358363
for interface_config in configs:
359364
logger.info("Creating LIF %s for project %s", interface_config.name, project_id)
360365
mgr.create_lif(project_id, interface_config)
366+
367+
# Create routes (new functionality)
368+
logger.info("Creating routes for project %s", project_id)
369+
route_results = mgr.create_routes_for_project(project_id, configs)
370+
371+
logger.info(
372+
"Successfully created %d routes for project %s", len(route_results), project_id
373+
)
361374
return
362375

363376

0 commit comments

Comments
 (0)