vagrant-xhyve 0.1.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile +13 -0
  6. data/LICENSE +9 -0
  7. data/README.md +140 -0
  8. data/Rakefile +22 -0
  9. data/example_box/README.md +31 -0
  10. data/example_box/initrd.gz +0 -0
  11. data/example_box/metadata.json +3 -0
  12. data/example_box/vmlinuz +0 -0
  13. data/lib/vagrant-xhyve/action/boot.rb +142 -0
  14. data/lib/vagrant-xhyve/action/import.rb +59 -0
  15. data/lib/vagrant-xhyve/action/is_created.rb +18 -0
  16. data/lib/vagrant-xhyve/action/is_stopped.rb +18 -0
  17. data/lib/vagrant-xhyve/action/message_already_created.rb +16 -0
  18. data/lib/vagrant-xhyve/action/message_not_created.rb +16 -0
  19. data/lib/vagrant-xhyve/action/message_will_not_destroy.rb +16 -0
  20. data/lib/vagrant-xhyve/action/read_ssh_info.rb +33 -0
  21. data/lib/vagrant-xhyve/action/read_state.rb +43 -0
  22. data/lib/vagrant-xhyve/action/stop_instance.rb +45 -0
  23. data/lib/vagrant-xhyve/action/terminate_instance.rb +47 -0
  24. data/lib/vagrant-xhyve/action/timed_provision.rb +21 -0
  25. data/lib/vagrant-xhyve/action/wait_for_state.rb +41 -0
  26. data/lib/vagrant-xhyve/action.rb +193 -0
  27. data/lib/vagrant-xhyve/config.rb +66 -0
  28. data/lib/vagrant-xhyve/errors.rb +19 -0
  29. data/lib/vagrant-xhyve/plugin.rb +73 -0
  30. data/lib/vagrant-xhyve/provider.rb +50 -0
  31. data/lib/vagrant-xhyve/util/timer.rb +17 -0
  32. data/lib/vagrant-xhyve/util/vagrant-xhyve.rb +50 -0
  33. data/lib/vagrant-xhyve/version.rb +5 -0
  34. data/lib/vagrant-xhyve.rb +18 -0
  35. data/locales/en.yml +83 -0
  36. data/spec/spec_helper.rb +1 -0
  37. data/spec/vagrant-xhyve/config_spec.rb +33 -0
  38. data/templates/metadata.json.erb +3 -0
  39. data/templates/vagrant-aws_package_Vagrantfile.erb +5 -0
  40. data/vagrant-xhyve.gemspec +60 -0
  41. metadata +158 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e86cc52b4ca725cdda0aef517879001aa4e3840e
