module PuppetX::NetDev::EosApi::SnmpMethods

SnmpMethods encapsulate the SNMP specific EOS API methods. This separation makes it easier to provide documentation and introspect where methods come from given an api instance.

Constants

SNMP_USER_PARAM

Map SNMP headings from ‘show snmp user` to snmp_user parameter names

Public Instance Methods

parse_snmp_communities(text) click to toggle source

parse_snmp_communities takes the text output from the ‘show snmp community` EAPI command and parses the text into structured data suitable for use as a resource hash to the provider initializer method. An example of the output looks like:

“‘ Community name: jeff Community access: read-write Access list: stest1

Community name: jeff2 Community access: read-write Access list: stest2 (non-existent)

Community name: private Community access: read-write

Community name: public Community access: read-only “‘

@param [String] text The text to parse

@api private

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 184
def parse_snmp_communities(text)
  blocks = text.split("\n\n")
  # (?:\s*\(.*?\)|\n|$) deals with trailing data after the value.  e.g.
  # an ACL might come back as `Access list: stest2 (non-existent)`
  regexp = / (\w+): (\w.*?)(?:\s*\(.*?\)|\n|$)/
  communities = blocks.map { |l| l.scan(regexp) }
  communities.map do |pairs|
    pairs.each_with_object({}) do |(key, val), resource_hash|
      resource_hash.merge!(map_snmp_keys(key, val))
    end
  end
end
parse_snmp_enable(text) click to toggle source

parse_snmp_enable parses the text output of the ‘show snmp` command an returns :true or :false for the enabled state.

@param [String] text The text of the snmp output, e.g. for a disabled

SNMP service:

  SNMP agent enabled in VRFs: default
  SNMP agent disabled: no communities or users configured

@api private

@return [Symbol] :true or :false

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 66
def parse_snmp_enable(text)
  disabled_regexp = /SNMP agent disabled:/m
  enabled_regexp = /SNMP packets input/m

  disabled_mdata = disabled_regexp.match(text)
  return :false if disabled_mdata

  enabled_mdata = enabled_regexp.match(text)
  return :true if enabled_mdata

  fail ArgumentError, 'could not parse text for SNMP enabled state'
end
parse_snmp_hosts(text) click to toggle source

parse_snmp_hosts parses the raw text from the ‘show snmp host` command and returns an Array of resource hashes.

rubocop:disable Metrics/MethodLength

@param [String] text The text of the ‘show snmp host` output, e.g.

for three hosts:

```
Notification host: 127.0.0.1       udp-port: 162   type: trap
user: public                       security model: v3 noauth

Notification host: 127.0.0.1       udp-port: 162   type: trap
user: smtpuser                     security model: v3 auth

Notification host: 127.0.0.2       udp-port: 162   type: trap
user: private                      security model: v2c

Notification host: 127.0.0.3       udp-port: 162   type: trap
user: public                       security model: v1

Notification host: 127.0.0.4       udp-port: 10162 type: inform
user: private                      security model: v2c

Notification host: 127.0.0.4       udp-port: 162   type: trap
user: priv@te                      security model: v1

Notification host: 127.0.0.4       udp-port: 162   type: trap
user: public                       security model: v1

Notification host: 127.0.0.4       udp-port: 20162 type: trap
user: private                      security model: v1

```

@api private

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 371
def parse_snmp_hosts(text)
  re = /host: ([^\s]+)\s+.*?port: (\d+)\s+type: (\w+)\s*user: (.*?)\s+security model: (.*?)\n/m # rubocop:disable Metrics/LineLength
  text.scan(re).map do |(host, port, type, username, auth)|
    resource_hash = { name: host, ensure: :present, port: port.to_i }
    sec_match = /^v3 (\w+)/.match(auth)
    resource_hash[:security] = sec_match[1] if sec_match
    ver_match = /^(v\d)/.match(auth) # first 2 characters
    resource_hash[:version] = ver_match[1] if ver_match
    resource_hash[:type] = /trap/.match(type) ? :traps : :informs
    resource_hash[:username] = username
    resource_hash
  end
end
parse_snmp_traps(text) click to toggle source

parse_snmp_traps takes the raw text output of the ‘show snmp trap` command and parses the data into hases suitable for new provider instances.

@param [String] text The raw text to process.

@api private

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 280
def parse_snmp_traps(text)
  regexp = /(\w+)\s+([-_\w]+)\s+(\w+).*$/
  triples = text.scan(regexp)
  triples.shift # Header
  triples.map do |triple|
    {
      name: format('%s %s', *triple),
      enable: /yes/xi.match(triple[2]) ? :true : :false
    }
  end
end
parse_snmp_users(text) click to toggle source

