Showing posts with label slax. Show all posts
Showing posts with label slax. Show all posts

Thursday, July 10, 2014

OP script - look up a vendor mac oui directly from a juniper switch using slax and cURL

I found a couple of cool things in Juniper scripting.

There is the ability to retrieve data over an internet connection using curl. From Juniper - cURL is a tool that uses the libcurl library and permits data transfers using a number of protocols, including FTP, FTPS, HTTP, HTTPS, SCP, and SMTP.

BTW I'm using cURL on an EX switch that is running 12.3R3.4. I didn't see this on 11.4 code.

This got me thinking. Whenever I'm troubleshooting a switch, usually due to some errant device in the network, I have to look up the IEEE Mac OUI address. This entails copying each mac address in the mac table of the script. Then I can go to a website like www.macvendors.com and paste the MACOUI to retrieve the vendor of the mac. This could be a pain if you had to parse through hundreds of mac addresses.

Luckily, macvendors.com has an API. 

So what if we used the power of curl and scripting to do this for you. Instead of having to open up a separate web browser, have the switch fetch the info over the internet and do it for you.

See the difference below.

{master:0}[edit]
user@SWITCH# run show ethernet-switching table                  
Ethernet-switching table: 9 entries, 6 learned, 0 persistent entries
  VLAN             MAC address       Type         Age Interfaces
  v250              *                 Flood          - All-members
  v150              *                 Flood          - All-members
  v150              00:00:05:00:00:00 Learn          0 ge-0/0/47.0
  v150              00:21:59:c7:09:41 Learn          0 ge-0/0/47.0
  v150              00:24:dc:d3:1a:10 Learn          0 ge-0/0/45.0
  v100              *                 Flood          - All-members
  v100              00:00:03:00:00:00 Learn          0 ge-0/0/45.0
  v100              00:24:dc:d3:1a:10 Learn          0 ge-0/0/45.0
  v100              a8:d0:e5:5a:59:08 Learn          0 ge-0/0/45.0

Now as an OP script:

{master:0}[edit]
user@SWITCH# run op mac-resolve                   
Vlan           Mac address Interfaces       Age Vendor 
v150  00:00:05:00:00:00 ge-0/0/47.0 0 XEROX CORPORATION
v150  00:21:59:c7:09:41 ge-0/0/47.0 0 Juniper Networks
v150  00:24:dc:d3:1a:10 ge-0/0/45.0 0 Juniper Networks
v100  00:00:03:00:00:00 ge-0/0/45.0 0 XEROX CORPORATION
v100  00:24:dc:d3:1a:10 ge-0/0/45.0 0 Juniper Networks
v100  a8:d0:e5:5a:59:08 ge-0/0/45.0 0 Juniper Networks


Now I can imagine if you really wanted to do some kind of accounting, you could create a Web page of equipment and users in your network. You could create scripts to populate this database. For example, DHCP users would have both their user logins and mac addresses. Then you could build onto this script by extracting the user login and show the user who is connected to the interface above.





The source code
-----------------

version 1.1;
ns curl extension = "http://xml.libslax.org/curl";

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> {
        var $mac-info =  <command> "show ethernet-switching table";
        var $mac-table = jcs:invoke($mac-info);
        <output> "Vlan\tMac address\t\tInterfaces\tAge\tVendor ";
        for-each($mac-table//mac-table-entry) {
          if (current()/mac-address != "*") {
        var $test = current()/mac-address;
        var $str = substring ($test,1,8);
          var $url = "http://api.macvendors.com/" _ $str;
        var $options := {
        <url> $url;
        <method> "get";
        }
        var $curl = curl:open();
        var $results = curl:perform($curl,$options);
        var $int = current()/mac-interfaces-list;
        var $int2 = translate ($int, "\t\n\r", "");
        <output> current()/mac-vlan _"\t" _ current()/mac-address _"\t" _ $int2 
_ "\t"_ current()/mac-age _ "\t"_ $results/raw-data;
        expr curl:close($curl);
            }
        }
    }

}

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);

      }

}

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 22, 2014

Test driving Open Contrail

So I went to the hands on Open Contrail MeetUp. It started off as a semi Q&A overview of the architecture and business use case.

There is a need from Service providers to create services for customers that could

a) be deployed in a timely matter (seconds rather than months

b) Lower Op Ex through automation

