From 3e7488f6135342deec2b829e70a8188f249a150f Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 8 Mar 2013 04:31:28 -0300 Subject: [PATCH 1/8] :wave: spike --- spike/provider | 277 ------------------------------------------------- 1 file changed, 277 deletions(-) delete mode 100755 spike/provider diff --git a/spike/provider b/spike/provider deleted file mode 100755 index 3c8f9a5..0000000 --- a/spike/provider +++ /dev/null @@ -1,277 +0,0 @@ -#!/usr/bin/env ruby - -require 'rubygems' -require 'log4r' -require 'yaml' -require 'shellwords' -require 'optparse' -require 'net/ssh' - -# Based on actions available to the VirtualBox provider: -# https://github.com/mitchellh/vagrant/tree/master/plugins/providers/virtualbox -class Provider - WAIT = 5 - - def initialize(config) - @config = config - @logger = Log4r::Logger.new("vagrant::provider::lxc") - @logger.outputters = Log4r::Outputter.stdout - if config['output'] - @logger.outputters << Log4r::FileOutputter.new('output', 'filename' => config['output']) - end - # @logger.level = Log4r::INFO - end - - # @see Vagrant::Plugin::V1::Provider#action - def action(name, *args) - # Attempt to get the action method from this class if it - # exists, otherwise return nil to show that we don't support the - # given action. - action_method = "action_#{name}" - return send(action_method, *args) if respond_to?(action_method) - nil - end - - protected - - def run(cmd) - @logger.debug "Running: #{cmd}" - system cmd - end - - def action_up - was_created = container_created? - if was_created - @logger.info("Container already created, moving on...") - else - @logger.info("Creating container...") - # TRY: run 'sudo lxc-create -t ubuntu -n vagrant-container -b vagrant' - # DISCUSS: Copy key directly to /var/lib/lxc/$host/root/.ssh/authorized_keys to be generic? - unless run 'sudo lxc-create -t ubuntu-cloud -n vagrant-container -- -S /home/vagrant/.ssh/id_rsa.pub' - puts 'Error creating box' - exit 1 - end - unless container_created? - puts 'Error creating container' - exit 1 - end - end - - if container_started? - @logger.info('Container already started') - else - share_folders - - @logger.info('Starting container...') - unless run "sudo lxc-start -n vagrant-container -d #{configs}"# -o /tmp/lxc-start.log -l DEBUG" - puts 'Error starting container!' - exit 1 - end - run 'sudo lxc-wait --name vagrant-container --state RUNNING' - unless container_started? - puts 'Error starting container!' - exit 1 - end - @logger.info('Container started') - - forward_ports - - unless was_created - @logger.debug "Waiting #{WAIT} seconds before setting up vagrant user" - sleep WAIT - setup_vagrant_user - end - end - end - - def action_halt - if container_started? - @logger.info('Stopping container...') - unless run 'sudo lxc-shutdown -n vagrant-container' - puts 'Error halting container!' - exit 1 - end - run 'sudo lxc-wait --name vagrant-container --state STOPPED' - if container_started? - puts 'Error halting container!' - exit 1 - end - @logger.info('Container halted') - else - @logger.info('Container already halted') - end - end - - def action_destroy - if container_created? - if container_started? - action_halt - @logger.debug "Waiting #{WAIT} seconds to proceed with destroy..." - sleep WAIT - end - @logger.info("Destroying container...") - unless run 'sudo lxc-destroy -n vagrant-container' - puts 'Error destroying container' - exit 1 - end - if container_created? - puts 'Error destroying container' - exit 1 - end - @logger.debug "Waiting #{WAIT} seconds for things to settle down..." - sleep WAIT - @logger.info("Container destroyed") - else - @logger.info("Container not created") - end - end - - def action_reload - action_halt if container_started? - action_up - end - - # TODO: Switch over to Net:SSH - def action_ssh(opts = {'user' => 'vagrant'}) - # FIXME: We should not depend on an IP to be configured - raise 'SSH support is currently available to a predefined IP only' unless @config['ip'] - - cmd = "ssh #{opts['user']}@#{@config['ip']} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet" - cmd << " -- #{Shellwords.escape opts['command']}" if opts['command'] - - unless run(cmd) - puts 'Error running ssh command!' - exit 1 - end - end - - def setup_vagrant_user - unless @config['ip'] - # FIXME: Need to find a way to grab the container IP - @logger.warn('Unfortunately automatic vagrant user setup does not work unless an IP is specified') - return - end - - @logger.info 'Setting up vagrant user' - - # TODO: We could try to use lxc-attach instead of SSH - - # Based on: - # https://github.com/jedi4ever/veewee/blob/master/templates/ubuntu-12.10-server-amd64-packages/vagrant.sh - cmds = [ - #'groupadd -r admin', - 'useradd -d /home/vagrant -m vagrant -r -s /bin/bash', - 'usermod -a -G admin vagrant', - 'cp /etc/sudoers /etc/sudoers.orig', - 'sed -i -e \'/Defaults\s\+env_reset/a Defaults\texempt_group=admin\' /etc/sudoers', - 'sed -i -e \'s/%admin\s\+ALL=(ALL)\s\+ALL/%admin ALL=NOPASSWD:ALL/g\' /etc/sudoers', - 'service sudo restart', - '-u vagrant -- mkdir -p /home/vagrant/.ssh', - '-u vagrant -- curl -o /home/vagrant/.ssh/authorized_keys https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub' - ] - - # FIXME: Needs to abort the process if any of this commands fail - ssh_conn('ubuntu') do |ssh| - cmds.each do |cmd| - @logger.debug "SSH: sudo #{cmd}" - ssh.exec!("sudo #{cmd}") - end - end - end - - def ssh_conn(user = 'vagrant') - Net::SSH.start(@config['ip'], user, :user_known_hosts_file => '/dev/null') do |ssh| - yield ssh - end - end - - def container_created? - `lxc-ls` =~ /^vagrant\-container/ - end - - def container_started? - `sudo -- lxc-info -n vagrant-container` =~ /RUNNING/ - end - - def share_folders - @logger.info('Setting up shared folders...') - - mount_folder(File.expand_path('.'), '/vagrant') - - Array(@config['shared_folders']).each do |folder| - mount_folder(folder['source'], folder['destination']) - end - end - - def mount_folder(source, destination) - @logger.info("Sharing #{source} as #{destination}") - run < #{host_port}") - forwards << "0.0.0.0 #{host_port} #{@config['ip']} #{guest_port}" - end - - # FIXME: We should be nice to others and not overwrite the config all the time ;) - File.open('/etc/rinetd.conf', 'w') do |f| - f.puts forwards - f.puts 'logfile /var/log/rinetd.log' - end - @logger.info('Restarting rinetd') - `sudo service rinetd restart` - end -end - -raise 'You need to provide an action' unless ARGV[0] - -action = ARGV.shift.to_sym -if action == :ssh - options = {'user' => 'vagrant'} - OptionParser.new do |opts| - opts.on("-c", '--command [COMMAND]') { |v| options['command'] = v } - opts.on('-u', '--user [USER]') { |v| options['user'] = v } - end.parse! - arguments = [options] -else - init_options = {} - OptionParser.new do |opts| - opts.on("-o", '--output [FILE]') { |v| init_options['output'] = v } - end.parse! -end - -config = YAML.load File.open('./config.yml') if File.exists? './config.yml' -config ||= {} -config['output'] = init_options.delete('output') if init_options && init_options.key?('output') - -@provider = Provider.new(config || {}) - -@provider.action(action, *(arguments || [])) From 9a168950fee243ff6fd59603fed4245ce00d7f13 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 8 Mar 2013 02:19:48 -0300 Subject: [PATCH 2/8] First stab at handling a custom lxc-dhcp IP Will help on #23 --- lib/vagrant-lxc/config.rb | 9 ++++++++- lib/vagrant-lxc/container.rb | 6 +++--- lib/vagrant-lxc/provider.rb | 2 +- spec/unit/container_spec.rb | 9 +++++---- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/vagrant-lxc/config.rb b/lib/vagrant-lxc/config.rb index 2dc5e3a..b03f662 100644 --- a/lib/vagrant-lxc/config.rb +++ b/lib/vagrant-lxc/config.rb @@ -6,8 +6,15 @@ module Vagrant # @return [Array] attr_reader :start_opts + # The ip set for the built in LXC dhcp server (defaults to configured ip + # at /etc/default/lxc or 10.0.3.1) + # + # @return [String] + attr_accessor :lxc_dhcp_ip + def initialize - @start_opts = [] + @start_opts = [] + @lxc_dhcp_ip = '10.0.3.1' end end end diff --git a/lib/vagrant-lxc/container.rb b/lib/vagrant-lxc/container.rb index 223459a..3de6be3 100644 --- a/lib/vagrant-lxc/container.rb +++ b/lib/vagrant-lxc/container.rb @@ -115,7 +115,7 @@ module Vagrant end end - def dhcp_ip + def dhcp_ip(server_ip) ip = '' # Right after creation lxc reports the container as running # before DNS is returning the right IP, so have to wait for a while @@ -123,7 +123,7 @@ module Vagrant # By default LXC supplies a dns server on 10.0.3.1 so we request the IP # of our target from there. # Tks to: https://github.com/neerolyte/vagueant/blob/master/bin/vagueant#L340 - r = (raw 'dig', @name, '@10.0.3.1', '+short') + r = (raw 'dig', @name, "@#{server_ip}", '+short') # If the command was a failure then raise an exception that is nicely # handled by Vagrant. @@ -131,7 +131,7 @@ module Vagrant if @interrupted @logger.info("Exit code != 0, but interrupted. Ignoring.") else - raise LXC::Errors::ExecuteError, :command => command.inspect + raise LXC::Errors::ExecuteError, :command => ['dig', @name, "@#{server_ip}", '+short'].inspect end end diff --git a/lib/vagrant-lxc/provider.rb b/lib/vagrant-lxc/provider.rb index 43f6a63..a4d8d3b 100644 --- a/lib/vagrant-lxc/provider.rb +++ b/lib/vagrant-lxc/provider.rb @@ -52,7 +52,7 @@ module Vagrant return nil if state == :not_created { - :host => @container.dhcp_ip, + :host => @container.dhcp_ip(@machine.provider_config.lxc_dhcp_ip), :port => 22 # @driver.ssh_port(@machine.config.ssh.guest_port) } end diff --git a/spec/unit/container_spec.rb b/spec/unit/container_spec.rb index 0d0d4e8..5dff6f2 100644 --- a/spec/unit/container_spec.rb +++ b/spec/unit/container_spec.rb @@ -181,8 +181,9 @@ describe Vagrant::LXC::Container do end describe 'dhcp ip' do - let(:name) { 'random-container-name' } - let(:ip) { "10.0.3.123" } + let(:name) { 'random-container-name' } + let(:ip) { "10.0.4.123" } + let(:server_ip) { "10.0.4.1" } before do subject.stub(:raw) { @@ -191,8 +192,8 @@ describe Vagrant::LXC::Container do end it 'digs the container ip from lxc dns server' do - subject.dhcp_ip.should == ip - subject.should have_received(:raw).with('dig', name, '@10.0.3.1', '+short') + subject.dhcp_ip(server_ip).should == ip + subject.should have_received(:raw).with('dig', name, "@#{server_ip}", '+short') end end end From 72893299f44a970f2752f1dd7eed5fc0c4ba854d Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 8 Mar 2013 02:32:28 -0300 Subject: [PATCH 3/8] First stab at setting up a lxc container for developing the gem itself --- development/Vagrantfile | 46 ++++++++++ development/lxc-configs/lxc-dev-default | 37 ++++++++ development/setup-lxc-dev-box | 25 ++++++ development/site.pp | 113 ++++++++++++++++++++++++ 4 files changed, 221 insertions(+) create mode 100644 development/Vagrantfile create mode 100644 development/lxc-configs/lxc-dev-default create mode 100755 development/setup-lxc-dev-box create mode 100644 development/site.pp diff --git a/development/Vagrantfile b/development/Vagrantfile new file mode 100644 index 0000000..3286904 --- /dev/null +++ b/development/Vagrantfile @@ -0,0 +1,46 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +def local_cache(box_name) + cache_dir = File.join(File.expand_path(Vagrant::Environment::DEFAULT_HOME), + 'cache', + 'apt', + box_name) + partial_dir = File.join(cache_dir, 'partial') + FileUtils.mkdir_p(partial_dir) unless File.exists? partial_dir + cache_dir +end + +Vagrant.require_plugin 'vagrant-lxc' + +Vagrant.configure("2") do |config| + config.vm.box = "lxc-quantal64" + config.vm.box_url = 'http://dl.dropbox.com/u/13510779/lxc-quantal64-2013-03-08.box' + config.vm.hostname = 'lxc-quantal64' + + config.vm.synced_folder "../", "/vagrant", name: 'vagrant-root' + + cache_dir = local_cache(config.vm.box) + config.vm.synced_folder cache_dir, + "/var/cache/apt/archives/", + name: "vagrant-cache" + + config.vm.provider :lxc do |lxc| + # Not sure we need this + lxc.start_opts << 'lxc.aa_profile=unconfined' + end + + config.vm.provision :shell, inline: ' + if ! [ -f /home/vagrant/.updated ]; then + sudo apt-get update && + sudo apt-get install puppet -y && + touch /home/vagrant/.updated + fi' + + config.vm.provision :puppet do |puppet| + puppet.manifests_path = "." + puppet.manifest_file = "site.pp" + # Pass DEBUG=1 to vagrant commands if you want to make some debugging noise + puppet.options << [ '--verbose', '--debug' ] if ENV['DEBUG'] == '1' + end +end diff --git a/development/lxc-configs/lxc-dev-default b/development/lxc-configs/lxc-dev-default new file mode 100644 index 0000000..4ad1a6d --- /dev/null +++ b/development/lxc-configs/lxc-dev-default @@ -0,0 +1,37 @@ +############################################################################### +# This file has the same configs as the built in /etc/default/lxc on Ubuntu, +# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.* +# which is likely to be running from the host machine +############################################################################### + + +# MIRROR to be used by ubuntu template at container creation: +# Leaving it undefined is fine +#MIRROR="http://archive.ubuntu.com/ubuntu" +# or +#MIRROR="http://:3142/archive.ubuntu.com/ubuntu" + +# LXC_AUTO - whether or not to start containers symlinked under +# /etc/lxc/auto +LXC_AUTO="true" + +# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your +# containers. Set to "false" if you'll use virbr0 or another existing +# bridge, or mavlan to your host's NIC. +USE_LXC_BRIDGE="true" + +# If you change the LXC_BRIDGE to something other than lxcbr1, then +# you will also need to update your /etc/lxc/lxc.conf as well as the +# configuration (/var/lib/lxc//config) for any containers +# already created using the default config to reflect the new bridge +# name. +# If you have the dnsmasq daemon installed, you'll also have to update +# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon. +LXC_BRIDGE="lxcbr1" +LXC_ADDR="10.0.254.1" +LXC_NETMASK="255.255.255.0" +LXC_NETWORK="10.0.254.0/24" +LXC_DHCP_RANGE="10.0.254.2,10.0.254.254" +LXC_DHCP_MAX="253" + +LXC_SHUTDOWN_TIMEOUT=120 diff --git a/development/setup-lxc-dev-box b/development/setup-lxc-dev-box new file mode 100755 index 0000000..01f148a --- /dev/null +++ b/development/setup-lxc-dev-box @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -e + +# Package ubuntu-cloud +if ! [ -f ../boxes/output/ubuntu-cloud.box ]; then + bundle exec rake boxes:build:ubuntu-cloud +fi + +# Fresh start +bundle exec vagrant-lxc destroy + +# Skip provisioning as we need to apt-get update first +bundle exec vagrant-lxc up --provider=lxc --no-provision + +# Trigger an update from here instead of doing it from puppet as we don't need to +# apt-get update every time we boot the container. If there is a way to do it +# from puppet I don't know. If you do, feel free to send a pull request ;) +bundle exec vagrant-lxc ssh -c ' +sudo sed -i -e "s/archive./br.archive./g" /etc/apt/sources.list && +sudo apt-get update' +bundle exec vagrant-lxc provision + +# Reload the container just to ensure it can boot properly after the upgrades +bundle exec vagrant-lxc reload diff --git a/development/site.pp b/development/site.pp new file mode 100644 index 0000000..e836f86 --- /dev/null +++ b/development/site.pp @@ -0,0 +1,113 @@ +Exec { path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/', '/usr/local/bin'] } + +# Because I'm lazy ;) +exec { + 'echo "alias be=\"bundle exec\"" >> ~/.bashrc': + unless => 'grep -q "bundle exec" ~/.bashrc'; + + 'echo "cd /vagrant" >> ~/.bashrc': + unless => 'grep -q "cd /vagrant" ~/.bashrc'; +} + +# Overwrite LXC default configs +exec { + 'config-lxc': + # We need to do this otherwise IPs will collide with the host's lxc dhcp server. + # If we install the package prior to setting this configs the container will go crazy. + command => 'cp /vagrant/development/lxc-configs/lxc-dev-default /etc/default/lxc', + unless => 'grep -q "10.0.4" /etc/default/lxc' +} + +# Install dependencies +package { + [ 'libffi-dev', 'bsdtar', 'exuberant-ctags', 'ruby1.9.1-dev', 'htop', 'git', 'build-essential' ]: + ensure => 'installed' + ; + + 'lxc': + require => Exec['config-lxc'] + ; + + 'bundler': + ensure => 'installed', + provider => 'gem' + ; +} + +# Allow gems to be installed on vagrant user home avoiding "sudo"s +# Tks to http://wiki.railsplayground.com/railsplayground/show/How+to+install+gems+and+non+root+user +file { + '/home/vagrant/gems': + ensure => directory, + owner => 'vagrant', + group => 'vagrant' + ; + + '/home/vagrant/.gemrc': + content => ' +--- +:verbose: true +gem: --no-ri --no-rdoc +:update_sources: true +:sources: +- http://gems.rubyforge.org +- http://gems.github.com +:backtrace: false +:bulk_threshold: 1000 +:benchmark: false +gemhome: $HOME/gems +gempath: +- /home/vagrant/gems +- /usr/local/lib/ruby/gems/1.8 +' +} +exec { + 'set-gem-paths': + command => 'cat << EOF >> /home/vagrant/.profile +export GEM_HOME=/home/vagrant/gems +export GEM_PATH=/home/vagrant/gems:/var/lib/gems/1.9.1 +export PATH=$PATH:/vagrant/gems/bin +EOF', + unless => 'grep -q "GEM_HOME" /home/vagrant/.profile' +} + +# Bundle! +exec { + 'su -l vagrant -c "cd /vagrant && bundle install"': + # We are checking for guard-rspec here but it could be any gem... + unless => 'gem list guard | grep -q rspec', + cwd => '/vagrant', + require => [ + Exec['set-gem-paths'], + File['/home/vagrant/gems', '/home/vagrant/.gemrc'], + Package['bundler'] + ] +} + +# Setup vagrant default ssh key +file { + '/home/vagrant/.ssh': + ensure => directory, + owner => 'vagrant', + group => 'vagrant' +} +exec { + 'download-private-key': + command => 'wget https://raw.github.com/mitchellh/vagrant/master/keys/vagrant -O /home/vagrant/.ssh/id_rsa', + creates => '/home/vagrant/.ssh/id_rsa', + require => File['/home/vagrant/.ssh'], + user => 'vagrant' + ; + + 'wget https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub -O /home/vagrant/.ssh/id_rsa.pub': + creates => '/home/vagrant/.ssh/id_rsa.pub', + require => File['/home/vagrant/.ssh'], + user => 'vagrant' + ; +} +file { + '/home/vagrant/.ssh/id_rsa': + ensure => 'present', + mode => '0600', + require => Exec['download-private-key'] +} From e406be521a70332256f356d7f8e51e2020823ac4 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Fri, 8 Mar 2013 03:36:54 -0300 Subject: [PATCH 4/8] Tweaks to start a container from within the dev container References #23 --- development/Vagrantfile | 7 ------- development/lxc-configs/lxc-dev-default | 2 +- development/setup-lxc-dev-box | 13 ++++--------- development/site.pp | 13 +++++++------ example/Vagrantfile | 2 +- example/puppet/manifests/site.pp | 1 - 6 files changed, 13 insertions(+), 25 deletions(-) diff --git a/development/Vagrantfile b/development/Vagrantfile index 3286904..f2188c2 100644 --- a/development/Vagrantfile +++ b/development/Vagrantfile @@ -30,13 +30,6 @@ Vagrant.configure("2") do |config| lxc.start_opts << 'lxc.aa_profile=unconfined' end - config.vm.provision :shell, inline: ' - if ! [ -f /home/vagrant/.updated ]; then - sudo apt-get update && - sudo apt-get install puppet -y && - touch /home/vagrant/.updated - fi' - config.vm.provision :puppet do |puppet| puppet.manifests_path = "." puppet.manifest_file = "site.pp" diff --git a/development/lxc-configs/lxc-dev-default b/development/lxc-configs/lxc-dev-default index 4ad1a6d..2d66a5e 100644 --- a/development/lxc-configs/lxc-dev-default +++ b/development/lxc-configs/lxc-dev-default @@ -27,7 +27,7 @@ USE_LXC_BRIDGE="true" # name. # If you have the dnsmasq daemon installed, you'll also have to update # /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon. -LXC_BRIDGE="lxcbr1" +LXC_BRIDGE="lxcbr0" LXC_ADDR="10.0.254.1" LXC_NETMASK="255.255.255.0" LXC_NETWORK="10.0.254.0/24" diff --git a/development/setup-lxc-dev-box b/development/setup-lxc-dev-box index 01f148a..a400e32 100755 --- a/development/setup-lxc-dev-box +++ b/development/setup-lxc-dev-box @@ -2,9 +2,9 @@ set -e -# Package ubuntu-cloud -if ! [ -f ../boxes/output/ubuntu-cloud.box ]; then - bundle exec rake boxes:build:ubuntu-cloud +# Package quantal64 +if ! [ -f ../boxes/output/lxc-quantal64.box ]; then + bundle exec rake boxes:quantal64:build fi # Fresh start @@ -13,12 +13,7 @@ bundle exec vagrant-lxc destroy # Skip provisioning as we need to apt-get update first bundle exec vagrant-lxc up --provider=lxc --no-provision -# Trigger an update from here instead of doing it from puppet as we don't need to -# apt-get update every time we boot the container. If there is a way to do it -# from puppet I don't know. If you do, feel free to send a pull request ;) -bundle exec vagrant-lxc ssh -c ' -sudo sed -i -e "s/archive./br.archive./g" /etc/apt/sources.list && -sudo apt-get update' +bundle exec vagrant-lxc ssh -c 'sudo apt-get update && sudo apt-get install puppet -y' bundle exec vagrant-lxc provision # Reload the container just to ensure it can boot properly after the upgrades diff --git a/development/site.pp b/development/site.pp index e836f86..fa64b55 100644 --- a/development/site.pp +++ b/development/site.pp @@ -2,11 +2,11 @@ Exec { path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/', '/usr/local/bin' # Because I'm lazy ;) exec { - 'echo "alias be=\"bundle exec\"" >> ~/.bashrc': - unless => 'grep -q "bundle exec" ~/.bashrc'; + 'echo "alias be=\"bundle exec\"" >> /home/vagrant/.bashrc': + unless => 'grep -q "bundle exec" /home/vagrant/.bashrc'; - 'echo "cd /vagrant" >> ~/.bashrc': - unless => 'grep -q "cd /vagrant" ~/.bashrc'; + 'echo "cd /vagrant" >> /home/vagrant/.bashrc': + unless => 'grep -q "cd /vagrant" /home/vagrant/.bashrc'; } # Overwrite LXC default configs @@ -15,12 +15,13 @@ exec { # We need to do this otherwise IPs will collide with the host's lxc dhcp server. # If we install the package prior to setting this configs the container will go crazy. command => 'cp /vagrant/development/lxc-configs/lxc-dev-default /etc/default/lxc', - unless => 'grep -q "10.0.4" /etc/default/lxc' + unless => 'grep -q "10.0.254" /etc/default/lxc' } # Install dependencies package { - [ 'libffi-dev', 'bsdtar', 'exuberant-ctags', 'ruby1.9.1-dev', 'htop', 'git', 'build-essential' ]: + [ 'libffi-dev', 'bsdtar', 'exuberant-ctags', 'ruby1.9.1-dev', 'htop', 'git', + 'build-essential', 'dnsutils' ]: ensure => 'installed' ; diff --git a/example/Vagrantfile b/example/Vagrantfile index 90ab563..313e190 100644 --- a/example/Vagrantfile +++ b/example/Vagrantfile @@ -7,11 +7,11 @@ Vagrant.configure("2") do |config| config.vm.box = "quantal64" config.vm.box_url = 'http://dl.dropbox.com/u/13510779/lxc-quantal64-2013-03-08.box' config.vm.hostname = 'lxc-quantal64' - config.vm.network :private_network, ip: "192.168.33.10" config.vm.synced_folder "/tmp", "/vagrant_data" config.vm.provider :lxc do |lxc| + lxc.lxc_dhcp_ip = '10.0.254.1' if ENV['USER'] == 'vagrant' lxc.start_opts << 'lxc.cgroup.memory.limit_in_bytes=400M' lxc.start_opts << 'lxc.cgroup.memory.memsw.limit_in_bytes=500M' end diff --git a/example/puppet/manifests/site.pp b/example/puppet/manifests/site.pp index 22446c1..947b061 100644 --- a/example/puppet/manifests/site.pp +++ b/example/puppet/manifests/site.pp @@ -3,4 +3,3 @@ Exec { path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/'] } notice "Hi there! puppet here" require hello_world - From a5d18567cb4aee5d4315db97ef4cad67ff52a17a Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 9 Mar 2013 01:43:57 -0300 Subject: [PATCH 5/8] Rename development Vagrantfile to Vagrantfile.dev.lxc --- .gitignore | 1 + development/{Vagrantfile => Vagrantfile.dev.lxc} | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) rename development/{Vagrantfile => Vagrantfile.dev.lxc} (84%) diff --git a/.gitignore b/.gitignore index 53e1754..ef1ae2b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ Vagrantfile /boxes/**/*.tar.gz /boxes/quantal64/rootfs-amd64/ /boxes/output/ +/development/Vagrantfile diff --git a/development/Vagrantfile b/development/Vagrantfile.dev.lxc similarity index 84% rename from development/Vagrantfile rename to development/Vagrantfile.dev.lxc index f2188c2..e1dcefd 100644 --- a/development/Vagrantfile +++ b/development/Vagrantfile.dev.lxc @@ -14,9 +14,9 @@ end Vagrant.require_plugin 'vagrant-lxc' Vagrant.configure("2") do |config| - config.vm.box = "lxc-quantal64" + config.vm.box = "lxc-quantal64-2013-03-08" config.vm.box_url = 'http://dl.dropbox.com/u/13510779/lxc-quantal64-2013-03-08.box' - config.vm.hostname = 'lxc-quantal64' + config.vm.hostname = "lxc-quantal64" config.vm.synced_folder "../", "/vagrant", name: 'vagrant-root' @@ -25,10 +25,9 @@ Vagrant.configure("2") do |config| "/var/cache/apt/archives/", name: "vagrant-cache" - config.vm.provider :lxc do |lxc| - # Not sure we need this - lxc.start_opts << 'lxc.aa_profile=unconfined' - end + config.vm.provision :shell, inline: ' + sudo apt-get update && + sudo apt-get install puppet -y' config.vm.provision :puppet do |puppet| puppet.manifests_path = "." From aa57fd794bdcb15564dc2bfed3f050e38225e075 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 9 Mar 2013 02:22:52 -0300 Subject: [PATCH 6/8] Finally a decent development environment :sunglasses: --- .gitignore | 2 - Vagrantfile.dev.1.0 | 25 ------ development/Vagrantfile.dev.lxc | 11 ++- development/setup-lxc-dev-box | 16 ++-- setup-vagrant-dev-box | 143 -------------------------------- 5 files changed, 16 insertions(+), 181 deletions(-) delete mode 100644 Vagrantfile.dev.1.0 delete mode 100755 setup-vagrant-dev-box diff --git a/.gitignore b/.gitignore index ef1ae2b..bcac09b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,6 @@ doc/ .vagrant /cache -Vagrantfile - /boxes/**/*.tar.gz /boxes/quantal64/rootfs-amd64/ /boxes/output/ diff --git a/Vagrantfile.dev.1.0 b/Vagrantfile.dev.1.0 deleted file mode 100644 index f024d2a..0000000 --- a/Vagrantfile.dev.1.0 +++ /dev/null @@ -1,25 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -if Vagrant::VERSION =~ /^1\.1/ - raise 'This Vagrantfile is meant to be used with Vagrant 1.0' -end - -Vagrant::Config.run do |config| - config.vm.box = "quantal64" - config.vm.box_url = "https://github.com/downloads/roderik/VagrantQuantal64Box/quantal64.box" - - if defined? VagrantVbguest::Config - config.vbguest.auto_update = false - config.vbguest.no_remote = true - end - - config.vm.network :hostonly, "192.168.33.10" - config.vm.customize [ - "modifyvm", :id, - "--memory", 1024, - "--cpus", "2" - ] - - config.vm.share_folder("v-root", "/vagrant", ".", :nfs => true) -end diff --git a/development/Vagrantfile.dev.lxc b/development/Vagrantfile.dev.lxc index e1dcefd..adf2126 100644 --- a/development/Vagrantfile.dev.lxc +++ b/development/Vagrantfile.dev.lxc @@ -25,9 +25,16 @@ Vagrant.configure("2") do |config| "/var/cache/apt/archives/", name: "vagrant-cache" + config.vm.provider :lxc do |lxc| + # Required to boot nested containers + lxc.start_opts << 'lxc.aa_profile=unconfined' + end + config.vm.provision :shell, inline: ' - sudo apt-get update && - sudo apt-get install puppet -y' + if ! `which puppet > /dev/null`; then + sudo apt-get update && + sudo apt-get install puppet -y + fi' config.vm.provision :puppet do |puppet| puppet.manifests_path = "." diff --git a/development/setup-lxc-dev-box b/development/setup-lxc-dev-box index a400e32..078fbe3 100755 --- a/development/setup-lxc-dev-box +++ b/development/setup-lxc-dev-box @@ -2,19 +2,17 @@ set -e -# Package quantal64 -if ! [ -f ../boxes/output/lxc-quantal64.box ]; then - bundle exec rake boxes:quantal64:build -fi - # Fresh start bundle exec vagrant-lxc destroy # Skip provisioning as we need to apt-get update first -bundle exec vagrant-lxc up --provider=lxc --no-provision +bundle exec vagrant-lxc up --no-provision --provider=lxc -bundle exec vagrant-lxc ssh -c 'sudo apt-get update && sudo apt-get install puppet -y' -bundle exec vagrant-lxc provision +# apt-get and install puppet so we can provision the dev machine +bundle exec vagrant-lxc provision --provision-with=shell -# Reload the container just to ensure it can boot properly after the upgrades +# Actual setup +bundle exec vagrant-lxc provision --provision-with=puppet + +# Reload the container just to ensure it can boot properly after provisioning bundle exec vagrant-lxc reload diff --git a/setup-vagrant-dev-box b/setup-vagrant-dev-box deleted file mode 100755 index 9ff9005..0000000 --- a/setup-vagrant-dev-box +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env ruby - -# I know, we should be using something like puppet or chef but trust me, this -# started as a small script :-) -# Please check https://github.com/fgrehm/vagrant-lxc/issues/7 for the current status. - -# In case something goes wrong after the machine has been set up, you can run this -# script again and it will ask you if you want to restore a clean snapshot. - -raise 'You should not run this script from the dev box' if ENV['USER'] == 'vagrant' - -require 'bundler' -require 'json' - -IMAGE_ROOT = 'https://cloud-images.ubuntu.com/releases/quantal/release-20130206' -IMAGE_NAME = 'ubuntu-12.10-server-cloudimg-amd64-root.tar.gz' - -def download(source, destination) - destination = "#{File.dirname __FILE__}/#{destination}" - return if File.exists?(destination) - - sh "wget #{source} -O #{destination}" -end - -def sh(cmd) - Bundler.with_clean_env do - puts cmd - raise 'Errored!' unless system cmd - end -end - -def restore_snapshot! - sh 'vagrant halt -f' - conf = JSON.parse File.read('.vagrant') - id = conf['active']['default'] - sh "VBoxManage snapshot '#{id}' restore ready-to-rock" - sh 'vagrant up' - exit 0 -end - -def vagrant_ssh(cmd) - sh "vagrant ssh -c '#{cmd}'" -end - -Bundler.with_clean_env do - # Ensure box has not been created yet - unless `vagrant status` =~ /not created/ - print 'Vagrant box already created, do you want to [r]ecreate it, restore [s]napshot or [A]bort? ' - answer = gets.chomp - exit 0 if answer.empty? || answer =~ /^a/i - - case - when answer =~ /^s/i - restore_snapshot! - when answer =~ /^r/i - sh 'vagrant destroy -f' - else - puts 'Invalid option!' - exit 1 - end - end -end - -# Cache development dependencies -`mkdir -p cache` - -# Fetches vagrant submodule -`git submodule update --init` - -# Download container image for building the base ubuntu-cloud box -download "#{IMAGE_ROOT}/#{IMAGE_NAME}", "boxes/ubuntu-cloud/#{IMAGE_NAME}" - -# Start vagrant -sh 'vagrant up' - -# Because I'm lazy ;) -vagrant_ssh 'echo "cd /vagrant" >> ~/.bashrc' -vagrant_ssh 'echo "alias be=\"bundle exec\"" >> ~/.bashrc' - -# "be" archive is too slow for me -vagrant_ssh 'sudo sed -i -e "s/be.archive/br.archive/g" /etc/apt/sources.list' - -# Ensure we have the latest packages around -vagrant_ssh "sudo apt-get update && sudo apt-get dist-upgrade -y" - -# Ensure the machine can boot properly after upgrades and dependencies have been installed -sh 'vagrant reload' - -# Install dependencies -vagrant_ssh "sudo apt-get install lxc rinetd libffi-dev bsdtar exuberant-ctags libffi-ruby ruby1.9.1-dev htop git virtualbox virtualbox-ose-dkms linux-headers-generic linux-headers-3.5.0-25-generic -y && sudo gem install bundler --no-ri --no-rdoc" -# vagrant_ssh "sudo dkms install virtualbox/4.1.18" -# vagrant_ssh "sudo service virtualbox start" - -# Ensure the machine can boot properly after dependencies have been installed -sh 'vagrant reload' - -# Allow gems to be installed on vagrant user home avoiding "sudo"s -# Tks to http://wiki.railsplayground.com/railsplayground/show/How+to+install+gems+and+non+root+user -vagrant_ssh 'mkdir -p ~/gems' -vagrant_ssh "cat << EOF >> ~/.profile -export GEM_HOME=$HOME/gems -export GEM_PATH=$HOME/gems:/var/lib/gems/1.9.1 -export PATH=$PATH:$HOME/gems/bin -EOF" -vagrant_ssh "cat << EOF > .gemrc ---- -:verbose: true -gem: --no-ri --no-rdoc -:update_sources: true -:sources: -- http://gems.rubyforge.org -- http://gems.github.com -:backtrace: false -:bulk_threshold: 1000 -:benchmark: false -gemhome: $HOME/gems -gempath: -- $HOME/gems -- /usr/local/lib/ruby/gems/1.8 -EOF" - -# Backup rinetd config -vagrant_ssh "cp /etc/rinetd.conf /vagrant/cache/rinetd.conf" - -# Make rinetd writable by vagrant user -vagrant_ssh 'sudo chown vagrant:vagrant /etc/rinetd.conf' - -# Setup vagrant default ssh key -vagrant_keys_path = '/vagrant/vendor/vagrant/keys' -vagrant_ssh "mkdir -p ~/.ssh && cd /vagrant && cp #{vagrant_keys_path}/vagrant ~/.ssh/id_rsa && cp #{vagrant_keys_path}/vagrant.pub ~/.ssh/id_rsa.pub && chmod 600 ~/.ssh/id_rsa" - -# Bundle! -vagrant_ssh 'cd /vagrant && bundle && cd /vagrant/example && bundle' - -# Add base box -vagrant_ssh 'cd /vagrant && rake boxes:build:ubuntu-cloud' - -# Click -sh 'vagrant halt' -conf = JSON.parse File.read('.vagrant') -id = conf['active']['default'] -sh "VBoxManage snapshot '#{id}' take ready-to-rock" -sh 'vagrant up' From ce8445b0011541ced3165a5380596a77d2f308f2 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 9 Mar 2013 02:51:50 -0300 Subject: [PATCH 7/8] Set up a Vagrantfile for 1.0 --- development/Vagrantfile.dev.vb | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 development/Vagrantfile.dev.vb diff --git a/development/Vagrantfile.dev.vb b/development/Vagrantfile.dev.vb new file mode 100644 index 0000000..87261a3 --- /dev/null +++ b/development/Vagrantfile.dev.vb @@ -0,0 +1,33 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +def local_cache(box_name) + cache_dir = File.join(File.expand_path(Vagrant::Environment::DEFAULT_HOME), + 'cache', + 'apt', + box_name) + partial_dir = File.join(cache_dir, 'partial') + FileUtils.mkdir_p(partial_dir) unless File.exists? partial_dir + cache_dir +end + +Vagrant::Config.run do |config| + config.vm.box = "quantal64" + config.vm.box_url = "https://github.com/downloads/roderik/VagrantQuantal64Box/quantal64.box" + + cache_dir = local_cache(config.vm.box) + config.vm.share_folder "v-root", "/vagrant", "../" + config.vm.share_folder "v-cache", "/var/apt/archives/", cache_dir + + if defined? VagrantVbguest::Config + config.vbguest.auto_update = false + config.vbguest.no_remote = true + end + + config.vm.provision :puppet do |puppet| + puppet.manifests_path = "." + puppet.manifest_file = "site.pp" + # Pass DEBUG=1 to vagrant commands if you want to make some debugging noise + puppet.options << [ "--verbose", "--debug" ] if ENV["DEBUG"] == '1' + end +end From 4b7be3dd72c707f56180404a4b34621d1031fef4 Mon Sep 17 00:00:00 2001 From: Fabio Rehm Date: Sat, 9 Mar 2013 03:11:55 -0300 Subject: [PATCH 8/8] Update README with recent dev box changes --- README.md | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6e32a6f..eed6cf2 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ bundle install bundle exec rake # to run all specs ``` -To rebuild and add the new quantal64 box: +To rebuild and add the provided quantal64 box: ``` bundle exec rake boxes:quantal64:build @@ -116,16 +116,35 @@ vagrant-lxc box add quantal64 boxes/output/lxc-quantal64.box ``` -### Using VirtualBox for development +### Using `vagrant-lxc` to develop itself -I've also prepared a Vagrant 1.0 VirtualBox machine for development that you can -get up and running with the [`setup-vagrant-dev-box`](setup-vagrant-dev-box) -script. Feel free to use it :) +Yes! The gem has been [bootstrapped](http://en.wikipedia.org/wiki/Bootstrapping_(compilers) +and since you can boot a container from within another, after cloning the +project you can run the commands below from the host machine to get a container +ready for development: + +```sh +bundle install +cd development +cp Vagrantfile.dev.lxc Vagrantfile +# Required in order to allow nested containers to be started +sudo apt-get install apparmor-utils && sudo aa-complain /usr/bin/lxc-start +./setup-lxc-dev-box +``` + +That should result in a container ready to be `bundle exec vagrant-lxc ssh`ed. +Once you've SSH into the guest container, you'll be already on the project's root. +Keep in mind that you'll probably need to run `sudo aa-complain /usr/bin/lxc-start` +on the host whenever you want to hack on it, otherwise you won't be able to +start nested containers there to try things out. + + +### Using VirtualBox and Vagrant 1.0 for development ``` -cp Vagrantfile.dev.1.0 Vagrantfile -./setup-vagrant-dev-box -vagrant ssh +cd development +cp Vagrantfile.dev.vb Vagrantfile +vagrant up ```