vagrant-lxc 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.vimrc +1 -1
  4. data/CHANGELOG.md +22 -0
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +10 -9
  7. data/README.md +43 -29
  8. data/boxes/quantal64/download-ubuntu +21 -20
  9. data/boxes/quantal64/lxc-template +11 -11
  10. data/boxes/quantal64/metadata.json +1 -1
  11. data/development/Vagrantfile +8 -4
  12. data/example/Vagrantfile +3 -15
  13. data/lib/vagrant-lxc.rb +0 -2
  14. data/lib/vagrant-lxc/action.rb +1 -14
  15. data/lib/vagrant-lxc/action/boot.rb +8 -9
  16. data/lib/vagrant-lxc/action/check_created.rb +6 -2
  17. data/lib/vagrant-lxc/action/check_running.rb +6 -2
  18. data/lib/vagrant-lxc/action/compress_rootfs.rb +1 -1
  19. data/lib/vagrant-lxc/action/create.rb +15 -7
  20. data/lib/vagrant-lxc/action/created.rb +6 -2
  21. data/lib/vagrant-lxc/action/destroy.rb +6 -2
  22. data/lib/vagrant-lxc/action/disconnect.rb +5 -1
  23. data/lib/vagrant-lxc/action/forced_halt.rb +3 -3
  24. data/lib/vagrant-lxc/action/forward_ports.rb +2 -2
  25. data/lib/vagrant-lxc/action/handle_box_metadata.rb +38 -27
  26. data/lib/vagrant-lxc/action/is_running.rb +6 -2
  27. data/lib/vagrant-lxc/action/share_folders.rb +8 -8
  28. data/lib/vagrant-lxc/config.rb +20 -10
  29. data/lib/vagrant-lxc/driver.rb +162 -0
  30. data/lib/vagrant-lxc/driver/builder.rb +21 -0
  31. data/lib/vagrant-lxc/{container → driver}/cli.rb +16 -11
  32. data/lib/vagrant-lxc/driver/fetch_ip_from_dnsmasq.rb +41 -0
  33. data/lib/vagrant-lxc/driver/fetch_ip_with_attach.rb +29 -0
  34. data/lib/vagrant-lxc/errors.rb +10 -0
  35. data/lib/vagrant-lxc/plugin.rb +4 -0
  36. data/lib/vagrant-lxc/provider.rb +14 -11
  37. data/lib/vagrant-lxc/version.rb +1 -1
  38. data/spec/fixtures/sample-ip-addr-output +2 -0
  39. data/spec/spec_helper.rb +1 -0
  40. data/spec/unit/action/compress_rootfs_spec.rb +4 -4
  41. data/spec/unit/action/forward_ports_spec.rb +3 -3
  42. data/spec/unit/action/handle_box_metadata_spec.rb +52 -26
  43. data/spec/unit/{container → driver}/cli_spec.rb +17 -19
  44. data/spec/unit/driver_spec.rb +173 -0
  45. data/tasks/boxes.rake +3 -3
  46. metadata +13 -15
  47. data/lib/vagrant-lxc/action/base_action.rb +0 -11
  48. data/lib/vagrant-lxc/action/network.rb +0 -21
  49. data/lib/vagrant-lxc/container.rb +0 -141
  50. data/lib/vagrant-lxc/machine_state.rb +0 -25
  51. data/spec/fixtures/sample-ifconfig-output +0 -18
  52. data/spec/unit/container_spec.rb +0 -147
  53. data/spec/unit/machine_state_spec.rb +0 -39
data/example/Vagrantfile CHANGED
@@ -1,34 +1,22 @@
1
1
  # -*- mode: ruby -*-
2
2
  # vi: set ft=ruby :
3
3
 
4
- def local_cache(box_name)
5
- cache_dir = File.join(File.expand_path(Vagrant::Environment::DEFAULT_HOME),
6
- 'cache',
7
- 'apt',
8
- box_name)
9
- partial_dir = File.join(cache_dir, 'partial')
10
- FileUtils.mkdir_p(partial_dir) unless File.exists? partial_dir
11
- cache_dir
12
- end
13
-
14
4
  # Not really needed, but useful while developing so that vagrant picks it up
