diff --git a/vmngclient/api/template_api.py b/vmngclient/api/template_api.py index 09571e781..d068688ba 100644 --- a/vmngclient/api/template_api.py +++ b/vmngclient/api/template_api.py @@ -25,6 +25,7 @@ from vmngclient.api.templates.models.cisco_logging_model import CiscoLoggingModel from vmngclient.api.templates.models.cisco_ntp_model import CiscoNTPModel from vmngclient.api.templates.models.cisco_omp_model import CiscoOMPModel +from vmngclient.api.templates.models.cisco_ospf import CiscoOSPFModel from vmngclient.api.templates.models.cisco_snmp_model import CiscoSNMPModel from vmngclient.api.templates.models.cisco_system import CiscoSystemModel from vmngclient.api.templates.models.cisco_vpn_interface_model import CiscoVpnInterfaceModel @@ -507,6 +508,7 @@ def is_created_by_generator(self, template: FeatureTemplate) -> bool: CiscoSNMPModel, CiscoVPNModel, CiscoBGPModel, + CiscoOSPFModel, CliTemplateModel, ) @@ -567,9 +569,15 @@ def generate_feature_template_payload( if value is None: value = template.dict(by_alias=True).get(field.key, None) + # TODO remove workaround, add specific object + # types like Ignore, Constant, None etc so generator will now + # which object to ommit while generating payload if template.type == "cisco_vpn_interface" and value is None: continue + if template.type == "cisco_ospf" and value is None: + continue + if isinstance(value, bool): value = str(value).lower() # type: ignore diff --git a/vmngclient/api/templates/models/cisco_ospf.py b/vmngclient/api/templates/models/cisco_ospf.py new file mode 100644 index 000000000..1f70b9500 --- /dev/null +++ b/vmngclient/api/templates/models/cisco_ospf.py @@ -0,0 +1,146 @@ +import ipaddress +from enum import Enum +from pathlib import Path +from typing import ClassVar, List, Optional + +from pydantic import Field + +from vmngclient.api.templates.feature_template import FeatureTemplate +from vmngclient.utils.pydantic_validators import ConvertBoolToStringModel + +DEFAULT_OSPF_HELLO_INTERVAL = 10 +DEFAULT_OSPF_DEAD_INTERVAL = 40 +DEFAULT_OSPF_RETRANSMIT_INTERVAL = 5 +DEFAULT_OSPF_INTERFACE_PRIORITY = 1 +DEFAULT_OSPF_REFERENCE_BANDWIDTH = 100 +DEFAULT_OSPF_EXTERNAL = 110 +DEFAULT_OSPF_INTER_AREA = 110 +DEFAULT_OSPF_INTRA_AREA = 110 +DEFAULT_OSPF_DELAY = 200 +DEFAULT_OSPF_INITIAL_HOLD = 1000 +DEFAULT_OSPF_MAX_HOLD = 10000 + + +class MetricType(str, Enum): + TYPE1 = "type1" + TYPE2 = "type2" + + +class Protocol(str, Enum): + STATIC = "static" + CONNECTED = "connected" + BGP = "bgp" + OMP = "omp" + NAT = "nat" + EIGRP = "eigrp" + + +class Redistribute(ConvertBoolToStringModel): + protocol: Protocol + route_policy: Optional[str] = Field(alias="route-policy") + dia: Optional[bool] = True + + class Config: + allow_population_by_field_name = True + + +class AdType(str, Enum): + ADMINISTRATIVE = "administrative" + ON_STARTUP = "on-startup" + + +class RouterLsa(ConvertBoolToStringModel): + ad_type: AdType = Field(alias="ad-type") + time: int + + class Config: + allow_population_by_field_name = True + + +class Direction(str, Enum): + IN = "in" + + +class RoutePolicy(ConvertBoolToStringModel): + direction: Direction + pol_name: str = Field(alias="pol-name") + + class Config: + allow_population_by_field_name = True + + +class Network(str, Enum): + BROADCAST = "broadcast" + POINT_TO_POINT = "point-to-point" + NON_BROADCAST = "non-broadcast" + POINT_TO_MULTIPOINT = "point-to-multipoint" + + +class Type(str, Enum): + SIMPLE = "simple" + MESSAGE_DIGEST = "message-digest" + NULL = "null" + + +class Interface(ConvertBoolToStringModel): + name: str + hello_interval: Optional[int] = Field(DEFAULT_OSPF_DEAD_INTERVAL, alias="hello-interval") + dead_interval: Optional[int] = Field(DEFAULT_OSPF_DEAD_INTERVAL, alias="dead-interval") + retransmit_interval: Optional[int] = Field(DEFAULT_OSPF_RETRANSMIT_INTERVAL, alias="retransmit-interval") + cost: Optional[int] + priority: Optional[int] = DEFAULT_OSPF_INTERFACE_PRIORITY + network: Optional[Network] = Network.BROADCAST + passive_interface: Optional[bool] = Field(False, alias="passive-interface") + type: Optional[Type] + message_digest_key: Optional[int] = Field(alias="message-digest-key") + md5: Optional[str] + + class Config: + allow_population_by_field_name = True + + +class Range(ConvertBoolToStringModel): + address: ipaddress.IPv4Interface + cost: Optional[int] + no_advertise: Optional[bool] = Field(False, alias="no-advertise") + + class Config: + allow_population_by_field_name = True + + +class Area(ConvertBoolToStringModel): + a_num: int = Field(alias="a-num") + stub_no_summary: Optional[bool] = Field(vmanage_key="no-summary", data_path=["stub", "no_summary"]) + nssa_no_summary: Optional[bool] = Field(vmanage_key="no-summary") + interface: Optional[List[Interface]] + range: Optional[List[Range]] + + class Config: + allow_population_by_field_name = True + + +class CiscoOSPFModel(FeatureTemplate, ConvertBoolToStringModel): + class Config: + arbitrary_types_allowed = True + allow_population_by_field_name = True + + router_id: Optional[ipaddress.IPv4Address] = Field(alias="router-id") + reference_bandwidth: Optional[int] = Field(DEFAULT_OSPF_REFERENCE_BANDWIDTH, alias="reference-bandwidth") + rfc1583: Optional[bool] = True + originate: Optional[bool] + always: Optional[bool] + metric: Optional[int] + metric_type: Optional[MetricType] = Field(alias="metric-type") + external: Optional[int] = DEFAULT_OSPF_EXTERNAL + inter_area: Optional[int] = Field(DEFAULT_OSPF_INTER_AREA, alias="inter-area") + intra_area: Optional[int] = Field(DEFAULT_OSPF_INTRA_AREA, alias="intra-area") + delay: Optional[int] = DEFAULT_OSPF_DELAY + initial_hold: Optional[int] = Field(DEFAULT_OSPF_INITIAL_HOLD, alias="initial-hold") + max_hold: Optional[int] = Field(DEFAULT_OSPF_MAX_HOLD, alias="max-hold") + redistribute: Optional[List[Redistribute]] + router_lsa: Optional[List[RouterLsa]] = Field(alias="router-lsa") + route_policy: Optional[List[RoutePolicy]] = Field(alias="route-policy") + area: Optional[List[Area]] + + payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" + type: ClassVar[str] = "cisco_ospf" diff --git a/vmngclient/api/templates/models/supported.py b/vmngclient/api/templates/models/supported.py index e11eb5c1b..876bc42a4 100644 --- a/vmngclient/api/templates/models/supported.py +++ b/vmngclient/api/templates/models/supported.py @@ -3,6 +3,7 @@ from vmngclient.api.templates.models.cisco_bfd_model import CiscoBFDModel from vmngclient.api.templates.models.cisco_logging_model import CiscoLoggingModel from vmngclient.api.templates.models.cisco_ntp_model import CiscoNTPModel +from vmngclient.api.templates.models.cisco_ospf import CiscoOSPFModel from vmngclient.api.templates.models.cisco_snmp_model import CiscoSNMPModel from vmngclient.api.templates.models.cisco_system import CiscoSystemModel from vmngclient.api.templates.models.cisco_vpn_interface_model import CiscoVpnInterfaceModel @@ -16,6 +17,7 @@ "cisco_bfd": CiscoBFDModel, "cisco_banner": CiscoBannerModel, "cisco_ntp": CiscoNTPModel, + "cisco_ospf": CiscoOSPFModel, "cisco_logging": CiscoLoggingModel, "omp_vsmart": OMPvSmart, "security_vsmart": SecurityvSmart,