vagrant-bhyve 0.1.0

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 (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +13 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +111 -0
  8. data/Rakefile +6 -0
  9. data/Vagrantfiles/Vagrantfile_CentOS-6 +14 -0
  10. data/Vagrantfiles/Vagrantfile_CentOS-7 +11 -0
  11. data/Vagrantfiles/Vagrantfile_Debian_Ubuntu +11 -0
  12. data/example_box/README.md +46 -0
  13. data/example_box/Vagrantfile +9 -0
  14. data/example_box/metadata.json +3 -0
  15. data/lib/vagrant-bhyve.rb +21 -0
  16. data/lib/vagrant-bhyve/action.rb +215 -0
  17. data/lib/vagrant-bhyve/action/boot.rb +26 -0
  18. data/lib/vagrant-bhyve/action/cleanup.rb +23 -0
  19. data/lib/vagrant-bhyve/action/create_bridge.rb +33 -0
  20. data/lib/vagrant-bhyve/action/create_tap.rb +31 -0
  21. data/lib/vagrant-bhyve/action/destroy.rb +23 -0
  22. data/lib/vagrant-bhyve/action/forward_ports.rb +53 -0
  23. data/lib/vagrant-bhyve/action/import.rb +32 -0
  24. data/lib/vagrant-bhyve/action/load.rb +27 -0
  25. data/lib/vagrant-bhyve/action/prepare_nfs_settings.rb +50 -0
  26. data/lib/vagrant-bhyve/action/prepare_nfs_valid_ids.rb +23 -0
  27. data/lib/vagrant-bhyve/action/setup.rb +27 -0
  28. data/lib/vagrant-bhyve/action/shutdown.rb +26 -0
  29. data/lib/vagrant-bhyve/action/wait_until_up.rb +48 -0
  30. data/lib/vagrant-bhyve/config.rb +75 -0
  31. data/lib/vagrant-bhyve/driver.rb +674 -0
  32. data/lib/vagrant-bhyve/errors.rb +55 -0
  33. data/lib/vagrant-bhyve/executor.rb +38 -0
  34. data/lib/vagrant-bhyve/plugin.rb +73 -0
  35. data/lib/vagrant-bhyve/provider.rb +126 -0
  36. data/lib/vagrant-bhyve/version.rb +5 -0
  37. data/locales/en.yml +90 -0
  38. data/vagrant-bhyve.gemspec +24 -0
  39. metadata +137 -0
@@ -0,0 +1,55 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module ProviderBhyve
5
+ module Errors
6
+ class VagrantBhyveError < Vagrant::Errors::VagrantError
7
+ error_namespace('vagrant_bhyve.errors')
8
+ end
9
+
10
+ class SystemVersionIsTooLow < VagrantBhyveError
11
+ error_key(:system_version_too_low)
12
+ end
13
+
14
+ class MissingPopcnt < VagrantBhyveError
15
+ error_key(:missing_popcnt)
16
+ end
17
+
18
+ class MissingEpt < VagrantBhyveError
19
+ error_key(:missing_ept)
20
+ end
21
+
22
+ class MissingIommu < VagrantBhyveError
23
+ error_key(:missing_iommu)
24
+ end
25
+
26
+ class HasNoRootPrivilege < VagrantBhyveError
27
+ error_key(:has_no_root_privilege)
28
+ end
29
+
30
+ class ExecuteError < VagrantBhyveError
31
+ error_key(:execute_error)
32
+ end
33
+
34
+ class UnableToLoadModule < VagrantBhyveError
35
+ error_key(:unable_to_load_module)
36
+ end
37
+
38
+ class UnableToCreateInterface < VagrantBhyveError
39
+ error_key(:unable_to_create_interface)
40
+ end
41
+
42
+ class GrubBhyveNotinstalled < VagrantBhyveError
43
+ error_key(:grub_bhyve_not_installed)
44
+ end
45
+
46
+ class RestartServiceFailed < VagrantBhyveError
47
+ error_key(:restart_service_failed)
48
+ end
49
+
50
+ class NotFoundLeasesInfo < VagrantBhyveError
51
+ error_key(:not_found_leases_info)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,38 @@
1
+ require "vagrant/util/busy"
2
+ require "vagrant/util/subprocess"
3
+
4
+ module VagrantPlugins
5
+ module ProviderBhyve
6
+ module Executor
7
+ # This class is used to execute commands as subprocess.
8
+ class Exec
9
+ # When we need the command's exit code we should set parameter
10
+ # exit_code to true, otherwise this method will return executed
11
+ # command's stdout
12
+ def execute(exit_code, *cmd, **opts, &block)
13
+ # Append in the options for subprocess
14
+ cmd << { notify: [:stdout, :stderr] }
15
+ cmd.unshift('sh', '-c')
16
+
17
+ interrupted = false
18
+ # Lambda to change interrupted to true
19
+ int_callback = ->{ interrupted = true }
20
+ result = ::Vagrant::Util::Busy.busy(int_callback) do
21
+ ::Vagrant::Util::Subprocess.execute(*cmd, &block)
22
+ end
23
+
24
+ return result.exit_code if exit_code
25
+
26
+ result.stderr.gsub!("\r\n", "\n")
27
+ result.stdout.gsub!("\r\n", "\n")
28
+
29
+ if result.exit_code != 0 || interrupted
30
+ raise Errors::ExecuteError
31
+ end
32
+
33
+ result.stdout[0..-2]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant Bhyve plugin must be run within Vagrant."
5
+ end
6
+
7
+ #############################################################
8
+ # TBD some version check #
9
+ #############################################################
10
+
11
+ module VagrantPlugins
12
+ module ProviderBhyve
13
+ class Plugin < Vagrant.plugin('2')
14
+ name "bhyve"
15
+ description <<-DESC
16
+ This plugin allows vagrant to manage VMs in bhyve, the hypervisor
17
+ provided by FreeBSD's kernel
18
+ DESC
19
+
20
+ config(:bhyve, :provider) do
21
+ require_relative "config"
22
+ Config
23
+ end
24
+
25
+ provider(:bhyve) do
26
+ require_relative "provider"
27
+ Provider
28
+ end
29
+
30
+ # This initializes the internationalization strings.
31
+ def self.setup_i18n
32
+ I18n.load_path << File.expand_path('locales/en.yml',
33
+ ProviderBhyve.source_root)
34
+ I18n.reload!
35
+ end
36
+
37
+ # This sets up our log level to be whatever VAGRANT_LOG is.
38
+ def self.setup_logging
39
+ require 'log4r'
40
+
41
+ level = nil
42
+ begin
43
+ level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
44
+ rescue NameError
45
+ # This means that the logging constant wasn't found,
46
+ # which is fine. We just keep `level` as `nil`. But
47
+ # we tell the user.
48
+ level = nil
49
+ end
50
+
51
+ # Some constants, such as "true" resolve to booleans, so the
52
+ # above error checking doesn't catch it. This will check to make
53
+ # sure that the log level is an integer, as Log4r requires.
54
+ level = nil if !level.is_a?(Integer)
55
+
56
+ # Set the logging level on all "vagrant" namespaced
57
+ # logs as long as we have a valid level.
58
+ if level
59
+ logger = Log4r::Logger.new('vagrant_bhyve')
60
+ logger.outputters = Log4r::Outputter.stderr
61
+ logger.level = level
62
+ logger = nil
63
+ end
64
+ end
65
+
66
+ # Setup logging and i18n before any autoloading loads other classes
67
+ # with logging configured as this prevents inheritance of the log level
68
+ # from the parent logger.
69
+ setup_logging
70
+ setup_i18n
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,126 @@
1
+ require "vagrant"
2
+ require "log4r"
3
+
4
+ module VagrantPlugins
5
+ module ProviderBhyve
6
+ autoload :Driver, 'vagrant-bhyve/driver'
7
+
8
+ class Provider < Vagrant.plugin('2', :provider)
9
+
10
+ def initialize(machine)
11
+ @logger = Log4r::Logger.new("vagrant::provider::bhyve")
12
+ @machine = machine
13
+ end
14
+
15
+ def driver
16
+ return @driver if @driver
17
+ @driver = Driver.new(@machine)
18
+ end
19
+
20
+ # This should return a hash of information that explains how to SSH
21
+ # into the machine. If the machine is not at a point where SSH is
22
+ # even possiable, then 'nil' should be returned
23
+ #
24
+ # The general structure of this returned hash should be the
25
+ # following:
26
+ #
27
+ # {
28
+ # host: "1.2.3.4",
29
+ # port: "22",
30
+ # username: "vagrant",
31
+ # private_key_path: "/path/to/my/key"
32
+ # }
33
+ def ssh_info
34
+ # We just return nil if were not able to identify the VM's IP and
35
+ # let Vagrant core deal with it like docker provider does
36
+ return nil if state.id != :running
37
+ tap_device = driver.get_attr('tap')
38
+ ip = driver.get_ip_address(tap_device) unless tap_device.length == 0
39
+ return nil if !ip
40
+ ssh_info = {
41
+ host: ip,
42
+ port: 22,
43
+ }
44
+ end
45
+
46
+ # This is called early, before a machine is instantiated, to check
47
+ # if this provider is usable. This should return true or false.
48
+ #
49
+ # If raise_error is true, then instead of returning false, this
50
+ # should raise an error with a helpful message about why this
51
+ # provider cannot be used.
52
+ #
53
+ # @param [Boolean] raise_error If true, raise exception if not usable.
54
+ # @return [Boolean]
55
+ def self.usable?(raise_error=false)
56
+ # Return true by default for backwards compat since this was
57
+ # introduced long after providers were being written.
58
+ true
59
+ end
60
+
61
+ # This is called early, before a machine is instantiated, to check
62
+ # if this provider is installed. This should return true or false.
63
+ #
64
+ # If the provider is not installed and Vagrant determines it is
65
+ # able to install this provider, then it will do so. Installation
66
+ # is done by calling Environment.install_provider.
67
+ #
68
+ # If Environment.can_install_provider? returns false, then an error
69
+ # will be shown to the user.
70
+ def self.installed?
71
+ # By default return true for backwards compat so all providers
72
+ # continue to work.
73
+ true
74
+ end
75
+
76
+ # This should return an action callable for the given name.
77
+ #
78
+ # @param [Symbol] name Name of the action.
79
+ # @return [Object] A callable action sequence object, whether it
80
+ # is a proc, object, etc.
81
+ def action(name)
82
+ # Attrmpt to get the action method from the Action class if it
83
+ # exists, otherwise return nil to show that we don't support the
84
+ # given action
85
+ action_method = "action_#{name}"
86
+ return Action.send(action_method) if Action.respond_to?(action_method)
87
+ nil
88
+ end
89
+
90
+ # This method is called if the underying machine ID changes. Providers
91
+ # can use this method to load in new data for the actual backing
92
+ # machine or to realize that the machine is now gone (the ID can
93
+ # become `nil`). No parameters are given, since the underlying machine
94
+ # is simply the machine instance given to this object. And no
95
+ # return value is necessary.
96
+ def machine_id_changed
97
+ end
98
+
99
+ # This should return the state of the machine within this provider.
100
+ # The state must be an instance of {MachineState}. Please read the
101
+ # documentation of that class for more information.
102
+ #
103
+ # @return [MachineState]
104
+ def state
105
+ state_id = nil
106
+ if @machine.id
107
+ vm_name = driver.get_attr('vm_name')
108
+ if vm_name.nil?
109
+ state_id = :uncreated
110
+ else
111
+ state_id = driver.state(vm_name)
112
+ end
113
+ else
114
+ state_id = :uncreated
115
+ end
116
+ short = state_id.to_s.gsub("_", " ")
117
+ long = I18n.t("vagrant_bhyve.states.#{state_id}")
118
+ # If we're not created, then specify the special ID flag
119
+ state_id = Vagrant::MachineState::NOT_CREATED_ID if state_id == :uncreated
120
+ # Return the MachineState object
121
+ Vagrant::MachineState.new(state_id, short, long)
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module ProviderBhyve
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,90 @@
1
+ en:
2
+ vagrant_bhyve:
3
+ commands:
4
+ common:
5
+ vm_not_created: |-
6
+ You are destroying a uncreated instance.
7
+ vm_not_running: |-
8
+ You are invokng this action on a box which is not running.
9
+ vm_already_running: |-
10
+ Your box has already be booted.
11
+
12
+ action:
13
+ vm:
14
+ setup_environment: |-
15
+ Checking if your system supports bhyve and loading kernel modules
16
+ we need to create bhyve VMs. You will be asked for password for
17
+ sudo if you are not running vagrant with root user.
18
+ import_box: |-
19
+ Copying box files.
20
+ forward_ports: |-
21
+ Setup port forwarding(if any).
22
+ boot:
23
+ setup_nat: |-
24
+ Setting up a nat environment using pf and dnsmasq to provide
25
+ network for VMs. You will need to have dnsmasq installed on
26
+ your system.
27
+ create_tap: |-
28
+ Creating tap device for VM to use.
29
+ load_kernel: |-
30
+ Loading guest OS's kernel into memory.
31
+ booting: |-
32
+ Booting VM with bhyve.
33
+ wait_until_up: |-
34
+ Please wait for a while until we can ssh into box.
35
+ halt:
36
+ shutting_down: |-
37
+ Trying to shutdown your VM through ACPI.
38
+ force_halt: |-
39
+ We have to force your VM to halt.
40
+ cleaning_up: |-
41
+ Cleaning up your environment.
42
+ reload:
43
+ reloading: |-
44
+ Rebooting your box.
45
+ destroying: |-
46
+ Deleting copied box files.
47
+
48
+ states:
49
+ uncreated: |-
50
+ Your instance of this box haven't been created.
51
+ running: |-
52
+ Bhyve is running right now.
53
+ stopped: |-
54
+ Bhyve is not running right now.
55
+ uncleaned: |-
56
+ It seems that the box has been shutdown but there reamains a vmm
57
+ device. Maybe you shutdown the box from inside. Run `vagrant halt`
58
+ to clean.
59
+ short_not_created: |-
60
+ environment_not_created
61
+ long_not_created: |-
62
+ The environment has not been created yet. Run `vagrant up` to create
63
+ the environment
64
+
65
+ errors:
66
+ system_version_too_low: |-
67
+ To use bhyve your FreeBSD's version should be newer then 10.0
68
+ missing_popcnt: |-
69
+ Popcnt is not supported by your CPU.
70
+ missing_ept: |-
71
+ EPT is not supported by your CPU.
72
+ missing_iommu: |-
73
+ IOMMU is not supported by your CPU.
74
+ has_no_root_privilege: |-
75
+ You need root privilege to manage bhyve VMs.
76
+ execute_error: |-
77
+ Failed when execute commands
78
+ unable_to_load_module: |-
79
+ Failed to load kernel modules we need to run bhyve VMs and provide
80
+ them networking.
81
+ unable_to_create_interface: |-
82
+ Failed to create network device.
83
+ grub_bhyve_not_installed: |-
84
+ Grub2-bhyve is not found on you system. You can install with `pkg
85
+ install grub2-bhyve` or install through port(sysutils/grub2-bhyve)
86
+ restart_service_failed: |-
87
+ Failed to restart a service on your system.
88
+ not_found_leases_info: |-
89
+ Unable to found IP from dnsmasq's leases file, please retry after a
90
+ few seconds.
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ require File.expand_path('../lib/vagrant-bhyve/version', __FILE__)
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "vagrant-bhyve"
6
+ spec.version = VagrantPlugins::ProviderBhyve::VERSION
7
+ spec.authors = ["Tong Li"]
8
+ spec.email = ["jesa7955@gmail.com"]
9
+
10
+ spec.summary = %q{Vagrant provider plugin to support bhyve}
11
+ spec.description = spec.summary
12
+ spec.homepage = "https://github.com/jesa7955/vagrant-bhyve"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.10"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_runtime_dependency "ruby_expect"
24
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-bhyve
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tong Li
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby_expect
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Vagrant provider plugin to support bhyve
70
+ email:
71
+ - jesa7955@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - Vagrantfiles/Vagrantfile_CentOS-6
84
+ - Vagrantfiles/Vagrantfile_CentOS-7
85
+ - Vagrantfiles/Vagrantfile_Debian_Ubuntu
86
+ - example_box/README.md
87
+ - example_box/Vagrantfile
88
+ - example_box/metadata.json
89
+ - lib/vagrant-bhyve.rb
90
+ - lib/vagrant-bhyve/action.rb
91
+ - lib/vagrant-bhyve/action/boot.rb
92
+ - lib/vagrant-bhyve/action/cleanup.rb
93
+ - lib/vagrant-bhyve/action/create_bridge.rb
94
+ - lib/vagrant-bhyve/action/create_tap.rb
95
+ - lib/vagrant-bhyve/action/destroy.rb
96
+ - lib/vagrant-bhyve/action/forward_ports.rb
97
+ - lib/vagrant-bhyve/action/import.rb
98
+ - lib/vagrant-bhyve/action/load.rb
99
+ - lib/vagrant-bhyve/action/prepare_nfs_settings.rb
100
+ - lib/vagrant-bhyve/action/prepare_nfs_valid_ids.rb
101
+ - lib/vagrant-bhyve/action/setup.rb
102
+ - lib/vagrant-bhyve/action/shutdown.rb
103
+ - lib/vagrant-bhyve/action/wait_until_up.rb
104
+ - lib/vagrant-bhyve/config.rb
105
+ - lib/vagrant-bhyve/driver.rb
106
+ - lib/vagrant-bhyve/errors.rb
107
+ - lib/vagrant-bhyve/executor.rb
108
+ - lib/vagrant-bhyve/plugin.rb
109
+ - lib/vagrant-bhyve/provider.rb
110
+ - lib/vagrant-bhyve/version.rb
111
+ - locales/en.yml
112
+ - vagrant-bhyve.gemspec
113
+ homepage: https://github.com/jesa7955/vagrant-bhyve
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.5.1
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Vagrant provider plugin to support bhyve
137
+ test_files: []