Puppet Network Device Management

Looking for more device management? Read about it here: Managing F5 BIG-IP Network Devices with Puppet

Puppet 2.7.0 was recently released. This version, like every new Puppet release, brings numerous new features (and not counting bug fixes), including one I'm very proud of: Network Device Management.

This all started during the Puppet Camp Europe 2010 in Ghent. One of the open space session was about managing non-POSIX systems like remote devices, database systems or proprietary appliances on which we can't directly run Puppet. Returning from the Puppet Camp, I started to think about implementing a network device management stack in Puppet, and several months later the feature was added to Puppet.

The Puppet Network Device system is a way to configure some network devices' (switches, routers) aspects. This is currently limited to a subset of Cisco IOS devices at that time, but the system could be extended with new device types.

For the moment only two aspects of a network device can be managed:

  • interfaces
  • vlans

A Bird's-Eye View

The configuration system does roughly the following:

  • connect to the device, through ssh or telnet
  • authenticate as a user (possibly unprivileged in which case it can "enable")
  • check the current device state
  • apply the necessary changes as IOS commands to bring it to the correct state

To achieve this, Puppet 2.7.0 introduces a new Puppet application called 'puppet device'. This application will run on a Puppet node (multiple puppet device can run on different hosts) and will make sure a given list of network devices will be managed.

This application acts as a smart proxy between the Puppet Master and the managed network device. To do this, puppet device will sequentially connects to the master on behalf of the managed network device and will ask for a catalog (a catalog containing only network device resources). It will then apply this catalog to the said device by translating the resources to orders the network device understands. Puppet device will then report back to the master for any changes and failures as a standard node.

Closer Look at Puppet Device

Puppet device is not yet a daemon, so the best way to run it is to schedule it with cron. Puppet device knows the devices it will manage by reading a simple configuration file: "/etc/puppet/device.conf". If the node on which puppet device runs is managed by Puppet, this file can be created by Puppet itself.

This file contains the list of device to manage with this instance of puppet device. It has this format:

  [device1 certname]
  type cisco
  url ssh://puppet:letmein@device.domain.com/

  [device2 certname]
  type cisco
  url telnet://puppet:letmein@router.domain.com/?enable=enablepassword

You'll notice that the configuration file lists three things:

  • the device certname. This is the name your master will refer to this device.
  • the device type. currently only cisco is supported
  • the device URL

The device URL must mention:

  • the access method. For the moment only ssh:// and telnet:// are supported
  • the user and password to connect to the device
  • the network hostname of said device
  • any potential TCP port
  • an enable password for unprivileged users requiring one

I mentioned certname in the description above. Yes, that means every device will have its own certificate in the Puppet ecosystem. This guarantees the security of the infrastructure, and allows to revoke devices when needed. The downside is that you'll have to sign those certificate, like we do for every puppet node. Puppet device acts like the regular Puppet Agent in this area, it will wait for a certificate if one of the managed device is not yet
signed.

Enough Talk—Let's Configure a Switch!

