Class: ChefMetalLXC::LXCTransport

Inherits:
ChefMetal::Transport
  • Object
show all
Includes:
Chef::Mixin::ShellOut
Defined in:
lib/chef_metal_lxc/lxc_transport.rb

Defined Under Namespace

Classes: LXCExecuteResult

Constant Summary collapse

@@active_transports =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, lxc_path, options = {}) ⇒ LXCTransport

Returns a new instance of LXCTransport.



24
25
26
27
28
29
30
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 24

def initialize(name, lxc_path, options={})
  @options = options
  @name = name
  @lxc_path = lxc_path
  @port_forwards = []
  @@active_transports << self
end

Instance Attribute Details

#lxc_pathObject (readonly)

Returns the value of attribute lxc_path.



20
21
22
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 20

def lxc_path
  @lxc_path
end

#nameObject (readonly)

Returns the value of attribute name.



20
21
22
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 20

def name
  @name
end

#optionsObject (readonly)

Returns the value of attribute options.



20
21
22
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 20

def options
  @options
end

Class Method Details

.disconnect_active_transportsObject



136
137
138
139
140
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 136

def self.disconnect_active_transports
  @@active_transports.to_a.dup.each do |transport|
    transport.disconnect
  end
end

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


127
128
129
130
131
132
133
134
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 127

def available?
  begin
    execute('pwd')
    true
  rescue Exception =>e
    false
  end
end

#containerObject



32
33
34
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 32

def container
  @container ||= LXC::Container.new(name, lxc_path)
end

#container_path(path) ⇒ Object



40
41
42
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 40

def container_path(path)
  File.join(rootfs, path)
end

#disconnectObject



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 112

def disconnect
  @port_forwards.each do |pid, thread, channel|
    begin
      Process.kill('KILL', pid)
    rescue
    end
    begin
      thread.kill
    rescue
    end
  end
  @port_forwards = []
  @@active_transports.delete(self)
end

#download_file(path, local_path) ⇒ Object



97
98
99
100
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 97

def download_file(path, local_path)
  Chef::Log.debug("Copying file #{path} from #{name} to local #{local_path}")
  FileUtils.cp_r(container_path(path), local_path)
end

#execute(command) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 44

def execute(command)
  Chef::Log.info("Executing #{command} on #{name}")
  container.execute do
    begin
      out = shell_out(command)
      LXCExecuteResult.new(out.stdout,out.stderr, out.exitstatus)
    rescue Exception => e
      LXCExecuteResult.new('', e.message, -1)
    end
  end
end

#make_url_available_to_remote(local_url) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 56

def make_url_available_to_remote(local_url)
  uri = URI(local_url)
  host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
  if host == '127.0.0.1' || host == '[::1]'

    Chef::Log.debug("Forwarding container port #{uri.port} to local port #{uri.port}")
    # Create the channel that will let the container and the host talk to each other
    channel = LXC::Extra::Channel.new

    # Start the container side of the proxy, listening for client connections
    pid = container.attach do
      begin
        server = TCPServer.new('127.0.0.1', uri.port)
        proxy = LXC::Extra::ProxyClientSide.new(channel, server)
        proxy.start
      rescue
        Chef::Log.error("ERROR in proxy (container side): #{$!}\n#{$!.backtrace.join("\n")}")
        raise
      end
    end

    # Start the host side of the proxy, which contacts the real server
    thread = Thread.new do
      proxy = LXC::Extra::ProxyServerSide.new(channel) do
        TCPSocket.new('127.0.0.1', uri.port)
      end
      proxy.start
    end

    @port_forwards << [ pid, thread, channel ]

  end
  local_url
end

#read_file(path) ⇒ Object



91
92
93
94
95
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 91

def read_file(path)
  if File.exists?(container_path(path))
    File.read(container_path(path))
  end
end

#rootfsObject



36
37
38
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 36

def rootfs
  container.config_item('lxc.rootfs')
end

#upload_file(local_path, path) ⇒ Object



108
109
110
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 108

def upload_file(local_path, path)
  FileUtils.cp_r(local_path, container_path(path))
end

#write_file(path, content) ⇒ Object



102
103
104
105
106
# File 'lib/chef_metal_lxc/lxc_transport.rb', line 102

def write_file(path, content)
  File.open(container_path(path), 'w') do |f|
    f.write(content)
  end
end