15
5
  Vagrant.require_plugin 'vagrant-lxc'
16
6
 
17
7
  Vagrant.configure("2") do |config|
18
8
  config.vm.box = "quantal64"
19
- config.vm.box_url = 'http://dl.dropbox.com/u/13510779/lxc-quantal64-2013-03-31.box'
9
+ config.vm.box_url = 'http://dl.dropbox.com/u/13510779/lxc-quantal64-2013-04-10.box'
20
10
  # Uncomment if you want to try out a box built locally
21
11
  # config.vm.box_url = '../boxes/output/lxc-quantal64.box'
22
12
  config.vm.hostname = 'lxc-quantal64-example'
23
13
 
24
14
  config.vm.synced_folder "/tmp", "/vagrant_data"
25
15
 
26
- cache_dir = local_cache(config.vm.box)
27
- config.vm.synced_folder cache_dir, "/var/cache/apt/archives"
28
16
 
29
17
  config.vm.provider :lxc do |lxc|
30
- lxc.start_opts << 'lxc.cgroup.memory.limit_in_bytes=400M'
31
- lxc.start_opts << 'lxc.cgroup.memory.memsw.limit_in_bytes=500M'
18
+ lxc.customize 'cgroup.memory.limit_in_bytes', '400M'
19
+ lxc.customize 'cgroup.memory.memsw.limit_in_bytes', '500M'
32
20
  end
33
21
 
34
22
  config.vm.provision :shell, :inline => <<-SCRIPT
data/lib/vagrant-lxc.rb CHANGED
@@ -1,4 +1,2 @@
1
1
  require "vagrant-lxc/version"
2
2
  require "vagrant-lxc/plugin"
3
-
4
- I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../locales/en.yml')
@@ -1,7 +1,3 @@
1
- # TODO: Remove base action
2
- require 'vagrant-lxc/action/base_action'
3
-
4
- # TODO: Use require_relative
5
1
  require 'vagrant-lxc/action/boot'
6
2
  require 'vagrant-lxc/action/check_created'
7
3
  require 'vagrant-lxc/action/check_running'
@@ -15,7 +11,6 @@ require 'vagrant-lxc/action/forced_halt'
15
11
  require 'vagrant-lxc/action/forward_ports'
16
12
  require 'vagrant-lxc/action/handle_box_metadata'
17
13
  require 'vagrant-lxc/action/is_running'
18
- require 'vagrant-lxc/action/network'
19
14
  require 'vagrant-lxc/action/setup_package_files'
20
15
  require 'vagrant-lxc/action/share_folders'
21
16
 
@@ -42,11 +37,6 @@ module Vagrant
42
37
  end
43
38
  end
44
39
 
45
- # We could do this here as VirtualBox does, but at least for now its better
46
- # to be explicit and have the full constant name in order to easily spot
47
- # what we implemented and what is builtin on Vagrant.
48
- #
49
- # include Vagrant::Action::Builtin
50
40
 
51
41
  # This action boots the VM, assuming the VM is in a state that requires
52
42
  # a bootup (i.e. not saved).
@@ -56,11 +46,8 @@ module Vagrant
56
46
  b.use Vagrant::Action::Builtin::Provision
57
47
  b.use Vagrant::Action::Builtin::EnvSet, :port_collision_repair => true
58
48
  # b.use PrepareForwardedPortCollisionParams
59
- # b.use ClearSharedFolders
60
49
  b.use ShareFolders
61
- b.use Network
62
50
  b.use Vagrant::Action::Builtin::SetHostname
63
- # b.use Customize
64
51
  b.use ForwardPorts
65
52
  b.use Boot
66
53
  end
@@ -135,7 +122,7 @@ module Vagrant
135
122
  b2.use Disconnect
136
123
  b2.use ClearForwardedPorts
137
124
  b2.use Vagrant::Action::Builtin::Call, Vagrant::Action::Builtin::GracefulHalt, :stopped, :running do |env2, b3|
138
- if !env2[:result] && env2[:machine].provider.state.running?
125
+ if !env2[:result]
139
126
  b3.use ForcedHalt
140
127
  end
141
128
  end
@@ -1,20 +1,19 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class Boot < BaseAction
4
+ class Boot
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
10
  @env = env
