Coverage for src/birdplan/bird_config/sections/protocols/ospf/area/__init__.py: 97%
58 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-25 07:38 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-25 07:38 +0000
1#
2# SPDX-License-Identifier: GPL-3.0-or-later
3#
4# Copyright (c) 2019-2025, AllWorldIT
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
19"""BIRD OSPF area configuration."""
21# pylint: disable=too-many-lines
23from typing import Any
25from ......exceptions import BirdPlanError
26from .....globals import BirdConfigGlobals
27from ....bird_attributes import SectionBirdAttributes
28from ....constants import SectionConstants
29from ....functions import SectionFunctions
30from ....tables import SectionTables
31from ...base import SectionProtocolBase
32from ..ospf_attributes import OSPFAttributes
33from .area_attributes import OSPFAreaAttributes
34from .interface import ProtocolOSPFAreaInterface
35from .ospf_area_types import OSPFAreaConfig
37__all__ = ["ProtocolOSPFArea"]
40OSPFAreaInterfaceConfig = dict[str, Any]
41OSPFAreaInterfaces = dict[str, ProtocolOSPFAreaInterface]
44class ProtocolOSPFArea(SectionProtocolBase): # pylint: disable=too-many-public-methods
45 """BIRD OSPF area configuration."""
47 # OSPF attributes
48 _ospf_attributes: OSPFAttributes
50 # OSPF area attributes
51 _area_attributes: OSPFAreaAttributes
53 # OSPF interfaces belonging to this area
54 _interfaces: OSPFAreaInterfaces
56 def __init__( # noqa: PLR0913,PLR0917
57 self,
58 birdconfig_globals: BirdConfigGlobals,
59 birdattributes: SectionBirdAttributes,
60 constants: SectionConstants,
61 functions: SectionFunctions,
62 tables: SectionTables,
63 ospf_attributes: OSPFAttributes,
64 area_name: str,
65 area_config: OSPFAreaConfig,
66 ) -> None:
67 """Initialize the object."""
68 super().__init__(birdconfig_globals, birdattributes, constants, functions, tables)
70 # Setup OSPF attributes
71 self._ospf_attributes = ospf_attributes
73 # Setup OSPF area attributes
74 self._area_attributes = OSPFAreaAttributes()
76 # Interfaces
77 self._interfaces = {}
79 # Set area name
80 self.name = str(area_name)
82 if area_config:
83 raise BirdPlanError("THIS SHOULD NOT HAPPEN UNTIL WE HAVE AREA CONFIG")
85 def configure(self) -> None:
86 """Configure the OSPF area."""
88 # Don't re-render the configuration, we're called twice for v4 and V6
89 if self.conf.items:
90 return
92 super().configure()
94 # Blank the OSPF area state
95 if "ospf" not in self.birdconfig_globals.state:
96 self.birdconfig_globals.state["ospf"] = {}
97 if "areas" not in self.birdconfig_globals.state["ospf"]:
98 self.birdconfig_globals.state["ospf"]["areas"] = {}
99 if self.name not in self.birdconfig_globals.state["ospf"]["areas"]:
100 self.birdconfig_globals.state["ospf"]["areas"][self.name] = {}
101 if "interfaces" not in self.birdconfig_globals.state["ospf"]["areas"][self.name]:
102 self.birdconfig_globals.state["ospf"]["areas"][self.name]["interfaces"] = {}
104 # Add area config block
105 self.conf.add(f" area {self.name} {{")
106 # Add interfaces
107 for _, interface in sorted(self.interfaces.items()):
108 self.conf.add(interface)
109 # Close area config block
110 self.conf.add(" };")
112 def add_interface(self, interface_name: str, interface_config: OSPFAreaConfig) -> ProtocolOSPFAreaInterface:
113 """Add interface to OSPF."""
115 # Make sure area interface doesn't exist
116 if interface_name in self.interfaces:
117 raise BirdPlanError(f"OSPF area '{self.name}'' interface '{interface_name}' already exists")
119 # Create OSPF area interface object
120 interface = ProtocolOSPFAreaInterface(
121 self.birdconfig_globals,
122 self.birdattributes,
123 self.constants,
124 self.functions,
125 self.tables,
126 self.area_attributes,
127 interface_name,
128 interface_config,
129 )
131 # Add interface to the area
132 self.interfaces[interface_name] = interface
134 return interface
136 @property
137 def area_attributes(self) -> OSPFAreaAttributes:
138 """OSPF area attributes."""
139 return self._area_attributes
141 @property
142 def name(self) -> str:
143 """Area name."""
144 return self.area_attributes.name
146 @name.setter
147 def name(self, name: str) -> None:
148 """Area name."""
149 self.area_attributes.name = name
151 @property
152 def interfaces(self) -> OSPFAreaInterfaces:
153 """OSPF area interfaces."""
154 return self._interfaces