Compare commits
No commits in common. "master" and "0.8-stable" have entirely different histories.
master
...
0.8-stable
87 changed files with 2764 additions and 2624 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,7 +19,6 @@ doc/
|
||||||
|
|
||||||
/tags
|
/tags
|
||||||
/gems.tags
|
/gems.tags
|
||||||
/Gemfile.lock
|
|
||||||
|
|
||||||
.vagrant
|
.vagrant
|
||||||
/cache
|
/cache
|
||||||
|
|
12
.travis.yml
12
.travis.yml
|
@ -1,10 +1,8 @@
|
||||||
language: ruby
|
language: ruby
|
||||||
rvm:
|
rvm:
|
||||||
- 2.2
|
- 1.9.3
|
||||||
- 2.3
|
- 2.0.0
|
||||||
- 2.4
|
matrix:
|
||||||
- 2.5
|
allow_failures:
|
||||||
install:
|
- rvm: 2.0.0
|
||||||
- gem install -v 1.12.5 bundler
|
|
||||||
- bundle _1.12.5_ install --jobs=3 --retry=3
|
|
||||||
script: "bundle exec rake ci"
|
script: "bundle exec rake ci"
|
||||||
|
|
34
BOXES.md
34
BOXES.md
|
@ -4,11 +4,20 @@ Although the official documentation says it is only supported for VirtualBox
|
||||||
environments, you can use the [`vagrant package`](http://docs.vagrantup.com/v2/cli/package.html)
|
environments, you can use the [`vagrant package`](http://docs.vagrantup.com/v2/cli/package.html)
|
||||||
command to export a `.box` file from an existing vagrant-lxc container.
|
command to export a `.box` file from an existing vagrant-lxc container.
|
||||||
|
|
||||||
There is also a set of [bash scripts](https://github.com/fgrehm/vagrant-lxc-base-boxes)
|
There is also a set of [bash scripts](https://github.com/fgrehm/vagrant-lxc/tree/master/boxes)
|
||||||
that you can use to build base boxes as needed. By default it won't include any
|
that you can use to build base boxes as needed. By default it won't include any
|
||||||
provisioning tool and you can pick the ones you want by providing some environment
|
provisioning tool and you can pick the ones you want by providing some environment
|
||||||
variables. Please refer to the [base boxes repository](https://github.com/fgrehm/vagrant-lxc-base-boxes)
|
variables.
|
||||||
for more information.
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/fgrehm/vagrant-lxc.git
|
||||||
|
cd vagrant-lxc/boxes
|
||||||
|
PUPPET=1 CHEF=1 sudo -E ./build-ubuntu-box.sh precise amd64
|
||||||
|
```
|
||||||
|
|
||||||
|
Will build a Ubuntu Precise x86_64 box with latest Puppet and Chef pre-installed, please refer to the scripts for more information.
|
||||||
|
|
||||||
## "Anatomy" of a box
|
## "Anatomy" of a box
|
||||||
|
|
||||||
|
@ -17,20 +26,19 @@ on knowing what makes a base box for vagrant-lxc, here's what's needed:
|
||||||
|
|
||||||
### Expected `.box` contents
|
### Expected `.box` contents
|
||||||
|
|
||||||
| FILE | REQUIRED? | DESCRIPTION |
|
| FILE | DESCRIPTION |
|
||||||
| --- | --- | --- |
|
| --- | --- |
|
||||||
| `metadata.json` | Yes | Required by Vagrant |
|
| `lxc-template` | Script responsible for creating and setting up the container (used with `lxc-create`), a ["generic script"]() is provided along with project's source. |
|
||||||
| `rootfs.tar.gz` | Yes | Compressed container rootfs tarball (need to remeber to pass in `--numeric-owner` when creating it) |
|
| `rootfs.tar.gz` | Compressed container rootfs tarball (need to remeber to pass in `--numeric-owner` when creating it) |
|
||||||
| `lxc-template` | No, a ["generic script"](scripts/lxc-template) is provided by the plugin if it doesn't exist on the base box | Script responsible for creating and setting up the container (used with `lxc-create`). |
|
| `lxc.conf` | |
|
||||||
| `lxc-config` | No | Box specific configuration to be _appended_ to the system's generated container config file |
|
| `metadata.json` | |
|
||||||
| `lxc.conf` | No | File passed in to `lxc-create -f` |
|
|
||||||
|
|
||||||
### metadata.json
|
### metadata.json
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"provider": "lxc",
|
"provider": "lxc",
|
||||||
"version": "1.0.0",
|
"version": "3",
|
||||||
"built-on": "Sat Sep 21 21:10:00 UTC 2013",
|
"built-on": "Sat Sep 21 21:10:00 UTC 2013",
|
||||||
"template-opts": {
|
"template-opts": {
|
||||||
"--arch": "amd64",
|
"--arch": "amd64",
|
||||||
|
@ -43,5 +51,5 @@ on knowing what makes a base box for vagrant-lxc, here's what's needed:
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `provider` | Yes | Required by Vagrant |
|
| `provider` | Yes | Required by Vagrant |
|
||||||
| `version` | Yes | Tracks backward incompatibilities |
|
| `version` | Yes | Tracks backward incompatibilities |
|
||||||
| `built-on` | No | Date / time when the box was packaged for the first time |
|
| `built-on` | No | Date / time when the box was packaged |
|
||||||
| `template-opts` | No | Extra options to be passed to the `lxc-template` script |
|
| `template-opts` | No | Extra options to be passed to the `lxc-template` script provided with the .box package |
|
||||||
|
|
302
CHANGELOG.md
302
CHANGELOG.md
|
@ -1,304 +1,4 @@
|
||||||
## [1.4.2](https://github.com/fgrehm/vagrant-lxc/compare/v1.4.1...v1.4.2) (Jul 17, 2018)
|
## [0.8.1](https://github.com/fgrehm/vagrant-lxc/compare/v0.8.0...master) (unreleased)
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
- Support to **all Vagrant versions prior to 1.5 are now deprecated**, there is a
|
|
||||||
[small layer](lib/vagrant-backports) that ensures compatibility with versions
|
|
||||||
starting with 1.1.5 but there is no guarantee that it will stick for too long.
|
|
||||||
- Boxes released prior to this version are now deprecated and won't be available
|
|
||||||
after the final 1.0.0 release.
|
|
||||||
- `--auth-key` argument is no longer provided to `lxc-template`. This will cause
|
|
||||||
all official base boxes prior to 09/28/2013 to break.
|
|
||||||
|
|
||||||
FEATURES:
|
|
||||||
|
|
||||||
- New `vagrant lxc sudoers` command for creating a policy for users in order to
|
|
||||||
avoid `sudo` passwords [[GH-237]] / [[GH-257]]
|
|
||||||
- Support for NFS and rsync synced folders.
|
|
||||||
- Support for synced folder mount options allowing for using read only synced
|
|
||||||
folders [[GH-193]]
|
|
||||||
|
|
||||||
[GH-237]: https://github.com/fgrehm/vagrant-lxc/issues/237
|
|
||||||
[GH-257]: https://github.com/fgrehm/vagrant-lxc/pull/257
|
|
||||||
[GH-193]: https://github.com/fgrehm/vagrant-lxc/issues/193
|
|
||||||
|
|
||||||
IMPROVEMENTS:
|
|
||||||
|
|
||||||
- `lxc-template` is now optional for base boxes and are bundled with the plugin,
|
|
||||||
allowing us to roll out updates without the need to rebuild boxes [[GH-254]]
|
|
||||||
- Set container's `utsname` to `config.vm.hostname` by default [[GH-253]]
|
|
||||||
- Added libvirt dnsmasq leases file to the lookup paths [[GH-251]]
|
|
||||||
- Improved compatibility with Vagrant 1.4 / 1.5 including the ability
|
|
||||||
to use `rsync` and `nfs` shared folders to work around synced folders
|
|
||||||
permission problems. More information can be found on the following
|
|
||||||
issues: [[GH-151]] [[GH-191]] [[GH-241]] [[GH-242]]
|
|
||||||
- Warn in case `:group` or `:owner` are specified for synced folders [[GH-196]]
|
|
||||||
- Acceptance specs are now powered by `vagrant-spec` [[GH-213]]
|
|
||||||
- Base boxes creation scripts were moved out to https://github.com/fgrehm/vagrant-lxc-base-boxes.
|
|
||||||
|
|
||||||
[GH-254]: https://github.com/fgrehm/vagrant-lxc/issues/254
|
|
||||||
[GH-196]: https://github.com/fgrehm/vagrant-lxc/issues/196
|
|
||||||
[GH-251]: https://github.com/fgrehm/vagrant-lxc/pull/251
|
|
||||||
[GH-253]: https://github.com/fgrehm/vagrant-lxc/pull/253
|
|
||||||
[GH-151]: https://github.com/fgrehm/vagrant-lxc/issues/151
|
|
||||||
[GH-213]: https://github.com/fgrehm/vagrant-lxc/issues/213
|
|
||||||
[GH-191]: https://github.com/fgrehm/vagrant-lxc/issues/191
|
|
||||||
[GH-241]: https://github.com/fgrehm/vagrant-lxc/issues/241
|
|
||||||
[GH-242]: https://github.com/fgrehm/vagrant-lxc/issues/242
|
|
||||||
|
|
||||||
|
|
||||||
## [0.8.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.7.0...v0.8.0) (Feb 26, 2014)
|
## [0.8.0](https://github.com/fgrehm/vagrant-lxc/compare/v0.7.0...v0.8.0) (Feb 26, 2014)
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
### Please read before contributing
|
### Please read before contributing
|
||||||
|
|
||||||
* If you have an issue with base boxes, please create it on https://github.com/fgrehm/vagrant-lxc-base-boxes,
|
|
||||||
this repository is for the Vagrant plugin only.
|
|
||||||
|
|
||||||
* Try not to post questions in the issues tracker. I will probably answer you
|
* Try not to post questions in the issues tracker. I will probably answer you
|
||||||
but I'll most likely close the issue right away and will continue the discussion
|
but I'll most likely close the issue right away and will continue the discussion
|
||||||
with the issue closed. If you have any questions about the plugin, make sure
|
with the issue closed. If you have any questions about the plugin, make sure
|
||||||
you go through the [Wiki](https://github.com/fgrehm/vagrant-lxc/wiki) pages
|
you go through the [Wiki](https://github.com/fgrehm/vagrant-lxc/wiki) pages
|
||||||
first (specially the [Troubleshooting Section](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting))
|
first (specially the [Troubleshooting Section](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting))
|
||||||
and if you still need answers please ask a question on [Stack Overflow](http://stackoverflow.com/questions/tagged/vagrant-lxc)
|
and if you still need answers please ask a question on [Stack Overflow](http://stackoverflow.com/questions/tagged/vagrant-lxc)
|
||||||
using the `vagrant` / `lxc` tag on it so that I get notified :)
|
using the `vagrant-lxc` tag on it so that I get notified :)
|
||||||
|
|
||||||
* Please do a search on the issues tracker before submitting your issue to
|
* Please do a small search on the issues tracker before submitting your issue to
|
||||||
check if it was already reported / fixed.
|
check if it was already reported / fixed.
|
||||||
|
|
||||||
* When reporting a bug, please include **all** information that you can get
|
* When reporting a bug, please include **all** information that you can get
|
||||||
|
|
27
Gemfile
27
Gemfile
|
@ -1,23 +1,24 @@
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
gemspec
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git'
|
gem 'vagrant', github: 'mitchellh/vagrant'
|
||||||
|
gem 'vagrant-cachier', github: 'fgrehm/vagrant-cachier'
|
||||||
|
gem 'vagrant-pristine', github: 'fgrehm/vagrant-pristine'
|
||||||
|
gem 'vagrant-omnibus'
|
||||||
gem 'guard'
|
gem 'guard'
|
||||||
gem 'guard-rspec'
|
gem 'guard-rspec'
|
||||||
gem 'rb-inotify'
|
gem 'rb-inotify'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development, :test do
|
|
||||||
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
|
|
||||||
|
|
||||||
group :plugins do
|
group :development, :test do
|
||||||
acceptance = (ENV['ACCEPTANCE'] == 'true')
|
gem 'rake'
|
||||||
gem 'vagrant-cachier', git: 'https://github.com/fgrehm/vagrant-cachier.git', require: !acceptance
|
# Update https://github.com/fgrehm/vagrant-lxc/issues/111 once we are able to
|
||||||
gem 'vagrant-pristine', git: 'https://github.com/fgrehm/vagrant-pristine.git', require: !acceptance
|
# upgrade to a newer release
|
||||||
gem 'vagrant-omnibus', require: !acceptance
|
gem 'rspec', '~> 2.13.0'
|
||||||
gemspec
|
gem 'rspec-fire', require: 'rspec/fire'
|
||||||
|
gem 'rspec-spies', require: false
|
||||||
|
gem 'coveralls', require: false
|
||||||
end
|
end
|
||||||
|
|
120
Gemfile.lock
Normal file
120
Gemfile.lock
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
GIT
|
||||||
|
remote: git://github.com/fgrehm/vagrant-cachier.git
|
||||||
|
revision: 2faa6615466f8d518893f5ba51b493b877d2efde
|
||||||
|
specs:
|
||||||
|
vagrant-cachier (0.6.1.dev)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: git://github.com/fgrehm/vagrant-pristine.git
|
||||||
|
revision: 4638491786943bfbf6f115b1fc379f069963fe46
|
||||||
|
specs:
|
||||||
|
vagrant-pristine (0.3.0)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: git://github.com/mitchellh/vagrant.git
|
||||||
|
revision: a92e03cf4ce936243d3959b7b5603262a234a58d
|
||||||
|
specs:
|
||||||
|
vagrant (1.3.6.dev)
|
||||||
|
childprocess (~> 0.3.7)
|
||||||
|
erubis (~> 2.7.0)
|
||||||
|
i18n (~> 0.6.0)
|
||||||
|
log4r (~> 1.1.9)
|
||||||
|
net-scp (~> 1.1.0)
|
||||||
|
net-ssh (~> 2.6.6)
|
||||||
|
|
||||||
|
PATH
|
||||||
|
remote: .
|
||||||
|
specs:
|
||||||
|
vagrant-lxc (0.8.1.dev)
|
||||||
|
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
celluloid (0.15.2)
|
||||||
|
timers (~> 1.1.0)
|
||||||
|
childprocess (0.3.9)
|
||||||
|
ffi (~> 1.0, >= 1.0.11)
|
||||||
|
coderay (1.0.9)
|
||||||
|
coveralls (0.7.0)
|
||||||
|
multi_json (~> 1.3)
|
||||||
|
rest-client
|
||||||
|
simplecov (>= 0.7)
|
||||||
|
term-ansicolor
|
||||||
|
thor
|
||||||
|
diff-lcs (1.2.5)
|
||||||
|
erubis (2.7.0)
|
||||||
|
ffi (1.9.3)
|
||||||
|
formatador (0.2.4)
|
||||||
|
guard (2.2.3)
|
||||||
|
formatador (>= 0.2.4)
|
||||||
|
listen (~> 2.1)
|
||||||
|
lumberjack (~> 1.0)
|
||||||
|
pry (>= 0.9.12)
|
||||||
|
thor (>= 0.18.1)
|
||||||
|
guard-rspec (3.1.0)
|
||||||
|
guard (>= 1.8)
|
||||||
|
rspec (~> 2.13)
|
||||||
|
i18n (0.6.5)
|
||||||
|
listen (2.2.0)
|
||||||
|
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.0)
|
||||||
|
multi_json (1.8.2)
|
||||||
|
net-scp (1.1.2)
|
||||||
|
net-ssh (>= 2.6.5)
|
||||||
|
net-ssh (2.6.8)
|
||||||
|
pry (0.9.12.2)
|
||||||
|
coderay (~> 1.0.5)
|
||||||
|
method_source (~> 0.8)
|
||||||
|
slop (~> 3.4)
|
||||||
|
rake (10.1.0)
|
||||||
|
rb-fsevent (0.9.3)
|
||||||
|
rb-inotify (0.9.2)
|
||||||
|
ffi (>= 0.5.0)
|
||||||
|
rest-client (1.6.7)
|
||||||
|
mime-types (>= 1.16)
|
||||||
|
rspec (2.13.0)
|
||||||
|
rspec-core (~> 2.13.0)
|
||||||
|
rspec-expectations (~> 2.13.0)
|
||||||
|
rspec-mocks (~> 2.13.0)
|
||||||
|
rspec-core (2.13.1)
|
||||||
|
rspec-expectations (2.13.0)
|
||||||
|
diff-lcs (>= 1.1.3, < 2.0)
|
||||||
|
rspec-fire (1.3.0)
|
||||||
|
rspec (>= 2.11, < 4)
|
||||||
|
rspec-mocks (2.13.1)
|
||||||
|
rspec-spies (2.1.4)
|
||||||
|
rspec (~> 2.0)
|
||||||
|
simplecov (0.7.1)
|
||||||
|
multi_json (~> 1.0)
|
||||||
|
simplecov-html (~> 0.7.1)
|
||||||
|
simplecov-html (0.7.1)
|
||||||
|
slop (3.4.6)
|
||||||
|
term-ansicolor (1.2.2)
|
||||||
|
tins (~> 0.8)
|
||||||
|
thor (0.18.1)
|
||||||
|
timers (1.1.0)
|
||||||
|
tins (0.13.0)
|
||||||
|
vagrant-omnibus (1.1.2)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
coveralls
|
||||||
|
guard
|
||||||
|
guard-rspec
|
||||||
|
rake
|
||||||
|
rb-inotify
|
||||||
|
rspec (~> 2.13.0)
|
||||||
|
rspec-fire
|
||||||
|
rspec-spies
|
||||||
|
vagrant!
|
||||||
|
vagrant-cachier!
|
||||||
|
vagrant-lxc!
|
||||||
|
vagrant-omnibus
|
||||||
|
vagrant-pristine!
|
165
README.md
165
README.md
|
@ -1,40 +1,47 @@
|
||||||
🟢 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
|
# vagrant-lxc
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/fgrehm/vagrant-lxc.png?branch=master)](https://travis-ci.org/fgrehm/vagrant-lxc) [![Gem Version](https://badge.fury.io/rb/vagrant-lxc.png)](http://badge.fury.io/rb/vagrant-lxc) [![Code Climate](https://codeclimate.com/github/fgrehm/vagrant-lxc.png)](https://codeclimate.com/github/fgrehm/vagrant-lxc) [![Coverage Status](https://coveralls.io/repos/fgrehm/vagrant-lxc/badge.png?branch=master)](https://coveralls.io/r/fgrehm/vagrant-lxc) [![Gitter chat](https://badges.gitter.im/fgrehm/vagrant-lxc.png)](https://gitter.im/fgrehm/vagrant-lxc)
|
[![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/)
|
||||||
|
|
||||||
[LXC](http://lxc.sourceforge.net/) provider for [Vagrant](http://www.vagrantup.com/) 1.9+
|
[LXC](http://lxc.sourceforge.net/) provider for [Vagrant](http://www.vagrantup.com/) 1.1+
|
||||||
|
|
||||||
This is a Vagrant plugin that allows it to control and provision Linux Containers
|
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
|
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/)
|
[this blog post](http://fabiorehm.com/blog/2013/04/28/lxc-provider-for-vagrant/)
|
||||||
to see it in action.
|
to see it in action.
|
||||||
|
|
||||||
## Features
|
|
||||||
|
## Features / Limitations
|
||||||
|
|
||||||
* Provides the same workflow as the Vagrant VirtualBox provider
|
* Provides the same workflow as the Vagrant VirtualBox provider
|
||||||
* Port forwarding via [`redir`](https://github.com/troglobit/redir)
|
* Port forwarding via [`redir`](http://linux.die.net/man/1/redir)
|
||||||
* Private networking via [`pipework`](https://github.com/jpetazzo/pipework)
|
* Does not support public / private networks
|
||||||
|
* Assumes you have a `lxcbr0` bridge configured on your host similar to [Ubuntu's built-in](https://help.ubuntu.com/lts/serverguide/lxc.html#lxcbr0)
|
||||||
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* [Vagrant 1.9+](http://www.vagrantup.com/downloads.html)
|
* [Vagrant 1.1+](http://downloads.vagrantup.com/)
|
||||||
* lxc >=2.1
|
* lxc 0.7.5+
|
||||||
* `redir` (if you are planning to use port forwarding)
|
* redir (if you are planning to use port forwarding)
|
||||||
* `brctl` (if you are planning to use private networks, on Ubuntu this means `apt-get install bridge-utils`)
|
* A [kernel != 3.5.0-17.28](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting#wiki-im-unable-to-restart-containers)
|
||||||
|
|
||||||
The plugin is known to work better and pretty much out of the box on Ubuntu 14.04+
|
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
|
hosts and installing the dependencies on it basically means a `apt-get install lxc lxc-templates cgroup-lite redir`
|
||||||
`apt-get install lxc lxc-templates cgroup-lite redir`. For setting up other
|
and a `apt-get update && apt-get dist-upgrade` to upgrade the kernel. For Debian
|
||||||
types of hosts please have a look at the [Wiki](https://github.com/fgrehm/vagrant-lxc/wiki).
|
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) :)
|
||||||
|
|
||||||
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)
|
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)
|
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.
|
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
|
## Installation
|
||||||
|
|
||||||
|
@ -43,33 +50,38 @@ vagrant plugin install vagrant-lxc
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Quick start
|
## Usage
|
||||||
|
|
||||||
|
After installing, add a [base box](#base-boxes) using any name you want, for example:
|
||||||
|
|
||||||
```
|
```
|
||||||
vagrant init fgrehm/precise64-lxc
|
vagrant box add quantal64 http://bit.ly/vagrant-lxc-quantal64-2013-10-23
|
||||||
vagrant up --provider=lxc
|
|
||||||
```
|
```
|
||||||
|
|
||||||
_More information about skipping the `--provider` argument can be found at the
|
Then create a Vagrantfile that looks like the following, changing the box name
|
||||||
"DEFAULT PROVIDER" section of [Vagrant docs](https://docs.vagrantup.com/v2/providers/basic_usage.html)_
|
to the one you've just added:
|
||||||
|
|
||||||
## Base boxes
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
You can modify container configurations from within your Vagrantfile using the
|
|
||||||
[provider block](http://docs.vagrantup.com/v2/providers/configuration.html):
|
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
config.vm.box = "fgrehm/trusty64-lxc"
|
config.vm.box = "quantal64"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
And finally run `vagrant up --provider=lxc`.
|
||||||
|
|
||||||
|
If you are using Vagrant 1.2+ you can also set `VAGRANT_DEFAULT_PROVIDER`
|
||||||
|
environmental variable to `lxc` in order to avoid typing `--provider=lxc` all
|
||||||
|
the time.
|
||||||
|
|
||||||
|
|
||||||
|
### 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):
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.box = "quantal64"
|
||||||
config.vm.provider :lxc do |lxc|
|
config.vm.provider :lxc do |lxc|
|
||||||
# Same effect as 'customize ["modifyvm", :id, "--memory", "1024"]' for VirtualBox
|
# Same effect as 'customize ["modifyvm", :id, "--memory", "1024"]' for VirtualBox
|
||||||
lxc.customize 'cgroup.memory.limit_in_bytes', '1024M'
|
lxc.customize 'cgroup.memory.limit_in_bytes', '1024M'
|
||||||
|
@ -81,29 +93,7 @@ vagrant-lxc will then write out `lxc.cgroup.memory.limit_in_bytes='1024M'` to th
|
||||||
container config file (usually kept under `/var/lib/lxc/<container>/config`)
|
container config file (usually kept under `/var/lib/lxc/<container>/config`)
|
||||||
prior to starting it.
|
prior to starting it.
|
||||||
|
|
||||||
For other configuration options, please check the [lxc.conf manpages](http://manpages.ubuntu.com/manpages/precise/man5/lxc.conf.5.html).
|
For other configuration options, please check the [lxc.conf manpages](http://manpages.ubuntu.com/manpages/quantal/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
|
### Container naming
|
||||||
|
|
||||||
|
@ -113,6 +103,8 @@ for you. However, if the container name is important to you, you may use the
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
|
config.vm.box = "quantal64"
|
||||||
|
|
||||||
config.vm.define "db" do |node|
|
config.vm.define "db" do |node|
|
||||||
node.vm.provider :lxc do |lxc|
|
node.vm.provider :lxc do |lxc|
|
||||||
lxc.container_name = :machine # Sets the container name to 'db'
|
lxc.container_name = :machine # Sets the container name to 'db'
|
||||||
|
@ -122,52 +114,19 @@ Vagrant.configure("2") do |config|
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
_Please note that there is a 64 chars limit and the container name will be
|
### Avoiding `sudo` passwords
|
||||||
trimmed down to that to ensure we can always bring the container up.
|
|
||||||
|
|
||||||
### Backingstore options
|
This plugin requires **a lot** of `sudo`ing since [user namespaces](https://wiki.ubuntu.com/UserNamespace)
|
||||||
|
are not supported on mainstream kernels. Have a look at the [Wiki](https://github.com/fgrehm/vagrant-lxc/wiki/Avoiding-'sudo'-passwords)
|
||||||
|
to find out how to work around that specially if you are running an OS with `sudo`
|
||||||
|
< 1.8.4 (like Ubuntu 12.04) as you might be affected by a bug.
|
||||||
|
|
||||||
Support for setting `lxc-create`'s backingstore option (`-B` and related) can be
|
### Base boxes
|
||||||
specified from the provider block and it defaults to `best`, to change it:
|
|
||||||
|
|
||||||
```ruby
|
Please check [the wiki](https://github.com/fgrehm/vagrant-lxc/wiki/Base-boxes)
|
||||||
Vagrant.configure("2") do |config|
|
for a list of [pre built](https://github.com/fgrehm/vagrant-lxc/wiki/Base-boxes#available-boxes)
|
||||||
config.vm.provider :lxc do |lxc|
|
base boxes and have a look at [`BOXES.md`](https://github.com/fgrehm/vagrant-lxc/tree/master/BOXES.md)
|
||||||
lxc.backingstore = 'lvm' # or 'btrfs', 'overlayfs', ...
|
for more information on building your own.
|
||||||
# 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/command/sudoers.rb).
|
|
||||||
|
|
||||||
|
|
||||||
## More information
|
## More information
|
||||||
|
|
22
boxes/build-all.sh
Executable file
22
boxes/build-all.sh
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# set -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Convenience script used for building all of the base boxes available
|
||||||
|
|
||||||
|
# Ubuntu boxes
|
||||||
|
sudo -E ./build-ubuntu-box.sh precise
|
||||||
|
sudo -E ./build-ubuntu-box.sh quantal
|
||||||
|
sudo -E ./build-ubuntu-box.sh raring
|
||||||
|
sudo -E ./build-ubuntu-box.sh saucy
|
||||||
|
|
||||||
|
# Debian boxes
|
||||||
|
sudo -E ./build-debian-box.sh squeeze
|
||||||
|
sudo -E ./build-debian-box.sh wheezy
|
||||||
|
sudo -E ./build-debian-box.sh sid
|
||||||
|
|
||||||
|
for box in precise raring quantal saucy squeeze wheezy sid; do
|
||||||
|
box="vagrant-lxc-${box}-amd64-`date +%Y-%m-%d`.box"
|
||||||
|
~/bin/dropbox_uploader.sh upload output/${box} Public/
|
||||||
|
done
|
167
boxes/build-debian-box.sh
Executable file
167
boxes/build-debian-box.sh
Executable file
|
@ -0,0 +1,167 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# set -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Script used to build Debian base vagrant-lxc containers, currently limited to
|
||||||
|
# host's arch
|
||||||
|
#
|
||||||
|
# USAGE:
|
||||||
|
# $ cd boxes && sudo ./build-debian-box.sh DEBIAN_RELEASE
|
||||||
|
#
|
||||||
|
# To enable Chef or any other configuration management tool pass '1' to the
|
||||||
|
# corresponding env var:
|
||||||
|
# $ CHEF=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE
|
||||||
|
# $ PUPPET=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE
|
||||||
|
# $ SALT=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE
|
||||||
|
# $ BABUSHKA=1 sudo -E ./build-debian-box.sh DEBIAN_RELEASE
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 0 - Initial setup and sanity checks
|
||||||
|
|
||||||
|
TODAY=$(date -u +"%Y-%m-%d")
|
||||||
|
NOW=$(date -u)
|
||||||
|
RELEASE=${1:-"wheezy"}
|
||||||
|
ARCH=$(dpkg --print-architecture) # This is what the Debian template will use under the hood
|
||||||
|
PKG=vagrant-lxc-${RELEASE}-${ARCH}-${TODAY}.box
|
||||||
|
WORKING_DIR=/tmp/vagrant-lxc-${RELEASE}
|
||||||
|
VAGRANT_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"
|
||||||
|
ROOTFS=/var/lib/lxc/${RELEASE}-base/rootfs
|
||||||
|
|
||||||
|
# Providing '1' will enable these tools
|
||||||
|
CHEF=${CHEF:-0}
|
||||||
|
PUPPET=${PUPPET:-0}
|
||||||
|
SALT=${SALT:-0}
|
||||||
|
BABUSHKA=${BABUSHKA:-0}
|
||||||
|
|
||||||
|
# Path to files bundled with the box
|
||||||
|
CWD=`readlink -f .`
|
||||||
|
LXC_TEMPLATE=${CWD}/common/lxc-template
|
||||||
|
LXC_CONF=${CWD}/common/lxc.conf
|
||||||
|
METATADA_JSON=${CWD}/common/metadata.json
|
||||||
|
|
||||||
|
# Set up a working dir
|
||||||
|
mkdir -p $WORKING_DIR
|
||||||
|
|
||||||
|
if [ -f "${WORKING_DIR}/${PKG}" ]; then
|
||||||
|
echo "Found a box on ${WORKING_DIR}/${PKG} already!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 1 - Create the base container
|
||||||
|
|
||||||
|
if $(lxc-ls | grep -q "${RELEASE}-base"); then
|
||||||
|
echo "Base container already exists, please remove it with \`lxc-destroy -n ${RELEASE}-base\`!"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
export SUITE=$RELEASE
|
||||||
|
lxc-create -n ${RELEASE}-base -t debian
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
######################################
|
||||||
|
# 2 - Fix some known issues
|
||||||
|
|
||||||
|
# Fixes some networking issues
|
||||||
|
# See https://github.com/fgrehm/vagrant-lxc/issues/91 for more info
|
||||||
|
sed -i -e "s/\(127.0.0.1\s\+localhost\)/\1\n127.0.1.1\t${RELEASE}-base\n/g" ${ROOTFS}/etc/hosts
|
||||||
|
|
||||||
|
# Ensures that `/tmp` does not get cleared on halt
|
||||||
|
# See https://github.com/fgrehm/vagrant-lxc/issues/68 for more info
|
||||||
|
chroot $ROOTFS /usr/sbin/update-rc.d -f checkroot-bootclean.sh remove
|
||||||
|
chroot $ROOTFS /usr/sbin/update-rc.d -f mountall-bootclean.sh remove
|
||||||
|
chroot $ROOTFS /usr/sbin/update-rc.d -f mountnfs-bootclean.sh remove
|
||||||
|
|
||||||
|
# Ensure locales are properly set, based on http://linux.livejournal.com/1880366.html
|
||||||
|
sed -i "s/^# en_US/en_US/" ${ROOTFS}/etc/locale.gen
|
||||||
|
chroot $ROOTFS /usr/sbin/locale-gen
|
||||||
|
chroot $ROOTFS update-locale LANG=en_US.UTF-8
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 3 - Prepare vagrant user
|
||||||
|
sudo chroot ${ROOTFS} useradd --create-home -s /bin/bash vagrant
|
||||||
|
|
||||||
|
echo -n 'vagrant:vagrant' | chroot ${ROOTFS} chpasswd
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 4 - Setup SSH access and passwordless sudo
|
||||||
|
|
||||||
|
# Configure SSH access
|
||||||
|
mkdir -p ${ROOTFS}/home/vagrant/.ssh
|
||||||
|
echo $VAGRANT_KEY > ${ROOTFS}/home/vagrant/.ssh/authorized_keys
|
||||||
|
chroot ${ROOTFS} chown -R vagrant: /home/vagrant/.ssh
|
||||||
|
|
||||||
|
chroot ${ROOTFS} apt-get install sudo -y --force-yes
|
||||||
|
chroot ${ROOTFS} adduser vagrant sudo
|
||||||
|
|
||||||
|
# Enable passwordless sudo for users under the "sudo" group
|
||||||
|
cp ${ROOTFS}/etc/sudoers{,.orig}
|
||||||
|
sed -i -e \
|
||||||
|
's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \
|
||||||
|
${ROOTFS}/etc/sudoers
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 5 - Add some goodies and update packages
|
||||||
|
|
||||||
|
PACKAGES=(vim curl wget man-db bash-completion ca-certificates)
|
||||||
|
chroot ${ROOTFS} apt-get install ${PACKAGES[*]} -y --force-yes
|
||||||
|
chroot ${ROOTFS} apt-get upgrade -y --force-yes
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 6 - Configuration management tools
|
||||||
|
|
||||||
|
if [ $CHEF = 1 ]; then
|
||||||
|
./common/install-chef $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $PUPPET = 1 ]; then
|
||||||
|
./common/install-puppet $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $SALT = 1 ]; then
|
||||||
|
./common/install-salt-debian $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $BABUSHKA = 1 ]; then
|
||||||
|
./common/install-babushka $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 7 - Free up some disk space
|
||||||
|
|
||||||
|
rm -rf ${ROOTFS}/tmp/*
|
||||||
|
chroot ${ROOTFS} apt-get clean
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 8 - Build box package
|
||||||
|
|
||||||
|
# Compress container's rootfs
|
||||||
|
cd $(dirname $ROOTFS)
|
||||||
|
tar --numeric-owner -czf /tmp/vagrant-lxc-${RELEASE}/rootfs.tar.gz ./rootfs/*
|
||||||
|
|
||||||
|
# Prepare package contents
|
||||||
|
cd $WORKING_DIR
|
||||||
|
cp $LXC_TEMPLATE .
|
||||||
|
cp $LXC_CONF .
|
||||||
|
cp $METATADA_JSON .
|
||||||
|
chmod +x lxc-template
|
||||||
|
sed -i "s/<TODAY>/${NOW}/" metadata.json
|
||||||
|
|
||||||
|
# Vagrant box!
|
||||||
|
tar -czf $PKG ./*
|
||||||
|
|
||||||
|
chmod +rw ${WORKING_DIR}/${PKG}
|
||||||
|
mkdir -p ${CWD}/output
|
||||||
|
mv ${WORKING_DIR}/${PKG} ${CWD}/output
|
||||||
|
|
||||||
|
# Clean up after ourselves
|
||||||
|
rm -rf ${WORKING_DIR}
|
||||||
|
|
||||||
|
echo "The base box was built successfully to ${CWD}/output/${PKG}"
|
159
boxes/build-openmandriva-box.sh
Normal file
159
boxes/build-openmandriva-box.sh
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# set -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Script used to build OpenMandriva base vagrant-lxc containers, currently limited to
|
||||||
|
# host's arch
|
||||||
|
#
|
||||||
|
# USAGE:
|
||||||
|
# $ cd boxes && sudo ./build-openmandriva-box.sh OPENMANDRIVA_RELEASE BOX_ARCH
|
||||||
|
#
|
||||||
|
# TODO: scripts for install CHEF, PUPPET, SALT, BABUSHKA
|
||||||
|
# To enable Chef or any other configuration management tool pass '1' to the
|
||||||
|
# corresponding env var:
|
||||||
|
# $ CHEF=1 sudo -E ./build-openmandriva-box.sh OPENMANDRIVA_RELEASE BOX_ARCH
|
||||||
|
# $ PUPPET=1 sudo -E ./build-openmandriva-box.sh OPENMANDRIVA_RELEASE BOX_ARCH
|
||||||
|
# $ SALT=1 sudo -E ./build-openmandriva-box.sh OPENMANDRIVA_RELEASE BOX_ARCH
|
||||||
|
# $ BABUSHKA=1 sudo -E ./build-openmandriva-box.sh OPENMANDRIVA_RELEASE BOX_ARCH
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 0 - Initial setup and sanity checks
|
||||||
|
|
||||||
|
TODAY=$(date -u +"%Y-%m-%d")
|
||||||
|
NOW=$(date -u)
|
||||||
|
RELEASE=${1:-"openmandriva2013.0"}
|
||||||
|
ARCH=${2:-"x86_64"}
|
||||||
|
PKG=vagrant-lxc-${RELEASE}-${ARCH}-${TODAY}.box
|
||||||
|
WORKING_DIR=/tmp/vagrant-lxc-${RELEASE}
|
||||||
|
VAGRANT_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"
|
||||||
|
ROOTFS=/var/lib/lxc/${RELEASE}-base/${RELEASE}-base/rootfs
|
||||||
|
|
||||||
|
# Providing '1' will enable these tools
|
||||||
|
CHEF=${CHEF:-0}
|
||||||
|
PUPPET=${PUPPET:-0}
|
||||||
|
SALT=${SALT:-0}
|
||||||
|
BABUSHKA=${BABUSHKA:-0}
|
||||||
|
|
||||||
|
# Path to files bundled with the box
|
||||||
|
CWD=`readlink -f .`
|
||||||
|
LXC_TEMPLATE=${CWD}/common/lxc-template-openmandriva
|
||||||
|
LXC_CONF=${CWD}/common/lxc.conf
|
||||||
|
METATADA_JSON=${CWD}/common/metadata.json
|
||||||
|
|
||||||
|
# Set up a working dir
|
||||||
|
mkdir -p $WORKING_DIR
|
||||||
|
|
||||||
|
if [ -f "${WORKING_DIR}/${PKG}" ]; then
|
||||||
|
echo "Found a box on ${WORKING_DIR}/${PKG} already!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 1 - Create the base container
|
||||||
|
|
||||||
|
if $(lxc-ls | grep -q "${RELEASE}-base"); then
|
||||||
|
echo "Base container already exists, please remove it with \`lxc-destroy -n ${RELEASE}-base\`!"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
export SUITE=$RELEASE
|
||||||
|
lxc-create -n ${RELEASE}-base -t openmandriva -- -R ${RELEASE} --arch ${ARCH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
######################################
|
||||||
|
# 2 - Fix some known issues
|
||||||
|
|
||||||
|
# Fixes some networking issues
|
||||||
|
cat /etc/resolv.conf > ${ROOTFS}/etc/resolv.conf
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 3 - Prepare vagrant user
|
||||||
|
chroot ${ROOTFS} su -c 'useradd --create-home -s /bin/bash vagrant'
|
||||||
|
|
||||||
|
# echo -n 'vagrant:vagrant' | chroot ${ROOTFS} chpasswd
|
||||||
|
chroot ${ROOTFS} su -c "echo -n 'vagrant:vagrant' | chpasswd"
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 4 - Setup SSH access and passwordless sudo
|
||||||
|
|
||||||
|
# Configure SSH access
|
||||||
|
mkdir -p ${ROOTFS}/home/vagrant/.ssh
|
||||||
|
echo $VAGRANT_KEY > ${ROOTFS}/home/vagrant/.ssh/authorized_keys
|
||||||
|
chroot ${ROOTFS} chown -R vagrant: /home/vagrant/.ssh
|
||||||
|
|
||||||
|
chroot ${ROOTFS} urpmi sudo --auto
|
||||||
|
chroot ${ROOTFS} usermod -a -G wheel vagrant
|
||||||
|
|
||||||
|
# Enable passwordless sudo for users under the "sudo" group
|
||||||
|
cp ${ROOTFS}/etc/sudoers{,.orig}
|
||||||
|
sed -i 's/Defaults requiretty/\# Defaults requiretty/' ${ROOTFS}/etc/sudoers
|
||||||
|
sed -i 's/\#%wheel/\%wheel/' ${ROOTFS}/etc/sudoers
|
||||||
|
sed -i 's/\# %wheel/\%wheel/' ${ROOTFS}/etc/sudoers
|
||||||
|
# sed -i -e \
|
||||||
|
# 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \
|
||||||
|
# ${ROOTFS}/etc/sudoers
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 5 - Add some goodies and update packages
|
||||||
|
|
||||||
|
PACKAGES=(vim curl wget man bash-completion openssh-server openssh-clients tar)
|
||||||
|
chroot ${ROOTFS} urpmi ${PACKAGES[*]} --auto
|
||||||
|
chroot ${ROOTFS} urpmi.update -a
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 6 - Configuration management tools
|
||||||
|
|
||||||
|
if [ $CHEF = 1 ]; then
|
||||||
|
./common/install-chef $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $PUPPET = 1 ]; then
|
||||||
|
./common/install-puppet $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $SALT = 1 ]; then
|
||||||
|
./common/install-salt $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $BABUSHKA = 1 ]; then
|
||||||
|
./common/install-babushka $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 7 - Free up some disk space
|
||||||
|
|
||||||
|
rm -rf ${ROOTFS}/tmp/*
|
||||||
|
# chroot ${ROOTFS} urpmi clean metadata
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 8 - Build box package
|
||||||
|
|
||||||
|
# Compress container's rootfs
|
||||||
|
cd $(dirname $ROOTFS)
|
||||||
|
tar --numeric-owner -czf /tmp/vagrant-lxc-${RELEASE}/rootfs.tar.gz ./rootfs/*
|
||||||
|
|
||||||
|
# Prepare package contents
|
||||||
|
cd $WORKING_DIR
|
||||||
|
cp $LXC_TEMPLATE lxc-template
|
||||||
|
cp $LXC_CONF .
|
||||||
|
cp $METATADA_JSON .
|
||||||
|
chmod +x lxc-template
|
||||||
|
sed -i "s/<TODAY>/${NOW}/" metadata.json
|
||||||
|
|
||||||
|
# Vagrant box!
|
||||||
|
tar -czf $PKG ./*
|
||||||
|
|
||||||
|
chmod +rw ${WORKING_DIR}/${PKG}
|
||||||
|
mkdir -p ${CWD}/output
|
||||||
|
mv ${WORKING_DIR}/${PKG} ${CWD}/output
|
||||||
|
|
||||||
|
# Clean up after ourselves
|
||||||
|
rm -rf ${WORKING_DIR}
|
||||||
|
|
||||||
|
echo "The base box was built successfully to ${CWD}/output/${PKG}"
|
151
boxes/build-ubuntu-box.sh
Executable file
151
boxes/build-ubuntu-box.sh
Executable file
|
@ -0,0 +1,151 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# set -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Script used to build Ubuntu base vagrant-lxc containers
|
||||||
|
#
|
||||||
|
# USAGE:
|
||||||
|
# $ cd boxes && sudo ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH
|
||||||
|
#
|
||||||
|
# To enable Chef or any other configuration management tool pass '1' to the
|
||||||
|
# corresponding env var:
|
||||||
|
# $ CHEF=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH
|
||||||
|
# $ PUPPET=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH
|
||||||
|
# $ SALT=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH
|
||||||
|
# $ BABUSHKA=1 sudo -E ./build-ubuntu-box.sh UBUNTU_RELEASE BOX_ARCH
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 0 - Initial setup and sanity checks
|
||||||
|
|
||||||
|
TODAY=$(date -u +"%Y-%m-%d")
|
||||||
|
NOW=$(date -u)
|
||||||
|
RELEASE=${1:-"raring"}
|
||||||
|
ARCH=${2:-"amd64"}
|
||||||
|
PKG=vagrant-lxc-${RELEASE}-${ARCH}-${TODAY}.box
|
||||||
|
WORKING_DIR=/tmp/vagrant-lxc-${RELEASE}
|
||||||
|
VAGRANT_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"
|
||||||
|
ROOTFS=/var/lib/lxc/${RELEASE}-base/rootfs
|
||||||
|
|
||||||
|
# Providing '1' will enable these tools
|
||||||
|
CHEF=${CHEF:-0}
|
||||||
|
PUPPET=${PUPPET:-0}
|
||||||
|
SALT=${SALT:-0}
|
||||||
|
BABUSHKA=${BABUSHKA:-0}
|
||||||
|
|
||||||
|
# Path to files bundled with the box
|
||||||
|
CWD=`readlink -f .`
|
||||||
|
LXC_TEMPLATE=${CWD}/common/lxc-template
|
||||||
|
LXC_CONF=${CWD}/common/lxc.conf
|
||||||
|
METATADA_JSON=${CWD}/common/metadata.json
|
||||||
|
|
||||||
|
# Set up a working dir
|
||||||
|
mkdir -p $WORKING_DIR
|
||||||
|
|
||||||
|
if [ -f "${WORKING_DIR}/${PKG}" ]; then
|
||||||
|
echo "Found a box on ${WORKING_DIR}/${PKG} already!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 1 - Create the base container
|
||||||
|
|
||||||
|
if $(lxc-ls | grep -q "${RELEASE}-base"); then
|
||||||
|
echo "Base container already exists, please remove it with \`lxc-destroy -n ${RELEASE}-base\`!"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
lxc-create -n ${RELEASE}-base -t ubuntu -- --release ${RELEASE} --arch ${ARCH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fixes some networking issues
|
||||||
|
# See https://github.com/fgrehm/vagrant-lxc/issues/91 for more info
|
||||||
|
echo 'ff02::3 ip6-allhosts' >> ${ROOTFS}/etc/hosts
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 2 - Prepare vagrant user
|
||||||
|
|
||||||
|
mv ${ROOTFS}/home/{ubuntu,vagrant}
|
||||||
|
chroot ${ROOTFS} usermod -l vagrant -d /home/vagrant ubuntu
|
||||||
|
chroot ${ROOTFS} groupmod -n vagrant ubuntu
|
||||||
|
|
||||||
|
echo -n 'vagrant:vagrant' | chroot ${ROOTFS} chpasswd
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 3 - Setup SSH access and passwordless sudo
|
||||||
|
|
||||||
|
# Configure SSH access
|
||||||
|
mkdir -p ${ROOTFS}/home/vagrant/.ssh
|
||||||
|
echo $VAGRANT_KEY > ${ROOTFS}/home/vagrant/.ssh/authorized_keys
|
||||||
|
chroot ${ROOTFS} chown -R vagrant: /home/vagrant/.ssh
|
||||||
|
|
||||||
|
# Enable passwordless sudo for users under the "sudo" group
|
||||||
|
cp ${ROOTFS}/etc/sudoers{,.orig}
|
||||||
|
sed -i -e \
|
||||||
|
's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' \
|
||||||
|
${ROOTFS}/etc/sudoers
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 4 - Add some goodies and update packages
|
||||||
|
|
||||||
|
PACKAGES=(vim curl wget man-db bash-completion)
|
||||||
|
chroot ${ROOTFS} apt-get install ${PACKAGES[*]} -y --force-yes
|
||||||
|
chroot ${ROOTFS} apt-get upgrade -y --force-yes
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 5 - Configuration management tools
|
||||||
|
|
||||||
|
if [ $CHEF = 1 ]; then
|
||||||
|
./common/install-chef $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $PUPPET = 1 ]; then
|
||||||
|
./common/install-puppet $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $SALT = 1 ]; then
|
||||||
|
./common/install-salt $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $BABUSHKA = 1 ]; then
|
||||||
|
./common/install-babushka $ROOTFS
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 6 - Free up some disk space
|
||||||
|
|
||||||
|
rm -rf ${ROOTFS}/tmp/*
|
||||||
|
chroot ${ROOTFS} apt-get clean
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################
|
||||||
|
# 7 - Build box package
|
||||||
|
|
||||||
|
# Compress container's rootfs
|
||||||
|
cd $(dirname $ROOTFS)
|
||||||
|
tar --numeric-owner -czf /tmp/vagrant-lxc-${RELEASE}/rootfs.tar.gz ./rootfs/*
|
||||||
|
|
||||||
|
# Prepare package contents
|
||||||
|
cd $WORKING_DIR
|
||||||
|
cp $LXC_TEMPLATE .
|
||||||
|
cp $LXC_CONF .
|
||||||
|
cp $METATADA_JSON .
|
||||||
|
chmod +x lxc-template
|
||||||
|
sed -i "s/<TODAY>/${NOW}/" metadata.json
|
||||||
|
|
||||||
|
# Vagrant box!
|
||||||
|
tar -czf $PKG ./*
|
||||||
|
|
||||||
|
chmod +rw ${WORKING_DIR}/${PKG}
|
||||||
|
mkdir -p ${CWD}/output
|
||||||
|
mv ${WORKING_DIR}/${PKG} ${CWD}/output
|
||||||
|
|
||||||
|
# Clean up after ourselves
|
||||||
|
rm -rf ${WORKING_DIR}
|
||||||
|
lxc-destroy -n ${RELEASE}-base
|
||||||
|
|
||||||
|
echo "The base box was built successfully to ${CWD}/output/${PKG}"
|
7
boxes/common/cleanup
Executable file
7
boxes/common/cleanup
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cache=`readlink -f .`
|
||||||
|
rootfs="${cache}/rootfs"
|
||||||
|
|
||||||
|
rm -rf $rootfs/tmp/*
|
||||||
|
chroot $rootfs apt-get clean
|
16
boxes/common/install-babushka
Executable file
16
boxes/common/install-babushka
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
rootfs=$1
|
||||||
|
|
||||||
|
echo "installing babushka"
|
||||||
|
cat > $rootfs/tmp/install-babushka.sh << EOF
|
||||||
|
#!/bin/sh
|
||||||
|
curl https://babushka.me/up | sudo bash
|
||||||
|
|
||||||
|
EOF
|
||||||
|
chmod +x $rootfs/tmp/install-babushka.sh
|
||||||
|
chroot $rootfs /tmp/install-babushka.sh
|
||||||
|
|
||||||
|
rm -rf $rootfs/tmp/*
|
15
boxes/common/install-chef
Executable file
15
boxes/common/install-chef
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
rootfs=$1
|
||||||
|
|
||||||
|
echo "installing chef"
|
||||||
|
cat > $rootfs/tmp/install-chef.sh << EOF
|
||||||
|
#!/bin/sh
|
||||||
|
curl -L https://www.opscode.com/chef/install.sh -k | sudo bash
|
||||||
|
EOF
|
||||||
|
chmod +x $rootfs/tmp/install-chef.sh
|
||||||
|
chroot $rootfs /tmp/install-chef.sh
|
||||||
|
|
||||||
|
rm -rf $rootfs/tmp/*
|
13
boxes/common/install-puppet
Executable file
13
boxes/common/install-puppet
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
rootfs=$1
|
||||||
|
|
||||||
|
echo "installing puppet"
|
||||||
|
wget http://apt.puppetlabs.com/puppetlabs-release-stable.deb -O "${rootfs}/tmp/puppetlabs-release-stable.deb"
|
||||||
|
chroot $rootfs dpkg -i "/tmp/puppetlabs-release-stable.deb"
|
||||||
|
chroot $rootfs apt-get update
|
||||||
|
chroot $rootfs apt-get install puppet -y --force-yes
|
||||||
|
|
||||||
|
rm -rf $rootfs/tmp/*
|
12
boxes/common/install-salt
Executable file
12
boxes/common/install-salt
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
rootfs=$1
|
||||||
|
|
||||||
|
echo "installing salt"
|
||||||
|
chroot $rootfs apt-add-repository -y ppa:saltstack/salt
|
||||||
|
chroot $rootfs apt-get update
|
||||||
|
chroot $rootfs apt-get install salt-minion -y --force-yes
|
||||||
|
|
||||||
|
rm -rf $rootfs/tmp/*
|
28
boxes/common/install-salt-debian
Executable file
28
boxes/common/install-salt-debian
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
rootfs=$1
|
||||||
|
|
||||||
|
echo "installing salt"
|
||||||
|
|
||||||
|
if [ $SUITE == "squeeze" ]; then
|
||||||
|
SALT_SOURCE="deb http://debian.saltstack.com/debian squeeze-saltstack main\ndeb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free"
|
||||||
|
elif [ $SUITE == "sid" ]; then
|
||||||
|
SALT_SOURCE="deb http://debian.saltstack.com/debian unstable main"
|
||||||
|
else
|
||||||
|
SALT_SOURCE="deb http://debian.saltstack.com/debian wheezy-saltstack main"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > $rootfs/tmp/install-salt << EOF
|
||||||
|
#!/bin/sh
|
||||||
|
echo "$SALT_SOURCE" > /etc/apt/sources.list.d/saltstack.list
|
||||||
|
wget -q -O- "http://debian.saltstack.com/debian-salt-team-joehealy.gpg.key" | apt-key add -
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y salt-minion
|
||||||
|
apt-get clean
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chroot $rootfs sh /tmp/install-salt
|
||||||
|
|
||||||
|
rm -rf $rootfs/tmp/*
|
226
boxes/common/lxc-template
Executable file
226
boxes/common/lxc-template
Executable file
|
@ -0,0 +1,226 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This is a modified version of /usr/share/lxc/templates/lxc-ubuntu
|
||||||
|
# that comes with Ubuntu 13.04 changed to suit vagrant-lxc needs
|
||||||
|
|
||||||
|
#
|
||||||
|
# template script for generating ubuntu container for LXC
|
||||||
|
#
|
||||||
|
# This script consolidates and extends the existing lxc ubuntu scripts
|
||||||
|
#
|
||||||
|
|
||||||
|
# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
|
||||||
|
# Copyright © 2010 Wilhelm Meier
|
||||||
|
# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License version 2, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -r /etc/default/lxc ]; then
|
||||||
|
. /etc/default/lxc
|
||||||
|
fi
|
||||||
|
|
||||||
|
extract_rootfs()
|
||||||
|
{
|
||||||
|
tarball=$1
|
||||||
|
arch=$2
|
||||||
|
rootfs=$3
|
||||||
|
|
||||||
|
echo "Extracting $tarball ..."
|
||||||
|
mkdir -p $rootfs
|
||||||
|
(cd $rootfs && tar xfz $tarball --strip-components=2)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
install_ubuntu()
|
||||||
|
{
|
||||||
|
rootfs=$1
|
||||||
|
release=$2
|
||||||
|
tarball=$3
|
||||||
|
mkdir -p /var/lock/subsys/
|
||||||
|
|
||||||
|
(
|
||||||
|
flock -x 200
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Cache repository is busy."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
extract_rootfs $tarball $arch $rootfs
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to copy rootfs"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
) 200>/var/lock/subsys/lxc
|
||||||
|
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_configuration()
|
||||||
|
{
|
||||||
|
path=$1
|
||||||
|
rootfs=$2
|
||||||
|
name=$3
|
||||||
|
|
||||||
|
grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
|
||||||
|
|
||||||
|
# if there is exactly one veth network entry, make sure it has an
|
||||||
|
# associated hwaddr.
|
||||||
|
nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
|
||||||
|
if [ $nics -eq 1 ]; then
|
||||||
|
grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to add configuration"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
post_process()
|
||||||
|
{
|
||||||
|
rootfs=$1
|
||||||
|
|
||||||
|
# rmdir /dev/shm for containers that have /run/shm
|
||||||
|
# I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
|
||||||
|
# get bind mounted to the host's /run/shm. So try to rmdir
|
||||||
|
# it, and in case that fails move it out of the way.
|
||||||
|
if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then
|
||||||
|
mv $rootfs/dev/shm $rootfs/dev/shm.bak
|
||||||
|
ln -s /run/shm $rootfs/dev/shm
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat <<EOF
|
||||||
|
$1 -h|--help [-a|--arch] [--trim] [-d|--debug] [--rootfs <rootfs>] [-T|--tarball <rootfs-tarball>
|
||||||
|
arch: the container architecture (e.g. amd64): defaults to host arch
|
||||||
|
EOF
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
options=$(getopt -o a:b:hp:r:xn:FS:d:C -l arch:,help,path:,release:,trim,name:,flush-cache,auth-key:,debug:,tarball:,rootfs: -- "$@")
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
usage $(basename $0)
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
eval set -- "$options"
|
||||||
|
|
||||||
|
release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems
|
||||||
|
if [ -f /etc/lsb-release ]; then
|
||||||
|
. /etc/lsb-release
|
||||||
|
if [ "$DISTRIB_ID" = "Ubuntu" ]; then
|
||||||
|
release=$DISTRIB_CODENAME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
arch=$(uname -m)
|
||||||
|
|
||||||
|
# Code taken from debootstrap
|
||||||
|
if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
|
||||||
|
arch=`/usr/bin/dpkg --print-architecture`
|
||||||
|
elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
|
||||||
|
arch=`/usr/bin/udpkg --print-architecture`
|
||||||
|
else
|
||||||
|
arch=$(uname -m)
|
||||||
|
if [ "$arch" = "i686" ]; then
|
||||||
|
arch="i386"
|
||||||
|
elif [ "$arch" = "x86_64" ]; then
|
||||||
|
arch="amd64"
|
||||||
|
elif [ "$arch" = "armv7l" ]; then
|
||||||
|
arch="armel"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
debug=0
|
||||||
|
trim_container=0
|
||||||
|
hostarch=$arch
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help) usage $0 && exit 0;;
|
||||||
|
--rootfs) rootfs=$2; shift 2;;
|
||||||
|
-p|--path) path=$2; shift 2;;
|
||||||
|
-n|--name) name=$2; shift 2;;
|
||||||
|
-T|--tarball) tarball=$2; shift 2;;
|
||||||
|
-a|--arch) arch=$2; shift 2;;
|
||||||
|
-S|--auth-key) auth_key=$2; shift 2;;
|
||||||
|
-d|--debug) debug=1; shift 1;;
|
||||||
|
--) shift 1; break ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $debug -eq 1 ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$arch" == "i686" ]; then
|
||||||
|
arch=i386
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
|
||||||
|
echo "can't create amd64 container on i386"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$path" ]; then
|
||||||
|
echo "'path' parameter is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(id -u)" != "0" ]; then
|
||||||
|
echo "This script should be run as 'root'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# detect rootfs
|
||||||
|
config="$path/config"
|
||||||
|
# if $rootfs exists here, it was passed in with --rootfs
|
||||||
|
if [ -z "$rootfs" ]; then
|
||||||
|
if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
|
||||||
|
rootfs=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'`
|
||||||
|
else
|
||||||
|
rootfs=$path/rootfs
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_ubuntu $rootfs $release $tarball
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "failed to install ubuntu $release"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
copy_configuration $path $rootfs $name $arch
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "failed write configuration file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
post_process $rootfs $release $trim_container
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "##"
|
||||||
|
echo "# The default user is 'vagrant' with password 'vagrant'!"
|
||||||
|
echo "# Use the 'sudo' command to run tasks as root in the container."
|
||||||
|
echo "##"
|
||||||
|
echo ""
|
225
boxes/common/lxc-template-openmandriva
Normal file
225
boxes/common/lxc-template-openmandriva
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This is a modified version of /usr/share/lxc/templates/lxc-openmandriva
|
||||||
|
# that comes with OpenMandriva changed to suit vagrant-lxc needs
|
||||||
|
|
||||||
|
#
|
||||||
|
# template script for generating openmandriva container for LXC
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# lxc: linux Container library
|
||||||
|
|
||||||
|
# Authors:
|
||||||
|
# Alexander Khryukin <alexander@mezon.ru>
|
||||||
|
# Vokhmin Alexey V <avokhmin@gmail.com>
|
||||||
|
|
||||||
|
# This library is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
# This library is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Lesser General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this library; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -r /etc/default/lxc ]; then
|
||||||
|
. /etc/default/lxc
|
||||||
|
fi
|
||||||
|
|
||||||
|
extract_rootfs()
|
||||||
|
{
|
||||||
|
tarball=$1
|
||||||
|
arch=$2
|
||||||
|
rootfs=$3
|
||||||
|
|
||||||
|
echo "Extracting $tarball ..."
|
||||||
|
mkdir -p $(dirname $rootfs)
|
||||||
|
(cd `dirname $rootfs` && tar xfz $tarball)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
install_openmandriva()
|
||||||
|
{
|
||||||
|
rootfs=$1
|
||||||
|
release=$2
|
||||||
|
tarball=$3
|
||||||
|
mkdir -p /var/lock/subsys/
|
||||||
|
|
||||||
|
(
|
||||||
|
flock -x 200
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Cache repository is busy."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
extract_rootfs $tarball $arch $rootfs
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to copy rootfs"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
) 200>/var/lock/subsys/lxc
|
||||||
|
|
||||||
|
return $?
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_configuration()
|
||||||
|
{
|
||||||
|
path=$1
|
||||||
|
rootfs=$2
|
||||||
|
name=$3
|
||||||
|
|
||||||
|
grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
|
||||||
|
|
||||||
|
# if there is exactly one veth network entry, make sure it has an
|
||||||
|
# associated hwaddr.
|
||||||
|
nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
|
||||||
|
if [ $nics -eq 1 ]; then
|
||||||
|
grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to add configuration"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
post_process()
|
||||||
|
{
|
||||||
|
rootfs=$1
|
||||||
|
|
||||||
|
# rmdir /dev/shm for containers that have /run/shm
|
||||||
|
# I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
|
||||||
|
# get bind mounted to the host's /run/shm. So try to rmdir
|
||||||
|
# it, and in case that fails move it out of the way.
|
||||||
|
if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then
|
||||||
|
mv $rootfs/dev/shm $rootfs/dev/shm.bak
|
||||||
|
ln -s /run/shm $rootfs/dev/shm
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat <<EOF
|
||||||
|
usage:
|
||||||
|
$1 -n|--name=<container_name>
|
||||||
|
[-p|--path=<path>] [-c|--clean] [-R|--release=<openmandriva2013.0/rosa2012.1/cooker/ release>]
|
||||||
|
[-4|--ipv4=<ipv4 address>] [-6|--ipv6=<ipv6 address>]
|
||||||
|
[-g|--gw=<gw address>] [-d|--dns=<dns address>]
|
||||||
|
[-P|--profile=<name of the profile>] [--rootfs=<path>]
|
||||||
|
[-A|--arch=<arch of the container>]
|
||||||
|
[-T|--tarball <tarball path>]
|
||||||
|
[-S|--auth-key <auth-key path>]
|
||||||
|
[-h|--help]
|
||||||
|
Mandatory args:
|
||||||
|
-n,--name container name, used to as an identifier for that container from now on
|
||||||
|
Optional args:
|
||||||
|
-p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc. The container config will go under /var/lib/lxc in that case
|
||||||
|
-c,--clean clean the cache
|
||||||
|
-R,--release openmandriva2013.0/cooker/rosa2012.1 release for the new container. if the host is OpenMandriva, then it will default to the host's release.
|
||||||
|
-4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24
|
||||||
|
-6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64
|
||||||
|
-g,--gw specify the default gw, eg. 192.168.1.1
|
||||||
|
-G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596
|
||||||
|
-d,--dns specify the DNS server, eg. 192.168.1.2
|
||||||
|
-P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache.
|
||||||
|
-A,--arch Define what arch the container will be [i586,x86_64,armv7l,armv7hl]
|
||||||
|
---rootfs rootfs path
|
||||||
|
-h,--help print this help
|
||||||
|
EOF
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
options=$(getopt -o hp:n:P:cR:4:6:g:d:A:S:T: -l help,rootfs:,path:,name:,profile:,clean:,release:,ipv4:,ipv6:,gw:,dns:,arch:,auth-key:,tarball: -- "$@")
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
usage $(basename $0)
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
eval set -- "$options"
|
||||||
|
|
||||||
|
# doesn't use
|
||||||
|
release=${release:-"cooker"}
|
||||||
|
|
||||||
|
hostarch=$(uname -m)
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help) usage $0 && exit 0;;
|
||||||
|
-p|--path) path=$2; shift 2;;
|
||||||
|
--rootfs) rootfs_path=$2; shift 2;;
|
||||||
|
-n|--name) name=$2; shift 2;;
|
||||||
|
-P|--profile) profile=$2; shift 2;;
|
||||||
|
-c|--clean) clean=$2; shift 2;;
|
||||||
|
-R|--release) release=$2; shift 2;;
|
||||||
|
-T|--tarball) tarball=$2; shift 2;;
|
||||||
|
-S|--auth-key) auth_key=$2; shift 2;;
|
||||||
|
-A|--arch) arch=$2; shift 2;;
|
||||||
|
-4|--ipv4) ipv4=$2; shift 2;;
|
||||||
|
-6|--ipv6) ipv6=$2; shift 2;;
|
||||||
|
-g|--gw) gw=$2; shift 2;;
|
||||||
|
-d|--dns) dns=$2; shift 2;;
|
||||||
|
--) shift 1; break ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
arch=${arch:-$hostarch}
|
||||||
|
if [ $hostarch = "i586" -a $arch = "x86_64" ]; then
|
||||||
|
echo "can't create x86_64 container on i586"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$path" ]; then
|
||||||
|
echo "'path' parameter is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(id -u)" != "0" ]; then
|
||||||
|
echo "This script should be run as 'root'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# detect rootfs
|
||||||
|
config="$path/config"
|
||||||
|
# if $rootfs exists here, it was passed in with --rootfs
|
||||||
|
if [ -z "$rootfs" ]; then
|
||||||
|
if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
|
||||||
|
rootfs=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'`
|
||||||
|
else
|
||||||
|
rootfs=$path/rootfs
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_openmandriva $rootfs $release $tarball
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "failed to install openmandriva $release"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
copy_configuration $path $rootfs $name $arch
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "failed write configuration file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
post_process $rootfs $release
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "##"
|
||||||
|
echo "# The default user is 'vagrant' with password 'vagrant'!"
|
||||||
|
echo "# Use the 'sudo' command to run tasks as root in the container."
|
||||||
|
echo "##"
|
||||||
|
echo ""
|
49
boxes/common/lxc.conf
Normal file
49
boxes/common/lxc.conf
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
lxc.network.type=veth
|
||||||
|
lxc.network.link=lxcbr0
|
||||||
|
lxc.network.flags=up
|
||||||
|
|
||||||
|
lxc.pivotdir = lxc_putold
|
||||||
|
|
||||||
|
lxc.devttydir = lxc
|
||||||
|
lxc.tty = 4
|
||||||
|
lxc.pts = 1024
|
||||||
|
|
||||||
|
lxc.arch = amd64
|
||||||
|
lxc.cap.drop = sys_module mac_admin mac_override
|
||||||
|
|
||||||
|
# When using LXC with apparmor, uncomment the next line to run unconfined:
|
||||||
|
#lxc.aa_profile = unconfined
|
||||||
|
|
||||||
|
lxc.cgroup.devices.deny = a
|
||||||
|
# Allow any mknod (but not using the node)
|
||||||
|
lxc.cgroup.devices.allow = c *:* m
|
||||||
|
lxc.cgroup.devices.allow = b *:* m
|
||||||
|
# /dev/null and zero
|
||||||
|
lxc.cgroup.devices.allow = c 1:3 rwm
|
||||||
|
lxc.cgroup.devices.allow = c 1:5 rwm
|
||||||
|
# consoles
|
||||||
|
lxc.cgroup.devices.allow = c 5:1 rwm
|
||||||
|
lxc.cgroup.devices.allow = c 5:0 rwm
|
||||||
|
#lxc.cgroup.devices.allow = c 4:0 rwm
|
||||||
|
#lxc.cgroup.devices.allow = c 4:1 rwm
|
||||||
|
# /dev/{,u}random
|
||||||
|
lxc.cgroup.devices.allow = c 1:9 rwm
|
||||||
|
lxc.cgroup.devices.allow = c 1:8 rwm
|
||||||
|
lxc.cgroup.devices.allow = c 136:* rwm
|
||||||
|
lxc.cgroup.devices.allow = c 5:2 rwm
|
||||||
|
# rtc
|
||||||
|
lxc.cgroup.devices.allow = c 254:0 rwm
|
||||||
|
#fuse
|
||||||
|
lxc.cgroup.devices.allow = c 10:229 rwm
|
||||||
|
#tun
|
||||||
|
lxc.cgroup.devices.allow = c 10:200 rwm
|
||||||
|
#full
|
||||||
|
lxc.cgroup.devices.allow = c 1:7 rwm
|
||||||
|
#hpet
|
||||||
|
lxc.cgroup.devices.allow = c 10:228 rwm
|
||||||
|
#kvm
|
||||||
|
lxc.cgroup.devices.allow = c 10:232 rwm
|
||||||
|
|
||||||
|
# mounts point
|
||||||
|
lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
|
||||||
|
lxc.mount.entry = sysfs sys sysfs defaults 0 0
|
5
boxes/common/metadata.json
Normal file
5
boxes/common/metadata.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"provider": "lxc",
|
||||||
|
"version": "3",
|
||||||
|
"built-on": "<TODAY>"
|
||||||
|
}
|
94
development/Vagrantfile
vendored
Normal file
94
development/Vagrantfile
vendored
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# -*- 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
|
||||||
|
config.cache.auto_detect = true
|
||||||
|
config.cache.enable_nfs = true
|
||||||
|
|
||||||
|
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
|
37
development/lxc-configs/lxc-dev-box
Normal file
37
development/lxc-configs/lxc-dev-box
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
###############################################################################
|
||||||
|
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
|
||||||
|
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
|
||||||
|
# which is likely to be running from the host machine
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# MIRROR to be used by ubuntu template at container creation:
|
||||||
|
# Leaving it undefined is fine
|
||||||
|
#MIRROR="http://archive.ubuntu.com/ubuntu"
|
||||||
|
# or
|
||||||
|
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
|
||||||
|
|
||||||
|
# LXC_AUTO - whether or not to start containers symlinked under
|
||||||
|
# /etc/lxc/auto
|
||||||
|
LXC_AUTO="true"
|
||||||
|
|
||||||
|
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
|
||||||
|
# containers. Set to "false" if you'll use virbr0 or another existing
|
||||||
|
# bridge, or mavlan to your host's NIC.
|
||||||
|
USE_LXC_BRIDGE="true"
|
||||||
|
|
||||||
|
# If you change the LXC_BRIDGE to something other than lxcbr1, then
|
||||||
|
# you will also need to update your /etc/lxc/lxc.conf as well as the
|
||||||
|
# configuration (/var/lib/lxc/<container>/config) for any containers
|
||||||
|
# already created using the default config to reflect the new bridge
|
||||||
|
# name.
|
||||||
|
# If you have the dnsmasq daemon installed, you'll also have to update
|
||||||
|
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
|
||||||
|
LXC_BRIDGE="lxcbr0"
|
||||||
|
LXC_ADDR="10.0.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
|
37
development/lxc-configs/sid
Normal file
37
development/lxc-configs/sid
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
###############################################################################
|
||||||
|
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
|
||||||
|
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
|
||||||
|
# which is likely to be running from the host machine
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# MIRROR to be used by ubuntu template at container creation:
|
||||||
|
# Leaving it undefined is fine
|
||||||
|
#MIRROR="http://archive.ubuntu.com/ubuntu"
|
||||||
|
# or
|
||||||
|
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
|
||||||
|
|
||||||
|
# LXC_AUTO - whether or not to start containers symlinked under
|
||||||
|
# /etc/lxc/auto
|
||||||
|
LXC_AUTO="true"
|
||||||
|
|
||||||
|
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
|
||||||
|
# containers. Set to "false" if you'll use virbr0 or another existing
|
||||||
|
# bridge, or mavlan to your host's NIC.
|
||||||
|
USE_LXC_BRIDGE="true"
|
||||||
|
|
||||||
|
# If you change the LXC_BRIDGE to something other than lxcbr1, then
|
||||||
|
# you will also need to update your /etc/lxc/lxc.conf as well as the
|
||||||
|
# configuration (/var/lib/lxc/<container>/config) for any containers
|
||||||
|
# already created using the default config to reflect the new bridge
|
||||||
|
# name.
|
||||||
|
# If you have the dnsmasq daemon installed, you'll also have to update
|
||||||
|
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
|
||||||
|
LXC_BRIDGE="lxcbr0"
|
||||||
|
LXC_ADDR="10.0.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
|
37
development/lxc-configs/squeeze
Normal file
37
development/lxc-configs/squeeze
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
###############################################################################
|
||||||
|
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
|
||||||
|
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
|
||||||
|
# which is likely to be running from the host machine
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# MIRROR to be used by ubuntu template at container creation:
|
||||||
|
# Leaving it undefined is fine
|
||||||
|
#MIRROR="http://archive.ubuntu.com/ubuntu"
|
||||||
|
# or
|
||||||
|
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
|
||||||
|
|
||||||
|
# LXC_AUTO - whether or not to start containers symlinked under
|
||||||
|
# /etc/lxc/auto
|
||||||
|
LXC_AUTO="true"
|
||||||
|
|
||||||
|
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
|
||||||
|
# containers. Set to "false" if you'll use virbr0 or another existing
|
||||||
|
# bridge, or mavlan to your host's NIC.
|
||||||
|
USE_LXC_BRIDGE="true"
|
||||||
|
|
||||||
|
# If you change the LXC_BRIDGE to something other than lxcbr1, then
|
||||||
|
# you will also need to update your /etc/lxc/lxc.conf as well as the
|
||||||
|
# configuration (/var/lib/lxc/<container>/config) for any containers
|
||||||
|
# already created using the default config to reflect the new bridge
|
||||||
|
# name.
|
||||||
|
# If you have the dnsmasq daemon installed, you'll also have to update
|
||||||
|
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
|
||||||
|
LXC_BRIDGE="lxcbr0"
|
||||||
|
LXC_ADDR="10.0.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
|
37
development/lxc-configs/vbox
Normal file
37
development/lxc-configs/vbox
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
###############################################################################
|
||||||
|
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
|
||||||
|
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
|
||||||
|
# which is likely to be running from the host machine
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# MIRROR to be used by ubuntu template at container creation:
|
||||||
|
# Leaving it undefined is fine
|
||||||
|
#MIRROR="http://archive.ubuntu.com/ubuntu"
|
||||||
|
# or
|
||||||
|
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
|
||||||
|
|
||||||
|
# LXC_AUTO - whether or not to start containers symlinked under
|
||||||
|
# /etc/lxc/auto
|
||||||
|
LXC_AUTO="true"
|
||||||
|
|
||||||
|
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
|
||||||
|
# containers. Set to "false" if you'll use virbr0 or another existing
|
||||||
|
# bridge, or mavlan to your host's NIC.
|
||||||
|
USE_LXC_BRIDGE="true"
|
||||||
|
|
||||||
|
# If you change the LXC_BRIDGE to something other than lxcbr1, then
|
||||||
|
# you will also need to update your /etc/lxc/lxc.conf as well as the
|
||||||
|
# configuration (/var/lib/lxc/<container>/config) for any containers
|
||||||
|
# already created using the default config to reflect the new bridge
|
||||||
|
# name.
|
||||||
|
# If you have the dnsmasq daemon installed, you'll also have to update
|
||||||
|
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
|
||||||
|
LXC_BRIDGE="lxcbr0"
|
||||||
|
LXC_ADDR="10.0.254.1"
|
||||||
|
LXC_NETMASK="255.255.255.0"
|
||||||
|
LXC_NETWORK="10.0.254.0/24"
|
||||||
|
LXC_DHCP_RANGE="10.0.254.2,10.0.254.254"
|
||||||
|
LXC_DHCP_MAX="253"
|
||||||
|
|
||||||
|
LXC_SHUTDOWN_TIMEOUT=120
|
37
development/lxc-configs/wheezy
Normal file
37
development/lxc-configs/wheezy
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
###############################################################################
|
||||||
|
# This file has the same configs as the built in /etc/default/lxc on Ubuntu,
|
||||||
|
# we only changed IPs to 10.0.254.* to avoid collision with LXC default 10.0.3.*
|
||||||
|
# which is likely to be running from the host machine
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# MIRROR to be used by ubuntu template at container creation:
|
||||||
|
# Leaving it undefined is fine
|
||||||
|
#MIRROR="http://archive.ubuntu.com/ubuntu"
|
||||||
|
# or
|
||||||
|
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"
|
||||||
|
|
||||||
|
# LXC_AUTO - whether or not to start containers symlinked under
|
||||||
|
# /etc/lxc/auto
|
||||||
|
LXC_AUTO="true"
|
||||||
|
|
||||||
|
# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
|
||||||
|
# containers. Set to "false" if you'll use virbr0 or another existing
|
||||||
|
# bridge, or mavlan to your host's NIC.
|
||||||
|
USE_LXC_BRIDGE="true"
|
||||||
|
|
||||||
|
# If you change the LXC_BRIDGE to something other than lxcbr1, then
|
||||||
|
# you will also need to update your /etc/lxc/lxc.conf as well as the
|
||||||
|
# configuration (/var/lib/lxc/<container>/config) for any containers
|
||||||
|
# already created using the default config to reflect the new bridge
|
||||||
|
# name.
|
||||||
|
# If you have the dnsmasq daemon installed, you'll also have to update
|
||||||
|
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
|
||||||
|
LXC_BRIDGE="lxcbr0"
|
||||||
|
LXC_ADDR="10.0.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
|
151
development/site.pp
Normal file
151
development/site.pp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
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(' ')"
|
||||||
|
}
|
|
@ -1,10 +1,2 @@
|
||||||
require "vagrant-lxc/version"
|
require "vagrant-lxc/version"
|
||||||
require "vagrant-lxc/plugin"
|
require "vagrant-lxc/plugin"
|
||||||
|
|
||||||
module Vagrant
|
|
||||||
module LXC
|
|
||||||
def self.source_root
|
|
||||||
@source_root ||= Pathname.new(File.dirname(__FILE__)).join('..').expand_path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,20 +1,30 @@
|
||||||
require 'vagrant-lxc/action/boot'
|
require 'vagrant-lxc/action/boot'
|
||||||
|
require 'vagrant-lxc/action/check_created'
|
||||||
|
require 'vagrant-lxc/action/check_running'
|
||||||
require 'vagrant-lxc/action/clear_forwarded_ports'
|
require 'vagrant-lxc/action/clear_forwarded_ports'
|
||||||
require 'vagrant-lxc/action/create'
|
require 'vagrant-lxc/action/create'
|
||||||
|
require 'vagrant-lxc/action/created'
|
||||||
require 'vagrant-lxc/action/destroy'
|
require 'vagrant-lxc/action/destroy'
|
||||||
require 'vagrant-lxc/action/destroy_confirm'
|
require 'vagrant-lxc/action/destroy_confirm'
|
||||||
|
require 'vagrant-lxc/action/disconnect'
|
||||||
require 'vagrant-lxc/action/compress_rootfs'
|
require 'vagrant-lxc/action/compress_rootfs'
|
||||||
require 'vagrant-lxc/action/fetch_ip_with_lxc_info'
|
require 'vagrant-lxc/action/fetch_ip_with_lxc_attach'
|
||||||
|
require 'vagrant-lxc/action/fetch_ip_from_dnsmasq_leases'
|
||||||
require 'vagrant-lxc/action/forced_halt'
|
require 'vagrant-lxc/action/forced_halt'
|
||||||
require 'vagrant-lxc/action/forward_ports'
|
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/handle_box_metadata'
|
||||||
require 'vagrant-lxc/action/prepare_nfs_settings'
|
require 'vagrant-lxc/action/is_running'
|
||||||
require 'vagrant-lxc/action/prepare_nfs_valid_ids'
|
require 'vagrant-lxc/action/message'
|
||||||
require 'vagrant-lxc/action/private_networks'
|
require 'vagrant-lxc/action/remove_temporary_files'
|
||||||
require 'vagrant-lxc/action/setup_package_files'
|
require 'vagrant-lxc/action/setup_package_files'
|
||||||
|
require 'vagrant-lxc/action/share_folders'
|
||||||
require 'vagrant-lxc/action/warn_networks'
|
require 'vagrant-lxc/action/warn_networks'
|
||||||
|
|
||||||
|
unless Vagrant::LXC.vagrant_1_3_or_later
|
||||||
|
require 'vagrant-lxc/action/wait_for_communicator'
|
||||||
|
Vagrant::Action::Builtin.const_set :WaitForCommunicator, Vagrant::LXC::Action::WaitForCommunicator
|
||||||
|
end
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
module Action
|
module Action
|
||||||
|
@ -27,9 +37,9 @@ module Vagrant
|
||||||
# machine back up with the new configuration.
|
# machine back up with the new configuration.
|
||||||
def self.action_reload
|
def self.action_reload
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2|
|
b.use Builtin::Call, Created do |env1, b2|
|
||||||
if env1[:result]
|
if !env1[:result]
|
||||||
b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created")
|
b2.use Message, :not_created
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,14 +57,10 @@ module Vagrant
|
||||||
b.use Builtin::Provision
|
b.use Builtin::Provision
|
||||||
b.use Builtin::EnvSet, :port_collision_repair => true
|
b.use Builtin::EnvSet, :port_collision_repair => true
|
||||||
b.use Builtin::HandleForwardedPortCollisions
|
b.use Builtin::HandleForwardedPortCollisions
|
||||||
b.use PrepareNFSValidIds
|
b.use ShareFolders
|
||||||
b.use Builtin::SyncedFolderCleanup
|
|
||||||
b.use Builtin::SyncedFolders
|
|
||||||
b.use PrepareNFSSettings
|
|
||||||
b.use Builtin::SetHostname
|
b.use Builtin::SetHostname
|
||||||
b.use WarnNetworks
|
b.use WarnNetworks
|
||||||
b.use ForwardPorts
|
b.use ForwardPorts
|
||||||
b.use PrivateNetworks
|
|
||||||
b.use Boot
|
b.use Boot
|
||||||
b.use Builtin::WaitForCommunicator
|
b.use Builtin::WaitForCommunicator
|
||||||
end
|
end
|
||||||
|
@ -64,15 +70,15 @@ module Vagrant
|
||||||
def self.action_provision
|
def self.action_provision
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::ConfigValidate
|
b.use Builtin::ConfigValidate
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2|
|
b.use Builtin::Call, Created do |env1, b2|
|
||||||
if env1[:result]
|
if !env1[:result]
|
||||||
b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created")
|
b2.use Message, :not_created
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
b2.use Builtin::Call, Builtin::IsState, :running do |env2, b3|
|
b2.use Builtin::Call, IsRunning do |env2, b3|
|
||||||
if !env2[:result]
|
if !env2[:result]
|
||||||
b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running")
|
b3.use Message, :not_running
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -87,8 +93,7 @@ module Vagrant
|
||||||
def self.action_start
|
def self.action_start
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::ConfigValidate
|
b.use Builtin::ConfigValidate
|
||||||
b.use Builtin::BoxCheckOutdated
|
b.use Builtin::Call, IsRunning do |env, b2|
|
||||||
b.use Builtin::Call, Builtin::IsState, :running do |env, b2|
|
|
||||||
# If the VM is running, then our work here is done, exit
|
# If the VM is running, then our work here is done, exit
|
||||||
next if env[:result]
|
next if env[:result]
|
||||||
b2.use action_boot
|
b2.use action_boot
|
||||||
|
@ -101,10 +106,10 @@ module Vagrant
|
||||||
def self.action_up
|
def self.action_up
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::ConfigValidate
|
b.use Builtin::ConfigValidate
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2|
|
b.use Builtin::Call, Created do |env, b2|
|
||||||
# If the VM is NOT created yet, then do the setup steps
|
# If the VM is NOT created yet, then do the setup steps
|
||||||
if env[:result]
|
if !env[:result]
|
||||||
b2.use Builtin::HandleBox
|
b2.use Builtin::HandleBoxUrl
|
||||||
b2.use HandleBoxMetadata
|
b2.use HandleBoxMetadata
|
||||||
b2.use Create
|
b2.use Create
|
||||||
end
|
end
|
||||||
|
@ -117,18 +122,19 @@ module Vagrant
|
||||||
# the virtual machine, gracefully or by force.
|
# the virtual machine, gracefully or by force.
|
||||||
def self.action_halt
|
def self.action_halt
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2|
|
b.use Builtin::Call, Created do |env, b2|
|
||||||
if env[:result]
|
if env[:result]
|
||||||
b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created")
|
# TODO: Remove once we drop support for vagrant 1.1
|
||||||
next
|
b2.use Disconnect
|
||||||
end
|
b2.use ClearForwardedPorts
|
||||||
|
b2.use RemoveTemporaryFiles
|
||||||
b2.use ClearForwardedPorts
|
b2.use Builtin::Call, Builtin::GracefulHalt, :stopped, :running do |env2, b3|
|
||||||
b2.use GcPrivateNetworkBridges
|
if !env2[:result]
|
||||||
b2.use Builtin::Call, Builtin::GracefulHalt, :stopped, :running do |env2, b3|
|
b3.use ForcedHalt
|
||||||
if !env2[:result]
|
end
|
||||||
b3.use ForcedHalt
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
b2.use Message, :not_created
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -138,21 +144,24 @@ module Vagrant
|
||||||
# freeing the resources of the underlying virtual machine.
|
# freeing the resources of the underlying virtual machine.
|
||||||
def self.action_destroy
|
def self.action_destroy
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2|
|
b.use Builtin::Call, Created do |env1, b2|
|
||||||
if env1[:result]
|
if !env1[:result]
|
||||||
b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created")
|
b2.use Message, :not_created
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: Use Vagrant's built in action once we drop support for vagrant 1.2
|
||||||
b2.use Builtin::Call, DestroyConfirm do |env2, b3|
|
b2.use Builtin::Call, DestroyConfirm do |env2, b3|
|
||||||
if env2[:result]
|
if env2[:result]
|
||||||
b3.use Builtin::ConfigValidate
|
b3.use Builtin::ConfigValidate
|
||||||
b3.use Builtin::EnvSet, :force_halt => true
|
b3.use Builtin::EnvSet, :force_halt => true
|
||||||
b3.use action_halt
|
b3.use action_halt
|
||||||
b3.use Destroy
|
b3.use Destroy
|
||||||
b3.use Builtin::ProvisionerCleanup
|
if Vagrant::LXC.vagrant_1_3_or_later
|
||||||
|
b3.use Builtin::ProvisionerCleanup
|
||||||
|
end
|
||||||
else
|
else
|
||||||
b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.will_not_destroy")
|
b3.use Message, :will_not_destroy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -162,9 +171,9 @@ module Vagrant
|
||||||
# This action packages the virtual machine into a single box file.
|
# This action packages the virtual machine into a single box file.
|
||||||
def self.action_package
|
def self.action_package
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env1, b2|
|
b.use Builtin::Call, Created do |env1, b2|
|
||||||
if env1[:result]
|
if !env1[:result]
|
||||||
b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created")
|
b2.use Message, :not_created
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -178,55 +187,29 @@ module Vagrant
|
||||||
|
|
||||||
# This action is called to read the IP of the container. The IP found
|
# This action is called to read the IP of the container. The IP found
|
||||||
# is expected to be put into the `:machine_ip` key.
|
# is expected to be put into the `:machine_ip` key.
|
||||||
def self.action_ssh_ip
|
def self.action_fetch_ip
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::Call, Builtin::ConfigValidate do |env, b2|
|
b.use Builtin::ConfigValidate
|
||||||
b2.use FetchIpWithLxcInfo
|
b.use FetchIpWithLxcAttach
|
||||||
end
|
b.use FetchIpFromDnsmasqLeases
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is the action that will exec into an SSH shell.
|
# This is the action that will exec into an SSH shell.
|
||||||
def self.action_ssh
|
def self.action_ssh
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::ConfigValidate
|
b.use CheckCreated
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2|
|
b.use CheckRunning
|
||||||
if env[:result]
|
b.use Builtin::SSHExec
|
||||||
b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
b2.use Builtin::Call, Builtin::IsState, :running do |env1, b3|
|
|
||||||
if !env1[:result]
|
|
||||||
b3.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_running")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
b3.use Builtin::SSHExec
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is the action that will run a single SSH command.
|
# This is the action that will run a single SSH command.
|
||||||
def self.action_ssh_run
|
def self.action_ssh_run
|
||||||
Builder.new.tap do |b|
|
Builder.new.tap do |b|
|
||||||
b.use Builtin::ConfigValidate
|
b.use CheckCreated
|
||||||
b.use Builtin::Call, Builtin::IsState, :not_created do |env, b2|
|
b.use CheckRunning
|
||||||
if env[:result]
|
b.use Builtin::SSHRun
|
||||||
b2.use Builtin::Message, I18n.t("vagrant_lxc.messages.not_created")
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
b2.use Builtin::Call, Builtin::IsState, :running do |env1, b3|
|
|
||||||
if !env1[:result]
|
|
||||||
raise Vagrant::Errors::VMNotRunningError
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
b3.use Builtin::SSHRun
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,35 +8,13 @@ module Vagrant
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
@env = env
|
@env = env
|
||||||
driver = env[:machine].provider.driver
|
|
||||||
config = env[:machine].provider_config
|
config = env[:machine].provider_config
|
||||||
|
|
||||||
utsname = env[:machine].config.vm.hostname || env[:machine].id
|
config.customize 'utsname', env[:machine].id
|
||||||
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[:ui].info I18n.t("vagrant_lxc.messages.starting")
|
||||||
driver.start(config.customizations)
|
env[:machine].provider.driver.start(config.customizations)
|
||||||
|
|
||||||
@app.call env
|
@app.call env
|
||||||
end
|
end
|
||||||
|
|
21
lib/vagrant-lxc/action/check_created.rb
Normal file
21
lib/vagrant-lxc/action/check_created.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
module Action
|
||||||
|
class CheckCreated
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
if env[:machine].state.id == :not_created
|
||||||
|
raise Vagrant::Errors::VMNotCreatedError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Call the next if we have one (but we shouldn't, since this
|
||||||
|
# middleware is built to run with the Call-type middlewares)
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
lib/vagrant-lxc/action/check_running.rb
Normal file
21
lib/vagrant-lxc/action/check_running.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
module Action
|
||||||
|
class CheckRunning
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
if env[:machine].state.id != :running
|
||||||
|
raise Vagrant::Errors::VMNotRunningError
|
||||||
|
end
|
||||||
|
|
||||||
|
# Call the next if we have one (but we shouldn't, since this
|
||||||
|
# middleware is built to run with the Call-type middlewares)
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,13 +13,9 @@ module Vagrant
|
||||||
if redir_pids.any?
|
if redir_pids.any?
|
||||||
env[:ui].info I18n.t("vagrant.actions.vm.clear_forward_ports.deleting")
|
env[:ui].info I18n.t("vagrant.actions.vm.clear_forward_ports.deleting")
|
||||||
redir_pids.each do |pid|
|
redir_pids.each do |pid|
|
||||||
next unless is_redir_pid?(pid[0])
|
next unless is_redir_pid?(pid)
|
||||||
@logger.debug "Killing pid #{pid[0]}"
|
@logger.debug "Killing pid #{pid}"
|
||||||
if pid[1]
|
system "pkill -TERM -P #{pid}"
|
||||||
system "sudo pkill -TERM -P #{pid[0]}"
|
|
||||||
else
|
|
||||||
system "pkill -TERM -P #{pid[0]}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@logger.info "Removing redir pids files"
|
@logger.info "Removing redir pids files"
|
||||||
|
@ -35,8 +31,7 @@ module Vagrant
|
||||||
|
|
||||||
def redir_pids
|
def redir_pids
|
||||||
@redir_pids = Dir[@env[:machine].data_dir.join('pids').to_s + "/redir_*.pid"].map do |file|
|
@redir_pids = Dir[@env[:machine].data_dir.join('pids').to_s + "/redir_*.pid"].map do |file|
|
||||||
port_number = File.basename(file).split(/[^\d]/).join
|
File.read(file).strip.chomp
|
||||||
[ File.read(file).strip.chomp , Integer(port_number) <= 1024 ]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
config = env[:machine].provider_config
|
container_name = env[:machine].provider_config.container_name
|
||||||
container_name = config.container_name
|
|
||||||
|
|
||||||
case container_name
|
case container_name
|
||||||
when :machine
|
when :machine
|
||||||
|
@ -16,49 +15,24 @@ module Vagrant
|
||||||
when String
|
when String
|
||||||
# Nothing to do here, move along...
|
# Nothing to do here, move along...
|
||||||
else
|
else
|
||||||
container_name = 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)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
backingstore = config.backingstore
|
env[:machine].provider.driver.create(
|
||||||
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,
|
container_name,
|
||||||
backingstore,
|
|
||||||
config.backingstore_options,
|
|
||||||
env[:lxc_template_src],
|
env[:lxc_template_src],
|
||||||
env[:lxc_template_config],
|
env[:lxc_template_config],
|
||||||
template_options
|
env[:lxc_template_opts]
|
||||||
)
|
)
|
||||||
driver.update_config_keys
|
|
||||||
|
|
||||||
env[:machine].id = container_name
|
env[:machine].id = container_name
|
||||||
|
|
||||||
@app.call env
|
@app.call env
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_container_name(env)
|
|
||||||
container_name = "#{env[:root_path].basename}_#{env[:machine].name}"
|
|
||||||
container_name.gsub!(/[^-a-z0-9_]/i, "")
|
|
||||||
|
|
||||||
# milliseconds + random number suffix to allow for simultaneous
|
|
||||||
# `vagrant up` of the same box in different dirs
|
|
||||||
container_name << "_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
|
|
||||||
|
|
||||||
# Trim container name to 64 chars, keeping "randomness"
|
|
||||||
trim_point = container_name.size > 64 ? -64 : -(container_name.size)
|
|
||||||
container_name[trim_point..-1]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
20
lib/vagrant-lxc/action/created.rb
Normal file
20
lib/vagrant-lxc/action/created.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
module Action
|
||||||
|
class Created
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
# Set the result to be true if the machine is created.
|
||||||
|
env[:result] = env[:machine].state.id != :not_created
|
||||||
|
|
||||||
|
# Call the next if we have one (but we shouldn't, since this
|
||||||
|
# middleware is built to run with the Call-type middlewares)
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
18
lib/vagrant-lxc/action/disconnect.rb
Normal file
18
lib/vagrant-lxc/action/disconnect.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
module Action
|
||||||
|
class Disconnect
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
@app.call env
|
||||||
|
# FIXME: Vagrant >= 1.1.3 should not need this
|
||||||
|
# https://github.com/mitchellh/vagrant/compare/715539eac30bc9ae62ddbb6337d13f036f7b774d...ec1bae0#L2R128
|
||||||
|
env[:machine].instance_variable_set(:@communicator, nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
48
lib/vagrant-lxc/action/fetch_ip_from_dnsmasq_leases.rb
Normal file
48
lib/vagrant-lxc/action/fetch_ip_from_dnsmasq_leases.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
def read_dnsmasq_leases
|
||||||
|
Dir["{#{LEASES_PATHS.join(',')}}"].map do |file|
|
||||||
|
File.read(file)
|
||||||
|
end.join("\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,31 +1,30 @@
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
module Action
|
module Action
|
||||||
class FetchIpWithLxcInfo
|
class FetchIpWithLxcAttach
|
||||||
# Include this so we can use `Subprocess` more easily.
|
# Include this so we can use `Subprocess` more easily.
|
||||||
include Vagrant::Util::Retryable
|
include Vagrant::Util::Retryable
|
||||||
|
|
||||||
def initialize(app, env)
|
def initialize(app, env)
|
||||||
@app = app
|
@app = app
|
||||||
@logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_with_lxc_info")
|
@logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_with_lxc_attach")
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
env[:machine_ip] ||= assigned_ip(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
|
ensure
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
def assigned_ip(env)
|
def assigned_ip(env)
|
||||||
config = env[:machine].provider_config
|
|
||||||
fetch_ip_tries = config.fetch_ip_tries
|
|
||||||
driver = env[:machine].provider.driver
|
driver = env[:machine].provider.driver
|
||||||
ip = ''
|
ip = ''
|
||||||
return config.ssh_ip_addr if not config.ssh_ip_addr.nil?
|
retryable(:on => LXC::Errors::ExecuteError, :tries => 10, :sleep => 3) do
|
||||||
retryable(:on => LXC::Errors::ExecuteError, :tries => fetch_ip_tries, :sleep => 3) do
|
|
||||||
unless ip = get_container_ip_from_ip_addr(driver)
|
unless ip = get_container_ip_from_ip_addr(driver)
|
||||||
# retry
|
# retry
|
||||||
raise LXC::Errors::ExecuteError, :command => "lxc-info"
|
raise LXC::Errors::ExecuteError, :command => "lxc-attach"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ip
|
ip
|
||||||
|
@ -33,8 +32,8 @@ module Vagrant
|
||||||
|
|
||||||
# From: https://github.com/lxc/lxc/blob/staging/src/python-lxc/lxc/__init__.py#L371-L385
|
# From: https://github.com/lxc/lxc/blob/staging/src/python-lxc/lxc/__init__.py#L371-L385
|
||||||
def get_container_ip_from_ip_addr(driver)
|
def get_container_ip_from_ip_addr(driver)
|
||||||
output = driver.info '-iH'
|
output = driver.attach '/sbin/ip', '-4', 'addr', 'show', 'scope', 'global', 'eth0', namespaces: 'network'
|
||||||
if output =~ /^([0-9.]+)/
|
if output =~ /^\s+inet ([0-9.]+)\/[0-9]+\s+/
|
||||||
return $1.to_s
|
return $1.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,5 +1,3 @@
|
||||||
require 'open3'
|
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
module Action
|
module Action
|
||||||
|
@ -69,9 +67,7 @@ module Vagrant
|
||||||
|
|
||||||
# TODO: Deprecate this behavior of "automagically" skipping ssh forwarded ports
|
# TODO: Deprecate this behavior of "automagically" skipping ssh forwarded ports
|
||||||
if type == :forwarded_port && options[:id] != 'ssh'
|
if type == :forwarded_port && options[:id] != 'ssh'
|
||||||
if options.fetch(:host_ip, '').to_s.strip.empty?
|
options.delete(:host_ip) if options.fetch(:host_ip, '').to_s.strip.empty?
|
||||||
options[:host_ip] = '127.0.0.1'
|
|
||||||
end
|
|
||||||
mappings[options[:host]] = options
|
mappings[options[:host]] = options
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -80,18 +76,11 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirect_port(host_ip, host_port, guest_ip, guest_port)
|
def redirect_port(host_ip, host_port, guest_ip, guest_port)
|
||||||
if redir_version >= 3
|
params = %W( --lport=#{host_port} --caddr=#{guest_ip} --cport=#{guest_port} )
|
||||||
params = %W( -n #{host_ip}:#{host_port} #{guest_ip}:#{guest_port} )
|
params.unshift "--laddr=#{host_ip}" if host_ip
|
||||||
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']
|
params << '--syslog' if ENV['REDIR_LOG']
|
||||||
if host_port < 1024
|
redir_cmd = "redir #{params.join(' ')} 2>/dev/null"
|
||||||
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}`"
|
@logger.debug "Forwarding port with `#{redir_cmd}`"
|
||||||
spawn redir_cmd
|
spawn redir_cmd
|
||||||
end
|
end
|
||||||
|
@ -105,13 +94,6 @@ module Vagrant
|
||||||
end
|
end
|
||||||
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?
|
def redir_installed?
|
||||||
system "which redir > /dev/null"
|
system "which redir > /dev/null"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
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
|
|
|
@ -3,8 +3,7 @@ module Vagrant
|
||||||
module Action
|
module Action
|
||||||
# Prepare arguments to be used for lxc-create
|
# Prepare arguments to be used for lxc-create
|
||||||
class HandleBoxMetadata
|
class HandleBoxMetadata
|
||||||
SUPPORTED_VERSIONS = ['1.0.0', '2', '3']
|
SUPPORTED_VERSIONS = [2, 3]
|
||||||
|
|
||||||
def initialize(app, env)
|
def initialize(app, env)
|
||||||
@app = app
|
@app = app
|
||||||
@logger = Log4r::Logger.new("vagrant::lxc::action::handle_box_metadata")
|
@logger = Log4r::Logger.new("vagrant::lxc::action::handle_box_metadata")
|
||||||
|
@ -17,53 +16,34 @@ module Vagrant
|
||||||
@env[:ui].info I18n.t("vagrant.actions.vm.import.importing",
|
@env[:ui].info I18n.t("vagrant.actions.vm.import.importing",
|
||||||
:name => @env[:machine].box.name)
|
:name => @env[:machine].box.name)
|
||||||
|
|
||||||
@logger.info 'Validating box contents'
|
@logger.debug 'Validating box contents'
|
||||||
validate_box
|
validate_box
|
||||||
|
|
||||||
@logger.info 'Setting box options on environment'
|
@logger.debug 'Setting box options on environment'
|
||||||
@env[:lxc_template_src] = template_src
|
|
||||||
@env[:lxc_template_opts] = template_opts
|
@env[:lxc_template_opts] = template_opts
|
||||||
|
@env[:lxc_template_src] = template_src
|
||||||
# FIXME: Remove support for pre 1.0.0 boxes
|
|
||||||
if box_version != '1.0.0'
|
|
||||||
@env[:ui].warn "WARNING: You are using a base box that has a format that has been deprecated, please upgrade to a new one."
|
|
||||||
@env[:lxc_template_opts].merge!(
|
|
||||||
'--auth-key' => Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if template_config_file.exist?
|
if template_config_file.exist?
|
||||||
@env[:lxc_box_config] = template_config_file.to_s
|
@env[:lxc_template_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
|
end
|
||||||
|
|
||||||
@app.call env
|
@app.call env
|
||||||
end
|
end
|
||||||
|
|
||||||
def template_src
|
def template_src
|
||||||
@template_src ||=
|
@template_src ||= @box.directory.join('lxc-template').to_s
|
||||||
if (box_template = @box.directory.join('lxc-template')).exist?
|
|
||||||
box_template.to_s
|
|
||||||
else
|
|
||||||
Vagrant::LXC.source_root.join('scripts/lxc-template').to_s
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def template_config_file
|
def template_config_file
|
||||||
@template_config_file ||= @box.directory.join('lxc-config')
|
@template_config_file ||= @box.directory.join('lxc.conf')
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: Remove this once we remove compatibility for < 1.0.0 boxes
|
|
||||||
def old_template_config_file
|
|
||||||
@old_template_config_file ||= @box.directory.join('lxc.conf')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def template_opts
|
def template_opts
|
||||||
@template_opts ||= @box.metadata.fetch('template-opts', {}).dup.merge!(
|
@template_opts ||= @box.metadata.fetch('template-opts', {}).dup.merge!(
|
||||||
'--tarball' => rootfs_tarball
|
'--tarball' => rootfs_tarball,
|
||||||
|
# TODO: Deprecate this, the rootfs should be ready for vagrant-lxc
|
||||||
|
# SSH access at this point
|
||||||
|
'--auth-key' => Vagrant.source_root.join('keys', 'vagrant.pub').expand_path.to_s
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -72,10 +52,10 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_box
|
def validate_box
|
||||||
unless SUPPORTED_VERSIONS.include? box_version
|
unless SUPPORTED_VERSIONS.include? @box.metadata.fetch('version').to_i
|
||||||
raise Errors::IncompatibleBox.new name: @box.name,
|
raise Errors::IncompatibleBox.new name: @box.name,
|
||||||
found: box_version,
|
found: @box.metadata.fetch('version').to_i,
|
||||||
supported: SUPPORTED_VERSIONS.join(', ')
|
supported: SUPPORTED_VERSIONS.join(' and ')
|
||||||
end
|
end
|
||||||
|
|
||||||
unless File.exists?(template_src)
|
unless File.exists?(template_src)
|
||||||
|
@ -86,10 +66,6 @@ module Vagrant
|
||||||
raise Errors::RootFSTarballMissing.new name: @box.name
|
raise Errors::RootFSTarballMissing.new name: @box.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def box_version
|
|
||||||
@box.metadata.fetch('version')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
19
lib/vagrant-lxc/action/is_running.rb
Normal file
19
lib/vagrant-lxc/action/is_running.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
module Action
|
||||||
|
class IsRunning
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
env[:result] = env[:machine].state.id == :running
|
||||||
|
|
||||||
|
# Call the next if we have one (but we shouldn't, since this
|
||||||
|
# middleware is built to run with the Call-type middlewares)
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
23
lib/vagrant-lxc/action/message.rb
Normal file
23
lib/vagrant-lxc/action/message.rb
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
module Action
|
||||||
|
# XXX: Is this really needed? Should we contribute this back to Vagrant's core?
|
||||||
|
class Message
|
||||||
|
def initialize(app, env, msg_key, type = :info)
|
||||||
|
@app = app
|
||||||
|
@msg_key = msg_key
|
||||||
|
@type = type
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
machine = env[:machine]
|
||||||
|
message = I18n.t("vagrant_lxc.messages.#{@msg_key}", name: machine.name)
|
||||||
|
|
||||||
|
env[:ui].send @type, message
|
||||||
|
|
||||||
|
@app.call env
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,64 +0,0 @@
|
||||||
module Vagrant
|
|
||||||
module LXC
|
|
||||||
module Action
|
|
||||||
class PrepareNFSSettings
|
|
||||||
include Vagrant::Util::Retryable
|
|
||||||
|
|
||||||
def initialize(app, env)
|
|
||||||
@app = app
|
|
||||||
@logger = Log4r::Logger.new("vagrant::action::vm::nfs")
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
@machine = env[:machine]
|
|
||||||
|
|
||||||
@app.call(env)
|
|
||||||
|
|
||||||
# if using_nfs? # TODO: && !privileged_container?
|
|
||||||
# raise Errors::NfsWithoutPrivilegedError
|
|
||||||
# end
|
|
||||||
|
|
||||||
if using_nfs?
|
|
||||||
@logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP")
|
|
||||||
add_ips_to_env!(env)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# We're using NFS if we have any synced folder with NFS configured. If
|
|
||||||
# we are not using NFS we don't need to do the extra work to
|
|
||||||
# populate these fields in the environment.
|
|
||||||
def using_nfs?
|
|
||||||
@machine.config.vm.synced_folders.any? { |_, opts| opts[:type] == :nfs }
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO:
|
|
||||||
# def privileged_container?
|
|
||||||
# @machine.provider.driver.privileged?(@machine.id)
|
|
||||||
# end
|
|
||||||
|
|
||||||
# Extracts the proper host and guest IPs for NFS mounts and stores them
|
|
||||||
# in the environment for the SyncedFolder action to use them in
|
|
||||||
# mounting.
|
|
||||||
#
|
|
||||||
# The ! indicates that this method modifies its argument.
|
|
||||||
def add_ips_to_env!(env)
|
|
||||||
provider = @machine.provider
|
|
||||||
|
|
||||||
host_ip = read_host_ip
|
|
||||||
machine_ip = provider.ssh_info[:host]
|
|
||||||
|
|
||||||
raise Vagrant::Errors::NFSNoHostonlyNetwork if !host_ip || !machine_ip
|
|
||||||
|
|
||||||
env[:nfs_host_ip] = host_ip
|
|
||||||
env[:nfs_machine_ip] = machine_ip
|
|
||||||
end
|
|
||||||
|
|
||||||
def read_host_ip
|
|
||||||
@machine.communicate.execute 'echo $SSH_CLIENT' do |buffer, output|
|
|
||||||
return output.chomp.split(' ')[0] if buffer == :stdout
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,19 +0,0 @@
|
||||||
module Vagrant
|
|
||||||
module LXC
|
|
||||||
module Action
|
|
||||||
class PrepareNFSValidIds
|
|
||||||
def initialize(app, env)
|
|
||||||
@app = app
|
|
||||||
@logger = Log4r::Logger.new("vagrant::action::vm::nfs")
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
machine = env[:machine]
|
|
||||||
env[:nfs_valid_ids] = machine.provider.driver.all_containers
|
|
||||||
|
|
||||||
@app.call(env)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,46 +0,0 @@
|
||||||
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
|
|
23
lib/vagrant-lxc/action/remove_temporary_files.rb
Normal file
23
lib/vagrant-lxc/action/remove_temporary_files.rb
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
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
|
|
@ -43,16 +43,12 @@ module Vagrant
|
||||||
|
|
||||||
def copy_box_files_to_pkg_dir
|
def copy_box_files_to_pkg_dir
|
||||||
box_dir = @env[:machine].box.directory
|
box_dir = @env[:machine].box.directory
|
||||||
|
FileUtils.cp box_dir.join('lxc-template').to_s, @env['package.directory'].to_s
|
||||||
FileUtils.cp box_dir.join('metadata.json').to_s, @env['package.directory'].to_s
|
FileUtils.cp box_dir.join('metadata.json').to_s, @env['package.directory'].to_s
|
||||||
if (template = box_dir.join('lxc-template')).exist?
|
# TODO: Update built-on metadata.json
|
||||||
FileUtils.cp template.to_s, @env['package.directory'].to_s
|
|
||||||
end
|
|
||||||
if (conf = box_dir.join('lxc.conf')).exist?
|
if (conf = box_dir.join('lxc.conf')).exist?
|
||||||
FileUtils.cp conf.to_s, @env['package.directory'].to_s
|
FileUtils.cp conf.to_s, @env['package.directory'].to_s
|
||||||
end
|
end
|
||||||
if (conf = box_dir.join('lxc-config')).exist?
|
|
||||||
FileUtils.cp conf.to_s, @env['package.directory'].to_s
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
67
lib/vagrant-lxc/action/share_folders.rb
Normal file
67
lib/vagrant-lxc/action/share_folders.rb
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
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
|
41
lib/vagrant-lxc/action/wait_for_communicator.rb
Normal file
41
lib/vagrant-lxc/action/wait_for_communicator.rb
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# This acts like a backport of Vagrant's built in action from 1.3+ for older versions
|
||||||
|
# and will probably be deprecated on 0.8+
|
||||||
|
# https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/action/builtin/wait_for_communicator.rb
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
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 I18n.t("vagrant_lxc.messages.container_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
|
|
@ -7,16 +7,16 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
if public_network_configured?(env[:machine].config)
|
if public_or_private_network_configured?(env[:machine].config)
|
||||||
env[:ui].warn(I18n.t("vagrant_lxc.messages.warn_networks"))
|
env[:ui].warn(I18n.t("vagrant_lxc.messages.warn_networks"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
def public_network_configured?(config)
|
def public_or_private_network_configured?(config)
|
||||||
config.vm.networks.find do |type, _|
|
config.vm.networks.find do |type, _|
|
||||||
type.to_sym == :public_network
|
[:private_network, :public_network].include?(type.to_sym)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
module Vagrant
|
|
||||||
module LXC
|
|
||||||
module Command
|
|
||||||
class Root < Vagrant.plugin("2", :command)
|
|
||||||
def self.synopsis
|
|
||||||
'vagrant-lxc specific commands'
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(argv, env)
|
|
||||||
@args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
|
||||||
@subcommands = Vagrant::Registry.new.tap do |registry|
|
|
||||||
registry.register(:sudoers) do
|
|
||||||
require_relative 'sudoers'
|
|
||||||
Sudoers
|
|
||||||
end
|
|
||||||
end
|
|
||||||
super(argv, env)
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute
|
|
||||||
# Print the help
|
|
||||||
return help if @args.include?("-h") || @args.include?("--help")
|
|
||||||
|
|
||||||
klazz = @subcommands.get(@sub_command.to_sym) if @sub_command
|
|
||||||
return help unless klazz
|
|
||||||
|
|
||||||
@logger.debug("Executing command: #{klazz} #{@sub_args.inspect}")
|
|
||||||
|
|
||||||
# Initialize and execute the command class
|
|
||||||
klazz.new(@sub_args, @env).execute
|
|
||||||
end
|
|
||||||
|
|
||||||
def help
|
|
||||||
opts = OptionParser.new do |opts|
|
|
||||||
opts.banner = "Usage: vagrant lxc <subcommand> [<args>]"
|
|
||||||
opts.separator ""
|
|
||||||
opts.separator "Available subcommands:"
|
|
||||||
|
|
||||||
# REFACTOR Use @subcommands.keys.sort
|
|
||||||
# https://github.com/mitchellh/vagrant/commit/4194da19c60956f6e59239c0145f772be257e79d
|
|
||||||
keys = []
|
|
||||||
@subcommands.each { |key, value| keys << key }
|
|
||||||
|
|
||||||
keys.sort.each do |key|
|
|
||||||
opts.separator " #{key}"
|
|
||||||
end
|
|
||||||
|
|
||||||
opts.separator ""
|
|
||||||
opts.separator "For help on any individual subcommand run `vagrant lxc <subcommand> -h`"
|
|
||||||
end
|
|
||||||
|
|
||||||
@env.ui.info(opts.help, :prefix => false)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,97 +0,0 @@
|
||||||
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', '--user user', String, "The user for which to create the policy (defaults to '#{options[:user]}')") do |u|
|
|
||||||
options[:user] = u
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
argv = parse_options(opts)
|
|
||||||
return unless argv
|
|
||||||
|
|
||||||
wrapper_path = 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
|
|
||||||
|
|
||||||
# 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
|
|
||||||
sudoers.path
|
|
||||||
end
|
|
||||||
|
|
||||||
def su_copy(files)
|
|
||||||
commands = files.map { |file|
|
|
||||||
[
|
|
||||||
"rm -f #{file[:target]}",
|
|
||||||
"cp #{file[:source]} #{file[:target]}",
|
|
||||||
"chown root:root #{file[:target]}",
|
|
||||||
"chmod #{file[:mode]} #{file[:target]}"
|
|
||||||
]
|
|
||||||
}.flatten
|
|
||||||
system "echo \"#{commands.join("; ")}\" | sudo sh"
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_cmd_paths_hash
|
|
||||||
{}.tap do |hash|
|
|
||||||
%w( which cat mkdir cp chown chmod rm tar chown ip ifconfig brctl ).each do |cmd|
|
|
||||||
hash[cmd] = `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
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -6,41 +6,20 @@ module Vagrant
|
||||||
# @return [Array]
|
# @return [Array]
|
||||||
attr_reader :customizations
|
attr_reader :customizations
|
||||||
|
|
||||||
# A string that contains the backing store type used with lxc-create -B
|
# A String that points to a file that acts as a wrapper for sudo commands.
|
||||||
attr_accessor :backingstore
|
|
||||||
|
|
||||||
# Optional arguments for the backing store, such as --fssize, --fstype, ...
|
|
||||||
#
|
#
|
||||||
# @return [Array]
|
# This allows us to have a single entry when whitelisting NOPASSWD commands
|
||||||
attr_accessor :backingstore_options
|
# on /etc/sudoers
|
||||||
|
attr_accessor :sudo_wrapper
|
||||||
|
|
||||||
# A string to explicitly set the container name. To use the vagrant
|
# A string to explicitly set the container name. To use the vagrant
|
||||||
# machine name, set this to :machine
|
# machine name, set this to :machine
|
||||||
attr_accessor :container_name
|
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
|
def initialize
|
||||||
@customizations = []
|
@customizations = []
|
||||||
@backingstore = UNSET_VALUE
|
@sudo_wrapper = UNSET_VALUE
|
||||||
@backingstore_options = []
|
|
||||||
@container_name = UNSET_VALUE
|
@container_name = UNSET_VALUE
|
||||||
@tmpfs_mount_size = UNSET_VALUE
|
|
||||||
@fetch_ip_tries = UNSET_VALUE
|
|
||||||
@ssh_ip_addr = UNSET_VALUE
|
|
||||||
@privileged = UNSET_VALUE
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Customize the container by calling `lxc-start` with the given
|
# Customize the container by calling `lxc-start` with the given
|
||||||
|
@ -58,19 +37,24 @@ module Vagrant
|
||||||
@customizations << [key, value]
|
@customizations << [key, value]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Stores options for backingstores like lvm, btrfs, etc
|
def finalize!
|
||||||
def backingstore_option(key, value)
|
@sudo_wrapper = nil if @sudo_wrapper == UNSET_VALUE
|
||||||
@backingstore_options << [key, value]
|
@container_name = nil if @container_name == UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize!
|
def validate(machine)
|
||||||
@container_name = nil if @container_name == UNSET_VALUE
|
errors = []
|
||||||
@backingstore = nil if @backingstore == UNSET_VALUE
|
|
||||||
@existing_container_name = nil if @existing_container_name == UNSET_VALUE
|
if @sudo_wrapper
|
||||||
@tmpfs_mount_size = '2G' if @tmpfs_mount_size == UNSET_VALUE
|
hostpath = Pathname.new(@sudo_wrapper).expand_path(machine.env.root_path)
|
||||||
@fetch_ip_tries = 10 if @fetch_ip_tries == UNSET_VALUE
|
if ! hostpath.file?
|
||||||
@ssh_ip_addr = nil if @ssh_ip_addr == UNSET_VALUE
|
errors << I18n.t('vagrant_lxc.sudo_wrapper_not_found', path: hostpath.to_s)
|
||||||
@privileged = true if @privileged == UNSET_VALUE
|
elsif ! hostpath.executable?
|
||||||
|
errors << I18n.t('vagrant_lxc.sudo_wrapper_not_executable', path: hostpath.to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
{ "lxc provider" => errors }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,12 +3,9 @@ require "vagrant/util/subprocess"
|
||||||
|
|
||||||
require "vagrant-lxc/errors"
|
require "vagrant-lxc/errors"
|
||||||
require "vagrant-lxc/driver/cli"
|
require "vagrant-lxc/driver/cli"
|
||||||
require "vagrant-lxc/sudo_wrapper"
|
|
||||||
|
|
||||||
require "etc"
|
require "etc"
|
||||||
|
|
||||||
require "tempfile"
|
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
class Driver
|
class Driver
|
||||||
|
@ -16,14 +13,16 @@ module Vagrant
|
||||||
# a name.
|
# a name.
|
||||||
class ContainerNotFound < StandardError; end
|
class ContainerNotFound < StandardError; end
|
||||||
|
|
||||||
# Default root folder where container configs are stored
|
# Root folder where container configs are stored
|
||||||
|
CONTAINERS_PATH = '/var/lib/lxc'
|
||||||
|
|
||||||
attr_reader :container_name,
|
attr_reader :container_name,
|
||||||
:customizations
|
:customizations
|
||||||
|
|
||||||
def initialize(container_name, sudo_wrapper = nil, cli = nil, privileged: true)
|
def initialize(container_name, sudo_wrapper, cli = nil)
|
||||||
@container_name = container_name
|
@container_name = container_name
|
||||||
@sudo_wrapper = sudo_wrapper || SudoWrapper.new(privileged: privileged)
|
@sudo_wrapper = sudo_wrapper
|
||||||
@cli = cli || CLI.new(@sudo_wrapper, container_name)
|
@cli = cli || CLI.new(sudo_wrapper, container_name)
|
||||||
@logger = Log4r::Logger.new("vagrant::provider::lxc::driver")
|
@logger = Log4r::Logger.new("vagrant::provider::lxc::driver")
|
||||||
@customizations = []
|
@customizations = []
|
||||||
end
|
end
|
||||||
|
@ -32,72 +31,45 @@ module Vagrant
|
||||||
raise ContainerNotFound if @container_name && ! @cli.list.include?(@container_name)
|
raise ContainerNotFound if @container_name && ! @cli.list.include?(@container_name)
|
||||||
end
|
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
|
def base_path
|
||||||
Pathname.new("#{containers_path}/#{@container_name}")
|
Pathname.new("#{CONTAINERS_PATH}/#{@container_name}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def config_path
|
|
||||||
base_path.join('config').to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def rootfs_path
|
def rootfs_path
|
||||||
pathtype, path = config_string.match(/^lxc\.rootfs(?:\.path)?\s+=\s+(.+:)?(.+)$/)[1..2]
|
Pathname.new(config_string.match(/^lxc\.rootfs\s+=\s+(.+)$/)[1])
|
||||||
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
|
end
|
||||||
|
|
||||||
def mac_address
|
def mac_address
|
||||||
return @mac_address if @mac_address
|
@mac_address ||= config_string.match(/^lxc\.network\.hwaddr\s*+=\s*+(.+)$/)[1]
|
||||||
|
|
||||||
if config_string =~ /^lxc\.network\.hwaddr\s*+=\s*+(.+)$/
|
|
||||||
@mac_address = $1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def config_string
|
def config_string
|
||||||
@sudo_wrapper.run('cat', config_path)
|
@sudo_wrapper.run('cat', base_path.join('config').to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(name, backingstore, backingstore_options, template_path, config_file, template_options = {})
|
def create(name, template_path, config_file, template_options = {})
|
||||||
@cli.name = @container_name = name
|
@cli.name = @container_name = name
|
||||||
|
|
||||||
@logger.debug "Creating container..."
|
import_template(template_path) do |template_name|
|
||||||
|
@logger.debug "Creating container..."
|
||||||
@cli.create template_path, backingstore, backingstore_options, config_file, template_options
|
@cli.create template_name, config_file, template_options
|
||||||
end
|
|
||||||
|
|
||||||
def share_folders(folders)
|
|
||||||
folders.each do |f|
|
|
||||||
share_folder(f[:hostpath], f[:guestpath], f.fetch(:mount_options, nil))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def share_folder(host_path, guest_path, mount_options = nil)
|
def share_folders(folders)
|
||||||
guest_path = guest_path.gsub(/^\//, '').gsub(' ', '\\\040')
|
folders.each do |folder|
|
||||||
mount_options = Array(mount_options || ['bind', 'create=dir'])
|
guestpath = rootfs_path.join(folder[:guestpath].gsub(/^\//, ''))
|
||||||
host_path = host_path.to_s.gsub(' ', '\\\040')
|
unless guestpath.directory?
|
||||||
@customizations << ['mount.entry', "#{host_path} #{guest_path} none #{mount_options.join(',')} 0 0"]
|
begin
|
||||||
|
@logger.debug("Guest path doesn't exist, creating: #{guestpath}")
|
||||||
|
@sudo_wrapper.run('mkdir', '-p', guestpath.to_s)
|
||||||
|
rescue Errno::EACCES
|
||||||
|
raise Vagrant::Errors::SharedFolderCreateFailed, :path => guestpath.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@customizations << ['mount.entry', "#{folder[:hostpath]} #{guestpath} none bind 0 0"]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def start(customizations)
|
def start(customizations)
|
||||||
|
@ -115,6 +87,9 @@ module Vagrant
|
||||||
|
|
||||||
def forced_halt
|
def forced_halt
|
||||||
@logger.info('Shutting down container...')
|
@logger.info('Shutting down container...')
|
||||||
|
@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 }
|
@cli.transition_to(:stopped) { |c| c.stop }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -126,103 +101,27 @@ module Vagrant
|
||||||
@cli.attach(*command)
|
@cli.attach(*command)
|
||||||
end
|
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
|
def version
|
||||||
@version ||= @cli.version
|
@version ||= @cli.version
|
||||||
end
|
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
|
# TODO: This needs to be reviewed and specs needs to be written
|
||||||
def compress_rootfs
|
def compress_rootfs
|
||||||
# TODO: Pass in tmpdir so we can clean up from outside
|
# TODO: Pass in tmpdir so we can clean up from outside
|
||||||
target_path = "#{Dir.mktmpdir}/rootfs.tar.gz"
|
target_path = "#{Dir.mktmpdir}/rootfs.tar.gz"
|
||||||
|
|
||||||
@logger.info "Compressing '#{rootfs_path}' rootfs to #{target_path}"
|
@logger.info "Compressing '#{rootfs_path}' rootfs to #{target_path}"
|
||||||
@sudo_wrapper.run('tar', '--numeric-owner', '-cvzf', target_path, '-C',
|
# "vagrant package" will copy the existing lxc-template in the new box file
|
||||||
rootfs_path.parent.to_s, "./#{rootfs_path.basename.to_s}")
|
# 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(' && '))
|
||||||
|
|
||||||
@logger.info "Changing rootfs tarball owner"
|
@logger.info "Changing rootfs tarball owner"
|
||||||
user_details = Etc.getpwnam(Etc.getlogin)
|
user_details = Etc.getpwnam(Etc.getlogin)
|
||||||
|
@ -240,16 +139,7 @@ module Vagrant
|
||||||
def prune_customizations
|
def prune_customizations
|
||||||
# Use sed to just strip out the block of code which was inserted by Vagrant
|
# Use sed to just strip out the block of code which was inserted by Vagrant
|
||||||
@logger.debug 'Prunning vagrant-lxc customizations'
|
@logger.debug 'Prunning vagrant-lxc customizations'
|
||||||
contents = config_string
|
@sudo_wrapper.su_c("sed -e '/^# VAGRANT-BEGIN/,/^# VAGRANT-END/ d' -ibak #{base_path.join('config')}")
|
||||||
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
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
@ -259,32 +149,46 @@ module Vagrant
|
||||||
"lxc.#{key}=#{value}"
|
"lxc.#{key}=#{value}"
|
||||||
end
|
end
|
||||||
customizations.unshift '# VAGRANT-BEGIN'
|
customizations.unshift '# VAGRANT-BEGIN'
|
||||||
customizations << "# VAGRANT-END\n"
|
customizations << '# VAGRANT-END'
|
||||||
|
|
||||||
contents = config_string
|
config_file = base_path.join('config').to_s
|
||||||
contents << customizations.join("\n")
|
customizations.each do |line|
|
||||||
|
@sudo_wrapper.su_c("echo '#{line}' >> #{config_file}")
|
||||||
write_config(contents)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_config(contents)
|
def import_template(path)
|
||||||
confpath = base_path.join('config').to_s
|
template_name = "vagrant-tmp-#{@container_name}"
|
||||||
begin
|
tmp_template_path = templates_path.join("lxc-#{template_name}").to_s
|
||||||
File.open(confpath, File::RDWR) do |file|
|
|
||||||
file.write contents
|
@logger.info 'Copying LXC template into place'
|
||||||
end
|
@sudo_wrapper.run('cp', path, tmp_template_path)
|
||||||
rescue
|
@sudo_wrapper.run('chmod', '+x', tmp_template_path)
|
||||||
# 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.
|
yield template_name
|
||||||
Tempfile.new('lxc-config').tap do |file|
|
ensure
|
||||||
file.chmod 0644
|
@logger.info 'Removing LXC template'
|
||||||
file.write contents
|
if tmp_template_path
|
||||||
file.close
|
@sudo_wrapper.run('rm', tmp_template_path)
|
||||||
@sudo_wrapper.run 'cp', '-f', file.path, confpath
|
|
||||||
@sudo_wrapper.run 'chown', 'root:root', confpath
|
|
||||||
end
|
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ module Vagrant
|
||||||
attr_accessor :name
|
attr_accessor :name
|
||||||
|
|
||||||
class TransitionBlockNotProvided < RuntimeError; end
|
class TransitionBlockNotProvided < RuntimeError; end
|
||||||
|
class ShutdownNotSupported < RuntimeError; end
|
||||||
class TargetStateNotReached < RuntimeError
|
class TargetStateNotReached < RuntimeError
|
||||||
def initialize(target_state, state)
|
def initialize(target_state, state)
|
||||||
msg = "Target state '#{target_state}' not reached, currently on '#{state}'"
|
msg = "Target state '#{target_state}' not reached, currently on '#{state}'"
|
||||||
|
@ -28,24 +29,14 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def version
|
def version
|
||||||
return @version if @version
|
if run(:version) =~ /lxc version:\s+(.+)\s*$/
|
||||||
@version = run(:create, '--version')
|
$1.downcase
|
||||||
if @version =~ /(lxc version:\s+|)(.+)\s*$/
|
|
||||||
@version = $2.downcase
|
|
||||||
else
|
else
|
||||||
# TODO: Raise an user friendly error
|
# TODO: Raise an user friendly error
|
||||||
raise 'Unable to parse lxc version!'
|
raise 'Unable to parse lxc version!'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def config(param)
|
|
||||||
run(:config, param).gsub("\n", '')
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_config(path)
|
|
||||||
run('update-config', '-c', path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def state
|
def state
|
||||||
if @name && run(:info, '--name', @name, retryable: true) =~ /^state:[^A-Z]+([A-Z]+)$/i
|
if @name && run(:info, '--name', @name, retryable: true) =~ /^state:[^A-Z]+([A-Z]+)$/i
|
||||||
$1.downcase.to_sym
|
$1.downcase.to_sym
|
||||||
|
@ -54,19 +45,17 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(template, backingstore, backingstore_options, config_file, template_opts = {})
|
def create(template, config_file, template_opts = {})
|
||||||
if config_file
|
if config_file
|
||||||
config_opts = ['-f', config_file]
|
config_opts = ['-f', config_file]
|
||||||
end
|
end
|
||||||
|
|
||||||
extra = template_opts.to_a.flatten.reject { |elem| elem.empty? }
|
extra = template_opts.to_a.flatten
|
||||||
extra.unshift '--' unless extra.empty?
|
extra.unshift '--' unless extra.empty?
|
||||||
|
|
||||||
run :create,
|
run :create,
|
||||||
'-B', backingstore,
|
|
||||||
'--template', template,
|
'--template', template,
|
||||||
'--name', @name,
|
'--name', @name,
|
||||||
*(backingstore_options.to_a.flatten),
|
|
||||||
*(config_opts),
|
*(config_opts),
|
||||||
*extra
|
*extra
|
||||||
rescue Errors::ExecuteError => e
|
rescue Errors::ExecuteError => e
|
||||||
|
@ -85,18 +74,17 @@ module Vagrant
|
||||||
run :start, '-d', '--name', @name, *Array(options)
|
run :start, '-d', '--name', @name, *Array(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
## lxc-stop will exit 2 if machine was already stopped
|
|
||||||
# Man Page:
|
|
||||||
# 2 The specified container exists but was not running.
|
|
||||||
def stop
|
def stop
|
||||||
begin
|
attach '/sbin/halt'
|
||||||
run :stop, '--name', @name
|
run :stop, '--name', @name
|
||||||
rescue LXC::Errors::ExecuteError => e
|
end
|
||||||
if e.exitcode == 2
|
|
||||||
@logger.debug "Machine already stopped, lxc-stop returned 2"
|
def shutdown
|
||||||
else
|
if system('which lxc-shutdown > /dev/null')
|
||||||
raise e
|
run :shutdown, '--name', @name
|
||||||
end
|
else
|
||||||
|
# REFACTOR: Do not use exception to control the flow
|
||||||
|
raise ShutdownNotSupported
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -107,23 +95,18 @@ module Vagrant
|
||||||
opts = cmd.pop
|
opts = cmd.pop
|
||||||
namespaces = Array(opts[:namespaces]).map(&:upcase).join('|')
|
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 namespaces
|
||||||
extra = ['--namespaces', namespaces]
|
if supports_attach_with_namespaces?
|
||||||
|
extra = ['--namespaces', namespaces]
|
||||||
|
else
|
||||||
|
raise LXC::Errors::NamespacesNotSupported
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
run :attach, '--name', @name, *((extra || []) + cmd)
|
run :attach, '--name', @name, *((extra || []) + cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
def info(*cmd)
|
|
||||||
run(:info, '--name', @name, *cmd)
|
|
||||||
end
|
|
||||||
|
|
||||||
def transition_to(target_state, tries = 30, timeout = 1, &block)
|
def transition_to(target_state, tries = 30, timeout = 1, &block)
|
||||||
raise TransitionBlockNotProvided unless block_given?
|
raise TransitionBlockNotProvided unless block_given?
|
||||||
|
|
||||||
|
@ -146,6 +129,14 @@ module Vagrant
|
||||||
def run(command, *args)
|
def run(command, *args)
|
||||||
@sudo_wrapper.run("lxc-#{command}", *args)
|
@sudo_wrapper.run("lxc-#{command}", *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def supports_attach_with_namespaces?
|
||||||
|
unless defined?(@supports_attach_with_namespaces)
|
||||||
|
@supports_attach_with_namespaces = run(:attach, '-h', :show_stderr => true).values.join.include?('--namespaces')
|
||||||
|
end
|
||||||
|
|
||||||
|
return @supports_attach_with_namespaces
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,28 +5,17 @@ module Vagrant
|
||||||
module Errors
|
module Errors
|
||||||
class ExecuteError < Vagrant::Errors::VagrantError
|
class ExecuteError < Vagrant::Errors::VagrantError
|
||||||
error_key(:lxc_execute_error)
|
error_key(:lxc_execute_error)
|
||||||
attr_reader :stderr, :stdout, :exitcode
|
attr_reader :stderr, :stdout
|
||||||
def initialize(message, *args)
|
def initialize(message, *args)
|
||||||
super
|
super
|
||||||
if message.is_a?(Hash)
|
if message.is_a?(Hash)
|
||||||
@stderr = message[:stderr]
|
@stderr = message[:stderr]
|
||||||
@stdout = message[:stdout]
|
@stdout = message[:stdout]
|
||||||
@exitcode = message[:exitcode]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Raised when user interrupts a subprocess
|
class NamespacesNotSupported < Vagrant::Errors::VagrantError
|
||||||
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
|
end
|
||||||
|
|
||||||
class LxcNotInstalled < Vagrant::Errors::VagrantError
|
class LxcNotInstalled < Vagrant::Errors::VagrantError
|
||||||
|
@ -37,10 +26,6 @@ module Vagrant
|
||||||
error_key(:lxc_container_already_exists)
|
error_key(:lxc_container_already_exists)
|
||||||
end
|
end
|
||||||
|
|
||||||
class CommandNotSupported < Vagrant::Errors::VagrantError
|
|
||||||
error_key(:lxc_command_not_supported)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Box related errors
|
# Box related errors
|
||||||
class TemplateFileMissing < Vagrant::Errors::VagrantError
|
class TemplateFileMissing < Vagrant::Errors::VagrantError
|
||||||
error_key(:lxc_template_file_missing)
|
error_key(:lxc_template_file_missing)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'vagrant'
|
require "vagrant"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
|
@ -9,43 +9,23 @@ module Vagrant
|
||||||
LXC-based virtual machines.
|
LXC-based virtual machines.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
provider(:lxc, parallel: true, priority: 7) do
|
provider(:lxc, parallel: true) do
|
||||||
require_relative 'provider'
|
require File.expand_path("../provider", __FILE__)
|
||||||
init!
|
|
||||||
|
I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml')
|
||||||
|
I18n.reload!
|
||||||
|
|
||||||
Provider
|
Provider
|
||||||
end
|
end
|
||||||
|
|
||||||
command "lxc" do
|
|
||||||
require_relative 'command/root'
|
|
||||||
init!
|
|
||||||
Command::Root
|
|
||||||
end
|
|
||||||
|
|
||||||
config(:lxc, :provider) do
|
config(:lxc, :provider) do
|
||||||
require_relative 'config'
|
require File.expand_path("../config", __FILE__)
|
||||||
init!
|
|
||||||
Config
|
Config
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
synced_folder(:lxc) do
|
def self.vagrant_1_3_or_later
|
||||||
require_relative 'synced_folder'
|
Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.3.0')
|
||||||
SyncedFolder
|
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,20 +2,13 @@ require "log4r"
|
||||||
|
|
||||||
require "vagrant-lxc/action"
|
require "vagrant-lxc/action"
|
||||||
require "vagrant-lxc/driver"
|
require "vagrant-lxc/driver"
|
||||||
|
require "vagrant-lxc/sudo_wrapper"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
class Provider < Vagrant.plugin("2", :provider)
|
class Provider < Vagrant.plugin("2", :provider)
|
||||||
attr_reader :driver
|
attr_reader :driver
|
||||||
|
|
||||||
def self.usable?(raise_error=false)
|
|
||||||
if !Vagrant::Util::Platform.linux?
|
|
||||||
raise Errors::LxcLinuxRequired
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(machine)
|
def initialize(machine)
|
||||||
@logger = Log4r::Logger.new("vagrant::provider::lxc")
|
@logger = Log4r::Logger.new("vagrant::provider::lxc")
|
||||||
@machine = machine
|
@machine = machine
|
||||||
|
@ -24,9 +17,17 @@ module Vagrant
|
||||||
machine_id_changed
|
machine_id_changed
|
||||||
end
|
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!
|
def ensure_lxc_installed!
|
||||||
begin
|
begin
|
||||||
SudoWrapper.new(privileged: @machine.provider_config.privileged).run("which", "lxc-create")
|
sudo_wrapper.run("which", "lxc-create")
|
||||||
rescue Vagrant::LXC::Errors::ExecuteError
|
rescue Vagrant::LXC::Errors::ExecuteError
|
||||||
raise Errors::LxcNotInstalled
|
raise Errors::LxcNotInstalled
|
||||||
end
|
end
|
||||||
|
@ -39,7 +40,7 @@ module Vagrant
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@logger.debug("Instantiating the container for: #{id.inspect}")
|
@logger.debug("Instantiating the container for: #{id.inspect}")
|
||||||
@driver = Driver.new(id, privileged: @machine.provider_config.privileged)
|
@driver = Driver.new(id, self.sudo_wrapper)
|
||||||
@driver.validate!
|
@driver.validate!
|
||||||
rescue Driver::ContainerNotFound
|
rescue Driver::ContainerNotFound
|
||||||
# The container doesn't exist, so we probably have a stale
|
# The container doesn't exist, so we probably have a stale
|
||||||
|
@ -62,13 +63,13 @@ module Vagrant
|
||||||
|
|
||||||
# Returns the SSH info for accessing the Container.
|
# Returns the SSH info for accessing the Container.
|
||||||
def ssh_info
|
def ssh_info
|
||||||
# If the Container is not running then we cannot possibly SSH into it, so
|
# If the Container is not created then we cannot possibly SSH into it, so
|
||||||
# we return nil.
|
# we return nil.
|
||||||
return nil if state.id != :running
|
return nil if state == :not_created
|
||||||
|
|
||||||
# Run a custom action called "ssh_ip" which does what it says and puts
|
# Run a custom action called "fetch_ip" which does what it says and puts
|
||||||
# the IP found into the `:machine_ip` key in the environment.
|
# the IP found into the `:machine_ip` key in the environment.
|
||||||
env = @machine.action("ssh_ip")
|
env = @machine.action("fetch_ip")
|
||||||
|
|
||||||
# If we were not able to identify the container's IP, we return nil
|
# If we were not able to identify the container's IP, we return nil
|
||||||
# here and we let Vagrant core deal with it ;)
|
# here and we let Vagrant core deal with it ;)
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
module Vagrant
|
|
||||||
module LXC
|
|
||||||
class Provider
|
|
||||||
module Cap
|
|
||||||
module PublicAddress
|
|
||||||
def self.public_address(machine)
|
|
||||||
return nil if machine.state.id != :running
|
|
||||||
|
|
||||||
ssh_info = machine.ssh_info
|
|
||||||
return nil if !ssh_info
|
|
||||||
ssh_info[:host]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -4,43 +4,24 @@ module Vagrant
|
||||||
# Include this so we can use `Subprocess` more easily.
|
# Include this so we can use `Subprocess` more easily.
|
||||||
include Vagrant::Util::Retryable
|
include Vagrant::Util::Retryable
|
||||||
|
|
||||||
attr_reader :wrapper_path
|
def initialize(wrapper_path = nil)
|
||||||
|
@wrapper_path = 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")
|
@logger = Log4r::Logger.new("vagrant::lxc::sudo_wrapper")
|
||||||
end
|
end
|
||||||
|
|
||||||
def run(*command)
|
def run(*command)
|
||||||
options = command.last.is_a?(Hash) ? command.last : {}
|
command.unshift @wrapper_path if @wrapper_path
|
||||||
|
execute *(['sudo'] + command)
|
||||||
|
end
|
||||||
|
|
||||||
# Avoid running LXC commands with a restrictive umask.
|
def su_c(command)
|
||||||
# Otherwise disasters occur, like the container root directory
|
su_command = if @wrapper_path
|
||||||
# having permissions `rwxr-x---` which prevents the `vagrant`
|
"#{@wrapper_path} \"#{command}\""
|
||||||
# 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
|
else
|
||||||
execute *(['/usr/bin/env'] + command)
|
"su root -c \"#{command}\""
|
||||||
end
|
end
|
||||||
ensure
|
@logger.debug "Running 'sudo #{su_command}'"
|
||||||
File.umask(old_mask)
|
system "sudo #{su_command}"
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -68,10 +49,10 @@ module Vagrant
|
||||||
# nicely handled by Vagrant.
|
# nicely handled by Vagrant.
|
||||||
if r.exit_code != 0
|
if r.exit_code != 0
|
||||||
if @interrupted
|
if @interrupted
|
||||||
raise LXC::Errors::SubprocessInterruptError, command.inspect
|
@logger.info("Exit code != 0, but interrupted. Ignoring.")
|
||||||
else
|
else
|
||||||
raise LXC::Errors::ExecuteError,
|
raise LXC::Errors::ExecuteError,
|
||||||
command: command.inspect, stderr: r.stderr, stdout: r.stdout, exitcode: r.exit_code
|
command: command.inspect, stderr: r.stderr, stdout: r.stdout
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
module Vagrant
|
|
||||||
module LXC
|
|
||||||
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
|
||||||
def usable?(machine)
|
|
||||||
# These synced folders only work if the provider is LXC
|
|
||||||
machine.provider_name == :lxc
|
|
||||||
end
|
|
||||||
|
|
||||||
def prepare(machine, folders, _opts)
|
|
||||||
machine.ui.output(I18n.t("vagrant.actions.lxc.share_folders.preparing"))
|
|
||||||
# short guestpaths first, so we don't step on ourselves
|
|
||||||
folders = folders.sort_by do |id, data|
|
|
||||||
if data[:guestpath]
|
|
||||||
data[:guestpath].length
|
|
||||||
else
|
|
||||||
# A long enough path to just do this at the end.
|
|
||||||
10000
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
folders.each do |id, data|
|
|
||||||
host_path = Pathname.new(File.expand_path(data[:hostpath], machine.env.root_path))
|
|
||||||
guest_path = data[:guestpath]
|
|
||||||
|
|
||||||
machine.env.ui.warn(I18n.t("vagrant_lxc.messages.warn_owner")) if data[:owner]
|
|
||||||
machine.env.ui.warn(I18n.t("vagrant_lxc.messages.warn_group")) if data[:group]
|
|
||||||
|
|
||||||
if !host_path.directory? && data[:create]
|
|
||||||
# Host path doesn't exist, so let's create it.
|
|
||||||
@logger.info("Host path doesn't exist, creating: #{host_path}")
|
|
||||||
|
|
||||||
begin
|
|
||||||
host_path.mkpath
|
|
||||||
rescue Errno::EACCES
|
|
||||||
raise Vagrant::Errors::SharedFolderCreateFailed,
|
|
||||||
:path => hostpath.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
mount_opts = data[:mount_options]
|
|
||||||
machine.provider.driver.share_folder(host_path, guest_path, mount_opts)
|
|
||||||
# Guest path specified, so mount the folder to specified point
|
|
||||||
machine.ui.detail(I18n.t("vagrant.actions.vm.share_folders.mounting_entry",
|
|
||||||
guestpath: data[:guestpath],
|
|
||||||
hostpath: data[:hostpath],
|
|
||||||
guest_path: data[:guestpath]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def enable(machine, folders, _opts)
|
|
||||||
# Emit an upstart event if we can
|
|
||||||
return unless machine.communicate.test("test -x /sbin/initctl")
|
|
||||||
|
|
||||||
# short guestpaths first, so we don't step on ourselves
|
|
||||||
folders = folders.sort_by do |id, data|
|
|
||||||
if data[:guestpath]
|
|
||||||
data[:guestpath].length
|
|
||||||
else
|
|
||||||
# A long enough path to just do this at the end.
|
|
||||||
10000
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
folders.each do |id, data|
|
|
||||||
guest_path = data[:guestpath]
|
|
||||||
machine.communicate.sudo(
|
|
||||||
"/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guest_path}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,5 +1,5 @@
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module LXC
|
module LXC
|
||||||
VERSION = "1.4.2"
|
VERSION = "0.8.1.dev"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,19 +12,15 @@ en:
|
||||||
Starting container...
|
Starting container...
|
||||||
force_shutdown: |-
|
force_shutdown: |-
|
||||||
Forcing shutdown of container...
|
Forcing shutdown of container...
|
||||||
|
# TODO: Remove the following keys after we drop support for vagrant < 1.3
|
||||||
|
waiting_for_start: |-
|
||||||
|
Waiting for container to start. This should not take long.
|
||||||
|
container_ready: |-
|
||||||
|
Container started and ready for use!
|
||||||
warn_networks: |-
|
warn_networks: |-
|
||||||
Warning! The LXC provider doesn't support public networks, the settings
|
Warning! The LXC provider doesn't support any of the Vagrant public / private
|
||||||
will be silently ignored.
|
network configurations (ex: `config.vm.network :private_network, ip: "some-ip"`).
|
||||||
warn_group: |-
|
They will be silently ignored.
|
||||||
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:
|
vagrant:
|
||||||
commands:
|
commands:
|
||||||
|
@ -40,9 +36,6 @@ en:
|
||||||
preparing: Setting up mount entries for shared folders...
|
preparing: Setting up mount entries for shared folders...
|
||||||
|
|
||||||
errors:
|
errors:
|
||||||
lxc_interrupt_error: |-
|
|
||||||
Interrupted
|
|
||||||
|
|
||||||
lxc_execute_error: |-
|
lxc_execute_error: |-
|
||||||
There was an error executing %{command}
|
There was an error executing %{command}
|
||||||
|
|
||||||
|
@ -62,12 +55,8 @@ en:
|
||||||
|
|
||||||
Looked up under: %{paths}
|
Looked up under: %{paths}
|
||||||
|
|
||||||
lxc_linux_required: |-
|
|
||||||
The LXC provider only works on Linux. Please try to use
|
|
||||||
another provider.
|
|
||||||
|
|
||||||
lxc_not_installed: |-
|
lxc_not_installed: |-
|
||||||
The `lxc` package does not seem to be installed or `lxc-create` is not accessible on the PATH.
|
The `lxc` package does not seem to be installed or is not accessible on the PATH.
|
||||||
|
|
||||||
lxc_redir_not_installed: |-
|
lxc_redir_not_installed: |-
|
||||||
`redir` is not installed or is not accessible on the PATH.
|
`redir` is not installed or is not accessible on the PATH.
|
||||||
|
@ -76,7 +65,3 @@ en:
|
||||||
There is container on your system with the same name you've specified
|
There is container on your system with the same name you've specified
|
||||||
on your Vagrantfile (%{name}), please choose a different one or
|
on your Vagrantfile (%{name}), please choose a different one or
|
||||||
run `lxc-destroy --name %{name}` and try again.
|
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}.
|
|
||||||
|
|
|
@ -1,180 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This is a modified version of /usr/share/lxc/templates/lxc-download
|
|
||||||
# that comes with ubuntu-lxc 1.0.0 stable from ppa changed to suit vagrant-lxc needs
|
|
||||||
#
|
|
||||||
# Copyright © 2014 Stéphane Graber <stgraber@ubuntu.com>
|
|
||||||
# Copyright © 2014 Fábio Rehm <fgrehm@gmail.com>
|
|
||||||
#
|
|
||||||
# This library is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
|
||||||
# License as published by the Free Software Foundation; either
|
|
||||||
# version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
# This library is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
# Lesser General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
|
||||||
# License along with this library; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
# USA
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
LXC_HOOK_DIR="/usr/share/lxc/hooks"
|
|
||||||
LXC_TEMPLATE_CONFIG="/usr/share/lxc/config"
|
|
||||||
|
|
||||||
LXC_MAPPED_GID=
|
|
||||||
LXC_MAPPED_UID=
|
|
||||||
LXC_NAME=
|
|
||||||
LXC_PATH=
|
|
||||||
LXC_ROOTFS=
|
|
||||||
LXC_TARBALL=
|
|
||||||
LXC_CONFIG=
|
|
||||||
LXC_USE_OLDCONFIG=
|
|
||||||
LXC_STRIP_COMPONENTS=2
|
|
||||||
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<EOF
|
|
||||||
vagrant-lxc default template
|
|
||||||
|
|
||||||
Required arguments:
|
|
||||||
[ --tarball <path> ]: The full path of the rootfs tarball
|
|
||||||
|
|
||||||
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!):
|
|
||||||
[ --name <name> ]: The container name
|
|
||||||
[ --path <path> ]: The path to the container
|
|
||||||
[ --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:,oldconfig,help:,name:,path:,rootfs:,mapped-uid:,mapped-gid:,strip-components: -- "$@")SS
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
usage $(basename $0)
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
eval set -- "$options"
|
|
||||||
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
case "$1" in
|
|
||||||
-h|--help) usage $0 && exit 0;;
|
|
||||||
--config) LXC_CONFIG=$2; shift 2;;
|
|
||||||
--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
|
|
||||||
|
|
||||||
if [ -z "${LXC_NAME}" ]; then
|
|
||||||
echo "'name' parameter is required"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${LXC_TARBALL}" ]; then
|
|
||||||
echo "'tarball' parameter is required"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${LXC_PATH}" ]; then
|
|
||||||
echo "'path' parameter is required"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# if $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"
|
|
||||||
|
|
||||||
(
|
|
||||||
flock -x 200
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Cache repository is busy."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p ${LXC_ROOTFS}
|
|
||||||
(cd ${LXC_ROOTFS} && tar xfz ${LXC_TARBALL} --strip-components=${LXC_STRIP_COMPONENTS} --xattrs --xattrs-include=* || true)
|
|
||||||
if [ ! -f ${LXC_ROOTFS}/bin/true ]; then
|
|
||||||
echo "Failed to extract rootfs"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
) 200>${LXC_PATH}/vagrant_lock
|
|
||||||
rm ${LXC_PATH}/vagrant_lock
|
|
||||||
|
|
||||||
mkdir -p ${LXC_ROOTFS}/dev/pts/
|
|
||||||
|
|
||||||
## Extract all the network config entries
|
|
||||||
sed -i -e "/lxc.network/{w ${LXC_PATH}/config-network" -e "d}" \
|
|
||||||
${LXC_PATH}/config
|
|
||||||
|
|
||||||
## Extract any other config entry
|
|
||||||
sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" ${LXC_PATH}/config
|
|
||||||
|
|
||||||
## Add the container-specific config
|
|
||||||
echo "" >> ${LXC_PATH}/config
|
|
||||||
echo "##############################################" >> ${LXC_PATH}/config
|
|
||||||
echo "# Container specific configuration (automatically set)" >> ${LXC_PATH}/config
|
|
||||||
if [ -e "${LXC_PATH}/config-auto" ]; then
|
|
||||||
cat ${LXC_PATH}/config-auto >> ${LXC_PATH}/config
|
|
||||||
rm ${LXC_PATH}/config-auto
|
|
||||||
fi
|
|
||||||
|
|
||||||
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
|
|
||||||
echo "" >> ${LXC_PATH}/config
|
|
||||||
echo "##############################################" >> ${LXC_PATH}/config
|
|
||||||
echo "# Network configuration (automatically set)" >> ${LXC_PATH}/config
|
|
||||||
cat ${LXC_PATH}/config-network >> ${LXC_PATH}/config
|
|
||||||
rm ${LXC_PATH}/config-network
|
|
||||||
fi
|
|
||||||
|
|
||||||
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
|
|
||||||
echo "##############################################" >> ${LXC_PATH}/config
|
|
||||||
echo "# vagrant-lxc container specific configuration" >> ${LXC_PATH}/config
|
|
||||||
|
|
||||||
exit 0
|
|
422
scripts/pipework
422
scripts/pipework
|
@ -1,422 +0,0 @@
|
||||||
#!/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
4
spec/Vagrantfile
vendored
|
@ -15,6 +15,10 @@ Vagrant.configure("2") do |config|
|
||||||
|
|
||||||
config.cache.auto_detect = true
|
config.cache.auto_detect = true
|
||||||
|
|
||||||
|
config.vm.provider :lxc do |lxc|
|
||||||
|
# lxc.sudo_wrapper = '/usr/bin/lxc-vagrant-wrapper'
|
||||||
|
end
|
||||||
|
|
||||||
config.vm.provision :shell,
|
config.vm.provision :shell,
|
||||||
inline: 'mkdir -p /vagrant/tmp && echo -n "Provisioned" > /vagrant/tmp/provisioning'
|
inline: 'mkdir -p /vagrant/tmp && echo -n "Provisioned" > /vagrant/tmp/provisioning'
|
||||||
|
|
||||||
|
|
111
spec/acceptance/sanity_check_spec.rb
Normal file
111
spec/acceptance/sanity_check_spec.rb
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
require 'acceptance_helper'
|
||||||
|
|
||||||
|
describe 'Sanity check' do
|
||||||
|
after(:all) { destroy_container }
|
||||||
|
|
||||||
|
context 'running `vagrant up` from scratch' do
|
||||||
|
before(:all) do
|
||||||
|
destroy_container
|
||||||
|
vagrant_up
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a container' do
|
||||||
|
containers = `sudo lxc-ls`.chomp.split(/\s+/).uniq
|
||||||
|
expect(containers).to include vagrant_container_name
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'starts the newly created container' do
|
||||||
|
status = `sudo lxc-info -n #{vagrant_container_name}`
|
||||||
|
expect(status).to include 'RUNNING'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is able to be SSH'ed" do
|
||||||
|
expect(vagrant_ssh('hostname')).to eq 'lxc-test-box'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'mounts shared folders with the right permissions' do
|
||||||
|
vagrant_ssh 'mkdir -p /vagrant/tmp && echo -n "Shared" > /vagrant/tmp/shared'
|
||||||
|
shared_file_contents = File.read('/vagrant/spec/tmp/shared')
|
||||||
|
expect(shared_file_contents).to eq 'Shared'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'provisions the container based on Vagrantfile configs' do
|
||||||
|
provisioned_file_contents = File.read('/vagrant/spec/tmp/provisioning')
|
||||||
|
expect(provisioned_file_contents).to eq 'Provisioned'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'forwards configured ports' do
|
||||||
|
output = `curl -s localhost:8080`.strip.chomp
|
||||||
|
expect(output).to include 'It works!'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context '`vagrant halt` on a running container' do
|
||||||
|
before(:all) do
|
||||||
|
destroy_container
|
||||||
|
vagrant_up
|
||||||
|
vagrant_ssh 'touch /tmp/{some,files}'
|
||||||
|
vagrant_halt
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'shuts down the container' do
|
||||||
|
status = `sudo lxc-info -n #{vagrant_container_name}`
|
||||||
|
expect(status).to include 'STOPPED'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'clears forwarded ports' do
|
||||||
|
`curl -s localhost:8080 --connect-timeout 2`
|
||||||
|
expect($?.exitstatus).to_not eq 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'kills redir processes' do
|
||||||
|
processes = `pgrep redir`
|
||||||
|
expect($?.exitstatus).to_not eq 0
|
||||||
|
end
|
||||||
|
|
||||||
|
xit 'removes files under `/tmp`' do
|
||||||
|
container_tmp_files = `sudo ls -l "/var/lib/lxc/#{vagrant_container_name}/rootfs/tmp"`.split("\n")
|
||||||
|
puts container_tmp_files.join("\n")
|
||||||
|
expect(container_tmp_files).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context '`vagrant destroy`' do
|
||||||
|
before(:all) do
|
||||||
|
destroy_container
|
||||||
|
vagrant_up
|
||||||
|
@container_name = vagrant_container_name
|
||||||
|
vagrant_destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'destroys the underlying container' do
|
||||||
|
containers = `sudo lxc-ls`.chomp.split(/\s+/).uniq
|
||||||
|
expect(containers).to_not include @container_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pending 'box packaging' do
|
||||||
|
before(:all) do
|
||||||
|
destroy_container
|
||||||
|
vagrant_box_remove('new-box')
|
||||||
|
vagrant_up
|
||||||
|
vagrant_package
|
||||||
|
@box_name = ENV['BOX_NAME']
|
||||||
|
# This will make
|
||||||
|
ENV["BOX_NAME"] = 'new-box'
|
||||||
|
ENV['BOX_URL'] = '/vagrant/spec/tmp/package.box'
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:all) do
|
||||||
|
vagrant_box_remove('new-box')
|
||||||
|
ENV["BOX_NAME"] = @box_name
|
||||||
|
ENV['BOX_URL'] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a package that can be successfully brought up on a later `vagrant up`' do
|
||||||
|
vagrant_up
|
||||||
|
# Just to make sure we packaged it properly
|
||||||
|
expect(vagrant_ssh('cat /home/vagrant/original-box')).to eq @box_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
76
spec/acceptance/support/acceptance_example_group.rb
Normal file
76
spec/acceptance/support/acceptance_example_group.rb
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
module AcceptanceExampleGroup
|
||||||
|
def self.included(base)
|
||||||
|
base.metadata[:type] = :acceptance
|
||||||
|
end
|
||||||
|
|
||||||
|
ID_FILE = "/vagrant/spec/.vagrant/machines/default/lxc/id"
|
||||||
|
def vagrant_container_name
|
||||||
|
File.read(ID_FILE).strip.chomp if File.exists?(ID_FILE)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_container
|
||||||
|
if name = vagrant_container_name
|
||||||
|
`sudo lxc-shutdown -n #{name} 2>/dev/null`
|
||||||
|
`sudo lxc-wait -n #{name} --state STOPPED 2>/dev/null`
|
||||||
|
`sudo lxc-destroy -n #{name} 2>/dev/null`
|
||||||
|
`rm -rf /vagrant/spec/.vagrant/`
|
||||||
|
end
|
||||||
|
`sudo killall -9 redir 2>/dev/null`
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_vagrant_environment
|
||||||
|
opts = { cwd: '/vagrant/spec', ui_class: TestUI }
|
||||||
|
env = Vagrant::Environment.new(opts)
|
||||||
|
yield env
|
||||||
|
env.unload
|
||||||
|
end
|
||||||
|
|
||||||
|
def vagrant_up
|
||||||
|
with_vagrant_environment do |env|
|
||||||
|
env.cli('up', '--provider', 'lxc')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def vagrant_halt
|
||||||
|
with_vagrant_environment do |env|
|
||||||
|
env.cli('halt')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def vagrant_destroy
|
||||||
|
with_vagrant_environment do |env|
|
||||||
|
env.cli('destroy', '-f')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def vagrant_ssh(cmd)
|
||||||
|
output = nil
|
||||||
|
with_vagrant_environment do |env|
|
||||||
|
result = env.cli('ssh', '-c', cmd)
|
||||||
|
if result.to_i != 0
|
||||||
|
raise "SSH command failed: '#{cmd}'\n#{env.ui.messages.inspect}"
|
||||||
|
end
|
||||||
|
output = env.ui.messages[:info].join("\n").chomp
|
||||||
|
end
|
||||||
|
output
|
||||||
|
end
|
||||||
|
|
||||||
|
def vagrant_package
|
||||||
|
with_vagrant_environment do |env|
|
||||||
|
pkg = '/vagrant/spec/tmp/package.box'
|
||||||
|
`rm -f #{pkg}`
|
||||||
|
env.cli('package', '--output', pkg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def vagrant_box_remove(name)
|
||||||
|
with_vagrant_environment do |env|
|
||||||
|
env.cli('box', 'list')
|
||||||
|
output = env.ui.messages[:info].join("\n").chomp
|
||||||
|
|
||||||
|
if output.include?(name)
|
||||||
|
env.cli('box', 'remove', name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
12
spec/acceptance/support/machine_ext.rb
Normal file
12
spec/acceptance/support/machine_ext.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Monkey patch vagrant in order to reuse the UI test object that is set on
|
||||||
|
# our Vagrant::Environments
|
||||||
|
#
|
||||||
|
require 'vagrant/machine'
|
||||||
|
Vagrant::Machine.class_eval do
|
||||||
|
alias :old_action :action
|
||||||
|
|
||||||
|
define_method :action do |action_name, extra_env = nil|
|
||||||
|
extra_env = { ui: @env.ui }.merge(extra_env || {})
|
||||||
|
old_action action_name, extra_env
|
||||||
|
end
|
||||||
|
end
|
22
spec/acceptance/support/test_ui.rb
Normal file
22
spec/acceptance/support/test_ui.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
class TestUI < Vagrant::UI::Interface
|
||||||
|
attr_reader :messages
|
||||||
|
|
||||||
|
METHODS = [:clear_line, :report_progress, :warn, :error, :info, :success]
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
@messages = METHODS.each_with_object({}) { |m, h| h[m] = [] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def ask(*args)
|
||||||
|
super
|
||||||
|
# Automated tests should not depend on user input, obviously.
|
||||||
|
raise Errors::UIExpectsTTY
|
||||||
|
end
|
||||||
|
|
||||||
|
METHODS.each do |method|
|
||||||
|
define_method(method) do |*args|#message, *opts|
|
||||||
|
@messages[method].push args[0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
spec/acceptance_helper.rb
Normal file
21
spec/acceptance_helper.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
unless ENV['USER'] == 'vagrant'
|
||||||
|
puts 'Acceptance specs are supposed to run from one of the vagrant-lxc dev machines'
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined? SimpleCov
|
||||||
|
SimpleCov.command_name 'acceptance'
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'vagrant'
|
||||||
|
require 'vagrant-lxc'
|
||||||
|
|
||||||
|
Dir[File.dirname(__FILE__) + "/acceptance/support/**/*.rb"].each { |f| require f }
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
config.include AcceptanceExampleGroup, :type => :acceptance, :example_group => {
|
||||||
|
:file_path => /\bspec\/acceptance\//
|
||||||
|
}
|
||||||
|
end
|
|
@ -10,10 +10,22 @@ require 'bundler/setup'
|
||||||
|
|
||||||
require 'i18n'
|
require 'i18n'
|
||||||
|
|
||||||
require 'vagrant-lxc'
|
require 'rspec-spies'
|
||||||
|
|
||||||
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
|
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
|
||||||
|
|
||||||
|
# If we should verify constant names, eager loads
|
||||||
|
if ENV['VERIFY_CONSTANT_NAMES']
|
||||||
|
require 'vagrant-lxc/plugin'
|
||||||
|
require 'vagrant-lxc/provider'
|
||||||
|
require 'vagrant-lxc/config'
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'rspec/fire'
|
||||||
|
RSpec::Fire.configure do |config|
|
||||||
|
config.verify_constant_names = ENV['VERIFY_CONSTANT_NAMES'] == '1'
|
||||||
|
end
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
config.treat_symbols_as_metadata_keys_with_true_values = true
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
||||||
config.run_all_when_everything_filtered = true
|
config.run_all_when_everything_filtered = true
|
||||||
|
@ -24,12 +36,4 @@ RSpec.configure do |config|
|
||||||
# the seed, which is printed after each run.
|
# the seed, which is printed after each run.
|
||||||
# --seed 1234
|
# --seed 1234
|
||||||
config.order = 'random'
|
config.order = 'random'
|
||||||
|
|
||||||
config.mock_with :rspec do |c|
|
|
||||||
c.yield_receiver_to_any_instance_implementation_blocks = true
|
|
||||||
end
|
|
||||||
config.expect_with :rspec do |c|
|
|
||||||
c.syntax = :expect
|
|
||||||
end
|
|
||||||
config.raise_errors_for_deprecations!
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,12 +24,12 @@ describe Vagrant::LXC::Action::ClearForwardedPorts do
|
||||||
after { FileUtils.rm_rf data_dir.to_s }
|
after { FileUtils.rm_rf data_dir.to_s }
|
||||||
|
|
||||||
it 'removes all files under pid directory' do
|
it 'removes all files under pid directory' do
|
||||||
expect(Dir[pids_dir.to_s + "/redir_*.pid"]).to be_empty
|
Dir[pids_dir.to_s + "/redir_*.pid"].should be_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a valid redir pid' do
|
context 'with a valid redir pid' do
|
||||||
it 'kills known processes' do
|
it 'kills known processes' do
|
||||||
expect(subject).to have_received(:system).with("pkill -TERM -P #{pid}")
|
subject.should have_received(:system).with("pkill -TERM -P #{pid}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ describe Vagrant::LXC::Action::ClearForwardedPorts do
|
||||||
let(:pid_cmd) { 'sudo ls' }
|
let(:pid_cmd) { 'sudo ls' }
|
||||||
|
|
||||||
it 'does not kill the process' do
|
it 'does not kill the process' do
|
||||||
expect(subject).not_to have_received(:system).with("pkill -TERM -P #{pid}")
|
subject.should_not have_received(:system).with("pkill -TERM -P #{pid}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
require 'unit_helper'
|
require 'unit_helper'
|
||||||
|
|
||||||
require 'vagrant-lxc/plugin'
|
|
||||||
require 'vagrant-lxc/provider'
|
|
||||||
require 'vagrant-lxc/action/compress_rootfs'
|
require 'vagrant-lxc/action/compress_rootfs'
|
||||||
|
|
||||||
describe Vagrant::LXC::Action::CompressRootFS do
|
describe Vagrant::LXC::Action::CompressRootFS do
|
||||||
let(:app) { double(:app, call: true) }
|
let(:app) { double(:app, call: true) }
|
||||||
let(:env) { {machine: machine, ui: double(info: true)} }
|
let(:env) { {machine: machine, ui: double(info: true)} }
|
||||||
let(:machine) { double(Vagrant::Machine, provider: provider) }
|
let(:machine) { instance_double('Vagrant::Machine', provider: provider) }
|
||||||
let(:provider) { double(Vagrant::LXC::Provider, driver: driver) }
|
let(:provider) { instance_double('Vagrant::LXC::Provider', driver: driver) }
|
||||||
let(:driver) { double(Vagrant::LXC::Driver, compress_rootfs: compressed_rootfs_path) }
|
let(:driver) { instance_double('Vagrant::LXC::Driver', compress_rootfs: compressed_rootfs_path) }
|
||||||
let(:compressed_rootfs_path) { '/path/to/rootfs.tar.gz' }
|
let(:compressed_rootfs_path) { '/path/to/rootfs.tar.gz' }
|
||||||
|
|
||||||
subject { described_class.new(app, env) }
|
subject { described_class.new(app, env) }
|
||||||
|
@ -20,10 +18,10 @@ describe Vagrant::LXC::Action::CompressRootFS do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "asks the driver to compress container's rootfs" do
|
it "asks the driver to compress container's rootfs" do
|
||||||
expect(driver).to have_received(:compress_rootfs)
|
driver.should have_received(:compress_rootfs)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets export.temp_dir on action env' do
|
it 'sets export.temp_dir on action env' do
|
||||||
expect(env['package.rootfs']).to eq(compressed_rootfs_path)
|
env['package.rootfs'].should == compressed_rootfs_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
require 'unit_helper'
|
require 'unit_helper'
|
||||||
|
|
||||||
require 'tmpdir'
|
require 'tmpdir'
|
||||||
require 'vagrant-lxc/provider'
|
require 'vagrant-lxc/errors'
|
||||||
require 'vagrant-lxc/action/forward_ports'
|
require 'vagrant-lxc/action/forward_ports'
|
||||||
|
|
||||||
describe Vagrant::LXC::Action::ForwardPorts do
|
describe Vagrant::LXC::Action::ForwardPorts do
|
||||||
let(:app) { double(:app, call: true) }
|
let(:app) { double(:app, call: true) }
|
||||||
let(:env) { {machine: machine, ui: double(info: true, warn: true)} }
|
let(:env) { {machine: machine, ui: double(info: true)} }
|
||||||
let(:machine) { double(:machine) }
|
let(:machine) { double(:machine) }
|
||||||
let!(:data_dir) { Pathname.new(Dir.mktmpdir) }
|
let!(:data_dir) { Pathname.new(Dir.mktmpdir) }
|
||||||
let(:provider) { double(Vagrant::LXC::Provider, ssh_info: {host: container_ip}) }
|
let(:provider) { instance_double('Vagrant::LXC::Provider', ssh_info: {host: container_ip}) }
|
||||||
let(:host_ip) { '127.0.0.1' }
|
let(:host_ip) { '127.0.0.1' }
|
||||||
let(:host_port) { 8080 }
|
let(:host_port) { 8080 }
|
||||||
let(:guest_port) { 80 }
|
let(:guest_port) { 80 }
|
||||||
|
@ -24,7 +24,6 @@ describe Vagrant::LXC::Action::ForwardPorts do
|
||||||
machine.stub_chain(:config, :vm, :networks).and_return(networks)
|
machine.stub_chain(:config, :vm, :networks).and_return(networks)
|
||||||
machine.stub(provider: provider, data_dir: data_dir)
|
machine.stub(provider: provider, data_dir: data_dir)
|
||||||
|
|
||||||
subject.stub(redir_version: 3)
|
|
||||||
subject.stub(exec: true)
|
subject.stub(exec: true)
|
||||||
subject.stub(spawn: pid)
|
subject.stub(spawn: pid)
|
||||||
end
|
end
|
||||||
|
@ -34,26 +33,26 @@ describe Vagrant::LXC::Action::ForwardPorts do
|
||||||
it 'forwards ports using redir' do
|
it 'forwards ports using redir' do
|
||||||
subject.stub(system: true)
|
subject.stub(system: true)
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
expect(subject).to have_received(:spawn).with(
|
subject.should have_received(:spawn).with(
|
||||||
"redir -n #{host_ip}:#{host_port} #{container_ip}:#{guest_port} 2>/dev/null"
|
"redir --laddr=#{host_ip} --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'Uses 127.0.0.1 as default if host_ip is nil' do
|
it 'skips --laddr parameter if host_ip is nil' do
|
||||||
forward_conf.delete(:host_ip)
|
forward_conf.delete(:host_ip)
|
||||||
subject.stub(system: true)
|
subject.stub(system: true)
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
expect(subject).to have_received(:spawn).with(
|
subject.should have_received(:spawn).with(
|
||||||
"redir -n 127.0.0.1:#{host_port} #{container_ip}:#{guest_port} 2>/dev/null"
|
"redir --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'Uses 127.0.0.1 by default if host_ip is a blank string' do
|
it 'skips --laddr parameter if host_ip is a blank string' do
|
||||||
forward_conf[:host_ip] = ' '
|
forward_conf[:host_ip] = ' '
|
||||||
subject.stub(system: true)
|
subject.stub(system: true)
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
expect(subject).to have_received(:spawn).with(
|
subject.should have_received(:spawn).with(
|
||||||
"redir -n 127.0.0.1:#{host_port} #{container_ip}:#{guest_port} 2>/dev/null"
|
"redir --lport=#{host_port} --caddr=#{container_ip} --cport=#{guest_port} 2>/dev/null"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,57 +60,18 @@ describe Vagrant::LXC::Action::ForwardPorts do
|
||||||
subject.stub(system: true)
|
subject.stub(system: true)
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
pid_file = data_dir.join('pids', "redir_#{host_port}.pid").read
|
pid_file = data_dir.join('pids', "redir_#{host_port}.pid").read
|
||||||
expect(pid_file).to eq(pid)
|
pid_file.should == pid
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'allows disabling a previously forwarded port' do
|
it 'allows disabling a previously forwarded port' do
|
||||||
forward_conf[:disabled] = true
|
forward_conf[:disabled] = true
|
||||||
subject.stub(system: true)
|
subject.stub(system: true)
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
expect(subject).not_to have_received(:spawn)
|
subject.should_not 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
|
end
|
||||||
|
|
||||||
it 'raises RedirNotInstalled error if `redir` is not installed' do
|
it 'raises RedirNotInstalled error if `redir` is not installed' do
|
||||||
subject.stub(system: false)
|
subject.stub(system: false)
|
||||||
expect { subject.call(env) }.to raise_error(Vagrant::LXC::Errors::RedirNotInstalled)
|
lambda { subject.call(env) }.should 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
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ require 'vagrant-lxc/action/handle_box_metadata'
|
||||||
|
|
||||||
describe Vagrant::LXC::Action::HandleBoxMetadata do
|
describe Vagrant::LXC::Action::HandleBoxMetadata do
|
||||||
let(:app) { double(:app, call: true) }
|
let(:app) { double(:app, call: true) }
|
||||||
let(:env) { {machine: machine, ui: double(info: true, warn: true)} }
|
let(:env) { {machine: machine, ui: double(info: true)} }
|
||||||
let(:machine) { double(:machine, box: box) }
|
let(:machine) { double(:machine, box: box) }
|
||||||
let(:box) { double(:box, name: 'box-name', metadata: metadata, directory: box_directory) }
|
let(:box) { double(:box, name: 'box-name', metadata: metadata, directory: box_directory) }
|
||||||
let(:box_directory) { Pathname.new('/path/to/box') }
|
let(:box_directory) { Pathname.new('/path/to/box') }
|
||||||
|
@ -16,111 +16,55 @@ describe Vagrant::LXC::Action::HandleBoxMetadata do
|
||||||
|
|
||||||
subject { described_class.new(app, env) }
|
subject { described_class.new(app, env) }
|
||||||
|
|
||||||
context 'with 1.0.0 box' do
|
context 'with valid contents' do
|
||||||
let(:version) { '1.0.0' }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
File.stub(exists?: true)
|
File.stub(exists?: true)
|
||||||
# REFACTOR: This is pretty bad
|
|
||||||
subject.stub_chain(:template_config_file, :exist?).and_return(true)
|
|
||||||
subject.stub_chain(:template_config_file, :to_s).and_return(box_directory.join('lxc-config').to_s)
|
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the tarball argument for the template' do
|
it 'sets the tarball argument for the template' do
|
||||||
expect(env[:lxc_template_opts]).to include(
|
env[:lxc_template_opts].should include(
|
||||||
'--tarball' => box_directory.join('rootfs.tar.gz').to_s
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the template --config parameter' do
|
|
||||||
expect(env[:lxc_template_opts]).to include(
|
|
||||||
'--config' => box_directory.join('lxc-config').to_s
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not set the auth key argument for the template' do
|
|
||||||
expect(env[:lxc_template_opts]).not_to include(
|
|
||||||
'--auth-key' => vagrant_key
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the template options from metadata on env hash' do
|
|
||||||
expect(env[:lxc_template_opts]).to include(metadata['template-opts'])
|
|
||||||
end
|
|
||||||
|
|
||||||
xit 'sets the template source path on env hash' do
|
|
||||||
expect(env[:lxc_template_src]).to eq(box_directory.join('lxc-template').to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not warn about deprecation' do
|
|
||||||
expect(env[:ui]).not_to have_received(:warn)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with valid pre 1.0.0 box' do
|
|
||||||
before do
|
|
||||||
File.stub(exists?: true)
|
|
||||||
# REFACTOR: This is pretty bad
|
|
||||||
subject.stub_chain(:old_template_config_file, :exist?).and_return(true)
|
|
||||||
subject.stub_chain(:old_template_config_file, :to_s).and_return(box_directory.join('lxc.conf').to_s)
|
|
||||||
subject.call(env)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the tarball argument for the template' do
|
|
||||||
expect(env[:lxc_template_opts]).to include(
|
|
||||||
'--tarball' => box_directory.join('rootfs.tar.gz').to_s
|
'--tarball' => box_directory.join('rootfs.tar.gz').to_s
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the auth key argument for the template' do
|
it 'sets the auth key argument for the template' do
|
||||||
expect(env[:lxc_template_opts]).to include(
|
env[:lxc_template_opts].should include(
|
||||||
'--auth-key' => vagrant_key
|
'--auth-key' => vagrant_key
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the lxc config file parameter' do
|
|
||||||
expect(env[:lxc_template_config]).to eq(box_directory.join('lxc.conf').to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the template options from metadata on env hash' do
|
it 'sets the template options from metadata on env hash' do
|
||||||
expect(env[:lxc_template_opts]).to include(metadata['template-opts'])
|
env[:lxc_template_opts].should include(metadata['template-opts'])
|
||||||
end
|
end
|
||||||
|
|
||||||
xit 'sets the template source path on env hash' do
|
it 'sets the template source path on env hash' do
|
||||||
expect(env[:lxc_template_src]).to eq(box_directory.join('lxc-template').to_s)
|
env[:lxc_template_src].should == box_directory.join('lxc-template').to_s
|
||||||
end
|
|
||||||
|
|
||||||
it 'warns about deprecation' do
|
|
||||||
expect(env[:ui]).to have_received(:warn)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'with invalid contents' do
|
describe 'with invalid contents' do
|
||||||
before { File.stub(exists?: true) }
|
before { File.stub(exists?: true) }
|
||||||
|
|
||||||
it 'validates box versions' do
|
it 'raises an error if the version is != 2' do
|
||||||
%w( 2 3 1.0.0 ).each do |v|
|
|
||||||
metadata['version'] = v
|
|
||||||
expect { subject.call(env) }.to_not raise_error
|
|
||||||
end
|
|
||||||
|
|
||||||
metadata['version'] = '1'
|
metadata['version'] = '1'
|
||||||
expect { subject.call(env) }.to raise_error
|
expect {
|
||||||
|
subject.call(env)
|
||||||
|
}.to raise_error(Vagrant::LXC::Errors::IncompatibleBox)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an error if the rootfs tarball cant be found' do
|
it 'raises an error if the rootfs tarball cant be found' do
|
||||||
allow(File).to receive(:exists?).with(box_directory.join('rootfs.tar.gz').to_s).and_return(false)
|
File.stub(:exists?).with(box_directory.join('rootfs.tar.gz').to_s).and_return(false)
|
||||||
expect {
|
expect {
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
}.to raise_error(Vagrant::LXC::Errors::RootFSTarballMissing)
|
}.to raise_error(Vagrant::LXC::Errors::RootFSTarballMissing)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not raise an error if the lxc-template script cant be found' do
|
it 'raises an error if the lxc-template script cant be found' do
|
||||||
allow(File).to receive(:exists?).with(box_directory.join('lxc-template').to_s).and_return(false)
|
File.stub(:exists?).with(box_directory.join('lxc-template').to_s).and_return(false)
|
||||||
expect {
|
expect {
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
}.to_not raise_error
|
}.to raise_error(Vagrant::LXC::Errors::TemplateFileMissing)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,16 +5,16 @@ require 'vagrant-lxc/action/setup_package_files'
|
||||||
describe Vagrant::LXC::Action::SetupPackageFiles do
|
describe Vagrant::LXC::Action::SetupPackageFiles do
|
||||||
let(:app) { double(:app, call: true) }
|
let(:app) { double(:app, call: true) }
|
||||||
let(:env) { {machine: machine, tmp_path: tmp_path, ui: double(info: true), 'package.rootfs' => rootfs_path} }
|
let(:env) { {machine: machine, tmp_path: tmp_path, ui: double(info: true), 'package.rootfs' => rootfs_path} }
|
||||||
let(:machine) { double(Vagrant::Machine, box: box) }
|
let(:machine) { instance_double('Vagrant::Machine', box: box) }
|
||||||
let!(:tmp_path) { Pathname.new(Dir.mktmpdir) }
|
let!(:tmp_path) { Pathname.new(Dir.mktmpdir) }
|
||||||
let(:box) { double(Vagrant::Box, directory: tmp_path.join('box')) }
|
let(:box) { instance_double('Vagrant::Box', directory: tmp_path.join('box')) }
|
||||||
let(:rootfs_path) { tmp_path.join('rootfs-amd64.tar.gz') }
|
let(:rootfs_path) { tmp_path.join('rootfs-amd64.tar.gz') }
|
||||||
|
|
||||||
subject { described_class.new(app, env) }
|
subject { described_class.new(app, env) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
box.directory.mkdir
|
box.directory.mkdir
|
||||||
files = %w( lxc-template metadata.json lxc.conf lxc-config ).map { |f| box.directory.join(f) }
|
files = %w( lxc-template metadata.json lxc.conf ).map { |f| box.directory.join(f) }
|
||||||
(files + [rootfs_path]).each do |file|
|
(files + [rootfs_path]).each do |file|
|
||||||
file.open('w') { |f| f.puts file.to_s }
|
file.open('w') { |f| f.puts file.to_s }
|
||||||
end
|
end
|
||||||
|
@ -30,34 +30,20 @@ describe Vagrant::LXC::Action::SetupPackageFiles do
|
||||||
before { subject.call(env) }
|
before { subject.call(env) }
|
||||||
|
|
||||||
it 'copies box lxc-template to package directory' do
|
it 'copies box lxc-template to package directory' do
|
||||||
expect(env['package.directory'].join('lxc-template')).to be_file
|
env['package.directory'].join('lxc-template').should be_file
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'copies metadata.json to package directory' do
|
it 'copies metadata.json to package directory' do
|
||||||
expect(env['package.directory'].join('metadata.json')).to be_file
|
env['package.directory'].join('metadata.json').should be_file
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'copies box lxc.conf to package directory' do
|
it 'copies box lxc.conf to package directory' do
|
||||||
expect(env['package.directory'].join('lxc-template')).to be_file
|
env['package.directory'].join('lxc-template').should be_file
|
||||||
end
|
|
||||||
|
|
||||||
it 'copies box lxc-config to package directory' do
|
|
||||||
expect(env['package.directory'].join('lxc-config')).to be_file
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'moves the compressed rootfs to package directory' do
|
it 'moves the compressed rootfs to package directory' do
|
||||||
expect(env['package.directory'].join(rootfs_path.basename)).to be_file
|
env['package.directory'].join(rootfs_path.basename).should be_file
|
||||||
expect(env['package.rootfs']).not_to be_file
|
env['package.rootfs'].should_not be_file
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when lxc-template file is not present' do
|
|
||||||
before do
|
|
||||||
box.directory.join('lxc-template').delete
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not blow up' do
|
|
||||||
expect { subject.call(env) }.to_not raise_error
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -70,14 +56,4 @@ describe Vagrant::LXC::Action::SetupPackageFiles do
|
||||||
expect { subject.call(env) }.to_not raise_error
|
expect { subject.call(env) }.to_not raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when lxc-config file is not present' do
|
|
||||||
before do
|
|
||||||
box.directory.join('lxc-config').delete
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not blow up' do
|
|
||||||
expect { subject.call(env) }.to_not raise_error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
require 'unit_helper'
|
require 'unit_helper'
|
||||||
|
|
||||||
require 'vagrant-lxc/sudo_wrapper'
|
|
||||||
require 'vagrant-lxc/driver/cli'
|
require 'vagrant-lxc/driver/cli'
|
||||||
|
|
||||||
describe Vagrant::LXC::Driver::CLI do
|
describe Vagrant::LXC::Driver::CLI do
|
||||||
let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true, wrapper_path: nil) }
|
let(:sudo_wrapper) { instance_double('Vagrant::LXC::SudoWrapper', run: true) }
|
||||||
|
|
||||||
subject { described_class.new(sudo_wrapper) }
|
subject { described_class.new(sudo_wrapper) }
|
||||||
|
|
||||||
|
@ -13,73 +12,51 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
let(:result) { @result }
|
let(:result) { @result }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:run).with(:ls).and_return(lxc_ls_out)
|
subject.stub(:run).with(:ls).and_return(lxc_ls_out)
|
||||||
@result = subject.list
|
@result = subject.list
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'grabs previously created containers from lxc-ls output' do
|
it 'grabs previously created containers from lxc-ls output' do
|
||||||
expect(result).to be_an Enumerable
|
result.should be_an Enumerable
|
||||||
expect(result).to include 'a-container'
|
result.should include 'a-container'
|
||||||
expect(result).to include 'dup-container'
|
result.should include 'dup-container'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes duplicates from lxc-ls output' do
|
it 'removes duplicates from lxc-ls output' do
|
||||||
expect(result.uniq).to eq(result)
|
result.uniq.should == result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'version' do
|
describe 'version' do
|
||||||
|
let(:lxc_version_out) { "lxc version: 0.x.y-rc1\n" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:run).with(:create, '--version').and_return(lxc_version_out)
|
subject.stub(:run).with(:version).and_return(lxc_version_out)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'lxc version after 1.x.x' do
|
it 'parses the version from the output' do
|
||||||
let(:lxc_version_out) { "1.0.0\n" }
|
subject.version.should == '0.x.y-rc1'
|
||||||
|
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'create' do
|
describe 'create' do
|
||||||
let(:template) { 'quantal-64' }
|
let(:template) { 'quantal-64' }
|
||||||
let(:name) { 'quantal-container' }
|
let(:name) { 'quantal-container' }
|
||||||
let(:backingstore) { 'btrfs' }
|
let(:config_file) { 'config' }
|
||||||
let(:backingstore_opts) { [['--dir', '/tmp/foo'], ['--foo', 'bar']] }
|
let(:template_args) { { '--extra-param' => 'param', '--other' => 'value' } }
|
||||||
let(:config_file) { 'config' }
|
|
||||||
let(:template_args) { { '--extra-param' => 'param', '--other' => 'value' } }
|
|
||||||
|
|
||||||
subject { described_class.new(sudo_wrapper, name) }
|
subject { described_class.new(sudo_wrapper, name) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:run) { |*args| @run_args = args }
|
subject.stub(:run) { |*args| @run_args = args }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'issues a lxc-create with provided template, container name and hash of arguments' do
|
it 'issues a lxc-create with provided template, container name and hash of arguments' do
|
||||||
subject.create(template, backingstore, backingstore_opts, config_file, template_args)
|
subject.create(template, config_file, template_args)
|
||||||
expect(subject).to have_received(:run).with(
|
subject.should have_received(:run).with(
|
||||||
:create,
|
:create,
|
||||||
'-B', backingstore,
|
|
||||||
'--template', template,
|
'--template', template,
|
||||||
'--name', name,
|
'--name', name,
|
||||||
*(backingstore_opts.flatten),
|
|
||||||
'-f', config_file,
|
'-f', config_file,
|
||||||
'--',
|
'--',
|
||||||
'--extra-param', 'param',
|
'--extra-param', 'param',
|
||||||
|
@ -88,9 +65,9 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'wraps a low level error into something more meaningful in case the container already exists' 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' }
|
subject.stub(:run) { raise Vagrant::LXC::Errors::ExecuteError, stderr: 'alreAdy Exists' }
|
||||||
expect {
|
expect {
|
||||||
subject.create(template, backingstore, backingstore_opts, config_file, template_args)
|
subject.create(template, config_file, template_args)
|
||||||
}.to raise_error(Vagrant::LXC::Errors::ContainerAlreadyExists)
|
}.to raise_error(Vagrant::LXC::Errors::ContainerAlreadyExists)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -101,12 +78,12 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
subject { described_class.new(sudo_wrapper, name) }
|
subject { described_class.new(sudo_wrapper, name) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:run)
|
subject.stub(:run)
|
||||||
subject.destroy
|
subject.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'issues a lxc-destroy with container name' do
|
it 'issues a lxc-destroy with container name' do
|
||||||
expect(subject).to have_received(:run).with(:destroy, '--name', name)
|
subject.should have_received(:run).with(:destroy, '--name', name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -115,12 +92,12 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
subject { described_class.new(sudo_wrapper, name) }
|
subject { described_class.new(sudo_wrapper, name) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:run)
|
subject.stub(:run)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'starts container on the background' do
|
it 'starts container on the background' do
|
||||||
subject.start
|
subject.start
|
||||||
expect(subject).to have_received(:run).with(
|
subject.should have_received(:run).with(
|
||||||
:start,
|
:start,
|
||||||
'-d',
|
'-d',
|
||||||
'--name', name
|
'--name', name
|
||||||
|
@ -128,17 +105,23 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'stop' do
|
describe 'shutdown' do
|
||||||
let(:name) { 'a-running-container' }
|
let(:name) { 'a-running-container' }
|
||||||
subject { described_class.new(sudo_wrapper, name) }
|
subject { described_class.new(sudo_wrapper, name) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:run)
|
subject.stub(system: true)
|
||||||
subject.stop
|
subject.stub(:run)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'issues a lxc-stop with provided container name' do
|
it 'issues a lxc-shutdown with provided container name' do
|
||||||
expect(subject).to have_received(:run).with(:stop, '--name', name)
|
subject.shutdown
|
||||||
|
subject.should have_received(:run).with(:shutdown, '--name', name)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises a ShutdownNotSupported in case it is not supported' do
|
||||||
|
subject.stub(:system).with('which lxc-shutdown > /dev/null').and_return(false)
|
||||||
|
expect { subject.shutdown }.to raise_error(described_class::ShutdownNotSupported)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -147,21 +130,21 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
subject { described_class.new(sudo_wrapper, name) }
|
subject { described_class.new(sudo_wrapper, name) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:run).and_return("state: STOPPED\npid: 2")
|
subject.stub(:run).and_return("state: STOPPED\npid: 2")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls lxc-info with the right arguments' do
|
it 'calls lxc-info with the right arguments' do
|
||||||
subject.state
|
subject.state
|
||||||
expect(subject).to have_received(:run).with(:info, '--name', name, retryable: true)
|
subject.should have_received(:run).with(:info, '--name', name, retryable: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'maps the output of lxc-info status out to a symbol' do
|
it 'maps the output of lxc-info status out to a symbol' do
|
||||||
expect(subject.state).to eq(:stopped)
|
subject.state.should == :stopped
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is not case sensitive' do
|
it 'is not case sensitive' do
|
||||||
allow(subject).to receive(:run).and_return("StatE: STarTED\npid: 2")
|
subject.stub(:run).and_return("StatE: STarTED\npid: 2")
|
||||||
expect(subject.state).to eq(:started)
|
subject.state.should == :started
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -177,25 +160,35 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
|
|
||||||
it 'calls lxc-attach with specified command' do
|
it 'calls lxc-attach with specified command' do
|
||||||
subject.attach(*command)
|
subject.attach(*command)
|
||||||
expect(subject).to have_received(:run).with(:attach, '--name', name, '--', *command)
|
subject.should have_received(:run).with(:attach, '--name', name, '--', *command)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'supports a "namespaces" parameter' do
|
it 'supports a "namespaces" parameter' do
|
||||||
allow(subject).to receive(:run).with(:attach, '-h', :show_stderr => true).and_return({:stdout => '', :stderr => '--namespaces'})
|
subject.stub(:run).with(:attach, '-h', :show_stderr => true).and_return({:stdout => '', :stderr => '--namespaces'})
|
||||||
subject.attach *(command + [{namespaces: ['network', 'mount']}])
|
subject.attach *(command + [{namespaces: ['network', 'mount']}])
|
||||||
expect(subject).to have_received(:run).with(:attach, '--name', name, '--namespaces', 'NETWORK|MOUNT', '--', *command)
|
subject.should have_received(:run).with(:attach, '--name', name, '--namespaces', 'NETWORK|MOUNT', '--', *command)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises a NamespacesNotSupported error if not supported' do
|
||||||
|
subject.stub(: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
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'transition block' do
|
describe 'transition block' do
|
||||||
|
let(:name) { 'a-running-container' }
|
||||||
|
subject { described_class.new(name) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
subject.stub(run: true, sleep: true, state: :stopped)
|
subject.stub(run: true, sleep: true, state: :stopped)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'yields a cli object' do
|
it 'yields a cli object' do
|
||||||
allow(subject).to receive(:shutdown)
|
subject.stub(:shutdown)
|
||||||
subject.transition_to(:stopped) { |c| c.shutdown }
|
subject.transition_to(:stopped) { |c| c.shutdown }
|
||||||
expect(subject).to have_received(:shutdown)
|
subject.should have_received(:shutdown)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'throws an exception if block is not provided' do
|
it 'throws an exception if block is not provided' do
|
||||||
|
@ -204,6 +197,6 @@ describe Vagrant::LXC::Driver::CLI do
|
||||||
}.to raise_error(described_class::TransitionBlockNotProvided)
|
}.to raise_error(described_class::TransitionBlockNotProvided)
|
||||||
end
|
end
|
||||||
|
|
||||||
skip 'waits for the expected container state'
|
pending 'waits for the expected container state'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
require 'unit_helper'
|
require 'unit_helper'
|
||||||
|
|
||||||
|
require 'vagrant'
|
||||||
require 'vagrant-lxc/driver'
|
require 'vagrant-lxc/driver'
|
||||||
require 'vagrant-lxc/driver/cli'
|
require 'vagrant-lxc/driver/cli'
|
||||||
require 'vagrant-lxc/sudo_wrapper'
|
|
||||||
|
|
||||||
describe Vagrant::LXC::Driver do
|
describe Vagrant::LXC::Driver do
|
||||||
describe 'container name validation' do
|
describe 'container name validation' do
|
||||||
let(:unknown_container) { described_class.new('unknown', nil, cli) }
|
let(:unknown_container) { described_class.new('unknown', nil, cli) }
|
||||||
let(:valid_container) { described_class.new('valid', nil, cli) }
|
let(:valid_container) { described_class.new('valid', nil, cli) }
|
||||||
let(:new_container) { described_class.new(nil, nil) }
|
let(:new_container) { described_class.new(nil, nil) }
|
||||||
let(:cli) { double(Vagrant::LXC::Driver::CLI, list: ['valid']) }
|
let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', list: ['valid']) }
|
||||||
|
|
||||||
it 'raises a ContainerNotFound error if an unknown container name gets provided' do
|
it 'raises a ContainerNotFound error if an unknown container name gets provided' do
|
||||||
expect {
|
expect {
|
||||||
|
@ -31,32 +31,28 @@ describe Vagrant::LXC::Driver do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'creation' do
|
describe 'creation' do
|
||||||
let(:name) { 'container-name' }
|
let(:name) { 'container-name' }
|
||||||
let(:backingstore) { 'btrfs' }
|
let(:template_name) { 'auto-assigned-template-id' }
|
||||||
let(:backingstore_opts) { [['--dir', '/tmp/foo'], ['--foo', 'bar']] }
|
let(:template_path) { '/path/to/lxc-template-from-box' }
|
||||||
let(:template_name) { 'auto-assigned-template-id' }
|
let(:template_opts) { {'--some' => 'random-option'} }
|
||||||
let(:template_path) { '/path/to/lxc-template-from-box' }
|
let(:config_file) { '/path/to/lxc-config-from-box' }
|
||||||
let(:template_opts) { {'--some' => 'random-option'} }
|
let(:rootfs_tarball) { '/path/to/cache/rootfs.tar.gz' }
|
||||||
let(:config_file) { '/path/to/lxc-config-from-box' }
|
let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', :create => true, :name= => true) }
|
||||||
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) }
|
subject { described_class.new(nil, nil, cli) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(subject).to receive(:import_template).and_yield(template_name)
|
subject.stub(:import_template).and_yield(template_name)
|
||||||
subject.create name, backingstore, backingstore_opts, template_path, config_file, template_opts
|
subject.create name, template_path, config_file, template_opts
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the cli object container name' do
|
it 'sets the cli object container name' do
|
||||||
expect(cli).to have_received(:name=).with(name)
|
cli.should have_received(:name=).with(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates container with the right arguments' do
|
it 'creates container with the right arguments' do
|
||||||
expect(cli).to have_received(:create).with(
|
cli.should have_received(:create).with(
|
||||||
template_path,
|
template_name,
|
||||||
backingstore,
|
|
||||||
backingstore_opts,
|
|
||||||
config_file,
|
config_file,
|
||||||
template_opts
|
template_opts
|
||||||
)
|
)
|
||||||
|
@ -64,32 +60,26 @@ describe Vagrant::LXC::Driver do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'destruction' do
|
describe 'destruction' do
|
||||||
let(:cli) { double(Vagrant::LXC::Driver::CLI, destroy: true) }
|
let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', destroy: true) }
|
||||||
|
|
||||||
subject { described_class.new('name', nil, cli) }
|
subject { described_class.new('name', nil, cli) }
|
||||||
|
|
||||||
before { subject.destroy }
|
before { subject.destroy }
|
||||||
|
|
||||||
it 'delegates to cli object' do
|
it 'delegates to cli object' do
|
||||||
expect(cli).to have_received(:destroy)
|
cli.should have_received(:destroy)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'start' do
|
describe 'start' do
|
||||||
let(:customizations) { [['a', '1'], ['b', '2']] }
|
let(:customizations) { [['a', '1'], ['b', '2']] }
|
||||||
let(:internal_customization) { ['internal', 'customization'] }
|
let(:internal_customization) { ['internal', 'customization'] }
|
||||||
let(:cli) { double(Vagrant::LXC::Driver::CLI, start: true) }
|
let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', start: true) }
|
||||||
let(:sudo) { double(Vagrant::LXC::SudoWrapper) }
|
let(:sudo) { instance_double('Vagrant::LXC::SudoWrapper', su_c: true) }
|
||||||
|
|
||||||
subject { described_class.new('name', sudo, cli) }
|
subject { described_class.new('name', sudo, cli) }
|
||||||
|
|
||||||
before do
|
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.customizations << internal_customization
|
||||||
subject.start(customizations)
|
subject.start(customizations)
|
||||||
end
|
end
|
||||||
|
@ -99,159 +89,78 @@ describe Vagrant::LXC::Driver do
|
||||||
it 'writes configurations to config file'
|
it 'writes configurations to config file'
|
||||||
|
|
||||||
it 'starts container with configured customizations' do
|
it 'starts container with configured customizations' do
|
||||||
expect(cli).to have_received(:start)
|
cli.should have_received(:start)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'halt' do
|
describe 'halt' do
|
||||||
let(:cli) { double(Vagrant::LXC::Driver::CLI, stop: true) }
|
let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', shutdown: true) }
|
||||||
|
|
||||||
subject { described_class.new('name', nil, cli) }
|
subject { described_class.new('name', nil, cli) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(cli).to receive(:transition_to).and_yield(cli)
|
cli.stub(:transition_to).and_yield(cli)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'delegates to cli stop' do
|
it 'delegates to cli shutdown' do
|
||||||
expect(cli).to receive(:stop)
|
cli.should_receive(:shutdown)
|
||||||
subject.forced_halt
|
subject.forced_halt
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'expects a transition to running state to take place' do
|
it 'expects a transition to running state to take place' do
|
||||||
expect(cli).to receive(:transition_to).with(:stopped)
|
cli.should_receive(:transition_to).with(:stopped)
|
||||||
subject.forced_halt
|
subject.forced_halt
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'attempts to force the container to stop in case a shutdown doesnt work' 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)
|
cli.stub(:shutdown).and_raise(Vagrant::LXC::Driver::CLI::TargetStateNotReached.new :target, :source)
|
||||||
expect(cli).to receive(:transition_to).with(:stopped)
|
cli.should_receive(:transition_to).with(:stopped).twice
|
||||||
expect(cli).to receive(:stop)
|
cli.should_receive(:stop)
|
||||||
|
subject.forced_halt
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'attempts to force the container to stop in case lxc-shutdown is not supported' do
|
||||||
|
cli.stub(:shutdown).and_raise(Vagrant::LXC::Driver::CLI::ShutdownNotSupported)
|
||||||
|
cli.should_receive(:transition_to).with(:stopped).twice
|
||||||
|
cli.should_receive(:stop)
|
||||||
subject.forced_halt
|
subject.forced_halt
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'state' do
|
describe 'state' do
|
||||||
let(:cli_state) { :something }
|
let(:cli_state) { :something }
|
||||||
let(:cli) { double(Vagrant::LXC::Driver::CLI, state: cli_state) }
|
let(:cli) { instance_double('Vagrant::LXC::Driver::CLI', state: cli_state) }
|
||||||
|
|
||||||
subject { described_class.new('name', nil, cli) }
|
subject { described_class.new('name', nil, cli) }
|
||||||
|
|
||||||
it 'delegates to cli' do
|
it 'delegates to cli' do
|
||||||
expect(subject.state).to eq(cli_state)
|
subject.state.should == cli_state
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'folder sharing' do
|
describe 'folder sharing' do
|
||||||
let(:shared_folder) { {guestpath: '/vagrant', hostpath: '/path/to/host/dir'} }
|
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] }
|
||||||
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') }
|
let(:rootfs_path) { Pathname('/path/to/rootfs') }
|
||||||
|
let(:expected_guest_path) { "#{rootfs_path}/vagrant" }
|
||||||
|
let(:sudo_wrapper) { instance_double('Vagrant::LXC::SudoWrapper', run: true) }
|
||||||
|
|
||||||
subject { described_class.new('name', sudo_wrapper) }
|
subject { described_class.new('name', sudo_wrapper) }
|
||||||
|
|
||||||
describe "with fixed rootfs" do
|
before do
|
||||||
before do
|
subject.stub(rootfs_path: rootfs_path, system: true)
|
||||||
subject.stub(rootfs_path: Pathname('/path/to/rootfs'), system: true)
|
subject.share_folders(folders)
|
||||||
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
|
end
|
||||||
|
|
||||||
describe "with directory-based LXC config" do
|
it "creates guest folder under container's rootfs" do
|
||||||
let(:config_string) {
|
sudo_wrapper.should have_received(:run).with("mkdir", "-p", expected_guest_path)
|
||||||
<<-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
|
end
|
||||||
|
|
||||||
describe "with overlayfs-based LXC config" do
|
it 'adds a mount.entry to its local customizations' do
|
||||||
let(:config_string) {
|
subject.customizations.should include [
|
||||||
<<-ENDCONFIG.gsub(/^\s+/, '')
|
'mount.entry',
|
||||||
# Blah blah comment
|
"#{shared_folder[:hostpath]} #{expected_guest_path} none bind 0 0"
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,23 +2,23 @@ module UnitExampleGroup
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
base.metadata[:type] = :unit
|
base.metadata[:type] = :unit
|
||||||
base.before do
|
base.before do
|
||||||
allow_any_instance_of(Object).to receive(:system) { |instance, *args, &block|
|
Object.any_instance.stub(:system) { |*args, &block|
|
||||||
UnitExampleGroup.prevent_system_calls(*args, &block)
|
UnitExampleGroup.prevent_system_calls(*args, &block)
|
||||||
}
|
}
|
||||||
allow_any_instance_of(Object).to receive(:`) { |instance, *args, &block|
|
Object.any_instance.stub(:`) { |*args, &block|
|
||||||
UnitExampleGroup.prevent_system_calls(*args, &block)
|
UnitExampleGroup.prevent_system_calls(*args, &block)
|
||||||
}
|
}
|
||||||
allow_any_instance_of(Object).to receive(:exec) { |instance, *args, &block|
|
Object.any_instance.stub(:exec) { |*args, &block|
|
||||||
UnitExampleGroup.prevent_system_calls(*args, &block)
|
UnitExampleGroup.prevent_system_calls(*args, &block)
|
||||||
}
|
}
|
||||||
allow_any_instance_of(Object).to receive(:fork) { |instance, *args, &block|
|
Object.any_instance.stub(:fork) { |*args, &block|
|
||||||
UnitExampleGroup.prevent_system_calls(*args, &block)
|
UnitExampleGroup.prevent_system_calls(*args, &block)
|
||||||
}
|
}
|
||||||
allow_any_instance_of(Object).to receive(:spawn) { |instance, *args, &block|
|
Object.any_instance.stub(:spawn) { |*args, &block|
|
||||||
UnitExampleGroup.prevent_system_calls(*args, &block)
|
UnitExampleGroup.prevent_system_calls(*args, &block)
|
||||||
}
|
}
|
||||||
require 'vagrant/util/subprocess'
|
require 'vagrant/util/subprocess'
|
||||||
allow(Vagrant::Util::Subprocess).to receive(:execute) { |*args, &block|
|
Vagrant::Util::Subprocess.stub(:execute) { |*args, &block|
|
||||||
UnitExampleGroup.prevent_system_calls(*args, &block)
|
UnitExampleGroup.prevent_system_calls(*args, &block)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,11 +7,9 @@ if defined? SimpleCov
|
||||||
end
|
end
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
|
config.include RSpec::Fire
|
||||||
|
|
||||||
config.include UnitExampleGroup, :type => :unit, :example_group => {
|
config.include UnitExampleGroup, :type => :unit, :example_group => {
|
||||||
:file_path => /\bspec\/unit\//
|
:file_path => /\bspec\/unit\//
|
||||||
}
|
}
|
||||||
|
|
||||||
config.mock_with :rspec do |c|
|
|
||||||
c.yield_receiver_to_any_instance_implementation_blocks = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ begin
|
||||||
require 'coveralls/rake/task'
|
require 'coveralls/rake/task'
|
||||||
|
|
||||||
desc 'Run all specs'
|
desc 'Run all specs'
|
||||||
task :spec => ['spec:set_coverage', 'spec:unit', 'spec:acceptance']
|
task :spec => ['spec:unit', 'spec:acceptance']
|
||||||
|
|
||||||
desc 'Default task which runs all specs with code coverage enabled'
|
desc 'Default task which runs all specs with code coverage enabled'
|
||||||
task :default => ['spec:set_coverage', 'spec:unit']
|
task :default => ['spec:set_coverage', 'spec:unit']
|
||||||
|
@ -17,24 +17,17 @@ namespace :spec do
|
||||||
ENV['COVERAGE'] = 'true'
|
ENV['COVERAGE'] = 'true'
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Run acceptance specs using vagrant-spec'
|
def types
|
||||||
task :acceptance do
|
dirs = Dir['./spec/**/*_spec.rb'].map { |f| f.sub(/^\.\/(spec\/\w+)\/.*/, '\\1') }.uniq
|
||||||
components = %w(
|
Hash[dirs.map { |d| [d.split('/').last, d] }]
|
||||||
basic
|
|
||||||
network/forwarded_port
|
|
||||||
synced_folder
|
|
||||||
synced_folder/nfs
|
|
||||||
synced_folder/rsync
|
|
||||||
provisioner/shell
|
|
||||||
provisioner/puppet
|
|
||||||
provisioner/chef-solo
|
|
||||||
package
|
|
||||||
).map{|s| "provider/lxc/#{s}" }
|
|
||||||
sh "export ACCEPTANCE=true && bundle exec vagrant-spec test --components=#{components.join(' ')}"
|
|
||||||
end
|
end
|
||||||
|
types.each do |type, dir|
|
||||||
|
desc "Run the code examples in #{dir}"
|
||||||
|
RSpec::Core::RakeTask.new(type) do |t|
|
||||||
|
# Tells rspec-fire to verify if constants used really exist
|
||||||
|
ENV['VERIFY_CONSTANT_NAMES'] = '1'
|
||||||
|
|
||||||
desc "Run unit specs with rspec"
|
t.pattern = "./#{dir}/**/*_spec.rb"
|
||||||
RSpec::Core::RakeTask.new(:unit) do |t|
|
end
|
||||||
t.pattern = "./unit/**/*_spec.rb"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
#!<%= 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)
|
|
|
@ -1,24 +0,0 @@
|
||||||
# FIXME: Figure out why this doesn't work
|
|
||||||
if ENV['COVERAGE'] == 'true'
|
|
||||||
require 'simplecov'
|
|
||||||
require 'coveralls'
|
|
||||||
|
|
||||||
SimpleCov.start { add_filter '/spec/' }
|
|
||||||
SimpleCov.command_name 'acceptance'
|
|
||||||
end
|
|
||||||
|
|
||||||
if ENV['BOX_PATH'] == nil
|
|
||||||
latest = ENV.fetch('LATEST_BOXES','2014-03-21')
|
|
||||||
release = ENV.fetch('RELEASE', 'acceptance')
|
|
||||||
local_path ="#{File.expand_path("../", __FILE__)}/boxes/output/#{latest}/vagrant-lxc-#{release}-amd64.box"
|
|
||||||
if File.exists?(local_path)
|
|
||||||
ENV['BOX_PATH'] = local_path
|
|
||||||
else
|
|
||||||
raise 'Set $BOX_PATH to the latest released boxes'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Vagrant::Spec::Acceptance.configure do |c|
|
|
||||||
c.component_paths << "spec/acceptance"
|
|
||||||
c.provider 'lxc', box: ENV['BOX_PATH'], features: ['!suspend']
|
|
||||||
end
|
|
Loading…
Reference in a new issue