7
11
 
8
12
  config = env[:machine].provider_config
9
13
 
10
- # Allows this middleware to be called multiple times. We need to
11
- # support this as base boxes might have after create scripts which
12
- # require SSH access
13
- unless env[:machine].state.running?
14
- env[:ui].info I18n.t("vagrant.actions.vm.boot.booting")
15
- env[:machine].provider.container.start(config)
16
- raise Vagrant::Errors::VMFailedToBoot if !wait_for_boot
17
- end
14
+ env[:ui].info I18n.t("vagrant.actions.vm.boot.booting")
15
+ env[:machine].provider.driver.start(config.customizations)
16
+ raise Vagrant::Errors::VMFailedToBoot if !wait_for_boot
18
17
 
19
18
  @app.call env
20
19
  end
@@ -1,9 +1,13 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class CheckCreated < BaseAction
4
+ class CheckCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
- unless env[:machine].state.created?
10
+ if env[:machine].state.id == :not_created
7
11
  raise Vagrant::Errors::VMNotCreatedError
8
12
  end
9
13
 
@@ -1,9 +1,13 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class CheckRunning < BaseAction
4
+ class CheckRunning
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
- unless env[:machine].state.running?
10
+ if env[:machine].state.id != :running
7
11
  raise Vagrant::Errors::VMNotRunningError
8
12
  end
9
13
 
@@ -12,7 +12,7 @@ module Vagrant
12
12
  raise Vagrant::Errors::VMPowerOffToPackage if env[:machine].provider.state.id != :stopped
13
13
 
14
14
  env[:ui].info I18n.t("vagrant.actions.lxc.compressing_rootfs")
15
- @rootfs = env['package.rootfs'] = env[:machine].provider.container.compress_rootfs
15
+ @rootfs = env['package.rootfs'] = env[:machine].provider.driver.compress_rootfs
16
16
 
17
17
  @app.call env
18
18
 
@@ -1,16 +1,24 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class Create < BaseAction
4
+ class Create
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
- base_name = env[:root_path].basename.to_s
7
- base_name.gsub!(/[^-a-z0-9_]/i, "")
10
+ container_name = env[:root_path].basename.to_s
11
+ container_name.gsub!(/[^-a-z0-9_]/i, "")
12
+ container_name << "-#{Time.now.to_i}"
13
+
14
+ env[:machine].provider.driver.create(
15
+ container_name,
16
+ env[:lxc_template_src],
17
+ env[:lxc_template_opts]
18
+ )
8
19
 
9
- target_rootfs_path = env[:machine].provider_config.target_rootfs_path
20
+ env[:machine].id = container_name
10
21
 
11
- machine_id = env[:machine].provider.container.create(base_name, target_rootfs_path, env[:machine].box.metadata)
12
- env[:machine].id = machine_id
13
- env[:just_created] = true
14
22
  @app.call env
15
23
  end
16
24
  end
@@ -1,10 +1,14 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class Created < BaseAction
4
+ class Created
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
10
  # Set the result to be true if the machine is created.
7
- env[:result] = env[:machine].state.created?
11
+ env[:result] = env[:machine].state.id != :not_created
8
12
 
9
13
  # Call the next if we have one (but we shouldn't, since this
10
14
  # middleware is built to run with the Call-type middlewares)
@@ -1,10 +1,14 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class Destroy < BaseAction
4
+ class Destroy
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
10
  env[:ui].info I18n.t("vagrant.actions.vm.destroy.destroying")
7
- env[:machine].provider.container.destroy
11
+ env[:machine].provider.driver.destroy
8
12
  env[:machine].id = nil
9
13
  @app.call env
10
14
  end
@@ -1,7 +1,11 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class Disconnect < BaseAction
4
+ class Disconnect
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
10
  @app.call env
7
11
  # FIXME: Vagrant >= 1.1.3 should not need this
@@ -7,11 +7,11 @@ module Vagrant
7
7
  end
8
8
 
9
9
  def call(env)
10
- if env[:machine].provider.state.running?
10
+ if env[:machine].provider.state.id == :running
11
11
  env[:ui].info I18n.t("vagrant.actions.vm.halt.force")
