Compare commits

...

254 commits

Author SHA1 Message Date
a47660a1e5 Update 'README.md' 2023-02-03 19:28:15 +00:00
3575d65ffb Update 'README.md' 2023-02-03 19:08:48 +00:00
Glenn Y. Rolland
938a29ed96
Merge branch 'fgrehm:master' into master 2023-02-03 19:56:32 +01:00
Fabio
ff58ecd5f2
Update README.md 2022-11-24 20:41:12 -03:00
Fabio
df6b78c4ed
Update README.md 2022-11-24 20:40:54 -03:00
Fabio
4d53acb9fb
Update README.md 2022-11-24 20:40:34 -03:00
Fabio
b88d50fb68
Update README.md 2022-11-16 22:39:19 -03:00
4e3306ed74 Fix the 'eval: Address:: not found' error that may appear 2022-09-28 15:01:04 +02:00
Fabio Rehm
c167ac7f83
Make it clear that project is looking for maintainers
Ref https://github.com/fgrehm/vagrant-lxc/issues/492
2021-01-12 11:15:50 -03:00
Virgil Dupras
a112b072aa
Merge pull request #473 from ebobby/fix-redir3
Fix redir version fetching.
2018-09-26 19:53:14 -04:00
Francisco Soto
f750bf406c Fix redir version fetching.
"" || "something" doesn't really work. Have to check for the actual string
length to determine if got something or not out of the pipe.
2018-09-24 18:43:03 -07:00
Virgil Dupras
2a5510b34c Fix "vargant package" for LXC 2.1+ config format
New config format would be under `lxc.rootfs.path` and be prefixed by
`dir:`.
2018-07-24 12:23:25 -04:00
Virgil Dupras
a1aa60ded5 Remove supports_attach? and call to /sbin/halt
Hosts without support for lxc-attach are ancien and can always use old
versions of vagrant-lxc. To be able to move forward more easily, we
should be able to assume a functional `lxc-attach`.

As for `/sbin/halt`, I'm really not sure it's needed anymore. Let's see
if its removal causes problems.
2018-07-24 11:21:09 -04:00
Virgil Dupras
61c921ac6f Use require_relative everywhere in plugin entry point 2018-07-24 10:25:08 -04:00
Virgil Dupras
437b5e7a2e README: base boxes status update 2018-07-24 10:08:07 -04:00
Virgil Dupras
2c2630a788 Bump minimum requirements for next vagrant-lxc release (v1.5)
We now depend on vagrant 1.9+ and LXC 2.0+, following bundled version in
debian stretch.

Also, update Gemfile to target latest vagrant/vagrant-spec. It's too
complicated to test against old vagrant versions. Vagrant 1.8.x didn't
specify an upper bound for supported versions but vagrant 1.9 does
(<2.4). This breaks out CI testing matrix which tests against 2.3, 2.4
and 2.5.

So let's make our live easier and just test against the latest vagrant
version and try not to mistakenly drop support for our lowest supported
vagrant version...
2018-07-24 09:37:34 -04:00
Virgil Dupras
5a1f6ab2cb
Merge pull request #469 from worxli/feature-add-ssh-ip
Add config for container SSH IP
2018-07-23 06:27:50 -04:00
Lukas Bischofberger
f71de429a1 Add config for container ssh IP 2018-07-21 14:52:26 +02:00
Virgil Dupras
50cbe5a0d6 v1.4.2 2018-07-17 14:37:18 -04:00
Virgil Dupras
44eefd81fb Merge tag 'v1.4.1' 2018-07-17 14:34:58 -04:00
Virgil Dupras
a84f8b59bf redir: adjust failing tests 2018-07-04 15:00:46 -04:00
Virgil Dupras
c1dd7baf2a redir: start in foreground mode under v3.x
ref #467
2018-07-04 14:34:26 -04:00
Virgil Dupras
8a1e1863a7 redir: fix version parsing
At some point in v 3.x, it outputted version in stderr, then went back
to stdout...
2018-07-04 14:33:51 -04:00
Virgil Dupras
b812a6934a v1.4.1 2018-04-30 21:32:33 -04:00
Virgil Dupras
8cfe577b17 Fix LXC 3.0 compatibility with old boxes
Creating a new vagrant machine with a box created with an old LXC config
format would fail with LXC 3.0. We now update the LXC config of the box
itself before calling `lxc-create`.
2018-04-30 20:45:25 -04:00
Virgil Dupras
dd24cdc3d6 Fix incompatibility with LXC 3.0
LXC 3.0, unlike 2.1, doesn't support old configuration formats at all
and because our previous approach to handling old format was incomplete,
running `vagrant up` on a system with LXC 3.0 would fail, even if the
base box itself was made with modernized config.

This commit fixes this problem: is the box has a modern config, it's
going to be properly created and booted under LXC 3.0. It does so
without breaking the support for LXC < 2.1
2018-04-29 22:57:31 -04:00
Virgil Dupras
208edd49e5
Merge pull request #461 from nicolasleger/patch-1
[CI] Test against Ruby 2.5
2018-03-18 16:41:55 -04:00
Virgil Dupras
484b868100
Merge pull request #460 from lucaskanashiro/support_redir-3.x
Support the new redir 3.x command line interface
2018-03-18 16:41:18 -04:00
Nicolas Leger
b5f2a9006c
[CI] Test against Ruby 2.5 2018-03-15 14:52:34 +01:00
Lucas Kanashiro
2e20f96fec Support the new redir 3.x command line interface
Since redir 2.x upstream is not evolving it, Joachim Nilsson adopted it
and have started to work on it and publish a new command line interface
(check out https://github.com/troglobit/redir). The redir 3.1 is already
available in Debian and Ubuntu in their stable releases.
2018-03-12 13:09:06 -03:00
Virgil Dupras
d3409ace2a v1.4.0 2018-03-04 09:22:58 -05:00
Virgil Dupras
530a899467 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.
2018-02-17 21:53:16 -05:00
Virgil Dupras
9e215ae1a1 v1.3.1 2018-02-06 22:02:29 -05:00
Cam Cope
8fa42b1ab4
Merge pull request #456 from fgrehm/tmpfs-revival
Revert tmpfs mount removal
2018-02-04 00:04:39 -08:00
Virgil Dupras
2ae84fcc51 Revert tmpfs mount removal
To fix #406, I reverted the tmpfs mount we add at boot time. As we can
see in #455, it was a bad idea.

In addition to bringing back that mount, I've also added a
`tmpfs_mount_size` config that allows to change the size of the mount
from its default `2G`. It's also possible to disable the mount
altogether.

fixes #455
2018-02-02 16:02:17 -05:00
Virgil Dupras
582e3b368a halt: check that machine is running before attempting to clear tmpfiles
Otherwise, running `vagrant halt` on a stopped machine would make us
crash. Particularly annoying in multi-machines environments.

ref #406
2018-01-27 14:32:42 -05:00
Virgil Dupras
6738febaa2 v1.3.0 2018-01-20 13:29:46 -05:00
Virgil Dupras
49ebf3488e sudoers: fix typo
fixes #451
2018-01-15 21:17:36 -05:00
Virgil Dupras
bd42317ec2 Update README
Fixes #431
2018-01-15 08:25:27 -05:00
Virgil Dupras
1c27047f4b Remove tmpfs mount on /tmp and bring back /tmp cleanup on halt
fixes #406 because the `tmpfs` mount isn't needed anymore.

Careful considerations had to be taken because #68 mentions host-side
data loss when cleaning up `/tmp`. We mitigate this by ensuring that all
mounts under `/tmp` are unmounted before we proceed with our `rm -rf`
operation.

More context about this issue can be found in #360.
2018-01-13 23:00:46 -05:00
Virgil Dupras
fef11bf7ef Update README 2018-01-13 21:06:45 -05:00
Virgil Dupras
c74ddbf2fc create: with LXC 2.1+ run lxc-update-config on new boxes
When running with LXC 2.1+, ensure that our boxes have up-to-date config
keys by running the `lxc-update-config` utility that ships with LXC
2.1+.

When the command doesn't exist (LXC <2.1), we do nothing.

ref #445
2018-01-13 21:03:34 -05:00
Virgil Dupras
2b08ae199f driver: little cleanup after LXC 1.0+ requirement bump
The conditional `lxc-version` and `lxc-config` mechanisms aren't needed
anymore. They were for pre-1.0 LXC versions.
2018-01-13 20:34:41 -05:00
Virgil Dupras
aa777653f4 Use lxc-info instead of lxc-attach to retrieve container IP
`lxc-info -iH` to retrieve IP address was not available in early LXC
development but was there at LXC 1.0. Because we've bumped our minimum
LXC requirement to v1.0 recently, we can simplify the IP retrieval
process and also get rid of the `dnsmasq` fallback.
2018-01-13 15:53:28 -05:00
Virgil Dupras
7e1eb1d373 Change version to 1.3.0-dev 2018-01-13 15:30:39 -05:00
Virgil Dupras
4ff412e2d2 Fix travis for real this time
Sorry for the commit noise, I didn't think I'd need this much fiddling
and I don't have push-force privileges on the repo.
2018-01-13 09:06:45 -05:00
Virgil Dupras
bd4aa8167c Fix travis (again) 2018-01-13 08:56:17 -05:00
Virgil Dupras
2423464cdb Fix travis (again) 2018-01-13 08:54:06 -05:00
Virgil Dupras
0b5087f72e Fix travis builds 2018-01-13 08:43:00 -05:00
Virgil Dupras
c8801ba8b2
Merge pull request #447 from hsoft/unprivileged-template
lxc-template: make runnable by unprivileged users
2018-01-13 08:35:43 -05:00
Virgil Dupras
97b5882262 Refactoring: make SudoWrapper a bit more self-contained
By looking at the code, it seems that it was a goal to make the sudo
wrapper path configurable through the Vagrantfile, but it wasn't
effective and didn't make much sense (that kind of config is a per-host
config, not a per-guest one).

This caused the cause to be needlessly complex by giving the Provider
the responsibility of instanciating the wrapper. This commit gets rid of
that.

I didn't get rid of `sudo_wrapper` injection in `Driver` and
`Driver::CLI` constructors because they're needed for tests. I'm not
ready to tackle this yet.
2018-01-13 08:32:27 -05:00
Virgil Dupras
6eb7ec1a2e Bump Vagrant and LXC requirements 2018-01-13 08:32:27 -05:00
Virgil Dupras
fe7d638b35 Remove Gemfile.lock and properly lock stuff in Gemfile
No other vagrant plugin use `Gemfile.lock`. It doesn't feel right.

When removing it, however, we end up with many dependencies conflicts.
It then becomes necessary to freeze dependencies in `Gemfile`.
2018-01-13 08:32:27 -05:00
Virgil Dupras
f8a78e520b Adjust changelog for v1.2.4 2017-12-20 15:45:31 -05:00
Virgil Dupras
dbf2dfb8ff
Merge pull request #448 from hsoft/master
v1.2.4
2017-12-20 10:33:49 -05:00
Virgil Dupras
d3788f55f3
Merge pull request #449 from nicobrevin/nicobrevin-master
Fix for #336
2017-12-16 19:15:16 -05:00
Nick Griffiths
f224fc5ea5 Fix for #336:
Subprocessed being interrupted resulted in it looking
like those commands were executing successfully but with
zero output.  Interrupting the sudo prompt would result
in any command running in sudo returning nothing and looking
like it had succeeded.  There was some clean up code in
the lxc provider that nuked vagrant container state in
the .vagrant directory if it looked like the container no
longer existed based on the result of lxc-ls.  Interrupting
this check resulted in it looking like the container not
existing, resulting in the provider code nuking the lxc dir
in .vagrant.  Voila
2017-12-16 12:07:11 +13:00
Virgil Dupras
1c64ea1b2c v1.2.4 2017-12-12 11:02:57 -05:00
Fabio Rehm
b96ba86f72
Update CHANGELOG.md 2017-12-12 13:55:25 -02:00
Virgil Dupras
8b93206c18
Merge pull request #435 from brandon-rhodes/fix-umask
Avoid `Timed out` error when umask is 027 or 077
2017-12-11 19:35:22 -05:00
Virgil Dupras
e4c566ebc9
Merge pull request #421 from TobleMiner/lxc-template-option-fix
Fixes #420 (blaze it)
2017-12-11 17:21:00 -05:00
Virgil Dupras
d35ee4aed0
Merge pull request #410 from ChaosCloud/abk
vagrant-lxc-wrapper need to allow sudoer first-found binary path
2017-12-11 17:07:21 -05:00
Virgil Dupras
03c23d7df8 README: mention incompatibility with LXC v2.1
see #445
2017-12-11 14:51:09 -05:00
Virgil Dupras
10c53c54d7 Support alternative lxcpath in sudo wrapper
The previously hardcoded lxc path prevented the sudo wrapper from
working in environment with alternative `lxcpath`.

I had to move `sudo_wrapper` from `provider` to `LXC` because the
concept of "provider" is tied to a machine when a command sush as
`sudoers` is not.

Fixes #413 and #399
2017-12-11 11:48:19 -05:00
Virgil Dupras
2ce460bc30
Merge pull request #438 from fkleon/fix-sudoers-vagrant-1.9.x
Update pipework regexp for sudo wrapper
2017-12-11 10:20:36 -05:00
Virgil Dupras
553f1b5ed0 lxc-template: make runnable by unprivileged users
lxc-template needlessly require root privileges in two places:

1. lock file location for `flock`
2. failing on `tar` failure during rootfs extraction

For `flock`, it's not necessary that the lock file be in `/var/lock`, it
can be anywhere. Why not put it in `LXC_PATH`?

For the failing `tar` thing, that's because some device are created with
`mknod` which unprivileged users can't do. These device, however, are
not necessary for the container to run well. We can ignore `tar`'s error
exit code.

I replaced the exist code check by a check for the existence of
`/bin/true` in rootfs. I think that it's a good indication of whether
the rootfs was extracted.

Why am I making this change? Because I'd like to add support for
unprivileged containers in `vagrant-lxc` but it's kind of a big change
to make at once, so I thought I'd go incrementally.
2017-12-09 19:36:54 -05:00
Frederik Leonhardt
1f805f6deb Update pipework regexp for sudo wrapper
On Vagrant 1.9+ plugin gems are installed into a different folder, their path
containing the ruby version. This updates the regular expression whitelisting
the pipework script to reflect this change.
2017-02-09 15:55:32 +13:00
Brandon Rhodes
43aa9bfb3e Avoid Timed out error when umask is 027 or 077
If LXC commands are run with a restrictive umask like 027 or 077, then
the root directory of new containers will lack read `r` and access `x`
permission for non-root users.  The first failure to result from this
during `vagrant up` is that the SSH daemon cannot read the crucial file
`/home/vagrant/.ssh/authorized_keys` after it drops privileges to the
level of the `vagrant` user.  The result is the familiar:

```
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.
```

