def get_route_to(self, destination="", protocol=""):
        """Return route details to a specific destination, learned from a certain protocol."""
        routes = {}

        if not isinstance(destination, py23_compat.string_types):
            raise TypeError("Please specify a valid destination!")

        if protocol and isinstance(destination, py23_compat.string_types):
            protocol = protocol.lower()

        if protocol == "connected":
            protocol = "direct"  # this is how is called on JunOS

        _COMMON_PROTOCOL_FIELDS_ = [
            "destination",
            "prefix_length",
            "protocol",
            "current_active",
            "last_active",
            "age",
            "next_hop",
            "outgoing_interface",
            "selected_next_hop",
            "preference",
            "inactive_reason",
            "routing_table",
        ]  # identifies the list of fileds common for all protocols

        _BOOLEAN_FIELDS_ = [
            "current_active",
            "selected_next_hop",
            "last_active",
        ]  # fields expected to have boolean values

        _PROTOCOL_SPECIFIC_FIELDS_ = {
            "bgp": [
                "local_as",
                "remote_as",
                "as_path",
                "communities",
                "local_preference",
                "preference2",
                "remote_address",
                "metric",
                "metric2",
            ],
            "isis": ["level", "metric", "local_as"],
        }

        routes_table = junos_views.junos_protocol_route_table(self.device)

        rt_kargs = {"destination": destination}
        if protocol and isinstance(destination, py23_compat.string_types):
            rt_kargs["protocol"] = protocol

        try:
            routes_table.get(**rt_kargs)
        except RpcTimeoutError:
            # on devices with milions of routes
            # in case the destination is too generic (e.g.: 10/8)
            # will take very very long to determine all routes and
            # moreover will return a huge list
            raise CommandTimeoutException(
                "Too many routes returned! Please try with a longer prefix or a specific protocol!"
            )
        except RpcError as rpce:
            if len(rpce.errs) > 0 and "bad_element" in rpce.errs[0]:
                raise CommandErrorException(
                    "Unknown protocol: {proto}".format(
                        proto=rpce.errs[0]["bad_element"]
                    )
                )
            raise CommandErrorException(rpce)
        except Exception as err:
            raise CommandErrorException(
                "Cannot retrieve routes! Reason: {err}".format(err=err)
            )

        routes_items = routes_table.items()

        for route in routes_items:
            d = {}
            # next_hop = route[0]
            d = {elem[0]: elem[1] for elem in route[1]}
            destination = d.pop("destination", "")
            prefix_length = d.pop("prefix_length", 32)
            destination = "{d}/{p}".format(d=destination, p=prefix_length)
            d.update({key: False for key in _BOOLEAN_FIELDS_ if d.get(key) is None})
            as_path = d.get("as_path")
            if as_path is not None:
                d["as_path"] = (
                    as_path.split(" I ")[0]
                    .replace("AS path:", "")
                    .replace("I", "")
                    .strip()
                )
                # to be sure that contains only AS Numbers
            if d.get("inactive_reason") is None:
                d["inactive_reason"] = ""
            route_protocol = d.get("protocol").lower()
            if protocol and protocol != route_protocol:
                continue
            communities = d.get("communities")
            if communities is not None and type(communities) is not list:
                d["communities"] = [communities]
            d_keys = list(d.keys())
            # fields that are not in _COMMON_PROTOCOL_FIELDS_ are supposed to be protocol specific
            all_protocol_attributes = {
                key: d.pop(key) for key in d_keys if key not in _COMMON_PROTOCOL_FIELDS_
            }
            protocol_attributes = {
                key: value
                for key, value in all_protocol_attributes.items()
                if key in _PROTOCOL_SPECIFIC_FIELDS_.get(route_protocol, [])
            }
            d["protocol_attributes"] = protocol_attributes
            if destination not in routes.keys():
                routes[destination] = []
            routes[destination].append(d)

        return routes
def get_route_to ( self , destination = "" , protocol = "" ) : routes = { } if not isinstance ( destination , py23_compat . string_types ) : raise TypeError ( "Please specify a valid destination!" ) if protocol and isinstance ( destination , py23_compat . string_types ) : protocol = protocol . lower ( ) if protocol == "connected" : protocol = "direct" _COMMON_PROTOCOL_FIELDS_ = [ "destination" , "prefix_length" , "protocol" , "current_active" , "last_active" , "age" , "next_hop" , "outgoing_interface" , "selected_next_hop" , "preference" , "inactive_reason" , "routing_table" , ] _BOOLEAN_FIELDS_ = [ "current_active" , "selected_next_hop" , "last_active" , ] _PROTOCOL_SPECIFIC_FIELDS_ = { "bgp" : [ "local_as" , "remote_as" , "as_path" , "communities" , "local_preference" , "preference2" , "remote_address" , "metric" , "metric2" , ] , "isis" : [ "level" , "metric" , "local_as" ] , } routes_table = junos_views . junos_protocol_route_table ( self . device ) rt_kargs = { "destination" : destination } if protocol and isinstance ( destination , py23_compat . string_types ) : rt_kargs [ "protocol" ] = protocol try : routes_table . get ( ** rt_kargs ) except RpcTimeoutError : raise CommandTimeoutException ( "Too many routes returned! Please try with a longer prefix or a specific protocol!" ) except RpcError as rpce : if len ( rpce . errs ) > 0 and "bad_element" in rpce . errs [ 0 ] : raise CommandErrorException ( "Unknown protocol: {proto}" . format ( proto = rpce . errs [ 0 ] [ "bad_element" ] ) ) raise CommandErrorException ( rpce ) except Exception as err : raise CommandErrorException ( "Cannot retrieve routes! Reason: {err}" . format ( err = err ) ) routes_items = routes_table . items ( ) for route in routes_items : d = { } d = { elem [ 0 ] : elem [ 1 ] for elem in route [ 1 ] } destination = d . pop ( "destination" , "" ) prefix_length = d . pop ( "prefix_length" , 32 ) destination = "{d}/{p}" . format ( d = destination , p = prefix_length ) d . update ( { key : False for key in _BOOLEAN_FIELDS_ if d . get ( key ) is None } ) as_path = d . get ( "as_path" ) if as_path is not None : d [ "as_path" ] = ( as_path . split ( " I " ) [ 0 ] . replace ( "AS path:" , "" ) . replace ( "I" , "" ) . strip ( ) ) if d . get ( "inactive_reason" ) is None : d [ "inactive_reason" ] = "" route_protocol = d . get ( "protocol" ) . lower ( ) if protocol and protocol != route_protocol : continue communities = d . get ( "communities" ) if communities is not None and type ( communities ) is not list : d [ "communities" ] = [ communities ] d_keys = list ( d . keys ( ) ) all_protocol_attributes = { key : d . pop ( key ) for key in d_keys if key not in _COMMON_PROTOCOL_FIELDS_ } protocol_attributes = { key : value for key , value in all_protocol_attributes . items ( ) if key in _PROTOCOL_SPECIFIC_FIELDS_ . get ( route_protocol , [ ] ) } d [ "protocol_attributes" ] = protocol_attributes if destination not in routes . keys ( ) : routes [ destination ] = [ ] routes [ destination ] . append ( d ) return routes
Return route details to a specific destination, learned from a certain protocol.