Merge pull request #7 from fgrehm/dev-box-puppet-provisioning
Provision dev box with puppet
This commit is contained in:
commit
4e85c402ac
16 changed files with 293 additions and 466 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -22,8 +22,7 @@ doc/
|
||||||
.vagrant
|
.vagrant
|
||||||
/cache
|
/cache
|
||||||
|
|
||||||
Vagrantfile
|
|
||||||
|
|
||||||
/boxes/**/*.tar.gz
|
/boxes/**/*.tar.gz
|
||||||
/boxes/quantal64/rootfs-amd64/
|
/boxes/quantal64/rootfs-amd64/
|
||||||
/boxes/output/
|
/boxes/output/
|
||||||
|
/development/Vagrantfile
|
||||||
|
|
35
README.md
35
README.md
|
@ -108,7 +108,7 @@ bundle install
|
||||||
bundle exec rake # to run all specs
|
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
|
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
|
Yes! The gem has been [bootstrapped](http://en.wikipedia.org/wiki/Bootstrapping_(compilers)
|
||||||
get up and running with the [`setup-vagrant-dev-box`](setup-vagrant-dev-box)
|
and since you can boot a container from within another, after cloning the
|
||||||
script. Feel free to use it :)
|
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
|
cd development
|
||||||
./setup-vagrant-dev-box
|
cp Vagrantfile.dev.vb Vagrantfile
|
||||||
vagrant ssh
|
vagrant up
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
45
development/Vagrantfile.dev.lxc
Normal file
45
development/Vagrantfile.dev.lxc
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# -*- 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-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.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|
|
||||||
|
# Required to boot nested containers
|
||||||
|
lxc.start_opts << 'lxc.aa_profile=unconfined'
|
||||||
|
end
|
||||||
|
|
||||||
|
config.vm.provision :shell, inline: '
|
||||||
|
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 = "."
|
||||||
|
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
|
33
development/Vagrantfile.dev.vb
Normal file
33
development/Vagrantfile.dev.vb
Normal file
|
@ -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
|
37
development/lxc-configs/lxc-dev-default
Normal file
37
development/lxc-configs/lxc-dev-default
Normal file
|
@ -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://<host-ip-addr>: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/<container>/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="lxcbr0"
|
||||||
|
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
|
18
development/setup-lxc-dev-box
Executable file
18
development/setup-lxc-dev-box
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Fresh start
|
||||||
|
bundle exec vagrant-lxc destroy
|
||||||
|
|
||||||
|
# Skip provisioning as we need to apt-get update first
|
||||||
|
bundle exec vagrant-lxc up --no-provision --provider=lxc
|
||||||
|
|
||||||
|
# apt-get and install puppet so we can provision the dev machine
|
||||||
|
bundle exec vagrant-lxc provision --provision-with=shell
|
||||||
|
|
||||||
|
# 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
|
114
development/site.pp
Normal file
114
development/site.pp
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
Exec { path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/', '/usr/local/bin'] }
|
||||||
|
|
||||||
|
# Because I'm lazy ;)
|
||||||
|
exec {
|
||||||
|
'echo "alias be=\"bundle exec\"" >> /home/vagrant/.bashrc':
|
||||||
|
unless => 'grep -q "bundle exec" /home/vagrant/.bashrc';
|
||||||
|
|
||||||
|
'echo "cd /vagrant" >> /home/vagrant/.bashrc':
|
||||||
|
unless => 'grep -q "cd /vagrant" /home/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.254" /etc/default/lxc'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
package {
|
||||||
|
[ 'libffi-dev', 'bsdtar', 'exuberant-ctags', 'ruby1.9.1-dev', 'htop', 'git',
|
||||||
|
'build-essential', 'dnsutils' ]:
|
||||||
|
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']
|
||||||
|
}
|
2
example/Vagrantfile
vendored
2
example/Vagrantfile
vendored
|
@ -7,11 +7,11 @@ Vagrant.configure("2") do |config|
|
||||||
config.vm.box = "quantal64"
|
config.vm.box = "quantal64"
|
||||||
config.vm.box_url = 'http://dl.dropbox.com/u/13510779/lxc-quantal64-2013-03-08.box'
|
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.network :private_network, ip: "192.168.33.10"
|
|
||||||
|
|
||||||
config.vm.synced_folder "/tmp", "/vagrant_data"
|
config.vm.synced_folder "/tmp", "/vagrant_data"
|
||||||
|
|
||||||
config.vm.provider :lxc do |lxc|
|
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.limit_in_bytes=400M'
|
||||||
lxc.start_opts << 'lxc.cgroup.memory.memsw.limit_in_bytes=500M'
|
lxc.start_opts << 'lxc.cgroup.memory.memsw.limit_in_bytes=500M'
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,4 +3,3 @@ Exec { path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/'] }
|
||||||
notice "Hi there! puppet here"
|
notice "Hi there! puppet here"
|
||||||
|
|
||||||
require hello_world
|
require hello_world
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,15 @@ module Vagrant
|
||||||
# @return [Array]
|
# @return [Array]
|
||||||
attr_reader :start_opts
|
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
|
def initialize
|
||||||
@start_opts = []
|
@start_opts = []
|
||||||
|
@lxc_dhcp_ip = '10.0.3.1'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -115,7 +115,7 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def dhcp_ip
|
def dhcp_ip(server_ip)
|
||||||
ip = ''
|
ip = ''
|
||||||
# Right after creation lxc reports the container as running
|
# Right after creation lxc reports the container as running
|
||||||
# before DNS is returning the right IP, so have to wait for a while
|
# 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
|
# By default LXC supplies a dns server on 10.0.3.1 so we request the IP
|
||||||
# of our target from there.
|
# of our target from there.
|
||||||
# Tks to: https://github.com/neerolyte/vagueant/blob/master/bin/vagueant#L340
|
# 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
|
# If the command was a failure then raise an exception that is nicely
|
||||||
# handled by Vagrant.
|
# handled by Vagrant.
|
||||||
|
@ -131,7 +131,7 @@ module Vagrant
|
||||||
if @interrupted
|
if @interrupted
|
||||||
@logger.info("Exit code != 0, but interrupted. Ignoring.")
|
@logger.info("Exit code != 0, but interrupted. Ignoring.")
|
||||||
else
|
else
|
||||||
raise LXC::Errors::ExecuteError, :command => command.inspect
|
raise LXC::Errors::ExecuteError, :command => ['dig', @name, "@#{server_ip}", '+short'].inspect
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ module Vagrant
|
||||||
return nil if state == :not_created
|
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)
|
:port => 22 # @driver.ssh_port(@machine.config.ssh.guest_port)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -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'
|
|
|
@ -181,8 +181,9 @@ describe Vagrant::LXC::Container do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'dhcp ip' do
|
describe 'dhcp ip' do
|
||||||
let(:name) { 'random-container-name' }
|
let(:name) { 'random-container-name' }
|
||||||
let(:ip) { "10.0.3.123" }
|
let(:ip) { "10.0.4.123" }
|
||||||
|
let(:server_ip) { "10.0.4.1" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
subject.stub(:raw) {
|
subject.stub(:raw) {
|
||||||
|
@ -191,8 +192,8 @@ describe Vagrant::LXC::Container do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'digs the container ip from lxc dns server' do
|
it 'digs the container ip from lxc dns server' do
|
||||||
subject.dhcp_ip.should == ip
|
subject.dhcp_ip(server_ip).should == ip
|
||||||
subject.should have_received(:raw).with('dig', name, '@10.0.3.1', '+short')
|
subject.should have_received(:raw).with('dig', name, "@#{server_ip}", '+short')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
277
spike/provider
277
spike/provider
|
@ -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 <<STR
|
|
||||||
sudo mount --bind #{source} #{source}
|
|
||||||
sudo mount --make-unbindable #{source}
|
|
||||||
sudo mount --make-shared #{source}
|
|
||||||
|
|
||||||
if ! [ -d /var/lib/lxc/vagrant-container/rootfs#{destination} ]; then
|
|
||||||
sudo mkdir -p /var/lib/lxc/vagrant-container/rootfs#{destination}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! $(sudo grep -q '#{source} /var/lib/lxc/vagrant-container/rootfs#{destination}' /var/lib/lxc/vagrant-container/fstab); then
|
|
||||||
cat <<EOF | sudo tee -a /var/lib/lxc/vagrant-container/fstab
|
|
||||||
#{source} /var/lib/lxc/vagrant-container/rootfs#{destination} none bind 0 0
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
STR
|
|
||||||
end
|
|
||||||
|
|
||||||
def configs
|
|
||||||
configs = []
|
|
||||||
configs << "-s lxc.network.ipv4='#{@config['ip']}'" if @config['ip']
|
|
||||||
configs << '-s lxc.cgroup.memory.limit_in_bytes=400M'
|
|
||||||
configs << '-s lxc.cgroup.memory.memsw.limit_in_bytes=500M'
|
|
||||||
configs.join(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def forward_ports
|
|
||||||
return unless @config.key?('forwards')
|
|
||||||
|
|
||||||
@logger.info('Forwarding ports...')
|
|
||||||
forwards = ''
|
|
||||||
@config['forwards'].each do |forward|
|
|
||||||
host_port, guest_port = forward
|
|
||||||
@logger.info("-- #{guest_port} => #{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 || []))
|
|
Loading…
Add table
Reference in a new issue