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