Junos Automation (Scripting)
Highlighted
Junos Automation (Scripting)

REST API All Logical Systems

‎09-15-2018 10:55 PM

Does anyone know if there is another way for the REST API to return information on all of the logical systems configured on a given physical device via the REST API? My suspicion is that it is not yet (or will never be) supported compared to the standard CLI. If you request a given command using the "all" parameter for logical systems on the CLI you get the proper output and the proper RPC output also is returned; example:

 

	root@devrtr> show ospf neighbor logical-system all 
		 
	logical-system: rtr1
	Address          Interface              State     ID               Pri  Dead
	10.254.254.2     ge-0/0/0.0             Full      10.255.255.2     128    39
	-----
	 
	logical-system: rtr2
	10.254.254.1     ge-0/0/1.0             Full      10.255.255.1     128    31
	-----
	 
	logical-system: default
	OSPF instance is not running



	root@devrtr> show ospf neighbor logical-system all | display xml rpc 
	<rpc-reply xmlns:junos="http://xml.juniper.net/junos/17.3R1/junos">
		<rpc>
			<get-ospf-neighbor-information>
			        <logical-system>all</logical-system>
			</get-ospf-neighbor-information>
		</rpc>
		<cli>
			<banner></banner>
		</cli>
	</rpc-reply>

 

If the command is run programmatically via CURL or "insert your favorite language", the return value offered by the REST API is empty (still a valid 200 reqeust), it only seems to allow a specific logical system as a parameter, or "default" as a parameter, but not "all" as a parameter. Thus far I have only tested this on 17.3R1; examples:

 

	curl http://<####>:3000/rpc/get-ospf-neighbor-information?logical-system=all -u "<####>:<####>" -H "Content-Type: application/xml" -H "Accept: application/json"
	{
		"output" : [
		{
		}
		]
	}
	
	
	curl http://<####>:3000/rpc/get-ospf-neighbor-information?logical-system=rtr1 -u "<####>:<####>" -H "Content-Type: application/xml" -H "Accept: application/json"
	{
		"ospf-neighbor-information" : [
		{
		    "ospf-neighbor" : [
		    {
		        "neighbor-address" : [
		        {
		            "data" : "10.254.254.2"
		        }
		        ], 
		        "interface-name" : [
		        {
		            "data" : "ge-0/0/0.0"
		        }
		        ], 
		        "ospf-neighbor-state" : [
		        {
		            "data" : "Full"
		        }
		        ], 
		        "neighbor-id" : [
		        {
		            "data" : "10.255.255.2"
		        }
		        ], 
		        "neighbor-priority" : [
		        {
		            "data" : "128"
		        }
		        ], 
		        "activity-timer" : [
		        {
		            "data" : "36"
		        }
		        ]
		    }
		    ]
		}
		]
	}

 

Since there seems to be no available channel to list all logical systems, which would make working around this issue relatively easy, has anyone been able retrieve all information for a given RPC command for all logical systems on a physical system via REST, or is this something that will need to raised up through through the proper channels?

1 REPLY 1
Highlighted
Junos Automation (Scripting)

Re: REST API All Logical Systems

‎09-17-2018 01:00 AM

I have not found any way to retrieve this information from a router via the REST API as of yet, but if anyone else is looking for a hacky solution, here is a workaround until such time the REST API supports the "all" parameter supported via the CLI interface, or another method of retrieving information on all logical systems for a given command configured on a given physical device is provided.

 

 

import sys
from jnpr.junos import Device
from jnpr.junos.exception import ConnectError
from lxml import etree
import re

HOSTNAME='<ip_address'
USERNAME='<username>'
PASSWORD='<password>'
PORT=<port>

d = Device(host=HOSTNAME, user=USERNAME, password=PASSWORD, port=PORT)


def get_logical_systems():

    if d.probe(timeout=3):
        try:
            d.open(gather_facts=False)

            ls_hack = d.rpc.get_config(options={'database' : 'committed', 'format': 'text'})
            ls_hack = etree.tostring(ls_hack, encoding='unicode')

            ls_hack_pattern = re.compile(r'foo\d{1,2}')

            re_hack = ls_hack_pattern.findall(string=ls_hack)

            logical_systems = list()
            [logical_systems.append(l) for l in re_hack if l not in logical_systems]

            d.close()

            return logical_systems

        except ConnectError:
            sys.exit()
    else:
        return None


foo = get_logical_systems()
if foo is not None:
    print(foo)

Output:

 

python3 test_1.py 
['foo1', 'foo2', 'foo3', 'foo4', 'foo5', 'foo6', 'foo7', 'foo8', 'foo10', 'foo11', 'foo12', 'foo20', 'foo9', 'foo99']

If anyone has a better (or proper) approach I am all ears, and it would be greatly appreciated.

Feedback