c) reduce Operational complexity with template configs

Contrail is a module that can be currently added to an Openstack or Cloudstack platform. I'll talk about the Openstack implementation as I know more about this Cloud platform. The Contrail Controller works entirely in the overlay. It does not know anything about the underlay except for the gateway so it expects the physical network to already be in place. This means it can interoperate with any existing switch vendor network. When you install Contrail as a Neutron plugin into Openstack, it will create a vRouter which is bound to the hypervisor. Currently KVM is the one it works with but I hear that it was tested on VMware as a vm but not directly onto ESXi.  The vRouter is important because you wouldn't use Open vSwitch (OVS). The main function of Contrail is creating the overlay network within Openstack.

Here's how this works. Let's look at this simple logical topology



First you would go to the Contrail Controller (Web GUI) and create the two networks.


Then you would go to the Openstack Horizon Web UI and spin up your VM instances. Under the networking tab you should be able to associate the network to the VM.



Next you would need to create a policy so that each network can talk to each other. Think of it as creating a firewall ACL.



Last you need to attach the policy to each network.

Contrail will automatically assign the VM an ip address and point the default route of the VM to the vRouter.


This will allow you to access the Back End Server.

Overall provisioning time would be roughly 2-3 minutes depending on how fast the VMs can spin up.

Now if you want to provide access to anything outside of the Data Center you'll need to go through a gateway router. AKA Data Center Interconnect (DCI)

To understand this more you will need a Gateway router that speaks MP-BGP can can support GRE or VXLAN. A GRE tunnel will be created from the Contrail vRouter (Virtual) to the physical Gateway Router. If you want to create multi-tenency, you will have to put each tunnel into a separate VRF on the Gateway Router. This provisioning is a manual process of the Gateway Router. Contrail does not manage the Gateway Router at all, however you may be able to automate this function using scripting.
The vRouter will exchange routes via MP-BGP and there is a setting in Contrail to create the Router-Target. The BGP  family types vRouter supports is inet-vpn (or vpnv4) and evpn.

Overall the provisioning is fairly simple. There are a few things I would like "improved" in the product, such as being able to attach a policy from the networking overview "tab" instead of having to drill down into each network and doing it there. There could be a more excel feel to this view as you should be able to make modifications from this view using pulldowns or directly adding the ip subnets.
Also the manual process of creating VRFs on the Gateway router is a bit tedious. I'm investigating whether Openstack has the ability run a script that can make a netconf rpc call to the gateway router.

An alternative is to use slax and curl on a Juniper MX router to extract the details from the Contrail controller.

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);
}

Saturday, October 19, 2013

Create your own command with op script. Show ldp statics from an mpls label.


My customer asked me whether JUNOS supports a function about ldp traffic statistics per mpls label. You can do show ldp statistics, but you have to know the prefix. I didn't find any command about the function and our firewall filter only supports label exp flag. Can we write some op script tho support it?
I created an op script that will do a reverse lookup of the prefix from the label. It combines the following commands:

show route x.x.x.x table inet.3
show ldp traffic-statistics

Basically it looks for the label that is in the inet.3 table and finds the associated route. It then looks for the ldp-traffic stats from the route.


See below on how it works:

user@router# show system                                         
host-name router;
scripts {
    op {
        file label-stats.slax;
    }
}

[edit]
user@router# run op label-stats label 300048                     
label 300048 prefix 202.0.0.0/24
202.0.0.0/24 Transit 114533658740 5726682937000 No.
202.0.0.0/24 Ingress 0 0 No.

[edit]
user@router# run show route 202.0.0.0/24 table inet.3            

inet.3: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

202.0.0.0/24       *[LDP/9] 22:28:18, metric 1
                    > to 10.2.3.3 via xe-3/0/0.0, Push 300048

[edit]
user@router# run show ldp traffic-statistics | find 202.0.0.0    
 202.0.0.0/24        Transit        114543762951      5727188147550    No   
                     Ingress                   0                  0    No   
 202.0.1.0/24        Transit           110333454         5516672700    No   
                     Ingress                   0                  0    No   
 202.0.2.0/24        Transit           110333454         5516672700    No   
                     Ingress                   0                  0    No   
 202.0.3.0/24        Transit           110333453         5516672650    No   
                     Ingress                   0                  0    No   

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";
var $arguments = <argument> {
    <name> "label";
    <description> "mpls label";
}
param $label;
param $indent = "  TEXT";
param $newline = "\n";