parse_snmp_users takes the text output from the ‘show snmp user` EAPI command and parses the text into structured data suitable for use as a resource has to the provider initializer method.

“‘

User name : jeff Security model : v3 Engine ID : f5717f00420008177800 Authentication : SHA Privacy : AES-128 Group : developers

User name : nigel Security model : v2c Group : sysops (not configured)

User name : nigel Security model : v3 Engine ID : f5717f00420008177800 Authentication : SHA Privacy : AES-128 Group : sysops “‘

rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/MethodLength

@param [String] text The text to parse

@api private

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 522
def parse_snmp_users(text)
  text.split("\n\n").map do |user_s|
    user_s.scan(/^(\w+).*?: (.*)/).each_with_object({}) do |(h, v), m|
      key = SNMP_USER_PARAM[h.downcase.intern] || h.downcase.intern
      m[key] = case key
               when :privacy  then /AES/.match(v) ? :aes128 : :des
               when :version  then v.sub('v2c', 'v2').intern
               when :auth     then v.downcase.intern
               when :roles    then v.sub(/ \(.*?\)/, '')
               else v.downcase
               end
    end
  end
end
snmp_attributes() click to toggle source

snmp_attributes retrieves the current state of the SNMP service on the device and returns data suitable for a provider instance.

@return [Hash<Symbol,String>]

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 17
def snmp_attributes
  rval = { name: 'settings', ensure: :present }
  rval.merge!(snmp_location)
  rval.merge!(snmp_enable)
  rval.merge!(snmp_contact)
end
snmp_communities() click to toggle source

snmp_communities retrieves all of the SNMP community strings defined on the target device and returns an Array of Hash objects suitable for use as a resource hash to the provider’s initializer method.

@param [String] buf Describe the string parameter here

@api public

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 150
def snmp_communities
  cmd = 'show snmp community'
  result = eapi_action(cmd, 'get snmp communities', format: 'text')
  text = result.first['output']
  parse_snmp_communities(text)
end
snmp_community_destroy(opts) click to toggle source

snmp_community_destroy deletes an SNMP community from the target device. given a hash of attributes from the resource model.

@option opts [String] :name (‘public’) The community name

@api public

@return [Boolean] true if the resource was successfully created

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 249
def snmp_community_destroy(opts)
  prefix = %w(enable configure)
  cmd = "no snmp-server community #{opts[:name]}"
  result = eapi_action([*prefix, cmd], 'destroy snmp community')
  result && true || false
end
snmp_community_set(opts) click to toggle source

snmp_community_set creates or updates an snmp community on the target device given a hash of attributes from the resource model.

@option opts [String] :name (‘public’) The community name

@option opts [Symbol] :group (:ro) :ro or :rw for read-only or

read-write access control for the community name.

@option opts [String] :acl (‘stest1’) The standard ACL name defined on

the switch.  This ACL is defined using the `ip access-list standard
stest1` command.

@api public

@return [Boolean] true if the resource was successfully created

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 232
def snmp_community_set(opts)
  prefix = %w(enable configure)
  cmd = "snmp-server community #{opts[:name]}"
  cmd << " #{opts[:group]}" if opts[:group]
  cmd << " #{opts[:acl]}" if opts[:acl]
  eapi_action([*prefix, cmd], 'define snmp community') && true || false
end
snmp_contact() click to toggle source

snmp_contact returns the snmp contact string configured on the device.

@api private

@return [Hash<Symbol,Symbol>] e.g. ‘{ contact: ’Jane Doe’ }‘

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 85
def snmp_contact
  cmd = 'show snmp contact'
  result = eapi_action(cmd, 'get snmp contact')
  contact = result.first['contact']
  { contact: contact }
end
snmp_contact=(contact) click to toggle source

snmp_contact= updates the SNMP contact on the target device.

@param [String] contact The contact name, e.g. ‘Jane Doe’

@api public

@return [Boolean] true or false

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 120
def snmp_contact=(contact)
  cmd = %w(enable configure)
  cmd << "snmp-server contact #{contact}"
  eapi_action(cmd, 'set snmp contact') && true || false
end
snmp_enable() click to toggle source

snmp_enable returns :true if SNMP is enabled on the device or :false otherwise as a Hash suitable for merge into ‘snmp_attributes`.

@api private

