Friday, April 14, 2017

junos zero touch privisioning automation

If you have hundreds of Juniper EX switches to deploy, this notes will explain how to automate the deployment procedure to save time & effort and money.

Download the deployment script written by Damien Garros:
https://github.com/dgarros/juniper-ztp-campus

ZTP process


Lab setup

Juniper EX3300 switch - always run > request system zeroize to reset to factory default and ticks off the imaging process

FTP server with anonymous access to the files. I am using vsftpd for this lab

Syslog server receives the output from the script ztp-dga.slax

DHCP server
This is one off setup. You shouldn't need to change it for different image or switch model.
dhcpd.conf if you running your isc-dhcpd server
ref:
http://www.juniper.net/techpubs/en_US/junos12.3/topics/task/configuration/software-image-and-configuration-automatic-provisioning-confguring.html
 or
Infoblox DHCP server in my case, but it doesn't support DHCP suboption at this time, so we have to do some conversion on this.
 DHCP option-150 points to my DHCP server 10.104.103.111
 DHCP option-43 01:11:2f:70:75:62:2f:6e:65:74:77:6f:72:6b:2e:63:6f:6e:66:03:03:66:74:70


Option-43 is Hex format:
  suboption code (01) + string length + path of config file + suboption code (03) + string length  + ftp

Notes for manipulating option-43:
00 = The sub option code "00"
33 = Length of the URL "/pub/jinstall-ex-3300-12.3R12.4-domestic-signed.tgz" in Hex format (i.e. 51 becomes 33 in Hex)
Rest is the URL "/pub/jinstall-ex-3300-12.3R12.4-domestic-signed.tgz" itself in Hex format.

03 = The sub option code "03"
03 = Length of the word "ftp"
66:74:70 = FTP in Hex format


network.conf
   This is the only file you will need to detail with once the lab is fully functional. In terms of changing the version of software and switch model.

E.X.
 system {
    host-name ex_juniper;
        root-authentication {
            encrypted-password "$1$Hu5R7lEG$U8lAwHVnejaH8XgWWAKcw/"; ## SECRET-DATA
        }
    services {
        ssh;
    }
    syslog {
        host 10.104.193.111{
            external any;
        }
    }
}
interfaces {
    me0 {
        unit 0 {
            family inet {
                dhcp;
            }
        }
    }
}

#-----------------------------------------
# ZTP bootstrap
#-----------------------------------------

system { delete: autoinstallation; }
event-options {
# time-interval is the problem where most of people encountering
# the time is too short to set 60sec hence more than one ztp-dga instance 
# disrupt each other, in my case I use 360s to cope my imaging cycle
# I will explain this problem in ztp-dga.slax script
  generate-event { ztp-dga time-interval 360; }
  policy ztp-dga  {
    events ztp-dga ;
    then {
       execute-commands {
          commands {
             "op url ftp://10.104.193.111/pub/ztp-dga.slax server 10.104.193.111 ex2200 12.3R12.4 ex3300 12.3R12.4";
          }
       }
    }
  }
}



ztp-dga.slax
 This is script does the magic. I don't copy the full script here, it is avaiable on github url above. I'm only hightlighing few sections from the script which you might need to fit your lab environment.

Change the path to match your ftp structure.
var $CONFIG-DIR = "ftp://" _ $server _ "/pub/";
var $UPLOAD-DIR = "ftp://" _ $server _ "/pub/";
var $JUNOS-DIR = "ftp://" _ $server _ "/pub/";

