Class: VagrantPlugins::Skytap::HostCommon::Cap::SSHTunnel

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb

Class Method Summary collapse

Class Method Details

.autossh_environment_variables(fp, machine, monitoring_port = 0) ⇒ Hash

Gets the environment variables to be set when calling autossh.



172
173
174
175
176
177
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 172

def autossh_environment_variables(fp, machine, monitoring_port = 0)
  {
    "AUTOSSH_PIDFILE" => pidfile_path(fp, machine),
    "AUTOSSH_PORT" => monitoring_port,
  }
end

.clear_forwarded_ports(env, machine) ⇒ Array

Convenience method which kills all autossh processes for the given [Vagrant::Machine].



55
56
57
58
59
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 55

def clear_forwarded_ports(env, machine)
  get_fp_from_directory(machine.data_dir).each do |fp|
    kill_ssh_tunnel(env, fp, machine)
  end
end

.create_loggerObject

Raises:

  • (NotImplementedError)


23
24
25
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 23

def create_logger
  raise NotImplementedError
end

.fp_to_pidfile(fp) ⇒ String

Generate a pidfile name which encodes enough information to reconstruct the given [Model::ForwardedPort].



128
129
130
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 128

def fp_to_pidfile(fp)
  "#{fp.id}_#{fp.protocol}_#{fp.host_port}_#{fp.guest_port}.pid"
end

.get_fp_from_directory(dir) ⇒ Array

Gets forwarded ports by reading pidfiles in the given directory.



90
91
92
93
94
95
96
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 90

def get_fp_from_directory(dir)
  pidfiles = []
  Vagrant::Util::SafeChdir.safe_chdir(dir) do
    pidfiles = Dir.glob("*.pid")
  end
  pidfiles.collect{|pidfile| pidfile_to_fp(pidfile)}
end

.kill_ssh_tunnel(env, fp, machine) ⇒ Vagrant::Util::Subprocess::Result

Kill the autossh process for the given [Model::ForwardedPort] on the given [Vagrant::Machine]. autossh will kill the ssh child process before terminating.



45
46
47
48
49
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 45

def kill_ssh_tunnel(env, fp, machine)
  if pid = read_pid(pidfile_path(fp, machine))
    Vagrant::Util::Subprocess.execute("kill", pid.to_s)
  end
end

.machine_data_dirs(env) ⇒ Hash

Returns a mapping of machine names to their data_dirs (full paths).



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 102

def machine_data_dirs(env)
  h = {}
  env_path = env.local_data_path
  Vagrant::Util::SafeChdir.safe_chdir(env.local_data_path) do
    Dir.foreach("machines") do |machine_name|
      data_dir = "machines/#{machine_name}/skytap"
      if Dir.exist?(data_dir)
        h[machine_name] = env_path.join(data_dir)
      end
    end
  end
  h
end

.pidfile_path(fp, machine) ⇒ Model::ForwardedPort

Gets the full path to the pidfile for the given

Model::ForwardedPort

and [Vagrant::Machine].



120
121
122
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 120

def pidfile_path(fp, machine)
  machine.data_dir.join(fp_to_pidfile(fp)).to_s
end

.pidfile_to_fp(pidfile) ⇒ Model::ForwardedPort

Create a [Model::ForwardedPort] from a parsed pidfile name.



135
136
137
138
139
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 135

def pidfile_to_fp(pidfile)
  pidfile =~ /(\w*)_(\w*)_(\w*)_(\w*)\.pid/
  id, protocol, host_port, guest_port = $1, $2, $3, $4
  Model::ForwardedPort.new(id, host_port.to_i, guest_port.to_i, protocol: protocol)
end

.read_forwarded_ports(env, machine) ⇒ Array

The currently forwarded ports for this [Vagrant::Machine].



64
65
66
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 64

def read_forwarded_ports(env, machine)
  get_fp_from_directory(machine.data_dir)
end

.read_pid(pidfile_path) ⇒ Integer

Reads the process id (pid) from the given pidfile.



82
83
84
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 82

def read_pid(pidfile_path)
  File.read(pidfile_path).presence.try(:to_i) if File.exist?(pidfile_path)
end

.read_used_ports(env, machine) ⇒ Array

The currently forwarded ports for all other [Vagrant::Machine]s in this project.



72
73
74
75
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 72

def read_used_ports(env, machine)
  search_paths = machine_data_dirs(env).reject!{|k,v| k == machine.name.to_s}.values
  search_paths.collect{|path| get_fp_from_directory(path)}.flatten
end

.ssh_args(fp, machine) ⇒ Array

Gets the arguments to be passed to ssh for the given

Model::ForwardedPort

on the given [Vagrant::Machine].



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 147

def ssh_args(fp, machine)
  ssh_info = machine.ssh_info
  # TODO: tune these settings
  ssh_options = {
    "ServerAliveInterval" => 10,
    "ServerAliveCountMax" => 3,
    "StrictHostKeyChecking" => "no",
  }

  args = []
  args << "-q" # quiet
  args << "-N" # no remote command
  args << "-i" << machine.data_dir.join("private_key").to_s
  args << "-L" << "#{fp.host_port}:localhost:#{fp.guest_port}"
  ssh_options.each do |k, v|
    # options in ssh config file format
    args << "-o" << "#{k}=#{v}"
  end
  args << "#{ssh_info[:username]}@#{ssh_info[:host]}"
end

.start_ssh_tunnel(env, fp, machine) ⇒ Vagrant::Util::Subprocess::Result

Start an autossh process for the given [Model::ForwardedPort] on the given [Vagrant::Machine]. If autossh is not available on the host, an appropriate error message will be shown, asking the user to install it.



33
34
35
36
37
38
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 33

def start_ssh_tunnel(env, fp, machine)
  kill_ssh_tunnel(env, fp, machine)
  args = ssh_args(fp, machine)
  args << {env: autossh_environment_variables(fp, machine)}
  Vagrant::Util::Subprocess.execute("autossh", "-f", *args)
end