vagrant-hyperkit 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
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