Check in of configuration files to a Gitlab server

I’m planning a small blog post series about Cisco configuration backup with Netbox and Gitlab.

My idea is to “control” which devices are backed up by Netbox with Device Type, Site, IPv4 address and Status (“Active”).

Based on above information the script should then login with SSH to the devices, send a couple of commands like banner, wr mem, copy run scp to start a file transfer to save the configuration on a SCP host temporary directory.

The configuration files are then checked in into a GitLab repository so it’s easy to track and compare configuration files.

To outline the idea, I made the drawing shown below.

Concept Cisco configuration backup with Netbox and Gitlab
Concept Cisco configuration backup with Netbox and Gitlab

Check in part for Gitlab

To check in the configuration files the script uses a for-loop to go through the devices. The for-loop does some IPv4 cleanup (remove the subnet bits) and checks for the device role.

If there is in the /tmp folder a configuration file, the script authenticate against the Gitlab server.

  • If Gitlab does not have the configuration file, the script needs to call the create action.

  • If there is already a configuration file, then the script needs to use the update action.

The try/except block for the create and update action is creating its data in JSON. This JSON data is then committed to the Gitlab server project.

  # Get the devices from Netbox
  devices = getDevicesFromNetbox()

  # Use a for-loop to go through the devices and check in the configuration files
  for i in range(0, len(devices)):

    # Split list
    role = str(devices[i][0])
    location = str(devices[i][1])
    hostname = str(devices[i][2])
    ipv4 = str(devices[i][3])[:len(str(devices[i][3]))-3]
    status = str(devices[i][4])

    # If device is active and has a primary IPv4 address (ssh connect action)
    if status == "Active" and ipv4 != "N":

      # role is a switch
        if role == "switch":
          cliCiscoSwitch()
        # role is a wlc
        elif role == "wificontroller":
          cliCiscoWirelessController()
        # role is a firewall
        elif role == "wanfirewall":
          cliCiscoAsaFirewall()

    # handle list from netbox if device is missing ipv4 or if
    # device status is set to something else than active
    else:
      print ("WARN: device not set to active or IP missing")

    # If device is active and has primary IPv4 address (open file action)
    if status == "Active" and ipv4 != "N":
      # open config file and read it into a string variable
      try:
        content = open('/tmp/' + hostname + '.cfg').read()
      except:
        print ("ERROR: Cannot open file: " + hostname + ".cfg")

      urllib3.disable_warnings()
      requests.packages.urllib3.disable_warnings()
      gl = gitlab.Gitlab(gitlab_url, ssl_verify=False, private_token=gitlab_token)
      # authenticate
      gl.auth()
      # get gitlab project
      project = gl.projects.get(project_id)

      # try with a commit create if file does not exist on gitlab project
      try:
        data_create = {
          'branch': 'master',
          'commit_message': 'Initial commit of config file on ' + today + ' by backup2git',
          'actions': [
            {
              'action': 'create',
               'file_path': location + '/' + hostname + '.cfg',
               'content': open('/tmp/' + hostname + '.cfg').read(),
            }
          ]
        }
      except:
        print ("Cannot build commit create JSON")
        pass
      # If file exists, use commit update to check in new version of file
      try:
        data_update = {
          'branch': 'master',
          'commit_message': 'Update of config file on ' + today + ' by backup2git',
          'actions': [
            {
              'action': 'update',
              'file_path': location + '/' + hostname + '.cfg',
              'content': open('/tmp/' + hostname + '.cfg').read(),
            }
          ]
        }
      except:
        print ("Cannot build commit update JSON")
        pass
Python: Function for Cisco Switch (IOS)

To handle multiple sites (in my case I moved from Germany to New Hampshire, after five years in the USA back to Germany and then within Germany), the Gitlab project uses different directories matching the Sites in Netbox.

Screenshot: Sites in Gitlab project
Screenshot: Sites in Gitlab project

As shown in the screenshot below, the configuration files are stored in the sites directory. Please note that if a configuration file did not exist, the comment would change to Initial commit of config file.

Screenshot: Configuration files in Gitlab project
Screenshot: Configuration files in Gitlab project

The nice thing and benefit of having Cisco configuration files on a Gitlab server is that I can now compare and track changes in the configuration below.

Screenshot: Changes in configuration file
Screenshot: Changes in configuration file

The source code of the script is now available on my Github account at sthierolf / network-automation-scripts / backup2git.py


Share: