8
8
from abc import abstractmethod
9
9
from ipaddress import IPv4Interface , IPv6Interface
10
10
11
- from .common import without_keys , JsonOutputType
11
+ from .common import without_keys , JsonOutputType , DeviceSerializationError
12
12
from typing import Self , Iterator , TypeVar , NoReturn
13
13
14
14
@@ -235,6 +235,33 @@ def getISISIdentifier(self) -> str|None:
235
235
return None
236
236
return sys_id
237
237
238
+ def getRouterID (self ) -> str :
239
+ # Deriving the router ID is a bit tricky, there is no 'correct' way.
240
+ # For us it's the primary loopback IPv4 address
241
+
242
+ # get first loopback interface in default vrf
243
+ loopback = next (filter (
244
+ lambda x : (x .isLoopbackChild () and x .getVRF () == None ),
245
+ self .getInterfaces ()
246
+ ), None )
247
+
248
+ if loopback == None :
249
+ raise DeviceSerializationError ("Can't derive Router ID, no suitable loopback interface found." )
250
+ return ""
251
+
252
+ # get first IPv4 of that interface
253
+ address = next (filter (
254
+ lambda i : type (i ) is IPv4Interface ,
255
+ map (lambda i : i .getIPInterfaceObject (), loopback .getIPAddresses ())
256
+ ), None )
257
+
258
+ if address == None :
259
+ raise DeviceSerializationError ("Can't derive Router ID, no suitable loopback IP address found." )
260
+ return ""
261
+
262
+ # return that IP without subnet mask and hope for the best
263
+ return str (address .ip )
264
+
238
265
239
266
class DeviceTypeType (AbstractNetboxType ):
240
267
def getBasePath (self ):
@@ -365,7 +392,9 @@ def getSubInterfaceParentInterfaceName(self) -> str|None:
365
392
return ret
366
393
367
394
def getVRF (self ) -> VRFType | None :
368
- return self .get ("vrf" )
395
+ if self ["vrf" ]:
396
+ return VRFType (self ["vrf" ])
397
+ return None
369
398
370
399
def spitInterfacePathWith (self , d : dict ) -> dict :
371
400
"""
@@ -449,6 +478,9 @@ def getIPAddresses(self) -> list[IPAddressType]:
449
478
def hasParentInterface (self ) -> bool :
450
479
return bool (self .get ("parent" ))
451
480
481
+ def isLoopbackChild (self ):
482
+ return '.' in self .getName () and self .getName ().startswith ("lo" )
483
+
452
484
def getConnectedEndpoints (self ) -> list [DeviceType ]:
453
485
return self .get ("connected_endpoints" , [])
454
486
@@ -486,7 +518,10 @@ def getBasePath(self):
486
518
return "/vpn/l2vpns/"
487
519
488
520
def getIdentifier (self ) -> int | None :
489
- return self ["identifier" ]
521
+ if self ["identifier" ]:
522
+ return self ["identifier" ]
523
+ else :
524
+ return self ["id" ]
490
525
491
526
def getType (self ) -> str :
492
527
return self ["type" ]
@@ -554,10 +589,9 @@ def getPrefixes(self) -> list[IPv6Interface|IPv4Interface]:
554
589
return [
555
590
ipaddress .ip_interface (p ["prefix" ]) for p in self ["ip_prefixes" ]
556
591
]
557
-
592
+
558
593
def isUniqueToDevice (self ) -> bool :
559
594
return len (self ["devices" ]) == 1
560
-
595
+
561
596
def hasIPRanges (self ) -> bool :
562
597
return len (self ["ip_ranges" ]) > 0
563
-
0 commit comments