Below are two sets of scripts that allow you to add ZTP device, image and configuration file entries to the Cisco Prime Network
Registrar (CPNR) DHCP server configuration file. There is one set of three scripts for IPv4, and a separate set of five scripts
for IPv6. To use these scripts:
-
Copy and paste the contents of the scripts into local text files with the names given here.
-
Modify the device, image and configuration entries in the ztp-v4-setup-vi-nrcmd.txt or ztp-v6-setup-vi-nrcmd.txt script to fit your needs, as explained in the script's comments.
-
Copy all of the script files you want to use to the root folder of your local CPNR server.
-
Execute the scripts on the CPNR server using the following command:
[root@cpnr-local ~]#/opt/nwreg2/local/usrbin/nrcmd -N username -P password <ztp-IPVersion-setup-via-nrcmd.txt
Where:
-
username is the name of a user ID with administrator privileges on the CPNR server.
-
password is the password for the corresponding CPNR admin user ID.
-
IPVersion is either v4
for the IPv4 version of the scripts, or v6
for the IPv6 version of the scripts.
Cisco recommends that you deploy Crosswork ZTP over secure networks only. Please see the additional requirements in #Cisco_Reference.dita_bcea55f7-a7aa-42a2-a707-2d254de554c7__.
IPv4 Script 1 of 3: ztp-v4-setup-vi-nrcmd.txt
#
# Create the scope
#
scope ztp-ncs-5501-mgmt create 192.0.20.0/24
# Add the dynamic range
scope ztp-ncs-5501-mgmt addrange 200 225
# Default the routers option. Note: No need to do subnet-mask. It is automatically provided.
scope-policy ztp-ncs-5501-mgmt setoption routers 10.10.10.1
# Set the lease time for clients on this scope
scope-policy ztp-ncs-5501-mgmt setoption dhcp-lease-time 216000
#
# Load the option 43 definitions
import option-set ztp-v4-option-set.txt
#
# Set the client classing expression and enable use of client-class
dhcp set client-class-lookup-id=@ztp-v4-client-class-expr.txt
dhcp enable client-class
#
# Load the client classes - these are used to lookup the correct client details
# depending on whether an iso or script is requested by the client.
client-class ztp-iso create
client-class ztp-iso set client-lookup-id="(or (try (concat (as-string
(request get option 61)) \"-iso\")) (request macaddress-string))"
#
client-class ztp-script create
client-class ztp-script set client-lookup-id="(or (try (concat (as-string
(request get option 61)) \"-script\")) (request macaddress-string))"
#
# Clients that are not ztp will fall into the ztp-none class
# and should not be offered service so they are excluded.
#
client-class ztp-none create
client-class ztp-none set action=exclude
#
# Create a default client that will prevent service to unknown clients.
client default create
client default set action=exclude
#
# Create some ZTP clients
#
# For each ZTP client we create two clients based on their serial number.
# (See above for the client-lookup-id expressions.)
# One has "-iso" added to the end that will be used when the client's
# request includes "iPXE" in option 77.
# The other has "-script" added to the end that will be used when the
# client's request includes "exr-config" in option 77.
#
### Device-1 Settings ####
client <device-1-serial-num>-iso create
client-policy <device-1-serial-num>-iso set packet-file-name=
"http://<cw-ipv4-address>:30604/crosswork/imagesvc/v1/device/files/cw-image-uuid-d3930e13-b081-4905-b2e5-051249d9b0cb"
client <device-1-serial-num>-script create
client-policy <device-1-serial-num>-script set packet-file-name=
"http://<cw-ipv4-address>:30604/crosswork/configsvc/v1/configs/device/files/d1d7b441-3a27-47d1-aef0-39c3087d34c1"
client-policy <device-1-serial-num>-script setvendoroption 43 Cisco-ZTP "(1 exr-config)(2 0)"
### Device-2 Settings ####
client <device-2-serial-num>--iso create
client-policy <device-2-serial-num>-iso set packet-file-name=
"http://<cw-ipv4-address>:30604/crosswork/imagesvc/v1/device/files/cw-image-uuid-d3930e13-b081-4905-b2e5-051249d9b0cb"
client <device-2-serial-num>-script create
client-policy <device-2-serial-num>-script set packet-file-name=
"http://<cw-ipv4-address>:30604/crosswork/configsvc/v1/configs/device/files/d1640deb-8252-47b6-aab1-a843c0c7757b"
client-policy <device-2-serial-num>-script setvendoroption 43 Cisco-ZTP "(1 exr-config)(2 0)"
#
# Create more as needed using the above as models.
# Note: For those that need option 67 (boot file), you can use:
# client-policy <name> setoption boot-file "<file-url>"
#
# The next line is optional. Uncomment it if you want to log what the script is doing.
# dhcp set log-settings=+incoming-packet-detail,outgoing-packet-detail,client-detail
# Assure that the server is up-to-date with this configuration
dhcp reload
IPv4 Script 2 of 3: ztp-v4-option-set.txt
#
#
# Option Definition Set Export/Import Utility
# Version: 1
#
{
( name = Cisco-ZTP )
( id-range = 1 )
( vendor-option-regex = PXEClient:Arch:.* )
( tenant-id = 0 )
( desc = Cisco ZTP Suboption Definitions )
( option-list = [
{
( id = 43 )
( name = Cisco-ZTP )
( base-type = AT_BLOB )
( desc = Cisco Zero Touch Provision )
( flags = )
( option-list = [
{
( id = 1 )
( name = clientId )
( base-type = AT_NSTRING )
( desc = )
( flags = )
}
{
( id = 2 )
( name = authCode )
( base-type = AT_INT8 )
( desc = )
( flags = )
}
{
( id = 3 )
( name = md5sum )
( base-type = AT_NSTRING )
( desc = )
( flags = )
}
] )
}
] )
}
IPv4 Script 3 of 3: ztp-v4-client-class-expr.txt
(or
(if (equal (as-string (request get-blob option 77)) "iPXE") "ztp-iso")
(if (equal (as-string (request get-blob option 77)) "exr-config") "ztp-script")
"ztp-none"
)
IPv6 Script 1 of 5: ztp-v6-setup-vi-nrcmd.txt
#
# create prefix for mgmt
prefix prefix-for-mgmt create 2001:DB8:10e:201a::/64
#
# Set the client classing expression and enable use
# of client-class
#
dhcp set v6-client-class-lookup-id=@ztp-v6-client-class-expr.txt
dhcp enable client-class
#
# Load the client classes - these are used to lookup the correct
# client details depending on whether an iso or script is requested
# by the client.
#
client-class ztp-iso create
client-class ztp-iso set v6-client-lookup-id=@ztp-v6-iso-lookup-expr.txt
#
client-class ztp-script create
client-class ztp-script set v6-client-lookup-id=@ztp-v6-script-lookup-expr.txt
client-class-policy ztp-script set v6-reply-options=17
#
# Delete option set (may not exist and ok if fails)
#
option-set dhcp6-cisco-custom delete
#
import option-set ztp-v6-options.txt
#
# Clients that are not ztp will fall into the ztp-none class
# and should not be offered service so they are excluded.
#
client-class ztp-none create action=exclude
#
# Create a default client that will prevent service to
# unknown clients.
#
client default create
client default set action=exclude
#
# Create some ZTP clients
#
# For each ZTP client we create two clients based on their mac-address.
# One has "-iso" added to the end that will be used when the client's
# request does not include the "exr-config" in option 77.
# The other has "-script" added to the end that will be used when the
# client's request does include "exr-config" in option 77.
#
client <device-serial-no>-iso create
# Set the vendor options using blob format as option definitions are for different data
client-policy <device-serial-no>-iso setV6VendorOption 17 dhcp6-cisco-custom "(1 exr-config)(2 0)"
# Escape the [ and ] as nrcmd (which uses tcl interpreter) will otherwise fail command
client-policy <device-serial-no>-iso setv6option bootfile-url
"http://\[cw-ipv6-address\]:30604/crosswork/imagesvc/v1/device/files/cw-image-uuid-aec596
a1-7847-4254-966a-2456aa5"
#
client <device-serial-no>-script create
# Set the vendor options using blob format as option definitions are for different data
client-policy <device-serial-no>-script setV6VendorOption 17 dhcp6-cisco-custom "(1 exr-config)(2 0)"
# Escape the [ and ] as nrcmd (which uses tcl interpreter) will otherwise fail command
client-policy <device-serial-no>-script setv6option bootfile-url
"http://\[cw-ipv6-address\]:30604/crosswork/configsvc/v1/configs/device/files/8eb6b7e1
-bd54-40bb-84e0-89f11a60128b"
#
# Assure the server is up-to-date with this configuration
dhcp reload
IPv6 Script 2 of 5: ztp-v6-client-class-expr.txt
(or (try (if (equal (as-string (request get option 15)) "exr-config") "ztp-script"))
(try (if (equal (as-string (request get option 15)) "iPXE") "ztp-iso"))
"ztp-none"
)
IPv6 Script 3 of 5: ztp-v6-iso-lookup-expr.txt
(let (id)
(setq id (request get option 1))
(or
# First try extracting the serial number from DUID
(try (if (equali (substring id 0 6) 00:02:00:00:00:09)
(concat (as-string (substring id 6 128)) "-script")
)
)
# If that fails, use normal client-id (DUID) lookup
(concat (to-string id) "-iso")
)
)
IPv6 Script 4 of 5: ztp-v6-script-lookup-expr.txt
(let (id)
(setq id (request get option 1))
(or
# First try extracting the serial number from DUID
(try (if (equali (substring id 0 6) 00:02:00:00:00:09)
(concat (as-string (substring id 6 128)) "-script")
)
)
# If that fails, use normal client-id (DUID) lookup
(concat (to-string id) "-script")
)
)
IPv6 Script 5 of 5: ztp-v6-options.txt
# Option Definition Set Export/Import Utility
# Version: 1
#
{
( name = dhcp6-cisco-custom )
( desc = Cisco Systems, Inc. )
( vendor-option-enterprise-id = 9 )
( id-range = 2 )
( option-list = [
{
( name = cisco-17 )
( id = 17 )
( base-type = AT_VENDOR_OPTS )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = clientID )
( id = 1 )
( base-type = AT_NSTRING )
( sepstr = , )
( desc = ZTP - clientID )
}
{
( name = authCode )
( id = 2 )
( base-type = AT_INT8 )
( sepstr = , )
( desc = ZTP - authCode )
}
{
( id = 3 )
( name = md5sum )
( base-type = AT_NSTRING )
( desc = ZTP - md5sum )
}
{
( name = cnr-leasequery )
( id = 13 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = oro )
( id = 1 )
( base-type = AT_SHORT )
( flags = AF_IMMUTABLE )
( repeat = ZERO_OR_MORE )
( sepstr = , )
}
{
( name = dhcp-state )
( id = 2 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = data-source )
( id = 3 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = start-time-of-state )
( id = 4 )
( base-type = AT_TIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = base-time )
( id = 5 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = query-start-time )
( id = 6 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = query-end-time )
( id = 7 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = client-class-name )
( id = 8 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = partner-last-transaction-time )
( id = 9 )
( base-type = AT_TIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = client-creation-time )
( id = 10 )
( base-type = AT_TIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = limitation-id )
( id = 11 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = binding-start-time )
( id = 12 )
( base-type = AT_TIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = binding-end-time )
( id = 13 )
( base-type = AT_STIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = fwd-dns-config-name )
( id = 14 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = rev-dns-config-name )
( id = 15 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = lookup-key )
( id = 16 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = user-defined-data )
( id = 17 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = prefix-name )
( id = 18 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = failover-state-serial-number )
( id = 19 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = reservation-key )
( id = 20 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = failover-partner-lifetime )
( id = 21 )
( base-type = AT_STIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = failover-next-partner-lifetime )
( id = 22 )
( base-type = AT_STIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = failover-expiration-time )
( id = 23 )
( base-type = AT_STIME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = client-oro )
( id = 24 )
( base-type = AT_SHORT )
( flags = AF_IMMUTABLE )
( repeat = ZERO_OR_MORE )
( sepstr = , )
}
] )
}
{
( name = failover )
( id = 21 )
( base-type = AT_BLOB )
( flags = AF_NO_CONFIG_OPTION,AF_SUPPORTS_ENCAP_OPTION,AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = server-state )
( id = 1 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = server-flags )
( id = 2 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = binding-status )
( id = 3 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = binding-flags )
( id = 4 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = start-time-of-state )
( id = 5 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = state-expiration-time )
( id = 6 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = failover-expiration-time )
( id = 7 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = bndupd-serial )
( id = 8 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = bndack-serial )
( id = 9 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = client-flags )
( id = 10 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = vpn-id )
( id = 11 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = lookup-key )
( id = 12 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = type )
( id = 0 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = data )
( id = 0 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
] )
}
{
( name = user-defined-data )
( id = 13 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = reconfigure-data )
( id = 14 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = time )
( id = 0 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = key )
( id = 0 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
] )
}
{
( name = requested-fqdn )
( id = 15 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = flags )
( id = 0 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = domain-name )
( id = 0 )
( base-type = AT_DNSNAME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
] )
}
{
( name = forward-dnsupdate )
( id = 16 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = reverse-dnsupdate )
( id = 17 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = partner-raw-cltt )
( id = 18 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = client-class )
( id = 19 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = status-code )
( id = 20 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = status-code )
( id = 0 )
( base-type = AT_SHORT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = status-message )
( id = 0 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
] )
}
{
( name = dns-info )
( id = 21 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = flags )
( id = 0 )
( base-type = AT_SHORT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = host-label-count )
( id = 0 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = name-number )
( id = 0 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
] )
}
{
( name = base-time )
( id = 22 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = relationship-name )
( id = 23 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = protocol-version )
( id = 24 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = mclt )
( id = 25 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = dns-removal-info )
( id = 26 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
( option-list = [
{
( name = host-name )
( id = 1 )
( base-type = AT_RDNSNAME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = zone-name )
( id = 2 )
( base-type = AT_DNSNAME )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = flags )
( id = 3 )
( base-type = AT_SHORT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = forward-dnsupdate )
( id = 4 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = reverse-dnsupdate )
( id = 5 )
( base-type = AT_NSTRING )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
] )
}
{
( name = max-unacked-bndupd )
( id = 27 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = receive-timer )
( id = 28 )
( base-type = AT_INT )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = hash-bucket-assignment )
( id = 29 )
( base-type = AT_BLOB )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = partner-down-time )
( id = 30 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = next-partner-lifetime )
( id = 31 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = next-partner-lifetime-sent )
( id = 32 )
( base-type = AT_DATE )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
{
( name = client-oro )
( id = 33 )
( base-type = AT_SHORT )
( flags = AF_IMMUTABLE )
( repeat = ZERO_OR_MORE )
( sepstr = , )
}
{
( name = requested-prefix-length )
( id = 34 )
( base-type = AT_INT8 )
( flags = AF_IMMUTABLE )
( sepstr = , )
}
] )
}
] )
}
] )
}