Skip to content
Snippets Groups Projects
Commit 1692073f authored by Karel van Klink's avatar Karel van Klink :smiley_cat: Committed by Neda Moeini
Browse files

Add IP Trunk validation workflow

parent be7d176d
No related branches found
No related tags found
1 merge request!139Feature/add validation workflows
"""Add IP Trunk validation workflow.
Revision ID: a1a69e7554c4
Revises: 75c63ad44cbb
Create Date: 2024-01-11 15:57:57.534785
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = 'a1a69e7554c4'
down_revision = '75c63ad44cbb'
branch_labels = None
depends_on = None
from orchestrator.migrations.helpers import create_workflow, delete_workflow
new_workflows = [
{
"name": "validate_iptrunk",
"target": "SYSTEM",
"description": "Validate IP trunk configuration",
"product_type": "Iptrunk"
}
]
def upgrade() -> None:
conn = op.get_bind()
for workflow in new_workflows:
create_workflow(conn, workflow)
def downgrade() -> None:
conn = op.get_bind()
for workflow in new_workflows:
delete_workflow(conn, workflow["name"])
......@@ -32,6 +32,7 @@ LazyWorkflowInstance("gso.workflows.iptrunk.migrate_iptrunk", "migrate_iptrunk")
LazyWorkflowInstance("gso.workflows.iptrunk.terminate_iptrunk", "terminate_iptrunk")
LazyWorkflowInstance("gso.workflows.iptrunk.create_imported_iptrunk", "create_imported_iptrunk")
LazyWorkflowInstance("gso.workflows.iptrunk.import_iptrunk", "import_iptrunk")
LazyWorkflowInstance("gso.workflows.iptrunk.validate_iptrunk", "validate_iptrunk")
# Router workflows
LazyWorkflowInstance("gso.workflows.router.activate_router", "activate_router")
......
"""Router validation workflow. Used in a nightly schedule."""
import json
from orchestrator.targets import Target
from orchestrator.utils.errors import ProcessFailureError
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 gso.products.product_types.iptrunk import Iptrunk
from gso.services import infoblox
from gso.services.provisioning_proxy import execute_playbook, pp_interaction
@step("Validate IP trunk configuration")
def validate_router_config(subscription: Iptrunk, callback_route: str) -> None:
"""Run an Ansible playbook that validates the configuration that is present on an active IP trunk."""
extra_vars = {"wfo_trunk_json": json.loads(json_dumps(subscription)), "verb": "validate"}
execute_playbook(
playbook_name="base_config.yaml",
callback_route=callback_route,
inventory=f"{subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn}\n"
f"{subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn}\n",
extra_vars=extra_vars,
)
@step("Verify IPAM resources for LAG interfaces")
def verify_ipam_loopback(subscription: Iptrunk) -> None:
"""Validate the :term:`IPAM` resources for the :term:`LAG` interfaces.
Raises an :class:`orchestrator.utils.errors.ProcessFailureError` if IPAM is configured incorrectly.
"""
ipam_errors = []
ipam_v4_network = infoblox.find_network_by_cidr(subscription.iptrunk.iptrunk_ipv4_network)
ipam_v6_network = infoblox.find_network_by_cidr(subscription.iptrunk.iptrunk_ipv6_network)
if not ipam_v4_network or not ipam_v6_network:
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}"
)
# 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 subscription.subscription_id not in record.comment:
ipam_errors += f"Found a misconfigured IPAM entry for {lag_fqdn}. Received: {record}"
if ipam_errors:
raise ProcessFailureError(str(ipam_errors))
@workflow(
"Validate IP trunk configuration",
target=Target.SYSTEM,
initial_input_form=wrap_modify_initial_input_form(None),
)
def validate_iptrunk() -> StepList:
"""Validate an existing, active IP Trunk subscription.
* Run an Ansible playbook to verify the configuration is intact.
* Verify that the LAG interfaces are correctly configured in IPAM.
"""
return (
init
>> store_process_subscription(Target.SYSTEM)
>> unsync
>> pp_interaction(validate_router_config)
>> verify_ipam_loopback
>> resync
>> done
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment