Showing posts with label junos. Show all posts
Showing posts with label junos. Show all posts

Sunday, October 12, 2014

Not all APIs are created equally.

Automation is starting to become the new catch phrase in the networking Industry. It seems like 2014 is the year that marketing groups from different vendors have been touting APIs on their products. Skeptical networking engineers however have claimed that an API does not mean that their jobs are getting easier. In fact it’s been making their jobs a little harder.
Before a networking engineer could strictly focus on pure networking. But now, network engineers are increasingly required to know more and more on how to code or at least know how to read code.

Just because you have an API doesn’t mean all the devices can and will play nice with each other. 

We can see this by looking at three different platforms. 

OpenStack         Contrail        Junos

Now let’s look at their API for data retrieval/configuration

REST                  REST           Netconf

Ok now you have two platforms that use one type of API and a third platform that uses a different API.

Let's look at the resulting Data Structure response

JSON                JSON XML

Again we have two platforms that have the same Data Structure and a third with a different Data Structure.

You might say, ok, at least two of these platforms have the same API and with the same data structure things should be good for both of them right? Actually as they say, the devil is in the details.

I can illustrate this just by looking at a simple IPv4 subnet. 

On Openstack the data abstracted looks like this

{ "networks": [ { "contrail:subnet_ipam":  [  { "subnet_cidr": "12.1.1.0/24",  } ] } ] }

On Contrail it looks like this

{"virtual-network":{ "network_ipam_refs":[ { "attr": { "ipam_subnets": [ { "subnet": { "ip_prefix": "12.1.1.0", "ip_prefix_len": 24 }, } ] }, } ], } }

You can see that one platform combines the subnet with the mask while the other one separates it. For a DevOps engineers and Network Engineers this is annoying. It’s like having to learn different Network Operating systems. The goal of an API should be to allow a simplified abstraction layer.


APIs need to be standardized. Openflow is a good attempt at this. Openflow requires the underlay to have a common protocol in order to allow a controller to programmatically configure them. The networking industry has done a great job at standardizing protocols but a sorry job at creating a common API standard. Maybe the IETF needs to jump in on this. A standardized API could ultimately make our jobs that much more easier.

Friday, August 29, 2014

Juniper olive console port issue

So I decided to try out the Juniper olive I've been hearing about. I looked online and noticed how people were able to create a virtual Junos device on a virtualization platform like VMWare ESXi. The one problem that all the users were having was that the images were meant to be installed onto an actual router and configuring the device meant connecting to it via a console port. The problem there is that in a virtual platform, there is no physical access to the console port.

What you end up seeing on the video console is this message:

If only you could modify the image so that the /boot/loader.conf file so instead of reading:

console="comconsole"

it could be modify to project on the video console.

console="comconsole, vidconsole"

I found out that VMWare has the ability to allow remote serial connectivity through telnet. First you add a serial port.

Then in the pull down menu, you choose network.

Next you select Direction and choose Server. In the port URL you'll need to map the port number to a new value that is not a well know port number. I chose 10026. You add the url

telnet://:<your_port_number>

Then after you spin up the VM. You access the new VM by telneting to the Host Server's IP and the custom port number you created. It may take a while, but eventually you'll get a prompt.

My_Mac% telnet 10.11.39.145 10026
Trying 10.11.39.145...
Connected to 10.11.39.145.
Escape character is '^]'.


Amnesiac (ttyd0)

login:root



Next you can edit the /boot/loader.conf file or add an IP address and turn on telnet/ssh service on the Virtual Junos so you can directly access the device through a management port.


Thursday, July 17, 2014

In service software upgrade ISSU on a Juniper leaf switch QFX5100 with minimal traffic distruption.

QFX5100 ISSU

The Juniper QFX5100 switch has the ability to be upgraded while in service (production) with minimal impact. This is useful when let's say this QFX is used as a leaf switch with servers directly attached to it. Since most TOR (Top-of-Rack) switches do not have redundant CPUs, i.e. control plane, this feature is a necessity.

Currently Data Centers would have to migrate VMs on host servers to other hosts residing on other TOR switches. An upgrade would happen on the switch that would be taken out of service and then VMs would have to be migrated back. This could take several hours and also could be an issue if resources on other switches were limited.

How ISSU works

Just like Virtualization in the Server world, the QFX switch has a hypervisor (KVM) and a VM that runs JUNOS (JVM).
You would need to configure GRES (Graceful Routing-Engine Switchover), non-stop routing and non-stop bridging before starting.
From the JVM (running the current code) you would issue the ISSU upgrade command: request system software in-service-upgrade <image version>
Using the new code image a second JVM is launched as a backup.
Next a Master-Backup election would happen between the VMs with the Master being elected on the current version of code.
It will then sync all the state tables to between the two VMs.
The Backup VM would then connect to the Packet Forwarding Engine (i.e. asic).
The device drivers would then detach from the old master while simultaneously attach the device drivers to current backup JVM
Switchover mastership for the current backup to tbecome the new master
Kill the old JVM running the old version of code.


In this test I setup IXIA traffic testers that injected 10K OSPF, 2K BGP routes and 10K mac addresses. Traffic was then sent to these destination addresses.

jnpr> show route summary
Autonomous system number: 100
Router ID: 1.1.1.1

inet.0: 12015 destinations, 12015 routes (12015 active, 0 holddown, 0 hidden)
              Direct:      7 routes,      7 active
               Local:      6 routes,      6 active
                OSPF:  10001 routes,  10001 active
                 BGP:   2000 routes,   2000 active
              Static:      1 routes,      1 active

{master:0}
jnpr> show ethernet-switching table summary
Total dynamic and static MAC addresses learned globally : 10004
Configured static MAC addresses learned globally       : 0

{master:0}
jnpr> edit  
Entering configuration mode

{master:0}[edit]
jnpr# show routing-options
nonstop-routing;
autonomous-system 100;

{master:0}[edit]
jnpr# show protocols layer2-control
nonstop-bridging;

{master:0}[edit]
jnpr# show chassis
redundancy {
    graceful-switchover;
}



jnpr# show interfaces
xe-0/0/0:0 {
    unit 0 {
        family ethernet-switching {
            interface-mode trunk;
            vlan {
                members all;
            }
        }
    }
}
xe-0/0/0:1 {
    unit 0 {
        family ethernet-switching {
            interface-mode trunk;
            vlan {
                members all;
            }
        }
    }
}
irb {
    unit 100 {
        family inet {
            address 100.1.1.1/24;
        }
    }
    unit 101 {
        family inet {
            address 101.1.1.1/24;
        }
    }
    unit 200 {                         
        family inet {
            address 200.1.1.1/24;
        }
    }
    unit 201 {
        family inet {
            address 201.1.1.1/24;
        }
    }
    unit 300 {
        family inet {
            address 110.1.1.254/24;
        }
    }
}
lo0 {
    unit 0 {
        family inet {
            address 1.1.1.1/32;
        }
    }
}

{master:0}[edit]
jnpr# show protocols
bgp {
    group EBGP {
        type external;
        neighbor 200.1.1.2 {
            peer-as 200;
        }
        neighbor 201.1.1.2 {
            peer-as 201;
        }
    }
}
ospf {
    area 0.0.0.0 {
        interface irb.100;
        interface irb.101;
    }
}
layer2-control {
    nonstop-bridging;
}


UPGRADE PROCESS:


{master:0}
jnpr> show version
fpc0:
--------------------------------------------------------------------------
Model: qfx5100-24q-2p
JUNOS Base OS Software Suite [13.2X51-D15.5]
JUNOS Base OS boot [13.2X51-D15.5]
JUNOS Crypto Software Suite [13.2X51-D15.5]
JUNOS Online Documentation [13.2X51-D15.5]
JUNOS Kernel Software Suite [13.2X51-D15.5]
JUNOS Packet Forwarding Engine Support (qfx-x86-32) [13.2X51-D15.5]
JUNOS Routing Software Suite [13.2X51-D15.5]
JUNOS Enterprise Software Suite [13.2X51-D15.5]
JUNOS py-base-i386 [13.2X51-D15.5]
JUNOS Host Software [13.2X51-D15.5]


{master:0}
jnpr> request system software in-service-upgrade ftp://jnpr:pass123@192.168.1.1:/jinstall-qfx-5-13.2X51-D21.1-domestic-img.tgz  
warning: Do NOT use /user during ISSU. Changes to /user during ISSU may get lost!
ISSU: Validating Image
Fetching package...
ISSU: Preparing Backup RE
Prepare for ISSU
ISSU: Backup RE Prepare Done
Spawning the backup RE
Spawn backup RE, index 0 successful
GRES in progress
GRES done in 13 seconds
Waiting for backup RE switchover ready
GRES operational
Copying home directories
Copying home directories successful
Initiating Chassis In-Service-Upgrade
Chassis ISSU Started
ISSU: Preparing Daemons
ISSU: Daemons Ready for ISSU
ISSU: Starting Upgrade for FRUs
ISSU: FPC Warm Booting
ISSU: FPC Warm Booted
ISSU: Preparing for Switchover
ISSU: Ready for Switchover
Checking In-Service-Upgrade status
  Item           Status                  Reason
  FPC 0          Online (ISSU)       