Let's suppose we're managing a small cisco 2950 switch (and that's good because I have one next to me), and that we want to manage some of its interfaces. This switch is a layer 2 only switch, so we won't configure any IP Address, just bare switch interfaces. Let's first add the node to our puppet
manifests:

  node "c2950.domain.com" {

    Interface {
      duplex => auto,
      speed => auto
    }

    interface {
      "FastEthernet 0/1":
        description => "--> to end-user workstation",
        mode => access,
        native_vlan => 1000
    }

    interface {
      # abbreviated interface name are supported
      "Fa0/17":
        description => "--> to web server (channel 1)",
        mode => access,
        etherchannel => 1
    }

    interface {
      "FastEthernet0/18":
        description => "--> to web server (channel 1)",
        mode => access,
        etherchannel => 1
    }

    interface {
      "GigabitEthernet0/1":
        description => "--> to upstream router",
        mode => trunk,
        allowed_trunk_vlans => "99, 1000"
    }
  }

We configured 4 interfaces, one for a standard workstation, two parts of a bonding channel, and finally one trunk to a router.

And when we run puppet device, the following happens:

  info: starting applying configuration to c2950.domain.com
  info: Caching catalog for c2950.domain.com
  info: Applying configuration version '1308408722'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[GigabitEthernet0/1]/description: defined 'description' as '--> to upstream router'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[GigabitEthernet0/1]/mode: mode changed 'access' to 'trunk'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[GigabitEthernet0/1]/allowed_trunk_vlans: defined 'allowed_trunk_vlans' as '99,1000'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[FastEthernet 0/1]/description: defined 'description' as '--> to end-user workstation'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[FastEthernet 0/1]/native_vlan: defined 'native_vlan' as '1000'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[FastEthernet 0/1]/mode: mode changed 'trunk' to 'access'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[FastEthernet0/18]/description: defined 'description' as '--> to web server (channel 1)'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[FastEthernet0/18]/etherchannel: defined 'etherchannel' as '1'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[Fa0/17]/description: defined 'description' as '--> to web server (channel 1)'
  notice: /Stage[main]//Node[c2950.domain.com]/Interface[Fa0/17]/etherchannel: defined 'etherchannel' as '1'
  notice: Finished catalog run in 28.24 seconds

We can see that the configuration was applied interface by interface and properties by properties. Let's connect to the switch to check the configuration changed:

  c2950#sh interfaces FastEthernet 0/1 status

  Port      Name               Status       Vlan       Duplex  Speed Type
  Fa0/1     --> to end-user wo connect      1000         auto   auto 10/100BaseTX

  c2950#sh etherchannel 1 summary 
  ...
  Number of channel-groups in use: 1
  Number of aggregators:           1

  Group  Port-channel  Protocol    Ports
  ------+-------------+-----------+-----------------------------------------------
  1      Po1(SD)         PAgP      Fa0/17(D)   Fa0/18(D)   

  c2950#sh running-config interface GigabitEthernet 0/1
  Building configuration...
  ...
  interface GigabitEthernet0/1
   description --> to upstream router
   switchport trunk allowed vlan 99,1000
   switchport mode trunk
  end

We can also manage vlan with the puppet vlan type:

  node "c2950.domain.com" {
    vlan {
      "103":
        description => "G&A_Dept"
    }
  }

This will make sure the vlan 103 exists and has the correct "G&A_Dept" name:

  info: starting applying configuration to c2950.domain.com
  info: Caching catalog for c2950.domain.com
  info: Applying configuration version '1308409100'
  notice: /Stage[main]//Node[c2950.domain.com]/Vlan[103]/ensure: created
  notice: Finished catalog run in 21.04 seconds

Let's check it worked:

  c2950#sh vlan         

  VLAN Name                             Status    Ports
  ---- -------------------------------- --------- -------------------------------
  ...
  103  G&A_Dept                         active    
  ...

And Routers?

This feature also allows to manage layer 3 interfaces. The only configurable aspect for router interface at this time is IP Addresses. Both IPv4 and IPv6 addresses are supported:

  node "c877.domain.com" {
    interface {
      "Vlan12":
        ipaddress => [ "192.168.14.14/24", "2001:2674:8C23::1/64" ]
    }
  }

And after running this manifest we can check it did setup the correct ip addresses:

  c877#sh running-config interface vlan 12
  ...
  interface Vlan12
   description Vlan12
   ip address 192.168.14.14 255.255.255.0
   ipv6 address 2001:2674:8C23::1/64
  end

Facts

Another important part of puppet is the ability for the node to send to the master its "facts". The puppet network device system also supports a limited number of facts:

  • hostname: configured hostname
  • uptime, uptime_seconds and uptime_days
  • hardwaremodel, processor, hardwarerevision
  • memorysize
  • operatingsystem, operatingsystemrelease

Status

The Puppet Network Device system is still very new. For instance, I found several bugs/regressions while I was writing this article (issues for which I sent patches for review). Bug reports and/or patches are more than welcome!

The Future

People might find strange this feature was added, in a world where networking becomes less and less prominent with more and more infrastructure being virtualized in the cloud.
I believe managing network device will still happen (for instance in cloud provider networks). I also see this software brick as the base of new features to manage cloud specific resources (for instance ec2 load balancers or VPN clouds).

Still, there are plenty of things we can add to this new system:

  • new device types, or device models
  • more configurable aspects (access lists, routes, vpns)
  • new puppet device features: ENC-like for device sources, daemonization, parallelism

We're ready for your contributions :)

Comments

Corey Osman

Corey Osman

Awesome!

Lets see off the top of my hand I could use this for the following.

-- configuring APC UPS, PDUs, and AC devices
-- configuring snap servers
-- out-of-band management devices (HP ilo, KVM devices)

Will definitely check this out.

Alessandro Franceschi

Alessandro Franceschi

Great job Brice! This is really an interesting extension of what can be managed and configured via Puppet.
While listening about it the first times I've to say that I was a bit doubtful about its real potentiality and acceptability, as in many mid/large organizations network people are generally separated from ops, they have their tools and methods to manage the network infrastructure and I suspect it will be difficult to "convince" them to have Puppet driven configuration on their routers.
But, as you said, there are other areas, related to networking but usually under the control of ops, where this could rock and be really handy... I'm referring to public clouds but also private virtual infrastructures... having providers for vmware, kvm, xen that allows you to control their virtual networking is something that would be really useful.

Dan Smart

Dan Smart

I have RANCID setup for config capturing, but a more powerful system like Puppet might be interesting.

Fady Afram

Fady Afram

Hi,

I would like to know if Network Device Management can do the following:

1.Collect configurations from network devices (Routers and FW)
2.Detect any change in configurations and send an alert
3.Push updated configuration to a group of devices
4. Integrate with Nagios/centrion

Thank you.

nanor

nanor

Very good initiative.
Cloud is nothing without network, we will need network config for a long time, so we will need more and more advanced and modern tools like Puppet to accomplish that.
Continue developping ! ;-)

Sean1234

Sean1234

can you do an example where you perform a command, like a ping, or a file copy or something very simple?

Leave a comment

Tradeshow
Aug 20
Camp
Aug 20
Tradeshow
Aug 23
Tradeshow
Aug 24