As you never know when you need to apply a security patch to your devices you should have a good way to upgrade devices at any time. You do however also want the ability to control which image will be used as you are provisioning new devices. This could be just to comply to your standard, or it could be a matter of having to run a specific version since the configuration you want to use might not be available in the version installed on the device from the beginning.
As a Cisco IOS device boots up and prepares for Autoinstall, it will look for a filename in DHCP option 125, download that file from the TFTP server and read the contents. That file then points to the image file to use. Finally, the device downloads that software file.
The format of option 125 is, interesting.
Let’s say that we call our file “software_to_download” and want to encode this in option 125 we first need to convert the string to hex. Here’s an example in Python:
>>> filename = 'software_to_download' >>> len(filename) 20 >>> hex(len(filename)) '0x14' >>> hex(len(filename))[2:] '14' >>> >>> filename.encode('utf-8').hex() '736f6674776172655f746f5f646f776e6c6f6164' >>> hex_option_125 = '00000009' + '16' + '05' + '14' + '736f6674776172655f746f5f646f776e6c6f6164' >>> hex_option_125 '00000009160514736f6674776172655f746f5f646f776e6c6f6164' >>> isc_dhcp_format = ":".join(map("".join, zip(*[iter(hex_option_125)]*2))).upper() >>> isc_dhcp_format '00:00:00:09:16:05:14:73:6F:66:74:77:61:72:65:5F:74:6F:5F:64:6F:77:6E:6C:6F:61:64' >>>
So, the filename is 20 characters long which is 14 in hex, adding two we come up with 16 which is the entire data length of the string following the vendor id. After that, we just concatenate the filename in hex and convert it to the format that ISC DHCP wants.
Doing this in the ISC DHCP configuration together with specific values for option 82 seemed like a world of pain I didn’t care to visit. I might take a look at it at some point, or instead, do it in Kea DHCP (the successor to ISC DHCP).
If you are provisioning the devices based on manual assignments with a mac address it would be simple enough to create sections for this in the DHCP server. Together with option 82, I didn’t even want to go there. Let me know if you do. :)
Aside from using the autoinstall option there are other ways to upgrade devices. Netmiko which comes installed with Napalm allows you to transfer images to the devices being provisioned.
One way could be to tie into the logic in /opt/ztp/app/tasks.py. I’m not going to add that to the code, but to illustrate how it could be done we can import the file_transfer function. This function requires a Netmiko connection to the device and since Napalm for IOS uses Netmiko under the hood we can piggyback on that connection.
from netmiko import file_transfer file_transfer(dev.device, source_file='image_file.bin', dest_file='image_file.bin')
You could then use Napalm to set the boot configuration and reload the device.