@return [Hash<Symbol,Symbol>] e.g. ‘{ enable: :true }`

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 45
def snmp_enable
  cmd = 'show snmp'
  result = eapi_action(cmd, 'get snmp status', format: 'text')
  text = result.first['output']
  enable = parse_snmp_enable(text)
  { enable: enable }
end
snmp_enable=(state) click to toggle source

snmp_enable= disables or enables SNMP

@param [Boolean] state enable SNMP if true, disable if false.

@api public

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 98
def snmp_enable=(state)
  cmd = %w(enable configure)
  case state
  when true
    cmd << 'snmp-server community public ro'
  when false
    cmd << 'no snmp-server'
  else
    fail ArgumentError, "invalid state #{state.inspect}"
  end

  eapi_action(cmd, 'configure snmp') && true || false
end
snmp_location() click to toggle source

snmp_location obtains the configured SNMP location string from the device.

@api private

@return [Hash<Symbol,String>]

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 31
def snmp_location
  cmd = 'show snmp location'
  result = eapi_action(cmd, 'get snmp location')
  location = result.first['location']
  { location: location }
end
snmp_location=(location) click to toggle source

snmp_location= updates the SNMP location on the target device.

@param [String] location The location, e.g. ‘Planet Earth’

@api public

@return [Boolean] true or false

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 134
def snmp_location=(location)
  cmd = %w(enable configure)
  cmd << "snmp-server location #{location}"
  eapi_action(cmd, 'set snmp location') && true || false
end
snmp_notification_receiver_remove(opts = {}) click to toggle source

snmp_notification_receiver_remove removes an snmp-server host from the target device.

@option opts [String] :name (‘127.0.0.1’) The hostname or ip address

of the snmp notification receiver host.

@option opts [String] :username (‘public’) The SNMP username, or

community, to use for authentication.

@option opts [Fixnum] :port (162) The UDP port of the receiver.

@option opts [Symbol] :version (:v3) The version, :v1, :v2, or :v3

@option opts [Symbol] :type (:traps) The notification type, :traps or

:informs.

@option opts [Symbol] :security (:auth) The security mode, :auth,

:noauth, or :priv

@api public

@return [Boolean]

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 460
def snmp_notification_receiver_remove(opts = {})
  prefix = %w(enable configure)
  cmd = 'no ' << snmp_notification_receiver_cmd(opts)
  result = eapi_action([*prefix, cmd], 'remove snmp host')
  result ? true : false
end
snmp_notification_receiver_set(opts = {}) click to toggle source

snmp_notification_receiver_set takes a resource hash and configures a SNMP notification host on the target device. In practice this method usually creates a resource because nearly all of the properties can vary and are components of a resource identifier.

@option opts [String] :name (‘127.0.0.1’) The hostname or ip address

of the snmp notification receiver host.

@option opts [String] :username (‘public’) The SNMP username, or

community, to use for authentication.

@option opts [Fixnum] :port (162) The UDP port of the receiver.

@option opts [Symbol] :version (:v3) The version, :v1, :v2, or :v3

@option opts [Symbol] :type (:traps) The notification type, :traps or

:informs.

@option opts [Symbol] :security (:auth) The security mode, :auth,

:noauth, or :priv

@api public

@return [Boolean]

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 411
def snmp_notification_receiver_set(opts = {})
  prefix = %w(enable configure)
  cmd = snmp_notification_receiver_cmd(opts)
  result = eapi_action([*prefix, cmd], 'set snmp host')
  result ? true : false
end
snmp_notification_receivers() click to toggle source

snmp_notification_receivers obtains a list of all the snmp notification receivers and returns them as an Array of resource hashes suitable for the provider’s new class method. This command maps the ‘show snmp host` command to an array of resource hashes.

@api public

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 324
def snmp_notification_receivers
  cmd = 'show snmp host'
  msg = 'get snmp notification hosts'
  result = eapi_action(cmd, msg, format: 'text')
  text = result.first['output']
  parse_snmp_hosts(text)
end
snmp_notification_set(opts) click to toggle source

snmp_notification_set configures a SNMP trap notification on the target device.

@option opts [String] :name (‘snmp link-down’) The trap name with the

type name as a prefix separated by a space.  The special name 'all'
will enable or disable all notifications.

@option opts [Symbol] :enable (:true) :true to enable the

notification, :false to disable the notification.

@api public

@return [Boolean] true if successful

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 306
def snmp_notification_set(opts)
  prefix = %w(enable configure)
  pre = opts[:enable] == :true ? '' : 'no '
  suffix = opts[:name] == 'all' ? '' : " #{opts[:name]}"
  cmd = pre << 'snmp-server enable traps' << suffix
  result = eapi_action([*prefix, cmd], 'set snmp trap')
  result && true || false
end
snmp_notifications() click to toggle source

snmp_notifications returns an Array of resource hashes suitable for initializing new provider resources.

@api public

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 263
def snmp_notifications
  cmd = 'show snmp trap'
  result = eapi_action(cmd, 'get snmp traps', format: 'text')
  text = result.first['output']
  parse_snmp_traps(text)
end
snmp_user_destroy(opts = {}) click to toggle source

snmp_user_destroy removes an SNMP user from the target device

@option opts [String] :name (‘johndoe’) The username

@option opts [Array] :roles ([‘developers’]) The group, as an Array,

this user is associated with.

@option opts [Symbol] :version (:v2) The snmp version for this user

account.

@option opts [Symbol] :auth (:sha) The authentication digest method

