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

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/>. 

18 

19"""BIRD OSPF area interface configuration.""" 

20 

21# pylint: disable=too-many-lines 

22 

23import fnmatch 

24from typing import Optional 

25 

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 

34 

35__all__ = ["ProtocolOSPFAreaInterface"] 

36 

37 

38class ProtocolOSPFAreaInterface(SectionProtocolBase): # pylint: disable=too-many-public-methods,too-many-instance-attributes 

39 """BIRD OSPF area interface configuration.""" 

40 

41 # OSPF area attributes 

42 _area_attributes: OSPFAreaAttributes 

43 

44 # OSPF area interface attributes 

45 _interface_attributes: OSPFAreaInterfaceAttributes 

46 

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) 

59 

60 # Setup the OSPF area attributes 

61 self._area_attributes = area_attributes 

62 

63 # Setup OSPF area interface attributes 

64 self._interface_attributes = OSPFAreaInterfaceAttributes() 

65 

66 # Set our interface name 

67 self.name = interface_name 

68 

69 # Check if we have a interface cost 

70 if "cost" in interface_config: 

71 self.cost = interface_config["cost"] 

72 

73 # Check if we have an interface ECMP weight 

74 if "ecmp_weight" in interface_config: 

75 self.ecmp_weight = interface_config["ecmp_weight"] 

76 

77 # Check if we have a interface hello 

78 if "hello" in interface_config: 

79 self.hello = interface_config["hello"] 

80 

81 # Check if we have a interface wait 

82 if "wait" in interface_config: 

83 self.wait = interface_config["wait"] 

84 

85 # Check if this interface is a stub 

86 if "stub" in interface_config: 

87 self.stub = interface_config["stub"] 

88 

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"] 

98 

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"] 

119 

120 def configure(self) -> None: 

121 """Configure the OSPF interface.""" 

122 

123 # Don't re-render the configuration, we're called twice for v4 and V6 

124 if self.conf.items: 

125 return 

126 

127 super().configure() 

128 

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] = {} 

133 

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 

138 

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(" };") 

158 

159 @property 

160 def is_stub(self) -> bool: 

161 """Return if interface is a stub.""" 

162 return self.stub 

163 

164 @property 

165 def area_attributes(self) -> OSPFAreaAttributes: 

166 """OSPF area attributes.""" 

167 return self._area_attributes 

168 

169 @property 

170 def interface_attributes(self) -> OSPFAreaInterfaceAttributes: 

171 """OSPF area interface attributes.""" 

172 return self._interface_attributes 

173 

174 @property 

175 def name(self) -> str: 

176 """Interface name.""" 

177 return self.interface_attributes.name 

178 

179 @name.setter 

180 def name(self, name: str) -> None: 

181 """Interface name.""" 

182 self.interface_attributes.name = name 

183 

184 @property 

185 def cost(self) -> int: 

186 """Interface cost.""" 

187 return self.interface_attributes.cost 

188 

189 @cost.setter 

190 def cost(self, cost: int) -> None: 

191 """Interface cost.""" 

192 self.interface_attributes.cost = cost 

193 

194 @property 

195 def ecmp_weight(self) -> Optional[int]: 

196 """Interface ECMP weight.""" 

197 return self.interface_attributes.ecmp_weight 

198 

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 

203 

204 @property 

205 def hello(self) -> Optional[int]: 

206 """Interface hello.""" 

207 return self.interface_attributes.hello 

208 

209 @hello.setter 

210 def hello(self, hello: int) -> None: 

211 """Interface hello.""" 

212 self.interface_attributes.hello = hello 

213 

214 @property 

215 def wait(self) -> Optional[int]: 

216 """Interface wait.""" 

217 return self.interface_attributes.wait 

218 

219 @wait.setter 

220 def wait(self, wait: int) -> None: 

221 """Interface wait.""" 

222 self.interface_attributes.wait = wait 

223 

224 @property 

225 def stub(self) -> bool: 

226 """Interface is a stub.""" 

227 return self.interface_attributes.stub 

228 

229 @stub.setter 

230 def stub(self, stub: bool) -> None: 

231 """Interface is a stub.""" 

232 self.interface_attributes.stub = stub