class Puppet::Util::NetworkDevice::Cisco::Device

Constants

IF

Attributes

enable_password[RW]

Public Class Methods

new(url, options = {}) click to toggle source
Calls superclass method Puppet::Util::NetworkDevice::Base.new
# File lib/puppet/util/network_device/cisco/device.rb, line 15
def initialize(url, options = {})
  super(url)
  @enable_password = options[:enable_password] || parse_enable(@url.query)
  transport.default_prompt = /[#>]\s?\z/
end

Public Instance Methods

canonalize_ifname(interface) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 86
def canonalize_ifname(interface)
  IF.each do |k,ifnames|
    if found = ifnames.find { |ifname| interface =~ /^#{ifname}\s*\d/ }
      found = /^#{found}(.+)\Z/.match(interface)
      return "#{k.to_s}#{found[1]}".gsub(/\s+/,'')
    end
  end
  interface
end
command(cmd=nil) { |self| ... } click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 25
def command(cmd=nil)
  Puppet.debug("command #{cmd}")
  transport.connect
  login
  transport.command("terminal length 0") do |out|
    enable if out =~ />\s?\z/
  end
  find_capabilities
  out = execute(cmd) if cmd
  yield self if block_given?
  transport.close
  out
end
enable() click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 53
def enable
  raise "Can't issue \"enable\" to enter privileged, no enable password set" unless enable_password
  transport.command("enable", :prompt => /^Password:/)
  transport.command(enable_password)
end
execute(cmd) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 39
def execute(cmd)
  transport.command(cmd)
end
facts() click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 96
def facts
  @facts ||= Puppet::Util::NetworkDevice::Cisco::Facts.new(transport)
  facts = {}
  command do |ng|
    facts = @facts.retrieve
  end
  facts
end
find_capabilities() click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 63
def find_capabilities
  out = transport.command("sh vlan brief")
  lines = out.split("\n")
  lines.shift; lines.pop

  @support_vlan_brief = ! (lines.first =~ /^%/)
end
interface(name) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 105
def interface(name)
  ifname = canonalize_ifname(name)
  interface = parse_interface(ifname)
  return { :ensure => :absent } if interface.empty?
  interface.merge!(parse_trunking(ifname))
  interface.merge!(parse_interface_config(ifname))
end
login() click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 43
def login
  return if transport.handles_login?
  if @url.user != ''
    transport.command(@url.user, :prompt => /^Password:/)
  else
    transport.expect(/^Password:/)
  end
  transport.command(@url.password)
end
new_interface(name) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 113
def new_interface(name)
  Puppet::Util::NetworkDevice::Cisco::Interface.new(canonalize_ifname(name), transport)
end
parse_enable(query) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 21
def parse_enable(query)
  return $1 if query =~ /enable=(.*)/
end
parse_interface(name) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 117
def parse_interface(name)
  resource = {}
  out = transport.command("sh interface #{name}")
  lines = out.split("\n")
  lines.shift; lines.pop
  lines.each do |l|
    if l =~ /#{name} is (.+), line protocol is /
      resource[:ensure] = ($1 == 'up' ? :present : :absent);
    end
    if l =~ /Auto Speed \(.+\),/ or l =~ /Auto Speed ,/ or l =~ /Auto-speed/
      resource[:speed] = :auto
    end
    if l =~ /, (.+)Mb\/s/
      resource[:speed] = $1
    end
    if l =~ /\s+Auto-duplex \((.{4})\),/
      resource[:duplex] = :auto
    end
    if l =~ /\s+(.+)-duplex/
      resource[:duplex] = $1 == "Auto" ? :auto : $1.downcase.to_sym
    end
    if l =~ /Description: (.+)/
      resource[:description] = $1
    end
  end
  resource
end
parse_interface_config(name) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 145
def parse_interface_config(name)
  resource = Hash.new { |hash, key| hash[key] = Array.new ; }
  out = transport.command("sh running-config interface #{name} | begin interface")
  lines = out.split("\n")
  lines.shift; lines.pop
  lines.each do |l|
    if l =~ /ip address (#{IP}) (#{IP})\s+secondary\s*$/
      resource[:ipaddress] << [prefix_length(IPAddr.new($2)), IPAddr.new($1), 'secondary']
    end
    if l =~ /ip address (#{IP}) (#{IP})\s*$/
      resource[:ipaddress] << [prefix_length(IPAddr.new($2)), IPAddr.new($1), nil]
    end
    if l =~ /ipv6 address (#{IP})\/(\d+) (eui-64|link-local)/
      resource[:ipaddress] << [$2.to_i, IPAddr.new($1), $3]
    end
    if l =~ /channel-group\s+(\d+)/
      resource[:etherchannel] = $1
    end
  end
  resource
end
parse_trunking(interface) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 214
def parse_trunking(interface)
  trunking = {}
  out = transport.command("sh interface #{interface} switchport")
  lines = out.split("\n")
  lines.shift; lines.pop
  lines.each do |l|
    case l
    when /^Administrative mode:\s+(.*)$/
      case $1
      when "trunk"
        trunking[:mode] = :trunk
      when "static access"
        trunking[:mode] = :access
      else
        raise "Unknown switchport mode: #{$1} for #{interface}"
      end
    when /^Administrative Trunking Encapsulation:\s+(.*)$/
      case $1
      when "dot1q","isl"
        trunking[:encapsulation] = $1.to_sym if trunking[:mode] == :trunk
      else
        raise "Unknown switchport encapsulation: #{$1} for #{interface}"
      end
    when /^Access Mode VLAN:\s+(.*) \(\(Inactive\)\)$/
      # nothing
    when /^Access Mode VLAN:\s+(.*) \(.*\)$/
      trunking[:native_vlan] = $1 if trunking[:mode] == :access
    when /^Trunking VLANs Enabled:\s+(.*)$/
      next if trunking[:mode] == :access
      vlans = $1
      trunking[:allowed_trunk_vlans] = case vlans
      when /all/
        :all
      when /none/
        :none
      else
        vlans
      end
    end
  end
  trunking
end
parse_vlans() click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 167
def parse_vlans
  vlans = {}
  out = transport.command(support_vlan_brief? ? "sh vlan brief" : "sh vlan-switch brief")
  lines = out.split("\n")
  lines.shift; lines.shift; lines.shift; lines.pop
  vlan = nil
  lines.each do |l|
    case l
          # vlan    name    status
    when /^(\d+)\s+(\w+)\s+(\w+)\s+([a-zA-Z0-9,\/. ]+)\s*$/
      vlan = { :name => $1, :description => $2, :status => $3, :interfaces => [] }
      if $4.strip.length > 0
        vlan[:interfaces] = $4.strip.split(/\s*,\s*/).map{ |ifn| canonalize_ifname(ifn) }
      end
      vlans[vlan[:name]] = vlan
    when /^\s+([a-zA-Z0-9,\/. ]+)\s*$/
      raise "invalid sh vlan summary output" unless vlan
      if $1.strip.length > 0
        vlan[:interfaces] += $1.strip.split(/\s*,\s*/).map{ |ifn| canonalize_ifname(ifn) }
      end
    else
    end
  end
  vlans
end
support_vlan_brief?() click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 59
def support_vlan_brief?
  !! @support_vlan_brief
end
update_vlan(id, is = {}, should = {}) click to toggle source
# File lib/puppet/util/network_device/cisco/device.rb, line 193
def update_vlan(id, is = {}, should = {})
  if should[:ensure] == :absent
    Puppet.info "Removing #{id} from device vlan"
    transport.command("conf t")
    transport.command("no vlan #{id}")
    transport.command("exit")
    return
  end

  # We're creating or updating an entry
  transport.command("conf t")
  transport.command("vlan #{id}")
  [is.keys, should.keys].flatten.uniq.each do |property|
    Puppet.debug("trying property: #{property}: #{should[property]}")
    next if property != :description
    transport.command("name #{should[property]}")
  end
  transport.command("exit")
  transport.command("exit")
end