@option opts [Symbol] :privacy (:aes) The encryption scheme for

privacy.

@option opts [String] :password (‘abc123’) The password to

configure for authentication and privacy.

@api public

@return [Hash<Symbol,Object>] Updated properties, e.g. the password

hash which is idempotent.

@return [String]

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 618
def snmp_user_destroy(opts = {})
  prefix = %w(enable configure)
  group = [*opts[:roles]].first
  version = opts[:version].to_s.sub('v2', 'v2c')
  cmd = "no snmp-server user #{opts[:name]} #{group} #{version}"
  eapi_action([*prefix, cmd], 'remove snmp user')
  {}
end
snmp_user_password_hash(running_config, user_cmd) click to toggle source

snmp_user_password obtains the password hash from the device in order to provide an idempotent configuration value.

@param [String] running_config The text of the current running

configuration.

@param [String] user_cmd The prefix of the command that identifies

the user in the running-config.  e.g. ('snmp-server user jeff
developers v3')

@return [Hash<Symbol,String>] The hashes for :auth and :privacy

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 639
def snmp_user_password_hash(running_config, user_cmd)
  regexp = /#{user_cmd} .*?auth \w+\s+(.*?)\s+priv \w+\s+(.*?)\s/
  (auth_hash, priv_hash) = running_config.scan(regexp).first
  { auth: auth_hash, privacy: priv_hash }
end
snmp_user_set(opts = {}) click to toggle source

snmp_user_set creates or updates an SNMP user account on the target device.

rubocop:disable Metrics/MethodLength

@option opts [String] :name (‘johndoe’) The username

@option opts [Array] :roles ([‘developers’]) The group, as an Array,

this user is associated with.

@option opts [Symbol] :version (:v2) The snmp version for this user

account.

@option opts [Symbol] :auth (:sha) The authentication digest method

@option opts [Symbol] :privacy (:aes) The encryption scheme for

privacy.

@option opts [String] :password (‘abc123’) The password to

configure for authentication and privacy.

@api public

@return [Hash<Symbol,Object>] Updated properties, e.g. the password

hash which is idempotent.
# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 574
def snmp_user_set(opts = {})
  prefix = %w(enable configure)
  group = [*opts[:roles]].first
  fail ArgumentError, 'at least one role is required' unless group
  version = opts[:version].to_s.sub('v2', 'v2c')
  cmd = user_cmd = "snmp-server user #{opts[:name]} #{group} #{version}"
  if opts[:password] && version == 'v3'
    privacy = opts[:privacy].to_s.scan(/aes|des/).first
    fail ArgumentError,
         'privacy is required when managing passwords' unless privacy
    cmd += " auth #{opts[:auth] || 'sha'} #{opts[:password]} "\
      "priv #{privacy} #{opts[:password]}"
  end
  eapi_action([*prefix, cmd], 'configure snmp user')
  hash = snmp_user_password_hash(running_config, user_cmd)
  { password: hash[:auth] }
end
snmp_users() click to toggle source

snmp_users retrieves all of the SNMP users defined on the target device and returns an Array of Hash objects suitable for use as a resource hash to the provider’s initializer method.

@api public

@return [Array<Hash<Symbol,Object>>] Array of resource hashes.

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 475
def snmp_users
  cmd = 'show snmp user'
  result = eapi_action(cmd, 'get snmp users', format: 'text')
  text = result.first['output']
  users = parse_snmp_users(text)
  text = running_config
  users.each do |h|
    cmd = "snmp-server user #{h[:name]} #{h[:roles]} #{h[:version]}"
    password = snmp_user_password_hash(text, cmd)[:auth]
    h[:password] = password if password
  end
end

Private Instance Methods

map_snmp_keys(key, val) click to toggle source

map_snmp_keys maps the keys and values parsed from the show snmp community raw text output into resource attributes and values.

@api private

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 202
def map_snmp_keys(key, val)
  case key
  when 'name' then { name: val }
  when 'list' then { acl: val }
  when 'access'
    group = case val
            when 'read-write'; then 'rw'
            when 'read-only'; then 'ro'
            end
    { group: group }
  end
end
snmp_notification_receiver_cmd(opts = {}) click to toggle source

snmp_notification_receiver_cmd builds a command given a resource hash.

@return [String]

# File lib/puppet_x/net_dev/eos_api/snmp_methods.rb, line 423
def snmp_notification_receiver_cmd(opts = {})
  host = opts[:name].split(':').first
  version = /\d+/.match(opts[:version]).to_s
  version.sub!('2', '2c')
  cmd = "snmp-server host #{host}"
  cmd << " #{opts[:type] || :traps}"
  cmd << " version #{version}"
  cmd << " #{opts[:security] || :noauth}" if version == '3'
  cmd << " #{opts[:username]}"
  cmd << " udp-port #{opts[:port]}"
  cmd
end