vagrant-bhyve 0.1.0

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