mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
211 lines
5.6 KiB
Python
211 lines
5.6 KiB
Python
"""Validate VRF configuration variables."""
|
|
|
|
# Standard Library Imports
|
|
from ipaddress import IPv4Address
|
|
from ipaddress import IPv4Network
|
|
from ipaddress import IPv6Address
|
|
from ipaddress import IPv6Network
|
|
from typing import List
|
|
from typing import Optional
|
|
|
|
# Third Party Imports
|
|
from pydantic import FilePath
|
|
from pydantic import StrictBool
|
|
from pydantic import StrictStr
|
|
from pydantic import conint
|
|
from pydantic import constr
|
|
from pydantic import root_validator
|
|
from pydantic import validator
|
|
|
|
# Project Imports
|
|
from hyperglass.configuration.models._utils import HyperglassModel
|
|
from hyperglass.configuration.models._utils import HyperglassModelExtra
|
|
|
|
|
|
class AccessList4(HyperglassModel):
|
|
"""Validation model for IPv4 access-lists."""
|
|
|
|
network: IPv4Network = "0.0.0.0/0"
|
|
action: constr(regex="permit|deny") = "permit"
|
|
ge: conint(ge=0, le=32) = 0
|
|
le: conint(ge=0, le=32) = 32
|
|
|
|
@validator("ge")
|
|
def validate_model(cls, value, values):
|
|
"""Ensure ge is at least the size of the input prefix.
|
|
|
|
Arguments:
|
|
value {int} -- Initial ge value
|
|
values {dict} -- Other post-validation fields
|
|
|
|
Returns:
|
|
{int} -- Validated ge value
|
|
"""
|
|
net_len = values["network"].prefixlen
|
|
if net_len > value:
|
|
value = net_len
|
|
return value
|
|
|
|
|
|
class AccessList6(HyperglassModel):
|
|
"""Validation model for IPv6 access-lists."""
|
|
|
|
network: IPv6Network = "::/0"
|
|
action: constr(regex=r"permit|deny") = "permit"
|
|
ge: conint(ge=0, le=128) = 0
|
|
le: conint(ge=0, le=128) = 128
|
|
|
|
@validator("ge")
|
|
def validate_model(cls, value, values):
|
|
"""Ensure ge is at least the size of the input prefix.
|
|
|
|
Arguments:
|
|
value {int} -- Initial ge value
|
|
values {dict} -- Other post-validation fields
|
|
|
|
Returns:
|
|
{int} -- Validated ge value
|
|
"""
|
|
net_len = values["network"].prefixlen
|
|
if net_len > value:
|
|
value = net_len
|
|
return value
|
|
|
|
|
|
class InfoConfigParams(HyperglassModelExtra):
|
|
"""Validation model for per-help params."""
|
|
|
|
title: Optional[StrictStr]
|
|
|
|
|
|
class InfoConfig(HyperglassModel):
|
|
"""Validation model for help configuration."""
|
|
|
|
enable: StrictBool = True
|
|
file: Optional[FilePath]
|
|
params: InfoConfigParams = InfoConfigParams()
|
|
|
|
|
|
class Info(HyperglassModel):
|
|
"""Validation model for per-VRF, per-Command help."""
|
|
|
|
bgp_aspath: InfoConfig = InfoConfig()
|
|
bgp_community: InfoConfig = InfoConfig()
|
|
bgp_route: InfoConfig = InfoConfig()
|
|
ping: InfoConfig = InfoConfig()
|
|
traceroute: InfoConfig = InfoConfig()
|
|
|
|
|
|
class DeviceVrf4(HyperglassModelExtra):
|
|
"""Validation model for IPv4 AFI definitions."""
|
|
|
|
source_address: IPv4Address
|
|
access_list: List[AccessList4] = [AccessList4()]
|
|
|
|
|
|
class DeviceVrf6(HyperglassModelExtra):
|
|
"""Validation model for IPv6 AFI definitions."""
|
|
|
|
source_address: IPv6Address
|
|
access_list: List[AccessList6] = [AccessList6()]
|
|
|
|
|
|
class Vrf(HyperglassModel):
|
|
"""Validation model for per VRF/afi config in devices.yaml."""
|
|
|
|
name: StrictStr
|
|
display_name: StrictStr
|
|
info: Info = Info()
|
|
ipv4: Optional[DeviceVrf4]
|
|
ipv6: Optional[DeviceVrf6]
|
|
|
|
@root_validator
|
|
def set_dynamic(cls, values):
|
|
"""Set dynamic attributes before VRF initialization.
|
|
|
|
Arguments:
|
|
values {dict} -- Post-validation VRF attributes
|
|
|
|
Returns:
|
|
{dict} -- VRF with new attributes set
|
|
"""
|
|
if values["name"] == "default":
|
|
protocol4 = "ipv4_default"
|
|
protocol6 = "ipv6_default"
|
|
|
|
else:
|
|
protocol4 = "ipv4_vpn"
|
|
protocol6 = "ipv6_vpn"
|
|
|
|
if values.get("ipv4") is not None:
|
|
values["ipv4"].protocol = protocol4
|
|
values["ipv4"].version = 4
|
|
|
|
if values.get("ipv6") is not None:
|
|
values["ipv6"].protocol = protocol6
|
|
values["ipv6"].version = 6
|
|
|
|
return values
|
|
|
|
def __getitem__(self, i):
|
|
"""Access the VRF's AFI by IP protocol number.
|
|
|
|
Arguments:
|
|
i {int} -- IP Protocol number (4|6)
|
|
|
|
Raises:
|
|
AttributeError: Raised if passed number is not 4 or 6.
|
|
|
|
Returns:
|
|
{object} -- AFI object
|
|
"""
|
|
if i not in (4, 6):
|
|
raise AttributeError(f"Must be 4 or 6, got '{i}")
|
|
|
|
return getattr(self, f"ipv{i}")
|
|
|
|
def __hash__(self):
|
|
"""Make VRF object hashable so the object can be deduplicated with set().
|
|
|
|
Returns:
|
|
{int} -- Hash of VRF name
|
|
"""
|
|
return hash((self.name,))
|
|
|
|
def __eq__(self, other):
|
|
"""Make VRF object comparable so the object can be deduplicated with set().
|
|
|
|
Arguments:
|
|
other {object} -- Object to compare
|
|
|
|
Returns:
|
|
{bool} -- True if comparison attributes are the same value
|
|
"""
|
|
result = False
|
|
if isinstance(other, HyperglassModel):
|
|
result = self.name == other.name
|
|
return result
|
|
|
|
|
|
class DefaultVrf(HyperglassModel):
|
|
"""Validation model for default routing table VRF."""
|
|
|
|
name: constr(regex="default") = "default"
|
|
display_name: StrictStr = "Global"
|
|
info: Info = Info()
|
|
|
|
class DefaultVrf4(HyperglassModel):
|
|
"""Validation model for IPv4 default routing table VRF definition."""
|
|
|
|
source_address: IPv4Address
|
|
access_list: List[AccessList4] = [AccessList4()]
|
|
|
|
class DefaultVrf6(HyperglassModel):
|
|
"""Validation model for IPv6 default routing table VRF definition."""
|
|
|
|
source_address: IPv6Address
|
|
access_list: List[AccessList6] = [AccessList6()]
|
|
|
|
ipv4: Optional[DefaultVrf4]
|
|
ipv6: Optional[DefaultVrf6]
|