Send ISSU done to chassisd on backup RE
Chassis ISSU Completed
ISSU: IDLE
Initiate em0 device handoff
Connection closed by foreign host.
[jnpr-laptop:~] jnpr%
[jnpr-laptop:~] jnpr% expect telly 10.161.33.53
spawn telnet -K 10.161.33.53
Trying 10.161.33.53...
Connected to 10.161.33.53.
Escape character is '^]'.

 (ttyp0)

login: jnpr
Password:

--- JUNOS 13.2X51-D21.1 built 2014-05-29 11:41:16 UTC
{master:0}
jnpr> show version
fpc0:
--------------------------------------------------------------------------
Model: qfx5100-24q-2p
JUNOS Base OS Software Suite [13.2X51-D21.1]
JUNOS Base OS boot [13.2X51-D21.1]
JUNOS Crypto Software Suite [13.2X51-D21.1]
JUNOS Online Documentation [13.2X51-D21.1]
JUNOS Kernel Software Suite [13.2X51-D21.1]
JUNOS Packet Forwarding Engine Support (qfx-ex-x86-32) [13.2X51-D21.1]
JUNOS Routing Software Suite [13.2X51-D21.1]
JUNOS Enterprise Software Suite [13.2X51-D21.1]
JUNOS py-base-i386 [13.2X51-D21.1]
JUNOS Host Software [13.2X51-D15.5]


IXIA Results

That's 52 frames lost with a service disruption of 2.6 ms (milliseconds).

Wednesday, June 18, 2014

Op script - Interface auto-description based on lldp learned neighbors

A coworker said that Arista had this python PortAutoDescription script that auto populates the ports on a switch with it's neighbor description learned through lldp. He was wondering if Juniper had such an implementation. Well this is not built into Junos, but is really easy to do as a SLAX script.

Here it is in action:

{master:0}[edit]

jnpr@SW1# run show lldp neighbors

Local Interface    Parent Interface    Chassis Id          Port info          System Name

ge-0/0/47.0        -                   00:21:59:c7:09:40   ge-0/0/47.0        SW3b               

ge-0/0/44.0        -                   78:19:f7:9f:77:00   ge-0/0/44.0        SW2b               



{master:0}[edit]

jnpr@SW1# show interfaces

ge-0/0/44 {

    unit 0 {

        family ethernet-switching {

            port-mode trunk;

            vlan {

                members all;

            }

        }

    }

}

ge-0/0/47 {

    unit 0 {

        family ethernet-switching {

            port-mode access;

            vlan {

                members v100;

            }

        }

    }

}



{master:0}[edit]

jnpr@SW1# run op IntAutoDesc

lldp-local-interface ge-0/0/47.0 connected to lldp-remote-system-name SW3b

configuration check succeeds

commit complete

lldp-local-interface ge-0/0/44.0 connected to lldp-remote-system-name SW2b

configuration check succeeds

commit complete



{master:0}[edit]

jnpr@SW1# show interfaces

ge-0/0/44 {

    description to-SW2b;

    unit 0 {

        family ethernet-switching {

            port-mode trunk;

            vlan {

                members all;

            }

        }

    }

}

ge-0/0/47 {

    description to-SW3b;

    unit 0 {

        family ethernet-switching {

            port-mode access;

            vlan {

                members v100;

            }

        }

    }

}

SOURCE CODE
----------------------------------

version 1.0;

ns junos= "http://xml.juniper.net/junos/*/junos";

ns xnm= "http://xml.juniper.net/xnm/1.1/xnm";

ns jcs= "http://xml.juniper.net/junos/commit-scripts/1.0";

import "../import/junos.xsl";

match /

{

    <event-op-results> {

        var $lldp-info = <command> "show lldp neighbor ";

        var $lldp-result = jcs:invoke($lldp-info);

        var $con = jcs:open();
        for-each($lldp-result/lldp-neighbor-information)

        {
                var $lldp-int = current()/lldp-local-interface;
                var $lldp-remote = current()/lldp-remote-system-name;
                <output>local-name($lldp-int) _ " " _ $lldp-int _ " connected to " _ local-name($lldp-remote) _ " " _ $lldp-remote;

        var $if = substring-before($lldp-int, ".");
        var $int = <configuration> {
           <interfaces> {
              <interface> {
                       <name> $if;
                       <description> "to-" _ $lldp-remote;
               }
             }
        }

        call jcs:load-configuration($connection = $con, $configuration = $int);


        }

        expr jcs:close($con);

      }

}

Monday, June 16, 2014

Python script - make a config change to a Juniper device remotely

I had a previous blog post on how to make a config change remotely using python. This new script uses a more structured framework from python-ez. I will be making calls to the following module:

% pwd
/Library/Python/2.7/site-packages/jnpr/junos/cfg/phyport

The base module supports the following methods:

    PROPERTIES = [
        'admin',              # True
        'description',        # str
        'speed',              # ['10m','100m','1g','10g']
        'duplex',             # ['full','half']
        'mtu',                # int
        'loopback',           # True
        '$unit_count'         # number of units defined
    ]

