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.

Returns:



193
194
195
196
197
198
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 193

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].

Returns:

  • (Array)

    of [Model::ForwardedPort] objects



77
78
79
80
81
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 77

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)


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

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].

Returns:



150
151
152
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 150

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.

Returns:

  • (Array)

    of [Model::ForwardedPort] objects



112
113
114
115
116
117
118
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 112

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.

Returns:

  • (Vagrant::Util::Subprocess::Result)


67
68
69
70
71
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 67

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).

Returns:



124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 124

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].



142
143
144
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 142

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.



157
158
159
160
161
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 157

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].

Returns:

  • (Array)

    of [Model::ForwardedPort] objects



86
87
88
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 86

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.

Returns:

  • (Integer)

    , or nil if not found.



104
105
106
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 104

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.

Returns:

  • (Array)

    of [Model::ForwardedPort] objects



94
95
96
97
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 94

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].

Returns:

  • (Array)

    of [String]



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/vagrant-skytap/hosts/common/cap/ssh_tunnel.rb', line 169

def ssh_args(fp, machine)
  ssh_info = machine.ssh_info
  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.

Returns:

  • (Vagrant::Util::Subprocess::Result)


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

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