4
+ data.tar.gz: d61ffc7960f9d079c37ffef1f0f90200f45f922b
5
+ SHA512:
6
+ metadata.gz: 160141682ee37beed607aef94bf476e31d8af4c42742090b3755e381ecb14ecb840bd3646455327a53af6ceca7c7da42e5757a07501e97b464757172250496ec
7
+ data.tar.gz: b026f9a63b2483c747c4413ddf051f81ca32029d9edf9fe60959923fb6c1b2beeb9a51f889831d93467ee0cd1549fbcbee4927e4884659d8f717847a338a5279
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ # OS-specific
2
+ .DS_Store
3
+
4
+ # editors
5
+ *.swp
6
+
7
+ # Bundler/Rubygems
8
+ *.gem
9
+ .bundle
10
+ pkg/*
11
+ tags
12
+ Gemfile.lock
13
+
14
+ # Vagrant
15
+ .vagrant
16
+ Vagrantfile
17
+ example_box
18
+ example.box
19
+
20
+ # RVM files for gemset/ruby setting
21
+ .ruby-*
22
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format doc --order random --color --fail-fast
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # 0.1.0 (April xx, 2016)
2
+
3
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "https://rubygems.org"
2
+
3
+ group :plugins do
4
+ gemspec
5
+ end
6
+
7
+ group :development do
8
+ # We depend on Vagrant for development, but we don't add it as a
9
+ # gem dependency because we expect to be installed within the
10
+ # Vagrant environment itself using `vagrant plugin`.
11
+ gem "vagrant", :git => "https://github.com/mitchellh/vagrant.git"
12
+ end
13
+
data/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2016 Patrick Armstrong
3
+ Copyright (c) 2014 Mitchell Hashimoto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # Vagrant xhyve Provider
2
+
3
+ This is a [Vagrant](http://www.vagrantup.com) plugin that adds an [xhyve](http://aws.amazon.com)
4
+ provider to Vagrant.
5
+
6
+ ## Features
7
+
8
+ * Sorta works
9
+
10
+ ## Limitations
11
+
12
+ You need to use sudo for most vagrant actions with the xhyve driver,
13
+ due to the entitlements needed for xhyve to run without sudo. More details
14
+ in the [xhyve github issue](https://github.com/mist64/xhyve/issues/60).
15
+
16
+ Also, sometimes launching a VM just fails. But I'm not quite sure why.
17
+
18
+ ## Usage
19
+
20
+ Install using standard Vagrant plugin installation methods. After
21
+ installing, `vagrant up` and specify the `xhyve` provider. An example is
22
+ shown below.
23
+
24
+ ```
25
+ $ vagrant plugin install vagrant-xhyve
26
+ ...
27
+ $ sudo vagrant up --provider=xhyve
28
+ ...
29
+ ```
30
+
31
+ Of course prior to doing this, you'll need to obtain an XHYVE-compatible
32
+ box file for Vagrant.
33
+
34
+ ## Quick Start
35
+
36
+ After installing the plugin (instructions above), the quickest way to get
37
+ started is to actually use a dummy AWS box and specify all the details
38
+ manually within a `config.vm.provider` block. So first, add the dummy
39
+ box using any name you want:
40
+
41
+ ```
42
+ $ vagrant box add oldpatricka/tinycorelinux
43
+ ...
44
+ ```
45
+
46
+ And then make a Vagrantfile that looks like the following, filling in
47
+ your information where necessary.
48
+
49
+ ```
50
+ Vagrant.configure("2") do |config|
51
+ config.vm.box = "oldpatricka/tinycorelinux"
52
+
53
+ config.vm.provider :xhyve do |xhyve|
54
+ xhyve.cpus = 1
55
+ xhyve.memory = 1G
56
+ end
57
+ end
58
+ ```
59
+
60
+ And then run `sudo vagrant up --provider=xhyve`.
61
+
62
+ This will start a Tiny Core Linux instance.
63
+
64
+ ## Box Format
65
+
66
+ The vagrant-xhyve box format is pretty straightforward. See
67
+ the [example_box/ directory](https://github.com/oldpatricka/vagrant-xhyve/tree/master/example_box).
68
+ That directory also contains instructions on how to build a box.
69
+
70
+ ## Configuration
71
+
72
+ This provider exposes quite a few provider-specific configuration options:
73
+
74
+ * `memory` - The amount of memory to give the VM. This can just be a simple
75
+ integer for memory in MB or you can use the suffixed style, eg. 2G for two
76
+ Gigabytes
77
+ * `cpus` - The number of CPUs to give the VM
78
+
79
+ These can be set like typical provider-specific configuration:
80
+
81
+ ```ruby
82
+ Vagrant.configure("2") do |config|
83
+ # ... other stuff
84
+
85
+ config.vm.provider :xhyve do |xhyve|
86
+ xhyve.cpus = 2
87
+ xhyve.memory = 1G
88
+ end
89
+ end
90
+ ```
91
+ ## Synced Folders
92
+
93
+ There is minimal support for synced folders. Upon `vagrant up`,
94
+ `vagrant reload`, and `vagrant provision`, the XHYVE provider will use
95
+ `rsync` (if available) to uni-directionally sync the folder to
96
+ the remote machine over SSH.
97
+
98
+ ## Questions
99
+
100
+ Q. Should I use this for my work?
101
+
102
+ A. Do you want to keep your job? I'm not even sure you should use this for toy
103
+ projects.
104
+
105
+ Q. Why?
106
+
107
+ A. This project is powered by ignorance and good intentions.
108
+
109
+ Q. Will I even not have to use sudo?
110
+
111
+ A. There's a theory in that issue linked above that wrapping xhyve in an
112
+ app store app would help. If that were the case, you could probably use the
113
+ embedded binary with vagrant-xhyve.
114
+
115
+ ## Development
116
+
117
+ To work on the `vagrant-xhyve` plugin, clone this repository out, and use
118
+ [Bundler](http://gembundler.com) to get the dependencies:
119
+
120
+ ```
121
+ $ bundle
122
+ ```
123
+
124
+ Once you have the dependencies, verify the unit tests pass with `rake`:
125
+
126
+ ```
127
+ $ bundle exec rake
128
+ ```
129
+
130
+ If those pass, you're ready to start developing the plugin. You can test
131
+ the plugin without installing it into your Vagrant environment by just
132
+ creating a `Vagrantfile` in the top level of this directory (it is gitignored)
133
+ and add the following line to your `Vagrantfile`
134
+ ```ruby
135
+ Vagrant.require_plugin "vagrant-xhyve"
136
+ ```
137
+ Use bundler to execute Vagrant:
138
+ ```
139
+ $ bundle exec vagrant up --provider=xhyve
140
+ ```
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file.
11
+ Dir.chdir(File.expand_path("../", __FILE__))
12
+
13
+ # This installs the tasks that help with gem creation and
14
+ # publishing.
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ # Install the `spec` task so that we can run tests.
18
+ RSpec::Core::RakeTask.new(:spec) do |t|
19
+ t.rspec_opts = "--order defined"
20
+ end
21
+ # Default task is to run the unit tests
22
+ task :default => :spec
@@ -0,0 +1,31 @@
1
+ # vagrant-xhyve Box Format
2
+
3
+ A vagrant-xhyve box, like all vagrant boxes is an archive of a directory of
4
+ files with a metadata file, a kernel, ramdisk, and optionally some raw disk
5
+ images.
6
+
7
+ Here's an example:
8
+
9
+ ```
10
+ .
11
+ |-- block0.img
12
+ |-- initrd.gz
13
+ |-- metadata.json
14
+ `-- vmlinuz
15
+ ```
16
+
17
+ The metadata.json just contains the defaults from the vagrant box documentation,
18
+ that is it looks like:
19
+
20
+ ```
21
+ {
22
+ "provider": "xhyve"
23
+ }
24
+ ```
25
+
26
+ initrd.gz and vmlinuz are extracted from a raw disk image using the technique
27
+ described in Michael Steil's nice blog post
28
+ [introducing xhyve](http://www.pagetable.com/?p=831).
29
+
30
+ You can have up to ten block devices to attach to your vm, named from block0.img
31
+ upto block9.img. You can also have zero. That's ok.
Binary file
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "xhyve"
3
+ }
Binary file
@@ -0,0 +1,142 @@
1
+ require "log4r"
2
+ require 'json'
3
+ require 'securerandom'
4
+
5
+ require 'vagrant/util/retryable'
6
+
7
+ require 'vagrant-xhyve/util/timer'
8
+ require 'vagrant-xhyve/util/vagrant-xhyve'
9
+
10
+ module VagrantPlugins
11
+ module XHYVE
12
+ module Action
13
+ # This runs the configured instance.
14
+ class Boot
15
+ include Vagrant::Util::Retryable
16
+
17
+ def initialize(app, env)
18
+ @app = app
19
+ @logger = Log4r::Logger.new("vagrant_xhyve::action::run_instance")
20
+ end
21
+
22
+ def call(env)
23
+ # Initialize metrics if they haven't been
24
+ env[:metrics] ||= {}
25
+
26
+ env[:ui].info(" About to launch vm")
27
+
28
+ memory = env[:machine].provider_config.memory
29
+ cpus = env[:machine].provider_config.cpus
30
+
31
+ # Launch!
32
+ env[:ui].info(" -- CPUs: #{cpus}") if cpus
33
+ env[:ui].info(" -- Memory: #{memory}")
34
+
35
+ machine_info_path = File.join(env[:machine].data_dir, "xhyve.json")
36
+ if File.exist?(machine_info_path) then
37
+ machine_json = File.read(machine_info_path)
38
+ machine_options = JSON.parse(machine_json, :symbolize_names => true)
39
+ machine_uuid = machine_options[:uuid]
40
+ @logger.debug("Found existing UUID: #{machine_uuid}")
41
+ else
42
+ machine_uuid = SecureRandom.uuid
43
+ @logger.debug("Created new UUID: #{machine_uuid}")
44
+ end
45
+
46
+ image_dir = File.join(env[:machine].data_dir, "image")
47
+ vmlinuz_file = File.join(image_dir, "vmlinuz")
48
+ initrd_file = File.join(image_dir, "initrd.gz")
49
+ block_devices = []
50
+
51
+ 0.upto(10).each do |blockidx|
52
+ block_file = File.join(image_dir, "block#{blockidx}.img")
53
+ if (File.exist? block_file) then
54
+ @logger.debug("Found block device #{block_file}")
55
+ block_devices.push(block_file)
56
+ else
57
+ break
58
+ end
59
+ end
60
+
61
+ if block_devices.any? then
62
+ disk_kernel_parameters = "root=/dev/vda1 ro"
63
+ else
64
+ disk_kernel_parameters = ""
65
+ end
66
+
67
+ kernel_parameters = "\"earlyprintk=serial console=ttyS0 #{disk_kernel_parameters}\""
68
+
69
+ firmware = "kexec,#{vmlinuz_file},#{initrd_file},#{kernel_parameters}"
70
+
71
+ @logger.debug("Machine data_dir: #{env[:machine].data_dir}")
72
+ @logger.debug("Kernel Options: #{kernel_parameters}")
73
+ @logger.debug("Block Devices: #{block_devices}")
74
+
75
+ xhyve_guest = Util::XhyveGuest.new(
76
+ kernel: vmlinuz_file,
77
+ initrd: initrd_file,
78
+ cmdline: kernel_parameters,
79
+ blockdevs: block_devices,
80
+ serial: 'com1',
81
+ memory: memory,
82
+ processors: cpus,
83
+ networking: true,
84
+ acpi: true
85
+ )
86
+
87
+
88
+ xhyve_pid = xhyve_guest.start
89
+ env[:ui].info(xhyve_guest.options().to_json)
90
+
91
+ # Immediately save the ID since it is created at this point.
92
+ env[:machine].id = xhyve_pid
93
+
94
+ # wait for ip
95
+ network_ready_retries = 0
96
+ network_ready_retries_max = 5
97
+ while true
98
+ break if env[:interrupted]
99
+
100
+ if xhyve_guest.ip
101
+ break
102
+ end
103
+ if network_ready_retries < network_ready_retries_max then
104
+ network_ready_retries += 1
105
+ env[:ui].info("Waiting for IP to be ready...")
106
+ else
107
+ raise 'Waited too long for IP to be ready. Your VM probably did not boot.'
108
+ end
109
+ sleep 2
110
+ end
111
+
112
+ machine_info_path = File.join(env[:machine].data_dir, "xhyve.json")
113
+ File.write(machine_info_path, xhyve_guest.options().to_json)
114
+
115
+ @logger.info(" Launched xhyve VM with PID #{xhyve_pid}, MAC: #{xhyve_guest.mac}, and IP #{xhyve_guest.ip}")
116
+
117
+ # Terminate the instance if we were interrupted
118
+ terminate(env) if env[:interrupted]
119
+
120
+ @app.call(env)
121
+ end
122
+
123
+ def recover(env)
124
+ return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
125
+
126
+ if env[:machine].provider.state.id != :not_created
127
+ # Undo the import
128
+ terminate(env)
129
+ end
130
+ end
131
+
132
+ def terminate(env)
133
+ destroy_env = env.dup
134
+ destroy_env.delete(:interrupted)
135
+ destroy_env[:config_validate] = false
136
+ destroy_env[:force_confirm_destroy] = true
137
+ env[:action_runner].run(Action.action_destroy, destroy_env)
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,59 @@
1
+ require "log4r"
2
+ require "json"
3
+ require "fileutils"
4
+
5
+ module VagrantPlugins
6
+ module XHYVE
7
+ module Action
8
+ # This terminates the running instance.
9
+ class Import
10
+ def initialize(app, env)
11
+ @app = app
12
+ @logger = Log4r::Logger.new("vagrant_xhyve::action::import")
13
+ end
14
+
15
+ def call(env)
16
+
17
+ #TODO: Progress bar
18
+ env[:ui].info("Importing box...")
19
+ # something like:
20
+ # # tempfile is a File instance
21
+ # File.open( new_file, 'wb' ) do |f|
22
+ # # Read in small 65k chunks to limit memory usage
23
+ # f.write(tempfile.read(2**16)) until tempfile.eof?
24
+ # end
25
+
26
+ image_dir = File.join(env[:machine].data_dir, "image")
27
+ box_dir = env[:machine].box.directory
28
+
29
+ box_files = [File.join(box_dir, "vmlinuz"), File.join(box_dir, "initrd.gz")]
30
+
31
+ 0.upto(10).each do |blockidx|
32
+ block_file = File.join(box_dir, "block#{blockidx}.img")
33
+ if (File.exist? block_file) then
34
+ box_files.push(block_file)
35
+ else
36
+ break
37
+ end
38
+ end
39
+
40
+ FileUtils.mkdir_p(image_dir)
41
+ FileUtils.cp(box_files, image_dir)
42
+
43
+ env[:ui].info("Done importing box.")
44
+
45
+ @app.call(env)
46
+ end
47
+
48
+ def process_alive(pid)
49
+ begin
50
+ Process.getpgid(pid)
51
+ true
52
+ rescue Errno::ESRCH
53
+ false
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module XHYVE
3
+ module Action
4
+ # This can be used with "Call" built-in to check if the machine
5
+ # is created and branch in the middleware.
6
+ class IsCreated
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ env[:result] = env[:machine].id != nil
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module XHYVE
3
+ module Action
4
+ # This can be used with "Call" built-in to check if the machine
5
+ # is stopped and branch in the middleware.
6
+ class IsStopped
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ env[:result] = env[:machine].state.id == :stopped
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module XHYVE
3
+ module Action
4
+ class MessageAlreadyCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t("vagrant_xhyve.already_status", :status => "created"))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module XHYVE
3
+ module Action
4
+ class MessageNotCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t("vagrant_xhyve.not_created"))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module XHYVE
3
+ module Action
4
+ class MessageWillNotDestroy
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t("vagrant_xhyve.will_not_destroy", name: env[:machine].name))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ require "log4r"
2
+ require 'vagrant-xhyve/util/vagrant-xhyve'
3
+
4
+ module VagrantPlugins
5
+ module XHYVE
6
+ module Action
7
+ # This action reads the SSH info for the machine and puts it into the
8
+ # `:machine_ssh_info` key in the environment.
9
+ class ReadSSHInfo
10
+ def initialize(app, env)
11
+ @app = app
12
+ @logger = Log4r::Logger.new("vagrant_xhyve::action::read_ssh_info")
13
+ end
14
+
15
+ def call(env)
16
+ env[:machine_ssh_info] = read_ssh_info(env)
17
+
18
+ @app.call(env)
19
+ end
20
+
21
+ def read_ssh_info(env)
22
+ return nil if env[:machine].id.nil?
23
+
24
+ machine_info_path = File.join(env[:machine].data_dir, "xhyve.json")
25
+ machine_json = File.read(machine_info_path)
26
+ machine_options = JSON.parse(machine_json, :symbolize_names => true)
27
+
28
+ return { :host => machine_options[:ip], :port => 22 }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,43 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module XHYVE
5
+ module Action
6
+ # This action reads the state of the machine and puts it in the
7
+ # `:machine_state_id` key in the environment.
8
+ class ReadState
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new("vagrant_xhyve::action::read_state")
12
+ end
13
+
14
+ def call(env)
15
+ env[:machine_state_id] = read_state(env[:machine])
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ def read_state(machine)
21
+ return :not_created if machine.id.nil?
22
+
23
+ xhyve_pid = Integer(machine.id)
24
+
25
+ if process_alive(xhyve_pid) then
26
+ return :running
27
+ else
28
+ return :stopped
29
+ end
30
+ end
31
+
32
+ def process_alive(pid)
33
+ begin
34
+ Process.getpgid(pid)
35
+ true
36
+ rescue Errno::ESRCH
37
+ false
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module XHYVE
5
+ module Action
6
+ # This stops the running instance.
7
+ class StopInstance
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new("vagrant_xhyve::action::stop_instance")
11
+ end
12
+
13
+ def call(env)
14
+ if env[:machine].state.id == :stopped
15
+ env[:ui].info(I18n.t("vagrant_xhyve.already_status", :status => env[:machine].state.id))
16
+ else
17
+ env[:ui].info(I18n.t("vagrant_xhyve.stopping"))
18
+
19
+ xhyve_pid = env[:machine].id
20
+
21
+ if xhyve_pid == nil then
22
+ @logger.debug("xhyve already gone")
23
+ elsif process_alive(Integer(xhyve_pid)) then
24
+ env[:ui].info(" Terminating xhyve instance with PID #{xhyve_pid}")
25
+ Process.kill(3, Integer(xhyve_pid))
26
+ else
27
+ @logger.debug("xhyve PID already gone #{xhyve_pid}")
28
+ end
29
+ end
30
+
31
+ @app.call(env)
32
+ end
33
+
34
+ def process_alive(pid)
35
+ begin
36
+ Process.getpgid(pid)
37
+ true
38
+ rescue Errno::ESRCH
39
+ false
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end