With python I can iterate through all the interfaces and change the mtu size on all the interfaces

before the change:

jnpr@R1# show interfaces
xe-0/0/0 {
    mtu 1500;
}
xe-0/0/1 {
    mtu 1500;
}
xe-0/0/2 {
    mtu 1500;
}
xe-0/0/3 {
    mtu 1500;
}

% python mtu-chg.py
Host: 10.161.33.171
Model: MX80-P
Version: 12.3R1.7
Changing MTU to 9000 on the following interfaces:
xe-0/0/0
xe-0/0/1
xe-0/0/2
xe-0/0/3

after

jnpr@R1# show interfaces   
xe-0/0/0 {
    mtu 9000;
}
xe-0/0/1 {
    mtu 9000;
}
xe-0/0/2 {
    mtu 9000;
}
xe-0/0/3 {
    mtu 9000;
}

SOURCE CODE
------------

from jnpr.junos import Device as Junos
from jnpr.junos.cfg.phyport import *

login = dict(user='jnpr', host='10.161.33.171', password='pass123')

rtr = Junos(**login)

rtr.open()

print "Host: " + rtr.hostname
print "Model: " + rtr.facts['model']
print "Version: " + rtr.facts['version']
size = 9000

ints = PhyPort(rtr)
print "Changing MTU to %s on the following interfaces:" % size
for int in ints:
  print int.name
  int['mtu'] = size
  int.write()

rtr.close()

Sunday, June 15, 2014

Python script - check for interface errors remotely.

In my last blog post I created a slax script that would tell you which interfaces that had errors on it. I recreated this script again using Python so a NetOps engineer could check it remotely. This could be useful if you have multiple networking equipment and want to track down what may be causing packet loss.

Somethings to consider. I'm using the juniper python library from GITHUB https://github.com/jeremyschulman/py-junos-eznc

There are a few things to note. The library to see the relevant python methods can be found here.

/Library/Python/2.7/site-packages/jnpr/junos/op

There is a YAML file phyport.yml which shows what each rpc and attributes are supported.


PhyPortErrorTable:
  rpc: get-interface-information
  args:
    extensive: True
    interface_name: '[fgx]e*'
  args_key: interface_name
  item: physical-interface
  view: PhyPortErrorView

PhyPortErrorView:
  groups:
    ts: traffic-statistics
    rxerrs: input-error-list
    txerrs: output-error-list

  # fields that are part of groups are called
  # "fields_<group-name>"

  fields_ts:
    rx_bytes: { input-bytes: int }
    rx_packets: { input-packets: int }
    tx_bytes: { output-bytes: int }
    tx_packets: { output-packets: int }

  fields_rxerrs:
    rx_err_input: { input-errors: int }
    rx_err_drops: { input-drops: int }
    rx_err_frame: { framing-errors: int }
    rx_err_runts: { input-runts: int }
    rx_err_discards: { input-discards: int }
    rx_err_l3-incompletes: { input-l3-incompletes: int }
    rx_err_l2-channel: { input-l2-channel-errors: int }
    rx_err_l2-mismatch: { input-l2-mismatch-timeouts: int }
    rx_err_fifo: { input-fifo-errors: int }
    rx_err_resource: { input-resource-errors: int }

  fields_txerrs:
    tx_err_carrier-transitions: { carrier-transitions: int }
    tx_err_output: { output-errors: int }
    tx_err_collisions: { output-collisions: int }
    tx_err_drops: { output-drops: int }
    tx_err_aged: { aged-packets: int }
    tx_err_mtu: { mtu-errors: int }
    tx_err_hs-crc: { hs-link-crc-errors: int }
    tx_err_fifo: { output-fifo-errors: int }
    tx_err_resource: { output-resource-errors: int }


script in action:

[mylaptop:~/scripts/PYTHON/] user% python error.py
host: 192.168.1.1
Interface    Error
xe-0/0/1     tx_err_carrier-transitions 6
xe-0/0/3     tx_err_carrier-transitions 7
ge-1/0/0     tx_err_drops 35994597
ge-1/0/0     tx_err_carrier-transitions 23
ge-1/1/0     tx_err_carrier-transitions 25
ge-1/1/1     tx_err_carrier-transitions 29
ge-1/1/3     rx_err_frame 1
ge-1/1/3     tx_err_carrier-transitions 31
ge-1/1/3     rx_err_input 1
ge-1/1/5     tx_err_carrier-transitions 11
ge-1/1/8     tx_err_carrier-transitions 8


-----------
SOURCE CODE
----------

from pprint import pprint as pp

from lxml import etree

from jnpr.junos import Device as Junos

from jnpr.junos.op.phyport import *

import json
import itertools

