Class: LinuxContainer
- Inherits:
-
Object
- Object
- LinuxContainer
- Defined in:
- lib/linux_container.rb
Defined Under Namespace
Classes: ProcessFailed
Instance Attribute Summary collapse
- #ip ⇒ Object
-
#name ⇒ Object
Returns the value of attribute name.
-
#ssh_key_path ⇒ Object
Returns the value of attribute ssh_key_path.
-
#username ⇒ Object
Returns the value of attribute username.
Class Method Summary collapse
Instance Method Summary collapse
- #bg_execute(*cmd) ⇒ Object
- #clone_from(from, *args) ⇒ Object
-
#create(config = {}) ⇒ Object
template, hostid, userdata, auth-key, arch, release.
- #dir(subdir = nil) ⇒ Object
- #execute(*cmd) ⇒ Object
-
#initialize(params = {}) ⇒ LinuxContainer
constructor
A new instance of LinuxContainer.
- #lxc_execute(cmd, *args) ⇒ Object
- #parent_container ⇒ Object
- #running? ⇒ Boolean
- #scp_from(srcpath, dstpath, *args) ⇒ Object
- #scp_to(srcpath, dstpath, *args) ⇒ Object
- #ssh(cmd, &bl) ⇒ Object
- #ssh_args ⇒ Object
- #sshable? ⇒ Boolean
- #start_ephemeral(config = {}) ⇒ Object
- #state ⇒ Object
- #wait_for(timeout = 300, interval = 1, &block) ⇒ Object
Constructor Details
#initialize(params = {}) ⇒ LinuxContainer
Returns a new instance of LinuxContainer.
20 21 22 23 |
# File 'lib/linux_container.rb', line 20 def initialize(params={}) params.each {|k,v| instance_variable_set "@#{k}", v } @username ||= 'ubuntu' end |
Instance Attribute Details
#ip ⇒ Object
30 31 32 |
# File 'lib/linux_container.rb', line 30 def ip @ip ||= self.class.get_ip_for(name) end |
#name ⇒ Object
Returns the value of attribute name.
7 8 9 |
# File 'lib/linux_container.rb', line 7 def name @name end |
#ssh_key_path ⇒ Object
Returns the value of attribute ssh_key_path.
7 8 9 |
# File 'lib/linux_container.rb', line 7 def ssh_key_path @ssh_key_path end |
#username ⇒ Object
Returns the value of attribute username.
7 8 9 |
# File 'lib/linux_container.rb', line 7 def username @username end |
Class Method Details
.all ⇒ Object
10 11 12 |
# File 'lib/linux_container.rb', line 10 def self.all `#{sudo_if_needed} lxc-ls -1`.lines.map(&:strip).uniq.map {|cname| new(name: cname) } end |
.get_ip_for(name) ⇒ Object
156 157 158 159 160 161 162 163 |
# File 'lib/linux_container.rb', line 156 def self.get_ip_for(name) fn = ['/var/lib/misc/dnsmasq.lxcbr0.leases', '/var/lib/misc/dnsmasq.leases'].detect {|f| File.readable?(f) } File.read(fn).each_line do |line| (,macaddr,ip,hostname,misc) = line.split(' ') return ip if hostname == name end nil end |
.sudo_if_needed ⇒ Object
165 166 167 |
# File 'lib/linux_container.rb', line 165 def self.sudo_if_needed 'sudo' unless Process.uid == 0 end |
.version ⇒ Object
14 15 16 17 18 |
# File 'lib/linux_container.rb', line 14 def self.version @version ||= if `lxc-version` =~ /version: (\d+\.\d+)\./i $1 end end |
Instance Method Details
#bg_execute(*cmd) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/linux_container.rb', line 143 def bg_execute(*cmd) logfile_path = "/tmp/lxc_ephemeral_#{Time.now.to_i.to_s(36)}#{$$}#{rand(0x100000000).to_s(36)}.log" cmdstring = "#{self.class.sudo_if_needed} #{cmd.shift} #{Shellwords.join(cmd)} >>#{logfile_path} 2>>#{logfile_path}" pid = spawn(cmdstring, pgroup: true) raise ProcessFailed.new("command failed: #{cmdstring.inspect}") unless pid > 0 Thread.abort_on_exception = true Thread.new do Process.waitpid pid raise ProcessFailed.new("command failed: #{cmdstring.inspect}") unless $? == 0 end logfile_path end |
#clone_from(from, *args) ⇒ Object
43 44 45 46 |
# File 'lib/linux_container.rb', line 43 def clone_from(from, *args) fromname = self.class === from ? from.name : from lxc_execute('clone', '-o',fromname, *args) end |
#create(config = {}) ⇒ Object
template, hostid, userdata, auth-key, arch, release
34 35 36 37 |
# File 'lib/linux_container.rb', line 34 def create(config={}) # template, hostid, userdata, auth-key, arch, release args = (ssh_key_path ? {'auth-key' => "#{ssh_key_path}.pub"} : {}).merge(config).map {|k, v| "--#{k}=#{v}" } lxc_execute('create', '-t', config.delete(:template) || 'ubuntu-cloud', '--', *args) end |
#dir(subdir = nil) ⇒ Object
102 103 104 |
# File 'lib/linux_container.rb', line 102 def dir(subdir=nil) "/var/lib/lxc/#{name}/rootfs/#{subdir}" end |
#execute(*cmd) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/linux_container.rb', line 128 def execute(*cmd) cmdstring = "#{self.class.sudo_if_needed} #{cmd.shift} #{Shellwords.join(cmd)}" result = '' IO.popen("#{cmdstring} 2>&1", 'r') do |io| io.each_line do |line| yield line if block_given? result << line end end raise "command failed: #{cmdstring.inspect}\n#{result}" unless $? == 0 result end |
#lxc_execute(cmd, *args) ⇒ Object
124 125 126 |
# File 'lib/linux_container.rb', line 124 def lxc_execute(cmd, *args) execute("lxc-#{cmd}", '-n', name, *args) end |
#parent_container ⇒ Object
48 49 50 51 |
# File 'lib/linux_container.rb', line 48 def parent_container n = name.dup self.class.new(name: n) if n.sub!(/(-temp)?-[0-9A-Za-z_\-]+$/, '') end |
#running? ⇒ Boolean
98 99 100 |
# File 'lib/linux_container.rb', line 98 def running? state == 'RUNNING' end |
#scp_from(srcpath, dstpath, *args) ⇒ Object
82 83 84 |
# File 'lib/linux_container.rb', line 82 def scp_from(srcpath, dstpath, *args) execute('scp', *args, *ssh_args, "#{username}@#{ip}:#{srcpath}", dstpath) end |
#scp_to(srcpath, dstpath, *args) ⇒ Object
78 79 80 |
# File 'lib/linux_container.rb', line 78 def scp_to(srcpath, dstpath, *args) execute('scp', *args, *ssh_args, srcpath, "#{username}@#{ip}:#{dstpath}") end |
#ssh(cmd, &bl) ⇒ Object
74 75 76 |
# File 'lib/linux_container.rb', line 74 def ssh(cmd, &bl) execute('ssh', *ssh_args, "#{username}@#{ip}", cmd, &bl) end |
#ssh_args ⇒ Object
86 87 88 89 90 91 |
# File 'lib/linux_container.rb', line 86 def ssh_args raise "cannot ssh without ip" unless ip args = ['-o','StrictHostKeyChecking=no','-o','UserKnownHostsFile=/dev/null','-q'] args.push('-i', ssh_key_path) if ssh_key_path args end |
#sshable? ⇒ Boolean
94 95 96 |
# File 'lib/linux_container.rb', line 94 def sshable? ssh('true') rescue false end |
#start_ephemeral(config = {}) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/linux_container.rb', line 53 def start_ephemeral(config={}) argshash = {'orig' => name, 'user' => username}.merge!(config) args = [] if self.class.version == '0.8' # ubuntu quantal and older argshash['union-type'] ||= 'aufs' args.push '-U', argshash.delete('union-type') else # ubuntu raring and newer argshash['union-type'] ||= 'overlayfs' args << '-d' end args.push *argshash.map {|k, v| "--#{k}=#{v}" } logfile_path = bg_execute('lxc-start-ephemeral', *args) newname = nil while newname.nil? sleep 1 newname = $1 || $2 if File.read(logfile_path) =~ /^(.*) is running|lxc-console -n (.*)$/ end self.class.new(name: newname, ssh_key_path: ssh_key_path, username: username) end |
#state ⇒ Object
25 26 27 28 |
# File 'lib/linux_container.rb', line 25 def state res = `#{self.class.sudo_if_needed} lxc-info -n #{Shellwords.escape name} -s 2>&1` res.chomp.split(':').last.to_s.strip end |
#wait_for(timeout = 300, interval = 1, &block) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/linux_container.rb', line 106 def wait_for(timeout=300, interval=1, &block) Timeout.timeout(timeout) do duration = 0 start = Time.now until instance_eval(&block) || duration > timeout sleep(interval.to_f) duration = Time.now - start end if duration > timeout false else duration end end end |