defget_connections(self,devices:list,instance:str=None,dry_run:bool=False,cables:bool=False,)->dict:""" Retrieve interface connection details for specified devices from Netbox. Args: devices (list): List of device names to retrieve connections for. instance (str, optional): Instance name for the GraphQL query. dry_run (bool, optional): If True, perform a dry run without making actual changes. cables (bool, optional): if True includes interfaces' directly attached cables details Returns: dict: A dictionary containing connection details for each device. Raises: Exception: If there is an error in the GraphQL query or data retrieval process. """# form final result dictionaryret=Result(task=f"{self.name}:get_connections",result={d:{}fordindevices})# form lists of fields to request from netboxcable_fields=""" cable { type status tenant {name} label tags {name} length length_unit custom_fields } """ifself.nb_version[0]==4:interfaces_fields=["name","device {name}","""connected_endpoints { __typename ... on InterfaceType {name device {name}} ... on ProviderNetworkType {name} }""",]elifself.nb_version[0]==3:interfaces_fields=["name","device {name}","""connected_endpoints { __typename ... on InterfaceType {name device {name}} }""",]interfaces_fields.append(""" link_peers { __typename ... on InterfaceType {name device {name}} ... on FrontPortType {name device {name}} ... on RearPortType {name device {name}} } """)console_ports_fields=["name","device {name}","""connected_endpoints { __typename ... on ConsoleServerPortType {name device {name}} }""","""link_peers { __typename ... on ConsoleServerPortType {name device {name}} ... on FrontPortType {name device {name}} ... on RearPortType {name device {name}} }""",]console_server_ports_fields=["name","device {name}","""connected_endpoints { __typename ... on ConsolePortType {name device {name}} }""","""link_peers { __typename ... on ConsolePortType {name device {name}} ... on FrontPortType {name device {name}} ... on RearPortType {name device {name}} }""",]# check if need to include cables infoifcablesisTrue:interfaces_fields.append(cable_fields)console_ports_fields.append(cable_fields)console_server_ports_fields.append(cable_fields)# form query dictionary with aliases to get data from Netboxqueries={"interface":{"obj":"interface_list","filters":{"device":devices},"fields":interfaces_fields,},"consoleport":{"obj":"console_port_list","filters":{"device":devices},"fields":console_ports_fields,},"consoleserverport":{"obj":"console_server_port_list","filters":{"device":devices},"fields":console_server_ports_fields,},}# retrieve full list of devices interface with all cablesquery_result=self.graphql(queries=queries,instance=instance,dry_run=dry_run)# return dry run resultifdry_run:returnquery_resultall_ports=query_result.result# extract interfacesforport_type,portsinall_ports.items():forportinports:endpoints=port["connected_endpoints"]# skip ports that have no remote device connectedifnotendpointsornotall(iforiinendpoints):continue# extract required parameterscable=port.get("cable",{})device_name=port["device"]["name"]port_name=port["name"]link_peers=port["link_peers"]remote_termination_type=endpoints[0]["__typename"].lower()remote_termination_type=remote_termination_type.replace("type","")# form initial connection dictionaryconnection={"breakout":len(endpoints)>1,"remote_termination_type":remote_termination_type,"termination_type":port_type,}# add remote connection detailsifremote_termination_type=="providernetwork":connection["remote_device"]=Noneconnection["remote_interface"]=Noneconnection["provider"]=endpoints[0]["name"]else:remote_interface=endpoints[0]["name"]iflen(endpoints)>1:remote_interface=[i["name"]foriinendpoints]connection["remote_interface"]=remote_interfaceconnection["remote_device"]=endpoints[0]["device"]["name"]# add cable and its peer detailsifcables:peer_termination_type=link_peers[0]["__typename"].lower()peer_termination_type=peer_termination_type.replace("type","")cable["peer_termination_type"]=peer_termination_typecable["peer_device"]=link_peers[0].get("device",{}).get("name")cable["peer_interface"]=link_peers[0].get("name")iflen(link_peers)>1:# handle breakout cablecable["peer_interface"]=[i["name"]foriinlink_peers]connection["cable"]=cableret.result[device_name][port_name]=connectionreturnret