vagrant-hyperkit 0.4.3

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 (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +20 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE +9 -0
  7. data/README.md +221 -0
  8. data/Rakefile +22 -0
  9. data/lib/vagrant-hyperkit.rb +22 -0
  10. data/lib/vagrant-hyperkit/action.rb +195 -0
  11. data/lib/vagrant-hyperkit/action/boot.rb +185 -0
  12. data/lib/vagrant-hyperkit/action/import.rb +69 -0
  13. data/lib/vagrant-hyperkit/action/is_created.rb +18 -0
  14. data/lib/vagrant-hyperkit/action/is_stopped.rb +18 -0
  15. data/lib/vagrant-hyperkit/action/message_already_created.rb +16 -0
  16. data/lib/vagrant-hyperkit/action/message_not_created.rb +16 -0
  17. data/lib/vagrant-hyperkit/action/message_will_not_destroy.rb +16 -0
  18. data/lib/vagrant-hyperkit/action/read_ssh_info.rb +27 -0
  19. data/lib/vagrant-hyperkit/action/read_state.rb +53 -0
  20. data/lib/vagrant-hyperkit/action/stop_instance.rb +49 -0
  21. data/lib/vagrant-hyperkit/action/terminate_instance.rb +31 -0
  22. data/lib/vagrant-hyperkit/action/timed_provision.rb +21 -0
  23. data/lib/vagrant-hyperkit/action/wait_for_state.rb +41 -0
  24. data/lib/vagrant-hyperkit/config.rb +83 -0
  25. data/lib/vagrant-hyperkit/errors.rb +19 -0
  26. data/lib/vagrant-hyperkit/plugin.rb +73 -0
  27. data/lib/vagrant-hyperkit/provider.rb +67 -0
  28. data/lib/vagrant-hyperkit/util/timer.rb +17 -0
  29. data/lib/vagrant-hyperkit/util/vagrant-hyperkit.rb +79 -0
  30. data/lib/vagrant-hyperkit/version.rb +5 -0
  31. data/locales/en.yml +83 -0
  32. data/spec/spec_helper.rb +1 -0
  33. data/spec/vagrant-hyperkit/config_spec.rb +33 -0
  34. data/templates/metadata.json.erb +3 -0
  35. data/templates/vagrant-aws_package_Vagrantfile.erb +5 -0
  36. data/vagrant-hyperkit.gemspec +61 -0
  37. data/vendor/xhyve-ruby/.gitignore +8 -0
  38. data/vendor/xhyve-ruby/.travis.yml +10 -0
  39. data/vendor/xhyve-ruby/Gemfile +3 -0
  40. data/vendor/xhyve-ruby/README.md +33 -0
  41. data/vendor/xhyve-ruby/Rakefile +42 -0
  42. data/vendor/xhyve-ruby/example/test.rb +17 -0
  43. data/vendor/xhyve-ruby/lib/rubygems_plugin.rb +7 -0
  44. data/vendor/xhyve-ruby/lib/xhyve.rb +4 -0
  45. data/vendor/xhyve-ruby/lib/xhyve/dhcp.rb +54 -0
  46. data/vendor/xhyve-ruby/lib/xhyve/guest.rb +92 -0
  47. data/vendor/xhyve-ruby/lib/xhyve/vendor/xhyve +0 -0
  48. data/vendor/xhyve-ruby/lib/xhyve/version.rb +4 -0
  49. data/vendor/xhyve-ruby/spec/fixtures/dhcpd_leases.txt +42 -0
  50. data/vendor/xhyve-ruby/spec/fixtures/guest/README.md +33 -0
  51. data/vendor/xhyve-ruby/spec/fixtures/guest/initrd +0 -0
  52. data/vendor/xhyve-ruby/spec/fixtures/guest/vmlinuz +0 -0
  53. data/vendor/xhyve-ruby/spec/lib/dhcp_spec.rb +35 -0
  54. data/vendor/xhyve-ruby/spec/lib/guest_spec.rb +51 -0
  55. data/vendor/xhyve-ruby/spec/spec_helper.rb +52 -0
  56. data/vendor/xhyve-ruby/xhyve-ruby.gemspec +23 -0
  57. metadata +192 -0
@@ -0,0 +1,83 @@
1
+ en:
2
+ vagrant_hyperkit:
3
+ already_status: |-
4
+ The machine is already %{status}.
5
+ launching_instance: |-
6
+ Launching an instance with the following settings...
7
+ not_created: |-
8
+ Instance is not created. Please run `vagrant up` first.
9
+ ready: |-
10
+ Machine is booted and ready for use!
11
+ rsync_not_found_warning: |-
12
+ Warning! Folder sync disabled because the rsync binary is missing in the %{side}.
13
+ Make sure rsync is installed and the binary can be found in the PATH.
14
+ rsync_folder: |-
15
+ Rsyncing folder: %{hostpath} => %{guestpath}
16
+ source_dest_checks_no_vpc: |-
17
+ Warning! Ignoring source_dest_checks flag as it can only be configured on
18
+ a VPC instance.
19
+ starting: |-
20
+ Starting the instance...
21
+ stopping: |-
22
+ Stopping the instance...
23
+ terminating: |-
24
+ Terminating the instance...
25
+ waiting_for_ready: |-
26
+ Waiting for instance to become "ready"...
27
+ waiting_for_ssh: |-
28
+ Waiting for SSH to become available...
29
+ warn_ssh_access: |-
30
+ Warning! Vagrant might not be able to SSH into the instance.
31
+ Please check your security groups settings.
32
+ will_not_destroy: |-
33
+ The instance '%{name}' will not be destroyed, since the confirmation
34
+ was declined.
35
+
36
+ errors:
37
+ rsync_error: |-
38
+ There was an error when attempting to rsync a shared folder.
39
+ Please inspect the error message below for more info.
40
+
41
+ Host path: %{hostpath}
42
+ Guest path: %{guestpath}
43
+ Error: %{stderr}
44
+ mkdir_error: |-
45
+ There was an error when attempting to create a shared host folder.
46
+ Please inspect the error message below for more info.
47
+
48
+ Host path: %{hostpath}
49
+ Error: %{err}
50
+
51
+ states:
52
+ short_not_created: |-
53
+ not created
54
+ long_not_created: |-
55
+ The xhyve VM is not created. Run `vagrant up` to create it.
56
+
57
+ short_stopped: |-
58
+ stopped
59
+ long_stopped: |-
60
+ The xhyve VM is stopped. Run `vagrant up` to start it.
61
+
62
+ short_stopping: |-
63
+ stopping
64
+ long_stopping: |-
65
+ The xhyve VM is stopping. Wait until is completely stopped to
66
+ run `vagrant up` and start it.
67
+
68
+ short_pending: |-
69
+ pending
70
+ long_pending: |-
71
+ The xhyve VM is pending a start (i.e. this is a transition state).
72
+
73
+ short_running: |-
74
+ running
75
+ long_running: |-
76
+ The xhyve VM is running. To stop this machine, you can run
77
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
78
+
79
+ short_pending: |-
80
+ pending
81
+ long_pending: |-
82
+ The xhyve VM is still being initialized. To destroy this machine,
83
+ you can run `vagrant destroy`.
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,33 @@
1
+ require "vagrant-hyperkit/config"
2
+ require 'rspec/its'
3
+
4
+ # remove deprecation warnings
5
+ # (until someone decides to update the whole spec file to rspec 3.4)
6
+ RSpec.configure do |config|
7
+ # ...
8
+ config.mock_with :rspec do |c|
9
+ c.syntax = [:should, :expect]
10
+ end
11
+ config.expect_with :rspec do |c|
12
+ c.syntax = [:should, :expect]
13
+ end
14
+ end
15
+
16
+ describe VagrantPlugins::HYPERKIT::Config do
17
+ let(:instance) { described_class.new }
18
+
19
+ before :each do
20
+ ENV.stub(:[] => nil)
21
+ end
22
+
23
+ describe "defaults" do
24
+ subject do
25
+ instance.tap do |o|
26
+ o.finalize!
27
+ end
28
+ end
29
+
30
+ its("memory") { should.to_s == "1024" }
31
+ its("cpus") { should == 1 }
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "aws"
3
+ }
@@ -0,0 +1,5 @@
1
+ Vagrant.configure("2") do |config|
2
+ config.vm.provider "aws" do |aws|
3
+ aws.region_config "<%= region %>", ami: "<%= ami %>"
4
+ end
5
+ end
@@ -0,0 +1,61 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+ require "vagrant-hyperkit/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "vagrant-hyperkit"
6
+ s.version = VagrantPlugins::HYPERKIT::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.license = "MIT"
9
+ s.authors = "Patrick Armstrong, Steve Glover (Accanto Systems Ltd)"
10
+ s.email = "pat@oldpatricka.com, steve.glover@accantosystems.com"
11
+ s.homepage = "http://github.com/oldpatricka/vagrant-xhyve"
12
+ s.summary = "Enables Vagrant to manage machines in hyperkit."
13
+ s.description = "Enables Vagrant to manage machines in hyperkit."
14
+
15
+ s.required_rubygems_version = ">= 1.3.6"
16
+ s.rubyforge_project = "vagrant-hyperkit"
17
+
18
+ s.add_runtime_dependency "xhyve-ruby", ">= 0.0.6"
19
+ s.add_runtime_dependency "net-ssh"
20
+ s.add_runtime_dependency "iniparse", "~> 1.4", ">= 1.4.2"
21
+
22
+ s.add_development_dependency "rake"
23
+ # rspec 3.4 to mock File
24
+ s.add_development_dependency "rspec", "~> 3.4"
25
+ s.add_development_dependency "rspec-its"
26
+
27
+ # The following block of code determines the files that should be included
28
+ # in the gem. It does this by reading all the files in the directory where
29
+ # this gemspec is, and parsing out the ignored files from the gitignore.
30
+ # Note that the entire gitignore(5) syntax is not supported, specifically
31
+ # the "!" syntax, but it should mostly work correctly.
32
+ root_path = File.dirname(__FILE__)
33
+ all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
34
+ all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
35
+ gitignore_path = File.join(root_path, ".gitignore")
36
+ gitignore = File.readlines(gitignore_path)
37
+ gitignore.map! { |line| line.chomp.strip }
38
+ gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
39
+
40
+ unignored_files = all_files.reject do |file|
41
+ # Ignore any directories, the gemspec only cares about files
42
+ next true if File.directory?(file)
43
+
44
+ # Ignore any paths that match anything in the gitignore. We do
45
+ # two tests here:
46
+ #
47
+ # - First, test to see if the entire path matches the gitignore.
48
+ # - Second, match if the basename does, this makes it so that things
49
+ # like '.DS_Store' will match sub-directories too (same behavior
50
+ # as git).
51
+ #
52
+ gitignore.any? do |ignore|
53
+ File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
54
+ File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
55
+ end
56
+ end
57
+
58
+ s.files = unignored_files
59
+ s.executables = unignored_files.map { |f| f[/^bin\/(.*)/, 1] }.compact
60
+ s.require_path = 'lib'
61
+ end
@@ -0,0 +1,8 @@
1
+ tmp
2
+ mkmf.log
3
+ Makefile
4
+ coverage
5
+ lib/xhyve/vmnet/vmnet.bundle
6
+ *.gem
7
+ *.swo
8
+ *.swp
@@ -0,0 +1,10 @@
1
+ os: osx
2
+ osx_image: xcode7.1
3
+ rvm:
4
+ - 2.1.5
5
+ install:
6
+ - sudo bundle install
7
+ - sudo bundle exec rake install
8
+ script: sudo bundle exec rake
9
+ env:
10
+ - TRAVIS=true
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,33 @@
1
+ ![](https://travis-ci.org/dalehamel/xhyve-ruby.svg)
2
+
3
+ # Ruby Xhyve
4
+
5
+ This is a simple ruby-wrapper around [xhyve](https://github.com/mist64/xhyve), allowing you to start hypervisor Guests on OS-X
6
+
7
+ # Usage
8
+
9
+ You can run a guest fairly easily:
10
+
11
+ ```
12
+ require 'xhyve'
13
+
14
+ guest = Xhyve::Guest.new(
15
+ kernel: 'guest/vmlinuz', # path to vmlinuz
16
+ initrd: 'guest/initrd', # path to initrd
17
+ cmdline: 'console=tty0', # boot flags to linux
18
+ blockdevs: 'loop.img', # path to img files to use as block devs
19
+ uuid: 'a-valid-uuid', # a valid UUID
20
+ serial: 'com2', # com1 / com2 (maps to ttyS0, ttyS1, etc)
21
+ memory: '200M', # amount of memory in M/G
22
+ processors: 1, # number of processors
23
+ networking: true, # Enable networking? (requires sudo)
24
+ acpi: true, # set up acpi? (required for clean shutdown)
25
+ )
26
+
27
+ pid = guest.start # starting the guest spawns an xhyve subprocess, returning the pid
28
+ guest.running? # is the guest running?
29
+ guest.ip # get the IP of the guest
30
+ guest.mac # get MAC address of the guest
31
+ guest.stop # stop the guest
32
+ guest.destroy # forcefully stop the guest
33
+ ```
@@ -0,0 +1,42 @@
1
+ require 'rake/extensiontask'
2
+ require 'rspec/core/rake_task'
3
+ require 'fileutils'
4
+
5
+ XHYVE_TMP = 'tmp/xhyve'
6
+
7
+ # Compile native extensions task
8
+ Rake::ExtensionTask.new 'vmnet' do |ext|
9
+ ext.lib_dir = 'lib/xhyve/vmnet'
10
+ end
11
+
12
+ # Spec test
13
+ RSpec::Core::RakeTask.new(:spec)
14
+
15
+ desc 'Build xhyve binary'
16
+ task :vendor do
17
+ Dir.chdir('tmp') do
18
+ unless Dir.exist?('xhyve/.git')
19
+ system('git clone https://github.com/mist64/xhyve.git') || fail('Could not clone xhyve')
20
+ end
21
+ Dir.chdir('xhyve') do
22
+ system('git fetch') || fail('Could not fetch')
23
+ system('git reset --hard origin/master') || fail('Could not reset head')
24
+ system('make') || fail('Make failed')
25
+ end
26
+ end
27
+ FileUtils.mkdir_p('lib/xhyve/vendor')
28
+ FileUtils.cp('tmp/xhyve/build/xhyve', 'lib/xhyve/vendor')
29
+ end
30
+
31
+ desc 'Build the ruby gem'
32
+ task :build do
33
+ system('gem build xhyve-ruby.gemspec') || fail('Failed to build gem')
34
+ end
35
+
36
+ desc 'Install gem'
37
+ task install: :build do
38
+ system('gem install xhyve-ruby*.gem') || fail('Couldn not install gem')
39
+ end
40
+
41
+ # Deps and defaults
42
+ task default: :spec
@@ -0,0 +1,17 @@
1
+ require 'xhyve'
2
+
3
+ guest = Xhyve::Guest.new(
4
+ kernel: 'spec/fixtures/guest/vmlinuz', # path to vmlinuz
5
+ initrd: 'spec/fixtures/guest/initrd', # path to initrd
6
+ cmdline: 'earlyprintk=true console=ttyS0', # boot flags to linux
7
+ serial: 'com1', # com1 / com2 (maps to ttyS0, ttyS1, etc)
8
+ memory: '200M', # amount of memory in M/G
9
+ processors: 1, # number of processors
10
+ networking: true, # use sudo? (required for network unless signed)
11
+ acpi: true, # set up acpi? (required for clean shutdown)
12
+ )
13
+
14
+ pid = guest.start # starting the guest spawns an xhyve subprocess, returning the pid
15
+ puts pid
16
+ puts guest.mac # get MAC address of the guest
17
+ puts guest.ip # get the IP of the guest
@@ -0,0 +1,7 @@
1
+ Gem.post_install do
2
+ if Gem::Platform.local.os =~ /darwin/
3
+ # Required until https://github.com/mist64/xhyve/issues/60 is resolved
4
+ bin = File.expand_path('../xhyve/vendor/xhyve', __FILE__)
5
+ `/usr/bin/osascript -e 'do shell script "chown root #{bin} && chmod +s #{bin}" with administrator privileges'`
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
2
+
3
+ require 'xhyve/version'
4
+ require 'xhyve/guest'
@@ -0,0 +1,54 @@
1
+ module Xhyve
2
+ # Parse DHCP leases file for a MAC address, and get its ip.
3
+ module DHCP
4
+ extend self
5
+ LEASES_FILE = '/var/db/dhcpd_leases'
6
+ WAIT_TIME = 1
7
+ MAX_ATTEMPTS = 60
8
+
9
+ def get_ip_for_mac(mac)
10
+ normalized_mac = normalize_mac(mac)
11
+
12
+ max = ENV.key?('MAX_IP_WAIT') ? ENV['MAX_IP_WAIT'].to_i : nil
13
+ ip = wait_for(max: max) do
14
+ ip = parse_lease_file_for_mac(normalized_mac)
15
+ end
16
+ end
17
+
18
+ def parse_lease_file_for_mac(mac)
19
+ lease_file = (ENV['LEASES_FILE'] || LEASES_FILE)
20
+ contents = wait_for do
21
+ File.read(lease_file) if File.exists?(lease_file)
22
+ end
23
+ pattern = contents.match(/ip_address=(\S+)\n\thw_address=\d+,#{mac}/)
24
+ if pattern
25
+ addrs = pattern.captures
26
+ addrs.first if addrs
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def wait_for(max: nil)
33
+ attempts = 0
34
+ max ||= MAX_ATTEMPTS
35
+ while attempts < max
36
+ attempts += 1
37
+ result = yield
38
+ return result if result
39
+ sleep(WAIT_TIME)
40
+ end
41
+ end
42
+
43
+ # macos dhcp represents mac addresses differently from xhyve. Specifically,
44
+ # it doesn't display leading zeros. This function normalized the mac
45
+ # address to the macos format
46
+ def normalize_mac(mac)
47
+ # don't try to normalize if it doesn't seem like a mac...
48
+ return mac if mac !~ /.*:.*:.*:.*:.*:.*/
49
+ mac_parts = mac.to_s.split(":")
50
+ normalized_parts = mac_parts.map {|s| Integer(s, 16).to_s(16) }
51
+ normalized_parts.join(":")
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,92 @@
1
+ require 'securerandom'
2
+ require 'io/console'
3
+
4
+ require 'xhyve/dhcp'
5
+
6
+ module Xhyve
7
+ BINARY_PATH = File.expand_path('../../../lib/xhyve/vendor/xhyve', __FILE__).freeze
8
+
9
+ # An object to represent a guest that we can start and stop
10
+ # Effectively, it's a command wrapper around xhyve to provide an
11
+ # object oriented interface to a hypervisor guest
12
+ class Guest
13
+ PCI_BASE = 3
14
+ NULLDEV = '/dev/null'
15
+
16
+ attr_reader :pid, :uuid, :mac
17
+
18
+ def initialize(**opts)
19
+ @kernel = opts.fetch(:kernel)
20
+ @initrd = opts.fetch(:initrd)
21
+ @cmdline = opts.fetch(:cmdline)
22
+ @blockdevs = [opts[:blockdevs] || []].flatten
23
+ @memory = opts[:memory] || '500M'
24
+ @processors = opts[:processors] || '1'
25
+ @uuid = opts[:uuid] || SecureRandom.uuid
26
+ @serial = opts[:serial] || 'com1'
27
+ @acpi = opts.fetch(:acpi, true)
28
+ @networking = opts.fetch(:networking, true)
29
+ @foreground = opts[:foreground] || false
30
+ @binary = opts[:binary] || BINARY_PATH
31
+ @command = build_command
32
+ #@mac = find_mac
33
+ end
34
+
35
+ def log
36
+ @logger ||= Log4r::Logger.new("vagrant_hyperkit::xhyve")
37
+ end
38
+
39
+ def start
40
+ outfile, errfile, infile = redirection
41
+ @pid = spawn(@command, out: outfile, err: errfile, in: infile)
42
+ if @foreground
43
+ Process.wait(@pid)
44
+ outfile.cooked!
45
+ infile.cooked!
46
+ end
47
+ @pid
48
+ end
49
+
50
+ def stop
51
+ Process.kill('KILL', @pid)
52
+ end
53
+
54
+ def running?
55
+ (true if Process.kill(0, @pid) rescue false)
56
+ end
57
+
58
+ def ip
59
+ @ip ||= Xhyve::DHCP.get_ip_for_mac(@mac)
60
+ end
61
+
62
+ private
63
+
64
+ def redirection
65
+ if @foreground
66
+ [$stdout.raw!, $stderr.raw!, $stdin.raw! ]
67
+ else
68
+ [NULLDEV, NULLDEV, NULLDEV]
69
+ end
70
+ end
71
+
72
+ def find_mac
73
+ `#{@command} -M`.strip.gsub(/MAC:\s+/,'')
74
+ end
75
+
76
+ def build_command
77
+ [
78
+ "#{@binary}",
79
+ "#{'-A' if @acpi}",
80
+ '-U', @uuid,
81
+ '-m', @memory,
82
+ '-c', @processors,
83
+ '-s', '0:0,hostbridge',
84
+ "#{"-s #{PCI_BASE - 1}:0,virtio-net" if @networking }" ,
85
+ "#{"#{@blockdevs.each_with_index.map { |p, i| "-s #{PCI_BASE + i},virtio-blk,#{p}" }.join(' ')}" unless @blockdevs.empty? }",
86
+ '-s', '31,lpc',
87
+ '-l', "#{@serial},stdio",
88
+ '-f' "kexec,#{@kernel},#{@initrd},'#{@cmdline}'"
89
+ ].join(' ')
90
+ end
91
+ end
92
+ end