@@ -62,6 +62,8 @@ class VMWareHandler(SourceBase):
6262 NBDeviceRole ,
6363 NBSite ,
6464 NBSiteGroup ,
65+ NBLocation ,
66+ NBRegion ,
6567 NBCluster ,
6668 NBDevice ,
6769 NBVM ,
@@ -474,13 +476,20 @@ def get_site_name(self, object_type, object_name, cluster_name=""):
474476
475477 site_name = self .get_object_relation (object_name , relation_name )
476478
477- if object_type == NBDevice and site_name is None :
479+ # check if cluster is in a different site than the host and override the site name if so
480+ if object_type == NBDevice :
478481 site_name = self .get_site_name (NBCluster , cluster_name )
479482 if site_name is not None :
480- log .debug2 (f"Found a matching cluster site for { object_name } , using site '{ site_name } '" )
481-
482- # set default site name
483- if site_name is None :
483+ log .debug2 (f"Found a matching cluster site for { object_name } , using site '{ site_name } '. Overriding host site relation '{ relation_name } '" )
484+ else :
485+ site_name = self .get_object_relation (object_name , relation_name )
486+ # set deault site name if no relation was found
487+ if site_name is None :
488+ site_name = self .site_name
489+ log .debug2 (f"No site relation for { type (object_name )} : '{ object_name } ' found, using default site '{ site_name } '" )
490+
491+ # set default site name for devices
492+ if site_name is None and object_type == NBDevice :
484493 site_name = self .site_name
485494 log .debug (f"No site relation for '{ object_name } ' found, using default site '{ site_name } '" )
486495
@@ -489,8 +498,95 @@ def get_site_name(self, object_type, object_name, cluster_name=""):
489498 site_name = None
490499 log .debug2 (f"Site relation for '{ object_name } ' set to None" )
491500
501+ log .debug2 (f"Returning site name '{ site_name } ' for { object_type .name } '{ object_name } '." )
502+
492503 return site_name
504+
505+ def get_scope_type (self , object_type , object_name ):
506+ """
507+ Retrieve the scope_type for a NBCluster instance by object name or from the config option
508+ cluster_scope_type_relation
509+
510+ Note: Only NBCluster is supported as the object_type.
511+
512+ Parameters
513+ ----------
514+ object_type: object type
515+ The NetBox object type (must be NBCluster).
516+ object_name: str
517+ The name of the object to look up.
518+
519+ Returns
520+ -------
521+ str or None: scope type if one is found, otherwise None
522+ """
523+
524+ # Validate object type
525+ if object_type != NBCluster :
526+ raise ValueError (f"Object type must be '{ NBCluster .name } '." )
527+
528+ # get scope type from relation config
529+ relation_name = "cluster_scope_type_relation"
530+ scope_type = self .get_object_relation (object_name , relation_name )
531+ log .debug (f"Retrieved scope type '{ scope_type } ' for { object_type .name } '{ object_name } ' from relation '{ relation_name } '." )
532+
533+ # if the scope_type is a list, use the first element
534+ if scope_type is not None and type (scope_type ) is list :
535+ scope_type_list = scope_type
536+ scope_type = scope_type_list [0 ] if len (scope_type_list ) > 0 else None
537+ log .debug (f"Scope type for { object_type .name } '{ object_name } ' is a list, using first element: '{ scope_type } '" )
538+
539+ # if scope_type is not a str, return None
540+ if type (scope_type ) is not str :
541+ log .debug (f"scope_type is type: { type (scope_type )} , not str" )
542+ return None
543+
544+ # set scope_type to None if it is configured as "<NONE>"
545+ if scope_type == "<NONE>" :
546+ log .debug (f"Scope type for { object_type .name } '{ object_name } ' is set to None" )
547+ return None
548+
549+ log .debug2 (f"Returning scope type '{ scope_type } ' for { object_type .name } '{ object_name } '." )
550+ return scope_type
551+
552+ def get_scope_id (self , object_type , object_name ):
553+ """
554+ Retrieve the scope_id for a NBCluster instance by object name or from the config option
555+ cluster_scope_id_relation
556+
557+ Note: Only NBCluster is supported as the object_type.
493558
559+ Parameters
560+ ----------
561+ object_type: type
562+ The NetBox object type (must be NBCluster).
563+ object_name: str
564+ The name of the object to look up.
565+
566+ Returns
567+ -------
568+ str or None: scope id if one is found, otherwise None
569+ """
570+ # Validate object type
571+ if object_type != NBCluster :
572+ raise ValueError (f"Object type must be '{ NBCluster .name } '." )
573+
574+ # get scope id from relation config
575+ relation_name = "cluster_scope_id_relation"
576+ scope_id = self .get_object_relation (object_name , relation_name )
577+
578+ # return None if scope_id is None or not a string
579+ if scope_id is None :
580+ log .debug (f"No scope id found for { object_name } ." )
581+ return None
582+ if type (scope_id ) is not str :
583+ log .debug (f"scope_id is type: { type (scope_id )} , not str" )
584+ return None
585+
586+ log .debug2 (f"Retrieved scope id '{ scope_id } ' for { object_type .name } '{ object_name } ' from relation '{ relation_name } '. End of method." )
587+
588+ return scope_id
589+
494590 def get_object_based_on_macs (self , object_type , mac_list = None ):
495591 """
496592 Try to find a NetBox object based on list of MAC addresses.
@@ -1378,21 +1474,44 @@ def add_cluster(self, obj):
13781474 self .settings .cluster_include_filter ,
13791475 self .settings .cluster_exclude_filter ) is False :
13801476 return
1477+ log .debug2 (f"Cluster '{ name } ' passes include and exclude filters. Continuing." )
13811478
1479+ # get scope type and id, or site name
1480+ scope_type = self .get_scope_type (NBCluster , full_cluster_name )
1481+ if scope_type is None :
1482+ scope_type = self .get_scope_type (NBCluster , name )
1483+
13821484 site_name = self .get_site_name (NBCluster , full_cluster_name )
13831485
1486+ scope_id = self .get_scope_id (NBCluster , full_cluster_name )
1487+ if scope_id is None :
1488+ scope_id = self .get_scope_id (NBCluster , name )
1489+ log .debug (f"Cluster '{ full_cluster_name } ' has scope id '{ scope_id } ' of type { type (scope_id )} ." )
1490+
13841491 data = {
13851492 "name" : name ,
13861493 "type" : {"name" : "VMware ESXi" },
13871494 "group" : group
13881495 }
13891496
13901497 if version .parse (self .inventory .netbox_api_version ) >= version .parse ("4.2.0" ):
1391- if site_name is not None :
1392- data ["scope_id" ] = {"name" : site_name }
1498+ # set the scope type and id if they are defined
1499+ if scope_type is not None :
1500+ data ["scope_type" ] = scope_type
1501+ data ["scope_id" ] = scope_id
1502+ log .debug (f"Cluster '{ full_cluster_name } ' (or { name } ) has scope type '{ scope_type } ' "
1503+ f"and scope id '{ scope_id } '." )
1504+ elif site_name is not None :
13931505 data ["scope_type" ] = "dcim.site"
1506+ data ["scope_id" ] = {"name" : site_name }
1507+ else :
1508+ log .debug (f"Cluster '{ full_cluster_name } ' has no scope type or scope id." )
13941509 else :
1395- data ["site" ] = {"name" : site_name }
1510+ # set site_name in the pre-4.2.0 NetBox versions if one is found
1511+ if site_name is not None :
1512+ data ["site" ] = {"name" : site_name }
1513+
1514+ log .debug (f"Cluster '{ full_cluster_name } ' (or { name } ) has data items '{ data .items ()} '." )
13961515
13971516 tenant_name = self .get_object_relation (full_cluster_name , "cluster_tenant_relation" )
13981517 if tenant_name is not None :
@@ -1411,11 +1530,12 @@ def add_cluster(self, obj):
14111530 if grab (cluster_candidate , "data.name" ) != name :
14121531 continue
14131532
1414- # try to find a cluster with matching site
1415- if cluster_candidate .get_site_name () == site_name :
1416- cluster_object = cluster_candidate
1417- log .debug2 ("Found an existing cluster where 'name' and 'site' are matching" )
1418- break
1533+ if site_name is not None :
1534+ # try to find a cluster with matching site
1535+ if cluster_candidate .get_site_name () == site_name :
1536+ cluster_object = cluster_candidate
1537+ log .debug2 ("Found an existing cluster where 'name' and 'site' are matching" )
1538+ break
14191539
14201540 if grab (cluster_candidate , "data.group" ) is not None and \
14211541 grab (cluster_candidate , "data.group.data.name" ) == group_name :
0 commit comments