So we should make sure that we run all LXC commands with a umask that at
least does not prevent group and world `r` and `x` bits from being set
in newly created files and directories.
2017-01-29 13:53:09 -05:00
Cam Cope
851f58d42a v1.2.3 2016-12-20 20:20:38 -08:00
Cam Cope
fdb7222965 Fix bad version in Gemfile.lock 2016-12-20 20:20:07 -08:00
Cam Cope
4fd0635204 v.1.2.2 2016-12-20 20:08:47 -08:00
Cam Cope
ae18c05b2b Merge pull request #426 from fonsecas72/patch-1
Make fetch_ip_tries configurable
2016-11-11 12:33:18 -05:00
Hugo Fonseca
6d8580a294 default values goes to finalize 2016-11-11 08:34:42 +00:00
Hugo Fonseca
cac4910296 tries amount of fetching ip is now configurable 2016-11-09 14:38:05 +00:00
Hugo Fonseca
2d63603d85 Increase the re-tries amount 2016-11-07 15:34:48 +00:00
Cam Cope
a68a1de21f Merge pull request #423 from sergle/master
Load locale file only once
2016-10-21 00:54:57 -07:00
Sergey Leschenko
671bd55cea Make code similar to other providers 2016-10-20 13:39:33 +03:00
Sergey Leschenko
1c2208a30e Load locale file only once 2016-10-18 14:40:37 +03:00
Tobias Schramm
0cdd4d352c Fixes #420 (blaze it) 2016-08-22 22:27:00 +02:00
Cam Cope
62535b6465 Merge pull request #411 from ccope/preserve-xattrs
Preserve xattrs in container rootfs
2016-06-02 00:16:40 -07:00
Cam Cope
932a7808be Merge pull request #408 from swettk/master
Forward port latest pipework script
2016-05-30 16:35:59 -07:00
Cam Cope
9dd12bfcdf update dependencies in the README 2016-05-11 16:54:12 -07:00
Cam Cope
6dcf584b25 preserve xattrs 2016-05-11 16:54:12 -07:00
Robert Heinzmann
544c061e65 Fix handling of non-fatal lxc-stop return code
Fixes #405
2016-05-11 16:50:29 -07:00
AbhishekKr
848383e081 vagrant-lxc-wrapper need to allow sudoer first-found binary path
sudoer PATH may have different order than current user
2016-05-11 23:51:29 +05:30
Keith Swett
d4e5122c6c Forward port latest pipework script 2016-04-26 19:52:57 +00:00
Robin Gloster
aa5fb7a932 1.2.1 2015-09-24 14:14:26 +00:00
Franz Pletz
81d70d26d3 Merge pull request #393 from mayflower/fix-sudo-wrapper
fix sudo wrapper
2015-09-24 15:27:40 +02:00
Robin Gloster
4c969a6ae7 fix sudo wrapper 2015-09-23 18:15:28 +00:00
Franz Pletz
1fb64dbbdf Merge pull request #392 from danielhodder/improve-lxc-missing-message
Added lxc-create to the error message
2015-09-21 01:16:21 +02:00
danielh
d11b6f2dc7 Added lxc-create to the error message
Added the command that vagrant-lxc is actually trying to run when it can't find the lxc-create command
2015-09-20 15:30:09 +12:00
Fabio Rehm
ad39aa9645 Update README.md 2015-09-17 12:43:57 -03:00
Fabio Rehm
050c160de2 v1.2.0 2015-09-15 09:57:48 -03:00
Robin Gloster
3d924985dd Prepare 1.2.0 2015-09-14 09:33:25 +00:00
Robin Gloster
95bfdfd54d explicitly add overlayfs as backingstore to readme
fixes #351
2015-09-08 21:00:26 +00:00
Robin Gloster
25d10cd3bc fix shebang in pipework 2015-09-08 20:54:29 +00:00
Franz Pletz
86381bfeee Merge branch 'stucki-create-bridge-if-missing' (PR #380) 2015-08-28 15:01:30 +02:00
Michael Stucki
7c778dfb4d Fix warning message 2015-08-28 15:00:37 +02:00
Michael Stucki
9e5637a9fe Do not remove system bridge virbr0 2015-08-28 15:00:37 +02:00
Michael Stucki
3257bd25bb Fix variable name 2015-08-28 15:00:37 +02:00
Andriy
06bbc7a5ef Update gc_private_network_bridges.rb 2015-08-28 15:00:37 +02:00
Andriy
6136ebb966 Update driver.rb
Fixing https://github.com/fgrehm/vagrant-lxc/issues/353 issue
2015-08-28 15:00:37 +02:00
Cam Cope
9b70f3daab make /tmp a tmpfs 2015-08-28 14:58:16 +02:00
Cam Cope
2accd886fa remove /tmp cleanup, fixes lvm rootfs 2015-08-28 14:58:16 +02:00
Robin Gloster
993e430ccc Use /usr/bin/env CMD instead of hardcoded paths
This fixes commands that currently rely on hardcoded paths and break
on systems like NixOS that don't have all binaries in /usr/bin etc.
2015-08-28 14:58:16 +02:00
Robin Gloster
ea99d13f76 Fix test on NixOS
Tempfile can be created in /run, too.
2015-08-28 14:58:16 +02:00
Robin Gloster
fddd8cc257 Update gems to resolve dependencies on NixOS 2015-08-28 14:58:16 +02:00
Robin Gloster
611a86ce84 do not copy the lxc template instead use the full path 2015-08-28 14:58:16 +02:00
Robin Gloster
e5a55d1020 fix shebang in template 2015-08-28 14:58:16 +02:00
Antonio Terceiro
64f561073c forward_ports: bind to localhost only by default
This has been raised as security concern on vagrant itself, and fixed
there some time ago.
2015-08-28 14:58:16 +02:00
Franz Pletz
0c353598f8 Merge pull request #362 from ccope/halt-lvm-fix
remove /tmp cleanup command, fixes lvm rootfs
2015-08-28 14:50:51 +02:00
Franz Pletz
78ef85aa97 Merge pull request #383 from stucki/use-system-bridge
Use system bridge
2015-08-25 15:20:11 +02:00
Michael Stucki
366a98a052 Fix warning message 2015-08-25 15:13:03 +02:00
Michael Stucki
40ced9d3d1 Do not remove system bridge virbr0 2015-08-25 15:12:32 +02:00
Franz Pletz
bbff802b5d Merge pull request #376 from globin/nixos-current
NixOS compatibility
2015-08-25 14:53:03 +02:00
Michael Stucki
eb503e42fd Fix variable name 2015-08-25 14:38:44 +02:00
Andriy
5329e8837e Update gc_private_network_bridges.rb 2015-08-25 14:38:31 +02:00
Andriy
d2c032a073 Update driver.rb
Fixing https://github.com/fgrehm/vagrant-lxc/issues/353 issue
2015-08-25 14:38:28 +02:00
Michael Stucki
7eb3be37de driver.rb: Check for correct bridge device name 2015-08-25 10:20:21 +02:00
Michael Stucki
31bb4eadf9 Move away from using ifconfig to ip link for enabling / disabling bridge devices 2015-08-25 10:18:14 +02:00
Cam Cope
5fb0bcbcbc make /tmp a tmpfs 2015-08-17 17:43:45 -07:00
Cam Cope
eba671c54d remove /tmp cleanup, fixes lvm rootfs 2015-08-17 17:43:24 -07:00
Robin Gloster
4b78c04a47 Use /usr/bin/env CMD instead of hardcoded paths
This fixes commands that currently rely on hardcoded paths and break
on systems like NixOS that don't have all binaries in /usr/bin etc.
2015-08-02 10:15:55 +00:00
Robin Gloster
9c67e13fb8 Fix test on NixOS
Tempfile can be created in /run, too.
2015-08-02 10:15:55 +00:00
Robin Gloster
5cd32c76df Update gems to resolve dependencies on NixOS 2015-08-02 10:15:55 +00:00
Robin Gloster
2b91983cae do not copy the lxc template instead use the full path 2015-08-02 10:15:55 +00:00
Robin Gloster
64240323f0 fix shebang in template 2015-08-02 09:58:36 +00:00
Franz Pletz
6718fed241 Merge pull request #381 from terceiro/bind-localhost
forward_ports: bind to localhost only by default
2015-07-31 19:04:12 +02:00
Antonio Terceiro
81f2c13541 forward_ports: bind to localhost only by default
This has been raised as security concern on vagrant itself, and fixed
there some time ago.
2015-07-19 12:29:27 -03:00
Michael Stucki
c3508870fd Private networking: Create bridge if it is missing 2015-07-06 18:01:18 +02:00
Michael Stucki
fb661300e7 Move bridge_exists check into a function 2015-07-06 18:01:15 +02:00
Fabio Rehm
bb21906ec4 Update README.md 2015-05-08 19:49:30 -03:00
Fabio Rehm
0365ad4a17 Update CHANGELOG.md 2015-04-06 11:02:18 -03:00
Fabio Rehm
fd22ccc073 Update CHANGELOG.md 2015-04-06 10:59:57 -03:00
Fabio Rehm
52cca8e7f6 Merge pull request #355 from lfaraone/use-current-ruby
vagrant-lxc-wrapper: Use correct ruby interpreter
2015-04-06 10:58:53 -03:00
Fabio Rehm
55bbadef6f Merge pull request #352 from ccope/private_dhcp
Support private networking using DHCP
2015-04-06 10:56:38 -03:00
Fabio Rehm
f52df5df14 Update CHANGELOG.md 2015-04-06 10:54:36 -03:00
Fabio Rehm
8cb0afeb39 Merge pull request #357 from agriffis/fedora-host-selinux-ro
Mount the selinux sys dir read-only [GH-301]
2015-04-06 10:51:30 -03:00
Fabio Rehm
8ccafecd9e Update CHANGELOG.md 2015-04-06 10:30:27 -03:00
Fabio Rehm
497f750248 Merge pull request #361 from ccope/autocreate-mountpoint
move mountpoint creation to lxc template for lvm rootfs support
2015-04-06 10:27:18 -03:00
Cam Cope
caa3c53a8f move mountpoint creation to lxc template for lvm rootfs support 2015-04-05 17:46:22 -07:00
Aron Griffis
7d017ada1e Mount the selinux sys dir read-only [GH-301] 2015-03-24 17:42:11 -04:00
Luke Faraone
05fdb3e000 vagrant-lxc-wrapper: Use correct ruby interpreter
Previously, we hardcoded to using the ruby binary in /opt/vagrant[..].
On some systems, this path is incorrect, so instead we use the
path of the interpreter that is executing the `vagrant lxc sudoers`
command.
2015-03-19 16:22:00 -07:00
Cam Cope
5da3fc8be5 support containers with dhcp private networking 2015-03-08 19:58:29 -07:00
Fabio Rehm
c9cd671a32 Update README.md 2015-01-14 21:46:18 -02:00
Fabio Rehm
3b45b92d1a v1.1.0 2015-01-14 21:44:28 -02:00
Fabio Rehm
156bc015c8 Allow backingstore options to be used along with the sudo wrapper script [GH-310] 2015-01-14 21:07:35 -02:00
Fabio Rehm
fb23e606cc action/create: Trim automatically generated container names to 64 chars
Fixes GH-337
2015-01-11 21:30:11 -02:00
Fabio Rehm
ef06ea622e Remove blank file 2015-01-11 21:18:56 -02:00
Fabio Rehm
7a09375ae7 Update CHANGELOG 2015-01-11 21:18:03 -02:00
Fabio Rehm
f4b738ebd9 Minor tweaks to specs introduced by GH-329 2015-01-11 21:16:30 -02:00
Fabio Rehm
555499d04a Merge branch 'master' of https://github.com/pruby/vagrant-lxc into next
Closes GH-329
2015-01-11 21:06:46 -02:00
Fabio Rehm
447d0dfc42 Experimental support for private networking [GH-298] 2015-01-11 20:59:38 -02:00
Fabio Rehm
bf3a9a5039 action: Some more tweaks around private networking + new pipework code [GH-298] 2015-01-08 03:57:49 -02:00
Fabio Rehm
28bdbe371d Merge remote-tracking branch 'origin/private-networks' into next 2015-01-08 02:28:45 -02:00
Fabio Rehm
758703ea6b provider: Use full which path when checking whether the lxc-create command is available
Fixes GH-322
2015-01-08 02:26:25 -02:00
Fabio Rehm
01d53a783c sudoers: Treat 256 exit codes as errors
I ran into an issue locally where I didnt have lxc installed and some
commands were giving me back some false positives. Weird but this fixes
the problem I was facing.
2015-01-08 02:18:38 -02:00
Fabio Rehm
8b37056294 provider: Show an user friendly message when trying to use the plugin on non-Linux environments 2015-01-08 02:17:32 -02:00
Fabio Rehm
2a667b88b6 plugin: Give the provider a higher priority over Vagrant's builtin VBox provider 2015-01-08 00:55:19 -02:00
Fabio Rehm
2a48f366d4 Merge branch 'tempfile_problem' of https://github.com/stefan-langenmaier/vagrant-lxc into next 2015-01-08 02:07:02 +00:00
Fabio Rehm
92685472ec Update bundle 2015-01-08 01:48:34 +00:00
Fabio Rehm
67523019aa 👋 to support for Vagrant < 1.5 2015-01-07 23:48:10 -02:00
Tim Goddard
fe532525c8 Support for formatted overlayfs path spec when finding the root FS path
We're using snapshots in a CI set-up so that a Vagrant cluster can be built
once, then each push to the repository only checked as an incremental
update to the cluster. We copy each LXC VM to a master image, then re-create
the original names as snapshots.

This change corrects a method which assumes the LXC root path in the config
file is a simple directory name, which is only true for directory-backed
instances.

Conflicts:
	spec/unit/driver_spec.rb
2014-11-12 15:21:28 +13:00
Stefan Langenmaier
188a1eb089 uninitialized constant Tempfile 2014-11-05 08:50:46 -05:00
Fabio Rehm
622366bd64 Update README.md 2014-10-15 01:18:16 -03:00
Fabio Rehm
2f0eccb236 🔨 Fix the build 🔨 2014-10-15 01:14:52 -03:00
Fabio Rehm
71e210f683 v1.0.1 2014-10-15 01:04:37 -03:00
Fabio Rehm
186d453621 Prefix action to fetch containers IP with ssh so that vagrant does not lock around its execution
Closes GH-321
2014-10-15 01:02:52 -03:00
Fabio Rehm
80ca559258 Tweaks to get the changes introduced on GH-317 to work with the sudo wrapper 2014-10-15 01:01:43 -03:00
Fabio Rehm
b4a642bc8a Merge pull request #318 from rtkrruvinskiy/lock_race
Work around WaitForCommunicator lock race condition
2014-10-15 00:31:10 -03:00
Fabio Rehm
8421291c52 Merge pull request #317 from azomazo/detect_container_path_by_lxc_config
The path of storage containers taken from lxc-config, instead of using a constant
2014-10-15 00:30:53 -03:00
Ray Ruvinskiy
dc55c914e4 Work around WaitForCommunicator lock race condition
The LXC provider issues the "fetch_ip" action to look up the IP address
of the container as part of its "ssh_info" action.
Vagrant::LXC::Action.action_fetch_ip checks the machine state using
Builtin::IsState, which calls Vagrant::Machine.state, which also updates
the state in the machine index and acquires a machine index entry lock to do that.
A race condition ensues in WaitForCommunicator.call, where ready_thr tries
to acquire the machine index lock while running ssh_info, and states_thr tries
to acquire the same lock doing its own state look up (env[:machine].state.id).
If they both try to acquire the lock at the same time, one will fail, and
an exception will be raised.

Work around this issue by checking for the desired machine state (:running) in
Vagrant::LXC::Provider.ssh_info, which can get the state from
Vagrant::LXC::Provider.state, which in turn does not write out the state into
the index file and does not acquire the index entry lock.
2014-09-29 16:47:29 -04:00
Azamat Khudaygulov
f454924a59 The path of storage containers taken from lxc-config, instead of using a constant for lxc>=1.0.0.
* for lxc to 1.0.0 using constant Vagrant::LXC::Driver::DEFAULT_CONTAINERS_PATH
 * change method Vagrant::LXC::Driver::CLI#version to call lxc-create if lxc-version command not exists (to lxc version 1.0.0)
2014-09-23 16:07:03 +04:00
Fabio Rehm
e76a18185c 🎆 v1.0.0 🎆 2014-09-23 01:03:48 -03:00
Fabio Rehm
5fa6f0dd09 synced_folder: Emit vagrant-mounted upstart event when starting containers
Closes GH-302
2014-09-22 23:44:01 -03:00
Fabio Rehm
5e155ec02e 💣 post install message 2014-09-22 23:07:56 -03:00
Fabio Rehm
dd5a8d16d0 Update README 2014-09-22 23:07:39 -03:00
Fabio Rehm
8ffc9ef92a Remove version suffix from generated sudoers commands 2014-09-22 23:07:12 -03:00
Fabio Rehm
86b169d358 Update changelog 2014-09-22 22:52:33 -03:00
Fabio Rehm
46640fbd3d Merge pull request #311 from postster/postster/tarball-strip-components-option
lxc-template: add parameter strip-components
2014-09-22 22:44:29 -03:00
Fabio Rehm
e297ea52b2 Merge pull request #314 from fpletz/fix/box-update-check
Add check for box updates to start action
2014-09-22 22:43:57 -03:00
Franz Pletz
ec4a52559a Add check for box updates to start action
This action apparently needs to be added to every provider. See
lib/vagrant/plugins/providers/virtualbox/action.rb from the Vagrant
source for reference how the virtualbox provider is doing it.
2014-09-05 20:52:03 +02:00
Dan Post
96b2c7175a lxc-template: add parameter strip-components, as not all tarballs are created like ./rootfs/... 2014-08-25 11:57:54 -07:00
Fabio Rehm
3f7c7ecabf v1.0.0.alpha.3 2014-08-09 16:37:40 -03:00
Fabio Rehm
0a017e476d Add link to gitter chat 2014-08-09 16:20:08 -03:00
Fabio Rehm
80d54bb261 Fix the build 2014-07-24 21:58:04 -03:00
Fabio Rehm
aac8c31410 driver: Remove calls to in favor of Vagrant's built in graceful halt 2014-07-24 21:58:04 -03:00
Fabio Rehm
d0642c95fd command/sudoers: Move wrapper string out to a template and use the full path to the scripts in order to make things work properly across different distros
Closes GH-304
Closes GH-305
2014-07-24 21:58:04 -03:00
Fabio Rehm
d3b9d53097 driver/cli: Deal with namespaces args for lxc-attach when the sudo wrapper script is in place [GH-300] 2014-07-24 21:58:04 -03:00
Fabio Rehm
752fa9b4e5 action/fetch_ip_with_lxc_attach: Attach to the MOUNT namespace in order to fix GH-300 2014-07-24 21:58:04 -03:00
Fabio Rehm
95b18a5d5c Fix link to sudoers command
Closes GH-303
2014-07-04 10:42:06 -03:00
Fabio Rehm
89f3e98679 Document brctl dependency for private networks 2014-06-09 00:56:37 -03:00
Fabio Rehm
a3252c3593 Update warning about networks 2014-06-09 00:56:27 -03:00
Fabio Rehm
5232f2c7b1 Begin work on supporting private networks 2014-06-09 00:48:52 -03:00
Fabio Rehm
d22d6588f8 scripts/private-network: Indent code 2014-06-09 00:25:41 -03:00
Fabio Rehm
0bd071f95d scripts/private-network: Remove Docker specifics 2014-06-09 00:21:01 -03:00
Fabio Rehm
044322d70f Vendor pipework as scripts/private-network 2014-06-09 00:20:10 -03:00
Fabio Rehm
09f855dc76 command/sudoers: Remove Cmnd_Alias from sudoers file
Since the wrapper is versioned, we would end up having multiple `LXC`
command aliases, making `sudo` unusable:

```
>>> /etc/sudoers.d/vagrant-lxc-1-0-0-alpha-3-dev: Alias `LXC' already
>>> defined near line 2 <<<
sudo: parse error in /etc/sudoers.d/vagrant-lxc-1-0-0-alpha-3-dev near
line 2
sudo: no valid sudoers sources found, quitting
sudo: unable to initialize policy plugin
```
2014-06-08 23:44:02 -03:00
Fabio Rehm
b4376ef995 command/sudoers: Use Vagrant's ruby for the sudoers file
This makes things work on systems that don't have a global ruby
installation in place and fix GH-289
2014-06-08 23:36:29 -03:00
Fabio Rehm
3e22f424e6 driver: Escape synced folders with spaces
Fix GH-291
2014-06-08 23:27:27 -03:00
Fabio Rehm
212d31543e Update bundle 2014-06-08 22:52:33 -03:00
Fabio Rehm
a284d66f9e Lets release another alpha before going to beta 2014-06-08 22:52:33 -03:00
Fabio Rehm
e52ba97b13 Update rspec 2014-06-08 22:52:33 -03:00
Fabio Rehm
235f268942 Backport some specs 2014-06-08 22:52:33 -03:00
Fabio Rehm
4cb28b88c6 Update CHANGELOG 2014-06-08 22:52:33 -03:00
Fabio Rehm
f49585db51 driver/cli: Improved lxc-attach check [GH-294] 2014-06-08 22:52:33 -03:00
Fabio Rehm
3fe6cc094e Merge pull request #294 from bkkrw/lxc-attach_support
Add fallback mechanism for platforms without attach support
2014-06-08 22:50:53 -03:00
Kristof Willaert
a4768c26ca Add fallback mechanism for platforms without attach support
Some platforms (most notably CentOS and RHEL) use a kernel without
'attach' support. This patch detects this absence and falls back
to the alternative ways of doing things like detection of IP address
and halting the container.
It does so by running the command "true" through lxc-attach.
2014-06-03 17:53:26 +02:00
Fabio Rehm
3a4c0ca79d Up dev version 2014-05-13 00:29:42 -03:00
Fabio Rehm
8eabac91d6 Move base boxes section up on README 2014-05-13 00:27:49 -03:00
Fabio Rehm
7bccdd2f71 v1.0.0.alpha.2 2014-05-13 00:25:53 -03:00
Fabio Rehm
be0b1a2abc Document backingstore option and highlight that it has to be set to "none" for old lxc versions [GH-277] 2014-05-13 00:16:30 -03:00
Fabio Rehm
2db9aa89a1 action/ip_from_dnsmasq: Handle nil container hwaddr value 2014-05-12 23:56:39 -03:00
Fabio Rehm
4d45a4082b lxc-template: Write rootfs config to container config file when the fallback kicks in
Fix GH-282
2014-05-12 23:54:51 -03:00
Fabio Rehm
d7935e55f3 action/boot: Bind mount /sys/fs/pstore to same path on containers to fix some apparmor issues when starting Ubuntu 14.04 containers
Fix GH-278
2014-05-12 23:27:14 -03:00
Fabio Rehm
9111261f79 driver: Do not show a stacktrace to the user if no network.hwaddr is present on container configs
This is enough to close GH-266 since Vagrant will take care of showing
an error informing the user that it was unable to connect to the
machine.
2014-05-12 23:21:41 -03:00
Fabio Rehm
c94e765391 Fix the build 2014-05-12 23:17:04 -03:00
Fabio Rehm
c580865ab2 driver: Fix lxc config customizations prunning [GH-279] 2014-05-12 23:06:45 -03:00
Fabio Rehm
1cf8ce50e4 command/sudoers: Fix whitelisting to take GH-277 into account 2014-05-12 23:05:42 -03:00
Fabio Rehm
638e134265 Update CHANGELOG 2014-05-12 22:48:49 -03:00
Fabio Rehm
8e9abe9129 Update bundle 2014-05-12 22:46:14 -03:00
Fabio Rehm
e1a29898a4 Merge pull request #283 from bkkrw/master
Make MAC address regex check case insensitive
2014-05-12 22:45:57 -03:00
Kristof Willaert
6b5c00089d Make MAC address regex check case insensitive
The regex check for the container MAC address presence in the
dnsmasq leases file is case sensitive. Dnsmasq outputs uppercase
addresses in the leases file.

As MAC addresses are generally considered case insensitive, it
makes sense to relax the regular expression check to allow for this.
2014-05-08 14:30:14 +02:00
Fabio Rehm
b210b260b1 lxc-template: Backport --rootfs fallback from old template [GH-282] 2014-05-07 17:34:00 -03:00
Fabio Rehm
3bd22955dd Update CHANGELOG 2014-05-04 20:56:01 -03:00
Fabio Rehm
5eef1524d7 driver: Use relative guest paths for synced folders
Closes GH-258
2014-05-04 20:52:00 -03:00
Fabio Rehm
b17fb7baa8 Fix broken specs 2014-05-04 20:50:04 -03:00
Fabio Rehm
856a847bc8 config: Switch default backingstore to "best" [GH-277] 2014-05-04 20:37:09 -03:00
Fabio Rehm
4c3143aa34 Merge branch 'backingstore_options' of https://github.com/tailhook/vagrant-lxc
Conflicts:
	lib/vagrant-lxc/config.rb
2014-05-03 23:42:39 -03:00
Fabio Rehm
529558e8b0 Update CHANGELOG 2014-05-03 23:38:21 -03:00
Fabio Rehm
7870d59184 Merge branch 'fix_mounts' of https://github.com/tailhook/vagrant-lxc 2014-05-03 23:36:23 -03:00
Fabio Rehm
9838d32c2d action/forward_ports: Merge port forwarding with sudo specs into a single file [GH-259] 2014-05-03 23:31:43 -03:00
Fabio Rehm
a0fe2f9cf0 action/clear_forwarded_ports: Fix privileged port detection and simplify code [GH-259] 2014-05-03 23:28:59 -03:00
Fabio Rehm
84bdb5cb22 Fix code indentation 2014-05-03 23:28:04 -03:00
Fabio Rehm
ee63d2b2ae Merge branch 'sudo-for-redir' of https://github.com/guerremdq/vagrant-lxc 2014-05-03 23:14:29 -03:00
Fabio Rehm
127b23c66c Update README 2014-05-03 23:11:37 -03:00
Fabio Rehm
1688a79efc Update CHANGELOG 2014-05-03 22:22:17 -03:00
Fabio Rehm
251dec55fe Merge branch 'master' of https://github.com/servebox/vagrant-lxc 2014-05-03 22:17:22 -03:00
Fabio Rehm
80171fcf90 Remove development environment as I havent used it neither updated on a long time 2014-05-03 21:09:50 -03:00
Fabio Rehm
9dbd5e409f Update bundle 2014-05-03 21:09:04 -03:00
guerremdq
b288c05921 Merge branch 'sudo-for-redir' of github.com:guerremdq/vagrant-lxc into sudo-for-redir 2014-04-29 00:02:55 -03:00
guerremdq
0b1fffc6e3 clean redir pid with sudo only if port is < than 1024 2014-04-29 00:02:16 -03:00
Cam Cope
a9248cb697 add backingstore parameters 2014-04-28 17:17:59 +03:00
Eric Hartmann
3b311ad840 Fix sudoers for multiple users 2014-04-23 17:49:04 +02:00
Eric Hartmann
2666f9e38d Fix argument parsing 2014-04-23 16:27:33 +02:00
Jef Mathiot
0eae5c0926 Removed unsecure calls to SudoWrapper#su_c. 2014-04-17 12:56:56 +02:00
Jef Mathiot
94e175dc07 sudoers command now creates a safe wrapper script.
Sudoers now creates a safe wrapper script that performs sanity checks on sudo :
* wrapper generated in /usr/local/bin (name includes version to allow multiple wrappers on the same system)
* sudoers command now generates a one-line file in /etc/sudoers.d
* SudoWrapper use the new wrapper
* Removed unused Config#validate method
2014-04-09 15:53:20 +02:00
Paul Colomiets
9f9cb1c791 Implement sorting of synced_folders
It's useful if you want to mount something inside /vagrant or if you
have some another mount in some synced folder.

This piece of code is extracted from virtualbox driver.
2014-04-09 16:16:56 +03:00
Fabio Rehm
47cf361b98 Up dev version 2014-04-06 18:52:19 -03:00
Fabio Rehm
8c6e9724bd Update release date on changelog and add instructions for installing the alpha version of the plugin 2014-04-06 18:45:49 -03:00
idontdomath
d8d371984b enabled warning on the used environment for forward ports spec.
removed warn checks on test were the condition didn't apply.
2014-03-29 20:21:14 -03:00
Facundo Guerrero
36b38b7664 add expect for warn message 2014-03-27 15:25:12 -03:00
guerremdq
697d8bde08 only use sudo with redir when port number is lower than 1024 2014-03-23 13:39:42 -03:00
guerremdq
fd948f8552 Add sudo for redir 2014-03-20 17:01:45 -03:00
53 changed files with 1800 additions and 1332 deletions

1
.gitignore vendored
View file

@ -19,6 +19,7 @@ doc/
/tags
/gems.tags
/Gemfile.lock
.vagrant
/cache

View file

@ -1,8 +1,10 @@
language: ruby
rvm:
- 2.0.0
- 2.1.1
matrix:
allow_failures:
- rvm: 2.1.1
- 2.2
- 2.3
- 2.4
- 2.5
install:
- gem install -v 1.12.5 bundler
- bundle _1.12.5_ install --jobs=3 --retry=3
script: "bundle exec rake ci"

View file

@ -1,4 +1,258 @@
## [1.0.0.alpha.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.8.0...v1.0.0.alpha.1) (Mar 04, 2014)
## [1.4.2](https://github.com/fgrehm/vagrant-lxc/compare/v1.4.1...v1.4.2) (Jul 17, 2018)
FIXES:
- Fix problems with `redir` 3.x command line. [[GH-467]]
## [1.4.1](https://github.com/fgrehm/vagrant-lxc/compare/v1.4.0...v1.4.1) (Apr 30, 2018)
FEATURES:
- Add support for LXC v3.0
- Add support for `redir` 3.x command line. [[GH-460]]
[GH-460]: https://github.com/fgrehm/vagrant-lxc/issues/460
## [1.4.0](https://github.com/fgrehm/vagrant-lxc/compare/v1.3.1...v1.4.0) (Mar 04, 2018)
FEATURES:
- Add support for unprivileged containers. [[GH-312]]
[GH-312]: https://github.com/fgrehm/vagrant-lxc/issues/312
## [1.3.1](https://github.com/fgrehm/vagrant-lxc/compare/v1.3.0...v1.3.1) (Fev 06, 2018)
FIXES:
- Fix problems with `tmpfs` fiddling in v1.3.0. [[GH-455]]
[GH-455]: https://github.com/fgrehm/vagrant-lxc/pull/455
## [1.3.0](https://github.com/fgrehm/vagrant-lxc/compare/v1.2.4...v1.3.0) (Jan 20, 2018)
FEATURES:
- lxc-template: make runnable by unprivileged users [[GH-447]]
- Use `lxc-info` instead of `lxc-attach` to retrieve container IP
- Add support for LXC v2.1+ [[GH-445]]
- Remove 2Gb limitation on `/tmp`. [[GH-406]]
OTHERS:
- Bump Vagrant requirements to v1.8+
- Bump LXC requirements to v1.0+
[GH-447]: https://github.com/fgrehm/vagrant-lxc/pull/447
[GH-445]: https://github.com/fgrehm/vagrant-lxc/pull/445
[GH-406]: https://github.com/fgrehm/vagrant-lxc/pull/406
## [1.2.4](https://github.com/fgrehm/vagrant-lxc/compare/v1.2.3...v1.2.4) (Dec 20, 2017)
BUGFIX:
- Support alternative `lxcpath` [[GH-413]]
- Update `pipework` regexp in sudo wrapper for Vagrant 1.9+ [[GH-438]]
- Work around restrictive `umask` values [[GH-435]]
- Make `--config` in `lxc-template` optional [[GH-421]]
- Fix sudo wrapper binpath construction logic [[GH-410]]
- Fix bug causing CTRL-C on `vagrant up` to destroy the VM [[GH-449]]
[GH-413]: https://github.com/fgrehm/vagrant-lxc/pull/413
[GH-438]: https://github.com/fgrehm/vagrant-lxc/pull/438
[GH-435]: https://github.com/fgrehm/vagrant-lxc/pull/435
[GH-421]: https://github.com/fgrehm/vagrant-lxc/pull/421
[GH-410]: https://github.com/fgrehm/vagrant-lxc/pull/410
[GH-449]: https://github.com/fgrehm/vagrant-lxc/pull/449
## [1.2.3](https://github.com/fgrehm/vagrant-lxc/compare/v1.2.2...v1.2.3) (Dec 20, 2016)
- Fix bug in Gemfile.lock
## [1.2.2](https://github.com/fgrehm/vagrant-lxc/compare/v1.2.1...v1.2.2) (Dec 20, 2016)
BUGFIX:
- Make the timeout for fetching container IP's configurable [[GH-426]]
- Load locale file only once [[GH-423]]
- Preserve xattrs in container filesystems [[GH-411]]
- Forward port latest pipework script [[GH-408]]
- Fix handling of non-fatal lxc-stop return code [[GH-405]]
[GH-426]: https://github.com/fgrehm/vagrant-lxc/pull/426
[GH-423]: https://github.com/fgrehm/vagrant-lxc/pull/423
[GH-411]: https://github.com/fgrehm/vagrant-lxc/pull/411
[GH-408]: https://github.com/fgrehm/vagrant-lxc/pull/408
[GH-405]: https://github.com/fgrehm/vagrant-lxc/pull/405
## [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:

View file

@ -1,16 +1,16 @@
source 'https://rubygems.org'
group :development do
gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git', tag: 'v1.5.1'
gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git'
gem 'guard'
gem 'guard-rspec'
gem 'rb-inotify'
end
group :development, :test do
gem 'rake'
gem 'rspec', '2.99.0.beta2'
gem 'coveralls', require: (ENV['COVERAGE'] == 'true')
gem 'rake', '~> 10.4.2'
gem 'rspec', '~> 3.5.0'
gem 'coveralls', '~> 0.7.2', require: (ENV['COVERAGE'] == 'true')
gem 'vagrant-spec', git: 'https://github.com/mitchellh/vagrant-spec.git'
end

View file

@ -1,135 +0,0 @@
GIT
remote: https://github.com/fgrehm/vagrant-cachier.git
revision: 2df1e319408a7e6f1c6e75d48e36591199e98527
specs:
vagrant-cachier (0.6.1.dev)
GIT
remote: https://github.com/fgrehm/vagrant-pristine.git
revision: 503dbc47848c81d0fbfa6840491856f518d244a1
specs:
vagrant-pristine (0.3.0)
GIT
remote: https://github.com/mitchellh/vagrant-spec.git
revision: aae28ee57071cdd121ca782c6e0709a5c650a4be
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: 6977e93ba98fd19112b1fed74dafb8619f581984
tag: v1.5.1
specs:
vagrant (1.5.1)
bundler (~> 1.5.2)
childprocess (~> 0.5.0)
erubis (~> 2.7.0)
i18n (~> 0.6.0)
listen (~> 2.4.0)
log4r (~> 1.1.9, < 1.1.11)
net-scp (~> 1.1.0)
net-ssh (>= 2.6.6, < 2.8.0)
rb-kqueue (~> 0.2.0)
wdm (~> 0.1.0)
PATH
remote: .
specs:
vagrant-lxc (1.0.0.alpha.1)
GEM
remote: https://rubygems.org/
specs:
celluloid (0.15.2)
timers (~> 1.1.0)
childprocess (0.5.1)
ffi (~> 1.0, >= 1.0.11)
coderay (1.1.0)
coveralls (0.7.0)
multi_json (~> 1.3)
rest-client
simplecov (>= 0.7)
term-ansicolor
thor
diff-lcs (1.2.5)
docile (1.1.3)
erubis (2.7.0)
ffi (1.9.3)
formatador (0.2.4)
guard (2.4.0)
formatador (>= 0.2.4)
listen (~> 2.1)
lumberjack (~> 1.0)
pry (>= 0.9.12)
thor (>= 0.18.1)
guard-rspec (4.2.8)
guard (~> 2.1)
rspec (>= 2.14, < 4.0)
i18n (0.6.9)
listen (2.4.1)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
log4r (1.1.10)
lumberjack (1.0.4)
method_source (0.8.2)
mime-types (2.1)
multi_json (1.9.0)
net-scp (1.1.2)
net-ssh (>= 2.6.5)
net-ssh (2.7.0)
pry (0.9.12.6)
coderay (~> 1.0)
method_source (~> 0.8)
slop (~> 3.4)
rake (10.1.1)
rb-fsevent (0.9.4)
rb-inotify (0.9.3)
ffi (>= 0.5.0)
rb-kqueue (0.2.2)
ffi (>= 0.5.0)
rest-client (1.6.7)
mime-types (>= 1.16)
rspec (2.99.0.beta2)
rspec-core (= 2.99.0.beta2)
rspec-expectations (= 2.99.0.beta2)
rspec-mocks (= 2.99.0.beta2)
rspec-core (2.99.0.beta2)
rspec-expectations (2.99.0.beta2)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.99.0.beta2)
simplecov (0.8.2)
docile (~> 1.1.0)
multi_json
simplecov-html (~> 0.8.0)
simplecov-html (0.8.0)
slop (3.5.0)
term-ansicolor (1.3.0)
tins (~> 1.0)
thor (0.18.1)
timers (1.1.0)
tins (1.0.0)
vagrant-omnibus (1.3.1)
wdm (0.1.0)
PLATFORMS
ruby
DEPENDENCIES
coveralls
guard
guard-rspec
rake
rb-inotify
rspec (= 2.99.0.beta2)
vagrant!
vagrant-cachier!
vagrant-lxc!
vagrant-omnibus
vagrant-pristine!
vagrant-spec!

157
README.md
View file

@ -1,58 +1,40 @@
🟢 We plan to support and maintain vagrant-lxc, as well as clean it up.<br/>
🟢 Please feel free to contribute Issues and pull requests.<br/>
🟢 P.S: Thanks [Fabio Rehm](https://fabiorehm.com) for the amazing initial project.
# 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) [![Gittip](http://img.shields.io/gittip/fgrehm.svg)](https://www.gittip.com/fgrehm/)
[![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.1+
[LXC](http://lxc.sourceforge.net/) provider for [Vagrant](http://www.vagrantup.com/) 1.9+
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.
**NOTICE:** The master branch is targetting an initial beta for 1.0.0, for the
latest stable version of the plugin, please check the [0.8-stable](https://github.com/fgrehm/vagrant-lxc/tree/0.8-stable)
branch.
## Usage with Vagrant 1.5
Usage with the recently released Vagrant 1.5 is only possible by [building the
plugin from sources](https://github.com/fgrehm/vagrant-lxc/wiki/Development#wiki-installing-the-plugin-from-source).
The 1.0.0.beta1 version of the plugin that will ship with the changes required
is expected to be released by April, 2014.
## Features
* Provides the same workflow as the Vagrant VirtualBox provider
* Port forwarding via [`redir`](http://linux.die.net/man/1/redir)
As of now, it does not support public / private networks, but [private networks](https://github.com/fgrehm/vagrant-lxc/issues/120)
will be coming along _soon_.
* Port forwarding via [`redir`](https://github.com/troglobit/redir)
* Private networking via [`pipework`](https://github.com/jpetazzo/pipework)
## Requirements
* [Vagrant 1.1+](http://www.vagrantup.com/downloads.html)
* lxc 0.7.5+
* [Vagrant 1.9+](http://www.vagrantup.com/downloads.html)
* lxc >=2.1
* `redir` (if you are planning to use port forwarding)
* A [kernel != 3.5.0-17.28](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting#wiki-im-unable-to-restart-containers)
* `brctl` (if you are planning to use private networks, on Ubuntu this means `apt-get install bridge-utils`)
The plugin is known to work better and pretty much out of the box on Ubuntu 12.04+
hosts and installing the dependencies on it basically means a `apt-get install lxc lxc-templates cgroup-lite redir`
and a `apt-get update && apt-get dist-upgrade` to upgrade the kernel. For Debian
hosts you'll need to follow the instructions described on the [Wiki](https://github.com/fgrehm/vagrant-lxc/wiki/Usage-on-debian-hosts).
Some manual steps are required to set up a Linode machine prior to using this
plugin, please check [the wiki](https://github.com/fgrehm/vagrant-lxc/wiki/Usage-on-Linode)
for more information. Documentation on how to set things up for other distros
[are welcome](https://github.com/fgrehm/vagrant-lxc/wiki) :)
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`. 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.
**NOTE: Some users have been experiencing networking issues and right now you might need to
disable checksum offloading as described on [this comment](https://github.com/fgrehm/vagrant-lxc/issues/153#issuecomment-26441273)**
## Installation
@ -63,33 +45,31 @@ vagrant plugin install vagrant-lxc
## Quick start
On Vagrant 1.5+:
```
vagrant init fgrehm/precise64-lxc
vagrant up --provider=lxc
```
On Vagrant < 1.5:
_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)_
```
vagrant init precise64 http://bit.ly/vagrant-lxc-precise64-2013-10-23
vagrant up --provider=lxc
```
## Base boxes
If you are using Vagrant 1.2+ you can also set the `VAGRANT_DEFAULT_PROVIDER`
environmental variable to `lxc` in order to avoid typing `--provider=lxc` all
the time.
Base boxes provided on Atlas haven't been refreshed for a good while and shouldn't be relied on.
Your best best is to build your boxes yourself. Some scripts to build your own are available at
[hsoft/vagrant-lxc-base-boxes](https://github.com/hsoft/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
## Advanced configuration
If you want, you can modify container configurations from within your Vagrantfile
using the [provider block](http://docs.vagrantup.com/v2/providers/configuration.html):
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 = "quantal64"
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'
@ -103,6 +83,28 @@ 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
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
@ -111,8 +113,6 @@ for you. However, if the container name is important to you, you may use the
```ruby
Vagrant.configure("2") do |config|
config.vm.box = "quantal64"
config.vm.define "db" do |node|
node.vm.provider :lxc do |lxc|
lxc.container_name = :machine # Sets the container name to 'db'
@ -122,25 +122,52 @@ Vagrant.configure("2") do |config|
end
```
### Avoiding `sudo` passwords
_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.
This plugin requires **a lot** of `sudo`ing since [user namespaces](https://wiki.ubuntu.com/UserNamespace)
are not supported on mainstream kernels. To work around that, you can use the
`vagrant lxc sudoers` command which will create a file under `/etc/sudoers.d/vagrant-lxc-<USER>`
whitelisting all commands required by `vagrant-lxc` to run.
### 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
```
## Unprivileged containers support
Since v1.4.0, `vagrant-lxc` gained support for unprivileged containers. For now, since it's a new
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
Vagrant.configure("2") do |config|
config.vm.provider :lxc do |lxc|
lxc.privileged = false
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
If you're not using unprivileged containers, this plugin requires **a lot** of `sudo`ing 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/commands/sudoers.rb#L58-L81).
_vagrant-lxc < 1.0.0 users, please check this [Wiki page](https://github.com/fgrehm/vagrant-lxc/wiki/Avoiding-%27sudo%27-passwords)_
### Base boxes
Base boxes can be found on [VagrantCloud](https://vagrantcloud.com/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.
[this code](lib/vagrant-lxc/command/sudoers.rb).
## More information

View file

@ -1,92 +0,0 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'pathname'
BASE_URL = 'http://bit.ly/'
LAST_RELEASE_DATE = '2013-09-28'
LOCAL_BOXES_PATH = Pathname('../boxes/output').expand_path
def lxc_box_url(release_name)
box_name = "vagrant-lxc-#{release_name}-amd64-#{LAST_RELEASE_DATE}"
local_box_file = LOCAL_BOXES_PATH.join("#{box_name}.box")
local_box_file.exist? ?
local_box_file.to_s :
"#{BASE_URL}/#{box_name}"
end
BOXES = {
precise: {
lxc_url: lxc_box_url('precise'),
vbox_url: 'http://files.vagrantup.com/precise64.box'
},
quantal: {
lxc_url: lxc_box_url('quantal'),
vbox_url: 'https://github.com/downloads/roderik/VagrantQuantal64Box/quantal64.box'
},
raring: {
lxc_url: lxc_box_url('raring'),
vbox_url: 'http://cloud-images.ubuntu.com/vagrant/raring/current/raring-server-cloudimg-amd64-vagrant-disk1.box'
},
saucy: {
vbox_url: 'http://cloud-images.ubuntu.com/vagrant/saucy/current/saucy-server-cloudimg-amd64-vagrant-disk1.box'
},
squeeze: {
lxc_url: lxc_box_url('squeeze'),
# https://gist.github.com/henare/1964037
vbox_url: 'http://dl.dropbox.com/u/174733/debian-squeeze-64.box'
},
wheezy: {
lxc_url: lxc_box_url('wheezy'),
vbox_url: 'http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210.box'
},
sid: {
lxc_url: lxc_box_url('sid'),
}
}
Vagrant.require_plugin 'vagrant-lxc'
Vagrant.require_plugin 'vagrant-cachier'
Vagrant.require_plugin 'vagrant-pristine'
Vagrant.configure("2") do |config|
config.vm.synced_folder "../", "/vagrant", id: 'vagrant-root', nfs: true
config.cache.scope = :machine
ip_suffix = 30
BOXES.each do |box_name, box_config|
config.vm.define(box_name.to_sym) do |vm_config|
vm_config.vm.network :private_network, ip: "192.168.50.#{ip_suffix += 1}"
vm_config.vm.box = "#{box_name}64"
if box_config[:vbox_url]
vm_config.vm.provider :virtualbox do |vb, vb_config|
vb_config.vm.box_url = box_config[:vbox_url]
vb_config.vm.hostname = 'vbox'
vb.customize [
"modifyvm", :id,
"--memory", '1536',
"--cpus", '2'
]
end
end
if box_config[:lxc_url]
vm_config.vm.provider :lxc do |lxc, lxc_config|
lxc_config.vm.box_url = box_config[:lxc_url]
lxc_config.vm.hostname = 'lxc-dev-box'
# Required to boot nested containers
lxc.customize 'aa_profile', 'unconfined' unless %w(squeeze wheezy sid).include? box_name.to_s
end
end
end
end
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "."
puppet.manifest_file = "site.pp"
puppet.options << [ '--verbose', '--debug' ]
end
end

View file

@ -1,37 +0,0 @@
###############################################################################
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
# which is likely to be running from the host machine
###############################################################################
# MIRROR to be used by ubuntu template at container creation:
# Leaving it undefined is fine
#MIRROR="http://archive.ubuntu.com/ubuntu"
# or
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
# LXC_AUTO - whether or not to start containers symlinked under
# /etc/lxc/auto
LXC_AUTO="true"
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
# containers. Set to "false" if you'll use virbr0 or another existing
# bridge, or mavlan to your host's NIC.
USE_LXC_BRIDGE="true"
# If you change the LXC_BRIDGE to something other than lxcbr1, then
# you will also need to update your /etc/lxc/lxc.conf as well as the
# configuration (/var/lib/lxc/<container>/config) for any containers
# already created using the default config to reflect the new bridge
# name.
# If you have the dnsmasq daemon installed, you'll also have to update
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.253.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.253.0/24"
LXC_DHCP_RANGE="10.0.253.2,10.0.253.254"
LXC_DHCP_MAX="253"
LXC_SHUTDOWN_TIMEOUT=120

View file

@ -1,37 +0,0 @@
###############################################################################
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
# which is likely to be running from the host machine
###############################################################################
# MIRROR to be used by ubuntu template at container creation:
# Leaving it undefined is fine
#MIRROR="http://archive.ubuntu.com/ubuntu"
# or
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
# LXC_AUTO - whether or not to start containers symlinked under
# /etc/lxc/auto
LXC_AUTO="true"
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
# containers. Set to "false" if you'll use virbr0 or another existing
# bridge, or mavlan to your host's NIC.
USE_LXC_BRIDGE="true"
# If you change the LXC_BRIDGE to something other than lxcbr1, then
# you will also need to update your /etc/lxc/lxc.conf as well as the
# configuration (/var/lib/lxc/<container>/config) for any containers
# already created using the default config to reflect the new bridge
# name.
# If you have the dnsmasq daemon installed, you'll also have to update
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.251.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.251.0/24"
LXC_DHCP_RANGE="10.0.253.2,10.0.251.254"
LXC_DHCP_MAX="253"
LXC_SHUTDOWN_TIMEOUT=120

View file

@ -1,37 +0,0 @@
###############################################################################
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
# which is likely to be running from the host machine
###############################################################################
# MIRROR to be used by ubuntu template at container creation:
# Leaving it undefined is fine
#MIRROR="http://archive.ubuntu.com/ubuntu"
# or
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
# LXC_AUTO - whether or not to start containers symlinked under
# /etc/lxc/auto
LXC_AUTO="true"
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
# containers. Set to "false" if you'll use virbr0 or another existing
# bridge, or mavlan to your host's NIC.
USE_LXC_BRIDGE="true"
# If you change the LXC_BRIDGE to something other than lxcbr1, then
# you will also need to update your /etc/lxc/lxc.conf as well as the
# configuration (/var/lib/lxc/<container>/config) for any containers
# already created using the default config to reflect the new bridge
# name.
# If you have the dnsmasq daemon installed, you'll also have to update
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.250.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.250.0/24"
LXC_DHCP_RANGE="10.0.253.2,10.0.250.254"
LXC_DHCP_MAX="253"
LXC_SHUTDOWN_TIMEOUT=120

View file

@ -1,37 +0,0 @@
###############################################################################
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
# which is likely to be running from the host machine
###############################################################################
# MIRROR to be used by ubuntu template at container creation:
# Leaving it undefined is fine
#MIRROR="http://archive.ubuntu.com/ubuntu"
# or
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
# LXC_AUTO - whether or not to start containers symlinked under
# /etc/lxc/auto
LXC_AUTO="true"
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
# containers. Set to "false" if you'll use virbr0 or another existing
# bridge, or mavlan to your host's NIC.
USE_LXC_BRIDGE="true"
# If you change the LXC_BRIDGE to something other than lxcbr1, then
# you will also need to update your /etc/lxc/lxc.conf as well as the
# configuration (/var/lib/lxc/<container>/config) for any containers
# already created using the default config to reflect the new bridge
# name.
# If you have the dnsmasq daemon installed, you'll also have to update
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.254.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.254.0/24"
LXC_DHCP_RANGE="10.0.254.2,10.0.254.254"
LXC_DHCP_MAX="253"
LXC_SHUTDOWN_TIMEOUT=120

View file

@ -1,37 +0,0 @@
###############################################################################
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
# which is likely to be running from the host machine
###############################################################################
# MIRROR to be used by ubuntu template at container creation:
# Leaving it undefined is fine
#MIRROR="http://archive.ubuntu.com/ubuntu"
# or
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
# LXC_AUTO - whether or not to start containers symlinked under
# /etc/lxc/auto
LXC_AUTO="true"
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
# containers. Set to "false" if you'll use virbr0 or another existing
# bridge, or mavlan to your host's NIC.
USE_LXC_BRIDGE="true"
# If you change the LXC_BRIDGE to something other than lxcbr1, then
# you will also need to update your /etc/lxc/lxc.conf as well as the
# configuration (/var/lib/lxc/<container>/config) for any containers
# already created using the default config to reflect the new bridge
# name.
# If you have the dnsmasq daemon installed, you'll also have to update
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
LXC_BRIDGE="lxcbr0"
LXC_ADDR="10.0.252.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.252.0/24"
LXC_DHCP_RANGE="10.0.253.2,10.0.252.254"
LXC_DHCP_MAX="253"
LXC_SHUTDOWN_TIMEOUT=120

View file

@ -1,151 +0,0 @@
Exec { path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/', '/usr/local/bin'] }
stage { 'preinstall':
before => Stage['main']
}
class apt_get_update {
exec { 'apt-get -y update':
unless => "test -f /etc/default/lxc"
}
}
class { 'apt_get_update':
stage => preinstall
}
# Because I'm lazy ;)
exec {
'echo "alias be=\"bundle exec\"" >> /home/vagrant/.bashrc':
unless => 'grep -q "bundle exec" /home/vagrant/.bashrc';
'echo "export VAGRANT_DEFAULT_PROVIDER=lxc" >> /home/vagrant/.bashrc':
unless => 'grep -q "VAGRANT_DEFAULT_PROVIDER" /home/vagrant/.bashrc';
'echo "cd /vagrant" >> /home/vagrant/.bashrc':
unless => 'grep -q "cd /vagrant" /home/vagrant/.bashrc';
}
# Overwrite LXC default configs
exec {
'config-lxc':
# We need to do this otherwise IPs will collide with the host's lxc dhcp server.
# If we install the package prior to setting this configs the container will go crazy.
command => "cp /vagrant/development/lxc-configs/${hostname} /etc/default/lxc"
;
}
# Install dependencies
package {
[ 'libffi-dev', 'bsdtar', 'exuberant-ctags', 'ruby1.9.1-dev', 'htop', 'git',
'build-essential', 'redir', 'curl', 'vim', 'btrfs-tools', 'psmisc' ]:
ensure => 'installed'
;
'lxc':
require => Exec['config-lxc']
;
'bundler':
ensure => 'installed',
provider => 'gem'
;
}
# Upgrade kernel if needed
package {
[ 'linux-image-generic', 'linux-headers-generic' ]:
ensure => 'latest'
}
# Make sure we can create and boot nested containers
if $hostname == 'vbox' {
package { 'apparmor-utils': }
exec { 'aa-complain /usr/bin/lxc-start': }
}
# Allow gems to be installed on vagrant user home avoiding "sudo"s
# Tks to http://wiki.railsplayground.com/railsplayground/show/How+to+install+gems+and+non+root+user
file {
'/home/vagrant/gems':
ensure => directory,
owner => 'vagrant',
group => 'vagrant'
;
'/home/vagrant/.gemrc':
content => '
---
:verbose: true
gem: --no-ri --no-rdoc
:update_sources: true
:sources:
- http://gems.rubyforge.org
- http://gems.github.com
:backtrace: false
:bulk_threshold: 1000
:benchmark: false
gemhome: /home/vagrant/gems
gempath:
- /home/vagrant/gems
- /var/lib/gems/1.9.1
'
}
exec {
'set-gem-paths':
command => 'cat << EOF >> /home/vagrant/.profile
export GEM_HOME=/home/vagrant/gems
export GEM_PATH=/home/vagrant/gems:/var/lib/gems/1.9.1
export PATH=$PATH:/home/vagrant/gems/bin
EOF',
unless => 'grep -q "GEM_HOME" /home/vagrant/.profile'
}
# Bundle!
exec {
'su -l vagrant -c "cd /vagrant && bundle install"':
# We are checking for guard-rspec here but it could be any gem...
unless => 'gem list guard | grep -q rspec',
cwd => '/vagrant',
require => [
Exec['set-gem-paths'],
File['/home/vagrant/gems', '/home/vagrant/.gemrc'],
Package['bundler']
]
}
# Setup vagrant default ssh key
file {
'/home/vagrant/.ssh':
ensure => directory,
owner => 'vagrant',
group => 'vagrant'
}
exec {
'download-private-key':
command => 'wget https://raw.github.com/mitchellh/vagrant/master/keys/vagrant -O /home/vagrant/.ssh/id_rsa',
creates => '/home/vagrant/.ssh/id_rsa',
require => File['/home/vagrant/.ssh'],
user => 'vagrant'
;
'wget https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub -O /home/vagrant/.ssh/id_rsa.pub':
creates => '/home/vagrant/.ssh/id_rsa.pub',
require => File['/home/vagrant/.ssh'],
user => 'vagrant'
;
}
file {
'/home/vagrant/.ssh/id_rsa':
ensure => 'present',
mode => '0600',
require => Exec['download-private-key']
}
# Passwordless sudo wrapper script
file {
'/usr/bin/lxc-vagrant-wrapper':
ensure => 'present',
mode => '0755',
content => "#!/usr/bin/env ruby
exec ARGV.join(' ')"
}

View file

@ -1,12 +0,0 @@
# vagrant-backports
<!--
[![Build Status](https://travis-ci.org/fgrehm/vagrant-backports.png?branch=master)](https://travis-ci.org/fgrehm/vagrant-backports) [![Gem Version](https://badge.fury.io/rb/vagrant-backports.png)](http://badge.fury.io/rb/vagrant-backports) [![Code Climate](https://codeclimate.com/github/fgrehm/vagrant-backports.png)](https://codeclimate.com/github/fgrehm/vagrant-backports) [![Coverage Status](https://coveralls.io/repos/fgrehm/vagrant-backports/badge.png?branch=master)](https://coveralls.io/r/fgrehm/vagrant-backports) [![Gittip](http://img.shields.io/gittip/fgrehm.svg)](https://www.gittip.com/fgrehm/)
-->
A _"hypothetical"_ gem that helps Vagrant plugin developers to stay sane when
keeping up with Vagrant improvements by backporting parts of its recent versions
functionality.
More information will be provided if there is enough interest on having this
extracted as a separate gem.

View file

@ -1 +0,0 @@
Vagrant::Action::Builtin.const_set :HandleBox, Vagrant::Action::Builtin::HandleBoxUrl

View file

@ -1,34 +0,0 @@
module Vagrant
module Backports
module Action
# This middleware is meant to be used with Call and can check if
# a machine is in the given state ID.
class IsState
# Note: Any of the arguments can be arrays as well.
#
# @param [Symbol] target_state The target state ID that means that
# the machine was properly shut down.
# @param [Symbol] source_state The source state ID that the machine
# must be in to be shut down.
def initialize(app, env, check, **opts)
@app = app
@logger = Log4r::Logger.new("vagrant::action::builtin::is_state")
@check = check
@invert = !!opts[:invert]
end
def call(env)
@logger.debug("Checking if machine state is '#{@check}'")
state = env[:machine].state.id
@logger.debug("-- Machine state: #{state}")
env[:result] = @check == state
env[:result] = !env[:result] if @invert
@app.call(env)
end
end
end
end
end
Vagrant::Action::Builtin.const_set :IsState, Vagrant::Backports::Action::IsState

View file

@ -1,20 +0,0 @@
module Vagrant
module Backports
module Action
# This middleware simply outputs a message to the UI.
class Message
def initialize(app, env, message, **opts)
@app = app
@message = message
end
def call(env)
env[:ui].info(@message)
@app.call(env)
end
end
end
end
end
Vagrant::Action::Builtin.const_set :Message, Vagrant::Backports::Action::Message

View file

@ -1,42 +0,0 @@
# This acts like a backport of Vagrant's built in action from 1.3+ for previous version
# https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/action/builtin/wait_for_communicator.rb
module Vagrant
module Backports
module Action
class WaitForCommunicator
def initialize(app, env)
@app = app
end
def call(env)
@env = env
raise Vagrant::Errors::VMFailedToBoot if !wait_for_communicator
@app.call env
end
def wait_for_communicator
max_tries = @env[:machine].config.ssh.max_tries.to_i
max_tries.times do |i|
if @env[:machine].communicate.ready?
@env[:ui].info 'Machine booted and ready!'
return true
end
# Return true so that the vm_failed_to_boot error doesn't
# get shown
return true if @env[:interrupted]
sleep 1 if !@env["vagrant.test"]
end
@env[:ui].error I18n.t("vagrant.actions.vm.boot.failed")
false
end
end
end
end
end
Vagrant::Action::Builtin.const_set :WaitForCommunicator, Vagrant::Backports::Action::WaitForCommunicator

View file

@ -1,12 +0,0 @@
module Vagrant
module UI
class Interface
def output(*args)
info(*args)
end
def detail(*args)
info(*args)
end
end
end
end

View file

@ -1,27 +0,0 @@
module Vagrant
module Backports
class << self
def vagrant_1_2_or_later?
greater_than?('1.2.0')
end
def vagrant_1_3_or_later?
greater_than?('1.3.0')
end
def vagrant_1_4_or_later?
greater_than?('1.4.0')
end
def vagrant_1_5_or_later?
greater_than?('1.5.0')
end
private
def greater_than?(version)
Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new(version)
end
end
end
end

View file

@ -4,27 +4,17 @@ 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/fetch_ip_with_lxc_info'
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/remove_temporary_files'
require 'vagrant-lxc/action/private_networks'
require 'vagrant-lxc/action/setup_package_files'
require 'vagrant-lxc/action/warn_networks'
unless Vagrant::Backports.vagrant_1_3_or_later?
require 'vagrant-backports/action/wait_for_communicator'
end
unless Vagrant::Backports.vagrant_1_5_or_later?
require 'vagrant-backports/ui'
require 'vagrant-backports/action/handle_box'
require 'vagrant-backports/action/message'
require 'vagrant-backports/action/is_state'
end
module Vagrant
module LXC
module Action
@ -57,18 +47,14 @@ module Vagrant
b.use Builtin::Provision
b.use Builtin::EnvSet, :port_collision_repair => true
b.use Builtin::HandleForwardedPortCollisions
if Vagrant::Backports.vagrant_1_4_or_later?
b.use PrepareNFSValidIds
b.use Builtin::SyncedFolderCleanup
b.use Builtin::SyncedFolders
b.use PrepareNFSSettings
else
require 'vagrant-lxc/backports/action/share_folders'
b.use ShareFolders
end
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
@ -101,6 +87,7 @@ module Vagrant
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]
@ -137,7 +124,7 @@ module Vagrant
end
b2.use ClearForwardedPorts
b2.use RemoveTemporaryFiles
b2.use GcPrivateNetworkBridges
b2.use Builtin::Call, Builtin::GracefulHalt, :stopped, :running do |env2, b3|
if !env2[:result]
b3.use ForcedHalt
@ -157,16 +144,13 @@ module Vagrant
next
end
# TODO: Use Vagrant's built in action once we drop support for vagrant 1.2
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
if Vagrant::Backports.vagrant_1_3_or_later?
b3.use Builtin::ProvisionerCleanup
end
b3.use Builtin::ProvisionerCleanup
else
b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.will_not_destroy")
end
@ -194,11 +178,11 @@ module Vagrant
# 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_fetch_ip
def self.action_ssh_ip
Builder.new.tap do |b|
b.use Builtin::ConfigValidate
b.use FetchIpWithLxcAttach
b.use FetchIpFromDnsmasqLeases
b.use Builtin::Call, Builtin::ConfigValidate do |env, b2|
b2.use FetchIpWithLxcInfo
end
end
end

View file

@ -8,14 +8,35 @@ module Vagrant
def call(env)
@env = env
driver = env[:machine].provider.driver
config = env[:machine].provider_config
utsname = env[:machine].config.vm.hostname || env[:machine].id
config.customize 'utsname', utsname
if driver.supports_new_config_format
config.customize 'uts.name', utsname
else
config.customize 'utsname', utsname
end
# 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
if config.tmpfs_mount_size && !config.tmpfs_mount_size.empty?
# 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=#{config.tmpfs_mount_size} 0 0"
end
env[:ui].info I18n.t("vagrant_lxc.messages.starting")
env[:machine].provider.driver.start(config.customizations)
driver.start(config.customizations)
@app.call env
end

View file

@ -13,9 +13,13 @@ module Vagrant
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)
@logger.debug "Killing pid #{pid}"
system "pkill -TERM -P #{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"
@ -31,7 +35,8 @@ module Vagrant
def redir_pids
@redir_pids = Dir[@env[:machine].data_dir.join('pids').to_s + "/redir_*.pid"].map do |file|
File.read(file).strip.chomp
port_number = File.basename(file).split(/[^\d]/).join
[ File.read(file).strip.chomp , Integer(port_number) <= 1024 ]
end
end

View file

@ -7,7 +7,8 @@ module Vagrant
end
def call(env)
container_name = env[:machine].provider_config.container_name
config = env[:machine].provider_config
container_name = config.container_name
case container_name
when :machine
@ -15,24 +16,49 @@ module Vagrant
when String
# Nothing to do here, move along...
else
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)}"
container_name = generate_container_name(env)
end
env[:machine].provider.driver.create(
backingstore = config.backingstore
if backingstore.nil?
backingstore = config.privileged ? "best" : "dir"
end
driver = env[:machine].provider.driver
template_options = env[:lxc_template_opts]
if driver.supports_new_config_format
if env[:lxc_box_config]
driver.update_config_keys(env[:lxc_box_config])
end
else
template_options['--oldconfig'] = ''
end
driver.create(
container_name,
backingstore,
config.backingstore_options,
env[:lxc_template_src],
env[:lxc_template_config],
env[:lxc_template_opts]
template_options
)
driver.update_config_keys
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

View file

@ -1,49 +0,0 @@
module 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}\s+([0-9.]+)\s+/
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

View file

@ -1,30 +1,31 @@
module Vagrant
module LXC
module Action
class FetchIpWithLxcAttach
class FetchIpWithLxcInfo
# 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")
@logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_with_lxc_info")
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)
config = env[:machine].provider_config
fetch_ip_tries = config.fetch_ip_tries
driver = env[:machine].provider.driver
ip = ''
retryable(:on => LXC::Errors::ExecuteError, :tries => 10, :sleep => 3) do
return config.ssh_ip_addr if not config.ssh_ip_addr.nil?
retryable(:on => LXC::Errors::ExecuteError, :tries => fetch_ip_tries, :sleep => 3) do
unless ip = get_container_ip_from_ip_addr(driver)
# retry
raise LXC::Errors::ExecuteError, :command => "lxc-attach"
raise LXC::Errors::ExecuteError, :command => "lxc-info"
end
end
ip
@ -32,8 +33,8 @@ module Vagrant
# 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'
if output =~ /^\s+inet ([0-9.]+)\/[0-9]+\s+/
output = driver.info '-iH'
if output =~ /^([0-9.]+)/
return $1.to_s
end
end

View file

@ -1,3 +1,5 @@
require 'open3'
module Vagrant
module LXC
module Action
@ -67,7 +69,9 @@ module Vagrant
# TODO: Deprecate this behavior of "automagically" skipping ssh forwarded ports
if type == :forwarded_port && options[:id] != 'ssh'
options.delete(:host_ip) if options.fetch(:host_ip, '').to_s.strip.empty?
if options.fetch(:host_ip, '').to_s.strip.empty?
options[:host_ip] = '127.0.0.1'
end
mappings[options[:host]] = options
end
end
@ -76,11 +80,18 @@ module Vagrant
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
if redir_version >= 3
params = %W( -n #{host_ip}:#{host_port} #{guest_ip}:#{guest_port} )
else
params = %W( --lport=#{host_port} --caddr=#{guest_ip} --cport=#{guest_port} )
params.unshift "--laddr=#{host_ip}" if host_ip
end
params << '--syslog' if ENV['REDIR_LOG']
redir_cmd = "redir #{params.join(' ')} 2>/dev/null"
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
@ -94,6 +105,13 @@ module Vagrant
end
end
def redir_version
stdout, stderr, _ = Open3.capture3 "redir --version"
# For some weird reason redir printed version information in STDERR prior to 3.2
version = stdout.empty? ? stderr : stdout
version.split('.')[0].to_i
end
def redir_installed?
system "which redir > /dev/null"
end

View file

@ -0,0 +1,47 @@
module 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

View file

@ -33,8 +33,10 @@ module Vagrant
end
if template_config_file.exist?
@env[:lxc_box_config] = template_config_file.to_s
@env[:lxc_template_opts].merge!('--config' => template_config_file.to_s)
elsif old_template_config_file.exist?
@env[:lxc_box_config] = old_template_config_file.to_s
@env[:lxc_template_config] = old_template_config_file.to_s
end

View file

@ -0,0 +1,46 @@
module 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

View file

@ -1,23 +0,0 @@
module Vagrant
module LXC
module Action
class RemoveTemporaryFiles
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::lxc::action::remove_tmp_files")
end
def call(env)
# Continue execution, we need the container to be stopped
@app.call env
if env[:machine].state.id == :stopped
@logger.debug 'Removing temporary files'
tmp_path = env[:machine].provider.driver.rootfs_path.join('tmp')
env[:machine].provider.sudo_wrapper.run('rm', '-rf', "#{tmp_path}/*")
end
end
end
end
end
end

View file

@ -7,16 +7,16 @@ module Vagrant
end
def call(env)
if public_or_private_network_configured?(env[:machine].config)
if public_network_configured?(env[:machine].config)
env[:ui].warn(I18n.t("vagrant_lxc.messages.warn_networks"))
end
@app.call(env)
end
def public_or_private_network_configured?(config)
def public_network_configured?(config)
config.vm.networks.find do |type, _|
[:private_network, :public_network].include?(type.to_sym)
type.to_sym == :public_network
end
end
end

View file

@ -1,67 +0,0 @@
module Vagrant
module LXC
module Action
class ShareFolders
def initialize(app, env)
@app = app
end
def call(env)
@env = env
prepare_folders
add_override_configs
@app.call env
end
# This method returns an actual list of synced folders to create and their
# proper path.
def shared_folders
{}.tap do |result|
@env[:machine].config.vm.synced_folders.each do |id, data|
# Ignore disabled shared folders
next if data[:disabled]
# This to prevent overwriting the actual shared folders data
result[id] = data.dup
end
end
end
# Prepares the shared folders by verifying they exist and creating them
# if they don't.
def prepare_folders
shared_folders.each do |id, options|
hostpath = Pathname.new(options[:hostpath]).expand_path(@env[:root_path])
if !hostpath.directory? && options[:create]
# Host path doesn't exist, so let's create it.
@logger.debug("Host path doesn't exist, creating: #{hostpath}")
begin
hostpath.mkpath
rescue Errno::EACCES
raise Vagrant::Errors::SharedFolderCreateFailed,
:path => hostpath.to_s
end
end
end
end
def add_override_configs
@env[:ui].info I18n.t("vagrant.actions.lxc.share_folders.preparing")
folders = []
shared_folders.each do |id, data|
folders << {
:name => id,
:hostpath => File.expand_path(data[:hostpath], @env[:root_path]),
:guestpath => data[:guestpath]
}
@env[:ui].info(I18n.t("vagrant.actions.vm.share_folders.mounting_entry",
:guest_path => data[:guestpath]))
end
@env[:machine].provider.driver.share_folders(folders)
end
end
end
end
end

View file

@ -1,16 +1,26 @@
require 'tempfile'
require "vagrant-lxc/driver"
require "vagrant-lxc/sudo_wrapper"
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', "The user for which to create the policy (defaults to '#{options[:user]}')") do |u|
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
@ -18,68 +28,68 @@ module Vagrant
argv = parse_options(opts)
return unless argv
filename = "vagrant-lxc-#{options[:user]}"
to_sudoers!(create_tempfile!(options[:user], filename), filename)
wrapper_path = SudoWrapper.dest_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
# REFACTOR: Make use ERB rendering after https://github.com/mitchellh/vagrant/issues/3231
# lands into core
def create_tempfile!(user, filename)
sudoers = Tempfile.new(filename).tap do |file|
file.write "# Automatically created by vagrant-lxc\n"
commands.each do |command|
file.write sudoers_policy(user, command[:cmd], command[:args])
end
# This requires vagrant 1.5.2+ https://github.com/mitchellh/vagrant/commit/3371c3716278071680af9b526ba19235c79c64cb
def create_wrapper!
lxc_base_path = Driver.new("").containers_path
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,
:lxc_base_path => lxc_base_path,
:pipework_regex => "#{ENV['HOME']}/\.vagrant\.d/gems/(?:\\d+?\\.\\d+?\\.\\d+?/)?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
File.chmod(0644, sudoers.path)
sudoers.path
end
def to_sudoers!(source, destination)
destination = "/etc/sudoers.d/#{destination}"
commands = [
"rm -f #{destination}",
"cp #{source} #{destination}",
"chmod 440 #{destination}"
]
`echo "#{commands.join('; ')}" | sudo sh`
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 sudoers_policy(user, command, args)
vagrant_home = "#{`echo ~#{user}`.chomp}/.vagrant.d"
args = args.gsub /%\{VAGRANT_D\}/, vagrant_home
args = args.gsub /%\{BOXES\}/, "#{vagrant_home}/boxes"
"#{user} ALL=(root) NOPASSWD: #{command} #{args}\n"
end
def commands
[
{ cmd: '/usr/bin/lxc-ls', args: '' },
{ cmd: '/usr/bin/lxc-info', args: '' },
{ cmd: '/usr/bin/lxc-attach', args: '' },
{ cmd: '/usr/bin/which', args: 'lxc-*' },
{ cmd: '/bin/cat', args: '/var/lib/lxc/*' },
{ cmd: '/bin/mkdir', args: '-p /var/lib/lxc/*' },
{ cmd: '/bin/su', args: "root -c sed -e '*' -ibak /var/lib/lxc/*" },
{ cmd: '/bin/su', args: "root -c echo '*' >> /var/lib/lxc/*" },
{ cmd: '/usr/bin/lxc-start', args: '-d --name *' },
{ cmd: '/bin/cp', args: '%{BOXES}/*/lxc/lxc-template /usr/lib/lxc/templates/*' },
{ cmd: '/bin/cp', args: '%{VAGRANT_D}/gems/gems/vagrant-lxc-*/scripts/lxc-template /usr/lib/lxc/templates/*' },
{ cmd: '/bin/cp', args: '%{BOXES}/*/lxc/lxc-template /usr/share/lxc/templates/*' },
{ cmd: '/bin/cp', args: '%{VAGRANT_D}/gems/gems/vagrant-lxc-*/scripts/lxc-template /usr/share/lxc/templates/*' },
{ cmd: '/bin/rm', args: '/usr/lib/lxc/templates/*' },
{ cmd: '/bin/rm', args: '/usr/share/lxc/templates/*' },
{ cmd: '/bin/chmod', args: '+x /usr/lib/lxc/*' },
{ cmd: '/bin/chmod', args: '+x /usr/share/lxc/*' },
{ cmd: '/usr/bin/lxc-create', args: '--template * --name * -- --tarball %{BOXES}/*' },
{ cmd: '/bin/rm', args: '-rf /var/lib/lxc/*/rootfs/tmp/*' },
{ cmd: '/usr/bin/lxc-shutdown', args: '--name *' },
{ cmd: '/usr/bin/lxc-stop', args: '--name *' },
{ cmd: '/usr/bin/lxc-destroy', args: '--name *' }
]
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] = `sudo which #{cmd}`.strip
end
hash['lxc_bin'] = Pathname(`sudo which lxc-create`.strip).parent.to_s
hash['ruby'] = Gem.ruby
end
end
end
end

View file

@ -6,20 +6,41 @@ module Vagrant
# @return [Array]
attr_reader :customizations
# A String that points to a file that acts as a wrapper for sudo commands.
# 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, ...
#
# This allows us to have a single entry when whitelisting NOPASSWD commands
# on /etc/sudoers
attr_accessor :sudo_wrapper
# @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
# Size (as a string like '400M') of the tmpfs to mount at /tmp on boot.
# Set to false or nil to disable the tmpfs mount altogether. Defaults to '2G'.
attr_accessor :tmpfs_mount_size
attr_accessor :fetch_ip_tries
attr_accessor :ssh_ip_addr
# 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
@customizations = []
@sudo_wrapper = UNSET_VALUE
@backingstore = UNSET_VALUE
@backingstore_options = []
@container_name = UNSET_VALUE
@tmpfs_mount_size = UNSET_VALUE
@fetch_ip_tries = UNSET_VALUE
@ssh_ip_addr = UNSET_VALUE
@privileged = UNSET_VALUE
end
# Customize the container by calling `lxc-start` with the given
@ -37,24 +58,19 @@ module Vagrant
@customizations << [key, value]
end
def finalize!
@sudo_wrapper = nil if @sudo_wrapper == UNSET_VALUE
@container_name = nil if @container_name == UNSET_VALUE
# Stores options for backingstores like lvm, btrfs, etc
def backingstore_option(key, value)
@backingstore_options << [key, value]
end
def validate(machine)
errors = []
if @sudo_wrapper
hostpath = Pathname.new(@sudo_wrapper).expand_path(machine.env.root_path)
if ! hostpath.file?
errors << I18n.t('vagrant_lxc.sudo_wrapper_not_found', path: hostpath.to_s)
elsif ! hostpath.executable?
errors << I18n.t('vagrant_lxc.sudo_wrapper_not_executable', path: hostpath.to_s)
end
end
{ "lxc provider" => errors }
def finalize!
@container_name = nil if @container_name == UNSET_VALUE
@backingstore = nil if @backingstore == UNSET_VALUE
@existing_container_name = nil if @existing_container_name == UNSET_VALUE
@tmpfs_mount_size = '2G' if @tmpfs_mount_size == UNSET_VALUE
@fetch_ip_tries = 10 if @fetch_ip_tries == UNSET_VALUE
@ssh_ip_addr = nil if @ssh_ip_addr == UNSET_VALUE
@privileged = true if @privileged == UNSET_VALUE
end
end
end

View file

@ -3,9 +3,12 @@ require "vagrant/util/subprocess"
require "vagrant-lxc/errors"
require "vagrant-lxc/driver/cli"
require "vagrant-lxc/sudo_wrapper"
require "etc"
require "tempfile"
module Vagrant
module LXC
class Driver
@ -13,16 +16,14 @@ module Vagrant
# a name.
class ContainerNotFound < StandardError; end
# Root folder where container configs are stored
CONTAINERS_PATH = '/var/lib/lxc'
# Default root folder where container configs are stored
attr_reader :container_name,
:customizations
def initialize(container_name, sudo_wrapper, cli = nil)
def initialize(container_name, sudo_wrapper = nil, cli = nil, privileged: true)
@container_name = container_name
@sudo_wrapper = sudo_wrapper
@cli = cli || CLI.new(sudo_wrapper, container_name)
@sudo_wrapper = sudo_wrapper || SudoWrapper.new(privileged: privileged)
@cli = cli || CLI.new(@sudo_wrapper, container_name)
@logger = Log4r::Logger.new("vagrant::provider::lxc::driver")
@customizations = []
end
@ -31,53 +32,71 @@ module Vagrant
raise ContainerNotFound if @container_name && ! @cli.list.include?(@container_name)
end
# Root folder where container configs are stored
def containers_path
@containers_path ||= @cli.config('lxc.lxcpath')
end
def all_containers
@cli.list
end
def base_path
Pathname.new("#{CONTAINERS_PATH}/#{@container_name}")
Pathname.new("#{containers_path}/#{@container_name}")
end
def config_path
base_path.join('config').to_s
end
def rootfs_path
Pathname.new(config_string.match(/^lxc\.rootfs\s+=\s+(.+)$/)[1])
pathtype, path = config_string.match(/^lxc\.rootfs(?:\.path)?\s+=\s+(.+:)?(.+)$/)[1..2]
case pathtype
when 'overlayfs:'
# Split on colon (:), ignoring any colon escaped by an escape character ( \ )
# Pays attention to when the escape character is itself escaped.
_, overlay_path = config_entry.split(/(?<!\\)(?:\\\\)*:/)
if overlay_path
Pathname.new(overlay_path)
else
# Malformed: fall back to prior behaviour
Pathname.new(path)
end
else
Pathname.new(path)
end
end
def mac_address
@mac_address ||= config_string.match(/^lxc\.network\.hwaddr\s*+=\s*+(.+)$/)[1]
return @mac_address if @mac_address
if config_string =~ /^lxc\.network\.hwaddr\s*+=\s*+(.+)$/
@mac_address = $1
end
end
def config_string
@sudo_wrapper.run('cat', base_path.join('config').to_s)
@sudo_wrapper.run('cat', config_path)
end
def create(name, template_path, config_file, template_options = {})
def create(name, backingstore, backingstore_options, template_path, config_file, template_options = {})
@cli.name = @container_name = name
import_template(template_path) do |template_name|
@logger.debug "Creating container..."
@cli.create template_name, config_file, template_options
end
@logger.debug "Creating container..."
@cli.create template_path, backingstore, backingstore_options, config_file, template_options
end
def share_folders(folders)
folders.each do |f|
share_folder(f[:hostpath], f[:guestpath], f.fetch(:mount_options, 'bind'))
share_folder(f[:hostpath], f[:guestpath], f.fetch(:mount_options, nil))
end
end
def share_folder(host_path, guest_path, mount_options = nil)
guest_path = rootfs_path.join(guest_path.gsub(/^\//, ''))
unless guest_path.directory?
begin
@logger.debug("Guest path doesn't exist, creating: #{guest_path}")
@sudo_wrapper.run('mkdir', '-p', guest_path.to_s)
rescue Errno::EACCES
raise Vagrant::Errors::SharedFolderCreateFailed, :path => guest_path.to_s
end
end
mount_options = Array(mount_options || ['bind'])
guest_path = guest_path.gsub(/^\//, '').gsub(' ', '\\\040')
mount_options = Array(mount_options || ['bind', 'create=dir'])
host_path = host_path.to_s.gsub(' ', '\\\040')
@customizations << ['mount.entry', "#{host_path} #{guest_path} none #{mount_options.join(',')} 0 0"]
end
@ -96,10 +115,6 @@ module Vagrant
def forced_halt
@logger.info('Shutting down container...')
# TODO: Remove `lxc-shutdown` usage, graceful halt is enough
@cli.transition_to(:stopped) { |c| c.shutdown }
# REFACTOR: Do not use exception to control the flow
rescue CLI::TargetStateNotReached, CLI::ShutdownNotSupported
@cli.transition_to(:stopped) { |c| c.stop }
end
@ -111,27 +126,103 @@ module Vagrant
@cli.attach(*command)
end
def info(*command)
@cli.info(*command)
end
def configure_private_network(bridge_name, bridge_ip, container_name, address_type, ip)
@logger.info "Configuring network interface for #{container_name} using #{ip} and bridge #{bridge_name}"
if ip
ip += '/24'
end
if ! bridge_exists?(bridge_name)
if not bridge_ip
raise "Bridge is missing and no IP was specified!"
end
@logger.info "Creating the bridge #{bridge_name}"
cmd = [
'brctl',
'addbr',
bridge_name
]
@sudo_wrapper.run(*cmd)
end
if ! bridge_has_an_ip?(bridge_name)
if not bridge_ip
raise "Bridge has no IP and none was specified!"
end
@logger.info "Adding #{bridge_ip} to the bridge #{bridge_name}"
cmd = [
'ip',
'addr',
'add',
"#{bridge_ip}/24",
'dev',
bridge_name
]
@sudo_wrapper.run(*cmd)
@sudo_wrapper.run('ip', 'link', 'set', bridge_name, 'up')
end
cmd = [
Vagrant::LXC.source_root.join('scripts/pipework').to_s,
bridge_name,
container_name,
ip ||= "dhcp"
]
@sudo_wrapper.run(*cmd)
end
def bridge_has_an_ip?(bridge_name)
@logger.info "Checking whether the bridge #{bridge_name} has an IP"
`ip -4 addr show scope global #{bridge_name}` =~ /^\s+inet ([0-9.]+)\/[0-9]+\s+/
end
def bridge_exists?(bridge_name)
@logger.info "Checking whether bridge #{bridge_name} exists"
brctl_output = `ip link | egrep -q " #{bridge_name}:"`
$?.to_i == 0
end
def bridge_is_in_use?(bridge_name)
# REFACTOR: This method is **VERY** hacky
@logger.info "Checking if bridge #{bridge_name} is in use"
brctl_output = `brctl show #{bridge_name} 2>/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
def supports_new_config_format
Gem::Version.new(version) >= Gem::Version.new('2.1.0')
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}"
# "vagrant package" will copy the existing lxc-template in the new box file
# To keep this function backwards compatible with existing boxes, the path
# included in the tarball needs to have the same amount of path components (2)
# that will be stripped before extraction, hence the './.'
# TODO: This should be reviewed before 1.0
cmds = [
"cd #{base_path}",
"rm -f rootfs.tar.gz",
"tar --numeric-owner -czf #{target_path} -C #{rootfs_path} './.'"
]
@sudo_wrapper.su_c(cmds.join(' && '))
@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)
@ -149,7 +240,16 @@ module Vagrant
def prune_customizations
# Use sed to just strip out the block of code which was inserted by Vagrant
@logger.debug 'Prunning vagrant-lxc customizations'
@sudo_wrapper.su_c("sed -e '/^# VAGRANT-BEGIN/,/^# VAGRANT-END/ d' -ibak #{base_path.join('config')}")
contents = config_string
contents.gsub! /^# VAGRANT-BEGIN(.|\s)*# VAGRANT-END\n/, ''
write_config(contents)
end
def update_config_keys(path = nil)
path = path || config_path
@cli.update_config(path)
rescue Errors::ExecuteError
# not on LXC 2.1+. Doesn't matter, ignore.
end
protected
@ -159,46 +259,32 @@ module Vagrant
"lxc.#{key}=#{value}"
end
customizations.unshift '# VAGRANT-BEGIN'
customizations << '# VAGRANT-END'
customizations << "# VAGRANT-END\n"
config_file = base_path.join('config').to_s
customizations.each do |line|
@sudo_wrapper.su_c("echo '#{line}' >> #{config_file}")
end
contents = config_string
contents << customizations.join("\n")
write_config(contents)
end
def import_template(path)
template_name = "vagrant-tmp-#{@container_name}"
tmp_template_path = templates_path.join("lxc-#{template_name}").to_s
@logger.info 'Copying LXC template into place'
@sudo_wrapper.run('cp', path, tmp_template_path)
@sudo_wrapper.run('chmod', '+x', tmp_template_path)
yield template_name
ensure
@logger.info 'Removing LXC template'
if tmp_template_path
@sudo_wrapper.run('rm', tmp_template_path)
def write_config(contents)
confpath = base_path.join('config').to_s
begin
File.open(confpath, File::RDWR) do |file|
file.write contents
end
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
TEMPLATES_PATH_LOOKUP = %w(
/usr/share/lxc/templates
/usr/lib/lxc/templates
/usr/lib64/lxc/templates
/usr/local/lib/lxc/templates
)
def templates_path
return @templates_path if @templates_path
path = TEMPLATES_PATH_LOOKUP.find { |candidate| File.directory?(candidate) }
if !path
raise Errors::TemplatesDirMissing.new paths: TEMPLATES_PATH_LOOKUP.inspect
end
@templates_path = Pathname(path)
end
end
end
end

View file

@ -10,7 +10,6 @@ module Vagrant
attr_accessor :name
class TransitionBlockNotProvided < RuntimeError; end
class ShutdownNotSupported < RuntimeError; end
class TargetStateNotReached < RuntimeError
def initialize(target_state, state)
msg = "Target state '#{target_state}' not reached, currently on '#{state}'"
@ -29,14 +28,24 @@ module Vagrant
end
def version
if run(:version) =~ /lxc version:\s+(.+)\s*$/
$1.downcase
return @version if @version
@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)
run(:config, param).gsub("\n", '')
end
def update_config(path)
run('update-config', '-c', path)
end
def state
if @name && run(:info, '--name', @name, retryable: true) =~ /^state:[^A-Z]+([A-Z]+)$/i
$1.downcase.to_sym
@ -45,17 +54,19 @@ module Vagrant
end
end
def create(template, config_file, template_opts = {})
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 = template_opts.to_a.flatten.reject { |elem| elem.empty? }
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
@ -74,17 +85,18 @@ module Vagrant
run :start, '-d', '--name', @name, *Array(options)
end
## lxc-stop will exit 2 if machine was already stopped
# Man Page:
# 2 The specified container exists but was not running.
def stop
attach '/sbin/halt'
run :stop, '--name', @name
end
def shutdown
if system('which lxc-shutdown > /dev/null')
run :shutdown, '--name', @name
else
# REFACTOR: Do not use exception to control the flow
raise ShutdownNotSupported
begin
run :stop, '--name', @name
rescue LXC::Errors::ExecuteError => e
if e.exitcode == 2
@logger.debug "Machine already stopped, lxc-stop returned 2"
else
raise e
end
end
end
@ -95,18 +107,23 @@ module Vagrant
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
extra = ['--namespaces', namespaces]
end
end
run :attach, '--name', @name, *((extra || []) + cmd)
end
def info(*cmd)
run(:info, '--name', @name, *cmd)
end
def transition_to(target_state, tries = 30, timeout = 1, &block)
raise TransitionBlockNotProvided unless block_given?
@ -129,14 +146,6 @@ module Vagrant
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

View file

@ -5,17 +5,28 @@ module Vagrant
module Errors
class ExecuteError < Vagrant::Errors::VagrantError
error_key(:lxc_execute_error)
attr_reader :stderr, :stdout
attr_reader :stderr, :stdout, :exitcode
def initialize(message, *args)
super
if message.is_a?(Hash)
@stderr = message[:stderr]
@stdout = message[:stdout]
@exitcode = message[:exitcode]
end
end
end
class NamespacesNotSupported < Vagrant::Errors::VagrantError
# Raised when user interrupts a subprocess
class SubprocessInterruptError < Vagrant::Errors::VagrantError
error_key(:lxc_interrupt_error)
def initialize(message, *args)
super
end
end
class LxcLinuxRequired < Vagrant::Errors::VagrantError
error_key(:lxc_linux_required)
end
class LxcNotInstalled < Vagrant::Errors::VagrantError
@ -26,6 +37,10 @@ module Vagrant
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)

View file

@ -1,5 +1,4 @@
require 'vagrant'
require 'vagrant-backports/utils'
module Vagrant
module LXC
@ -10,40 +9,43 @@ module Vagrant
LXC-based virtual machines.
EOF
extra = []
extra << {parallel: true} if Vagrant::Backports.vagrant_1_2_or_later?
provider(:lxc, *extra) do
require File.expand_path("../provider", __FILE__)
I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml')
I18n.reload!
provider(:lxc, parallel: true, priority: 7) do
require_relative 'provider'
init!
Provider
end
command "lxc" do
require_relative 'command/root'
init!
Command::Root
end
config(:lxc, :provider) do
require File.expand_path("../config", __FILE__)
require_relative 'config'
init!
Config
end
if Vagrant::Backports.vagrant_1_4_or_later?
synced_folder(:lxc) do
require File.expand_path("../synced_folder", __FILE__)
SyncedFolder
end
synced_folder(:lxc) do
require_relative 'synced_folder'
SyncedFolder
end
if Vagrant::Backports.vagrant_1_5_or_later?
provider_capability("lxc", "public_address") do
require_relative "provider/cap/public_address"
Provider::Cap::PublicAddress
end
provider_capability("lxc", "public_address") do
require_relative "provider/cap/public_address"
Provider::Cap::PublicAddress
end
protected
def self.init!
return if defined?(@_init)
I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml')
I18n.reload!
@_init = true
end
end
end
end

View file

@ -2,13 +2,20 @@ require "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
@ -17,17 +24,9 @@ module Vagrant
machine_id_changed
end
def sudo_wrapper
@shell ||= begin
wrapper = @machine.provider_config.sudo_wrapper
wrapper = Pathname(wrapper).expand_path(@machine.env.root_path).to_s if wrapper
SudoWrapper.new(wrapper)
end
end
def ensure_lxc_installed!
begin
sudo_wrapper.run("which", "lxc-create")
SudoWrapper.new(privileged: @machine.provider_config.privileged).run("which", "lxc-create")
rescue Vagrant::LXC::Errors::ExecuteError
raise Errors::LxcNotInstalled
end
@ -40,7 +39,7 @@ module Vagrant
begin
@logger.debug("Instantiating the container for: #{id.inspect}")
@driver = Driver.new(id, self.sudo_wrapper)
@driver = Driver.new(id, privileged: @machine.provider_config.privileged)
@driver.validate!
rescue Driver::ContainerNotFound
# The container doesn't exist, so we probably have a stale
@ -63,13 +62,13 @@ module Vagrant
# Returns the SSH info for accessing the Container.
def ssh_info
# If the Container is not created then we cannot possibly SSH into it, so
# If the Container is not running then we cannot possibly SSH into it, so
# we return nil.
return nil if state == :not_created
return nil if state.id != :running
# Run a custom action called "fetch_ip" which does what it says and puts
# 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("fetch_ip")
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 ;)

View file

@ -4,24 +4,43 @@ module Vagrant
# Include this so we can use `Subprocess` more easily.
include Vagrant::Util::Retryable
def initialize(wrapper_path = nil)
@wrapper_path = wrapper_path
attr_reader :wrapper_path
def self.dest_path
"/usr/local/bin/vagrant-lxc-wrapper"
end
def initialize(privileged: true)
@wrapper_path = Pathname.new(SudoWrapper.dest_path).exist? && SudoWrapper.dest_path || nil
@privileged = privileged
@logger = Log4r::Logger.new("vagrant::lxc::sudo_wrapper")
end
def run(*command)
command.unshift @wrapper_path if @wrapper_path
execute *(['sudo'] + command)
end
options = command.last.is_a?(Hash) ? command.last : {}
def su_c(command)
su_command = if @wrapper_path
"#{@wrapper_path} \"#{command}\""
# Avoid running LXC commands with a restrictive umask.
# Otherwise disasters occur, like the container root directory
# having permissions `rwxr-x---` which prevents the `vagrant`
# user from accessing its own home directory; among other
# problems, SSH cannot then read `authorized_keys`!
old_mask = File.umask
File.umask(old_mask & 022) # allow all `r` and `x` bits
begin
if @privileged
if @wrapper_path && !options[:no_wrapper]
command.unshift @wrapper_path
execute *(['sudo'] + command)
else
execute *(['sudo', '/usr/bin/env'] + command)
end
else
"su root -c \"#{command}\""
execute *(['/usr/bin/env'] + command)
end
@logger.debug "Running 'sudo #{su_command}'"
system "sudo #{su_command}"
ensure
File.umask(old_mask)
end
end
private
@ -49,10 +68,10 @@ module Vagrant
# nicely handled by Vagrant.
if r.exit_code != 0
if @interrupted
@logger.info("Exit code != 0, but interrupted. Ignoring.")
raise LXC::Errors::SubprocessInterruptError, command.inspect
else
raise LXC::Errors::ExecuteError,
command: command.inspect, stderr: r.stderr, stdout: r.stdout
command: command.inspect, stderr: r.stderr, stdout: r.stdout, exitcode: r.exit_code
end
end
end

View file

@ -8,6 +8,15 @@ module Vagrant
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))
@ -37,6 +46,27 @@ module Vagrant
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

View file

@ -1,5 +1,5 @@
module Vagrant
module LXC
VERSION = "1.0.0.alpha.1"
VERSION = "1.4.2"
end
end

View file

@ -13,15 +13,18 @@ en:
force_shutdown: |-
Forcing shutdown of container...
warn_networks: |-
Warning! The LXC provider doesn't support any of the Vagrant public / private
network configurations (ex: `config.vm.network :private_network, ip: "some-ip"`).
They will be silently ignored.
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:
@ -37,6 +40,9 @@ en:
preparing: Setting up mount entries for shared folders...
errors:
lxc_interrupt_error: |-
Interrupted
lxc_execute_error: |-
There was an error executing %{command}
@ -56,8 +62,12 @@ en:
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 is not accessible on the PATH.
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.
@ -66,3 +76,7 @@ en:
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}.

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/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
@ -33,6 +33,9 @@ LXC_PATH=
LXC_ROOTFS=
LXC_TARBALL=
LXC_CONFIG=
LXC_USE_OLDCONFIG=
LXC_STRIP_COMPONENTS=2
usage() {
cat <<EOF
@ -43,6 +46,7 @@ Required arguments:
Optional arguments:
[ --config ]: Configuration file to be used when building the container
[ --oldconfig ]: Use pre LXC 2.1 config format
[ -h | --help ]: This help message
LXC internal arguments (do not pass manually!):
@ -51,11 +55,12 @@ LXC internal arguments (do not pass manually!):
[ --rootfs <rootfs> ]: The path to the container's rootfs
[ --mapped-uid <map> ]: A uid map (user namespaces)
[ --mapped-gid <map> ]: A gid map (user namespaces)
[ --strip-components <num> ]: 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: -- "$@")SS
options=$(getopt -o h -l tarball:,config:,oldconfig,help:,name:,path:,rootfs:,mapped-uid:,mapped-gid:,strip-components: -- "$@")SS
if [ $? -ne 0 ]; then
usage $(basename $0)
@ -68,12 +73,14 @@ do
case "$1" in
-h|--help) usage $0 && exit 0;;
--config) LXC_CONFIG=$2; shift 2;;
--oldconfig) LXC_USE_OLDCONFIG=1; shift 1;;
--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
@ -88,25 +95,25 @@ if [ -z "${LXC_TARBALL}" ]; then
exit 1
fi
if [ -z "${LXC_ROOTFS}" ]; then
echo "'rootfs' parameter is required"
exit 1
fi
if [ -z "${LXC_CONFIG}" ]; then
echo "'config' parameter is required"
exit 1
fi
if [ -z "${LXC_PATH}" ]; then
echo "'path' 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
@ -115,13 +122,14 @@ mkdir -p /var/lock/subsys
fi
mkdir -p ${LXC_ROOTFS}
(cd ${LXC_ROOTFS} && tar xfz ${LXC_TARBALL} --strip-components=2)
if [ $? -ne 0 ]; then
(cd ${LXC_ROOTFS} && tar xfz ${LXC_TARBALL} --strip-components=${LXC_STRIP_COMPONENTS} --xattrs --xattrs-include=* || true)
if [ ! -f ${LXC_ROOTFS}/bin/true ]; then
echo "Failed to extract rootfs"
exit 1
fi
) 200>/var/lock/subsys/lxc
) 200>${LXC_PATH}/vagrant_lock
rm ${LXC_PATH}/vagrant_lock
mkdir -p ${LXC_ROOTFS}/dev/pts/
@ -140,7 +148,12 @@ 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
if [ $LXC_USE_OLDCONFIG ]; then
echo "lxc.utsname = ${LXC_NAME}" >> ${LXC_PATH}/config
else
echo "lxc.uts.name = ${LXC_NAME}" >> ${LXC_PATH}/config
fi
## Re-add the previously removed network config
if [ -e "${LXC_PATH}/config-network" ]; then
@ -151,11 +164,13 @@ if [ -e "${LXC_PATH}/config-network" ]; then
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
if [ -n "${LXC_CONFIG}" ]; then
## 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
fi
# Empty section for lxc.customize calls from vagrantfile
echo "" >> ${LXC_PATH}/config

422
scripts/pipework Executable file
View file

@ -0,0 +1,422 @@
#!/bin/sh
# This code should (try to) follow Google's Shell Style Guide
# (https://google-styleguide.googlecode.com/svn/trunk/shell.xml)
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
if [ "$2" = "-l" ]; then
LOCAL_IFNAME=$3
shift 2
fi
GUESTNAME=$2
IPADDR=$3
MACADDR=$4
case "$MACADDR" in
*@*)
VLAN="${MACADDR#*@}"
VLAN="${VLAN%%@*}"
MACADDR="${MACADDR%%@*}"
;;
*)
VLAN=
;;
esac
# did they ask to generate a custom MACADDR?
# generate the unique string
case "$MACADDR" in
U:*)
macunique="${MACADDR#*:}"
# now generate a 48-bit hash string from $macunique
MACADDR=$(echo $macunique|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/')
;;
esac
[ "$IPADDR" ] || [ "$WAIT" ] || {
echo "Syntax:"
echo "pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan]"
echo "pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> dhcp [macaddr][@vlan]"
echo "pipework route <guest> <route_command>"
echo "pipework --wait [-i containerinterface]"
exit 1
}
# Succeed if the given utility is installed. Fail otherwise.
# For explanations about `which` vs `type` vs `command`, see:
# http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script/677212#677212
# (Thanks to @chenhanxiao for pointing this out!)
installed () {
command -v "$1" >/dev/null 2>&1
}
# Google Styleguide says error messages should go to standard error.
warn () {
echo "$@" >&2
}
die () {
status="$1"
shift
warn "$@"
exit "$status"
}
# First step: determine type of first argument (bridge, physical interface...),
# Unless "--wait" is set (then skip the whole section)
if [ -z "$WAIT" ]; then
if [ -d "/sys/class/net/$IFNAME" ]
then
if [ -d "/sys/class/net/$IFNAME/bridge" ]; then
IFTYPE=bridge
BRTYPE=linux
elif installed ovs-vsctl && ovs-vsctl list-br|grep -q "^${IFNAME}$"; then
IFTYPE=bridge
BRTYPE=openvswitch
elif [ "$(cat "/sys/class/net/$IFNAME/type")" -eq 32 ]; then # InfiniBand IPoIB interface type 32
IFTYPE=ipoib
# The IPoIB kernel module is fussy, set device name to ib0 if not overridden
CONTAINER_IFNAME=${CONTAINER_IFNAME:-ib0}
PKEY=$VLAN
else IFTYPE=phys
fi
else
case "$IFNAME" in
br*)
IFTYPE=bridge
BRTYPE=linux
;;
ovs*)
if ! installed ovs-vsctl; then
die 1 "Need OVS installed on the system to create an ovs bridge"
fi
IFTYPE=bridge
BRTYPE=openvswitch
;;
route*)
IFTYPE=route
;;
dummy*)
IFTYPE=dummy
;;
*) die 1 "I do not know how to setup interface $IFNAME." ;;
esac
fi
fi
# Set the default container interface name to eth1 if not already set
CONTAINER_IFNAME=${CONTAINER_IFNAME:-eth1}
[ "$WAIT" ] && {
while true; do
# This first method works even without `ip` or `ifconfig` installed,
# but doesn't work on older kernels (e.g. CentOS 6.X). See #128.
grep -q '^1$' "/sys/class/net/$CONTAINER_IFNAME/carrier" && break
# This method hopefully works on those older kernels.
ip link ls dev "$CONTAINER_IFNAME" && break
sleep 1
done > /dev/null 2>&1
exit 0
}
[ "$IFTYPE" = bridge ] && [ "$BRTYPE" = linux ] && [ "$VLAN" ] && {
die 1 "VLAN configuration currently unsupported for Linux bridge."
}
[ "$IFTYPE" = ipoib ] && [ "$MACADDR" ] && {
die 1 "MACADDR configuration unsupported for IPoIB interfaces."
}
# Second step: find the guest (for now, we only support LXC containers)
while read _ mnt fstype options _; do
[ "$fstype" != "cgroup" ] && continue
echo "$options" | grep -qw devices || continue
CGROUPMNT=$mnt
done < /proc/mounts
[ "$CGROUPMNT" ] || {
die 1 "Could not locate cgroup mount point."
}
# 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 installed docker; 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 ] && {
die 1 "Docker inspect returned invalid PID 0"
}
[ "$DOCKERPID" = "<no value>" ] && {
die 1 "Container $GUESTNAME not found, and unknown to Docker."
}
else
die 1 "Container $GUESTNAME not found, and Docker not installed."
fi
;;
1) true ;;
*) die 1 "Found more than one container matching $GUESTNAME." ;;
esac
# only check IPADDR if we are not in a route mode
[ "$IFTYPE" != route ] && {
case "$IPADDR" in
# Let's check first if the user asked for DHCP allocation.
dhcp|dhcp:*)
# Use Docker-specific strategy to run the DHCP client
# from the busybox image, in the network namespace of
# the container.
if ! [ "$DOCKERPID" ]; then
warn "You asked for a Docker-specific DHCP method."
warn "However, $GUESTNAME doesn't seem to be a Docker container."
warn "Try to replace 'dhcp' with another option?"
die 1 "Aborting."
fi
DHCP_CLIENT=${IPADDR%%:*}
;;
udhcpc|udhcpc:*|udhcpc-f|udhcpc-f:*|dhcpcd|dhcpcd:*|dhclient|dhclient:*|dhclient-f|dhclient-f:*)
DHCP_CLIENT=${IPADDR%%:*}
# did they ask for the client to remain?
DHCP_FOREGROUND=
[ "${DHCP_CLIENT: -2}" = '-f' ] && {
DHCP_FOREGROUND=true
}
DHCP_CLIENT=${DHCP_CLIENT%-f}
if ! installed "$DHCP_CLIENT"; then
die 1 "You asked for DHCP client $DHCP_CLIENT, but I can't find it."
fi
;;
# Alright, no DHCP? Then let's see if we have a subnet *and* gateway.
*/*@*)
GATEWAY="${IPADDR#*@}" GATEWAY="${GATEWAY%%@*}"
IPADDR="${IPADDR%%@*}"
;;
# No gateway? We need at least a subnet, anyway!
*/*) : ;;
# ... No? Then stop right here.
*)
warn "The IP address should include a netmask."
die 1 "Maybe you meant $IPADDR/24 ?"
;;
esac
}
# If a DHCP method was specified, extract the DHCP options.
if [ "$DHCP_CLIENT" ]; then
case "$IPADDR" in
*:*) DHCP_OPTIONS="${IPADDR#*:}" ;;
esac
fi
if [ "$DOCKERPID" ]; then
NSPID=$DOCKERPID
else
NSPID=$(head -n 1 "$(find "$CGROUPMNT" -name "$GUESTNAME" | head -n 1)/tasks")
[ "$NSPID" ] || {
# it is an alternative way to get the pid
NSPID=$(lxc-info -n "$GUESTNAME" | grep PID | grep -Eo '[0-9]+')
[ "$NSPID" ] || {
die 1 "Could not find a process inside container $GUESTNAME."
}
}
fi
# Check if an incompatible VLAN device already exists
[ "$IFTYPE" = phys ] && [ "$VLAN" ] && [ -d "/sys/class/net/$IFNAME.VLAN" ] && {
ip -d link show "$IFNAME.$VLAN" | grep -q "vlan.*id $VLAN" || {
die 1 "$IFNAME.VLAN already exists but is not a VLAN device for tag $VLAN"
}
}
[ ! -d /var/run/netns ] && mkdir -p /var/run/netns
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"
}
}
[ "$IFTYPE" != "route" ] && [ "$IFTYPE" != "dummy" ] && MTU=$(ip link show "$IFNAME" | awk '{print $5}')
# If it's a bridge, we need to create a veth pair
[ "$IFTYPE" = bridge ] && {
if [ -z "$LOCAL_IFNAME" ]; then
LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}"
fi
GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}"
# Does the link already exist?
if ip link show "$LOCAL_IFNAME" >/dev/null 2>&1; then
# link exists, is it in use?
if ip link show "$LOCAL_IFNAME" up | grep -q "UP"; then
echo "Link $LOCAL_IFNAME exists and is up"
exit 1
fi
# delete the link so we can re-add it afterwards
ip link del "$LOCAL_IFNAME"
fi
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)
if ! ovs-vsctl list-ports "$IFNAME" | grep -q "^${LOCAL_IFNAME}$"; then
ovs-vsctl add-port "$IFNAME" "$LOCAL_IFNAME" ${VLAN:+tag="$VLAN"}
fi
;;
esac
ip link set "$LOCAL_IFNAME" up
}
# 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
}
# If it's an IPoIB interface, create a virtual IPoIB interface (the IPoIB
# equivalent of a macvlan device)
#
# Note: no macvlan subinterface nor Ethernet bridge can be created on top of an
# IPoIB interface. InfiniBand is not Ethernet. IPoIB is an IP layer on top of
# InfiniBand, without an intermediate Ethernet layer.
[ "$IFTYPE" = ipoib ] && {
GUEST_IFNAME="${IFNAME}.${NSPID}"
# If a partition key is provided, use it
[ "$PKEY" ] && {
GUEST_IFNAME="${IFNAME}.${PKEY}.${NSPID}"
PKEY="pkey 0x$PKEY"
}
ip link add link "$IFNAME" name "$GUEST_IFNAME" type ipoib $PKEY
ip link set "$IFNAME" up
}
# If its a dummy interface, create a dummy interface.
[ "$IFTYPE" = dummy ] && {
GUEST_IFNAME=du$NSPID$CONTAINER_IFNAME
ip link add dev "$GUEST_IFNAME" type dummy
}
# If the `route` command was specified ...
if [ "$IFTYPE" = route ]; then
# ... discard the first two arguments and pass the rest to the route command.
shift 2
ip netns exec "$NSPID" ip route "$@"
else
# Otherwise, run normally.
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"
# When using any of the DHCP methods, we start a DHCP client in the
# network namespace of the container. With the 'dhcp' method, the
# client used is taken from the Docker busybox image (therefore
# requiring no specific client installed on the host). Other methods
# use a locally installed client.
case "$DHCP_CLIENT" in
dhcp)
docker run -d --net container:$GUESTNAME --cap-add NET_ADMIN \
busybox udhcpc -i "$CONTAINER_IFNAME" -x "hostname:$GUESTNAME" \
$DHCP_OPTIONS \
>/dev/null
;;
udhcpc)
DHCP_Q="-q"
[ "$DHCP_FOREGROUND" ] && {
DHCP_OPTIONS="$DHCP_OPTIONS -f"
}
ip netns exec "$NSPID" "$DHCP_CLIENT" -qi "$CONTAINER_IFNAME" \
-x "hostname:$GUESTNAME" \
-p "/var/run/udhcpc.$GUESTNAME.pid" \
$DHCP_OPTIONS
[ ! "$DHCP_FOREGROUND" ] && {
rm "/var/run/udhcpc.$GUESTNAME.pid"
}
;;
dhclient)
ip netns exec "$NSPID" "$DHCP_CLIENT" "$CONTAINER_IFNAME" \
-pf "/var/run/dhclient.$GUESTNAME.pid" \
-lf "/etc/dhclient/dhclient.$GUESTNAME.leases" \
$DHCP_OPTIONS
# kill dhclient after get ip address to prevent device be used after container close
[ ! "$DHCP_FOREGROUND" ] && {
kill "$(cat "/var/run/dhclient.$GUESTNAME.pid")"
rm "/var/run/dhclient.$GUESTNAME.pid"
}
;;
dhcpcd)
ip netns exec "$NSPID" "$DHCP_CLIENT" -q "$CONTAINER_IFNAME" -h "$GUESTNAME"
;;
"")
if installed ipcalc; then
eval "$(ipcalc -b $IPADDR)"
ip netns exec "$NSPID" ip addr add "$IPADDR" brd "$BROADCAST" dev "$CONTAINER_IFNAME"
else
ip netns exec "$NSPID" ip addr add "$IPADDR" dev "$CONTAINER_IFNAME"
fi
[ "$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"
}
;;
esac
# Give our ARP neighbors a nudge about the new interface
if installed arping; 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
fi
# Remove NSPID to avoid `ip netns` catch it.
rm -f "/var/run/netns/$NSPID"
# vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab :

4
spec/Vagrantfile vendored
View file

@ -15,10 +15,6 @@ Vagrant.configure("2") do |config|
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'

View file

@ -6,7 +6,7 @@ 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)} }
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}) }
@ -24,6 +24,7 @@ describe Vagrant::LXC::Action::ForwardPorts do
machine.stub_chain(:config, :vm, :networks).and_return(networks)
machine.stub(provider: provider, data_dir: data_dir)
subject.stub(redir_version: 3)
subject.stub(exec: true)
subject.stub(spawn: pid)
end
@ -34,25 +35,25 @@ describe Vagrant::LXC::Action::ForwardPorts 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"
"redir -n #{host_ip}:#{host_port} #{container_ip}:#{guest_port} 2>/dev/null"
)
end
it 'skips --laddr parameter if host_ip is nil' do
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 --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null"
"redir -n 127.0.0.1:#{host_port} #{container_ip}:#{guest_port} 2>/dev/null"
)
end
it 'skips --laddr parameter if host_ip is a blank string' do
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 --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null"
"redir -n 127.0.0.1:#{host_port} #{container_ip}:#{guest_port} 2>/dev/null"
)
end
@ -70,8 +71,47 @@ describe Vagrant::LXC::Action::ForwardPorts do
expect(subject).not_to have_received(:spawn)
end
it 'uses redir 2.x command line interface' do
subject.stub(system: true)
subject.stub(redir_version: 2)
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 '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 -n #{host_ip}:#{host_port} #{container_ip}:#{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 -n 127.0.0.1:#{host_port} #{container_ip}:#{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 -n 127.0.0.1:#{host_port} #{container_ip}:#{guest_port} 2>/dev/null"
)
end
end
end

View file

@ -4,7 +4,7 @@ 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) }
let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true, wrapper_path: nil) }
subject { described_class.new(sudo_wrapper) }
@ -29,22 +29,42 @@ describe Vagrant::LXC::Driver::CLI do
end
describe 'version' do
let(:lxc_version_out) { "lxc version: 0.x.y-rc1\n" }
before do
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
it 'parses the version from the output' do
expect(subject.version).to eq('0.x.y-rc1')
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(:run).with(:config, 'lxc.lxcpath').and_return(lxc_config_out)
allow(subject).to receive(:run).with(:create, '--version').and_return(lxc_version_out)
end
describe 'lxc version after 1.x.x'do
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(:config_file) { 'config' }
let(:template_args) { { '--extra-param' => 'param', '--other' => 'value' } }
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) }
@ -53,11 +73,13 @@ describe Vagrant::LXC::Driver::CLI do
end
it 'issues a lxc-create with provided template, container name and hash of arguments' do
subject.create(template, config_file, template_args)
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',
@ -68,7 +90,7 @@ describe Vagrant::LXC::Driver::CLI do
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, config_file, template_args)
subject.create(template, backingstore, backingstore_opts, config_file, template_args)
}.to raise_error(Vagrant::LXC::Errors::ContainerAlreadyExists)
end
end
@ -106,23 +128,17 @@ describe Vagrant::LXC::Driver::CLI do
end
end
describe 'shutdown' do
describe 'stop' do
let(:name) { 'a-running-container' }
subject { described_class.new(sudo_wrapper, name) }
before do
subject.stub(system: true)
allow(subject).to receive(:run)
subject.stop
end
it 'issues a lxc-shutdown with provided container name' do
subject.shutdown
expect(subject).to have_received(:run).with(:shutdown, '--name', name)
end
it 'raises a ShutdownNotSupported in case it is not supported' do
allow(subject).to receive(:system).with('which lxc-shutdown > /dev/null').and_return(false)
expect { subject.shutdown }.to raise_error(described_class::ShutdownNotSupported)
it 'issues a lxc-stop with provided container name' do
expect(subject).to have_received(:run).with(:stop, '--name', name)
end
end
@ -169,19 +185,9 @@ describe Vagrant::LXC::Driver::CLI do
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
let(:name) { 'a-running-container' }
subject { described_class.new(name) }
before do
subject.stub(run: true, sleep: true, state: :stopped)
end

View file

@ -31,19 +31,21 @@ describe Vagrant::LXC::Driver do
end
describe 'creation' do
let(:name) { 'container-name' }
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) }
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, template_path, config_file, template_opts
subject.create name, backingstore, backingstore_opts, template_path, config_file, template_opts
end
it 'sets the cli object container name' do
@ -52,7 +54,9 @@ describe Vagrant::LXC::Driver do
it 'creates container with the right arguments' do
expect(cli).to have_received(:create).with(
template_name,
template_path,
backingstore,
backingstore_opts,
config_file,
template_opts
)
@ -75,11 +79,17 @@ describe Vagrant::LXC::Driver do
let(:customizations) { [['a', '1'], ['b', '2']] }
let(:internal_customization) { ['internal', 'customization'] }
let(:cli) { double(Vagrant::LXC::Driver::CLI, start: true) }
let(:sudo) { double(Vagrant::LXC::SudoWrapper, su_c: true) }
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')
expect(cli).to receive(:config).with("lxc.lxcpath").and_return("/var/lib/lxc")
subject.customizations << internal_customization
subject.start(customizations)
end
@ -94,7 +104,7 @@ describe Vagrant::LXC::Driver do
end
describe 'halt' do
let(:cli) { double(Vagrant::LXC::Driver::CLI, shutdown: true) }
let(:cli) { double(Vagrant::LXC::Driver::CLI, stop: true) }
subject { described_class.new('name', nil, cli) }
@ -102,8 +112,8 @@ describe Vagrant::LXC::Driver do
allow(cli).to receive(:transition_to).and_yield(cli)
end
it 'delegates to cli shutdown' do
expect(cli).to receive(:shutdown)
it 'delegates to cli stop' do
expect(cli).to receive(:stop)
subject.forced_halt
end
@ -114,14 +124,7 @@ describe Vagrant::LXC::Driver do
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).twice
expect(cli).to receive(:stop)
subject.forced_halt
end
it 'attempts to force the container to stop in case lxc-shutdown is not supported' do
allow(cli).to receive(:shutdown).and_raise(Vagrant::LXC::Driver::CLI::ShutdownNotSupported)
expect(cli).to receive(:transition_to).with(:stopped).twice
expect(cli).to receive(:transition_to).with(:stopped)
expect(cli).to receive(:stop)
subject.forced_halt
end
@ -138,37 +141,117 @@ describe Vagrant::LXC::Driver do
end
end
describe 'containers_path' do
let(:cli) { double(Vagrant::LXC::Driver::CLI, config: cli_config_value) }
subject { described_class.new('name', nil, cli) }
describe 'lxc version after 1.x.x' do
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(:folders) { [shared_folder, ro_rw_folder] }
let(:rootfs_path) { Pathname('/path/to/rootfs') }
let(:expected_guest_path) { "#{rootfs_path}/vagrant" }
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) }
before do
subject.stub(rootfs_path: rootfs_path, system: true)
subject.share_folders(folders)
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
it "creates guest folder under container's rootfs" do
expect(sudo_wrapper).to have_received(:run).with("mkdir", "-p", expected_guest_path)
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.max = 4
lxc.pty.max = 1024
lxc.rootfs.path = #{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
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 0 0"
]
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.max = 4
lxc.pty.max = 1024
lxc.rootfs.path = overlayfs:/path/to/master/directory:#{rootfs_path}
# VAGRANT-BEGIN
lxc.network.type=veth
lxc.network.name=eth1
# VAGRANT-END
ENDCONFIG
}
it 'supports additional mount options' do
expect(subject.customizations).to include [
'mount.entry',
"#{ro_rw_folder[:hostpath]} #{rootfs_path}/vagrant/ro_rw none ro,rw 0 0"
]
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

129
templates/sudoers.rb.erb Normal file
View file

@ -0,0 +1,129 @@
#!<%= 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 = "<%= lxc_base_path %>"
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-info', '--name', /.*/, '-iH'
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'
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-update-config', '-c', /.*/
##
# 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)

View file

@ -17,11 +17,4 @@ Gem::Specification.new do |gem|
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"]
gem.post_install_message = %Q{
Thanks for giving vagrant-lxc #{Vagrant::LXC::VERSION} a try!
This version introduces many changes and includes some deprecations,
please see the project's CHANGELOG:
https://github.com/fgrehm/vagrant-lxc/blob/master/CHANGELOG.md
}
end