match / {
    <op-script-results> {
        var $result = jcs:invoke("get-route-information");
        var $test = ($result);
        <output method = "text"> {
            
            for-each ($result/route-table) {
                if (table-name == "inet.3") {
                    var $content = .;
                    
                    for-each ($content/rt/rt-entry/nh) {
                        var $check = mpls-label;
                        
                        if (contains($check, $label)) {
                            var $route = normalize-space(../../rt-destination);
                            
                            expr "label " _ $label _ " prefix " _ $route _ "\n";
                            var $stats = jcs:invoke("get-ldp-traffic-statistics-information");
                            
                            for-each ($stats/ldp-traffic-statistics) {
                                var $compare = normalize-space(./ldp-prefix);
                                
                                if ($compare == $route) {
                                    expr normalize-space(.);
                                    expr ".\n";
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Wednesday, October 16, 2013

An Event script to change static routing based upon interface flaps


An Event script to change static routing based upon interface flaps

user@router# run show interfaces ge-0/1/3 terse 
Interface               Admin Link Proto    Local                 Remote
ge-0/1/3                up    up  
ge-0/1/3.0              up    up   inet     192.10.1.1/24   

[edit]
user@router# show routing-options 
static {
    route 50.0.0.0/24 next-hop 192.10.1.2;
}

[edit]


DISABLED THE PHYSICAL INTERFACE

[edit]
user@router# run show interfaces ge-0/1/3 terse    
Interface               Admin Link Proto    Local                 Remote
ge-0/1/3                up    down
ge-0/1/3.0              up    down inet     192.10.1.1/24   

CHECK the router to see if the static route is deactivated.

[edit]
user@router# show routing-options                  
static {
    inactive: route 50.0.0.0/24 next-hop 192.10.1.2;
}

[edit]
user@router# run show log messages   
Jul 17 11:19:53 router clear-log[27080]: logfile cleared
Jul 17 11:20:00  router rpd[1336]: EVENT <UpDown> ge-0/1/3.0 index 69 <Broadcast Multicast> address #0 0.5.85.d4.40.22
Jul 17 11:20:00  router rpd[1336]: EVENT UpDown ge-0/1/3.0 index 69 192.10.1.1/24 -> 192.10.1.255 <Broadcast Multicast Localup>
Jul 17 11:20:00  router mib2d[1362]: SNMP_TRAP_LINK_DOWN: ifIndex 133, ifAdminStatus up(1), ifOperStatus down(2), ifName ge-0/1/3
Jul 17 11:20:00  router rpd[1336]: EVENT <UpDown> index 133 <Broadcast Multicast> address #0 0.5.85.d4.40.22
Jul 17 11:20:01  router file[27087]: UI_CFG_AUDIT_OTHER: User 'root' deactivate: [juniper-config routing-options static route 50.0.0.0/24]
Jul 17 11:20:03  router rpd: proceeding. -C
Jul 17 11:20:05  router rpd[1336]: RPD_TASK_REINIT: Reinitializing
Jul 17 11:20:05  router rpd[1336]: task_reconfigure reinitializing done
Jul 17 11:20:06  router cscript: removing static route
Jul 17 11:20:06  router cscript: Route-change[warning]: Disabling static route 50.0.0.0/24
Jul 17 11:20:06  router root: invoke-commands: Executed /tmp/evt_cmd_kzGMAH, output to /tmp/evt_op_K7nJxd in text format
Jul 17 11:20:06  router root: transfer-file: Transferred /tmp/evt_op_K7nJxd



REENABLED THE PHYSICAL INTERFACE

[edit]
user@router# run show interfaces ge-0/1/3 terse 
Interface               Admin Link Proto    Local                 Remote
ge-0/1/3                up    up  
ge-0/1/3.0              up    up   inet     192.10.1.1/24   

CHECK THE STATIC ROUTE
[edit]
user@router# show routing-options           
static {
    route 50.0.0.0/24 next-hop 192.10.1.2;
}

[edit]
user@router# run show log messages   

Jul 17 11:20:55  router rpd[1336]: EVENT <UpDown> ge-0/1/3.0 index 69 <Up Broadcast Multicast> address #0 0.5.85.d4.40.22
Jul 17 11:20:55  router rpd[1336]: EVENT UpDown ge-0/1/3.0 index 69 192.10.1.1/24 -> 192.10.1.255 <Up Broadcast Multicast>
Jul 17 11:20:55  router mib2d[1362]: SNMP_TRAP_LINK_UP: ifIndex 133, ifAdminStatus up(1), ifOperStatus up(1), ifName ge-0/1/3
Jul 17 11:20:55  router mib2d[1362]: SNMP_TRAP_LINK_UP: ifIndex 159, ifAdminStatus up(1), ifOperStatus up(1), ifName ge-0/1/3.0
Jul 17 11:20:55  router rpd[1336]: EVENT <UpDown> index 133 <Up Broadcast Multicast> address #0 0.5.85.d4.40.22
Jul 17 11:20:56  router file[27353]: UI_CFG_AUDIT_OTHER: User 'root' activate: [juniper-config routing-options static route 50.0.0.0/24]
Jul 17 11:20:58  router rpd: proceeding. -C
Jul 17 11:21:00  router rpd[1336]: RPD_TASK_REINIT: Reinitializing
Jul 17 11:21:00  router rpd[1336]: task_reconfigure reinitializing done
Jul 17 11:21:01  router cscript: Enabling static route 50.0.0.0/24
Jul 17 11:21:01  router cscript: Route-change[warning]: Enabling static route 50.0.0.0/24
Jul 17 11:21:01  router root: invoke-commands: Executed /tmp/evt_cmd_4j1XoH, output to /tmp/evt_op_NxKJIo in text format
Jul 17 11:21:01  router cscript: Enabling static route 50.0.0.0/24
Jul 17 11:21:01  router cscript: Route-change[warning]: Enabling static route 50.0.0.0/24
Jul 17 11:21:01  router root: transfer-file: Transferred /tmp/evt_op_NxKJIo
Jul 17 11:21:01  router root: invoke-commands: Executed /tmp/evt_cmd_QrBmxm, output to /tmp/evt_op_pP79Iy in text format
Jul 17 11:21:01  router root: transfer-file: Transferred /tmp/evt_op_pP79Iy

[edit]
user@router# show event-options 
policy track-interface-down {
    events snmp_trap_link_down;
    attributes-match {
        snmp_trap_link_down.interface-name matches ge-0/1/3;
    }
    then {
        event-script route-change.slax {
            arguments {
                action 1;
                prefix 50.0.0.0/24;
            }
            output-filename track-int;
            destination local;
            output-format text;
        }
    }
}
policy track-interface-up {
    events snmp_trap_link_up;
    attributes-match {
        snmp_trap_link_up.interface-name matches ge-0/1/3;
    }
    then {
        event-script route-change.slax {
            arguments {
                action 0;
                prefix 50.0.0.0/24;
            }
            output-filename track-int;
            destination local;
            output-format text;
        }
    }
}
destinations {
    local {
        archive-sites {
            /var/home/user/;
        }
    }
}

Source code: route-change.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> "action";
    <description> "0 to enable, 1 to disable";
    }
    <argument> {
        <name> "prefix";
        <description> "route prefix with mask, ie 10.0.0.0/24";
    }
}
param $action = 0;
param $prefix;

match / {
    /*
     * Open connection with mgd
     */
    var $con = jcs:open();

    if (not($con)) {
        call emit-error($message = "Not able to connect to local mgd");
    }

        if ($action = 1) {
            expr jcs:output("Disabling Route");
            var $check-int = jcs:invoke ("get-configuration");
            for-each ($check-int/routing-options/static/route) {        
                      if (name = $prefix) {
                      expr jcs:output(name);
                       /*
                        *   REMOVE route
                        */
                          var $disable = <configuration> {
                                           <routing-options> {
                                                <static> {  
                                           <route inactive="inactive"> {    
           
                                                          <name> $prefix;   
                                                            }
                                                    }
                                        }

                          }
                          call jcs:load-configuration($connection = $con, $configuration = $disable);
                          expr jcs:syslog("user.info","removing static route");
                          var $message = concat ("Disabling static route " , $prefix);
                          call emit-success($message);
                      }
            }
        }  
        if ($action = 0) {
            expr jcs:output("Enabling Route");
             /*
              *   ADD route
              */
            var $int = <configuration> {
                           <routing-options> {
                                      <static> {
                                            <route active="active"> {
                                               <name> $prefix;
                                      }
                                }
                       }
             }
         call jcs:load-configuration($connection = $con, $configuration = $int);
         expr jcs:syslog("user.info","Enabling static route " , $prefix);
         var $message = concat ("Enabling static route " , $prefix);
         /*
          * Emit messages
          */
          call emit-fail($message);

        }
     /*
      * Close the mgd connection
      */
      expr jcs:close($con);

}
template emit-fail ($message) {   
    expr jcs:syslog("user.info", "Route-change[warning]: ", $message);
}

template emit-success ($message) {
    expr jcs:syslog("user.info", "Route-change[warning]: ", $message);
}


Tuesday, October 15, 2013

How to test/simulate an event to trigger an event script



instead of waiting for an event to happen you can generate an event using the logger command from the cli.

First you need to get the attribute of the event if you want to pass an argument to the script. Use "help syslog <command>" 
jnpr@router> help syslog UI_CHILD_EXITED    
Name:          UI_CHILD_EXITED
Message:       Child exited: PID <pid>, status <return-value><core-dump-status>, command '<command>'
Help:          Child process of mgd exited

In help syslog the attribute will be displayed inside the <> bracket.
pid, return-value, core-dump-status, and command are the attributes



jnpr@router# show event-options
policy test {
    events ui_child_exited;
    then {
        event-script test.slax {
            arguments {
                mib "{$UI_CHILD_EXITED.pid}";
            }
            output-filename ARG;
            destination local;
        }
    }
}
destinations {
    local {
        archive-sites {
            "ftp://user:password@192.168.1.1";
        }
    }
}


go into shell as root and then issue the logger command

logger [-e event-id/tag] [-p priority] [-d daemon] [-a attr=value]
       [message]

root@router% logger -e UI_CHILD_EXITED -a "pid=111" test-syslog-message


jnpr@router# run show log messages
Jun 30 23:57:45 router clear-log[6242]: logfile cleared
Jun 30 23:58:01  router logger: UI_CHILD_EXITED: test-syslog-message
Jun 30 23:58:02  router root: invoke-commands: Executed /tmp/evt_cmd_k0dUOC, output to /tmp/evt_op_YRuPs6 in text format
Jun 30 23:58:02  router ftpd[6259]: connection from 192.168.1.1 (192.168.1.1)
Jun 30 23:58:02  router ftpd[6259]: FTP LOGIN FROM 192.168.1.1 as user
Jun 30 23:58:02  router root: transfer-file: Transferred /tmp/evt_op_YRuPs6


[edit]
jnpr@router# run file show router_ARG_20090701_065802


root@router> op test.slax mib "111"

111


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

root@router% more test.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> "mib";

}
param $mib;

match / {
    <op-script-results> {

        <output method = "text"> {

                    expr $mib;
            <xsl:document href = "/var/home/jnpr/text.txt"> {
                copy-of $mib;
            }
        }
    }


Sunday, October 13, 2013

Juniper Op script to convert Hex to Decimal


Created an op script that would take a string of hex pairs and convert them into decimal. Actually I took some xslt script I found on the internet and made the conversion to slax.

user@router> op hex 
07 d9 08 1c 04 32 13 00 2d 07 00
7
217
8
28
4
50
19
0
45
7
0

Could be useful in other scripts if you need to make a conversion.

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 / {
    <op-script-results> {
     var $string = 07 d9 08 1c 04 32 13 00 2d 07 00;
     var $hexval = translate($string,' ','');
     <output> $string;
     var $len = string-length($hexval);
     var $loopCounter := { call create-loop-counter( $counter = 11); }
     for-each( $loopCounter/counter ) {
       call hexpairs-to-dec($pair = position(), $hexval);
     }

    }
   
}
template create-loop-counter( $counter ) {
if( $counter > 0 ) {
<counter>;
call create-loop-counter( $counter = $counter -1 );
}
}

template hexpairs-to-dec ($pair = 1, $hexval) {
    var $hexpair = substring($hexval, $pair * 2 - 1, 2);
   
    if ($hexpair) {
        var $hex = 0123456789abcdef;

        <output> (string-length(substring-before($hex, substring($hexpair, 1, 1)))) * 16 + string-length(substring-before($hex, subs
tring($hexpair, 2, 1)));
    }
}