Remove the syslog server configure if you have something different in your production configs.
/*** We remove unnecessary part of the configuration ***/

    var $load-config-rpc = <load-configuration action = "merge" format = "xml"> {
        <configuration> {
            <system> {
                                <syslog> {
                                        <host delete="delete"> {
                                                <name> "172.26.5.116";
                                        }

Check the ztp-dga script has already started, if yes, don't start a new one. This process time interval is related to the value we set on network.conf

This is my problem here....
My understanding:
1. ztp-dga.splax script starts
2. check if is-already-running
3. if not, the script will do  > request snmp utility-mib set instance ztp-dga object-type integer object-value 1

In your ex switch you can run:
> show snmp mib walk jnxUtil
jnxUtilIntegerValue.112.116.112.45.100.103.97 = 0

In the script, it runs through the following if statements and functions

  /* Check if script is already running,
        if it is, we stop the script
        If not, we set the tracker within the Utility mib
   */
   if( ztp:is-already-running( $jnx ) )
   {
        expr jcs:syslog( $SYSLOG, $SYSLOG_TAG, "Script already running - STOP" );
        <xsl:message terminate="yes">;
   }
   else{
        expr jcs:syslog( $SYSLOG, $SYSLOG_TAG, "Set instance value to 1" );
        expr ztp:set-tracker( $jnx );
   }
...
...
...
/* ------------------------------------------------- */
/* this function is used to set activity tracker to 1 */
/* ------------------------------------------------- */
<func:function name="ztp:set-tracker">
{
   param $jnx;

   var $cmd = <request-snmp-utility-mib-set> {
                  <object-type> "integer";
                  <instance> "ztp-dga";
                  <object-value> "1";
              }

   var $res = jcs:execute( $jnx, $cmd );

   <func:result select="true()">;
}
/* ------------------------------------------------- */
/* this function is used to set activity tracker to 0 */
/* ------------------------------------------------- */
<func:function name="ztp:remove-tracker">
{
   param $jnx;

   var $cmd = <request-snmp-utility-mib-set> {
                  <object-type> "integer";
                  <instance> "ztp-dga";
                  <object-value> "0";
              }

   var $res = jcs:execute( $jnx, $cmd );

   <func:result select="true()">;
}

/* ------------------------------------------------- */
/* this function is used to get activity tracker */
/* ------------------------------------------------- */
<func:function name="ztp:is-already-running">
{
   param $jnx;

   var $cmd = <get-snmp-object> {
                         <snmp-object-name>"jnxUtilIntegerValue.112.116.112.45.100.103.97";
                         /*<snmp-object-name>"1.3.6.1.4.1.2636.3.47.1.1.3.1.2.106.101.97.112.45.100.101.105";*/
                }

   var $res = jcs:execute( $jnx, $cmd )//snmp-object/object-value;

   if( $res == "1" ){
/*      expr jcs:syslog( $SYSLOG, $SYSLOG_TAG, "Check if the script is running: ", $res );*/
        <func:result select="true()">;
   }
   else{
/*      expr jcs:syslog( $SYSLOG, $SYSLOG_TAG, "Check if the script is running: ", $res );*/
        <func:result select="false()">;
   }
}

Thursday, April 13, 2017

Little note for building deb and rpm package for Linux

This is my old little note about how to build deb package for Debian, it is almost 9 years ago. Just saw it today sitting in my folder, thought still a good stuff to leave it here:

deb package
apt-get install debhelper dh-make dpkg-dev
apt-get install debian-policy devscripts

# create new package
dh_make --createorig

pkg-admin-update --- add dependency file

ref:
http://www.debian-administration.org/articles/286
http://www.debian.org/doc/manuals/repository-howto/repository-howto.en.html
http://www.debian.org/doc/devel-manuals#maint-guide
http://users.telenet.be/mydotcom/howto/linux/package02.htm
http://www.debian.org/doc/FAQ/ch-pkg_basics.en.html

http://www.linuxscrew.com/2008/06/11/create-deb-or-rpm-from-targz-with-checkinstall/


alien - convert and install rpm and other packages
autoconf -

# modify changelog
dch -i


# reprepro
mkdir -p /var/www/pkg-debian/conf
cp /var/www/pkg-debian/conf/distributions /var/www/pkg-debian/conf

# add pkg to reprository
reprepro -Vb . include jaunty $i
reprepro --ignore=undefinedtarget -Vb . include jaunty $i

# remove pkg
reprepro -b . remove lenny pkgname


# rename file in a directory
rename:
krb5-config-pkg.debhelper.log
krb5-config-pkg.dirs
krb5-config-pkg.postinst
krb5-config-pkg.postrm

to:
krb5-config-pkgnew.debhelper.log
krb5-config-pkgnew.dirs
krb5-config-pkgnew.postinst
krb5-config-pkgnew.postrm

by cmd:
for i in krb5-config* ; do mv $i ${i/pkg/pkgnew} ; done


rpm packages

rpmbuild -bb pkg-admin-update.spec

rpm -ivh pkg-admin-update.rpm

rpm -qi pkg-admin-update

# on debian
createrepo
apt-rpm-repository

# yum repro
yum-arch

yum-arch /var/www/pkg-centos/5.2/pkg/base

# install SRPM to /usr/src/redhat/
rpm -i rp-pppoe-3.5-32.1.src.rpm

# build SRPM
rpmbuild -ba rp-pppoe.spec
# build RPM
rpmbuild -bb rp-pppoe.spec


#Fedora
http://fedoraproject.org/wiki/Docs/CustomKernel

yum install rpmdevtools yum-utils

rpmdev-setuptree

yumdownloader --source kernel

yum-builddep kernel-<version>.src.rpm

rpm -Uvh kernel-<version>.src.rpm