Class: Delayed::SshRemoteWorker

Inherits:
Object
  • Object
show all
Defined in:
lib/delayed/ssh_remote_worker.rb,
lib/delayed/ssh_remote_worker/railtie.rb

Defined Under Namespace

Classes: Railtie

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ SshRemoteWorker

Returns a new instance of SshRemoteWorker.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/delayed/ssh_remote_worker.rb', line 16

def initialize(config)
  @config              = Hash[config.map { |k, v| [ k.to_sym, v ] }]
  @debug               = !!@config[:ssh_debug]

  @remote_ssh_username = @config[:ssh_username]
  @remote_ssh_hostname = @config[:ssh_hostname]
  @remote_ssh_port     = @config[:ssh_port].to_i
  @remote_ssh_port     = 22 if remote_ssh_port <= 0

  @remote_db_hostname  = @config[:host].to_s.strip
  @remote_db_hostname  = "localhost" if remote_db_hostname == ""
  @remote_db_port      = @config[:port].to_i
  @remote_db_port      = default_port_number(@config[:adapter]) if remote_db_port <= 0

  @local_db_hostname = "127.0.0.1"
  @local_db_port     = nil
end

Instance Attribute Details

#childObject (readonly)

Returns the value of attribute child.



13
14
15
# File 'lib/delayed/ssh_remote_worker.rb', line 13

def child
  @child
end

#configObject (readonly)

Returns the value of attribute config.



14
15
16
# File 'lib/delayed/ssh_remote_worker.rb', line 14

def config
  @config
end

#gateway_in_rdObject (readonly)

Returns the value of attribute gateway_in_rd.



11
12
13
# File 'lib/delayed/ssh_remote_worker.rb', line 11

def gateway_in_rd
  @gateway_in_rd
end

#gateway_in_wrObject (readonly)

Returns the value of attribute gateway_in_wr.



11
12
13
# File 'lib/delayed/ssh_remote_worker.rb', line 11

def gateway_in_wr
  @gateway_in_wr
end

#gateway_out_rdObject (readonly)

Returns the value of attribute gateway_out_rd.



12
13
14
# File 'lib/delayed/ssh_remote_worker.rb', line 12

def gateway_out_rd
  @gateway_out_rd
end

#gateway_out_wrObject (readonly)

Returns the value of attribute gateway_out_wr.



12
13
14
# File 'lib/delayed/ssh_remote_worker.rb', line 12

def gateway_out_wr
  @gateway_out_wr
end

#gateway_portObject (readonly)

Returns the value of attribute gateway_port.



10
11
12
# File 'lib/delayed/ssh_remote_worker.rb', line 10

def gateway_port
  @gateway_port
end

#gateway_sshObject (readonly)

Returns the value of attribute gateway_ssh.



10
11
12
# File 'lib/delayed/ssh_remote_worker.rb', line 10

def gateway_ssh
  @gateway_ssh
end

#local_db_hostnameObject (readonly)

Returns the value of attribute local_db_hostname.



9
10
11
# File 'lib/delayed/ssh_remote_worker.rb', line 9

def local_db_hostname
  @local_db_hostname
end

#local_db_portObject (readonly)

Returns the value of attribute local_db_port.



9
10
11
# File 'lib/delayed/ssh_remote_worker.rb', line 9

def local_db_port
  @local_db_port
end

#remote_db_hostnameObject (readonly)

Returns the value of attribute remote_db_hostname.



8
9
10
# File 'lib/delayed/ssh_remote_worker.rb', line 8

def remote_db_hostname
  @remote_db_hostname
end

#remote_db_portObject (readonly)

Returns the value of attribute remote_db_port.



8
9
10
# File 'lib/delayed/ssh_remote_worker.rb', line 8

def remote_db_port
  @remote_db_port
end

#remote_ssh_hostnameObject (readonly)

Returns the value of attribute remote_ssh_hostname.



7
8
9
# File 'lib/delayed/ssh_remote_worker.rb', line 7

def remote_ssh_hostname
  @remote_ssh_hostname
end

#remote_ssh_portObject (readonly)

Returns the value of attribute remote_ssh_port.



7
8
9
# File 'lib/delayed/ssh_remote_worker.rb', line 7

def remote_ssh_port
  @remote_ssh_port
end

#remote_ssh_usernameObject (readonly)

Returns the value of attribute remote_ssh_username.



7
8
9
# File 'lib/delayed/ssh_remote_worker.rb', line 7

def remote_ssh_username
  @remote_ssh_username
end

Instance Method Details

#connect_to_tunneled_databaseObject



75
76
77
78
79
80
81
82
83
84
# File 'lib/delayed/ssh_remote_worker.rb', line 75

def connect_to_tunneled_database
  # Load just ActiveRecord. Do this before any part of the native Rails project is loaded.
  require "active_record"

  # Connect to the remote Postgres database.
  ActiveRecord::Base.establish_connection(activerecord_config)

  # Log a simple query just to verify that we actually have a connection.
  debug "Connected to remote Postgres. Found #{ User.count } users in the remote database."
end

#create_port_tunnelObject



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
68
69
70
71
72
73
# File 'lib/delayed/ssh_remote_worker.rb', line 34

def create_port_tunnel
  # Create two pipes - one will be used to get the port number from the child
  # process, the other will be used to tell the child process when it's time
  # to exit.
  ( @gateway_in_rd  , @gateway_in_wr  ) = IO.pipe
  ( @gateway_out_rd , @gateway_out_wr ) = IO.pipe

  # The child process will establish the SSH connection to the database server.
  @child = fork {
    debug "CHILD: Tunneling to #{ remote_db_hostname }:#{ remote_db_port } on #{ remote_ssh_username }@#{ remote_ssh_hostname }:#{ remote_ssh_port }."

    @gateway_ssh  = Net::SSH::Gateway.new(remote_ssh_hostname, remote_ssh_username, port: remote_ssh_port)
    @gateway_port = gateway_ssh.open(remote_db_hostname, remote_db_port)

    debug "CHILD: Notifying parent process of gateway port number #{ gateway_port }."

    gateway_out_rd.close
    gateway_out_wr.write(gateway_port.to_s)
    gateway_out_wr.close

    debug "CHILD: Waiting for parent to close pipe."

    gateway_in_wr.close
    gateway_in_rd.read
    gateway_in_rd.close

    debug "CHILD: Parent closed pipe. Exiting."

    gateway_ssh.shutdown!
  }

  # Get the port number back from the child process once the SSH connection is established.
  debug "PARENT: Reading port number from child."
  gateway_out_wr.close
  @local_db_port = Integer(gateway_out_rd.read)
  gateway_out_rd.close

  # Log and proceed with the next task.
  debug "PARENT: Received port number #{ gateway_port } from child. Proceeding with execution."
end

#destroy_port_tunnelObject



86
87
88
89
90
91
92
# File 'lib/delayed/ssh_remote_worker.rb', line 86

def destroy_port_tunnel
  # Close the pipe with the gateway, indicating that it should close.
  debug "PARENT: Closing pipe with child to terminate gateway."
  gateway_in_wr.close
  gateway_in_rd.close
  Process.wait(child)
end