Class: Puppet::Util::NetworkDevice::Transport::Ssh

Inherits:
Base
  • Object
show all
Defined in:
lib/vendor/puppet/util/network_device/transport/ssh.rb

Overview

This is an adaptation/simplification of gem net-ssh-telnet, which aims to have a sane interface to Net::SSH. Credits goes to net-ssh-telnet authors

Instance Attribute Summary collapse

Attributes inherited from Base

#default_prompt, #host, #password, #port, #timeout, #user

Instance Method Summary collapse

Methods inherited from Base

#command

Constructor Details

#initializeSsh

Returns a new instance of Ssh.



12
13
14
15
16
17
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 12

def initialize
  super
  unless Puppet.features.ssh?
    raise 'Connecting with ssh to a network device requires the \'net/ssh\' ruby library'
  end
end

Instance Attribute Details

#bufObject

Returns the value of attribute buf.



10
11
12
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 10

def buf
  @buf
end

#channelObject

Returns the value of attribute channel.



10
11
12
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 10

def channel
  @channel
end

#sshObject

Returns the value of attribute ssh.



10
11
12
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 10

def ssh
  @ssh
end

#verboseObject

Returns the value of attribute verbose.



10
11
12
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 10

def verbose
  @verbose
end

Instance Method Details

#closeObject



69
70
71
72
73
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 69

def close
  @channel.close if @channel
  @channel = nil
  @ssh.close if @ssh
end

#connect(&block) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 27

def connect(&block)
  @output = []
  @channel_data = ""

  begin
    Puppet.debug("connecting to #{host} as #{user}")
    @ssh = Net::SSH.start(host, user, :port => port, :password => password, :timeout => timeout)
  rescue TimeoutError
    raise TimeoutError, "timed out while opening an ssh connection to the host"
  rescue Net::SSH::AuthenticationFailed
    raise Puppet::Error, "SSH authentication failure connecting to #{host} as #{user}"
  rescue Net::SSH::Exception => detail
    raise Puppet::Error, "SSH connection failure to #{host}"
  end

  @buf = ""
  @eof = false
  @channel = nil
  @ssh.open_channel do |channel|
    channel.request_pty { |ch,success| raise "failed to open pty" unless success }

    channel.send_channel_request("shell") do |ch, success|
      raise "failed to open ssh shell channel" unless success

      ch.on_data { |ch,data| @buf << data }
      ch.on_extended_data { |ch,type,data|  @buf << data if type == 1 }
      ch.on_close { @eof = true }

      @channel = ch
      expect(default_prompt, &block)
      # this is a little bit unorthodox, we're trying to escape
      # the ssh loop there while still having the ssh connection up
      # otherwise we wouldn't be able to return ssh stdout/stderr
      # for a given call of command.
      return
    end

  end
  @ssh.loop

end

#eof?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 23

def eof?
  !! @eof
end

#expect(prompt) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 75

def expect(prompt)
  line = ''
  sock = @ssh.transport.socket

  while not @eof
    break if line =~ prompt and @buf == ''
    break if sock.closed?

    IO::select([sock], [sock], nil, nil)

    process_ssh

    # at this point we have accumulated some data in @buf
    # or the channel has been closed
    if @buf != ""
      line += @buf.gsub(/\r\n/no, "\n")
      @buf = ''
      yield line if block_given?
    elsif @eof
      # channel has been closed
      break if line =~ prompt
      if line == ''
        line = nil
        yield nil if block_given?
      end
      break
    end
  end
  Puppet.debug("ssh: expected #{line}") if @verbose
  line
end

#handles_login?Boolean

Returns:

  • (Boolean)


19
20
21
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 19

def handles_login?
  true
end

#process_sshObject



112
113
114
115
116
117
118
119
120
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 112

def process_ssh
  while @buf == "" and not eof?
    begin
      @channel.connection.process(0.1)
    rescue IOError
      @eof = true
    end
  end
end

#send(line) ⇒ Object



107
108
109
110
# File 'lib/vendor/puppet/util/network_device/transport/ssh.rb', line 107

def send(line)
  Puppet.debug("ssh: send #{line}") if @verbose
  @channel.send_data(line + "\n")
end