Home > Blogs > VMware vCloud Blog


Device Management With Puppet

By: Nan Liu, Senior Systems Engineer at VMware.

This is a repost from Nan’s personal blog.

In Puppet 2.7, one of the new features added was device management. In this initial release, only a small number of Cisco switches were supported. Overall the capabilities weren’t really significant, however the concept shifted people’s perception of the boundaries for configuration management. All of sudden Puppet didn’t end at the operating system, and extended to black boxes that were previously thought to be a bridge too far.

This slowly spawned a flurry of activities exploring network devices, load-balancers, and storage:

The benefits of having the entire infrastructure automated with a single tool chain under version control is indisputable. A Software Define Data Center is not complete until you gap the management capabilities whether it’s your network or storage. With that said, there’s still some limitations with puppet device. Currently, the device command only supports communication with a single device at a time. This is fine when the device is self contained, but in some instances it’s necessary to interact with a series of devices to perform a meaningful task. For this reason, we developed transport resource to support multiple connectivity for a single puppet execution. This is not a substitution for orchestration of a chain of events, but rather to group resources that have interactions between different devices:


1
2
3
4
5
6
7
8
9
10
11
12
13
transport { 'ssh':
  username => 'root',
  password => 'p@ss',
  server   => '192.168.1.10',
  # support connection options in net::ssh :
  options  => { 'port' => 10022 },
}

transport { 'rest':
  username => 'admin',
  password => 'secret!',
  server   => '192.168.1.11',
}

A transport is shared and reused across several resources, and custom type/provider can leverage any transport connectivity:


1
2
3
4
5
# this is a mockup
remote_service { 'ntp':
  ensure    => running,
  transport => Transport['ssh'],
}

Here’s an example debug output showing ssh connectivity established and reused for 192.168.1.10 to perform a series of activity.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
debug: PuppetX::Puppetlabs::Transport::Ssh initializing connection to: 192.168.1.10
debug: Executing on 192.168.1.10:
vpxd_servicecfg eula read
debug: Execution result:
VC_EULA_STATUS=1
VC_CFG_RESULT=0

debug: Executing on 192.168.1.10:
vpxd_servicecfg db read
debug: Execution result:
VC_DB_TYPE=embedded
VC_DB_SERVER=
VC_DB_SERVER_PORT=
VC_DB_INSTANCE=
VC_DB_USER=
VC_DB_SCHEMA_VERSION=
VC_CFG_RESULT=0

debug: Executing on 192.168.1.10:
vpxd_servicecfg sso read
debug: Execution result:
SSO_TYPE=embedded
SSO_LS_LOCATION=https://192.168.1.10:7444/lookupservice/sdk
SSO_DB_TYPE=embedded
SSO_DB_SERVER=localhost
SSO_DB_SERVER_PORT=5432
SSO_DB_INSTANCE=ssodb
SSO_DB_USER=ssod
SSO_DB_PASSWORD=
VC_CFG_RESULT=0

debug: Executing on 192.168.1.10:
vpxd_servicecfg service status
debug: Execution result:
VC_SERVICE_STATUS=1
VC_CFG_RESULT=0

debug: Finishing transaction 2205823080
debug: Closing PuppetX::Puppetlabs::Transport::Ssh connection to: 192.168.1.10
debug: Storing state
debug: Stored state in 0.07 seconds
notice: Finished catalog run in 2.90 seconds

In the example above, a single ssh connection was established at the beginning, and closed at the end of the session. This was one of the roadblock Jeremy Schulman brought up when developing network devices NETCONF sessions. Originally I suggested a resource responsible for closing the connections that had automatic dependencies to the correct network resources since there was no API to do this in the provider2. However this doesn’t take in consideration for resources failures which results in dangling open connections. Ultimately, I went back to Puppet::Transaction and added the connection cleanup at the end of evaluate method:


1
2
3
4
5
6
7
8
9
10
module Puppet
  class Transaction
    alias_method :evaluate_original, :evaluate

    def evaluate
      evaluate_original
      PuppetX::Puppetlabs::Transport.cleanup
    end
  end
end

This isn’t the cleanest solution, since it monkey patches Puppet’s internal, and does not trap user termination of Puppet, but it is more reliable then depending on every resource succeeding. Thanks again to Jeremy’s original work with transaction.rb which led me down this path. For now this is a work around, while we wait for Puppet Labs come up with a formal solution to #3946.

Next week at VMware Partners Exchange (PEX 2013), Nick Weaver and Carl Caum will present more about Puppet and how it works with VMware Products at session VPN1298. This is just a sneak preview, so please attend to get the complete picture. Stay tuned, and I will provide more technical details about what we are using Puppet for next week after the PEX announcement.

  1. Juniper has gone as far as embedding Puppet agent to the device.

  2. See #3946. Work on Puppet long enough, you’ll find tickets indicating Dan has explored these dark corners before anyone else.