Blogs

How do I allow the user to issue select attributes on a range of interfaces on EX and MX?

By Erdem posted 08-14-2015 15:14

  
This applies to SLAX version 1.0 and higher.
 
Overview

To allow the user to issue select attributes on a range of interfaces on EX and MX.

Description

This script uses the "range" macro for configuring a range of interfaces (DPC and PIC for EX, DPC for MX). If the vlan specified to be placed on the interfaces does not exist in "vlans", the vlan will be created and the "vlan-id" will be added.

Source Code
GitHub Links

The source code below is also available from GitHub at the following locations:

Example Configuration
01 HOW TO USE:    
02  
03 This script will be called for each "apply-macro" found in the
04 configuration that starts with "range".  There is no limited to
05 the number of times it may be called in a configuration.        
06               
07 Additionally, if the vlan specificed to be placed on the interfaces
08 does not exist in "vlans", the vlan will be created and the "vlan-id"
09 will be added if the "vlan-id" parm is passed to the script.
10                        
11 Parms:   
12 "action delete" (will delete what ever is specified)
13         (the interface if no vlan or mode is specified)
14         (if mode and/or vlan is specified only they are
15         delete)
16 "mode trunk"    (sets the interface's port-mode to trunk) 
17         ("access" is the default and implied)         
18 "from xx"   (the interface to start the range at)
19 "to xx"     (the interface to stop the range at)
20 "vlan-id xx"    (the tag number for the vlan)      
21         (this is not needed for the interface.     
22         it is only used if the vlan does not exist      
23         in vlans)
24 "vlan xx"       (the vlan name to add to the port)     
25 "remove"        (remove the range macro upon successful
26         commit or commit check)               
27 "ztrace"        (turns on debugging)
28 "setv"          (puts the interface into the VLANS
29         hierarchy instead of putting the
30         vlan name on the interface)                
31                        
32 Example 1:
33        Add vlan "red" to interfaces ge-0/0/0 through ge-0/0/10
34            and if the vlan has not been created, create it and
35            set the vlan-id.
36                        
37        apply-macro range {
38           from ge-0/0/0
39           to ge-0/0/10
40           vlan-id 10
41           vlan red
42        }
43                        
44 Example 2:
45        Make ge-3/1/0 through ge-3/1/3 trunk ports and delete
46            the macro from the configuration.
47                     
48        apply-macro range2 {   
49           from ge-3/1/0
50           to ge-3/1/3
51           mode trunk           
52           remove
53        }
54  
55 Example 3:
56        Delete ge-1/0/0 through ge-1/0/5
57  
58        apply-macro range3 {
59           from ge-1/0/0
60           to ge-1/0/5
61           action delete
62        }
63  
64 Example 4:
65        Add vlan "red" to interfaces ge-4/0/5 through ge-4/0/10
66           and if the vlan has not been created, create it and
67           set the vlan-id.
68           Additionally, make them trunk ports.
69  
70        apply-macro range4 {
71           from ge-4/0/5
72           to ge-4/0/10
73           vlan-id 10
74           mode trunk
75           vlan red
76        }
77  
78 Example 5:
79        Add interfaces ge-4/0/5 through ge-4/0/10 to vlan red
80            and if the vlan has not been created, create it and
81            set the vlan-id.
82            Additionally, make the interfaces trunk ports and
83            delete the macro upon a successful commit or
84            commit check.
85  
86  
87        apply-macro range4 {
88           from ge-4/0/5
89           to ge-4/0/10
90           vlan-id 10
91           mode trunk
92           vlan red
93           setv
94           remove
95       }
SLAX Script Contents

0001 /* 

0002 * 

0003 *    NAME: range.slax 

0004 *    PURPOSE: To allow the user to issue select attributes on a range of 

0005 *             interfaces.  Interfaces must be on the same "dpc" and "pic" 

0006 *             on EX-series switches.  Interfaces must be on the same "dpc" 

0007 *             for MX-series switches. 

0008 * 

0009 *    CREATED: 09/05/08 

0010 *    BY: Jay Wilson (Southwest Regional JUNOS Specialist) 

0011 *    LAST MOD: 10/27/08 

0012 *    BY: Jay Wilson 

0013 *    VERSION: 3.02 

0014 * 

0015 *    MODIFICATION HISTORY: 

0016 *        V1.00 = Initial release 

0017 *        V1.01 = Changed the parm names for the macro to match the JUNOS 

0018 *                names (vname ==> vlan, vid ==> vlan-id, mode ==> port-mode) 

0019 *        V1.02 = Added a parm called "remove". 

0020 *                It has no options. 

0021 *                If it is specificed in the macro, that macro will be 

0022 *                removed from the configuration upon a successful commit. 

0023 *        V1.03 = Added a check to ensure the script is running on an EX device. 

0024 *        V1.04 = Removed warning messages when script is run. 

0025 *                Added a check for a ztrace option in the macro that 

0026 *                   if specified calls WRITE-MSG to print out a 

0027 *                   warning message showing what changes will happen 

0028 *                   to each interface. 

0029 *        V2.00 = Major rewrite!! 

0030 *                   Modularized the code via templates. 

0031 *                   Added support for the "setv" option, which allows the 

0032 *                      user to put the interface into the VLANS 

0033 *                      hierarchy instead of putting the vlan name on 

0034 *                      the interface in the INTERFACES hierarchy 

0035 *        V3.00 = Major rewrite!! 

0036 *                   Added support for MX-series at the request of the EABU. 

0037 *                      Several new templates were added to support the 

0038 *                      specific requirements of the MX. 

0039 *                      The device check was modified to allow the script 

0040 *                      to work on both the EX-series and MX-Series. 

0041 *                      The range macro is still limited to a single PIC 

0042 *                      for EX member, but for the MX it can cross PICs on 

0043 *                      the same DPC. 

0044 *                      The same marcro syntax is used for both MX and EX 

0045 *                      and the script translates the options for each 

0046 *                      series. 

0047 *        V3.01 = MX-series changes 

0048 *                   Removed unused macro options 

0049 *        V3.02 = EX & MX changes 

0050 *                   Added "description" option, which allows the 

0051 *                      user to put a description on all interfaces 

0052 *                      specified. 

0053 * 

0054 * 

0055 *    HOW TO USE: 

0056 *        This script will be called for each "apply-macro" found in the 

0057 *        configuration that starts with "range".  There is no limited to 

0058 *        the number of times it may be called in a configuration. 

0059 * 

0060 *        Additionally, if the vlan specificed to be placed on the interfaces 

0061 *        does not exist in "vlans", the vlan will be created and the "vlan-id" 

0062 *        will be added if the "vlan-id" parm is passed to the script. 

0063 * 

0064 *        Parms: 

0065 *           "action delete"  (will delete what ever is specified) 

0066 *                            (the interface if no vlan or mode is specified) 

0067 *                            (if mode and/or vlan is specified only they are 

0068 *                             delete) 

0069 *           "mode trunk"     (sets the interface's port-mode to trunk) 

0070 *                            ("access" is the default and implied) 

0071 *           "from xx"        (the interface to start the range at) 

0072 *           "to xx"          (the interface to stop the range at) 

0073 *           "vlan-id xx"         (the tag number for the vlan) 

0074 *                            (this is not needed for the interface. 

0075 *                             it is only used if the vlan does not exist 

0076 *                             in vlans) 

0077 *           "vlan xx"       (the vlan name to add to the port) 

0078 *           "remove"        (remove the range macro upon successful 

0079 *                            commit or commit check) 

0080 *           "ztrace"        (turns on debugging) 

0081 *           "setv"          (puts the interface into the VLANS 

0082 *                            hierarchy instead of putting the 

0083 *                            vlan name on the interface) 

0084 * 

0085 *    Example 1: 

0086 *       Add vlan "red" to interfaces ge-0/0/0 through ge-0/0/10 

0087 *           and if the vlan has not been created, create it and 

0088 *           set the vlan-id. 

0089 * 

0090 *       apply-macro range { 

0091 *          from ge-0/0/0 

0092 *          to ge-0/0/10 

0093 *          vlan-id 10 

0094 *          vlan red 

0095 *       } 

0096 * 

0097 *    Example 2: 

0098 *       Make ge-3/1/0 through ge-3/1/3 trunk ports and delete 

0099 *          the macro from the configuration. 

0100 * 

0101 *       apply-macro range2 { 

0102 *          from ge-3/1/0 

0103 *          to ge-3/1/3 

0104 *          mode trunk 

0105 *          remove 

0106 *       } 

0107 * 

0108 *    Example 3: 

0109 *       Delete ge-1/0/0 through ge-1/0/5 

0110 * 

0111 *       apply-macro range3 { 

0112 *          from ge-1/0/0 

0113 *          to ge-1/0/5 

0114 *          action delete 

0115 *       } 

0116 * 

0117 *    Example 4: 

0118 *       Add vlan "red" to interfaces ge-4/0/5 through ge-4/0/10 

0119 *           and if the vlan has not been created, create it and 

0120 *           set the vlan-id. 

0121 *           Additionally, make them trunk ports. 

0122 * 

0123 *       apply-macro range4 { 

0124 *          from ge-4/0/5 

0125 *          to ge-4/0/10 

0126 *          vlan-id 10 

0127 *          mode trunk 

0128 *          vlan red 

0129 *       } 

0130 * 

0131 *    Example 5: 

0132 *       Add interfaces ge-4/0/5 through ge-4/0/10 to vlan red 

0133 *           and if the vlan has not been created, create it and 

0134 *           set the vlan-id. 

0135 *           Additionally, make the interfaces trunk ports and 

0136 *           delete the macro upon a successful commit or 

0137 *           commit check. 

0138 *           

0139 * 

0140 *       apply-macro range4 { 

0141 *          from ge-4/0/5 

0142 *          to ge-4/0/10 

0143 *          vlan-id 10 

0144 *          mode trunk 

0145 *          vlan red 

0146 *          setv 

0147 *          remove 

0148 *       } 

0149 * 

0150 */ 

0151 version 1.0; 

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

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

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

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

0156 match configuration { 

0157 /* 

0158 * 

0159 *  get the device information before entering the macro processing loop 

0160 * 

0161 *  Only SNMP returns a consistantly formated result for all Juniper 

0162 *  platforms. 

0163 * 

0164 */ 

0165    var $rpc-cmd = { 

0166        <get-snmp-object> { 

0167           <snmp-object-name>"1.3.6.1.2.1.1.2.0"; 

0168        } 

0169    } 

0170    var $sysobjid = jcs:invoke($rpc-cmd); 

0171    var $sub-sysobjid = substring-after($sysobjid,"jnxProduct"); 

0172    var $model = substring-before($sub-sysobjid,"\n"); 

0173   

0174 /* 

0175 * 

0176 *  Make sure the macro and script are used on a supported device type 

0177 *  and if they are, select the correct templates to use 

0178 * 

0179 */ 

0180    if (contains($model,"EX") || contains($model,"ex")) { 

0181        call ex-main; 

0182    } 

0183    else if (contains($model,"MX") || contains($model,"mx")) { 

0184        call mx-main; 

0185    } 

0186    else { 

0187        <xnm:error> { 

0188          <message> "RANGE ERROR: Macro is only supported on EX-series and MX-Series"; 

0189        } 

0190    } 

0191 } 

0192   

0193 /******************************************************************/ 

0194 /*                                                                */ 

0195 /*                       EX Specific Templates                    */ 

0196 /*                                                                */ 

0197 /******************************************************************/ 

0198   

0199 template ex-main { 

0200   

0201 /* Save the candidate node set point for vlans */ 

0202   

0203 var $vnode = ./vlans; 

0204   

0205 /* 

0206 *  Process the apply-macros 

0207 *        Only look at macros that start with "range" 

0208 * 

0209 */ 

0210    for-each (apply-macro[starts-with(name,"range")]) { 

0211       var $vlan = data[name = 'vlan']/value; 

0212       var $vlan-id = data[name = 'vlan-id']/value; 

0213       var $from = data[name = 'from']/value; 

0214       var $to   = data[name = 'to']/value; 

0215       var $action = data[name = 'action']/value; 

0216       var $port-mode = data[name = 'port-mode']/value; 

0217       var $fromtype = substring-before($from,'-'); 

0218       var $totype = substring-before($to,'-'); 

0219       var $description = data[name = 'description']/value; 

0220       /* check to see if macro should be delete on successful commit */ 

0221       var $bitbucket = { if (data[name = 'remove']) { 

0222                             expr name; 

0223                          } 

0224                          else { 

0225                             expr ""; 

0226                          } 

0227                        } 

0228       /* check to see if macro tracing was turned on                */ 

0229       var $trace = { if (data[name = 'ztrace']) { 

0230                             expr "ztrace"; 

0231                          } 

0232                          else { 

0233                             expr ""; 

0234                          } 

0235                        } 

0236       /* check to see if set location was turned on                */ 

0237       var $set-loc = { if (data[name = 'setv']) { 

0238                             expr "setv"; 

0239                          } 

0240                          else { 

0241                             expr ""; 

0242                          } 

0243                        } 

0244        if (not($fromtype =='') and not($totype =='') and $fromtype == $totype and ($fromtype == "ge" ||$fromtype == "xe") and ($totype == "ge" || $totype == "xe")) { 

0245   

0246           /* Split up the Interfaces into DPC, PIC, PORT */ 

0247   

0248           var $fromtriple = substring-after($from,'-'); 

0249           var $fromoct1 = substring-before($fromtriple,'/'); 

0250           var $fromleft = substring-after($fromtriple,'/'); 

0251           var $fromoct2 = substring-before($fromleft,'/'); 

0252           var $fromoct3 = substring-after($fromleft,'/'); 

0253           var $totriple = substring-after($to,'-'); 

0254           var $tooct1 = substring-before($totriple,'/'); 

0255           var $toleft = substring-after($totriple,'/'); 

0256           var $tooct2 = substring-before($toleft,'/'); 

0257           var $tooct3 = substring-after($toleft,'/'); 

0258           /* If the vlan doesn't exist, create it and add the vlan-id */ 

0259           /*    if it was supplied.                                   */ 

0260           /* The vlan is created to avoid warning messages on the commit. */ 

0261           /* Put a vlan on an Interface without the vlan existing in  */ 

0262           /* vlans, causes the warning.                               */ 

0263           if ($vlan and not($action == "delete")) { 

0264              <change> { 

0265                 <vlans> { 

0266                    <vlan> { 

0267                      <name> $vlan; 

0268                      if ($vlan-id) { 

0269                      <vlan-id> $vlan-id; 

0270                      } 

0271                    } 

0272                 } 

0273              } 

0274           } 

0275           /* Validate the information supplied in the macro          */ 

0276           /*                                                         */ 

0277           if (not($fromoct1) || not($fromoct2) || not($fromoct3) || not($tooct1) || not($tooct2) || not($tooct3)) { 

0278              <xnm:error> { 

0279                 <message> "RANGE ERROR: Invalid Interface Format"; 

0280              } 

0281           } 

0282           else if (not($fromoct1 == $tooct1)) { 

0283              <xnm:error> { 

0284                 <message> "RANGE ERROR: From Member != To Member"; 

0285              } 

0286           } 

0287           else if (not($fromoct2 == $tooct2)) { 

0288              <xnm:error> { 

0289                 <message> "RANGE ERROR: From and To PIC must match"; 

0290              } 

0291           } 

0292           else if ($fromoct1 == $tooct1 and $fromoct2 > $tooct2) { 

0293              /* Should not be called until multi-member is supported */ 

0294              <xnm:error> { 

0295                 <message> "RANGE ERROR: From PIC >= To PIC on same Member"; 

0296              } 

0297           } 

0298           else if ($fromtype == "xe" and $fromoct2 != 1) { /* remove this if when all 10G switch is available */ 

0299              <xnm:error> { 

0300                 <message> "RANGE ERROR: xe- interfaces only supported on PIC 1"; 

0301              } 

0302           } 

0303           else if ($fromoct1 == $tooct1 and $fromoct2 == $tooct2 and $fromoct3 >= $tooct3) { 

0304              <xnm:error> { 

0305                 <message> "RANGE ERROR: From Port >= To Port on same Member/PIC"; 

0306              } 

0307           } 

0308           else if ($fromoct1 > 9 || $tooct1 > 9) { 

0309              <xnm:error> { 

0310                 <message> "RANGE ERROR: Member must be 0 to 9"; 

0311              } 

0312           } 

0313           else if ($fromoct2 > 1 || $tooct2 > 1) { 

0314              <xnm:error> { 

0315                 <message> "RANGE ERROR: PIC must be 0 or 1"; 

0316              } 

0317           } 

0318           else if ($fromtype == "xe" and $fromoct2 != 1) { 

0319              <xnm:error> { 

0320                 <message> "RANGE ERROR: PIC must be 1 for xe- Interfaces"; 

0321              } 

0322           } 

0323           else if ($fromoct2 == 1 and (($fromoct3 > 3 || $tooct3 > 3) and $fromtype == "ge")) { 

0324              <xnm:error> { 

0325                 <message> "RANGE ERROR: GE PIC Interfaces Must be < 4"; 

0326              } 

0327           } 

0328           else if ($fromoct2 == 1 and (($fromoct3 > 1 || $tooct3 > 1) and $fromtype == "xe")) { 

0329              <xnm:error> { 

0330                 <message> "RANGE ERROR: XE PIC Interfaces Must be < 2"; 

0331              } 

0332           } 

0333           else if (not($vlan) and not($port-mode) and not($action)) { 

0334              <xnm:error> { 

0335                 <message> "RANGE ERROR: Macro MUST include a vlan and/or MODE"; 

0336              } 

0337           } 

0338           else if ($action and not($action == "delete")) { 

0339              <xnm:error> { 

0340                 <message> "RANGE ERROR: Valid ACTION is delete. set is implied."; 

0341              } 

0342           } 

0343           else if ($port-mode and not($port-mode == "trunk")) { 

0344              <xnm:error> { 

0345                 <message> "RANGE ERROR: Valid MODE is trunk.  access is implied."; 

0346              }         

0347           } 

0348           else { 

0349           /*                                                          */ 

0350           /*  Process each Interface of the range.                    */ 

0351           /*  This is accomplished by calling a recursive template.   */ 

0352           /*                                                          */ 

0353           call ex-loop($maxcount = $tooct3, $initial-value = $fromoct3, $fromtype, $fromoct1, $fromoct2,$port-mode, $vlan, $vlan-id, $action, $trace, $set-loc, $description); 

0354           /* See if the user wants the macro removed from the config. */ 

0355           call macro-attack($bitbucket); 

0356      } 

0357      } 

0358      else { 

0359        <xnm:error> { 

0360           <message> { 

0361              expr "RANGE ERROR: Invalid FROM "; 

0362              expr $from; 

0363              expr " or TO "; 

0364              expr $to; 

0365              expr " interface \n"; 

0366           } 

0367         } 

0368      } 

0369 } 

0370 } 

0371   

0372 /* 

0373 *   NAME: EX-LOOP 

0374 *   PURPOSE: To process each Interface in the range specified. 

0375 *   CALLED: Called if no errors where found with the input to the macro. 

0376 *           Also called recursively within itself.  This is how looping works. 

0377 * 

0378 *   PARMS PASSED: 

0379 *        $maxcount = It's the ending Interface number 

0380 *                    Used for controlling the loop 

0381 *        $initial-value = It's the starting Interface number 

0382 *                         Used for controlling the loop 

0383 *        $fromtype = Type of interface (GE or XE) 

0384 *                    Used to reconstruct the full Interface name 

0385 *        $fromoct1 = The DPC (Member) number 

0386 *                    Used to reconstruct the full Interface name 

0387 *        $fromoct2 = The PIC number 

0388 *                    Used to reconstruct the full Interface name 

0389 *        $port-mode = If set to "trunk", then the "port-mode trunk" option 

0390 *                     is added to the Interface 

0391 *        $vlan = The vlan name to add to the Interface 

0392 *        $vlan-id = The vlan-id for the vlan. 

0393 *                   Currently not used 

0394 *        $action = If set to "delete", then kill-it is called 

0395 *        $trace = If "ztrace" is specified in the macro, then 

0396 *                 print out debugging information 

0397 *        $set-loc = Instead of adding the vlan to the interface, 

0398 *                   add the interface to the vlan. 

0399 *        $description = The "description" to set on each interface 

0400 * 

0401 */ 

0402 template ex-loop ($maxcount, $initial-value, $fromtype, $fromoct1, $fromoct2, $port-mode, $vlan, $vlan-id, $action, $trace, $set-loc, $description) { 

0403       

0404     if ($initial-value <= $maxcount) { 

0405         var $ifl = $fromtype _ "-" _ $fromoct1 _ "/" _ $fromoct2 _ "/" _ $initial-value; 

0406         /*                                                                 */ 

0407         /* If debug was requested from the macro, then print out a message */ 

0408         /* for each interface being worked on.                             */ 

0409         /*                                                                 */ 

0410         if (contains($trace,"ztrace")) { 

0411            call write-msg($ifl, $port-mode, $vlan, $vlan-id, $action, $type = "ex", $set-loc); 

0412         } 

0413         if ($action == "delete" and not($set-loc == "setv")) { 

0414            call kill-it-interfaces($ifl, $port-mode, $vlan); 

0415         } 

0416         else if ($action == "delete" and $set-loc == "setv") { 

0417            call kill-it-vlans($ifl, $port-mode, $vlan); 

0418         } 

0419         else if ($set-loc == "setv") { 

0420            call attach-to-vlans($ifl, $port-mode, $vlan, $description); 

0421          } 

0422         else { 

0423            call attach-to-interfaces-ex($ifl, $port-mode, $vlan, $description); 

0424         } 

0425         call ex-loop($maxcount, $initial-value = $initial-value + 1, $fromtype, $fromoct1, $fromoct2,$port-mode, $vlan, $vlan-id, $action, $trace, $set-loc, $description); 

0426     } 

0427 } 

0428   

0429 /* 

0430 *   NAME: KILL-IT-INTERFACES 

0431 *   PURPOSE: To remove an element from the configuration. 

0432 *   CALLED: Only called if "action delete" is specified in the range macro 

0433 *           and if "setv" is NOT specified in the range macro 

0434 * 

0435 *   PARMS PASSED: 

0436 *        $ifl = The interface name to act on 

0437 *        $port-mode = if "mode = trunk", then delete the <port-mode> element 

0438 *        $vlan = if "vlan" is non-blank, then delete the <members> element 

0439 * 

0440 *        NOTE: If both $port-mode and $vlan are true, then both will be deleted. 

0441 *              If only $ifl is specified, then the complete interface is deleted 

0442 * 

0443 */ 

0444 template kill-it-interfaces($ifl, $port-mode, $vlan) { 

0445    if (not($vlan) and not($port-mode)) { 

0446      <change> { 

0447         <interfaces> { 

0448            <interface delete="delete"> { 

0449                <name> $ifl; 

0450            } 

0451         } 

0452      } 

0453    } 

0454    else { 

0455       <change> { 

0456           <interfaces> { 

0457               <interface> { 

0458                  <name> $ifl; 

0459                     <unit> { 

0460                        <name> "0"; 

0461                         <family> { 

0462                             <ethernet-switching> { 

0463                              if ($port-mode) { 

0464                                 <port-mode delete="delete">; 

0465                              } 

0466                              if ($vlan) { 

0467                                 <vlan> { 

0468                                    <members delete="delete"> $vlan; 

0469                                 } 

0470                              } 

0471                              } 

0472                           } 

0473                   } 

0474               } 

0475             } 

0476    } 

0477 } 

0478 } 

0479 /* 

0480 *   NAME: KILL-IT-VLANS 

0481 *   PURPOSE: To remove an element from the configuration. 

0482 *   CALLED: Only called if "action delete" is specified in the range macro 

0483 *           and if "setv" is specified in the range macro 

0484 * 

0485 *   PARMS PASSED: 

0486 *        $ifl = The interface name to act on 

0487 *        $port-mode = if "mode = trunk", then delete the <port-mode> element 

0488 *        $vlan = if "vlan" is non-blank, then delete the Interface from the 

0489 *                VLANS hierarchy 

0490 * 

0491 *        NOTE: If both $port-mode and $vlan are true, then both will be deleted. 

0492 *              If only $ifl is specified, then the complete interface is deleted 

0493 * 

0494 */ 

0495 template kill-it-vlans($ifl, $port-mode, $vlan) { 

0496    if (not($vlan) and not($port-mode)) { 

0497      <change> { 

0498         <interfaces> { 

0499            <interface delete="delete"> { 

0500                <name> $ifl; 

0501            } 

0502         } 

0503      } 

0504    } 

0505    else { 

0506       <change> { 

0507           <interfaces> { 

0508               <interface> { 

0509                  <name> $ifl; 

0510                     <unit> { 

0511                        <name> "0"; 

0512                         <family> { 

0513                             <ethernet-switching> { 

0514                              if ($port-mode) { 

0515                                 <port-mode delete="delete">; 

0516                              } 

0517                              } 

0518                           } 

0519                   } 

0520               } 

0521             } 

0522       } 

0523       <change> { 

0524          <vlans> { 

0525             <vlan> { 

0526                <name> $vlan; 

0527                   <interface delete="delete"> { 

0528                      <name> $ifl _ ".0"; 

0529                   } 

0530             } 

0531          } 

0532       } 

0533                

0534    } 

0535 } 

0536 /* 

0537 *   NAME: MACRO-ATTACK 

0538 *   PURPOSE: To remove the range macro from the configuration. 

0539 *   CALLED: Only called if "remove" is specified in the range macro 

0540 * 

0541 *   PARMS PASSED: 

0542 *        $bitbucket = The name of the apply-macro to delete 

0543   

0544 */ 

0545 template macro-attack($bitbucket) { 

0546    if (not($bitbucket == "")) { 

0547      <change> { 

0548         <apply-macro delete="delete"> { 

0549                <name> $bitbucket; 

0550         } 

0551      } 

0552    } 

0553 } 

0554   

0555   

0556 /* 

0557 *   NAME: WRITE-MSG 

0558 *   PURPOSE: Prints a Warning Message showing the CLI command that will be 

0559 *            applied to the configuration. 

0560 *   CALLED: Only called if "ztrace" is specified in the range macro 

0561 * 

0562 *   PARMS PASSED: 

0563 *        $ifl = The interface name being acted on 

0564 *        $port-mode = "port-mode" specified in the macro 

0565 *        $vlan = "vlan" specified in the macro 

0566 *        $action = "action" specified in the macro 

0567 *        $set-loc = "setv" specified in the macro 

0568 * 

0569 * 

0570 */ 

0571 template write-msg($ifl, $port-mode, $vlan, $vlan-id, $action, $type, $set-loc) { 

0572    <xnm:warning> { 

0573       <message> { 

0574          expr "RANGE TRACE: "; 

0575          if ($action == "delete") { 

0576             expr "delete "; 

0577          } 

0578          else { 

0579             expr "set "; 

0580          } 

0581          expr $ifl; 

0582          if ($port-mode == "trunk" || $vlan and $type == "ex") { 

0583             expr " unit 0 family ethernet-switching"; 

0584             if ($port-mode == "trunk") { 

0585               expr " port-mode trunk"; 

0586             } 

0587             if ($vlan) { 

0588               expr " vlan members "; 

0589               expr $vlan; 

0590               expr " location "; 

0591               expr $set-loc; 

0592             } 

0593          } 

0594          if ($port-mode == "trunk" || $vlan-id and $type == "mx") { 

0595             expr " unit 0 family bridge"; 

0596             if ($port-mode == "trunk") { 

0597               expr " interface-mode trunk"; 

0598               expr " vlan-id-list "; 

0599               expr $vlan-id; 

0600             } 

0601             else { 

0602               expr " interface-mode access"; 

0603               expr " vlan-id "; 

0604               expr $vlan-id; 

0605             } 

0606          } 

0607       } 

0608    }   

0609 } 

0610 /* 

0611 *   NAME: ATTACH-INTERFACES-EX 

0612 *   PURPOSE: Build the XML statement needed to add the information to 

0613 *            the Interfaces heirarchy 

0614 *   CALLED: Only called if "setv" is NOT specified in the range macro 

0615 *           for EX-series devices 

0616 * 

0617 *   PARMS PASSED: 

0618 *        $ifl = The interface name being acted on 

0619 *        $port-mode = "port-mode" specified in the macro 

0620 *        $vlan = "vlan" specified in the macro 

0621 *        $description = "description" specified in the macro 

0622 * 

0623 * 

0624 */ 

0625 template attach-to-interfaces-ex($ifl, $port-mode, $vlan, $description) { 

0626            <change> { 

0627               <interfaces> { 

0628                  <interface> { 

0629                     <name> $ifl; 

0630                     if ($description) { 

0631                        <description> $description; 

0632                     } 

0633                        <unit> { 

0634                           <name> "0"; 

0635                              <family> { 

0636                                 <ethernet-switching> { 

0637                                    if ($port-mode == "trunk") { 

0638                                       <port-mode> "trunk"; 

0639                                    } 

0640                                    <vlan> { 

0641                                       <members> $vlan; 

0642                                    } 

0643                                 } 

0644                              } 

0645                           } 

0646                   } 

0647               } 

0648             } 

0649 } 

0650   

0651 /* 

0652 *   NAME: ATTACH-VLANS 

0653 *   PURPOSE: Build the XML statement needed to add the information to 

0654 *            the VLANS heirarchy 

0655 *   CALLED: Only called if "setv" is specified in the range macro 

0656 * 

0657 *   PARMS PASSED: 

0658 *        $ifl = The interface name being acted on 

0659 *        $port-mode = "port-mode" specified in the macro 

0660 *        $vlan = "vlan" specified in the macro 

0661 *        $description = "description" specified in the macro 

0662 * 

0663 * 

0664 */ 

0665 template attach-to-vlans($ifl, $port-mode, $vlan, $description) { 

0666            <change> { 

0667               <vlans> { 

0668                  <vlan> { 

0669                     <name> $vlan; 

0670                     <interface> { 

0671                        <name> $ifl; 

0672                     } 

0673                  } 

0674               } 

0675            } 

0676            <change> { 

0677               <interfaces> { 

0678                  <interface> { 

0679                     <name> $ifl; 

0680                     if ($description) { 

0681                        <description> $description; 

0682                     } 

0683                        <unit> { 

0684                           <name> "0"; 

0685                              <family> { 

0686                                 <ethernet-switching> { 

0687                                    if ($port-mode == "trunk") { 

0688                                       <port-mode> "trunk"; 

0689                                   } 

0690                                 } 

0691                              } 

0692                         } 

0693                     } 

0694                } 

0695            } 

0696 } 

0697   

0698 /******************************************************************/ 

0699 /*                                                                */ 

0700 /*                       MX Specific Templates                    */ 

0701 /*                                                                */ 

0702 /******************************************************************/ 

0703 template mx-main { 

0704   

0705 /* 

0706 *  Process the apply-macros 

0707 *        Only look at macros that start with "range" 

0708 * 

0709 */ 

0710    for-each (apply-macro[starts-with(name,"range")]) { 

0711       var $vlan = data[name = 'vlan']/value; 

0712       var $vlan-id = data[name = 'vlan-id']/value; 

0713       var $from = data[name = 'from']/value; 

0714       var $to   = data[name = 'to']/value; 

0715       var $action = data[name = 'action']/value; 

0716       var $port-mode = data[name = 'port-mode']/value; 

0717       var $fromtype = substring-before($from,'-'); 

0718       var $totype = substring-before($to,'-'); 

0719       var $description = data[name = 'description']/value; 

0720       /* check to see if macro should be delete on successful commit */ 

0721       var $bitbucket = { if (data[name = 'remove']) { 

0722                             expr name; 

0723                          } 

0724                          else { 

0725                             expr ""; 

0726                          } 

0727                        } 

0728       /* check to see if macro tracing was turned on                */ 

0729       var $trace = { if (data[name = 'ztrace']) { 

0730                             expr "ztrace"; 

0731                          } 

0732                          else { 

0733                             expr ""; 

0734                          } 

0735                        } 

0736       /* check to see if set location was turned on                */ 

0737      if (data[name = 'setv']) { 

0738           <xnm:warning> { 

0739              <message> "RANGE MACRO: option SETV is not supported on the MX-series."; 

0740           } 

0741      } 

0742        if (not($fromtype =='') and not($totype =='') and $fromtype == $totype and ($fromtype == "ge" ||$fromtype == "xe") and ($totype == "ge" || $totype == "xe")) { 

0743   

0744           /* Split up the Interfaces into DPC, PIC, PORT */ 

0745   

0746           var $fromtriple = substring-after($from,'-'); 

0747           var $fromoct1 = substring-before($fromtriple,'/'); 

0748           var $fromleft = substring-after($fromtriple,'/'); 

0749           var $fromoct2 = substring-before($fromleft,'/'); 

0750           var $fromoct3 = substring-after($fromleft,'/'); 

0751           var $totriple = substring-after($to,'-'); 

0752           var $tooct1 = substring-before($totriple,'/'); 

0753           var $toleft = substring-after($totriple,'/'); 

0754           var $tooct2 = substring-before($toleft,'/'); 

0755           var $tooct3 = substring-after($toleft,'/'); 

0756   

0757           /* Validate the information supplied in the macro          */ 

0758           /*                                                         */ 

0759           if (not($fromoct1) || not($fromoct2) || not($fromoct3) || not($tooct1) || not($tooct2) || not($tooct3)) { 

0760              <xnm:error> { 

0761                 <message> "RANGE ERROR: Invalid Interface Format"; 

0762              } 

0763           } 

0764           else if (not($fromoct1 == $tooct1)) { 

0765              <xnm:error> { 

0766                 <message> "RANGE ERROR: From DPC != To DPC"; 

0767              } 

0768           } 

0769           else if ($fromoct1 == $tooct1 and $fromoct2 > $tooct2) { 

0770              <xnm:error> { 

0771                 <message> "RANGE ERROR: From PIC >= To PIC on same DOC"; 

0772              } 

0773           } 

0774           else if ($fromoct1 == $tooct1 and $fromoct2 == $tooct2 and $fromoct3 >= $tooct3) { 

0775              <xnm:error> { 

0776                 <message> "RANGE ERROR: From Port >= To Port on same DPC/PIC"; 

0777              } 

0778           } 

0779           else if ($fromoct1 > 7 || $tooct1 > 7) { 

0780              <xnm:error> { 

0781                 <message> "RANGE ERROR: DPC must be 0 to 7"; 

0782              } 

0783           } 

0784           else if (not($vlan-id) and not($port-mode) and not($action)) { 

0785              <xnm:error> { 

0786                 <message> "RANGE ERROR: Macro MUST include a vlan-id and/or MODE"; 

0787              } 

0788           } 

0789           else if ($action and not($action == "delete")) { 

0790              <xnm:error> { 

0791                 <message> "RANGE ERROR: Valid ACTION is delete. set is implied."; 

0792              } 

0793           } 

0794           else if ($port-mode and not($port-mode == "trunk")) { 

0795              <xnm:error> { 

0796                 <message> "RANGE ERROR: Valid MODE is trunk.  access is implied."; 

0797              }         

0798           } 

0799           else { 

0800              /* If the vlan doesn't exist, create it and add the vlan-id */ 

0801              /* The vlan is created to avoid warning messages on the commit. */ 

0802              /* Putting a vlan on an Interface without the vlan existing in  */ 

0803              /* vlans, causes the warning.                               */ 

0804              if ($vlan and not($action == "delete")) { 

0805                 <change> { 

0806                    <bridge-domains> { 

0807                       <domain> { 

0808                         <name> $vlan; 

0809                         <vlan-id> $vlan-id; 

0810                       } 

0811                    } 

0812                 } 

0813              } 

0814           /*                                                          */ 

0815           /*  Process each Interface of the range.                    */ 

0816           /*  This is accomplished by calling a recursive template.   */ 

0817           /*                                                          */ 

0818           call mx-loop-outside($maxcount = $tooct3, $initial-value = $fromoct3, $fromtype, $fromoct1,$str-pic = $fromoct2, $end-pic = $tooct2, $tooct3, $port-mode, $vlan, $vlan-id, $action, $trace,$description); 

0819           /* See if the user wants the macro removed from the config. */ 

0820           call macro-attack($bitbucket); 

0821      } 

0822      } 

0823      else { 

0824        <xnm:error> { 

0825           <message> { 

0826              expr "RANGE ERROR: Invalid FROM "; 

0827              expr $from; 

0828              expr " or TO "; 

0829              expr $to; 

0830              expr " interface \n"; 

0831           } 

0832         } 

0833      } 

0834 } 

0835 } 

0836 /* 

0837 *   NAME: MX-LOOP-OUTSIDE 

0838 *   PURPOSE: To process each Interface in the range specified. 

0839 *   CALLED: Called if no errors where found with the input to the macro. 

0840 *           Also called recursively within itself.  This is how looping works. 

0841 * 

0842 *   PARMS PASSED: 

0843 *        $maxcount = It's the ending Interface number 

0844 *                    Used for controlling the loop 

0845 *        $initial-value = It's the starting Interface number 

0846 *                         Used for controlling the loop 

0847 *        $fromtype = Type of interface (GE or XE) 

0848 *                    Used to reconstruct the full Interface name 

0849 *        $fromoct1 = The DPC (Member) number 

0850 *                    Used to reconstruct the full Interface name 

0851 *        $str-pic  = The PIC number to start on 

0852 *                    Used to reconstruct the full Interface name 

0853 *        $end-pic  = The PIC number to end on 

0854 *                    Used to reconstruct the full Interface name 

0855 *        $tooct3   = The Interface number to end on 

0856 *                    Used to reconstruct the full Interface name 

0857 *        $port-mode = If set to "trunk", then the "port-mode trunk" option 

0858 *                     is added to the Interface 

0859 *        $vlan = The vlan name to add to the Interface 

0860 *        $vlan-id = The vlan-id for the vlan. 

0861 *                   Currently not used 

0862 *        $action = If set to "delete", then kill-it is called 

0863 *        $trace = If "ztrace" is specified in the macro, then 

0864 *                 print out debugging information 

0865 *        $description = The "description" to add to each Interface. 

0866 * 

0867 */ 

0868 template mx-loop-outside ($maxcount, $initial-value, $fromtype, $fromoct1, $str-pic, $end-pic, $tooct3,$port-mode, $vlan, $vlan-id, $action, $trace, $description) { 

0869 /*                                                        */ 

0870 /*   To cross PICs, nested loops must be used and both    */ 

0871 /*   loops must be recursive.                             */ 

0872 /*                                                        */ 

0873    if ($str-pic = $end-pic) { 

0874       call mx-loop-inside ($maxcount = $tooct3, $initial-value, $fromtype, $fromoct1, $str-pic, $end-pic,$tooct3, $port-mode, $vlan, $vlan-id, $action, $trace, $description); 

0875    } 

0876    else if ($str-pic < $end-pic and $fromtype == "ge") { 

0877       call mx-loop-inside ($maxcount = 9, $initial-value, $fromtype, $fromoct1, $str-pic, $end-pic,$tooct3, $port-mode, $vlan, $vlan-id, $action, $trace, $description); 

0878       call mx-loop-outside ($maxcount, $initial-value = 0, $fromtype, $fromoct1, $str-pic = $str-pic + 1,$end-pic, $tooct3, $port-mode, $vlan, $vlan-id, $action, $trace, $description); 

0879    } 

0880    else if ($str-pic < $end-pic and $fromtype == "xe") { 

0881       call mx-loop-inside ($maxcount = 1, $initial-value, $fromtype, $fromoct1, $str-pic, $end-pic,$tooct3, $port-mode, $vlan, $vlan-id, $action, $trace, $description); 

0882       call mx-loop-outside ($maxcount, $initial-value = 0, $fromtype, $fromoct1, $str-pic = $str-pic + 1,$end-pic, $tooct3, $port-mode, $vlan, $vlan-id, $action, $trace, $description); 

0883    } 

0884   

0885 } 

0886 /* 

0887 *   NAME: MX-LOOP-INSIDE 

0888 *   PURPOSE: To process each Interface in the range specified. 

0889 *   CALLED: Called if no errors where found with the input to the macro. 

0890 *           Also called recursively within itself.  This is how looping works. 

0891 * 

0892 *   PARMS PASSED: 

0893 *        $maxcount = It's the ending Interface number 

0894 *                    Used for controlling the loop 

0895 *        $initial-value = It's the starting Interface number 

0896 *                         Used for controlling the loop 

0897 *        $fromtype = Type of interface (GE or XE) 

0898 *                    Used to reconstruct the full Interface name 

0899 *        $fromoct1 = The DPC (Member) number 

0900 *                    Used to reconstruct the full Interface name 

0901 *        $str-pic  = The PIC number to start on 

0902 *                    Used to reconstruct the full Interface name 

0903 *        $end-pic  = The PIC number to end on 

0904 *                    Used to reconstruct the full Interface name 

0905 *        $tooct3   = The Interface number to end on 

0906 *                    Used to reconstruct the full Interface name 

0907 *        $port-mode = If set to "trunk", then the "port-mode trunk" option 

0908 *                     is added to the Interface 

0909 *        $vlan = The vlan name to add to the Interface 

0910 *        $vlan-id = The vlan-id for the vlan. 

0911 *                   Currently not used 

0912 *        $action = If set to "delete", then kill-it is called 

0913 *        $trace = If "ztrace" is specified in the macro, then 

0914 *                 print out debugging information 

0915 *        $description = The "description" to add to each Interface.                    

0916 * 

0917 */ 

0918 template mx-loop-inside ($maxcount, $initial-value, $fromtype, $fromoct1, $str-pic, $end-pic, $tooct3,$port-mode, $vlan, $vlan-id, $action, $trace, $description){   

0919     if ($initial-value <= $maxcount) { 

0920         var $ifl = $fromtype _ "-" _ $fromoct1 _ "/" _ $str-pic _ "/" _ $initial-value; 

0921         /*                                                                 */ 

0922         /* If debug was requested from the macro, then print out a message */ 

0923         /* for each interface being worked on.                             */ 

0924         /*                                                                 */ 

0925         if (contains($trace,"ztrace")) { 

0926            call write-msg($ifl, $port-mode, $vlan, $vlan-id, $action, $type = "mx", $set-loc); 

0927         } 

0928         if ($action == "delete") { 

0929            call kill-it-interfaces-mx($ifl, $port-mode, $vlan-id); 

0930         } 

0931         else { 

0932            call attach-to-interfaces-mx($ifl, $port-mode, $vlan-id, $description); 

0933         } 

0934   

0935         call mx-loop-inside ($maxcount, $initial-value = $initial-value + 1, $fromtype, $fromoct1, $str-pic, $end-pic, $tooct3, $port-mode, $vlan, $vlan-id, $action, $trace, $description); 

0936     } 

0937 } 

0938   

0939 /* 

0940 *   NAME: KILL-IT-INTERFACES-MX 

0941 *   PURPOSE: To remove an element from the configuration. 

0942 *   CALLED: Only called if "action delete" is specified in the range macro 

0943 * 

0944 *   PARMS PASSED: 

0945 *        $ifl = The interface name to act on 

0946 *        $port-mode = if "mode = trunk", then delete the <port-mode> element 

0947 *        $vlan-id = if "vlan-id" is non-blank, then delete the <vlan-id> element 

0948 *                   or <vlan-id-list> element depending on $port-mode. 

0949 * 

0950 *        NOTE: If both $port-mode and $vlan-ld are true, then both will be deleted. 

0951 *              If only $ifl is specified, then the complete interface is deleted 

0952 * 

0953 */ 

0954 template kill-it-interfaces-mx($ifl, $port-mode, $vlan-id) { 

0955    if (not($vlan-id) and not($port-mode)) { 

0956      <change> { 

0957         <interfaces> { 

0958            <interface delete="delete"> { 

0959                <name> $ifl; 

0960            } 

0961         } 

0962      } 

0963    } 

0964    else { 

0965       <change> { 

0966           <interfaces> { 

0967               <interface> { 

0968                  <name> $ifl; 

0969                     <unit> { 

0970                        <name> "0"; 

0971                              if ($vlan-id and $port-mode) { 

0972                                 if(count(../interfaces/interface[name=$ifl]/unit[name="0"]/family/bridge/vlan-id-list) == 1) { 

0973                                    /*                                           */ 

0974                                    /*  If only 1 vlan-id is on the trunk        */ 

0975                                    /*  the whole family needs to be removed     */ 

0976                                    /*  or else the "commit" will fail since     */ 

0977                                    /*  the trunk will have no vlans on it       */ 

0978                                    /*                                           */ 

0979                                    <family delete="delete"> { 

0980                                       <bridge>; 

0981                                    } 

0982                                 } 

0983                                 else { 

0984                                    <family> { 

0985                                       <bridge> { 

0986                                          <vlan-id-list delete="delete"> $vlan-id; 

0987                                       } 

0988                                    } 

0989                                 } 

0990                              } 

0991                              /*                                              */ 

0992                              /*  If not a trunk and the vlan-id is being     */ 

0993                              /*  deleted, then we must remove the own family */ 

0994                              /*  or else the "commit" will fail since        */ 

0995                              /*  "family bridge" with an "interface-mode"    */ 

0996                              /*  of "access" must have a vlan-id on it.      */ 

0997                              /*                                              */ 

0998                              else if ($vlan-id) {  

0999                                 <family delete="delete"> { 

1000                                    <bridge>; 

1001                                 } 

1002                              } 

1003                   } 

1004               } 

1005             } 

1006    } 

1007 } 

1008 } 

1009 /* 

1010 *   NAME: ATTACH-INTERFACES-MX 

1011 *   PURPOSE: Build the XML statement needed to add the information to 

1012 *            the Interfaces heirarchy 

1013 *   CALLED: Only called for MX-series devices 

1014 * 

1015 *   PARMS PASSED: 

1016 *        $ifl = The interface name being acted on 

1017 *        $port-mode = "port-mode" specified in the macro 

1018 *        $vlan = "vlan" specified in the macro 

1019 *        $description = "description" specified in the macro 

1020 * 

1021 * 

1022 */ 

1023 template attach-to-interfaces-mx($ifl, $port-mode, $vlan-id, $description) { 

1024 /* 

1025 *   Verify that the the interface we are working is on suitable. 

1026 *      If the interface exists, determine if "family bridge" is 

1027 *      already set.  If not, then print a warning and do not 

1028 *      apply any macro settings. 

1029 * 

1030 */ 

1031    var $u-count=count(../interfaces/interface[name = $ifl]/unit); 

1032    var $f-count=count(../interfaces/interface[name = $ifl]/unit[name="0"]/family); 

1033    if ($u-count > 1 || $f-count > 1 || (not(../interfaces/interface[name = $ifl]/unit[name ="0"]/family/bridge) and $f-count = 1)) { 

1034      <xnm:warning> { 

1035         <message> { 

1036            expr "RANGE MACRO: Conflict on Interface "; 

1037            expr $ifl; 

1038            expr ".  Unable to apply macro to the interface."; 

1039         } 

1040      } 

1041    } 

1042      else { 

1043         <change> { 

1044            <interfaces> { 

1045               <interface> { 

1046                  <name> $ifl; 

1047                  if ($description) { 

1048                     <description> $description; 

1049                  } 

1050                     <unit> { 

1051                        <name> "0"; 

1052                           <family> { 

1053                              <bridge> { 

1054                                 /*                                           */ 

1055                                 /*  Trunks on MX do not support "vlan-id" so */ 

1056                                 /*  make sure to write into "vlan-id-list"   */ 

1057                                 /*                                           */ 

1058                                 if ($port-mode == "trunk") { 

1059                                    <interface-mode> "trunk"; 

1060                                    <vlan-id-list> $vlan-id; 

1061                                 } 

1062                                 else { 

1063                                 /*                                           */ 

1064                                 /*  MX does not assume a port is of type     */ 

1065                                 /*  access, so we must set the type when     */ 

1066                                 /*  we set the vlan-id or the commit will    */ 

1067                                 /*  fail.                                    */ 

1068                                 /*                                           */ 

1069                                    <interface-mode> "access"; 

1070                                    <vlan-id> $vlan-id; 

1071                                 } 

1072                              } 

1073                           } 

1074                        } 

1075                } 

1076            } 

1077         } 

1078      } 

1079 } 
 
XML Script Contents
 

 
01 <?xml version="1.0"?> 

02 <script> 

03 <title>range.slax</title> 

04 <author>jayw</author> 

05 <synopsis> 

06 To allow the user to issue select attributes on a range of interfaces on EX and MX. 

07 </synopsis> 

08 <coe>commit</coe> 

09 <type>interfaces</type> 

10   

11 <description> 

12 This script uses the "range" macro for configuring a range of interfaces (DPC and PIC for EX, DPC for MX). If the vlan specified to be placed on the interfaces does not exist in "vlans", the vlan will 

13  be created and the "vlan-id" will be added. 

14 </description> 

15   

16  <example> 

17  <title>Config</title> 

18  <config>example-1.conf</config> 

19  </example> 

20   

21 <xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml" 

22 src="../../../../../web/leaf.js" 

23 type="text/javascript"/> 

24 </script> 

#SLAX
#commit-script
#VLAN