login = dict(user='user', host='192.168.1.1', password='password')

rtr = Junos(**login)

rtr.open()

ports = PhyPortTable(rtr).get()
stats = PhyPortErrorTable(rtr).get()


print "host: " + rtr.hostname
print "Interface\tError"



for port,stat in map(None,ports,stats):
   for attr in stat.FIELDS:
     if 'err' in attr:
       if getattr(stat,attr) != 0:
         print port.name.ljust(12), attr.ljust(12), getattr(stat, attr)



rtr.close()

Wednesday, June 11, 2014

Find and display any and all interface errors easily. Juniper slax script

Whenever I troubleshot a router in a network, I always started at layer 1. However when there were hundreds of links connected to the equipment, narrowing the problem down was difficult.

When there are are many interfaces on your Juniper router, it could take a long time to look at each interface and check to see if there are errors.

Doing a "pipe" and grepping for errors is a mess. You can't find out which interface the counters are associated with.

This simple Juniper slax script will do all the work for you. Saved me many times when I found out the problem was a layer 1 issue.


jnpr@router> op error
Error on input errors:  xe-1/0/2 on input-errors 768
Error on input errors:  xe-1/0/2 on framing-errors 768
Error on input errors:  xe-8/2/3 on input-errors 8
Error on input errors:  xe-8/2/3 on framing-errors 8
Error on input errors:  xe-9/0/1 on input-errors 2
Error on input errors:  xe-9/0/1 on framing-errors 2

---------------

version 1.0;

ns junos= "http://xml.juniper.net/junos/*/junos";

ns xnm= "http://xml.juniper.net/xnm/1.1/xnm";

ns jcs= "http://xml.juniper.net/junos/commit-scripts/1.0";

import "../import/junos.xsl";



