diff --git a/.kitchen.yml b/.kitchen.yml index 1470769..ae1a6ad 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -12,8 +12,28 @@ suites: provisioner: name: chef_solo run_list: - - 'recipe[lxc-test::default]' + - 'recipe[vagabond]' attributes: + lxc: + enable_daily_ppa: true + vagabond: + bases: + centos_5: + enabled: false + centos_6: + enabled: true + centos_7: + enabled: true + ubuntu_1204: + enabled: true + ubuntu_1404: + enabled: true + debian_6: + enabled: true + debian_7: + enabled: true + debian_8: + enabled: true - name: test-container provisioner: name: chef_zero diff --git a/Batali b/Batali index bc6c67c..4d7e458 100644 --- a/Batali +++ b/Batali @@ -2,6 +2,7 @@ Batali.define do source 'https://supermarket.chef.io' cookbook 'apt' cookbook 'yum-epel' + cookbook 'vagabond', git: 'git://github.com/chrisroberts/chef-vagabond', :ref => 'develop' cookbook 'lxc-test', path: './test/fixtures/cookbooks/lxc-test' metadata diff --git a/Gemfile b/Gemfile index 537d3a0..ad024cf 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,9 @@ source 'https://rubygems.org' gem 'kitchen-vagrant' +gem 'batali' gem 'batali-tk' -gem 'librarian-chef' if(ENV['DEATH_TO_OMNIBUS']) - gem 'vagrant', :git => 'https://github.com/mitchellh/vagrant', :tag => 'v1.7.2' + gem 'vagrant', :git => 'https://github.com/mitchellh/vagrant', :tag => 'v1.7.4' end diff --git a/attributes/default.rb b/attributes/default.rb index 4a92166..a052d29 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -15,9 +15,12 @@ default[:lxc][:proxy][:enable] = false -default[:lxc][:elecksee][:version_restriction] = '~> 1.1.2' +default[:lxc][:elecksee][:version_restriction] = '~> 2.0.2' default[:lxc][:elecksee][:action] = :install +default[:lxc][:default_config_enabled] = true +default[:lxc][:default_fstab_enabled] = false + default[:lxc][:default_config][:lxc_auto] = node[:lxc][:auto_start] default[:lxc][:default_config][:use_lxc_bridge] = node[:lxc][:use_bridge] default[:lxc][:default_config][:lxc_bridge] = node[:lxc][:bridge] @@ -34,6 +37,8 @@ default[:lxc][:user_locks] = %w(ubuntu) +default[:lxc][:enable_daily_ppa] = false +default[:lxc][:ppa_packages] = ['lxc', 'lxc-templates'] default[:lxc][:packages] = node.platform_family?('rhel') ? ['lxc', 'lxc-templates', 'lxc-libs', 'bridge-utils', 'libcgroup'] : ['lxc'] default[:lxc][:mirror] = 'http://archive.ubuntu.com/ubuntu' default[:lxc][:containers] = {} diff --git a/providers/config.rb b/providers/config.rb index a247df5..d581de2 100644 --- a/providers/config.rb +++ b/providers/config.rb @@ -1,81 +1,59 @@ require 'securerandom' def load_current_resource - require 'elecksee/lxc_file_config' - new_resource.utsname new_resource.container if new_resource.container - new_resource.utsname new_resource.name unless new_resource.utsname + if(new_resource.container) + new_resource.struct.lxc.utsname new_resource.container + end + unless(new_resource.struct[:lxc] && new_resource.struct[:lxc][:utsname]) + new_resource.struct.lxc.utsname new_resource.name + end @lxc = ::Lxc.new( - new_resource.utsname, + new_resource.struct.lxc.utsname, :base_dir => node[:lxc][:container_directory], :dnsmasq_lease_file => node[:lxc][:dnsmasq_lease_file] ) - new_resource.rootfs @lxc.rootfs.to_path unless new_resource.rootfs - - new_resource.default_bridge node[:lxc][:bridge] unless new_resource.default_bridge - new_resource.mount @lxc.path.join('fstab').to_path unless new_resource.mount - config = ::Lxc::FileConfig.new(@lxc.container_config) - if((new_resource.network.nil? || new_resource.network.empty?)) - if(config.network.empty?) - default_net = { - :type => :veth, - :link => new_resource.default_bridge, - :flags => :up, - :hwaddr => "00:16:3e#{SecureRandom.hex(3).gsub(/(..)/, ':\1')}" - } - else - default_net = config.network.first - default_net.delete(:ipv4) if default_net.has_key?(:ipv4) - default_net.merge!(:link => new_resource.default_bridge) - end - new_resource.network(default_net) - else - [new_resource.network].flatten.each_with_index do |net_hash, idx| - if(config.network[idx].nil? || config.network[idx][:hwaddr].nil?) - net_hash[:hwaddr] ||= "00:16:3e#{SecureRandom.hex(3).gsub(/(..)/, ':\1')}" - end - end - end - new_resource.cgroup( - Chef::Mixin::DeepMerge.merge( - Mash.new( - 'devices.deny' => 'a', - 'devices.allow' => [ - 'c *:* m', - 'b *:* m', - 'c 1:3 rwm', - 'c 1:5 rwm', - 'c 5:1 rwm', - 'c 5:0 rwm', - 'c 1:9 rwm', - 'c 1:8 rwm', - 'c 136:* rwm', - 'c 5:2 rwm', - 'c 254:0 rwm', - 'c 10:229 rwm', - 'c 10:200 rwm', - 'c 1:7 rwm', - 'c 10:228 rwm', - 'c 10:232 rwm' - ] - ), - new_resource.cgroup - ) - ) + @config = ::Lxc::FileConfig.new(@lxc.container_config.to_path) end action :create do _lxc = @lxc + _config = @config directory @lxc.path.to_path do action :create end + if(new_resource.resource_style.to_s == 'merge') + if(node[:lxc][:original_configs].nil?) + node.set[:lxc][:original_configs] = {} + end + if(node[:lxc][:original_configs][new_resource.name].nil?) + node.set[:lxc][:original_configs][new_resource.name] = _config.state_hash + end + _config.state._merge!(new_resource.struct) + else + _config.state = new_resource.struct + end + file "lxc update_config[#{new_resource.utsname}]" do path _lxc.container_config.to_path - content ::Lxc::FileConfig.generate_config(new_resource) + content _config.generate_content mode 0644 end end + +action :delete do + _lxc = @lxc + + if(node[:lxc][:original_configs] && node[:lxc][:original_configs][new_resource.name]) + node.set[:lxc][:original_configs][new_resource.name] = nil + end + + file "lxc delete_config[#{new_resource.name}]" do + path _lxc.container_config.to_path + action :delete + end +end diff --git a/providers/container.rb b/providers/container.rb index 0618e90..97dff8d 100644 --- a/providers/container.rb +++ b/providers/container.rb @@ -14,6 +14,14 @@ def load_current_resource if(new_resource.static_ip && new_resource.static_gateway.nil?) raise "Static gateway must be defined when static IP is provided (Container: #{new_resource.name})" end + + if(new_resource.default_config.nil?) + new_resource.default_config node[:lxc][:default_config_enabled] + end + if(new_resource.default_fstab.nil?) + new_resource.default_fstab node[:lxc][:default_fstab_enabled] + end + new_resource.default_bridge node[:lxc][:bridge] unless new_resource.default_bridge node.run_state[:lxc] ||= Mash.new node.run_state[:lxc][:meta] ||= Mash.new @@ -49,14 +57,6 @@ def load_current_resource end end - #### Create container configuration bits - if(new_resource.default_config) - lxc_config new_resource.name do - action :create - default_bridge new_resource.default_bridge - end - end - if(new_resource.default_fstab) lxc_fstab "proc[#{new_resource.name}]" do container new_resource.name @@ -75,6 +75,14 @@ def load_current_resource end end + #### Create container configuration bits + if(new_resource.default_config) + lxc_config new_resource.name do + action :create + default_bridge new_resource.default_bridge + end + end + if(new_resource.static_ip) lxc_interface "eth0[#{new_resource.name}]" do container new_resource.name @@ -100,10 +108,6 @@ def load_current_resource source 'fstab.erb' cookbook 'lxc' variables :container => new_resource.name - only_if do - node.run_state[:lxc][:fstabs] && - node.run_state[:lxc][:fstabs][new_resource.name] - end mode 0644 end @@ -129,7 +133,10 @@ def load_current_resource end #### Use cached chef package from host if available - VERSION_REGEXP = %r{(\d+\.\d+\.\d+(-\d+)?)} + unless(defined?(VERSION_REGEXP)) + VERSION_REGEXP = %r{(\d+\.\d+\.\d+(-\d+)?)} + end + if(%w(debian ubuntu).include?(new_resource.template) && system('ls /opt/chef*.deb 2>&1 > /dev/null')) file_path = Dir.glob(::File.join('/opt', 'chef*.deb')).sort do |x,y| version_x = x.scan(VERSION_REGEXP).flatten.first @@ -221,18 +228,17 @@ def load_current_resource end #### Have initialize commands for the container? Run them now - ruby_block "lxc initialize_commands[#{new_resource.name}]" do - block do - new_resource.initialize_commands.each do |cmd| + new_resource.initialize_commands.each do |cmd| + ruby_block "lxc initialize_command[#{new_resource.name}:#{cmd}]" do + block do Chef::Log.info "Running command on #{new_resource.name}: #{cmd}" _lxc.container_command(cmd, 5) end + only_if do + node.run_state[:lxc][:meta][new_resource.name][:new_container] + end + retries 5 end - only_if do - node.run_state[:lxc][:meta][new_resource.name][:new_container] && - !new_resource.initialize_commands.empty? - end - retries 5 end # Make sure we have chef in the container diff --git a/recipes/package.rb b/recipes/package.rb index be7c247..924f99f 100644 --- a/recipes/package.rb +++ b/recipes/package.rb @@ -1,4 +1,40 @@ +package 'software-properties-common' do + only_if{ node[:lxc][:enable_daily_ppa] } +end + +execute 'enable lxc-daily ppa' do + command 'apt-add-repository ppa:ubuntu-lxc/daily -y' + only_if do + node.platform_family?('debian') && + node[:lxc][:enable_daily_ppa] + end + not_if 'grep -R "^deb.*ppa.*lxc.daily" /etc/apt/sources.list*' +end + +execute 'ppa update' do + command 'apt-get update' + action :nothing + subscribes :run, 'execute[enable lxc-daily ppa]', :immediately +end + +execute 'lxc ppa system upgrade' do + command 'apt-get upgrade -yq' + action :nothing + subscribes :run, 'execute[enable lxc-daily ppa]', :immediately + environment 'DEBIAN_FRONTEND' => 'noninteractive' +end + +ruby_block 'ppa lxc package list' do + block do + node.default[:lxc][:packages] = node[:lxc][:ppa_packages] + end + action :nothing + subscribes :create, 'execute[enable lxc-daily ppa]', :immediately +end + # install the server dependencies to run lxc node[:lxc][:packages].each do |lxcpkg| - package lxcpkg + package lxcpkg do + subscribes :upgrade, 'execute[enable lxc-daily ppa]', :immediately + end end diff --git a/resources/config.rb b/resources/config.rb index 81f7567..c479d67 100644 --- a/resources/config.rb +++ b/resources/config.rb @@ -1,20 +1,16 @@ +attr_reader :struct + actions :create, :delete default_action :create attribute :container, :kind_of => String, :default => nil # alias for utsname -attribute :utsname, :kind_of => String, :default => nil # defaults to resource name -attribute :aa_profile, :kind_of => String, :default => nil # platform specific? -attribute :network, :kind_of => [Array, Hash] -attribute :default_bridge, :kind_of => String -attribute :static_ip, :kind_of => String -attribute :pts, :kind_of => Numeric, :default => 1024 -attribute :tty, :kind_of => Numeric, :default => 4 -attribute :arch, :kind_of => String, :default => 'amd64' -attribute :devttydir, :kind_of => String, :default => 'lxc' -attribute :cgroup, :kind_of => Hash, :default => Mash.new -attribute :cap_drop, :kind_of => [String, Array], :default => %w(sys_module mac_admin) -attribute :mount, :kind_of => String -attribute :mount_entry, :kind_of => String -attribute :rootfs, :kind_of => [String,Pathname] -attribute :rootfs_mount, :kind_of => String -attribute :pivotdir, :kind_of => String +attribute :resource_style, :equal_to => [:replace, :merge, 'replace', 'merge'], :default => :merge + +def method_missing(*args, &block) + unless(@struct) + require 'elecksee/lxc_file_config' + @struct = LxcStruct.new + @struct._set_state(:value_collapse => true) + end + @struct.method_missing(*args, &block) +end diff --git a/resources/container.rb b/resources/container.rb index c4e13ee..9d22665 100644 --- a/resources/container.rb +++ b/resources/container.rb @@ -23,8 +23,8 @@ def initialize(*args) attribute :static_ip, :kind_of => String attribute :static_netmask, :kind_of => String, :default => '255.255.255.0' attribute :static_gateway, :kind_of => String -attribute :default_config, :kind_of => [TrueClass, FalseClass], :default => true -attribute :default_fstab, :kind_of => [TrueClass, FalseClass], :default => true +attribute :default_config, :kind_of => [TrueClass, FalseClass] +attribute :default_fstab, :kind_of => [TrueClass, FalseClass] attribute :container_commands, :kind_of => Array, :default => [] attribute :initialize_commands, :kind_of => Array, :default => [] attribute :clone, :kind_of => String diff --git a/templates/default/fstab.erb b/templates/default/fstab.erb index e5fe5aa..6793c44 100644 --- a/templates/default/fstab.erb +++ b/templates/default/fstab.erb @@ -1,5 +1,4 @@ # Chef generated fstab! -<% node.run_state[:lxc][:fstabs][@container].each do |line| -%> +<% node.run_state[:lxc].fetch(:fstabs, {}).fetch(@container, {}).each do |line| -%> <%= line %> <% end -%> -