12
- # TODO: Container#halt is kinda graceful as well, if it doesn't
12
+ # TODO: Driver#halt is kinda graceful as well, if it doesn't
13
13
  # work we can issue a lxc-stop.
14
- env[:machine].provider.container.halt
14
+ env[:machine].provider.driver.halt
15
15
  end
16
16
 
17
17
  @app.call(env)
@@ -29,7 +29,7 @@ module Vagrant
29
29
  end
30
30
 
31
31
  def forward_ports
32
- @container_ip = @env[:machine].provider.container.assigned_ip
32
+ @container_ip = @env[:machine].provider.driver.assigned_ip
33
33
 
34
34
  @env[:forwarded_ports].each do |fp|
35
35
  message_attributes = {
@@ -63,7 +63,7 @@ module Vagrant
63
63
  end
64
64
 
65
65
  def redirect_port(host, guest)
66
- redir_cmd = "sudo redir --laddr=127.0.0.1 --lport=#{host} --cport=#{guest} --caddr=#{@container_ip}"
66
+ redir_cmd = "sudo redir --laddr=127.0.0.1 --lport=#{host} --cport=#{guest} --caddr=#{@container_ip} 2>/dev/null"
67
67
 
68
68
  @logger.debug "Forwarding port with `#{redir_cmd}`"
69
69
  fork { exec redir_cmd }
@@ -2,45 +2,56 @@ module Vagrant
2
2
  module LXC
3
3
  module Action
4
4
  # Prepare arguments to be used for lxc-create
5
- class HandleBoxMetadata < BaseAction
6
- LXC_TEMPLATES_PATH = Pathname.new("/usr/share/lxc/templates")
7
- TEMP_PREFIX = "vagrant-lxc-rootfs-temp-"
8
-
5
+ class HandleBoxMetadata
9
6
  def initialize(app, env)
10
- super
7
+ @app = app
11
8
  @logger = Log4r::Logger.new("vagrant::lxc::action::handle_box_metadata")
12
9
  end
13
10
 
14
11
  def call(env)
15
- env[:ui].info I18n.t("vagrant.actions.vm.import.importing",
16
- :name => env[:machine].box.name)
12
+ @env = env
13
+ @box = @env[:machine].box
17
14
 
18
- rootfs_cache = Dir.mktmpdir(TEMP_PREFIX)
19
- box = env[:machine].box
20
- template_name = "vagrant-#{box.name}"
15
+ @env[:ui].info I18n.t("vagrant.actions.vm.import.importing",
16
+ :name => @env[:machine].box.name)
21
17
 
22
- # Prepends "lxc-" to the template file so that `lxc-create` is able to find it
23
- lxc_template_src = box.directory.join('lxc-template').to_s
24
- unless File.exists?(lxc_template_src)
25
- raise Errors::TemplateFileMissing.new name: box.name
26
- end
27
- dest = LXC_TEMPLATES_PATH.join("lxc-#{template_name}").to_s
28
- @logger.debug('Copying LXC template into place')
29
- system(%Q[sudo su root -c "cp #{lxc_template_src} #{dest}"])
18
+ @logger.debug 'Validating box contents'
19
+ validate_box
30
20
 
31
- @logger.debug('Extracting rootfs')
32
- # TODO: Ideally the compressed rootfs should not output errors...
33
- system(%Q[sudo su root -c "cd #{box.directory} && tar xfz rootfs.tar.gz -C #{rootfs_cache} 2>/dev/null"])
21
+ @logger.debug 'Setting box options on environment'
22
+ @env[:lxc_template_opts] = template_opts
23
+ @env[:lxc_template_src] = template_src
24
+
25
+ @app.call env
26
+ end
34
27
 
35
- box.metadata.merge!(
36
- 'template-name' => template_name,
37
- 'rootfs-cache-path' => rootfs_cache
28
+ def template_src
29
+ @template_src ||= @box.directory.join('lxc-template').to_s
30
+ end
31
+
32
+ def template_opts
33
+ @template_opts ||= @box.metadata.fetch('template-opts', {}).dup.merge!(
34
+ '--tarball' => rootfs_tarball,
35
+ '--auth-key' => Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s
38
36
  )
37
+ end
39
38
 
40
- @app.call(env)
39
+ def rootfs_tarball
40
+ @rootfs_tarball ||= @box.directory.join('rootfs.tar.gz').to_s
41
+ end
42
+
43
+ def validate_box
44
+ if @box.metadata.fetch('version').to_i != 2
45
+ raise Errors::InvalidBoxVersion.new name: @box.name
46
+ end
41
47
 
42
- ensure
43
- system %Q[sudo su root -c "rm -rf #{rootfs_cache}"]
48
+ unless File.exists?(template_src)
49
+ raise Errors::TemplateFileMissing.new name: @box.name
50
+ end
51
+
52
+ unless File.exists?(rootfs_tarball)
53
+ raise Errors::RootFSTarballMissing.new name: @box.name
54
+ end
44
55
  end
45
56
  end
46
57
  end
@@ -1,9 +1,13 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class IsRunning < BaseAction
4
+ class IsRunning
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
- env[:result] = env[:machine].state.running?
10
+ env[:result] = env[:machine].state.id == :running
7
11
 
8
12
  # Call the next if we have one (but we shouldn't, since this
9
13
  # middleware is built to run with the Call-type middlewares)
@@ -1,11 +1,15 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  module Action
4
- class ShareFolders < BaseAction
4
+ class ShareFolders
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
5
9
  def call(env)
6
10
  @env = env
7
11
  prepare_folders
8
- add_start_opts
12
+ add_override_configs
9
13
  @app.call env
10
14
  end
11
15
 
@@ -14,9 +18,6 @@ module Vagrant
14
18
  def shared_folders
15
19
  {}.tap do |result|
16
20
  @env[:machine].config.vm.synced_folders.each do |id, data|
17
- # Ignore NFS shared folders
18
- next if data[:nfs]
19
-
20
21
  # This to prevent overwriting the actual shared folders data
21
22
  result[id] = data.dup
22
23
  end
@@ -43,7 +44,7 @@ module Vagrant
43
44
  end
44
45
  end
45
46
 
46
- def add_start_opts
47
+ def add_override_configs
47
48
  @env[:ui].info I18n.t("vagrant.actions.lxc.share_folders.preparing")
48
49
 
49
50
  folders = []
@@ -56,8 +57,7 @@ module Vagrant
56
57
  @env[:ui].info(I18n.t("vagrant.actions.vm.share_folders.mounting_entry",
57
58
  :guest_path => data[:guestpath]))
58
59
  end
59
- config = @env[:machine].provider_config
60
- @env[:machine].provider.container.share_folders(folders, config)
60
+ @env[:machine].provider.driver.share_folders(folders)
61
61
  end
62
62
  end
63
63
  end
@@ -1,21 +1,31 @@
1
1
  module Vagrant
2
2
  module LXC
3
3
  class Config < Vagrant.plugin("2", :config)
4
- # An array of options to be passed to lxc-start when booting the machine.
4
+ # An array of container's configuration overrides to be provided to `lxc-start`.
5
5
  #
6
6
  # @return [Array]
7
- attr_reader :start_opts
8
-
9
- # Base directory to store container's rootfs
10
- #
11
- # Defaults to nil, which means it will be stored wherever the lxc template
12
- # tells it to be stored
13
- attr_accessor :target_rootfs_path
7
+ attr_reader :customizations
14
8
 
15
9
  def initialize
16
- @start_opts = []
17
- @target_rootfs_path = nil
10
+ @customizations = []
11
+ end
12
+
13
+ # Customize the container by calling `lxc-start` with the given
14
+ # configuration overrides.
15
+ #
16
+ # For example, if you want to set the memory limit, you can use it
17
+ # like: config.customize 'cgroup.memory.limit_in_bytes', '400M'
18
+ #
19
+ # When `lxc-start`ing the container, vagrant-lxc will pass in
20
+ # "-s lxc.cgroup.memory.limit_in_bytes=400M" to it.
21
+ #
22
+ # @param [String] key Configuration key to override
23
+ # @param [String] value Configuration value to override
24
+ def customize(key, value)
25
+ @customizations << [key, value]
18
26
  end
27
+
28
+ # TODO: At some point in the future it would be nice to validate these options
19
29
  end
20
30
  end
21
31
  end