match /
{
    <event-op-results> {

        var $interface-info = <command> "show interfaces extensive ";
        var $interface-result = jcs:invoke($interface-info);

        for-each($interface-result/physical-interface)
        {
                var $interface-name = current()/name;
                for-each(current()/input-error-list/*) {
                if(current() != 0)
                {
                        <output>"Error on input errors:  " _ $interface-name _ " on " _ local-name(current()) _ " " _ current();
                }
              }
                for-each(current()/output-error-list/*) {
                if(current() != 0)
                {
                        <output>"Error on output errors:  " _ $interface-name _ " on " _ local-name(current()) _ " " _ current();
                 
                }
              }
        }
      }
}

Thursday, May 29, 2014

python script that will add a vlan on a Juniper switch

Here's a simple python script to add a vlan on an EX switch. I use an argument to pass the vlan id to the script.

from my laptop shell
----------
[MYMAC:~/scripts/PYTHON] user% python vlan_add.py 100
Config added:
set vlans v100 vlan-id 100
diff from junos device:

[edit vlans]
+   v100 {
+       vlan-id 100;
+   }

None
---------------------------
On the EX switch:

{master:0}[edit]
user@myswitch# show vlans 
v100 {
    vlan-id 100;
}

The python script:

[MYMAC:~/scripts/PYTHON] user% more vlan_add.py 
------------------------
from sys import argv
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
session = Device(host='myswitch',user='user',password='password')
session.open()
change = Config(session)
vlan = argv[1]
cmd = 'set vlans v%s vlan-id %s' % (vlan,vlan)
print 'Config added:'
print cmd
change.load(cmd, format ='set')
print 'diff from junos device:'
print change.pdiff()
change.commit()
session.close()

Monday, April 21, 2014

JUNOS scripts on a EX Virtual Chassis needs each potential Routing Engine to have a copy of all scripts in /var/db/scripts/

How do we go about copying these to all devices in a Virtual Chassis?

normally you would use the file copy command:

run file copy /var/db/scripts/commit/script.slax fpc0:/var/db/scripts/commit/

This is a manual process. So let's try to automate this. The name of the test script is called "vc-copy.slax" you could create an argument in the script to pass the file name to the op script.

This script will look at the member id and see which fpcs are present to copy the scripts.


jnpr@EX4200-VC1# run show virtual-chassis status  

Virtual Chassis ID: 030b.bd6f.ed90
                                          Mastership            Neighbor List
Member ID  Status   Serial No    Model    priority    Role      ID  Interface
0 (FPC 0)  Prsnt    BP0208192416 ex4200-48t      200  Master*    3  vcp-0    
                                                                 1  vcp-1    
1 (FPC 1)  Prsnt    BP0208377206 ex4200-48t      199  Backup     0  vcp-0    
                                                                 2  vcp-1    
2 (FPC 2)  Prsnt    BP0208377298 ex4200-48t      198  Linecard   1  vcp-0    
                                                                 3  vcp-1    
3 (FPC 3)  Prsnt    BP0208192367 ex4200-48t      128  Linecard   2  vcp-0    
                                                                 0  vcp-1    

Member ID for next new member: 4 (FPC 4)


jnpr@EX4200-VC1# run file list /var/db/scripts/op

/var/db/scripts/op:
vc-copy.slax

{master:0}[edit]
jnpr@EX4200-VC1# run op vc-copy                          
fpc0:/var/db/scripts/op/vc-copy.slax
fpc1:/var/db/scripts/op/vc-copy.slax
fpc2:/var/db/scripts/op/vc-copy.slax
fpc3:/var/db/scripts/op/vc-copy.slax

{master:0}[edit]
jnpr@EX4200-VC1# run file list fpc1:/var/db/scripts/op
fpc1:
--------------------------------------------------------------------------

/var/db/scripts/op:
vc-copy.slax

{master:0}[edit]
jnpr@EX4200-VC1# run file list fpc2:/var/db/scripts/op  
fpc2:
--------------------------------------------------------------------------

/var/db/scripts/op:
vc-copy.slax
-----------------

version 1.0;

ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";

import "../import/junos.xsl";

match / {
    <op-script-results> {
        <output method = "text"> {
            var $rpc = <command> "show virtual-chassis status";

            var $out = jcs:invoke($rpc);
              
            for-each ($out//member){
         
            var $fpc = ./fpc-slot;
  
            var $strip-space = translate($fpc, ' ', '');
            var $strip-left = translate($strip-space, '( ', '');
            var $strip-right = translate($strip-left, ')', ''); 
            var $result = translate($strip-right, 'FPC', 'fpc');
           

            var $dest = concat ($result, ':/var/db/scripts/op/vc-copy.slax'); 
            expr $dest _ "\n";


            var $ftp = {
                         <file-copy> {
                           <source> "/var/db/scripts/op/vc-copy.slax";
                           <destination> $dest;
                         }
            }
            var $exec = jcs:invoke($ftp);   




            }
            
        }
    }
}

Friday, April 18, 2014

Junos Scripting - Is it possible to pass multiple values as part of the same argument?


For example, assume I want to check something only on certain interfaces.  Can I say something like:
op check-intf <argument> [ ge-0/0/0 ge-0/0/1 ge-0/0/2 ]

 If possible, I assume this would be passed as an array.  If so, what is the syntax to for-each over each element?

you should be able to enclose the multiple values in quotes to make a single string.  You could use jcs:split( " ", $argument ) to separate out the different values from the combined string.


jnpr@EX4200-VC1# run op parse objects "ge-1/0/0 ge-1/1/0 ge-1/2/0" 
field: ge-1/0/0
field: ge-1/1/0
field: ge-1/2/0


script
-----------------------------------


version 1.0;
 
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
 
import "../import/junos.xsl";
 
var $arguments = {
            expr $objects;
         
    <argument> {
       <name> "objects";
       <description> "enter objects";
    }
 
}
 
param $objects;
 
match / {
    <op-script-results> {
        <output method = "text"> {
            var $field = jcs:split(' ', $objects);        

            for-each ($field) {

               expr "field: " _ . _ "\n";    
            }
        }
    }
}

Sunday, March 30, 2014

Op script - Sort of an array

Defining ENUM-like data structure in the script itself. A simple tutorial script on how to sort via slax.


[edit]
jnpr@Boomer-RE0# run op array    
10.10.10.3
10.10.10.2
10.10.10.1

---------------
version 1.0;
 
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
 
import "../import/junos.xsl";
 
match / {
    <op-script-results> {
        <output method= "text"> {

            var $enum := {
               <ipaddr>"10.10.10.1";
               <ipaddr>"10.10.10.2";
               <ipaddr>"10.10.10.3";
            }


            for-each ($enum/ipaddr) { 
                <xsl:sort select = "." order = "descending">;
                expr . _ "\n";
            }
        }
    }
}

Saturday, March 29, 2014

Split an IP address and convert decimal to hex using Junos scripting

Here's a simple script to convert decimal to hex. There could be a reason to get the hex value of an ip address.
user@router# run op HEX
BEFORE 192.168.1.1
AFTER C0A811
script
-------------
version 1.0;
/* OP SCRIPT BY FERDINAND */
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
import "../import/junos.xsl";
match / {
    <op-script-results> {
        <output method= "text"> {
        var $ip_address = "192.168.1.1";
          expr "BEFORE " _ $ip_address _ "\n";
          var $field = jcs:split('\\.', $ip_address);
          expr "AFTER ";
            for-each ($field) {
               call dec_to_hex($value = .);
            }
        }
    }
}
template dec_to_hex ($value) {
    if ($value >= 16) {
        call dec_to_hex($value = floor($value div 16));
    }
    var $hex_digits = "0123456789ABCDEF";
    expr substring($hex_digits,($value mod 16) + 1, 1);
}

Wednesday, November 20, 2013

Running shell scripts on Junos

You can run a shell script in Junos.

user@R1> start shell
% su
Password:
root@R1% sh tpl.sh 
root@R1% ls
op1.txt tpl.sh
root@R1% more op1.txt 
set interfaces xe-0/0/0 description to-R4-xe-0/3/0
set interfaces xe-0/0/0 unit 0 family inet mtu 1500

root@R1% 
root@R1% more tpl.sh 
#!/sbin/sh

cli -c 'show configuration interfaces | display set' >> op1.txt
root@R1% 
root@R1% exit
exit
% exit

Saturday, November 9, 2013

Op script to disable a vc-port in a virtual chassis

A customer asked for a script to disable a vcp-port in case there were flapping issues.

There is a cli command that does this

jnpr@EX4200-VC-2> request virtual-chassis vc-port set interface vcp-0 disable member 0 
fpc0:
--------------------------------------------------------------------------

{master:0}
jnpr@EX4200-VC-2> show virtual-chassis vc-port 
fpc0:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Disabled     32000   <<<<<<<<<<<<<<<< HERE
vcp-1       Dedicated           2    Up           32000        1   vcp-0  

fpc1:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        0   vcp-1  
vcp-1       Dedicated           2    Down         32000

jnpr@EX4200-VC-2> request virtual-chassis vc-port set interface vcp-0 member 0           
fpc0:
--------------------------------------------------------------------------

{master:0}
jnpr@EX4200-VC-2> show virtual-chassis vc-port                                    
fpc0:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        1   vcp-1  <<<<<<<<<<< re-enabled
vcp-1       Dedicated           2    Up           32000        1   vcp-0  

fpc1:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        0   vcp-1  
vcp-1       Dedicated           2    Up           32000        0   vcp-0  

----------------------

Demo of the script to disable vc-port

-----------------------

jnpr@EX4200-VC-2# run show virtual-chassis vc-port 
fpc0:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        1   vcp-1  
vcp-1       Dedicated           2    Up           32000        1   vcp-0  

fpc1:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        0   vcp-1  
vcp-1       Dedicated           2    Up           32000        0   vcp-0  

{master:0}[edit]
jnpr@EX4200-VC-2# run op vcp ?
Possible completions:
  <[Enter]>            Execute this command
  <name>               Argument name
  action               0 to enable, 1 to disable
  detail               Display detailed output
  interface            interface name.
  |                    Pipe through a command
{master:0}[edit]
jnpr@EX4200-VC-2# run op vcp interface vcp-0 action 1 

jnpr@EX4200-VC-2# run show virtual-chassis vc-port 
fpc0:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Disabled     32000
vcp-1       Dedicated           2    Up           32000        1   vcp-0  

fpc1:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        0   vcp-1  
vcp-1       Dedicated           2    Down         32000

{master:0}[edit]
jnpr@EX4200-VC-2# run op vcp interface vcp-0 action 0    

{master:0}[edit]
jnpr@EX4200-VC-2# run show virtual-chassis vc-port       
fpc0:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        1   vcp-1  
vcp-1       Dedicated           2    Up           32000        1   vcp-0  

fpc1:
--------------------------------------------------------------------------
Interface   Type              Trunk  Status       Speed        Neighbor
or                             ID                 (mbps)       ID  Interface
PIC / Port
vcp-0       Dedicated           1    Up           32000        0   vcp-1  
vcp-1       Dedicated           2    Up           32000        0   vcp-0  


---------------------------- 
Source code
----------------------------

jnpr@EX4200-VC-2# run file show /var/db/scripts/op/vcp.slax 
version 1.0;

ns junos= "http://xml.juniper.net/junos/*/junos";

ns xnm= "http://xml.juniper.net/xnm/1.1/xnm";

ns jcs= "http://xml.juniper.net/junos/commit-scripts/1.0";

import "../import/junos.xsl";

var $arguments = {
    <argument> {
        <name> "interface";
        <description> "interface name.";
    }
    <argument> {
        <name> "action";
        <description> "0 to enable, 1 to disable";
    }
}
param $interface;
param $action =0;

                                        
match /
{
    <event-op-results> {

        if ($action = 1) {
           var $interface-info = <command> "request virtual-chassis vc-port set interface " _ $interface _ " disable member 0";
           var $interface-result = jcs:invoke($interface-info);
        }
        if ($action = 0) {
           var $interface-info = <command> "request virtual-chassis vc-port set
interface " _ $interface _ " member 0";
           var $interface-result = jcs:invoke($interface-info);
        }

    }

}

Thursday, November 7, 2013

FEC 129 - VPLS with BGP auto-discovery using LDP

New version of JUNOS supports FEC 129 BGP auto-discovery.
You don't have to manually configure each pseudo wire. You will use BGP to auto discover the other PEs. no need for a site-ids (rsvp based) or vpls-ids (manual ldp psuedowires). 

Two commands to consider is the l2vpn-id which is similar to the vrf-target. And the auto-discovery-only command in BGP. 

Below will connect to various PEs 

user@router# show routing-instances 
VPLS {
    instance-type vpls;
    interface et-0/1/0.1;
    route-distinguisher 2.2.2.2:852;
    l2vpn-id l2vpn-id:100:1;
    vrf-target target:100:1;
    protocols {
        vpls {
            encapsulation-type ethernet-vlan;
            no-tunnel-services;
        }
    }
}

{master}[edit]
user@router# show protocols bgp 
path-selection external-router-id;
log-updown;
group RR {
    type internal;
    local-address 2.2.2.2;
    family l2vpn {
        auto-discovery-only;
    }
    neighbor 192.168.1.1;
    neighbor 192.168.1.2;
    neighbor 192.168.1.3;
    neighbor 192.168.1.4;
    neighbor 192.168.1.5;
    neighbor 192.168.1.6;               
    neighbor 192.168.1.7;
    neighbor 192.168.1.8;
    neighbor 192.168.1.10;
}

{master}[edit]
user@router# show interfaces et-0/1/0 
flexible-vlan-tagging;
encapsulation flexible-ethernet-services;
unit 1 {
    encapsulation vlan-vpls;
    vlan-id 1;
    family vpls;
}


user@router# run show ldp database session 192.168.1.1 
Input label database, 2.2.2.2:0--192.168.1.1:0
  Label     Prefix
     16      FEC129 NoCtrlWord VLAN 000a0064:00000001 c0a80101 02020202

Output label database, 2.2.2.2:0--192.168.1.1:0
  Label     Prefix
      0      2.2.2.2/32
 299920      192.168.1.1/32
 299936      192.168.1.2/32
 299952      192.168.1.3/32
 299968      192.168.1.4/32
 299984      192.168.1.5/32
 300000      192.168.1.6/32
 300016      192.168.1.7/32
 300032      192.168.1.8/32
 300048      192.168.1.9/32
 300064      192.168.1.10/32
 262145      FEC129 NoCtrlWord VLAN 000a0064:00000001 02020202 c0a80101

{master}[edit]
user@router# run show bgp summary 
Groups: 1 Peers: 9 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0               
                       0          0          0          0          0          0
inet6.0              
                       0          0          0          0          0          0
bgp.l2vpn.0          
                       9          9          0          0          0          0
inet.2               
                       0          0          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.168.1.1             852         18         20       0       0        8:07 Establ
  inet.0: 0/0/0/0
  inet6.0: 0/0/0/0
  bgp.l2vpn.0: 1/1/1/0
  inet.2: 0/0/0/0
  VPLS.l2vpn.0: 1/1/1/0

                                        
{master}[edit]
user@router# run show vpls connections 
Layer-2 VPN connections:

Legend for connection status (St)   
EI -- encapsulation invalid      NC -- interface encapsulation not CCC/TCC/VPLS
EM -- encapsulation mismatch     WE -- interface and instance encaps not same
VC-Dn -- Virtual circuit down    NP -- interface hardware not present 
CM -- control-word mismatch      -> -- only outbound connection is up
CN -- circuit not provisioned    <- -- only inbound connection is up
OR -- out of range               Up -- operational
OL -- no outgoing label          Dn -- down                      
LD -- local site signaled down   CF -- call admission control failure      
RD -- remote site signaled down  SC -- local and remote site ID collision
LN -- local site not designated  LM -- local site ID not minimum designated
RN -- remote site not designated RM -- remote site ID not minimum designated
XX -- unknown connection status  IL -- no incoming label
MM -- MTU mismatch               MI -- Mesh-Group ID not available
BK -- Backup connection         ST -- Standby connection
PF -- Profile parse failure      PB -- Profile busy
RS -- remote site standby SN -- Static Neighbor
LB -- Local site not best-site   RB -- Remote site not best-site
VM -- VLAN ID mismatch

Legend for interface status 
Up -- operational           
Dn -- down

Instance: VPLS
  L2vpn-id: 100:1
  Local-id: 2.2.2.2
    Remote-id                 Type  St     Time last up          # Up trans
    192.168.1.1               rmt   Up     Nov  7 20:58:18 2013           1
      Remote PE: 192.168.1.1, Negotiated control-word: No
      Incoming label: 262145, Outgoing label: 16
      Local interface: lsi.1048841, Status: Up, Encapsulation: VLAN
        Description: Intf - vpls VPLS local-id 2.2.2.2 remote-id 192.168.1.1 neighbor 192.168.1.1