lib/dev-lxc/container.rb in dev-lxc-0.6.4 vs lib/dev-lxc/container.rb in dev-lxc-1.0.0
- old
+ new
@@ -1,44 +1,62 @@
module DevLXC
class Container < LXC::Container
+ def status
+ if self.defined?
+ state = self.state
+ ip_addresses = self.ip_addresses.join(" ") if self.state == :running
+ else
+ state = "not_created"
+ end
+ { 'name' => self.name, 'state' => state, 'ip_addresses' => ip_addresses }
+ end
+
def start
- raise "Container #{self.name} does not exist." unless self.defined?
- puts "Starting container #{self.name}"
+ unless self.defined?
+ puts "ERROR: Container '#{self.name}' does not exist."
+ exit 1
+ end
+ puts "Starting container '#{self.name}'"
super
wait(:running, 3)
- puts "Waiting for #{self.name} container's network"
+ puts "Waiting for '#{self.name}' container's network"
ips = nil
30.times do
ips = self.ip_addresses
break unless ips.empty?
sleep 1
end
- raise "Container #{self.name} network is not available." if ips.empty?
+ if ips.empty?
+ puts "ERROR: Container '#{self.name}' network is not available."
+ exit 1
+ end
end
def stop
- puts "Stopping container #{self.name}"
+ puts "Stopping container '#{self.name}'"
super
wait("STOPPED", 3)
end
def destroy
- return unless self.defined?
stop if running?
- puts "Destroying container #{self.name}"
- super
+ puts "Destroying container '#{self.name}'"
+ super if self.defined?
end
def sync_mounts(mounts)
existing_mounts = self.config_item("lxc.mount.entry")
unless existing_mounts.nil?
preserved_mounts = existing_mounts.delete_if { |m| m.end_with?("## dev-lxc ##") }
self.clear_config_item('lxc.mount.entries')
self.set_config_item("lxc.mount.entry", preserved_mounts)
end
mounts.each do |mount|
- raise "Mount source #{mount.split.first} does not exist." unless File.exists?(mount.split.first)
+ unless File.exists?(mount.split.first)
+ puts "ERROR: Mount source #{mount.split.first} does not exist."
+ exit 1
+ end
if ! preserved_mounts.nil? && preserved_mounts.any? { |m| m.start_with?("#{mount} ") }
puts "Skipping mount entry #{mount}, it already exists"
next
else
puts "Adding mount entry #{mount}"
@@ -47,24 +65,136 @@
end
self.save_config
end
def run_command(command)
- raise "Container #{self.name} must be running first" unless running?
- attach({:wait => true, :stdin => STDIN, :stdout => STDOUT, :stderr => STDERR}) do
+ unless running?
+ puts "ERROR: Container '#{self.name}' must be running first"
+ exit 1
+ end
+ attach_opts = { wait: true, env_policy: LXC::LXC_ATTACH_CLEAR_ENV, extra_env_vars: ['HOME=/root'] }
+ attach(attach_opts) do
LXC.run_command(command)
end
end
def install_package(package_path)
- raise "File #{package_path} does not exist in container #{self.name}" unless run_command("test -e #{package_path}") == 0
- puts "Installing #{package_path} in container #{self.name}"
+ unless run_command("test -e #{package_path}") == 0
+ puts "ERROR: File #{package_path} does not exist in container '#{self.name}'"
+ exit 1
+ end
+ puts "Installing #{package_path} in container '#{self.name}'"
case File.extname(package_path)
when ".deb"
install_command = "dpkg -D10 -i #{package_path}"
when ".rpm"
install_command = "rpm -Uvh #{package_path}"
end
run_command(install_command)
end
+
+ def install_chef_client(version=nil)
+ unless self.defined?
+ puts "ERROR: Container '#{self.name}' does not exist."
+ exit 1
+ end
+ unless running?
+ puts "ERROR: Container '#{self.name}' is not running"
+ exit 1
+ end
+ if self.ip_addresses.empty?
+ puts "ERROR: Container '#{self.name}' network is not available."
+ exit 1
+ end
+
+ require 'tempfile'
+
+ installed_version = nil
+ file = Tempfile.new('installed_chef_client_version')
+ begin
+ attach_opts = { wait: true, env_policy: LXC::LXC_ATTACH_CLEAR_ENV, extra_env_vars: ['HOME=/root'], stdout: file }
+ attach(attach_opts) do
+ puts `chef-client -v`
+ end
+ file.rewind
+ installed_version = Regexp.last_match[1] if file.read.match(/chef:\s*(\d+\.\d+\.\d+)/i)
+ ensure
+ file.close
+ file.unlink
+ end
+ if installed_version.nil? || ( ! version.nil? && ! installed_version.start_with?(version) )
+ require "net/https"
+ require "uri"
+
+ uri = URI.parse("https://www.chef.io/chef/install.sh")
+ http = Net::HTTP.new(uri.host, uri.port)
+ http.use_ssl = true
+
+ request = Net::HTTP::Get.new(uri.request_uri)
+
+ response = http.request(request)
+
+ file = Tempfile.new('install_sh', "#{config_item('lxc.rootfs')}/tmp")
+ file.write(response.body)
+ begin
+ version = 'latest' if version.nil?
+ install_command = "bash /tmp/#{File.basename(file.path)} -v #{version}"
+ run_command(install_command)
+ ensure
+ file.close
+ file.unlink
+ end
+ else
+ puts "Chef #{installed_version} is already installed."
+ end
+ end
+
+ def configure_chef_client(chef_server_url, validation_client_name, validation_key)
+ unless self.defined?
+ puts "ERROR: Container '#{self.name}' does not exist."
+ exit 1
+ end
+
+ puts "Configuring Chef Client in container '#{self.name}' for Chef Server '#{chef_server_url}'"
+
+ FileUtils.mkdir_p("#{config_item('lxc.rootfs')}/etc/chef")
+
+ client_rb = %Q(chef_server_url '#{chef_server_url}'
+validation_client_name '#{validation_client_name}'
+ssl_verify_mode :verify_none
+)
+ IO.write("#{config_item('lxc.rootfs')}/etc/chef/client.rb", client_rb)
+
+ begin
+ FileUtils.cp(validation_key, "#{config_item('lxc.rootfs')}/etc/chef/validation.pem")
+ rescue Errno::ENOENT
+ puts "ERROR: The validation key '#{validation_key}' does not exist."
+ end
+ end
+
+ def bootstrap_container(base_container_name=nil, version=nil, run_list=nil, chef_server_url, validation_client_name, validation_key)
+ puts "Bootstrapping container '#{self.name}' for Chef Server '#{chef_server_url}'"
+ if base_container_name
+ if self.defined?
+ puts "WARN: Skipping cloning. Container '#{self.name}' already exists"
+ else
+ puts "Cloning base container '#{base_container_name}' into container '#{self.name}'"
+ base_container = DevLXC::Container.new(base_container_name)
+ unless base_container.defined?
+ puts "ERROR: Base container '#{base_container_name} does not exist"
+ exit 1
+ end
+ base_container.clone(self.name, {:flags => LXC::LXC_CLONE_SNAPSHOT})
+ self.load_config
+ end
+ end
+ self.start unless self.running?
+ self.install_chef_client(version)
+ self.configure_chef_client(chef_server_url, validation_client_name, validation_key)
+
+ chef_client_command = "chef-client"
+ chef_client_command += " -r #{run_list}" if run_list
+ self.run_command(chef_client_command)
+ end
+
end
end