Class: Ipswitch::Ssh

Inherits:
Object
  • Object
show all
Defined in:
lib/ipswitch/ssh.rb

Instance Method Summary collapse

Constructor Details

#initialize(host, options = {}) ⇒ Ssh

TODO

  • sudo support

  • proxy support

  • password

  • specify id_dsa/rsa



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/ipswitch/ssh.rb', line 13

def initialize(host, options={})
  @host = host
  @options = options

  begin
    @ssh = Net::SSH.start(@host, @options[:user], { port: @options[:port] })

    # if block is given, execute everything, then close connection
    if block_given?
      yield(self)
      @ssh.close
    end

  rescue SocketError => e
    abort "Could not connect to #{@options[:user]}@#{@host}: #{e.message}"
  end
end

Instance Method Details

#arping(ip) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/ipswitch/ssh.rb', line 97

def arping(ip)
  unless exec('which arping', safe: true)[:exit_code] == 0
    say 'arping not installed, skipping'
    return false
  end

  arping = "arping -B -S #{ip}"
  arping << " -i #{@options[:interface]}" if @options[:interface]
  arping << " -c #{@options[:count]}"     if @options[:count]
  arping << " |tail -n1"

  say 'Running arpping'
  say exec(arping)[:stdout].chomp
end

#broadcast(ip) ⇒ Object



116
117
118
119
120
121
122
123
# File 'lib/ipswitch/ssh.rb', line 116

def broadcast(ip)
  case @options[:family]
  when 'inet'
    arping(ip)
  when 'inet6'
    rdisc6(ip)
  end
end

#exec(command, options = {}) ⇒ Object



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
# File 'lib/ipswitch/ssh.rb', line 31

def exec(command, options={})
  options = { safe: false }.merge(options)

  stdout = ''
  stderr = ''
  exit_code = nil
  exit_signal = nil

  say(command, debug: true) if @options[:debug]

  # if this is a save command, execute it even when in dryrun mode
  if @options[:dryrun] and not options[:safe]
    return { exit_code: 0, stdout: 'dry run -- no output' }
  end

  @ssh.open_channel do |channel|
    channel.exec command do |ch, success|
      abort 'Could not execute command (ssh.channel.exec)' unless success

      channel.on_data { |ch, data| stdout << data }
      channel.on_extended_data { |ch, type, data| stderr << data }
      channel.on_request('exit-status') { |ch, data| exit_code = data.read_long }
      channel.on_request('exit-signal') { |ch, data| exit_signal = data.read_long }
    end
  end

  @ssh.loop
  { stdout: stdout, stderr: stderr, exit_code: exit_code, exit_signal: exit_signal }
end

#get_ipObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/ipswitch/ssh.rb', line 82

def get_ip
  say "Getting IP for interface #{@options[:interface]}"
  ip_info = exec("ip -oneline -family #{@options[:family]} addr list dev #{@options[:interface]}", safe: true)

  begin
    ip = IPAddress(ip_info[:stdout].match(/.*#{@options[:family]}\s(\S+)\s.*/)[1])
  rescue => e
    say "could not get IP address: #{e.message}"
    return false
  end

  say "Found IP #{ip.to_string}"
  ip
end

#ip(command, ip) ⇒ Object



61
62
63
64
65
66
67
68
69
70
# File 'lib/ipswitch/ssh.rb', line 61

def ip(command, ip)
  ret = exec("ip addr #{command} #{ip.to_string} dev #{@options[:interface]}")[:exit_code]

  unless ret == 0
    say "Unable to set IP to #{ip.to_string} (interface: #{@options[:interface]})"
    return false
  end

  true
end

#ip_add(ip) ⇒ Object



72
73
74
75
# File 'lib/ipswitch/ssh.rb', line 72

def ip_add(ip)
  say "Adding IP address #{ip.to_string} to interface #{@options[:interface]}"
  ip('add', ip)
end

#ip_del(ip) ⇒ Object



77
78
79
80
# File 'lib/ipswitch/ssh.rb', line 77

def ip_del(ip)
  say "Removing IP address #{ip.to_string} from interface #{@options[:interface]}"
  ip('del', ip)
end

#rdisc6(ip) ⇒ Object



112
113
114
# File 'lib/ipswitch/ssh.rb', line 112

def rdisc6(ip)
  # TODO
end