vagrant-lxc-1.2.1/0000755000004100000410000000000012611107101013757 5ustar www-datawww-datavagrant-lxc-1.2.1/Rakefile0000644000004100000410000000011212611107101015416 0ustar www-datawww-dataDir['./tasks/**/*.rake'].each { |f| load f } require 'bundler/gem_tasks' vagrant-lxc-1.2.1/Gemfile.lock0000644000004100000410000001003212611107101016175 0ustar www-datawww-dataGIT remote: https://github.com/fgrehm/vagrant-cachier.git revision: 40dddfb368526948e769492a00a7937c5a044a4d specs: vagrant-cachier (1.2.1) GIT remote: https://github.com/fgrehm/vagrant-pristine.git revision: 6d044265db17451c606f000bf43437e95a742bb4 specs: vagrant-pristine (0.3.0) GIT remote: https://github.com/mitchellh/vagrant-spec.git revision: 1df5a3af81cb7cce568b2eac52b8f6822bcb1d8e specs: vagrant-spec (0.0.1) childprocess (~> 0.5.0) log4r (~> 1.1.9) rspec (~> 2.14) thor (~> 0.18.1) GIT remote: https://github.com/mitchellh/vagrant.git revision: 78ea5e4a78ce644717ab16d8001ab77430168f0f tag: v1.7.4 specs: vagrant (1.7.4) bundler (>= 1.5.2, <= 1.10.5) childprocess (~> 0.5.0) erubis (~> 2.7.0) hashicorp-checkpoint (~> 0.1.1) i18n (>= 0.6.0, <= 0.8.0) listen (~> 3.0.2) log4r (~> 1.1.9, < 1.1.11) net-scp (~> 1.1.0) net-sftp (~> 2.1) net-ssh (>= 2.6.6, < 2.10.0) nokogiri (= 1.6.3.1) rb-kqueue (~> 0.2.0) rest-client (>= 1.6.0, < 2.0) wdm (~> 0.1.0) winrm (~> 1.3) winrm-fs (~> 0.2.0) PATH remote: . specs: vagrant-lxc (1.2.1) GEM remote: https://rubygems.org/ specs: builder (3.2.2) childprocess (0.5.6) ffi (~> 1.0, >= 1.0.11) coderay (1.1.0) coveralls (0.7.2) multi_json (~> 1.3) rest-client (= 1.6.7) simplecov (>= 0.7) term-ansicolor (= 1.2.2) thor (= 0.18.1) diff-lcs (1.2.5) docile (1.1.5) erubis (2.7.0) ffi (1.9.10) formatador (0.2.5) gssapi (1.2.0) ffi (>= 1.0.1) guard (2.12.8) formatador (>= 0.2.4) listen (>= 2.7, <= 4.0) lumberjack (~> 1.0) nenv (~> 0.1) notiffany (~> 0.0) pry (>= 0.9.12) shellany (~> 0.0) thor (>= 0.18.1) guard-compat (1.2.1) guard-rspec (4.6.2) guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) gyoku (1.3.1) builder (>= 2.1.2) hashicorp-checkpoint (0.1.4) httpclient (2.6.0.1) i18n (0.7.0) json (1.8.3) listen (3.0.2) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) little-plugger (1.1.3) log4r (1.1.10) logging (1.8.2) little-plugger (>= 1.1.3) multi_json (>= 1.8.4) lumberjack (1.0.9) method_source (0.8.2) mime-types (2.6.1) mini_portile (0.6.0) multi_json (1.11.2) nenv (0.2.0) net-scp (1.1.2) net-ssh (>= 2.6.5) net-sftp (2.1.2) net-ssh (>= 2.6.5) net-ssh (2.9.2) nokogiri (1.6.3.1) mini_portile (= 0.6.0) nori (2.6.0) notiffany (0.0.6) nenv (~> 0.1) shellany (~> 0.0) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) rake (10.4.2) rb-fsevent (0.9.5) rb-inotify (0.9.5) ffi (>= 0.5.0) rb-kqueue (0.2.4) ffi (>= 0.5.0) rest-client (1.6.7) mime-types (>= 1.16) rspec (2.99.0) rspec-core (~> 2.99.0) rspec-expectations (~> 2.99.0) rspec-mocks (~> 2.99.0) rspec-core (2.99.2) rspec-expectations (2.99.2) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.99.4) rubyntlm (0.4.0) rubyzip (1.1.7) shellany (0.0.1) simplecov (0.10.0) docile (~> 1.1.0) json (~> 1.8) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slop (3.6.0) term-ansicolor (1.2.2) tins (~> 0.8) thor (0.18.1) tins (0.13.2) uuidtools (2.1.5) vagrant-omnibus (1.4.1) wdm (0.1.1) winrm (1.3.3) builder (>= 2.1.2) gssapi (~> 1.2) gyoku (~> 1.0) httpclient (~> 2.2, >= 2.2.0.2) logging (~> 1.6, >= 1.6.1) nori (~> 2.0) rubyntlm (~> 0.4.0) uuidtools (~> 2.1.2) winrm-fs (0.2.0) erubis (~> 2.7) logging (~> 1.6, >= 1.6.1) rubyzip (~> 1.1) winrm (~> 1.3.0) PLATFORMS ruby DEPENDENCIES coveralls guard guard-rspec rake rb-inotify rspec (= 2.99.0) vagrant! vagrant-cachier! vagrant-lxc! vagrant-omnibus vagrant-pristine! vagrant-spec! vagrant-lxc-1.2.1/Gemfile0000644000004100000410000000133312611107101015252 0ustar www-datawww-datasource 'https://rubygems.org' group :development do gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git', tag: 'v1.7.4' gem 'guard' gem 'guard-rspec' gem 'rb-inotify' end group :development, :test do gem 'rake' gem 'rspec', '2.99.0' gem 'coveralls', require: (ENV['COVERAGE'] == 'true') gem 'vagrant-spec', git: 'https://github.com/mitchellh/vagrant-spec.git' end group :plugins do acceptance = (ENV['ACCEPTANCE'] == 'true') gem 'vagrant-cachier', git: 'https://github.com/fgrehm/vagrant-cachier.git', require: !acceptance gem 'vagrant-pristine', git: 'https://github.com/fgrehm/vagrant-pristine.git', require: !acceptance gem 'vagrant-omnibus', require: !acceptance gemspec end vagrant-lxc-1.2.1/.rspec0000644000004100000410000000003712611107101015074 0ustar www-datawww-data--color --format documentation vagrant-lxc-1.2.1/LICENSE.txt0000644000004100000410000000206112611107101015601 0ustar www-datawww-dataCopyright (c) 2013-2014 Fábio Rehm MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. vagrant-lxc-1.2.1/templates/0000755000004100000410000000000012611107101015755 5ustar www-datawww-datavagrant-lxc-1.2.1/templates/sudoers.rb.erb0000644000004100000410000000750412611107101020543 0ustar www-datawww-data#!<%= cmd_paths['ruby'] %> # Automatically created by vagrant-lxc class Whitelist class << self def add(command, *args) list[command] ||= [] list[command] << args end def add_regex(regex, *args) regex_list << [regex, [args]] end def list @list ||= {} end def regex_list @regex_list ||= [] end def allowed(command) list[command] || allowed_regex(command) || [] end def allowed_regex(command) found = regex_list.find { |r| r[0] =~ command } return found[1] if found end def run!(argv) begin command, args = `which #{argv.shift}`.chomp, argv || [] check!(command, args) system "#{command} #{args.join(" ")}" exit_code = $?.to_i exit_code = 1 if exit_code == 256 exit exit_code rescue => e STDERR.puts e.message exit 1 end end private def check!(command, args) allowed(command).each do |checks| return if valid_args?(args, checks) end raise_invalid(command, args) end def valid_args?(args, checks) return false unless valid_length?(args, checks) check = nil args.each_with_index do |provided, i| check = checks[i] unless check == '**' return false unless match?(provided, check) end true end def valid_length?(args, checks) args.length == checks.length || checks.last == '**' end def match?(arg, check) check == '**' || check.is_a?(Regexp) && !!check.match(arg) || arg == check end def raise_invalid(command, args) raise "Invalid arguments for command #{command}, " << "provided args: #{args.inspect}" end end end base = "/var/lib/lxc" base_path = %r{\A#{base}/.*\z} ## # Commands from provider.rb # - Check lxc is installed Whitelist.add '<%= cmd_paths['which'] %>', /\Alxc-\w+\z/ ## # Commands from driver.rb # - Container config file Whitelist.add '<%= cmd_paths['cat'] %>', base_path # - Shared folders Whitelist.add '<%= cmd_paths['mkdir'] %>', '-p', base_path # - Container config customizations and pruning Whitelist.add '<%= cmd_paths['cp'] %>', '-f', %r{/tmp/.*}, base_path Whitelist.add '<%= cmd_paths['chown'] %>', 'root:root', base_path # - Packaging Whitelist.add '<%= cmd_paths['tar'] %>', '--numeric-owner', '-cvzf', %r{/tmp/.*/rootfs.tar.gz}, '-C', base_path, './rootfs' Whitelist.add '<%= cmd_paths['chown'] %>', /\A\d+:\d+\z/, %r{\A/tmp/.*/rootfs\.tar\.gz\z} # - Private network script and commands Whitelist.add '<%= cmd_paths['ip'] %>', 'addr', 'add', /(\d+|\.)+\/24/, 'dev', /.+/ Whitelist.add '<%= cmd_paths['ip'] %>', 'link', 'set', /.+/, /(up|down)/ Whitelist.add '<%= cmd_paths['brctl'] %>', /(addbr|delbr)/, /.+/ Whitelist.add_regex %r{<%= pipework_regex %>}, '**' ## # Commands from driver/cli.rb Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-version' Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-ls' Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-info', '--name', /.*/ Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-create', '-B', /.*/, '--template', /.*/, '--name', /.*/, '**' Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-create', '--version' Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-destroy', '--name', /.*/ Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-start', '-d', '--name', /.*/, '**' Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-stop', '--name', /.*/ Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-shutdown', '--name', /.*/ Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-attach', '--name', /.*/, '**' Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-attach', '-h' Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-config', 'lxc.lxcpath' ## # Commands from driver/action/remove_temporary_files.rb Whitelist.add '<%= cmd_paths['rm'] %>', '-rf', %r{\A#{base}/.*/rootfs/tmp/.*} # Watch out for stones Whitelist.run!(ARGV) vagrant-lxc-1.2.1/spec/0000755000004100000410000000000012611107101014711 5ustar www-datawww-datavagrant-lxc-1.2.1/spec/spec_helper.rb0000644000004100000410000000161412611107101017531 0ustar www-datawww-dataif ENV['COVERAGE'] require 'simplecov' require 'coveralls' SimpleCov.start { add_filter '/spec/' } SimpleCov.merge_timeout 300 end require 'bundler/setup' require 'i18n' require 'vagrant-lxc' Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f } RSpec.configure do |config| config.treat_symbols_as_metadata_keys_with_true_values = true config.run_all_when_everything_filtered = true config.filter_run :focus # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 config.order = 'random' config.mock_with :rspec do |c| c.yield_receiver_to_any_instance_implementation_blocks = true end config.expect_with :rspec do |c| c.syntax = :expect end config.raise_errors_for_deprecations! end vagrant-lxc-1.2.1/spec/unit_helper.rb0000644000004100000410000000063012611107101017553 0ustar www-datawww-datarequire 'spec_helper' Dir[File.dirname(__FILE__) + "/unit/support/**/*.rb"].each { |f| require f } if defined? SimpleCov SimpleCov.command_name 'unit' end RSpec.configure do |config| config.include UnitExampleGroup, :type => :unit, :example_group => { :file_path => /\bspec\/unit\// } config.mock_with :rspec do |c| c.yield_receiver_to_any_instance_implementation_blocks = true end end vagrant-lxc-1.2.1/spec/fixtures/0000755000004100000410000000000012611107101016562 5ustar www-datawww-datavagrant-lxc-1.2.1/spec/fixtures/sample-ip-addr-output0000644000004100000410000000022512611107101022641 0ustar www-datawww-data49: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 inet 10.0.254.137/24 brd 10.0.254.255 scope global eth0 vagrant-lxc-1.2.1/spec/Vagrantfile0000644000004100000410000000160312611107101017076 0ustar www-datawww-data# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.require_plugin 'vagrant-lxc' Vagrant.require_plugin 'vagrant-cachier' ENV['BOX_NAME'] ||= 'quantal64' puts "Running vagrant commands using #{ENV['BOX_NAME']} box" Vagrant.configure("2") do |config| config.vm.box = ENV['BOX_NAME'] config.vm.hostname = 'lxc-test-box' config.vm.box_url = ENV['BOX_URL'] config.vm.network :forwarded_port, guest: 80, host: 8080 config.cache.auto_detect = true config.vm.provider :lxc do |lxc| # lxc.sudo_wrapper = '/usr/bin/lxc-vagrant-wrapper' end config.vm.provision :shell, inline: 'mkdir -p /vagrant/tmp && echo -n "Provisioned" > /vagrant/tmp/provisioning' config.vm.provision :shell, inline: 'apt-get install apache2 -y' config.vm.provision :shell, privileged: false, inline: "if ! [ -f $HOME/original-box ]; then echo '#{ENV['BOX_NAME']}' > $HOME/original-box; fi" end vagrant-lxc-1.2.1/spec/unit/0000755000004100000410000000000012611107101015670 5ustar www-datawww-datavagrant-lxc-1.2.1/spec/unit/action/0000755000004100000410000000000012611107101017145 5ustar www-datawww-datavagrant-lxc-1.2.1/spec/unit/action/compress_rootfs_spec.rb0000644000004100000410000000200112611107101023724 0ustar www-datawww-datarequire 'unit_helper' require 'vagrant-lxc/plugin' require 'vagrant-lxc/provider' require 'vagrant-lxc/action/compress_rootfs' describe Vagrant::LXC::Action::CompressRootFS do let(:app) { double(:app, call: true) } let(:env) { {machine: machine, ui: double(info: true)} } let(:machine) { double(Vagrant::Machine, provider: provider) } let(:provider) { double(Vagrant::LXC::Provider, driver: driver) } let(:driver) { double(Vagrant::LXC::Driver, compress_rootfs: compressed_rootfs_path) } let(:compressed_rootfs_path) { '/path/to/rootfs.tar.gz' } subject { described_class.new(app, env) } before do provider.stub_chain(:state, :id).and_return(:stopped) subject.call(env) end it "asks the driver to compress container's rootfs" do expect(driver).to have_received(:compress_rootfs) end it 'sets export.temp_dir on action env' do expect(env['package.rootfs']).to eq(compressed_rootfs_path) end end vagrant-lxc-1.2.1/spec/unit/action/clear_forwarded_ports_spec.rb0000644000004100000410000000230212611107101025053 0ustar www-datawww-datarequire 'unit_helper' require 'tmpdir' require 'vagrant-lxc/action/clear_forwarded_ports' describe Vagrant::LXC::Action::ClearForwardedPorts do let(:app) { double(:app, call: true) } let(:env) { {machine: machine, ui: double(info: true)} } let(:machine) { double(:machine, data_dir: data_dir) } let!(:data_dir) { Pathname.new(Dir.mktmpdir) } let(:pids_dir) { data_dir.join('pids') } let(:pid) { 'a-pid' } let(:pid_cmd) { 'redir' } subject { described_class.new(app, env) } before do pids_dir.mkdir pids_dir.join('redir_1234.pid').open('w') { |f| f.write(pid) } subject.stub(system: true, :` => pid_cmd) subject.call(env) end after { FileUtils.rm_rf data_dir.to_s } it 'removes all files under pid directory' do expect(Dir[pids_dir.to_s + "/redir_*.pid"]).to be_empty end context 'with a valid redir pid' do it 'kills known processes' do expect(subject).to have_received(:system).with("pkill -TERM -P #{pid}") end end context 'with an invalid pid' do let(:pid_cmd) { 'sudo ls' } it 'does not kill the process' do expect(subject).not_to have_received(:system).with("pkill -TERM -P #{pid}") end end end vagrant-lxc-1.2.1/spec/unit/action/forward_ports_spec.rb0000644000004100000410000000711312611107101023401 0ustar www-datawww-datarequire 'unit_helper' require 'tmpdir' require 'vagrant-lxc/provider' require 'vagrant-lxc/action/forward_ports' describe Vagrant::LXC::Action::ForwardPorts do let(:app) { double(:app, call: true) } let(:env) { {machine: machine, ui: double(info: true, warn: true)} } let(:machine) { double(:machine) } let!(:data_dir) { Pathname.new(Dir.mktmpdir) } let(:provider) { double(Vagrant::LXC::Provider, ssh_info: {host: container_ip}) } let(:host_ip) { '127.0.0.1' } let(:host_port) { 8080 } let(:guest_port) { 80 } let(:container_ip) { '10.0.1.234' } let(:pid) { 'a-pid' } let(:forward_conf) { {guest: guest_port, host: host_port, host_ip: host_ip} } let(:networks) { [[:other_config, {}], [:forwarded_port, forward_conf]] } subject { described_class.new(app, env) } before do machine.stub_chain(:config, :vm, :networks).and_return(networks) machine.stub(provider: provider, data_dir: data_dir) subject.stub(exec: true) subject.stub(spawn: pid) end after { FileUtils.rm_rf data_dir.to_s } it 'forwards ports using redir' do subject.stub(system: true) subject.call(env) expect(subject).to have_received(:spawn).with( "redir --laddr=#{host_ip} --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null" ) end it 'Uses 127.0.0.1 as default if host_ip is nil' do forward_conf.delete(:host_ip) subject.stub(system: true) subject.call(env) expect(subject).to have_received(:spawn).with( "redir --laddr=127.0.0.1 --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null" ) end it 'Uses 127.0.0.1 by default if host_ip is a blank string' do forward_conf[:host_ip] = ' ' subject.stub(system: true) subject.call(env) expect(subject).to have_received(:spawn).with( "redir --laddr=127.0.0.1 --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null" ) end it "stores redir pids on machine's data dir" do subject.stub(system: true) subject.call(env) pid_file = data_dir.join('pids', "redir_#{host_port}.pid").read expect(pid_file).to eq(pid) end it 'allows disabling a previously forwarded port' do forward_conf[:disabled] = true subject.stub(system: true) subject.call(env) expect(subject).not_to have_received(:spawn) end it 'raises RedirNotInstalled error if `redir` is not installed' do subject.stub(system: false) expect { subject.call(env) }.to raise_error(Vagrant::LXC::Errors::RedirNotInstalled) end context 'when a privileged port is used' do let(:host_port) { 80 } it 'forwards ports using redir' do subject.stub(system: true) subject.call(env) expect(subject).to have_received(:spawn).with( "sudo redir --laddr=#{host_ip} --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null" ) end it 'Uses 127.0.0.1 by default if host_ip is nil' do forward_conf.delete(:host_ip) subject.stub(system: true) subject.call(env) expect(subject).to have_received(:spawn).with( "sudo redir --laddr=127.0.0.1 --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null" ) end it 'Uses 127.0.0.1 by default if host_ip is a blank string' do forward_conf[:host_ip] = ' ' subject.stub(system: true) subject.call(env) expect(subject).to have_received(:spawn).with( "sudo redir --laddr=127.0.0.1 --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null" ) end end end vagrant-lxc-1.2.1/spec/unit/action/setup_package_files_spec.rb0000644000004100000410000000457412611107101024513 0ustar www-datawww-datarequire 'unit_helper' require 'vagrant-lxc/action/setup_package_files' describe Vagrant::LXC::Action::SetupPackageFiles do let(:app) { double(:app, call: true) } let(:env) { {machine: machine, tmp_path: tmp_path, ui: double(info: true), 'package.rootfs' => rootfs_path} } let(:machine) { double(Vagrant::Machine, box: box) } let!(:tmp_path) { Pathname.new(Dir.mktmpdir) } let(:box) { double(Vagrant::Box, directory: tmp_path.join('box')) } let(:rootfs_path) { tmp_path.join('rootfs-amd64.tar.gz') } subject { described_class.new(app, env) } before do box.directory.mkdir files = %w( lxc-template metadata.json lxc.conf lxc-config ).map { |f| box.directory.join(f) } (files + [rootfs_path]).each do |file| file.open('w') { |f| f.puts file.to_s } end subject.stub(recover: true) # Prevents files from being removed on specs end after do FileUtils.rm_rf(tmp_path.to_s) end context 'when all files exist' do before { subject.call(env) } it 'copies box lxc-template to package directory' do expect(env['package.directory'].join('lxc-template')).to be_file end it 'copies metadata.json to package directory' do expect(env['package.directory'].join('metadata.json')).to be_file end it 'copies box lxc.conf to package directory' do expect(env['package.directory'].join('lxc-template')).to be_file end it 'copies box lxc-config to package directory' do expect(env['package.directory'].join('lxc-config')).to be_file end it 'moves the compressed rootfs to package directory' do expect(env['package.directory'].join(rootfs_path.basename)).to be_file expect(env['package.rootfs']).not_to be_file end end context 'when lxc-template file is not present' do before do box.directory.join('lxc-template').delete end it 'does not blow up' do expect { subject.call(env) }.to_not raise_error end end context 'when lxc.conf file is not present' do before do box.directory.join('lxc.conf').delete end it 'does not blow up' do expect { subject.call(env) }.to_not raise_error end end context 'when lxc-config file is not present' do before do box.directory.join('lxc-config').delete end it 'does not blow up' do expect { subject.call(env) }.to_not raise_error end end end vagrant-lxc-1.2.1/spec/unit/action/handle_box_metadata_spec.rb0000644000004100000410000001011512611107101024445 0ustar www-datawww-datarequire 'unit_helper' require 'vagrant' require 'vagrant-lxc/errors' require 'vagrant-lxc/action/handle_box_metadata' describe Vagrant::LXC::Action::HandleBoxMetadata do let(:app) { double(:app, call: true) } let(:env) { {machine: machine, ui: double(info: true, warn: true)} } let(:machine) { double(:machine, box: box) } let(:box) { double(:box, name: 'box-name', metadata: metadata, directory: box_directory) } let(:box_directory) { Pathname.new('/path/to/box') } let(:version) { '2' } let(:metadata) { {'template-opts' => {'--foo' => 'bar'}, 'version' => version} } let(:vagrant_key) { Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s } subject { described_class.new(app, env) } context 'with 1.0.0 box' do let(:version) { '1.0.0' } before do File.stub(exists?: true) # REFACTOR: This is pretty bad subject.stub_chain(:template_config_file, :exist?).and_return(true) subject.stub_chain(:template_config_file, :to_s).and_return(box_directory.join('lxc-config').to_s) subject.call(env) end it 'sets the tarball argument for the template' do expect(env[:lxc_template_opts]).to include( '--tarball' => box_directory.join('rootfs.tar.gz').to_s ) end it 'sets the template --config parameter' do expect(env[:lxc_template_opts]).to include( '--config' => box_directory.join('lxc-config').to_s ) end it 'does not set the auth key argument for the template' do expect(env[:lxc_template_opts]).not_to include( '--auth-key' => vagrant_key ) end it 'sets the template options from metadata on env hash' do expect(env[:lxc_template_opts]).to include(metadata['template-opts']) end xit 'sets the template source path on env hash' do expect(env[:lxc_template_src]).to eq(box_directory.join('lxc-template').to_s) end it 'does not warn about deprecation' do expect(env[:ui]).not_to have_received(:warn) end end context 'with valid pre 1.0.0 box' do before do File.stub(exists?: true) # REFACTOR: This is pretty bad subject.stub_chain(:old_template_config_file, :exist?).and_return(true) subject.stub_chain(:old_template_config_file, :to_s).and_return(box_directory.join('lxc.conf').to_s) subject.call(env) end it 'sets the tarball argument for the template' do expect(env[:lxc_template_opts]).to include( '--tarball' => box_directory.join('rootfs.tar.gz').to_s ) end it 'sets the auth key argument for the template' do expect(env[:lxc_template_opts]).to include( '--auth-key' => vagrant_key ) end it 'sets the lxc config file parameter' do expect(env[:lxc_template_config]).to eq(box_directory.join('lxc.conf').to_s) end it 'sets the template options from metadata on env hash' do expect(env[:lxc_template_opts]).to include(metadata['template-opts']) end xit 'sets the template source path on env hash' do expect(env[:lxc_template_src]).to eq(box_directory.join('lxc-template').to_s) end it 'warns about deprecation' do expect(env[:ui]).to have_received(:warn) end end describe 'with invalid contents' do before { File.stub(exists?: true) } it 'validates box versions' do %w( 2 3 1.0.0 ).each do |v| metadata['version'] = v expect { subject.call(env) }.to_not raise_error end metadata['version'] = '1' expect { subject.call(env) }.to raise_error end it 'raises an error if the rootfs tarball cant be found' do allow(File).to receive(:exists?).with(box_directory.join('rootfs.tar.gz').to_s).and_return(false) expect { subject.call(env) }.to raise_error(Vagrant::LXC::Errors::RootFSTarballMissing) end it 'does not raise an error if the lxc-template script cant be found' do allow(File).to receive(:exists?).with(box_directory.join('lxc-template').to_s).and_return(false) expect { subject.call(env) }.to_not raise_error end end end vagrant-lxc-1.2.1/spec/unit/driver/0000755000004100000410000000000012611107101017163 5ustar www-datawww-datavagrant-lxc-1.2.1/spec/unit/driver/cli_spec.rb0000644000004100000410000002201512611107101021271 0ustar www-datawww-datarequire 'unit_helper' require 'vagrant-lxc/sudo_wrapper' require 'vagrant-lxc/driver/cli' describe Vagrant::LXC::Driver::CLI do let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true, wrapper_path: nil) } subject { described_class.new(sudo_wrapper) } describe 'list' do let(:lxc_ls_out) { "dup-container\na-container dup-container" } let(:result) { @result } before do allow(subject).to receive(:run).with(:ls).and_return(lxc_ls_out) @result = subject.list end it 'grabs previously created containers from lxc-ls output' do expect(result).to be_an Enumerable expect(result).to include 'a-container' expect(result).to include 'dup-container' end it 'removes duplicates from lxc-ls output' do expect(result.uniq).to eq(result) end end describe 'version' do before do allow(subject).to receive(:support_version_command?).and_return(true) allow(subject).to receive(:run).with(:version).and_return(lxc_version_out) end describe 'lxc version before 1.x.x' do let(:lxc_version_out) { "lxc version: 0.x.y-rc1\n" } it 'parses the version from the output' do expect(subject.version).to eq('0.x.y-rc1') end end describe 'lxc version after 1.x.x' do let(:lxc_version_out) { "1.0.0\n" } it 'parses the version from the output' do expect(subject.version).to eq('1.0.0') end end end describe 'config' do before do allow(subject).to receive(:support_version_command?).and_return(support_version_command?) allow(subject).to receive(:run).with(:config, 'lxc.lxcpath').and_return(lxc_config_out) allow(subject).to receive(:run).with(:version).and_return(lxc_version_out) allow(subject).to receive(:run).with(:create, '--version').and_return(lxc_version_out) end describe 'lxc version before 1.x.x' do let(:support_version_command?) { true } let(:lxc_config_out) { "/var/lib/lxc\n" } let(:lxc_version_out) { "lxc version: 0.x.y-rc1\n" } it 'not supported' do expect{subject.config('lxc.lxcpath')}.to raise_error(Vagrant::LXC::Errors::CommandNotSupported) end end describe 'lxc version before after 1.x.x'do let(:support_version_command?) { false } let(:lxc_config_out) { "/var/lib/lxc\n" } let(:lxc_version_out) { "1.0.0\n" } it 'parser the lxc.lxcpath value' do expect(subject.config('lxc.lxcpath')).not_to end_with("\n") end end end describe 'create' do let(:template) { 'quantal-64' } let(:name) { 'quantal-container' } let(:backingstore) { 'btrfs' } let(:backingstore_opts) { [['--dir', '/tmp/foo'], ['--foo', 'bar']] } let(:config_file) { 'config' } let(:template_args) { { '--extra-param' => 'param', '--other' => 'value' } } subject { described_class.new(sudo_wrapper, name) } before do allow(subject).to receive(:run) { |*args| @run_args = args } end it 'issues a lxc-create with provided template, container name and hash of arguments' do subject.create(template, backingstore, backingstore_opts, config_file, template_args) expect(subject).to have_received(:run).with( :create, '-B', backingstore, '--template', template, '--name', name, *(backingstore_opts.flatten), '-f', config_file, '--', '--extra-param', 'param', '--other', 'value' ) end it 'wraps a low level error into something more meaningful in case the container already exists' do allow(subject).to receive(:run) { raise Vagrant::LXC::Errors::ExecuteError, stderr: 'alreAdy Exists' } expect { subject.create(template, backingstore, backingstore_opts, config_file, template_args) }.to raise_error(Vagrant::LXC::Errors::ContainerAlreadyExists) end end describe 'destroy' do let(:name) { 'a-container-for-destruction' } subject { described_class.new(sudo_wrapper, name) } before do allow(subject).to receive(:run) subject.destroy end it 'issues a lxc-destroy with container name' do expect(subject).to have_received(:run).with(:destroy, '--name', name) end end describe 'start' do let(:name) { 'a-container' } subject { described_class.new(sudo_wrapper, name) } before do allow(subject).to receive(:run) end it 'starts container on the background' do subject.start expect(subject).to have_received(:run).with( :start, '-d', '--name', name ) end end describe 'stop' do let(:name) { 'a-running-container' } subject { described_class.new(sudo_wrapper, name) } before do allow(subject).to receive(:run) end context 'lxc-attach is supported' do before do subject.stub(attach: true, supports_attach?: true) subject.stop end it 'runs a /sbin/halt within the container' do expect(subject).to have_received(:attach).with('/sbin/halt') end it 'issues a lxc-stop with provided container name' do expect(subject).to have_received(:run).with(:stop, '--name', name) end end context 'lxc-attach is not supported' do before do subject.stub(attach: false, supports_attach?: false) subject.stop end it 'runs a /sbin/halt within the container' do expect(subject).to_not have_received(:attach) end it 'issues a lxc-stop with provided container name' do expect(subject).to have_received(:run).with(:stop, '--name', name) end end end describe 'state' do let(:name) { 'a-container' } subject { described_class.new(sudo_wrapper, name) } before do allow(subject).to receive(:run).and_return("state: STOPPED\npid: 2") end it 'calls lxc-info with the right arguments' do subject.state expect(subject).to have_received(:run).with(:info, '--name', name, retryable: true) end it 'maps the output of lxc-info status out to a symbol' do expect(subject.state).to eq(:stopped) end it 'is not case sensitive' do allow(subject).to receive(:run).and_return("StatE: STarTED\npid: 2") expect(subject.state).to eq(:started) end end describe 'attach' do let(:name) { 'a-running-container' } let(:command) { ['ls', 'cat /tmp/file'] } let(:command_output) { 'folders list' } subject { described_class.new(sudo_wrapper, name) } before do subject.stub(run: command_output) end it 'calls lxc-attach with specified command' do subject.attach(*command) expect(subject).to have_received(:run).with(:attach, '--name', name, '--', *command) end it 'supports a "namespaces" parameter' do allow(subject).to receive(:run).with(:attach, '-h', :show_stderr => true).and_return({:stdout => '', :stderr => '--namespaces'}) subject.attach *(command + [{namespaces: ['network', 'mount']}]) expect(subject).to have_received(:run).with(:attach, '--name', name, '--namespaces', 'NETWORK|MOUNT', '--', *command) end it 'raises a NamespacesNotSupported error if not supported' do allow(subject).to receive(:run).with(:attach, '-h', :show_stderr => true).and_return({:stdout => '', :stderr => 'not supported'}) expect { subject.attach *(command + [{namespaces: ['network', 'mount']}]) }.to raise_error(Vagrant::LXC::Errors::NamespacesNotSupported) end end describe 'transition block' do before do subject.stub(run: true, sleep: true, state: :stopped) end it 'yields a cli object' do allow(subject).to receive(:shutdown) subject.transition_to(:stopped) { |c| c.shutdown } expect(subject).to have_received(:shutdown) end it 'throws an exception if block is not provided' do expect { subject.transition_to(:running) }.to raise_error(described_class::TransitionBlockNotProvided) end skip 'waits for the expected container state' end describe 'check for whether lxc-attach is supported' do let(:name) { 'a-running-container' } subject { described_class.new(sudo_wrapper, name) } context 'lxc-attach is present on system' do before { subject.stub(run: true) } it 'returns true if `lxc-attach --name CNAME -- /bin/true` works' do expect(subject.supports_attach?).to be_truthy expect(subject).to have_received(:run).with( :attach, '--name', name, '--', '/bin/true' ) end end context 'lxc-attach is not present on system' do before do allow(subject).to receive(:run).and_raise(Vagrant::LXC::Errors::ExecuteError.new('msg')) end it 'returns true if `lxc-attach --name CNAME -- /bin/true` works' do expect(subject.supports_attach?).to be_falsy expect(subject).to have_received(:run).with( :attach, '--name', name, '--', '/bin/true' ) end end end end vagrant-lxc-1.2.1/spec/unit/support/0000755000004100000410000000000012611107101017404 5ustar www-datawww-datavagrant-lxc-1.2.1/spec/unit/support/unit_example_group.rb0000644000004100000410000000254112611107101023641 0ustar www-datawww-datamodule UnitExampleGroup def self.included(base) base.metadata[:type] = :unit base.before do allow_any_instance_of(Object).to receive(:system) { |instance, *args, &block| UnitExampleGroup.prevent_system_calls(*args, &block) } allow_any_instance_of(Object).to receive(:`) { |instance, *args, &block| UnitExampleGroup.prevent_system_calls(*args, &block) } allow_any_instance_of(Object).to receive(:exec) { |instance, *args, &block| UnitExampleGroup.prevent_system_calls(*args, &block) } allow_any_instance_of(Object).to receive(:fork) { |instance, *args, &block| UnitExampleGroup.prevent_system_calls(*args, &block) } allow_any_instance_of(Object).to receive(:spawn) { |instance, *args, &block| UnitExampleGroup.prevent_system_calls(*args, &block) } require 'vagrant/util/subprocess' allow(Vagrant::Util::Subprocess).to receive(:execute) { |*args, &block| UnitExampleGroup.prevent_system_calls(*args, &block) } end end def self.prevent_system_calls(*args, &block) args.pop if args.last.is_a?(Hash) raise <<-MSG Somehow your code under test is trying to execute a command on your system, please stub it out or move your spec code to an acceptance spec. Block: #{block.inspect} Command: "#{args.join(' ')}" MSG end end vagrant-lxc-1.2.1/spec/unit/driver_spec.rb0000644000004100000410000002175112611107101020530 0ustar www-datawww-datarequire 'unit_helper' require 'vagrant-lxc/driver' require 'vagrant-lxc/driver/cli' require 'vagrant-lxc/sudo_wrapper' describe Vagrant::LXC::Driver do describe 'container name validation' do let(:unknown_container) { described_class.new('unknown', nil, cli) } let(:valid_container) { described_class.new('valid', nil, cli) } let(:new_container) { described_class.new(nil, nil) } let(:cli) { double(Vagrant::LXC::Driver::CLI, list: ['valid']) } it 'raises a ContainerNotFound error if an unknown container name gets provided' do expect { unknown_container.validate! }.to raise_error end it 'does not raise a ContainerNotFound error if a valid container name gets provided' do expect { valid_container.validate! }.not_to raise_error end it 'does not raise a ContainerNotFound error if nil is provider as name' do expect { new_container.validate! }.not_to raise_error end end describe 'creation' do let(:name) { 'container-name' } let(:backingstore) { 'btrfs' } let(:backingstore_opts) { [['--dir', '/tmp/foo'], ['--foo', 'bar']] } let(:template_name) { 'auto-assigned-template-id' } let(:template_path) { '/path/to/lxc-template-from-box' } let(:template_opts) { {'--some' => 'random-option'} } let(:config_file) { '/path/to/lxc-config-from-box' } let(:rootfs_tarball) { '/path/to/cache/rootfs.tar.gz' } let(:cli) { double(Vagrant::LXC::Driver::CLI, :create => true, :name= => true) } subject { described_class.new(nil, nil, cli) } before do allow(subject).to receive(:import_template).and_yield(template_name) subject.create name, backingstore, backingstore_opts, template_path, config_file, template_opts end it 'sets the cli object container name' do expect(cli).to have_received(:name=).with(name) end it 'creates container with the right arguments' do expect(cli).to have_received(:create).with( template_path, backingstore, backingstore_opts, config_file, template_opts ) end end describe 'destruction' do let(:cli) { double(Vagrant::LXC::Driver::CLI, destroy: true) } subject { described_class.new('name', nil, cli) } before { subject.destroy } it 'delegates to cli object' do expect(cli).to have_received(:destroy) end end describe 'supports_attach?' do let(:cli) { double(Vagrant::LXC::Driver::CLI, supports_attach?: true) } subject { described_class.new('name', nil, cli) } it 'delegates to cli object' do expect(subject.supports_attach?).to be_truthy expect(cli).to have_received(:supports_attach?) end end describe 'start' do let(:customizations) { [['a', '1'], ['b', '2']] } let(:internal_customization) { ['internal', 'customization'] } let(:cli) { double(Vagrant::LXC::Driver::CLI, start: true, support_config_command?: false) } let(:sudo) { double(Vagrant::LXC::SudoWrapper) } subject { described_class.new('name', sudo, cli) } before do sudo.should_receive(:run).with('cat', '/var/lib/lxc/name/config').exactly(2).times. and_return('# CONFIGURATION') sudo.should_receive(:run).twice.with('cp', '-f', %r{/(run|tmp)/.*}, '/var/lib/lxc/name/config') sudo.should_receive(:run).twice.with('chown', 'root:root', '/var/lib/lxc/name/config') subject.customizations << internal_customization subject.start(customizations) end it 'prunes previous customizations before writing' it 'writes configurations to config file' it 'starts container with configured customizations' do expect(cli).to have_received(:start) end end describe 'halt' do let(:cli) { double(Vagrant::LXC::Driver::CLI, stop: true) } subject { described_class.new('name', nil, cli) } before do allow(cli).to receive(:transition_to).and_yield(cli) end it 'delegates to cli stop' do expect(cli).to receive(:stop) subject.forced_halt end it 'expects a transition to running state to take place' do expect(cli).to receive(:transition_to).with(:stopped) subject.forced_halt end it 'attempts to force the container to stop in case a shutdown doesnt work' do allow(cli).to receive(:shutdown).and_raise(Vagrant::LXC::Driver::CLI::TargetStateNotReached.new :target, :source) expect(cli).to receive(:transition_to).with(:stopped) expect(cli).to receive(:stop) subject.forced_halt end end describe 'state' do let(:cli_state) { :something } let(:cli) { double(Vagrant::LXC::Driver::CLI, state: cli_state) } subject { described_class.new('name', nil, cli) } it 'delegates to cli' do expect(subject.state).to eq(cli_state) end end describe 'containers_path' do let(:cli) { double(Vagrant::LXC::Driver::CLI, config: cli_config_value, support_config_command?: cli_support_config_command_value) } subject { described_class.new('name', nil, cli) } describe 'lxc version before 1.x.x' do let(:cli_support_config_command_value) { false } let(:cli_config_value) { '/var/lib/lxc' } it 'delegates to cli' do expect(subject.containers_path).to eq(cli_config_value) end end describe 'lxc version after 1.x.x' do let(:cli_support_config_command_value) { true } let(:cli_config_value) { '/etc/lxc' } it 'delegates to cli' do expect(subject.containers_path).to eq(cli_config_value) end end end describe 'folder sharing' do let(:shared_folder) { {guestpath: '/vagrant', hostpath: '/path/to/host/dir'} } let(:ro_rw_folder) { {guestpath: '/vagrant/ro_rw', hostpath: '/path/to/host/dir', mount_options: ['ro', 'rw']} } let(:with_space_folder) { {guestpath: '/tmp/with space', hostpath: '/path/with space'} } let(:folders) { [shared_folder, ro_rw_folder, with_space_folder] } let(:expected_guest_path) { "vagrant" } let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true) } let(:rootfs_path) { Pathname('/path/to/rootfs') } subject { described_class.new('name', sudo_wrapper) } describe "with fixed rootfs" do before do subject.stub(rootfs_path: Pathname('/path/to/rootfs'), system: true) subject.share_folders(folders) end it 'adds a mount.entry to its local customizations' do expect(subject.customizations).to include [ 'mount.entry', "#{shared_folder[:hostpath]} #{expected_guest_path} none bind,create=dir 0 0" ] end it 'supports additional mount options' do expect(subject.customizations).to include [ 'mount.entry', "#{ro_rw_folder[:hostpath]} vagrant/ro_rw none ro,rw 0 0" ] end it 'supports directories with spaces' do expect(subject.customizations).to include [ 'mount.entry', "/path/with\\040space tmp/with\\040space none bind,create=dir 0 0" ] end end describe "with directory-based LXC config" do let(:config_string) { <<-ENDCONFIG.gsub(/^\s+/, '') # Blah blah comment lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 lxc.mount.entry = sysfs sys sysfs defaults 0 0 lxc.tty = 4 lxc.pts = 1024 lxc.rootfs = #{rootfs_path} # VAGRANT-BEGIN lxc.network.type=veth lxc.network.name=eth1 # VAGRANT-END ENDCONFIG } before do subject { described_class.new('name', sudo_wrapper) } subject.stub(config_string: config_string) subject.share_folders(folders) end it 'adds a mount.entry to its local customizations' do expect(subject.customizations).to include [ 'mount.entry', "#{shared_folder[:hostpath]} #{expected_guest_path} none bind,create=dir 0 0" ] end end describe "with overlayfs-based LXC config" do let(:config_string) { <<-ENDCONFIG.gsub(/^\s+/, '') # Blah blah comment lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 lxc.mount.entry = sysfs sys sysfs defaults 0 0 lxc.tty = 4 lxc.pts = 1024 lxc.rootfs = overlayfs:/path/to/master/directory:#{rootfs_path} # VAGRANT-BEGIN lxc.network.type=veth lxc.network.name=eth1 # VAGRANT-END ENDCONFIG } before do subject { described_class.new('name', sudo_wrapper) } subject.stub(config_string: config_string) subject.share_folders(folders) end it 'adds a mount.entry to its local customizations' do expect(subject.customizations).to include [ 'mount.entry', "#{shared_folder[:hostpath]} #{expected_guest_path} none bind,create=dir 0 0" ] end end end end vagrant-lxc-1.2.1/spec/support/0000755000004100000410000000000012611107101016425 5ustar www-datawww-datavagrant-lxc-1.2.1/spec/support/.gitkeep0000644000004100000410000000000012611107101020044 0ustar www-datawww-datavagrant-lxc-1.2.1/.travis.yml0000644000004100000410000000016112611107101016066 0ustar www-datawww-datalanguage: ruby rvm: - 2.0.0 - 2.1.1 matrix: allow_failures: - rvm: 2.1.1 script: "bundle exec rake ci" vagrant-lxc-1.2.1/lib/0000755000004100000410000000000012611107101014525 5ustar www-datawww-datavagrant-lxc-1.2.1/lib/vagrant-lxc.rb0000644000004100000410000000045112611107101017300 0ustar www-datawww-datarequire "vagrant-lxc/version" require "vagrant-lxc/plugin" module Vagrant module LXC def self.source_root @source_root ||= Pathname.new(File.dirname(__FILE__)).join('..').expand_path end def self.sudo_wrapper_path "/usr/local/bin/vagrant-lxc-wrapper" end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/0000755000004100000410000000000012611107101016753 5ustar www-datawww-datavagrant-lxc-1.2.1/lib/vagrant-lxc/action/0000755000004100000410000000000012611107101020230 5ustar www-datawww-datavagrant-lxc-1.2.1/lib/vagrant-lxc/action/prepare_nfs_settings.rb0000644000004100000410000000356112611107101025006 0ustar www-datawww-datamodule Vagrant module LXC module Action class PrepareNFSSettings include Vagrant::Util::Retryable def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::action::vm::nfs") end def call(env) @machine = env[:machine] @app.call(env) # if using_nfs? # TODO: && !privileged_container? # raise Errors::NfsWithoutPrivilegedError # end if using_nfs? @logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP") add_ips_to_env!(env) end end # We're using NFS if we have any synced folder with NFS configured. If # we are not using NFS we don't need to do the extra work to # populate these fields in the environment. def using_nfs? @machine.config.vm.synced_folders.any? { |_, opts| opts[:type] == :nfs } end # TODO: # def privileged_container? # @machine.provider.driver.privileged?(@machine.id) # end # Extracts the proper host and guest IPs for NFS mounts and stores them # in the environment for the SyncedFolder action to use them in # mounting. # # The ! indicates that this method modifies its argument. def add_ips_to_env!(env) provider = @machine.provider host_ip = read_host_ip machine_ip = provider.ssh_info[:host] raise Vagrant::Errors::NFSNoHostonlyNetwork if !host_ip || !machine_ip env[:nfs_host_ip] = host_ip env[:nfs_machine_ip] = machine_ip end def read_host_ip @machine.communicate.execute 'echo $SSH_CLIENT' do |buffer, output| return output.chomp.split(' ')[0] if buffer == :stdout end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/destroy_confirm.rb0000644000004100000410000000067412611107101023772 0ustar www-datawww-datarequire "vagrant/action/builtin/confirm" module Vagrant module LXC module Action class DestroyConfirm < Vagrant::Action::Builtin::Confirm def initialize(app, env) force_key = :force_confirm_destroy message = I18n.t("vagrant.commands.destroy.confirmation", :name => env[:machine].name) super(app, env, message, force_key) end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/destroy.rb0000644000004100000410000000056412611107101022253 0ustar www-datawww-datamodule Vagrant module LXC module Action class Destroy def initialize(app, env) @app = app end def call(env) env[:ui].info I18n.t("vagrant.actions.vm.destroy.destroying") env[:machine].provider.driver.destroy env[:machine].id = nil @app.call env end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/warn_networks.rb0000644000004100000410000000103212611107101023454 0ustar www-datawww-datamodule Vagrant module LXC module Action class WarnNetworks def initialize(app, env) @app = app end def call(env) if public_network_configured?(env[:machine].config) env[:ui].warn(I18n.t("vagrant_lxc.messages.warn_networks")) end @app.call(env) end def public_network_configured?(config) config.vm.networks.find do |type, _| type.to_sym == :public_network end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/setup_package_files.rb0000644000004100000410000000322712611107101024556 0ustar www-datawww-datarequire 'fileutils' module Vagrant module LXC module Action class SetupPackageFiles def initialize(app, env) @app = app env["package.include"] ||= [] env["package.vagrantfile"] ||= nil end def call(env) @env = env create_package_temp_dir move_rootfs_to_pkg_dir copy_box_files_to_pkg_dir @app.call env recover # called to cleanup temp directory end def recover(*) if @temp_dir && File.exist?(@temp_dir) FileUtils.rm_rf(@temp_dir) end end private def create_package_temp_dir @env[:ui].info I18n.t("vagrant.actions.vm.export.create_dir") @temp_dir = @env["package.directory"] = @env[:tmp_path].join("container-export-#{Time.now.to_i.to_s}") FileUtils.mkpath(@temp_dir) end def move_rootfs_to_pkg_dir FileUtils.mv @env['package.rootfs'].to_s, @env['package.directory'].to_s end def copy_box_files_to_pkg_dir box_dir = @env[:machine].box.directory FileUtils.cp box_dir.join('metadata.json').to_s, @env['package.directory'].to_s if (template = box_dir.join('lxc-template')).exist? FileUtils.cp template.to_s, @env['package.directory'].to_s end if (conf = box_dir.join('lxc.conf')).exist? FileUtils.cp conf.to_s, @env['package.directory'].to_s end if (conf = box_dir.join('lxc-config')).exist? FileUtils.cp conf.to_s, @env['package.directory'].to_s end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/boot.rb0000644000004100000410000000241312611107101021520 0ustar www-datawww-datamodule Vagrant module LXC module Action class Boot def initialize(app, env) @app = app end def call(env) @env = env config = env[:machine].provider_config utsname = env[:machine].config.vm.hostname || env[:machine].id config.customize 'utsname', utsname # Fix apparmor issues when starting Ubuntu 14.04 containers # See https://github.com/fgrehm/vagrant-lxc/issues/278 for more information if Dir.exists?('/sys/fs/pstore') config.customize 'mount.entry', '/sys/fs/pstore sys/fs/pstore none bind,optional 0 0' end # Make selinux read-only, see # https://github.com/fgrehm/vagrant-lxc/issues/301 if Dir.exists?('/sys/fs/selinux') config.customize 'mount.entry', '/sys/fs/selinux sys/fs/selinux none bind,ro 0 0' end # Make /tmp a tmpfs to prevent init scripts from nuking synced folders mounted in here config.customize 'mount.entry', 'tmpfs tmp tmpfs nodev,nosuid,size=2G 0 0' env[:ui].info I18n.t("vagrant_lxc.messages.starting") env[:machine].provider.driver.start(config.customizations) @app.call env end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/gc_private_network_bridges.rb0000644000004100000410000000257712611107101026163 0ustar www-datawww-datamodule Vagrant module LXC module Action class GcPrivateNetworkBridges def initialize(app, env) @app = app end def call(env) was_running = env[:machine].provider.state.id == :running # Continue execution, we need the container to be stopped @app.call(env) was_running = was_running && env[:machine].provider.state.id != :running if was_running && private_network_configured?(env[:machine].config) private_network_configured?(env[:machine].config) remove_bridges_that_are_not_in_use(env) end end def private_network_configured?(config) config.vm.networks.find do |type, _| type.to_sym == :private_network end end def remove_bridges_that_are_not_in_use(env) env[:machine].config.vm.networks.find do |type, config| next if type.to_sym != :private_network bridge = config.fetch(:lxc__bridge_name) driver = env[:machine].provider.driver if ! driver.bridge_is_in_use?(bridge) env[:ui].info I18n.t("vagrant_lxc.messages.remove_bridge", name: bridge) unless ['lxcbr0', 'virbr0'].include? bridge driver.remove_bridge(bridge) end end end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/compress_rootfs.rb0000644000004100000410000000131212611107101024001 0ustar www-datawww-datarequire "fileutils" module Vagrant module LXC module Action class CompressRootFS def initialize(app, env) @app = app end def call(env) raise Vagrant::Errors::VMPowerOffToPackage if env[:machine].provider.state.id != :stopped env[:ui].info I18n.t("vagrant.actions.lxc.compressing_rootfs") @rootfs = env['package.rootfs'] = env[:machine].provider.driver.compress_rootfs @app.call env recover # called to remove the rootfs tarball end def recover(*) if @rootfs && File.exist?(@rootfs) FileUtils.rm_rf(File.dirname @rootfs) end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/private_networks.rb0000644000004100000410000000247512611107101024173 0ustar www-datawww-datamodule Vagrant module LXC module Action class PrivateNetworks def initialize(app, env) @app = app end def call(env) @app.call(env) if private_network_configured?(env[:machine].config) env[:ui].output(I18n.t("vagrant_lxc.messages.setup_private_network")) configure_private_networks(env) end end def private_network_configured?(config) config.vm.networks.find do |type, _| type.to_sym == :private_network end end def configure_private_networks(env) env[:machine].config.vm.networks.find do |type, config| next if type.to_sym != :private_network container_name = env[:machine].provider.driver.container_name address_type = config[:type] ip = config[:ip] bridge_ip = config.fetch(:lxc__bridge_ip) { build_bridge_ip(ip) } bridge = config.fetch(:lxc__bridge_name) env[:machine].provider.driver.configure_private_network(bridge, bridge_ip, container_name, address_type, ip) end end def build_bridge_ip(ip) if ip ip.sub(/^(\d+\.\d+\.\d+)\.\d+/, '\1.254') end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/clear_forwarded_ports.rb0000644000004100000410000000310412611107101025125 0ustar www-datawww-datamodule Vagrant module LXC module Action class ClearForwardedPorts def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::lxc::action::clear_forwarded_ports") end def call(env) @env = env if redir_pids.any? env[:ui].info I18n.t("vagrant.actions.vm.clear_forward_ports.deleting") redir_pids.each do |pid| next unless is_redir_pid?(pid[0]) @logger.debug "Killing pid #{pid[0]}" if pid[1] system "sudo pkill -TERM -P #{pid[0]}" else system "pkill -TERM -P #{pid[0]}" end end @logger.info "Removing redir pids files" remove_redir_pids else @logger.info "No redir pids found" end @app.call env end protected def redir_pids @redir_pids = Dir[@env[:machine].data_dir.join('pids').to_s + "/redir_*.pid"].map do |file| port_number = File.basename(file).split(/[^\d]/).join [ File.read(file).strip.chomp , Integer(port_number) <= 1024 ] end end def is_redir_pid?(pid) @logger.debug "Checking if #{pid} is a redir process with `ps -o cmd= #{pid}`" `ps -o cmd= #{pid}`.strip.chomp =~ /redir/ end def remove_redir_pids Dir[@env[:machine].data_dir.join('pids').to_s + "/redir_*.pid"].each do |file| File.delete file end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/fetch_ip_from_dnsmasq_leases.rb0000644000004100000410000000256512611107101026453 0ustar www-datawww-datamodule Vagrant module LXC module Action class FetchIpFromDnsmasqLeases def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_from_dnsmasq_leases") end def call(env) env[:machine_ip] ||= assigned_ip(env) @app.call(env) end def assigned_ip(env) mac_address = env[:machine].provider.driver.mac_address ip = nil 10.times do dnsmasq_leases = read_dnsmasq_leases @logger.debug "Attempting to load ip from dnsmasq leases (mac: #{mac_address})" @logger.debug dnsmasq_leases if dnsmasq_leases =~ /#{Regexp.escape mac_address.to_s}\s+([0-9.]+)\s+/i ip = $1.to_s break else @logger.debug 'Ip could not be parsed from dnsmasq leases file' sleep 2 end end ip end LEASES_PATHS = %w( /var/lib/misc/dnsmasq.*.leases /var/lib/misc/dnsmasq.leases /var/lib/dnsmasq/dnsmasq.leases /var/db/dnsmasq.leases /var/lib/libvirt/dnsmasq/*.leases ) def read_dnsmasq_leases Dir["{#{LEASES_PATHS.join(',')}}"].map do |file| File.read(file) end.join("\n") end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/fetch_ip_with_lxc_attach.rb0000644000004100000410000000270412611107101025566 0ustar www-datawww-datamodule Vagrant module LXC module Action class FetchIpWithLxcAttach # Include this so we can use `Subprocess` more easily. include Vagrant::Util::Retryable def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_with_lxc_attach") end def call(env) env[:machine_ip] ||= assigned_ip(env) rescue LXC::Errors::NamespacesNotSupported @logger.info 'The `lxc-attach` command available does not support the --namespaces parameter, falling back to dnsmasq leases to fetch container ip' ensure @app.call(env) end def assigned_ip(env) driver = env[:machine].provider.driver ip = '' retryable(:on => LXC::Errors::ExecuteError, :tries => 10, :sleep => 3) do unless ip = get_container_ip_from_ip_addr(driver) # retry raise LXC::Errors::ExecuteError, :command => "lxc-attach" end end ip end # From: https://github.com/lxc/lxc/blob/staging/src/python-lxc/lxc/__init__.py#L371-L385 def get_container_ip_from_ip_addr(driver) output = driver.attach '/sbin/ip', '-4', 'addr', 'show', 'scope', 'global', 'eth0', namespaces: ['network', 'mount'] if output =~ /^\s+inet ([0-9.]+)\/[0-9]+\s+/ return $1.to_s end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/create.rb0000644000004100000410000000273212611107101022024 0ustar www-datawww-datamodule Vagrant module LXC module Action class Create def initialize(app, env) @app = app end def call(env) config = env[:machine].provider_config container_name = config.container_name case container_name when :machine container_name = env[:machine].name.to_s when String # Nothing to do here, move along... else container_name = generate_container_name(env) end env[:machine].provider.driver.create( container_name, config.backingstore, config.backingstore_options, env[:lxc_template_src], env[:lxc_template_config], env[:lxc_template_opts] ) env[:machine].id = container_name @app.call env end def generate_container_name(env) container_name = "#{env[:root_path].basename}_#{env[:machine].name}" container_name.gsub!(/[^-a-z0-9_]/i, "") # milliseconds + random number suffix to allow for simultaneous # `vagrant up` of the same box in different dirs container_name << "_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}" # Trim container name to 64 chars, keeping "randomness" trim_point = container_name.size > 64 ? -64 : -(container_name.size) container_name[trim_point..-1] end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/forced_halt.rb0000644000004100000410000000064512611107101023034 0ustar www-datawww-datamodule Vagrant module LXC module Action class ForcedHalt def initialize(app, env) @app = app end def call(env) if env[:machine].provider.state.id == :running env[:ui].info I18n.t("vagrant_lxc.messages.force_shutdown") env[:machine].provider.driver.forced_halt end @app.call(env) end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/prepare_nfs_valid_ids.rb0000644000004100000410000000062312611107101025100 0ustar www-datawww-datamodule Vagrant module LXC module Action class PrepareNFSValidIds def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::action::vm::nfs") end def call(env) machine = env[:machine] env[:nfs_valid_ids] = machine.provider.driver.all_containers @app.call(env) end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/forward_ports.rb0000644000004100000410000000647112611107101023460 0ustar www-datawww-datamodule Vagrant module LXC module Action class ForwardPorts def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::lxc::action::forward_ports") end def call(env) @env = env # Get the ports we're forwarding env[:forwarded_ports] = compile_forwarded_ports(env[:machine].config) if @env[:forwarded_ports].any? and not redir_installed? raise Errors::RedirNotInstalled end # Warn if we're port forwarding to any privileged ports env[:forwarded_ports].each do |fp| if fp[:host] <= 1024 env[:ui].warn I18n.t("vagrant.actions.vm.forward_ports.privileged_ports") break end end # Continue, we need the VM to be booted in order to grab its IP @app.call env if @env[:forwarded_ports].any? env[:ui].info I18n.t("vagrant.actions.vm.forward_ports.forwarding") forward_ports end end def forward_ports @env[:forwarded_ports].each do |fp| message_attributes = { # TODO: Add support for multiple adapters :adapter => 'eth0', :guest_port => fp[:guest], :host_port => fp[:host] } # TODO: Remove adapter from logging @env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.forwarding_entry", message_attributes)) redir_pid = redirect_port( fp[:host_ip], fp[:host], fp[:guest_ip] || @env[:machine].provider.ssh_info[:host], fp[:guest] ) store_redir_pid(fp[:host], redir_pid) end end private def compile_forwarded_ports(config) mappings = {} config.vm.networks.each do |type, options| next if options[:disabled] # TODO: Deprecate this behavior of "automagically" skipping ssh forwarded ports if type == :forwarded_port && options[:id] != 'ssh' if options.fetch(:host_ip, '').to_s.strip.empty? options[:host_ip] = '127.0.0.1' end mappings[options[:host]] = options end end mappings.values end def redirect_port(host_ip, host_port, guest_ip, guest_port) params = %W( --lport=#{host_port} --caddr=#{guest_ip} --cport=#{guest_port} ) params.unshift "--laddr=#{host_ip}" if host_ip params << '--syslog' if ENV['REDIR_LOG'] if host_port < 1024 redir_cmd = "sudo redir #{params.join(' ')} 2>/dev/null" else redir_cmd = "redir #{params.join(' ')} 2>/dev/null" end @logger.debug "Forwarding port with `#{redir_cmd}`" spawn redir_cmd end def store_redir_pid(host_port, redir_pid) data_dir = @env[:machine].data_dir.join('pids') data_dir.mkdir unless data_dir.directory? data_dir.join("redir_#{host_port}.pid").open('w') do |pid_file| pid_file.write(redir_pid) end end def redir_installed? system "which redir > /dev/null" end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action/handle_box_metadata.rb0000644000004100000410000000574012611107101024526 0ustar www-datawww-datamodule Vagrant module LXC module Action # Prepare arguments to be used for lxc-create class HandleBoxMetadata SUPPORTED_VERSIONS = ['1.0.0', '2', '3'] def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::lxc::action::handle_box_metadata") end def call(env) @env = env @box = @env[:machine].box @env[:ui].info I18n.t("vagrant.actions.vm.import.importing", :name => @env[:machine].box.name) @logger.info 'Validating box contents' validate_box @logger.info 'Setting box options on environment' @env[:lxc_template_src] = template_src @env[:lxc_template_opts] = template_opts # FIXME: Remove support for pre 1.0.0 boxes if box_version != '1.0.0' @env[:ui].warn "WARNING: You are using a base box that has a format that has been deprecated, please upgrade to a new one." @env[:lxc_template_opts].merge!( '--auth-key' => Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s ) end if template_config_file.exist? @env[:lxc_template_opts].merge!('--config' => template_config_file.to_s) elsif old_template_config_file.exist? @env[:lxc_template_config] = old_template_config_file.to_s end @app.call env end def template_src @template_src ||= if (box_template = @box.directory.join('lxc-template')).exist? box_template.to_s else Vagrant::LXC.source_root.join('scripts/lxc-template').to_s end end def template_config_file @template_config_file ||= @box.directory.join('lxc-config') end # TODO: Remove this once we remove compatibility for < 1.0.0 boxes def old_template_config_file @old_template_config_file ||= @box.directory.join('lxc.conf') end def template_opts @template_opts ||= @box.metadata.fetch('template-opts', {}).dup.merge!( '--tarball' => rootfs_tarball ) end def rootfs_tarball @rootfs_tarball ||= @box.directory.join('rootfs.tar.gz').to_s end def validate_box unless SUPPORTED_VERSIONS.include? box_version raise Errors::IncompatibleBox.new name: @box.name, found: box_version, supported: SUPPORTED_VERSIONS.join(', ') end unless File.exists?(template_src) raise Errors::TemplateFileMissing.new name: @box.name end unless File.exists?(rootfs_tarball) raise Errors::RootFSTarballMissing.new name: @box.name end end def box_version @box.metadata.fetch('version') end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/driver.rb0000644000004100000410000001771012611107101020601 0ustar www-datawww-datarequire "vagrant/util/retryable" require "vagrant/util/subprocess" require "vagrant-lxc/errors" require "vagrant-lxc/driver/cli" require "etc" require "tempfile" module Vagrant module LXC class Driver # This is raised if the container can't be found when initializing it with # a name. class ContainerNotFound < StandardError; end # Default root folder where container configs are stored DEFAULT_CONTAINERS_PATH = '/var/lib/lxc' attr_reader :container_name, :customizations def initialize(container_name, sudo_wrapper, cli = nil) @container_name = container_name @sudo_wrapper = sudo_wrapper @cli = cli || CLI.new(sudo_wrapper, container_name) @logger = Log4r::Logger.new("vagrant::provider::lxc::driver") @customizations = [] end def validate! raise ContainerNotFound if @container_name && ! @cli.list.include?(@container_name) end # Root folder where container configs are stored def containers_path @containers_path ||= @cli.support_config_command? ? @cli.config('lxc.lxcpath') : DEFAULT_CONTAINERS_PATH end def all_containers @cli.list end def base_path Pathname.new("#{containers_path}/#{@container_name}") end def rootfs_path config_entry = config_string.match(/^lxc\.rootfs\s+=\s+(.+)$/)[1] case config_entry when /^overlayfs:/ # Split on colon (:), ignoring any colon escaped by an escape character ( \ ) # Pays attention to when the escape character is itself escaped. fs_type, master_path, overlay_path = config_entry.split(/(?/dev/null | tail -n +2 | grep -q veth` $?.to_i == 0 end def remove_bridge(bridge_name) if ['lxcbr0', 'virbr0'].include? bridge_name @logger.info "Skipping removal of system bridge #{bridge_name}" return end return unless bridge_exists?(bridge_name) @logger.info "Removing bridge #{bridge_name}" @sudo_wrapper.run('ip', 'link', 'set', bridge_name, 'down') @sudo_wrapper.run('brctl', 'delbr', bridge_name) end def version @version ||= @cli.version end # TODO: This needs to be reviewed and specs needs to be written def compress_rootfs # TODO: Pass in tmpdir so we can clean up from outside target_path = "#{Dir.mktmpdir}/rootfs.tar.gz" @logger.info "Compressing '#{rootfs_path}' rootfs to #{target_path}" @sudo_wrapper.run('tar', '--numeric-owner', '-cvzf', target_path, '-C', rootfs_path.parent.to_s, "./#{rootfs_path.basename.to_s}") @logger.info "Changing rootfs tarball owner" user_details = Etc.getpwnam(Etc.getlogin) @sudo_wrapper.run('chown', "#{user_details.uid}:#{user_details.gid}", target_path) target_path end def state if @container_name @cli.state end end def prune_customizations # Use sed to just strip out the block of code which was inserted by Vagrant @logger.debug 'Prunning vagrant-lxc customizations' contents = config_string contents.gsub! /^# VAGRANT-BEGIN(.|\s)*# VAGRANT-END\n/, '' write_config(contents) end protected def write_customizations(customizations) customizations = customizations.map do |key, value| "lxc.#{key}=#{value}" end customizations.unshift '# VAGRANT-BEGIN' customizations << "# VAGRANT-END\n" contents = config_string contents << customizations.join("\n") write_config(contents) end def write_config(contents) Tempfile.new('lxc-config').tap do |file| file.chmod 0644 file.write contents file.close @sudo_wrapper.run 'cp', '-f', file.path, base_path.join('config').to_s @sudo_wrapper.run 'chown', 'root:root', base_path.join('config').to_s end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/errors.rb0000644000004100000410000000306012611107101020613 0ustar www-datawww-datarequire 'vagrant/errors' module Vagrant module LXC module Errors class ExecuteError < Vagrant::Errors::VagrantError error_key(:lxc_execute_error) attr_reader :stderr, :stdout def initialize(message, *args) super if message.is_a?(Hash) @stderr = message[:stderr] @stdout = message[:stdout] end end end class NamespacesNotSupported < Vagrant::Errors::VagrantError end class LxcLinuxRequired < Vagrant::Errors::VagrantError error_key(:lxc_linux_required) end class LxcNotInstalled < Vagrant::Errors::VagrantError error_key(:lxc_not_installed) end class ContainerAlreadyExists < Vagrant::Errors::VagrantError error_key(:lxc_container_already_exists) end class CommandNotSupported < Vagrant::Errors::VagrantError error_key(:lxc_command_not_supported) end # Box related errors class TemplateFileMissing < Vagrant::Errors::VagrantError error_key(:lxc_template_file_missing) end class TemplatesDirMissing < Vagrant::Errors::VagrantError error_key(:lxc_templates_dir_missing) end class RootFSTarballMissing < Vagrant::Errors::VagrantError error_key(:lxc_invalid_box_version) end class IncompatibleBox < Vagrant::Errors::VagrantError error_key(:lxc_incompatible_box) end class RedirNotInstalled < Vagrant::Errors::VagrantError error_key(:lxc_redir_not_installed) end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/plugin.rb0000644000004100000410000000175512611107101020606 0ustar www-datawww-datarequire 'vagrant' module Vagrant module LXC class Plugin < Vagrant.plugin("2") name "vagrant-lxc" description <<-EOF The LXC provider allows Vagrant to manage and control LXC-based virtual machines. EOF provider(:lxc, parallel: true, priority: 7) do require File.expand_path("../provider", __FILE__) I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml') I18n.reload! Provider end command "lxc" do require_relative 'command/root' Command::Root end config(:lxc, :provider) do require File.expand_path("../config", __FILE__) Config end synced_folder(:lxc) do require File.expand_path("../synced_folder", __FILE__) SyncedFolder end provider_capability("lxc", "public_address") do require_relative "provider/cap/public_address" Provider::Cap::PublicAddress end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/command/0000755000004100000410000000000012611107101020371 5ustar www-datawww-datavagrant-lxc-1.2.1/lib/vagrant-lxc/command/root.rb0000644000004100000410000000330612611107101021703 0ustar www-datawww-datamodule Vagrant module LXC module Command class Root < Vagrant.plugin("2", :command) def self.synopsis 'vagrant-lxc specific commands' end def initialize(argv, env) @args, @sub_command, @sub_args = split_main_and_subcommand(argv) @subcommands = Vagrant::Registry.new.tap do |registry| registry.register(:sudoers) do require_relative 'sudoers' Sudoers end end super(argv, env) end def execute # Print the help return help if @args.include?("-h") || @args.include?("--help") klazz = @subcommands.get(@sub_command.to_sym) if @sub_command return help unless klazz @logger.debug("Executing command: #{klazz} #{@sub_args.inspect}") # Initialize and execute the command class klazz.new(@sub_args, @env).execute end def help opts = OptionParser.new do |opts| opts.banner = "Usage: vagrant lxc []" opts.separator "" opts.separator "Available subcommands:" # REFACTOR Use @subcommands.keys.sort # https://github.com/mitchellh/vagrant/commit/4194da19c60956f6e59239c0145f772be257e79d keys = [] @subcommands.each { |key, value| keys << key } keys.sort.each do |key| opts.separator " #{key}" end opts.separator "" opts.separator "For help on any individual subcommand run `vagrant lxc -h`" end @env.ui.info(opts.help, :prefix => false) end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/command/sudoers.rb0000644000004100000410000000546312611107101022412 0ustar www-datawww-datarequire 'tempfile' module Vagrant module LXC module Command class Sudoers < Vagrant.plugin("2", :command) def initialize(argv, env) super @argv @env = env end def execute options = { user: ENV['USER'] } opts = OptionParser.new do |opts| opts.banner = "Usage: vagrant lxc sudoers" opts.separator "" opts.on('-u user', '--user user', String, "The user for which to create the policy (defaults to '#{options[:user]}')") do |u| options[:user] = u end end argv = parse_options(opts) return unless argv wrapper_path = Vagrant::LXC.sudo_wrapper_path wrapper = create_wrapper! sudoers = create_sudoers!(options[:user], wrapper_path) su_copy([ {source: wrapper, target: wrapper_path, mode: "0555"}, {source: sudoers, target: sudoers_path, mode: "0440"} ]) end def sudoers_path "/etc/sudoers.d/vagrant-lxc" end private # This requires vagrant 1.5.2+ https://github.com/mitchellh/vagrant/commit/3371c3716278071680af9b526ba19235c79c64cb def create_wrapper! wrapper = Tempfile.new('lxc-wrapper').tap do |file| template = Vagrant::Util::TemplateRenderer.new( 'sudoers.rb', :template_root => Vagrant::LXC.source_root.join('templates').to_s, :cmd_paths => build_cmd_paths_hash, :pipework_regex => "#{ENV['HOME']}/\.vagrant\.d/gems/gems/vagrant-lxc.+/scripts/pipework" ) file.puts template.render end wrapper.close wrapper.path end def create_sudoers!(user, command) sudoers = Tempfile.new('vagrant-lxc-sudoers').tap do |file| file.puts "# Automatically created by vagrant-lxc" file.puts "#{user} ALL=(root) NOPASSWD: #{command}" end sudoers.close sudoers.path end def su_copy(files) commands = files.map { |file| [ "rm -f #{file[:target]}", "cp #{file[:source]} #{file[:target]}", "chown root:root #{file[:target]}", "chmod #{file[:mode]} #{file[:target]}" ] }.flatten system "echo \"#{commands.join("; ")}\" | sudo sh" end def build_cmd_paths_hash {}.tap do |hash| %w( which cat mkdir cp chown chmod rm tar chown ip ifconfig brctl ).each do |cmd| hash[cmd] = `which #{cmd}`.strip end hash['lxc_bin'] = Pathname(`which lxc-create`.strip).parent.to_s hash['ruby'] = Gem.ruby end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/provider.rb0000644000004100000410000000633312611107101021137 0ustar www-datawww-datarequire "log4r" require "vagrant-lxc/action" require "vagrant-lxc/driver" require "vagrant-lxc/sudo_wrapper" module Vagrant module LXC class Provider < Vagrant.plugin("2", :provider) attr_reader :driver def self.usable?(raise_error=false) if !Vagrant::Util::Platform.linux? raise Errors::LxcLinuxRequired end true end def initialize(machine) @logger = Log4r::Logger.new("vagrant::provider::lxc") @machine = machine ensure_lxc_installed! machine_id_changed end def sudo_wrapper @shell ||= begin wrapper = Pathname.new(LXC.sudo_wrapper_path).exist? && LXC.sudo_wrapper_path || nil @logger.debug("Found sudo wrapper : #{wrapper}") if wrapper SudoWrapper.new(wrapper) end end def ensure_lxc_installed! begin sudo_wrapper.run("which", "lxc-create") rescue Vagrant::LXC::Errors::ExecuteError raise Errors::LxcNotInstalled end end # If the machine ID changed, then we need to rebuild our underlying # container. def machine_id_changed id = @machine.id begin @logger.debug("Instantiating the container for: #{id.inspect}") @driver = Driver.new(id, self.sudo_wrapper) @driver.validate! rescue Driver::ContainerNotFound # The container doesn't exist, so we probably have a stale # ID. Just clear the id out of the machine and reload it. @logger.debug("Container not found! Clearing saved machine ID and reloading.") id = nil retry end end # @see Vagrant::Plugin::V2::Provider#action def action(name) # Attempt to get the action method from the Action class if it # exists, otherwise return nil to show that we don't support the # given action. action_method = "action_#{name}" return LXC::Action.send(action_method) if LXC::Action.respond_to?(action_method) nil end # Returns the SSH info for accessing the Container. def ssh_info # If the Container is not running then we cannot possibly SSH into it, so # we return nil. return nil if state.id != :running # Run a custom action called "ssh_ip" which does what it says and puts # the IP found into the `:machine_ip` key in the environment. env = @machine.action("ssh_ip") # If we were not able to identify the container's IP, we return nil # here and we let Vagrant core deal with it ;) return nil unless env[:machine_ip] { :host => env[:machine_ip], :port => @machine.config.ssh.guest_port } end def state state_id = nil state_id = :not_created if !@driver.container_name state_id = @driver.state if !state_id state_id = :unknown if !state_id short = state_id.to_s.gsub("_", " ") long = I18n.t("vagrant.commands.status.#{state_id}") Vagrant::MachineState.new(state_id, short, long) end def to_s id = @machine.id ? @machine.id : "new VM" "LXC (#{id})" end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/provider/0000755000004100000410000000000012611107101020605 5ustar www-datawww-datavagrant-lxc-1.2.1/lib/vagrant-lxc/provider/cap/0000755000004100000410000000000012611107101021350 5ustar www-datawww-datavagrant-lxc-1.2.1/lib/vagrant-lxc/provider/cap/public_address.rb0000644000004100000410000000053612611107101024664 0ustar www-datawww-datamodule Vagrant module LXC class Provider module Cap module PublicAddress def self.public_address(machine) return nil if machine.state.id != :running ssh_info = machine.ssh_info return nil if !ssh_info ssh_info[:host] end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/version.rb0000644000004100000410000000007412611107101020766 0ustar www-datawww-datamodule Vagrant module LXC VERSION = "1.2.1" end end vagrant-lxc-1.2.1/lib/vagrant-lxc/config.rb0000644000004100000410000000362312611107101020551 0ustar www-datawww-datamodule Vagrant module LXC class Config < Vagrant.plugin("2", :config) # An array of container's configuration overrides to be provided to `lxc-start`. # # @return [Array] attr_reader :customizations # A string that contains the backing store type used with lxc-create -B attr_accessor :backingstore # Optional arguments for the backing store, such as --fssize, --fstype, ... # # @return [Array] attr_accessor :backingstore_options # A string to explicitly set the container name. To use the vagrant # machine name, set this to :machine attr_accessor :container_name def initialize @customizations = [] @backingstore = UNSET_VALUE @backingstore_options = [] @sudo_wrapper = UNSET_VALUE @container_name = UNSET_VALUE end # Customize the container by calling `lxc-start` with the given # configuration overrides. # # For example, if you want to set the memory limit, you can use it # like: config.customize 'cgroup.memory.limit_in_bytes', '400M' # # When `lxc-start`ing the container, vagrant-lxc will pass in # "-s lxc.cgroup.memory.limit_in_bytes=400M" to it. # # @param [String] key Configuration key to override # @param [String] value Configuration value to override def customize(key, value) @customizations << [key, value] end # Stores options for backingstores like lvm, btrfs, etc def backingstore_option(key, value) @backingstore_options << [key, value] end def finalize! @sudo_wrapper = nil if @sudo_wrapper == UNSET_VALUE @container_name = nil if @container_name == UNSET_VALUE @backingstore = "best" if @backingstore == UNSET_VALUE @existing_container_name = nil if @existing_container_name == UNSET_VALUE end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/synced_folder.rb0000644000004100000410000000503612611107101022124 0ustar www-datawww-datamodule Vagrant module LXC class SyncedFolder < Vagrant.plugin("2", :synced_folder) def usable?(machine) # These synced folders only work if the provider is LXC machine.provider_name == :lxc end def prepare(machine, folders, _opts) machine.ui.output(I18n.t("vagrant.actions.lxc.share_folders.preparing")) # short guestpaths first, so we don't step on ourselves folders = folders.sort_by do |id, data| if data[:guestpath] data[:guestpath].length else # A long enough path to just do this at the end. 10000 end end folders.each do |id, data| host_path = Pathname.new(File.expand_path(data[:hostpath], machine.env.root_path)) guest_path = data[:guestpath] machine.env.ui.warn(I18n.t("vagrant_lxc.messages.warn_owner")) if data[:owner] machine.env.ui.warn(I18n.t("vagrant_lxc.messages.warn_group")) if data[:group] if !host_path.directory? && data[:create] # Host path doesn't exist, so let's create it. @logger.info("Host path doesn't exist, creating: #{host_path}") begin host_path.mkpath rescue Errno::EACCES raise Vagrant::Errors::SharedFolderCreateFailed, :path => hostpath.to_s end end mount_opts = data[:mount_options] machine.provider.driver.share_folder(host_path, guest_path, mount_opts) # Guest path specified, so mount the folder to specified point machine.ui.detail(I18n.t("vagrant.actions.vm.share_folders.mounting_entry", guestpath: data[:guestpath], hostpath: data[:hostpath], guest_path: data[:guestpath])) end end def enable(machine, folders, _opts) # Emit an upstart event if we can return unless machine.communicate.test("test -x /sbin/initctl") # short guestpaths first, so we don't step on ourselves folders = folders.sort_by do |id, data| if data[:guestpath] data[:guestpath].length else # A long enough path to just do this at the end. 10000 end end folders.each do |id, data| guest_path = data[:guestpath] machine.communicate.sudo( "/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guest_path}") end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/driver/0000755000004100000410000000000012611107101020246 5ustar www-datawww-datavagrant-lxc-1.2.1/lib/vagrant-lxc/driver/cli.rb0000644000004100000410000001161212611107101021343 0ustar www-datawww-datarequire "vagrant/util/retryable" require "vagrant/util/subprocess" require "vagrant-lxc/errors" module Vagrant module LXC class Driver class CLI attr_accessor :name class TransitionBlockNotProvided < RuntimeError; end class TargetStateNotReached < RuntimeError def initialize(target_state, state) msg = "Target state '#{target_state}' not reached, currently on '#{state}'" super(msg) end end def initialize(sudo_wrapper, name = nil) @sudo_wrapper = sudo_wrapper @name = name @logger = Log4r::Logger.new("vagrant::provider::lxc::container::cli") end def list run(:ls).split(/\s+/).uniq end def version return @version if @version @version = support_version_command? ? run(:version) : run(:create, '--version') if @version =~ /(lxc version:\s+|)(.+)\s*$/ @version = $2.downcase else # TODO: Raise an user friendly error raise 'Unable to parse lxc version!' end end def config(param) if support_config_command? run(:config, param).gsub("\n", '') else raise Errors::CommandNotSupported, name: 'config', available_version: '> 1.x.x', version: version end end def state if @name && run(:info, '--name', @name, retryable: true) =~ /^state:[^A-Z]+([A-Z]+)$/i $1.downcase.to_sym elsif @name :unknown end end def create(template, backingstore, backingstore_options, config_file, template_opts = {}) if config_file config_opts = ['-f', config_file] end extra = template_opts.to_a.flatten extra.unshift '--' unless extra.empty? run :create, '-B', backingstore, '--template', template, '--name', @name, *(backingstore_options.to_a.flatten), *(config_opts), *extra rescue Errors::ExecuteError => e if e.stderr =~ /already exists/i raise Errors::ContainerAlreadyExists, name: @name else raise end end def destroy run :destroy, '--name', @name end def start(options = []) run :start, '-d', '--name', @name, *Array(options) end def stop attach '/sbin/halt' if supports_attach? run :stop, '--name', @name end def attach(*cmd) cmd = ['--'] + cmd if cmd.last.is_a?(Hash) opts = cmd.pop namespaces = Array(opts[:namespaces]).map(&:upcase).join('|') # HACK: The wrapper script should be able to handle this if @sudo_wrapper.wrapper_path namespaces = "'#{namespaces}'" end if namespaces if supports_attach_with_namespaces? extra = ['--namespaces', namespaces] else raise LXC::Errors::NamespacesNotSupported end end end run :attach, '--name', @name, *((extra || []) + cmd) end def transition_to(target_state, tries = 30, timeout = 1, &block) raise TransitionBlockNotProvided unless block_given? yield self while (last_state = self.state) != target_state && tries > 0 @logger.debug "Target state '#{target_state}' not reached, currently on '#{last_state}'" sleep timeout tries -= 1 end unless last_state == target_state # TODO: Raise an user friendly message raise TargetStateNotReached.new target_state, last_state end end def supports_attach? unless defined?(@supports_attach) begin @supports_attach = true run(:attach, '--name', @name, '--', '/bin/true') rescue LXC::Errors::ExecuteError @supports_attach = false end end return @supports_attach end def support_config_command? version[0].to_i >= 1 end def support_version_command? @sudo_wrapper.run('which', 'lxc-version').strip.chomp != '' rescue Vagrant::LXC::Errors::ExecuteError return false end private def run(command, *args) @sudo_wrapper.run("lxc-#{command}", *args) end def supports_attach_with_namespaces? unless defined?(@supports_attach_with_namespaces) @supports_attach_with_namespaces = run(:attach, '-h', :show_stderr => true).values.join.include?('--namespaces') end return @supports_attach_with_namespaces end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/action.rb0000644000004100000410000001762612611107101020571 0ustar www-datawww-datarequire 'vagrant-lxc/action/boot' require 'vagrant-lxc/action/clear_forwarded_ports' require 'vagrant-lxc/action/create' require 'vagrant-lxc/action/destroy' require 'vagrant-lxc/action/destroy_confirm' require 'vagrant-lxc/action/compress_rootfs' require 'vagrant-lxc/action/fetch_ip_with_lxc_attach' require 'vagrant-lxc/action/fetch_ip_from_dnsmasq_leases' require 'vagrant-lxc/action/forced_halt' require 'vagrant-lxc/action/forward_ports' require 'vagrant-lxc/action/gc_private_network_bridges' require 'vagrant-lxc/action/handle_box_metadata' require 'vagrant-lxc/action/prepare_nfs_settings' require 'vagrant-lxc/action/prepare_nfs_valid_ids' require 'vagrant-lxc/action/private_networks' require 'vagrant-lxc/action/setup_package_files' require 'vagrant-lxc/action/warn_networks' module Vagrant module LXC module Action # Shortcuts Builtin = Vagrant::Action::Builtin Builder = Vagrant::Action::Builder # This action is responsible for reloading the machine, which # brings it down, sucks in new configuration, and brings the # machine back up with the new configuration. def self.action_reload Builder.new.tap do |b| b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| if env1[:result] b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end b2.use Builtin::ConfigValidate b2.use action_halt b2.use action_start end end end # This action boots the VM, assuming the VM is in a state that requires # a bootup (i.e. not saved). def self.action_boot Builder.new.tap do |b| b.use Builtin::Provision b.use Builtin::EnvSet, :port_collision_repair => true b.use Builtin::HandleForwardedPortCollisions b.use PrepareNFSValidIds b.use Builtin::SyncedFolderCleanup b.use Builtin::SyncedFolders b.use PrepareNFSSettings b.use Builtin::SetHostname b.use WarnNetworks b.use ForwardPorts b.use PrivateNetworks b.use Boot b.use Builtin::WaitForCommunicator end end # This action just runs the provisioners on the machine. def self.action_provision Builder.new.tap do |b| b.use Builtin::ConfigValidate b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| if env1[:result] b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end b2.use Builtin::Call, Builtin::IsState, :running do |env2, b3| if !env2[:result] b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running") next end b3.use Builtin::Provision end end end end # This action starts a container, assuming it is already created and exists. # A precondition of this action is that the container exists. def self.action_start Builder.new.tap do |b| b.use Builtin::ConfigValidate b.use Builtin::BoxCheckOutdated b.use Builtin::Call, Builtin::IsState, :running do |env, b2| # If the VM is running, then our work here is done, exit next if env[:result] b2.use action_boot end end end # This action brings the machine up from nothing, including creating the # container, configuring metadata, and booting. def self.action_up Builder.new.tap do |b| b.use Builtin::ConfigValidate b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| # If the VM is NOT created yet, then do the setup steps if env[:result] b2.use Builtin::HandleBox b2.use HandleBoxMetadata b2.use Create end end b.use action_start end end # This is the action that is primarily responsible for halting # the virtual machine, gracefully or by force. def self.action_halt Builder.new.tap do |b| b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| if env[:result] b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end b2.use ClearForwardedPorts b2.use GcPrivateNetworkBridges b2.use Builtin::Call, Builtin::GracefulHalt, :stopped, :running do |env2, b3| if !env2[:result] b3.use ForcedHalt end end end end end # This is the action that is primarily responsible for completely # freeing the resources of the underlying virtual machine. def self.action_destroy Builder.new.tap do |b| b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| if env1[:result] b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end b2.use Builtin::Call, DestroyConfirm do |env2, b3| if env2[:result] b3.use Builtin::ConfigValidate b3.use Builtin::EnvSet, :force_halt => true b3.use action_halt b3.use Destroy b3.use Builtin::ProvisionerCleanup else b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.will_not_destroy") end end end end end # This action packages the virtual machine into a single box file. def self.action_package Builder.new.tap do |b| b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2| if env1[:result] b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end b2.use action_halt b2.use CompressRootFS b2.use SetupPackageFiles b2.use Vagrant::Action::General::Package end end end # This action is called to read the IP of the container. The IP found # is expected to be put into the `:machine_ip` key. def self.action_ssh_ip Builder.new.tap do |b| b.use Builtin::Call, Builtin::ConfigValidate do |env, b2| b2.use FetchIpWithLxcAttach if env[:machine].provider.driver.supports_attach? b2.use FetchIpFromDnsmasqLeases end end end # This is the action that will exec into an SSH shell. def self.action_ssh Builder.new.tap do |b| b.use Builtin::ConfigValidate b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| if env[:result] b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end b2.use Builtin::Call, Builtin::IsState, :running do |env1, b3| if !env1[:result] b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running") next end b3.use Builtin::SSHExec end end end end # This is the action that will run a single SSH command. def self.action_ssh_run Builder.new.tap do |b| b.use Builtin::ConfigValidate b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2| if env[:result] b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created") next end b2.use Builtin::Call, Builtin::IsState, :running do |env1, b3| if !env1[:result] raise Vagrant::Errors::VMNotRunningError next end b3.use Builtin::SSHRun end end end end end end end vagrant-lxc-1.2.1/lib/vagrant-lxc/sudo_wrapper.rb0000644000004100000410000000455712611107101022025 0ustar www-datawww-datamodule Vagrant module LXC class SudoWrapper # Include this so we can use `Subprocess` more easily. include Vagrant::Util::Retryable attr_reader :wrapper_path def initialize(wrapper_path = nil) @wrapper_path = wrapper_path @logger = Log4r::Logger.new("vagrant::lxc::sudo_wrapper") end def run(*command) options = command.last.is_a?(Hash) ? command.last : {} if @wrapper_path && !options[:no_wrapper] command.unshift @wrapper_path execute *(['sudo'] + command) else execute *(['sudo', '/usr/bin/env'] + command) end end private # TODO: Review code below this line, it was pretty much a copy and # paste from VirtualBox base driver and has no tests def execute(*command, &block) # Get the options hash if it exists opts = {} opts = command.pop if command.last.is_a?(Hash) tries = 0 tries = 3 if opts[:retryable] sleep = opts.fetch(:sleep, 1) # Variable to store our execution result r = nil retryable(:on => LXC::Errors::ExecuteError, :tries => tries, :sleep => sleep) do # Execute the command r = raw(*command, &block) # If the command was a failure, then raise an exception that is # nicely handled by Vagrant. if r.exit_code != 0 if @interrupted @logger.info("Exit code != 0, but interrupted. Ignoring.") else raise LXC::Errors::ExecuteError, command: command.inspect, stderr: r.stderr, stdout: r.stdout end end end # Return the output, making sure to replace any Windows-style # newlines with Unix-style. stdout = r.stdout.gsub("\r\n", "\n") if opts[:show_stderr] { :stdout => stdout, :stderr => r.stderr.gsub("\r\n", "\n") } else stdout end end def raw(*command, &block) int_callback = lambda do @interrupted = true @logger.info("Interrupted.") end # Append in the options for subprocess command << { :notify => [:stdout, :stderr] } Vagrant::Util::Busy.busy(int_callback) do Vagrant::Util::Subprocess.execute(*command, &block) end end end end end vagrant-lxc-1.2.1/scripts/0000755000004100000410000000000012611107101015446 5ustar www-datawww-datavagrant-lxc-1.2.1/scripts/lxc-template0000755000004100000410000001234512611107101020000 0ustar www-datawww-data#!/usr/bin/env bash # This is a modified version of /usr/share/lxc/templates/lxc-download # that comes with ubuntu-lxc 1.0.0 stable from ppa changed to suit vagrant-lxc needs # # Copyright © 2014 Stéphane Graber # Copyright © 2014 Fábio Rehm # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 # USA set -eu LXC_HOOK_DIR="/usr/share/lxc/hooks" LXC_TEMPLATE_CONFIG="/usr/share/lxc/config" LXC_MAPPED_GID= LXC_MAPPED_UID= LXC_NAME= LXC_PATH= LXC_ROOTFS= LXC_TARBALL= LXC_CONFIG= LXC_STRIP_COMPONENTS=2 usage() { cat < ]: The full path of the rootfs tarball Optional arguments: [ --config ]: Configuration file to be used when building the container [ -h | --help ]: This help message LXC internal arguments (do not pass manually!): [ --name ]: The container name [ --path ]: The path to the container [ --rootfs ]: The path to the container's rootfs [ --mapped-uid ]: A uid map (user namespaces) [ --mapped-gid ]: A gid map (user namespaces) [ --strip-components ]: Number of path components to strip from tarball EOF return 0 } options=$(getopt -o h -l tarball:,config:,help:,name:,path:,rootfs:,mapped-uid:,mapped-gid:,strip-components: -- "$@")SS if [ $? -ne 0 ]; then usage $(basename $0) exit 1 fi eval set -- "$options" while true do case "$1" in -h|--help) usage $0 && exit 0;; --config) LXC_CONFIG=$2; shift 2;; --tarball) LXC_TARBALL=$2; shift 2;; --name) LXC_NAME=$2; shift 2;; --path) LXC_PATH=$2; shift 2;; --rootfs) LXC_ROOTFS=$2; shift 2;; --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; --strip-components) LXC_STRIP_COMPONENTS=$2; shift 2;; *) break;; esac done if [ -z "${LXC_NAME}" ]; then echo "'name' parameter is required" exit 1 fi if [ -z "${LXC_TARBALL}" ]; then echo "'tarball' parameter is required" exit 1 fi if [ -z "${LXC_PATH}" ]; then echo "'path' parameter is required" exit 1 fi if [ -z "${LXC_CONFIG}" ]; then echo "'config' parameter is required" exit 1 fi # if $LXC_ROOTFS exists here, it was passed in with --rootfs if [ -z "${LXC_ROOTFS}" ]; then config=${LXC_PATH}/config if grep -q '^lxc.rootfs' $config 2>/dev/null ; then LXC_ROOTFS=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'` else LXC_ROOTFS=$LXC_PATH/rootfs echo "lxc.rootfs = ${LXC_ROOTFS}" >> $config fi fi # Unpack the rootfs echo "Unpacking the rootfs" mkdir -p /var/lock/subsys ( flock -x 200 if [ $? -ne 0 ]; then echo "Cache repository is busy." exit 1 fi mkdir -p ${LXC_ROOTFS} (cd ${LXC_ROOTFS} && tar xfz ${LXC_TARBALL} --strip-components=${LXC_STRIP_COMPONENTS}) if [ $? -ne 0 ]; then echo "Failed to extract rootfs" exit 1 fi ) 200>/var/lock/subsys/lxc mkdir -p ${LXC_ROOTFS}/dev/pts/ ## Extract all the network config entries sed -i -e "/lxc.network/{w ${LXC_PATH}/config-network" -e "d}" \ ${LXC_PATH}/config ## Extract any other config entry sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" ${LXC_PATH}/config ## Add the container-specific config echo "" >> ${LXC_PATH}/config echo "##############################################" >> ${LXC_PATH}/config echo "# Container specific configuration (automatically set)" >> ${LXC_PATH}/config if [ -e "${LXC_PATH}/config-auto" ]; then cat ${LXC_PATH}/config-auto >> ${LXC_PATH}/config rm ${LXC_PATH}/config-auto fi echo "lxc.utsname = ${LXC_NAME}" >> ${LXC_PATH}/config ## Re-add the previously removed network config if [ -e "${LXC_PATH}/config-network" ]; then echo "" >> ${LXC_PATH}/config echo "##############################################" >> ${LXC_PATH}/config echo "# Network configuration (automatically set)" >> ${LXC_PATH}/config cat ${LXC_PATH}/config-network >> ${LXC_PATH}/config rm ${LXC_PATH}/config-network fi ## Append the defaults echo "" >> ${LXC_PATH}/config echo "##############################################" >> ${LXC_PATH}/config echo "# vagrant-lxc base box specific configuration" >> ${LXC_PATH}/config cat ${LXC_CONFIG} >> ${LXC_PATH}/config # Empty section for lxc.customize calls from vagrantfile echo "" >> ${LXC_PATH}/config echo "##############################################" >> ${LXC_PATH}/config echo "# vagrant-lxc container specific configuration" >> ${LXC_PATH}/config exit 0 vagrant-lxc-1.2.1/scripts/pipework0000755000004100000410000002116512611107101017241 0ustar www-datawww-data#!/usr/bin/env bash # Borrowed from https://github.com/jpetazzo/pipework set -e case "$1" in --wait) WAIT=1 ;; esac IFNAME=$1 # default value set further down if not set here CONTAINER_IFNAME= if [ "$2" = "-i" ]; then CONTAINER_IFNAME=$3 shift 2 fi GUESTNAME=$2 IPADDR=$3 MACADDR=$4 if echo $MACADDR | grep -q @ then VLAN=$(echo $MACADDR | cut -d@ -f2) MACADDR=$(echo $MACADDR | cut -d@ -f1) else VLAN= fi [ "$IPADDR" ] || [ "$WAIT" ] || { echo "Syntax:" echo "pipework [-i containerinterface] /[@default_gateway] [macaddr][@vlan]" echo "pipework [-i containerinterface] dhcp [macaddr][@vlan]" echo "pipework --wait [-i containerinterface]" exit 1 } # First step: determine type of first argument (bridge, physical interface...), skip if --wait set if [ -z "$WAIT" ]; then if [ -d /sys/class/net/$IFNAME ] then if [ -d /sys/class/net/$IFNAME/bridge ] then IFTYPE=bridge BRTYPE=linux elif $(which ovs-vsctl >/dev/null 2>&1) && $(ovs-vsctl list-br|grep -q ^$IFNAME$) then IFTYPE=bridge BRTYPE=openvswitch elif [ $(cat /sys/class/net/$IFNAME/type) -eq 32 ]; # Infiniband IPoIB interface type 32 then IFTYPE=ipoib # The IPoIB kernel module is fussy, set device name to ib0 if not overridden CONTAINER_IFNAME=${CONTAINER_IFNAME:-ib0} else IFTYPE=phys fi else # case "$IFNAME" in # br*) IFTYPE=bridge BRTYPE=linux # ;; # ovs*) # if ! $(which ovs-vsctl >/dev/null) # then # echo "Need OVS installed on the system to create an ovs bridge" # exit 1 # fi # IFTYPE=bridge # BRTYPE=openvswitch # ;; # *) # echo "I do not know how to setup interface $IFNAME." # exit 1 # ;; # esac fi fi # Set the default container interface name to eth1 if not already set CONTAINER_IFNAME=${CONTAINER_IFNAME:-eth1} [ "$WAIT" ] && { while ! grep -q ^1$ /sys/class/net/$CONTAINER_IFNAME/carrier 2>/dev/null do sleep 1 done exit 0 } [ $IFTYPE = bridge ] && [ $BRTYPE = linux ] && [ "$VLAN" ] && { echo "VLAN configuration currently unsupported for Linux bridge." exit 1 } [ $IFTYPE = ipoib ] && [ $MACADDR ] && { echo "MACADDR configuration unsupported for IPoIB interfaces." exit 1 } # Second step: find the guest (for now, we only support LXC containers) while read dev mnt fstype options dump fsck do [ "$fstype" != "cgroup" ] && continue echo $options | grep -qw devices || continue CGROUPMNT=$mnt done < /proc/mounts [ "$CGROUPMNT" ] || { echo "Could not locate cgroup mount point." exit 1 } # Try to find a cgroup matching exactly the provided name. N=$(find "$CGROUPMNT" -name "$GUESTNAME" | wc -l) case "$N" in 0) # If we didn't find anything, try to lookup the container with Docker. if which docker >/dev/null then RETRIES=3 while [ $RETRIES -gt 0 ]; do DOCKERPID=$(docker inspect --format='{{ .State.Pid }}' $GUESTNAME) [ $DOCKERPID != 0 ] && break sleep 1 RETRIES=$((RETRIES - 1)) done [ "$DOCKERPID" = 0 ] && { echo "Docker inspect returned invalid PID 0" exit 1 } [ "$DOCKERPID" = "" ] && { echo "Container $GUESTNAME not found, and unknown to Docker." exit 1 } else echo "Container $GUESTNAME not found, and Docker not installed." exit 1 fi ;; 1) true ;; *) echo "Found more than one container matching $GUESTNAME." exit 1 ;; esac if [ "$IPADDR" = "dhcp" ] then # Check for first available dhcp client DHCP_CLIENT_LIST="udhcpc dhcpcd dhclient" for CLIENT in $DHCP_CLIENT_LIST; do which $CLIENT >/dev/null && { DHCP_CLIENT=$CLIENT break } done [ -z $DHCP_CLIENT ] && { echo "You asked for DHCP; but no DHCP client could be found." exit 1 } else # Check if a subnet mask was provided. echo $IPADDR | grep -q / || { echo "The IP address should include a netmask." echo "Maybe you meant $IPADDR/24 ?" exit 1 } # Check if a gateway address was provided. if echo $IPADDR | grep -q @ then GATEWAY=$(echo $IPADDR | cut -d@ -f2) IPADDR=$(echo $IPADDR | cut -d@ -f1) else GATEWAY= fi fi if [ $DOCKERPID ]; then NSPID=$DOCKERPID else NSPID=$(head -n 1 $(find "$CGROUPMNT" -name "$GUESTNAME" | head -n 1)/tasks) [ "$NSPID" ] || { echo "Could not find a process inside container $GUESTNAME." exit 1 } fi # Check if an incompatible VLAN device already exists [ $IFTYPE = phys ] && [ "$VLAN" ] && [ -d /sys/class/net/$IFNAME.VLAN ] && { [ -z "$(ip -d link show $IFNAME.$VLAN | grep "vlan.*id $VLAN")" ] && { echo "$IFNAME.VLAN already exists but is not a VLAN device for tag $VLAN" exit 1 } } [ ! -d /var/run/netns ] && mkdir -p /var/run/netns [ -f /var/run/netns/$NSPID ] && rm -f /var/run/netns/$NSPID ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID # Check if we need to create a bridge. [ $IFTYPE = bridge ] && [ ! -d /sys/class/net/$IFNAME ] && { [ $BRTYPE = linux ] && { (ip link add dev $IFNAME type bridge > /dev/null 2>&1) || (brctl addbr $IFNAME) ip link set $IFNAME up } [ $BRTYPE = openvswitch ] && { ovs-vsctl add-br $IFNAME } } MTU=$(ip link show $IFNAME | awk '{print $5}') # If it's a bridge, we need to create a veth pair [ $IFTYPE = bridge ] && { LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}" GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}" ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU case "$BRTYPE" in linux) (ip link set $LOCAL_IFNAME master $IFNAME > /dev/null 2>&1) || (brctl addif $IFNAME $LOCAL_IFNAME) ;; openvswitch) ovs-vsctl add-port $IFNAME $LOCAL_IFNAME ${VLAN:+"tag=$VLAN"} ;; esac ip link set $LOCAL_IFNAME up } # Note: if no container interface name was specified, pipework will default to ib0 # Note: no macvlan subinterface or ethernet bridge can be created against an # ipoib interface. Infiniband is not ethernet. ipoib is an IP layer for it. # To provide additional ipoib interfaces to containers use SR-IOV and pipework # to assign them. [ $IFTYPE = ipoib ] && { GUEST_IFNAME=$CONTAINER_IFNAME } # If it's a physical interface, create a macvlan subinterface [ $IFTYPE = phys ] && { [ "$VLAN" ] && { [ ! -d /sys/class/net/$IFNAME.$VLAN ] && { ip link add link $IFNAME name $IFNAME.$VLAN mtu $MTU type vlan id $VLAN } ip link set $IFNAME up IFNAME=$IFNAME.$VLAN } GUEST_IFNAME=ph$NSPID$CONTAINER_IFNAME ip link add link $IFNAME dev $GUEST_IFNAME mtu $MTU type macvlan mode bridge ip link set $IFNAME up } ip link set $GUEST_IFNAME netns $NSPID ip netns exec $NSPID ip link set $GUEST_IFNAME name $CONTAINER_IFNAME [ "$MACADDR" ] && ip netns exec $NSPID ip link set dev $CONTAINER_IFNAME address $MACADDR if [ "$IPADDR" = "dhcp" ] then [ $DHCP_CLIENT = "udhcpc" ] && ip netns exec $NSPID $DHCP_CLIENT -qi $CONTAINER_IFNAME -x hostname:$GUESTNAME if [ $DHCP_CLIENT = "dhclient" ] then # kill dhclient after get ip address to prevent device be used after container close ip netns exec $NSPID $DHCP_CLIENT -pf "/var/run/dhclient.$NSPID.pid" $CONTAINER_IFNAME kill "$(cat "/var/run/dhclient.$NSPID.pid")" rm "/var/run/dhclient.$NSPID.pid" fi [ $DHCP_CLIENT = "dhcpcd" ] && ip netns exec $NSPID $DHCP_CLIENT -q $CONTAINER_IFNAME -h $GUESTNAME else ip netns exec $NSPID ip addr add $IPADDR dev $CONTAINER_IFNAME [ "$GATEWAY" ] && { ip netns exec $NSPID ip route delete default >/dev/null 2>&1 && true } ip netns exec $NSPID ip link set $CONTAINER_IFNAME up [ "$GATEWAY" ] && { ip netns exec $NSPID ip route get $GATEWAY >/dev/null 2>&1 || \ ip netns exec $NSPID ip route add $GATEWAY/32 dev $CONTAINER_IFNAME ip netns exec $NSPID ip route replace default via $GATEWAY } fi # Give our ARP neighbors a nudge about the new interface if which arping > /dev/null 2>&1 then IPADDR=$(echo $IPADDR | cut -d/ -f1) ip netns exec $NSPID arping -c 1 -A -I $CONTAINER_IFNAME $IPADDR > /dev/null 2>&1 || true else echo "Warning: arping not found; interface may not be immediately reachable" fi # Remove NSPID to avoid `ip netns` catch it. [ -f /var/run/netns/$NSPID ] && rm -f /var/run/netns/$NSPID exit 0 vagrant-lxc-1.2.1/metadata.yml0000644000004100000410000000646012611107101016270 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: vagrant-lxc version: !ruby/object:Gem::Version version: 1.2.1 platform: ruby authors: - Fabio Rehm autorequire: bindir: bin cert_chain: [] date: 2015-09-24 00:00:00.000000000 Z dependencies: [] description: Linux Containers provider for Vagrant email: - fgrehm@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - ".rspec" - ".travis.yml" - ".vimrc" - BOXES.md - CHANGELOG.md - CONTRIBUTING.md - Gemfile - Gemfile.lock - Guardfile - LICENSE.txt - README.md - Rakefile - lib/vagrant-lxc.rb - lib/vagrant-lxc/action.rb - lib/vagrant-lxc/action/boot.rb - lib/vagrant-lxc/action/clear_forwarded_ports.rb - lib/vagrant-lxc/action/compress_rootfs.rb - lib/vagrant-lxc/action/create.rb - lib/vagrant-lxc/action/destroy.rb - lib/vagrant-lxc/action/destroy_confirm.rb - lib/vagrant-lxc/action/fetch_ip_from_dnsmasq_leases.rb - lib/vagrant-lxc/action/fetch_ip_with_lxc_attach.rb - lib/vagrant-lxc/action/forced_halt.rb - lib/vagrant-lxc/action/forward_ports.rb - lib/vagrant-lxc/action/gc_private_network_bridges.rb - lib/vagrant-lxc/action/handle_box_metadata.rb - lib/vagrant-lxc/action/prepare_nfs_settings.rb - lib/vagrant-lxc/action/prepare_nfs_valid_ids.rb - lib/vagrant-lxc/action/private_networks.rb - lib/vagrant-lxc/action/setup_package_files.rb - lib/vagrant-lxc/action/warn_networks.rb - lib/vagrant-lxc/command/root.rb - lib/vagrant-lxc/command/sudoers.rb - lib/vagrant-lxc/config.rb - lib/vagrant-lxc/driver.rb - lib/vagrant-lxc/driver/cli.rb - lib/vagrant-lxc/errors.rb - lib/vagrant-lxc/plugin.rb - lib/vagrant-lxc/provider.rb - lib/vagrant-lxc/provider/cap/public_address.rb - lib/vagrant-lxc/sudo_wrapper.rb - lib/vagrant-lxc/synced_folder.rb - lib/vagrant-lxc/version.rb - locales/en.yml - scripts/lxc-template - scripts/pipework - spec/Vagrantfile - spec/fixtures/sample-ip-addr-output - spec/spec_helper.rb - spec/support/.gitkeep - spec/unit/action/clear_forwarded_ports_spec.rb - spec/unit/action/compress_rootfs_spec.rb - spec/unit/action/forward_ports_spec.rb - spec/unit/action/handle_box_metadata_spec.rb - spec/unit/action/setup_package_files_spec.rb - spec/unit/driver/cli_spec.rb - spec/unit/driver_spec.rb - spec/unit/support/unit_example_group.rb - spec/unit_helper.rb - tasks/spec.rake - templates/sudoers.rb.erb - vagrant-lxc.gemspec - vagrant-spec.config.rb homepage: https://github.com/fgrehm/vagrant-lxc licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.1 signing_key: specification_version: 4 summary: Linux Containers provider for Vagrant test_files: - spec/Vagrantfile - spec/fixtures/sample-ip-addr-output - spec/spec_helper.rb - spec/support/.gitkeep - spec/unit/action/clear_forwarded_ports_spec.rb - spec/unit/action/compress_rootfs_spec.rb - spec/unit/action/forward_ports_spec.rb - spec/unit/action/handle_box_metadata_spec.rb - spec/unit/action/setup_package_files_spec.rb - spec/unit/driver/cli_spec.rb - spec/unit/driver_spec.rb - spec/unit/support/unit_example_group.rb - spec/unit_helper.rb vagrant-lxc-1.2.1/.vimrc0000644000004100000410000000006712611107101015103 0ustar www-datawww-dataset wildignore+=*/boxes/*/rootfs/*,*/boxes/*/partial/* vagrant-lxc-1.2.1/.gitignore0000644000004100000410000000042712611107101015752 0ustar www-datawww-data*.gem *.rbc .bundle .config coverage InstalledFiles lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp # YARD artifacts .yardoc _yardoc doc/ /tags /gems.tags .vagrant /cache /boxes/**/*.tar.gz /boxes/**/partial/ /boxes/**/rootfs/ /boxes/temp/ /boxes/output/ vagrant-lxc-1.2.1/vagrant-lxc.gemspec0000644000004100000410000000137312611107101017556 0ustar www-datawww-data# -*- encoding: utf-8 -*- lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'vagrant-lxc/version' Gem::Specification.new do |gem| gem.name = "vagrant-lxc" gem.version = Vagrant::LXC::VERSION gem.authors = ["Fabio Rehm"] gem.email = ["fgrehm@gmail.com"] gem.description = %q{Linux Containers provider for Vagrant} gem.summary = gem.description gem.license = 'MIT' gem.homepage = "https://github.com/fgrehm/vagrant-lxc" gem.files = `git ls-files`.split($/) gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = ["lib"] end vagrant-lxc-1.2.1/BOXES.md0000644000004100000410000000415612611107101015167 0ustar www-datawww-data# vagrant-lxc base boxes Although the official documentation says it is only supported for VirtualBox environments, you can use the [`vagrant package`](http://docs.vagrantup.com/v2/cli/package.html) command to export a `.box` file from an existing vagrant-lxc container. There is also a set of [bash scripts](https://github.com/fgrehm/vagrant-lxc-base-boxes) that you can use to build base boxes as needed. By default it won't include any provisioning tool and you can pick the ones you want by providing some environment variables. Please refer to the [base boxes repository](https://github.com/fgrehm/vagrant-lxc-base-boxes) for more information. ## "Anatomy" of a box If you need to go deeper and build your scripts from scratch or if you are interested on knowing what makes a base box for vagrant-lxc, here's what's needed: ### Expected `.box` contents | FILE | REQUIRED? | DESCRIPTION | | --- | --- | --- | | `metadata.json` | Yes | Required by Vagrant | | `rootfs.tar.gz` | Yes | Compressed container rootfs tarball (need to remeber to pass in `--numeric-owner` when creating it) | | `lxc-template` | No, a ["generic script"](scripts/lxc-template) is provided by the plugin if it doesn't exist on the base box | Script responsible for creating and setting up the container (used with `lxc-create`). | | `lxc-config` | No | Box specific configuration to be _appended_ to the system's generated container config file | | `lxc.conf` | No | File passed in to `lxc-create -f` | ### metadata.json ```json { "provider": "lxc", "version": "1.0.0", "built-on": "Sat Sep 21 21:10:00 UTC 2013", "template-opts": { "--arch": "amd64", "--release": "quantal" } } ``` | KEY | REQUIRED? | DESCRIPTION | | --- | --- | --- | | `provider` | Yes | Required by Vagrant | | `version` | Yes | Tracks backward incompatibilities | | `built-on` | No | Date / time when the box was packaged for the first time | | `template-opts` | No | Extra options to be passed to the `lxc-template` script | vagrant-lxc-1.2.1/tasks/0000755000004100000410000000000012611107101015104 5ustar www-datawww-datavagrant-lxc-1.2.1/tasks/spec.rake0000644000004100000410000000203212611107101016677 0ustar www-datawww-databegin require 'rspec/core/rake_task' require 'coveralls/rake/task' desc 'Run all specs' task :spec => ['spec:set_coverage', 'spec:unit', 'spec:acceptance'] desc 'Default task which runs all specs with code coverage enabled' task :default => ['spec:set_coverage', 'spec:unit'] Coveralls::RakeTask.new task :ci => ['spec:set_coverage', 'spec:unit', 'coveralls:push'] rescue LoadError; end namespace :spec do task :set_coverage do ENV['COVERAGE'] = 'true' end desc 'Run acceptance specs using vagrant-spec' task :acceptance do components = %w( basic network/forwarded_port synced_folder synced_folder/nfs synced_folder/rsync provisioner/shell provisioner/puppet provisioner/chef-solo package ).map{|s| "provider/lxc/#{s}" } sh "export ACCEPTANCE=true && bundle exec vagrant-spec test --components=#{components.join(' ')}" end desc "Run unit specs with rspec" RSpec::Core::RakeTask.new(:unit) do |t| t.pattern = "./unit/**/*_spec.rb" end end vagrant-lxc-1.2.1/CONTRIBUTING.md0000644000004100000410000000262612611107101016216 0ustar www-datawww-data### Please read before contributing * If you have an issue with base boxes, please create it on https://github.com/fgrehm/vagrant-lxc-base-boxes, this repository is for the Vagrant plugin only. * Try not to post questions in the issues tracker. I will probably answer you but I'll most likely close the issue right away and will continue the discussion with the issue closed. If you have any questions about the plugin, make sure you go through the [Wiki](https://github.com/fgrehm/vagrant-lxc/wiki) pages first (specially the [Troubleshooting Section](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting)) and if you still need answers please ask a question on [Stack Overflow](http://stackoverflow.com/questions/tagged/vagrant-lxc) using the `vagrant` / `lxc` tag on it so that I get notified :) * Please do a search on the issues tracker before submitting your issue to check if it was already reported / fixed. * When reporting a bug, please include **all** information that you can get about your environment. Things like vagrant / vagrant-lxc / kernel / lxc / distro versions, the list of plugins you have installed, a [gist](https://gist.github.com/) with the output of running `VAGRANT_LOG=debug vagrant COMMAND`, the `Vagrantfile` you are using and / or base box URL are really useful when tracking down what's going on on your side of the globe and will get bonus points :) Thanks! vagrant-lxc-1.2.1/CHANGELOG.md0000644000004100000410000004710412611107101015576 0ustar www-datawww-data## [1.2.1](https://github.com/fgrehm/vagrant-lxc/compare/v1.2.0...v1.2.1) (Sep 24, 2015) BUGFIX: - Fix sudo Wrapper [[GH-393]] [GH-393]: https://github.com/fgrehm/vagrant-lxc/pull/393 ## [1.2.0](https://github.com/fgrehm/vagrant-lxc/compare/v1.1.0...v1.2.0) (Sep 15, 2015) FEATURES: - Support private networking using DHCP [[GH-352]] [GH-352]: https://github.com/fgrehm/vagrant-lxc/pull/352 IMPROVEMENTS: - Move mountpoint creation to lxc template for lvm rootfs support [[GH-361]] / [[GH-359]] - Mount selinux sys dir read-only [[GH-357]] / [[GH-301]] - Use correct ruby interpreter when generating sudoers file [[GH-355]] - Fix shebangs to be more portable [[GH-376]] - Fix removal of lxcbr0/virbr0 when using private networking [[GH-383]] - Improve /tmp handling by using tmpfs [[GH-362]] [GH-301]: https://github.com/fgrehm/vagrant-lxc/issues/301 [GH-355]: https://github.com/fgrehm/vagrant-lxc/pull/355 [GH-357]: https://github.com/fgrehm/vagrant-lxc/pull/357 [GH-359]: https://github.com/fgrehm/vagrant-lxc/issues/359 [GH-361]: https://github.com/fgrehm/vagrant-lxc/pull/361 [GH-376]: https://github.com/fgrehm/vagrant-lxc/pull/376 [GH-383]: https://github.com/fgrehm/vagrant-lxc/pull/383 [GH-362]: https://github.com/fgrehm/vagrant-lxc/pull/362 ## [1.1.0](https://github.com/fgrehm/vagrant-lxc/compare/v1.0.1...v1.1.0) (Jan 14, 2015) BACKWARDS INCOMPATIBILITIES: - Support for Vagrant versions prior to 1.5 have been removed. The plugin now targets Vagrant 1.7+ but it _might_ work on 1.5+. FEATURES: - New experimental support for private networking [[GH-298]] / [[GH-120]]. - Support for formatted overlayfs path [[GH-329]] [GH-298]: https://github.com/fgrehm/vagrant-lxc/pull/298 [GH-120]: https://github.com/fgrehm/vagrant-lxc/issues/120 [GH-329]: https://github.com/fgrehm/vagrant-lxc/pull/329 IMPROVEMENTS: - The provider will now have a higher priority over the VirtualBox provider in case VirtualBox is installed alongside lxc dependecies. - Show an user friendly message when trying to use the plugin on non-Linux environments. BUG FIXES: - Allow backingstore options to be used along with the sudo wrapper script [[GH-310]] - Trim automatically generated container names to 64 chars [[GH-337]] [GH-337]: https://github.com/fgrehm/vagrant-lxc/issues/337 [GH-310]: https://github.com/fgrehm/vagrant-lxc/issues/310 ## [1.0.1](https://github.com/fgrehm/vagrant-lxc/compare/v1.0.0...v1.0.1) (Oct 15, 2014) IMPROVEMENTS: - Avoid lock race condition when fetching container's IP [[GH-318]] and SSH execution [[GH-321]] - Support for custom containers storage path by reading `lxc.lxcpath` [[GH-317]] [GH-317]: https://github.com/fgrehm/vagrant-lxc/pull/317 [GH-318]: https://github.com/fgrehm/vagrant-lxc/pull/318 [GH-321]: https://github.com/fgrehm/vagrant-lxc/issues/321 ## [1.0.0](https://github.com/fgrehm/vagrant-lxc/compare/v1.0.0.alpha.3...v1.0.0) (Sep 23, 2014) DEPRECATIONS: - Support to **all Vagrant versions prior to 1.5 are deprecated**, there is a [small layer](lib/vagrant-backports) that ensures compatibility with versions starting with 1.1.5 that will be removed on a future release. - Official base boxes that were made available from http://bit.ly are no longer supported and were removed from @fgrehm's Dropbox, please upgrade your Vagrant and vagrant-lxc installation and use a base box from [VagrantCloud](https://vagrantcloud.com/search?provider=lxc) BACKWARDS INCOMPATIBILITIES: - Remove plugin version from config file name generated by the `vagrant lxc sudoers` command. Manual removal of `/usr/local/bin/vagrant-lxc-wrapper-*` / `/etc/sudoers.d/vagrant-lxc-*` files are required. IMPROVEMENTS: - `vagrant-mounted` upstart event is now emited on containers that support it [[GH-302]] - Add support for specifying the `--strip-parameters` used by the [default template](scripts/lxc-template) when extracting rootfs tarballs [[GH-311]] [GH-302]: https://github.com/fgrehm/vagrant-lxc/issues/302 BUG FIXES: - Check for outdated base boxes when starting containers [[GH-314]] [GH-311]: https://github.com/fgrehm/vagrant-lxc/pull/311 [GH-314]: https://github.com/fgrehm/vagrant-lxc/pull/314 ## [1.0.0.alpha.3](https://github.com/fgrehm/vagrant-lxc/compare/v1.0.0.alpha.2...v1.0.0.alpha.3) (Aug 9, 2014) IMPROVEMENTS: - Remove `lxc-shutdown` usage in favor of Vagrant's built in graceful halt - Add fallback mechanism for platforms without `lxc-attach` support [[GH-294]] [GH-294]: https://github.com/fgrehm/vagrant-lxc/pull/294 BUG FIXES: - Figure out the real executable paths for whitelisted commands on the sudo wrapper script instead of hardcoding Ubuntu paths [[GH-304]] / [[GH-305]] - Attach to containers using the `MOUNT` namespace when attempting to fetch container's IP [[GH-300]] - Escape space characters for synced folders [[GH-291]] - Use Vagrant's ruby on the sudoers file so that it works on systems that don't have a global ruby installation [[GH-289]] [GH-304]: https://github.com/fgrehm/vagrant-lxc/issues/304 [GH-305]: https://github.com/fgrehm/vagrant-lxc/issues/305 [GH-300]: https://github.com/fgrehm/vagrant-lxc/issues/300 [GH-291]: https://github.com/fgrehm/vagrant-lxc/issues/291 [GH-289]: https://github.com/fgrehm/vagrant-lxc/issues/289 ## [1.0.0.alpha.2](https://github.com/fgrehm/vagrant-lxc/compare/v1.0.0.alpha.1...v1.0.0.alpha.2) (May 13, 2014) BACKWARDS INCOMPATIBILITIES: - The `sudo_wrapper` provider configuration was removed in favor of using the secure wrapper generated by `vagrant lxc sudoers` [[GH-272]] - Support for specifying backingstore parameters from `Vagrantfile`s for `lxc-create` was added and it defaults to the `best` option. On older lxc versions that does not support that value, it needs to be set to `none`. FEATURES: - Add support for specifying backingstore parameters from `Vagrantfile`s [[GH-277]] IMPROVEMENTS: - Make `dnsmasq` leases MAC address regex check case insensitive [[GH-283]] - Use relative paths for `lxc.mount.entry` to avoid issues with `lxc-clone` [[GH-258]]. - Sort synced folders when mounting [[GH-271]] - Privileged ports can now be forwarded with `sudo` [[GH-259]] - The `vagrant lxc sudoers` generated sudoers configuration and wrapper script are safer and properly whitelists the commands required by vagrant-lxc to run. [[GH-272]] / [[GH-269]] BUG FIXES: - Fix `lxc-create` issues with pre 1.0.0 versions [[GH-282]] [GH-283]: https://github.com/fgrehm/vagrant-lxc/pull/283 [GH-282]: https://github.com/fgrehm/vagrant-lxc/pull/282 [GH-269]: https://github.com/fgrehm/vagrant-lxc/issues/269 [GH-272]: https://github.com/fgrehm/vagrant-lxc/pull/272 [GH-259]: https://github.com/fgrehm/vagrant-lxc/pull/259 [GH-271]: https://github.com/fgrehm/vagrant-lxc/pull/271 [GH-277]: https://github.com/fgrehm/vagrant-lxc/pull/277 [GH-258]: https://github.com/fgrehm/vagrant-lxc/issues/258 ## [1.0.0.alpha.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.8.0...v1.0.0.alpha.1) (Apr 06, 2014) DEPRECATIONS: - Support to **all Vagrant versions prior to 1.5 are now deprecated**, there is a [small layer](lib/vagrant-backports) that ensures compatibility with versions starting with 1.1.5 but there is no guarantee that it will stick for too long. - Boxes released prior to this version are now deprecated and won't be available after the final 1.0.0 release. - `--auth-key` argument is no longer provided to `lxc-template`. This will cause all official base boxes prior to 09/28/2013 to break. FEATURES: - New `vagrant lxc sudoers` command for creating a policy for users in order to avoid `sudo` passwords [[GH-237]] / [[GH-257]] - Support for NFS and rsync synced folders. - Support for synced folder mount options allowing for using read only synced folders [[GH-193]] [GH-237]: https://github.com/fgrehm/vagrant-lxc/issues/237 [GH-257]: https://github.com/fgrehm/vagrant-lxc/pull/257 [GH-193]: https://github.com/fgrehm/vagrant-lxc/issues/193 IMPROVEMENTS: - `lxc-template` is now optional for base boxes and are bundled with the plugin, allowing us to roll out updates without the need to rebuild boxes [[GH-254]] - Set container's `utsname` to `config.vm.hostname` by default [[GH-253]] - Added libvirt dnsmasq leases file to the lookup paths [[GH-251]] - Improved compatibility with Vagrant 1.4 / 1.5 including the ability to use `rsync` and `nfs` shared folders to work around synced folders permission problems. More information can be found on the following issues: [[GH-151]] [[GH-191]] [[GH-241]] [[GH-242]] - Warn in case `:group` or `:owner` are specified for synced folders [[GH-196]] - Acceptance specs are now powered by `vagrant-spec` [[GH-213]] - Base boxes creation scripts were moved out to https://github.com/fgrehm/vagrant-lxc-base-boxes. [GH-254]: https://github.com/fgrehm/vagrant-lxc/issues/254 [GH-196]: https://github.com/fgrehm/vagrant-lxc/issues/196 [GH-251]: https://github.com/fgrehm/vagrant-lxc/pull/251 [GH-253]: https://github.com/fgrehm/vagrant-lxc/pull/253 [GH-151]: https://github.com/fgrehm/vagrant-lxc/issues/151 [GH-213]: https://github.com/fgrehm/vagrant-lxc/issues/213 [GH-191]: https://github.com/fgrehm/vagrant-lxc/issues/191 [GH-241]: https://github.com/fgrehm/vagrant-lxc/issues/241 [GH-242]: https://github.com/fgrehm/vagrant-lxc/issues/242 ## [0.8.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.7.0...v0.8.0) (Feb 26, 2014) FEATURES: - Support for naming containers from Vagrantfiles [#132](https://github.com/fgrehm/vagrant-lxc/issues/132) IMPROVEMENTS: - Use a safer random name for containers [#152](https://github.com/fgrehm/vagrant-lxc/issues/152) - Improve Ubuntu 13.10 compatibility [#190](https://github.com/fgrehm/vagrant-lxc/pull/190) / [#197](https://github.com/fgrehm/vagrant-lxc/pull/197) - Improved mac address detection from lxc configs [#226](https://github.com/fgrehm/vagrant-lxc/pull/226) BUG FIXES: - Properly detect if lxc is installed on hosts that do not have `lxc-version` on their paths [#186](https://github.com/fgrehm/vagrant-lxc/issues/186) ## [0.7.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.6.4...v0.7.0) (Nov 8, 2013) IMPROVEMENTS: - Support for `vagrant up` in parallel [#152](https://github.com/fgrehm/vagrant-lxc/issues/152) - Warn users about unsupported private / public networking configs [#154](https://github.com/fgrehm/vagrant-lxc/issues/154) - Respect Vagrantfile options to disable forwarded port [#149](https://github.com/fgrehm/vagrant-lxc/issues/149) BUG FIXES: - Nicely handle blank strings provided to `:host_ip` when specifying forwarded ports [#170](https://github.com/fgrehm/vagrant-lxc/issues/170) - Fix "Permission denied" when starting/destroying containers after lxc security update in Ubuntu [#180](https://github.com/fgrehm/vagrant-lxc/issues/180) - Fix `vagrant package` [#172](https://github.com/fgrehm/vagrant-lxc/issues/172) ## [0.6.4](https://github.com/fgrehm/vagrant-lxc/compare/v0.6.3...v0.6.4) (Oct 27, 2013) FEATURES: - New script for building OpenMandriva base boxes [#167](https://github.com/fgrehm/vagrant-lxc/issues/167) IMPROVEMENTS: - Make `lxc-template` compatible with Ubuntu 13.10 [#150](https://github.com/fgrehm/vagrant-lxc/issues/150) BUG FIXES: - Fix force halt for hosts that do not have `lxc-shutdown` around (like Ubuntu 13.10) [#150](https://github.com/fgrehm/vagrant-lxc/issues/150) ## [0.6.3](https://github.com/fgrehm/vagrant-lxc/compare/v0.6.2...v0.6.3) (Oct 12, 2013) IMPROVEMENTS: - Respect Vagrantfile option to disable synced folders [#147](https://github.com/fgrehm/vagrant-lxc/issues/147) BUG FIXES: - Fix error raised when fetching container's IP with the sudo wrapper disabled [#157](https://github.com/fgrehm/vagrant-lxc/issues/157) ## [0.6.2](https://github.com/fgrehm/vagrant-lxc/compare/v0.6.1...v0.6.2) (Oct 03, 2013) IMPROVEMENTS: - Cache the result of `lxc-attach --namespaces` parameter support checking to avoid excessive logging. BUG FIXES: - Fix detection of `lxc-attach --namespaces` parameter support checking. ## [0.6.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.6.0...v0.6.1) (Oct 03, 2013) IMPROVEMENTS: - Fall back to `dnsmasq` leases file if not able to fetch IP with `lxc-attach` [#118](https://github.com/fgrehm/vagrant-lxc/issues/118) - Make sure lxc templates are executable prior to `lxc-create` [#128](https://github.com/fgrehm/vagrant-lxc/issues/128) - New base boxes with support for lxc 1.0+ BUG FIXES: - Fix various issues related to detecting whether the container is running and is "SSHable" [#142](https://github.com/fgrehm/vagrant-lxc/issues/142) - Nicely handle missing templates path [#139](https://github.com/fgrehm/vagrant-lxc/issues/139) ## [0.6.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.5.0...v0.6.0) (Sep 12, 2013) IMPROVEMENTS: - Compatibility with Vagrant 1.3+ [#136](https://github.com/fgrehm/vagrant-lxc/pull/136) - Set plugin name to `vagrant-lxc` so that it is easier to check if the plugin is installed with the newly added `Vagrant.has_plugin?` BUG FIXES: - Fix box package ownership on `vagrant package` [#140](https://github.com/fgrehm/vagrant-lxc/pull/140) - Fix error while compressing container's rootfs under Debian hosts [#131](https://github.com/fgrehm/vagrant-lxc/issues/131) / [#133](https://github.com/fgrehm/vagrant-lxc/issues/133) ## [0.5.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.4.0...v0.5.0) (Aug 1, 2013) BACKWARDS INCOMPATIBILITIES: - To align with Vagrant's core behaviour, forwarded ports are no longer attached to 127.0.0.1 and `redir`'s `--laddr` parameter is skipped in case the `:host_ip` config is not provided, that means `redir` will listen on connections coming from any of the host's IPs. FEATURES: - Add support for salt-minion and add latest dev release for ubuntu codenamed saucy [#116](https://github.com/fgrehm/vagrant-lxc/pull/116) - Add support for using a sudo wrapper script [#90](https://github.com/fgrehm/vagrant-lxc/issues/90) - `redir` will log to `/var/log/syslog` if `REDIR_LOG` env var is provided IMPROVEMENTS: - Error out if dependencies are not installed [#11](https://github.com/fgrehm/vagrant-lxc/issues/11) / [#112](https://github.com/fgrehm/vagrant-lxc/issues/112) - Support for specifying host interface/ip for binding `redir` [#76](https://github.com/fgrehm/vagrant-lxc/issues/76) - Add Vagrantfile VM name to the container name [#115](https://github.com/fgrehm/vagrant-lxc/issues/115) - Properly handle forwarded port collisions [#5](https://github.com/fgrehm/vagrant-lxc/issues/5) - Container's customizations are now written to the config file (usually kept under `/var/lib/lxc/CONTAINER/config`) instead of passed in as a `-s` parameter to `lxc-start` ## [0.4.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.3.4...v0.4.0) (Jul 18, 2013) FEATURES: - New box format [#89](https://github.com/fgrehm/vagrant-lxc/issues/89) BUG FIXES: - Add translation for stopped status [#97](https://github.com/fgrehm/vagrant-lxc/issues/97) - Enable retries when fetching container state [#74](https://github.com/fgrehm/vagrant-lxc/issues/74) - Fix error when setting Debian boxes hostname from Vagrantfile [#91](https://github.com/fgrehm/vagrant-lxc/issues/91) - BTRFS-friendly base boxes [#81](https://github.com/fgrehm/vagrant-lxc/issues/81) - Extended templates path lookup [#77](https://github.com/fgrehm/vagrant-lxc/issues/77) (tks to @aries1980) - Fix default group for packaged boxes tarballs on the rake task [#82](https://github.com/fgrehm/vagrant-lxc/issues/82) (tks to @cduez) ## [0.3.4](https://github.com/fgrehm/vagrant-lxc/compare/v0.3.3...v0.3.4) (May 08, 2013) FEATURES: - Support for building Debian boxes (tks to @Val) - Support for installing babushka on base boxes (tks to @Val) IMPROVEMENTS: - Replace `lxc-wait` usage with a "[retry mechanism](https://github.com/fgrehm/vagrant-lxc/commit/3cca16824879731315dac32bc2df1c643f30d461#L2R88)" [#22](https://github.com/fgrehm/vagrant-lxc/issues/22) - Remove `/tmp` files after the machine has been successfully shut down [#68](https://github.com/fgrehm/vagrant-lxc/issues/68) - Clean up base boxes files after they've been configured, resulting in smaller packages - Bump development dependency to Vagrant 1.2+ series BUG FIXES: - Issue a `lxc-stop` in case the container cannot shutdown gracefully [#72](https://github.com/fgrehm/vagrant-lxc/issues/72) ## [0.3.3](https://github.com/fgrehm/vagrant-lxc/compare/v0.3.2...v0.3.3) (April 23, 2013) BUG FIXES: - Properly kill `redir` child processes [#59](https://github.com/fgrehm/vagrant-lxc/issues/59) - Use `uname -m` on base Ubuntu lxc-template [#53](https://github.com/fgrehm/vagrant-lxc/issues/53) IMPROVEMENTS: - Initial acceptance test suite - New rake tasks for building Ubuntu precise and raring base amd64 boxes ## [0.3.2](https://github.com/fgrehm/vagrant-lxc/compare/v0.3.1...v0.3.2) (April 18, 2013) - Do not display port forwarding message in case no forwarded ports were set ## [0.3.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.3.0...v0.3.1) (April 18, 2013) - Improved output to match lxc "verbiage" ## [0.3.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.2.0...v0.3.0) (April 10, 2013) BACKWARDS INCOMPATIBILITIES: - Boxes `lxc-template` should support a `--tarball` parameter - `start_opts` config was renamed to `customize`, please check the README for the expected parameters - V1 boxes are no longer supported - `target_rootfs_path` is no longer supported, just symlink `/var/lib/lxc` to the desired folder in case you want to point it to another partition - Removed support for configuring private networks. It will come back at some point in the future but if you need it you should be able to set using `customize 'network.ipv4', '1.2.3.4/24'` IMPROVEMENTS: - lxc templates are removed from lxc template dir after container is created - Treat NFS shared folders as a normal shared folder instead of ignoring it so we can share the same Vagrantfile with VBox environments - Support for lxc 0.7.5 (tested on Ubuntu 12.04) [#49](https://github.com/fgrehm/vagrant-lxc/issues/49) - Remove `/tmp` files when packaging quantal64 base box [#48](https://github.com/fgrehm/vagrant-lxc/issues/48) - Avoid picking the best mirror on quantal64 base box [#38](https://github.com/fgrehm/vagrant-lxc/issues/38) BUG FIXES: - Redirect `redir`'s stderr output to `/dev/null` [#51](https://github.com/fgrehm/vagrant-lxc/issues/51) - Switch from `ifconfig` to `ip` to grab container's IP to avoid localization issues [#50](https://github.com/fgrehm/vagrant-lxc/issues/50) ## [0.2.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.1.1...v0.2.0) (March 30, 2013) - Experimental box packaging (only tested with Ubuntu 64 base box) ## [0.1.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.1.0...v0.1.1) (March 29, 2013) - Removed support for development under Vagrant < 1.1 - Removed rsync from base quantal64 box to speed up containers creation [#40](https://github.com/fgrehm/vagrant-lxc/issues/40) - Containers are now named after project's root dir [#14](https://github.com/fgrehm/vagrant-lxc/issues/14) - Skip Vagrant's built in SSH redirect - Allow setting rootfs from Vagrantfile [#30](https://github.com/fgrehm/vagrant-lxc/issues/30) ## [0.1.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.0.3...v0.1.0) (March 27, 2013) - Support for chef added to base quantal64 box - Puppet upgraded to 3.1.1 on base quantal64 box - Port forwarding support added [#6](https://github.com/fgrehm/vagrant-lxc/issues/6) ## Previous The changelog began with version 0.1.0 so any changes prior to that can be seen by checking the tagged releases and reading git commit messages. vagrant-lxc-1.2.1/locales/0000755000004100000410000000000012611107101015401 5ustar www-datawww-datavagrant-lxc-1.2.1/locales/en.yml0000644000004100000410000000531512611107101016532 0ustar www-datawww-dataen: vagrant_lxc: messages: not_created: |- The container hasn't been created yet. not_running: |- The container is not currently running. will_not_destroy: |- The container '%{name}' will not be destroyed, since the confirmation was declined. starting: |- Starting container... force_shutdown: |- Forcing shutdown of container... warn_networks: |- Warning! The LXC provider doesn't support public networks, the settings will be silently ignored. warn_group: |- Warning! The LXC provider doesn't support the :group parameter for synced folders. It will be silently ignored. warn_owner: |- Warning! The LXC provider doesn't support the :owner parameter for synced folders. It will be silently ignored. setup_private_network: |- Setting up private networks... remove_bridge: |- Removing bridge '%{name}'... vagrant: commands: status: stopped: |- The container is currently stopped. Run `vagrant up` to bring it up again. actions: lxc: compressing_rootfs: Compressing container's rootfs... share_folders: preparing: Setting up mount entries for shared folders... errors: lxc_execute_error: |- There was an error executing %{command} For more information on the failure, enable detailed logging by setting the environment variable VAGRANT_LOG to DEBUG. lxc_incompatible_box: |- The base box you are trying to use is not compatible with the installed vagrant-lxc version. Supported box versions are %{supported} but %{found} was found. lxc_template_file_missing: |- The template file used for creating the container was not found for %{name} box. lxc_templates_dir_missing: |- Unable to identify lxc templates path. Looked up under: %{paths} lxc_linux_required: |- The LXC provider only works on Linux. Please try to use another provider. lxc_not_installed: |- The `lxc` package does not seem to be installed or `lxc-create` is not accessible on the PATH. lxc_redir_not_installed: |- `redir` is not installed or is not accessible on the PATH. lxc_container_already_exists: |- There is container on your system with the same name you've specified on your Vagrantfile (%{name}), please choose a different one or run `lxc-destroy --name %{name}` and try again. lxc_command_not_supported: |- Command (lxc-%{command}) not supported in version %{version}. This command is available with version %{available_version}. vagrant-lxc-1.2.1/vagrant-spec.config.rb0000644000004100000410000000133112611107101020140 0ustar www-datawww-data# FIXME: Figure out why this doesn't work if ENV['COVERAGE'] == 'true' require 'simplecov' require 'coveralls' SimpleCov.start { add_filter '/spec/' } SimpleCov.command_name 'acceptance' end if ENV['BOX_PATH'] == nil latest = ENV.fetch('LATEST_BOXES','2014-03-21') release = ENV.fetch('RELEASE', 'acceptance') local_path ="#{File.expand_path("../", __FILE__)}/boxes/output/#{latest}/vagrant-lxc-#{release}-amd64.box" if File.exists?(local_path) ENV['BOX_PATH'] = local_path else raise 'Set $BOX_PATH to the latest released boxes' end end Vagrant::Spec::Acceptance.configure do |c| c.component_paths << "spec/acceptance" c.provider 'lxc', box: ENV['BOX_PATH'], features: ['!suspend'] end vagrant-lxc-1.2.1/README.md0000644000004100000410000001670412611107101015246 0ustar www-datawww-data# vagrant-lxc [![Build Status](https://travis-ci.org/fgrehm/vagrant-lxc.png?branch=master)](https://travis-ci.org/fgrehm/vagrant-lxc) [![Gem Version](https://badge.fury.io/rb/vagrant-lxc.png)](http://badge.fury.io/rb/vagrant-lxc) [![Code Climate](https://codeclimate.com/github/fgrehm/vagrant-lxc.png)](https://codeclimate.com/github/fgrehm/vagrant-lxc) [![Coverage Status](https://coveralls.io/repos/fgrehm/vagrant-lxc/badge.png?branch=master)](https://coveralls.io/r/fgrehm/vagrant-lxc) [![Gitter chat](https://badges.gitter.im/fgrehm/vagrant-lxc.png)](https://gitter.im/fgrehm/vagrant-lxc) [LXC](http://lxc.sourceforge.net/) provider for [Vagrant](http://www.vagrantup.com/) 1.6+ This is a Vagrant plugin that allows it to control and provision Linux Containers as an alternative to the built in VirtualBox provider for Linux hosts. Check out [this blog post](http://fabiorehm.com/blog/2013/04/28/lxc-provider-for-vagrant/) to see it in action. ## Features * Provides the same workflow as the Vagrant VirtualBox provider * Port forwarding via [`redir`](http://linux.die.net/man/1/redir) * Private networking via [`pipework`](https://github.com/jpetazzo/pipework) ## Requirements * [Vagrant 1.5+](http://www.vagrantup.com/downloads.html) (tested with 1.7.2) * lxc 0.7.5+ * `redir` (if you are planning to use port forwarding) * `brctl` (if you are planning to use private networks, on Ubuntu this means `apt-get install bridge-utils`) * A [kernel != 3.5.0-17.28](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting#wiki-im-unable-to-restart-containers) The plugin is known to work better and pretty much out of the box on Ubuntu 14.04+ hosts and installing the dependencies on it basically means a `apt-get install lxc lxc-templates cgroup-lite redir` (older LXC versions like 0.7.5 shipped with Ubuntu 12.04 by default might require [additional configurations to work](#backingstore-options)). For setting up other types of hosts please have a look at the [Wiki](https://github.com/fgrehm/vagrant-lxc/wiki). If you are on a Mac or Windows machine, you might want to have a look at [this](http://the.taoofmac.com/space/HOWTO/Vagrant) blog post for some ideas on how to set things up or check out [this other repo](https://github.com/fgrehm/vagrant-lxc-vbox-hosts) for a set of Vagrant VirtualBox machines ready for vagrant-lxc usage. ## Installation ``` vagrant plugin install vagrant-lxc ``` ## Quick start ``` vagrant init fgrehm/precise64-lxc vagrant up --provider=lxc ``` _More information about skipping the `--provider` argument can be found at the "DEFAULT PROVIDER" section of [Vagrant docs](https://docs.vagrantup.com/v2/providers/basic_usage.html)_ ## Base boxes Base boxes can be found on [Atlas](https://atlas.hashicorp.com/boxes/search?provider=lxc) and some scripts to build your own are available at [fgrehm/vagrant-lxc-base-boxes](https://github.com/fgrehm/vagrant-lxc-base-boxes). If you want to build your own boxes, please have a look at [`BOXES.md`](https://github.com/fgrehm/vagrant-lxc/tree/master/BOXES.md) for more information. ## Advanced configuration You can modify container configurations from within your Vagrantfile using the [provider block](http://docs.vagrantup.com/v2/providers/configuration.html): ```ruby Vagrant.configure("2") do |config| config.vm.box = "fgrehm/trusty64-lxc" config.vm.provider :lxc do |lxc| # Same effect as 'customize ["modifyvm", :id, "--memory", "1024"]' for VirtualBox lxc.customize 'cgroup.memory.limit_in_bytes', '1024M' end end ``` vagrant-lxc will then write out `lxc.cgroup.memory.limit_in_bytes='1024M'` to the container config file (usually kept under `/var/lib/lxc//config`) prior to starting it. For other configuration options, please check the [lxc.conf manpages](http://manpages.ubuntu.com/manpages/precise/man5/lxc.conf.5.html). ### Private Networks [EXPERIMENTAL] Starting with vagrant-lxc 1.1.0, there is some rudimentary support for configuring [Private Networks](https://docs.vagrantup.com/v2/networking/private_network.html) by leveraging the [pipework](https://github.com/jpetazzo/pipework) project. On its current state, there is a requirement for setting the bridge name that will be created and will allow your machine to comunicate with the container For example: ```ruby Vagrant.configure("2") do |config| config.vm.network "private_network", ip: "192.168.2.100", lxc__bridge_name: 'vlxcbr1' end ``` Will create a new `veth` device for the container and will set up (or reuse) a `vlxcbr1` bridge between your machine and the `veth` device. Once the last vagrant-lxc container attached to the bridge gets `vagrant halt`ed, the plugin will delete the bridge. ### Container naming By default vagrant-lxc will attempt to generate a unique container name for you. However, if the container name is important to you, you may use the `container_name` attribute to set it explicitly from the `provider` block: ```ruby Vagrant.configure("2") do |config| config.vm.define "db" do |node| node.vm.provider :lxc do |lxc| lxc.container_name = :machine # Sets the container name to 'db' lxc.container_name = 'mysql' # Sets the container name to 'mysql' end end end ``` _Please note that there is a 64 chars limit and the container name will be trimmed down to that to ensure we can always bring the container up. ### Backingstore options Support for setting `lxc-create`'s backingstore option (`-B` and related) can be specified from the provider block and it defaults to `best`, to change it: ```ruby Vagrant.configure("2") do |config| config.vm.provider :lxc do |lxc| lxc.backingstore = 'lvm' # or 'btrfs', 'overlayfs', ... # lvm specific options lxc.backingstore_option '--vgname', 'schroots' lxc.backingstore_option '--fssize', '5G' lxc.backingstore_option '--fstype', 'xfs' end end ``` For old versions of lxc (like 0.7.5 shipped with Ubuntu 12.04 by default) that does not support `best` for the backingstore option, changing it to `none` is required and a default for all Vagrant environments can be set from your `~/.vagrant.d/Vagrantfile` using the same `provider` block: ```ruby Vagrant.configure("2") do |config| config.vm.provider :lxc do |lxc| lxc.backingstore = 'none' end end ``` ## Avoiding `sudo` passwords This plugin requires **a lot** of `sudo`ing since [user namespaces](https://wiki.ubuntu.com/UserNamespace) is not supported yet. To work around that, you can use the `vagrant lxc sudoers` command which will create a file under `/etc/sudoers.d/vagrant-lxc` whitelisting all commands required by `vagrant-lxc` to run. If you are interested on what will be generated by that command, please check [this code](lib/vagrant-lxc/command/sudoers.rb). _vagrant-lxc < 1.0.0 users, please check this [Wiki page](https://github.com/fgrehm/vagrant-lxc/wiki/Avoiding-%27sudo%27-passwords)_ ## More information Please refer the [wiki](https://github.com/fgrehm/vagrant-lxc/wiki). ## Problems / ideas? Please review the [Troubleshooting](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting) wiki page + [known bugs](https://github.com/fgrehm/vagrant-lxc/issues?labels=bug&page=1&state=open) list if you have a problem and feel free to use the [issue tracker](https://github.com/fgrehm/vagrant-lxc/issues) propose new functionality and / or report bugs. ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request vagrant-lxc-1.2.1/Guardfile0000644000004100000410000000051412611107101015604 0ustar www-datawww-dataguard 'rspec', :spec_paths => ["spec/unit"] do watch(%r{^spec/unit/.+_spec\.rb$}) watch(%r{^lib/vagrant-lxc/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" } watch('spec/unit_helper.rb') { "spec/unit" } watch('spec/spec_helper.rb') { "spec/unit" } watch(%r{^spec/support/(.+)\.rb$}) { "spec/unit" } end