Add support for unprivileged containers
fixes #312 I've also remove the "EXPERIMENTAL" flag to bridge support in the README. It's been there long enough.
This commit is contained in:
parent
9e215ae1a1
commit
530a899467
6 changed files with 57 additions and 28 deletions
24
README.md
24
README.md
|
@ -78,7 +78,7 @@ 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).
|
For other configuration options, please check the [lxc.conf manpages](http://manpages.ubuntu.com/manpages/precise/man5/lxc.conf.5.html).
|
||||||
|
|
||||||
### Private Networks [EXPERIMENTAL]
|
### Private Networks
|
||||||
|
|
||||||
Starting with vagrant-lxc 1.1.0, there is some rudimentary support for configuring
|
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)
|
[Private Networks](https://docs.vagrantup.com/v2/networking/private_network.html)
|
||||||
|
@ -137,25 +137,29 @@ Vagrant.configure("2") do |config|
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
For old versions of lxc (like 0.7.5 shipped with Ubuntu 12.04 by default) that
|
## Unprivileged containers support
|
||||||
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
|
Since v1.4.0, `vagrant-lxc` gained support for unprivileged containers. For now, since it's a new
|
||||||
`~/.vagrant.d/Vagrantfile` using the same `provider` block:
|
feature, privileged containers are still the default, but you can have your `Vagrantfile` use
|
||||||
|
unprivileged containers with the `privileged` flag (which defaults to `true`). Example:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
config.vm.provider :lxc do |lxc|
|
config.vm.provider :lxc do |lxc|
|
||||||
lxc.backingstore = 'none'
|
lxc.privileged = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For unprivileged containers to work with `vagrant-lxc`, you need a properly configured system. On
|
||||||
|
some distros, it can be somewhat of a challenge. Your journey to configuring your system can start
|
||||||
|
with [Stéphane Graber's blog post about it](https://stgraber.org/2014/01/17/lxc-1-0-unprivileged-containers/).
|
||||||
|
|
||||||
## Avoiding `sudo` passwords
|
## Avoiding `sudo` passwords
|
||||||
|
|
||||||
This plugin requires **a lot** of `sudo`ing since [unprivileged containers](https://github.com/fgrehm/vagrant-lxc/issues/312)
|
If you're not using unprivileged containers, this plugin requires **a lot** of `sudo`ing To work
|
||||||
are not supported yet. To work around that, you can use the `vagrant lxc sudoers`
|
around that, you can use the `vagrant lxc sudoers` command which will create a file under
|
||||||
command which will create a file under `/etc/sudoers.d/vagrant-lxc` whitelisting
|
`/etc/sudoers.d/vagrant-lxc` whitelisting all commands required by `vagrant-lxc` to run.
|
||||||
all commands required by `vagrant-lxc` to run.
|
|
||||||
|
|
||||||
If you are interested on what will be generated by that command, please check
|
If you are interested on what will be generated by that command, please check
|
||||||
[this code](lib/vagrant-lxc/command/sudoers.rb).
|
[this code](lib/vagrant-lxc/command/sudoers.rb).
|
||||||
|
|
|
@ -19,10 +19,14 @@ module Vagrant
|
||||||
container_name = generate_container_name(env)
|
container_name = generate_container_name(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
backingstore = config.backingstore
|
||||||
|
if backingstore.nil?
|
||||||
|
backingstore = config.privileged ? "best" : "dir"
|
||||||
|
end
|
||||||
driver = env[:machine].provider.driver
|
driver = env[:machine].provider.driver
|
||||||
driver.create(
|
driver.create(
|
||||||
container_name,
|
container_name,
|
||||||
config.backingstore,
|
backingstore,
|
||||||
config.backingstore_options,
|
config.backingstore_options,
|
||||||
env[:lxc_template_src],
|
env[:lxc_template_src],
|
||||||
env[:lxc_template_config],
|
env[:lxc_template_config],
|
||||||
|
|
|
@ -24,6 +24,12 @@ module Vagrant
|
||||||
|
|
||||||
attr_accessor :fetch_ip_tries
|
attr_accessor :fetch_ip_tries
|
||||||
|
|
||||||
|
# Whether the container needs to be privileged. Defaults to true (unprivileged containers
|
||||||
|
# is a very new feature in vagrant-lxc). If false, will try creating an unprivileged
|
||||||
|
# container. If it can't, will revert to the old "sudo wrapper" method to create a privileged
|
||||||
|
# container.
|
||||||
|
attr_accessor :privileged
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@customizations = []
|
@customizations = []
|
||||||
@backingstore = UNSET_VALUE
|
@backingstore = UNSET_VALUE
|
||||||
|
@ -31,6 +37,7 @@ module Vagrant
|
||||||
@container_name = UNSET_VALUE
|
@container_name = UNSET_VALUE
|
||||||
@tmpfs_mount_size = UNSET_VALUE
|
@tmpfs_mount_size = UNSET_VALUE
|
||||||
@fetch_ip_tries = UNSET_VALUE
|
@fetch_ip_tries = UNSET_VALUE
|
||||||
|
@privileged = UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
# Customize the container by calling `lxc-start` with the given
|
# Customize the container by calling `lxc-start` with the given
|
||||||
|
@ -55,10 +62,11 @@ module Vagrant
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
@container_name = nil if @container_name == UNSET_VALUE
|
@container_name = nil if @container_name == UNSET_VALUE
|
||||||
@backingstore = "best" if @backingstore == UNSET_VALUE
|
@backingstore = nil if @backingstore == UNSET_VALUE
|
||||||
@existing_container_name = nil if @existing_container_name == UNSET_VALUE
|
@existing_container_name = nil if @existing_container_name == UNSET_VALUE
|
||||||
@tmpfs_mount_size = '2G' if @tmpfs_mount_size == UNSET_VALUE
|
@tmpfs_mount_size = '2G' if @tmpfs_mount_size == UNSET_VALUE
|
||||||
@fetch_ip_tries = 10 if @fetch_ip_tries == UNSET_VALUE
|
@fetch_ip_tries = 10 if @fetch_ip_tries == UNSET_VALUE
|
||||||
|
@privileged = true if @privileged == UNSET_VALUE
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,9 +20,9 @@ module Vagrant
|
||||||
attr_reader :container_name,
|
attr_reader :container_name,
|
||||||
:customizations
|
:customizations
|
||||||
|
|
||||||
def initialize(container_name, sudo_wrapper = nil, cli = nil)
|
def initialize(container_name, sudo_wrapper = nil, cli = nil, privileged: true)
|
||||||
@container_name = container_name
|
@container_name = container_name
|
||||||
@sudo_wrapper = sudo_wrapper || SudoWrapper.new()
|
@sudo_wrapper = sudo_wrapper || SudoWrapper.new(privileged: privileged)
|
||||||
@cli = cli || CLI.new(@sudo_wrapper, container_name)
|
@cli = cli || CLI.new(@sudo_wrapper, container_name)
|
||||||
@logger = Log4r::Logger.new("vagrant::provider::lxc::driver")
|
@logger = Log4r::Logger.new("vagrant::provider::lxc::driver")
|
||||||
@customizations = []
|
@customizations = []
|
||||||
|
@ -266,12 +266,21 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_config(contents)
|
def write_config(contents)
|
||||||
Tempfile.new('lxc-config').tap do |file|
|
confpath = base_path.join('config').to_s
|
||||||
file.chmod 0644
|
begin
|
||||||
file.write contents
|
File.open(confpath, File::RDWR) do |file|
|
||||||
file.close
|
file.write contents
|
||||||
@sudo_wrapper.run 'cp', '-f', file.path, config_path
|
end
|
||||||
@sudo_wrapper.run 'chown', 'root:root', config_path
|
rescue
|
||||||
|
# We don't have permissions to write in the conf file. That's probably because it's a
|
||||||
|
# privileged container. Work around that through sudo_wrapper.
|
||||||
|
Tempfile.new('lxc-config').tap do |file|
|
||||||
|
file.chmod 0644
|
||||||
|
file.write contents
|
||||||
|
file.close
|
||||||
|
@sudo_wrapper.run 'cp', '-f', file.path, confpath
|
||||||
|
@sudo_wrapper.run 'chown', 'root:root', confpath
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,6 @@ require "log4r"
|
||||||
|
|
||||||
require "vagrant-lxc/action"
|
require "vagrant-lxc/action"
|
||||||
require "vagrant-lxc/driver"
|
require "vagrant-lxc/driver"
|
||||||
require "vagrant-lxc/sudo_wrapper"
|
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
|
@ -27,7 +26,7 @@ module Vagrant
|
||||||
|
|
||||||
def ensure_lxc_installed!
|
def ensure_lxc_installed!
|
||||||
begin
|
begin
|
||||||
SudoWrapper.new().run("which", "lxc-create")
|
SudoWrapper.new(privileged: @machine.provider_config.privileged).run("which", "lxc-create")
|
||||||
rescue Vagrant::LXC::Errors::ExecuteError
|
rescue Vagrant::LXC::Errors::ExecuteError
|
||||||
raise Errors::LxcNotInstalled
|
raise Errors::LxcNotInstalled
|
||||||
end
|
end
|
||||||
|
@ -40,7 +39,7 @@ module Vagrant
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@logger.debug("Instantiating the container for: #{id.inspect}")
|
@logger.debug("Instantiating the container for: #{id.inspect}")
|
||||||
@driver = Driver.new(id)
|
@driver = Driver.new(id, privileged: @machine.provider_config.privileged)
|
||||||
@driver.validate!
|
@driver.validate!
|
||||||
rescue Driver::ContainerNotFound
|
rescue Driver::ContainerNotFound
|
||||||
# The container doesn't exist, so we probably have a stale
|
# The container doesn't exist, so we probably have a stale
|
||||||
|
|
|
@ -10,8 +10,9 @@ module Vagrant
|
||||||
"/usr/local/bin/vagrant-lxc-wrapper"
|
"/usr/local/bin/vagrant-lxc-wrapper"
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize()
|
def initialize(privileged: true)
|
||||||
@wrapper_path = Pathname.new(SudoWrapper.dest_path).exist? && SudoWrapper.dest_path || nil
|
@wrapper_path = Pathname.new(SudoWrapper.dest_path).exist? && SudoWrapper.dest_path || nil
|
||||||
|
@privileged = privileged
|
||||||
@logger = Log4r::Logger.new("vagrant::lxc::sudo_wrapper")
|
@logger = Log4r::Logger.new("vagrant::lxc::sudo_wrapper")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -27,11 +28,15 @@ module Vagrant
|
||||||
File.umask(old_mask & 022) # allow all `r` and `x` bits
|
File.umask(old_mask & 022) # allow all `r` and `x` bits
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if @wrapper_path && !options[:no_wrapper]
|
if @privileged
|
||||||
command.unshift @wrapper_path
|
if @wrapper_path && !options[:no_wrapper]
|
||||||
execute *(['sudo'] + command)
|
command.unshift @wrapper_path
|
||||||
|
execute *(['sudo'] + command)
|
||||||
|
else
|
||||||
|
execute *(['sudo', '/usr/bin/env'] + command)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
execute *(['sudo', '/usr/bin/env'] + command)
|
execute *(['/usr/bin/env'] + command)
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
File.umask(old_mask)
|
File.umask(old_mask)
|
||||||
|
|
Loading…
Reference in a new issue