Coverage for birdplan/bird_config/sections/protocols/ospf/area/interface/__init__.py: 99%
112 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 03:27 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-23 03:27 +0000
1#
2# SPDX-License-Identifier: GPL-3.0-or-later
3#
4# Copyright (c) 2019-2024, 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 interface configuration."""
21# pylint: disable=too-many-lines
23import fnmatch
24from typing import Optional
26from ......globals import BirdConfigGlobals
27from .....constants import SectionConstants
28from .....functions import SectionFunctions
29from .....tables import SectionTables
30from ....base import SectionProtocolBase
31from ..area_attributes import OSPFAreaAttributes
32from .interface_attributes import OSPFAreaInterfaceAttributes
33from .ospf_area_interface_types import OSPFAreaInterfaceConfig
35__all__ = ["ProtocolOSPFAreaInterface"]
38class ProtocolOSPFAreaInterface(SectionProtocolBase): # pylint: disable=too-many-public-methods,too-many-instance-attributes
39 """BIRD OSPF area interface configuration."""
41 # OSPF area attributes
42 _area_attributes: OSPFAreaAttributes
44 # OSPF area interface attributes
45 _interface_attributes: OSPFAreaInterfaceAttributes
47 def __init__( # noqa: CFQ002 # pylint: disable=too-many-arguments,too-many-branches
48 self,
49 birdconfig_globals: BirdConfigGlobals,
50 constants: SectionConstants,
51 functions: SectionFunctions,
52 tables: SectionTables,
53 area_attributes: OSPFAreaAttributes,
54 interface_name: str,
55 interface_config: OSPFAreaInterfaceConfig,
56 ):
57 """Initialize the object."""
58 super().__init__(birdconfig_globals, constants, functions, tables)
60 # Setup the OSPF area attributes
61 self._area_attributes = area_attributes
63 # Setup OSPF area interface attributes
64 self._interface_attributes = OSPFAreaInterfaceAttributes()
66 # Set our interface name
67 self.name = interface_name
69 # Check if we have a interface cost
70 if "cost" in interface_config:
71 self.cost = interface_config["cost"]
73 # Check if we have an interface ECMP weight
74 if "ecmp_weight" in interface_config:
75 self.ecmp_weight = interface_config["ecmp_weight"]
77 # Check if we have a interface hello
78 if "hello" in interface_config:
79 self.hello = interface_config["hello"]
81 # Check if we have a interface wait
82 if "wait" in interface_config:
83 self.wait = interface_config["wait"]
85 # Check if this interface is a stub
86 if "stub" in interface_config:
87 self.stub = interface_config["stub"]
89 # Check if we have a interface setting overrides
90 if (
91 "ospf" in self.birdconfig_globals.state
92 and "areas" in self.birdconfig_globals.state["ospf"]
93 and self.area_attributes.name in self.birdconfig_globals.state["ospf"]["areas"]
94 and "+interfaces" in self.birdconfig_globals.state["ospf"]["areas"][self.area_attributes.name]
95 ):
96 # Make things easier below
97 interface_overrides = self.birdconfig_globals.state["ospf"]["areas"][self.area_attributes.name]["+interfaces"]
99 # Check if this interface is in the override structure
100 if self.name in interface_overrides:
101 # Check if we have a cost override
102 if "cost" in interface_overrides[self.name]:
103 self.cost = interface_overrides[self.name]["cost"]
104 # Check if we have an ecmp_weight override
105 if "ecmp_weight" in interface_overrides[self.name]:
106 self.ecmp_weight = interface_overrides[self.name]["ecmp_weight"]
107 # If not we process the patterns
108 else:
109 for item in sorted(interface_overrides):
110 # Skip non patterns
111 if "*" not in item:
112 continue
113 # If pattern matches peer name, set the value for quarantine
114 if fnmatch.fnmatch(self.name, item):
115 if "cost" in interface_overrides[item]:
116 self.cost = interface_overrides[item]["cost"]
117 if "ecmp_weight" in interface_overrides[item]:
118 self.ecmp_weight = interface_overrides[item]["ecmp_weight"]
120 def configure(self) -> None:
121 """Configure the OSPF interface."""
123 # Don't re-render the configuration, we're called twice for v4 and V6
124 if self.conf.items:
125 return
127 super().configure()
129 # Blank the OSPF area interface state
130 area_interfaces_state = self.birdconfig_globals.state["ospf"]["areas"][self.area_attributes.name]["interfaces"]
131 if self.name not in area_interfaces_state:
132 area_interfaces_state[self.name] = {}
134 # Setup our state
135 interface_state = area_interfaces_state[self.name]
136 interface_state["cost"] = self.cost
137 interface_state["ecmp_weight"] = self.ecmp_weight
139 # Start interface block
140 self.conf.add(f' interface "{self.name}" {{')
141 # Check if we have a cost
142 if self.cost:
143 self.conf.add(f" cost {self.cost};")
144 # Check if we have a ecmp_weight
145 if self.ecmp_weight:
146 self.conf.add(f" ecmp weight {self.ecmp_weight};")
147 # Check if we have a hello
148 if self.hello:
149 self.conf.add(f" hello {self.hello};")
150 # Check if we have a wait
151 if self.wait:
152 self.conf.add(f" wait {self.wait};")
153 # Check our stub option
154 if self.is_stub:
155 self.conf.add(" stub;")
156 # Close off interface block
157 self.conf.add(" };")
159 @property
160 def is_stub(self) -> bool:
161 """Return if interface is a stub."""
162 return self.stub
164 @property
165 def area_attributes(self) -> OSPFAreaAttributes:
166 """OSPF area attributes."""
167 return self._area_attributes
169 @property
170 def interface_attributes(self) -> OSPFAreaInterfaceAttributes:
171 """OSPF area interface attributes."""
172 return self._interface_attributes
174 @property
175 def name(self) -> str:
176 """Interface name."""
177 return self.interface_attributes.name
179 @name.setter
180 def name(self, name: str) -> None:
181 """Interface name."""
182 self.interface_attributes.name = name
184 @property
185 def cost(self) -> int:
186 """Interface cost."""
187 return self.interface_attributes.cost
189 @cost.setter
190 def cost(self, cost: int) -> None:
191 """Interface cost."""
192 self.interface_attributes.cost = cost
194 @property
195 def ecmp_weight(self) -> Optional[int]:
196 """Interface ECMP weight."""
197 return self.interface_attributes.ecmp_weight
199 @ecmp_weight.setter
200 def ecmp_weight(self, ecmp_weight: int) -> None:
201 """Interface ECMP weight."""
202 self.interface_attributes.ecmp_weight = ecmp_weight
204 @property
205 def hello(self) -> Optional[int]:
206 """Interface hello."""
207 return self.interface_attributes.hello
209 @hello.setter
210 def hello(self, hello: int) -> None:
211 """Interface hello."""
212 self.interface_attributes.hello = hello
214 @property
215 def wait(self) -> Optional[int]:
216 """Interface wait."""
217 return self.interface_attributes.wait
219 @wait.setter
220 def wait(self, wait: int) -> None:
221 """Interface wait."""
222 self.interface_attributes.wait = wait
224 @property
225 def stub(self) -> bool:
226 """Interface is a stub."""
227 return self.interface_attributes.stub
229 @stub.setter
230 def stub(self, stub: bool) -> None:
231 """Interface is a stub."""
232 self.interface_attributes.stub = stub