diff --git a/gso/workflows/iptrunk/validate_iptrunk.py b/gso/workflows/iptrunk/validate_iptrunk.py index 2eac8ce4d228a73580b9fe7be318dadb00ffaa08..a66cb41986f9117447e81939afb608507d925b8a 100644 --- a/gso/workflows/iptrunk/validate_iptrunk.py +++ b/gso/workflows/iptrunk/validate_iptrunk.py @@ -8,10 +8,14 @@ from orchestrator.utils.json import json_dumps from orchestrator.workflow import StepList, done, init, step, workflow from orchestrator.workflows.steps import resync, store_process_subscription, unsync from orchestrator.workflows.utils import wrap_modify_initial_input_form +from workflows.iptrunk.deploy_twamp import deploy_twamp_dry +from workflows.iptrunk.migrate_iptrunk import check_ip_trunk_isis +from workflows.iptrunk.modify_trunk_interface import provision_ip_trunk_iface_dry from gso.products.product_types.iptrunk import Iptrunk from gso.services import infoblox -from gso.services.lso_client import execute_playbook, lso_interaction +from gso.services.lso_client import anonymous_lso_interaction, execute_playbook +from gso.utils.workflow_steps import detect_configuration_drift @step("Validate IP trunk configuration") @@ -29,7 +33,7 @@ def validate_router_config(subscription: Iptrunk, callback_route: str) -> None: @step("Verify IPAM resources for LAG interfaces") -def verify_ipam_loopback(subscription: Iptrunk) -> None: +def verify_ipam_records(subscription: Iptrunk) -> None: """Validate the :term:`IPAM` resources for the :term:`LAG` interfaces. Raises an :class:`orchestrator.utils.errors.ProcessFailureError` if :term:`IPAM` is configured incorrectly. @@ -42,23 +46,68 @@ def verify_ipam_loopback(subscription: Iptrunk) -> None: ipam_errors += [ ( "Missing IP trunk IPAM records, found the following instead.\n" - f"IPv4 expected {subscription.iptrunk.iptrunk_ipv4_network}, actual: {ipam_v4_network}\n" - f"IPv6 expected {subscription.iptrunk.iptrunk_ipv6_network}, actual: {ipam_v6_network}" + f"IPv4 expected {subscription.iptrunk.iptrunk_ipv4_network}, actual: {ipam_v4_network.network}\n" + f"IPv6 expected {subscription.iptrunk.iptrunk_ipv6_network}, actual: {ipam_v6_network.network}" ) ] - # Validate both sides of the trunk. - for trunk_side in subscription.iptrunk.iptrunk_sides: - lag_fqdn = f"{trunk_side.iptrunk_side_ae_iface}.{trunk_side.iptrunk_side_node.router_fqdn}" - # Validate both IPv4 and IPv6 records. - for record in [infoblox.find_host_by_fqdn(lag_fqdn), infoblox.find_v6_host_by_fqdn(lag_fqdn)]: - if not record: - ipam_errors += [f"Missing IPAM record for LAG interface {lag_fqdn}."] - elif str(subscription.subscription_id) not in record.comment: - ipam_errors += [f"Found a misconfigured IPAM entry for {lag_fqdn}. Received: {record}"] + for index, side in enumerate(subscription.iptrunk.iptrunk_sides): + lag_fqdn = f"{side.iptrunk_side_ae_iface}.{side.iptrunk_side_node.router_fqdn}" + side_v4 = subscription.iptrunk.iptrunk_ipv4_network[index] + side_v6 = subscription.iptrunk.iptrunk_ipv6_network[index + 1] + # Validate IPv4 address allocation + record = infoblox.find_host_by_fqdn(lag_fqdn) + if not record: + ipam_errors += [f"No IPv4 host record found with FQDN {lag_fqdn}"] + else: + # Allocation inside IPv4 network must be correct + if str(side_v4) != record.ipv4addr: + ipam_errors += [ + ( + f"Incorrectly allocated host record for FQDN {lag_fqdn}.\n" + f"Expected {side_v4}, actual: {record.ipv4addr}" + ) + ] + + # Allocated host record needs to be set correctly + if record.comment != subscription.subscription_id: + ipam_errors += [ + ( + f"Incorrect host record found for {lag_fqdn} at {side_v4}. Comment should have been equal to" + f"subscription ID {subscription.subscription_id}." + ) + ] + + # Validate IPv6 address allocation + record = infoblox.find_v6_host_by_fqdn(lag_fqdn) + if not record: + ipam_errors += [f"No IPv6 host record found with FQDN {lag_fqdn}"] + else: + # Allocation inside IPv6 network must be correct + if str(side_v6) != record.ipv6addr: + ipam_errors += [ + ( + f"Incorrectly allocated host record for FQDN {lag_fqdn}.\n" + f"Expected {side_v6}, actual: {record.ipv6addr}" + ) + ] + + # Allocated host record needs to be set correctly + if record.comment != subscription.subscription_id: + ipam_errors += [ + ( + f"Incorrect host record found for {lag_fqdn} at {side_v6}. Comment should have been equal to" + f"subscription ID {subscription.subscription_id}." + ) + ] if ipam_errors: - raise ProcessFailureError(str(ipam_errors)) + raise ProcessFailureError(message="IPAM misconfiguration(s) found", details=str(ipam_errors)) + + +@step("Verify Netbox entries") +def verify_netbox_entries() -> None: + """Validate required entries for an IP trunk in Netbox.""" @workflow( @@ -76,8 +125,11 @@ def validate_iptrunk() -> StepList: init >> store_process_subscription(Target.SYSTEM) >> unsync - >> lso_interaction(validate_router_config) - >> verify_ipam_loopback + >> verify_ipam_records + >> verify_netbox_entries + >> anonymous_lso_interaction(provision_ip_trunk_iface_dry, detect_configuration_drift) + >> anonymous_lso_interaction(check_ip_trunk_isis) + >> anonymous_lso_interaction(deploy_twamp_dry, detect_configuration_drift) >> resync >> done )