├── .gitignore ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── bhyveCon-WIP.pdf ├── lib ├── vagrant-openbsd-provider.rb └── vagrant-openbsd-provider │ ├── action │ └── ACTIONABLE_TASKS │ ├── command │ └── VAGRANT_COMMANDS │ ├── driver.rb │ ├── errors.rb │ ├── executor.rb │ ├── plugin.rb │ ├── provider.rb │ └── version.rb ├── locales └── en.yml └── vagrant-openbsd-provider.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | .ruby-version 2 | *.lock 3 | *.gem 4 | *.rbc 5 | /.config 6 | /coverage/ 7 | /InstalledFiles 8 | /pkg/ 9 | /spec/reports/ 10 | /spec/examples.txt 11 | /test/tmp/ 12 | /test/version_tmp/ 13 | /tmp/ 14 | 15 | # Used by dotenv library to load environment variables. 16 | # .env 17 | 18 | ## Specific to RubyMotion: 19 | .dat* 20 | .repl_history 21 | build/ 22 | *.bridgesupport 23 | build-iPhoneOS/ 24 | build-iPhoneSimulator/ 25 | 26 | ## Specific to RubyMotion (use of CocoaPods): 27 | # 28 | # We recommend against adding the Pods directory to your .gitignore. However 29 | # you should judge for yourself, the pros and cons are mentioned at: 30 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 31 | # 32 | # vendor/Pods/ 33 | 34 | ## Documentation cache and generated files: 35 | /.yardoc/ 36 | /_yardoc/ 37 | /doc/ 38 | /rdoc/ 39 | 40 | ## Environment normalization: 41 | /.bundle/ 42 | /vendor/bundle 43 | /lib/bundler/man/ 44 | 45 | # for a library or gem, you might want to ignore these files since the code is 46 | # intended to run in multiple environments; otherwise, check them in: 47 | # Gemfile.lock 48 | # .ruby-version 49 | # .ruby-gemset 50 | 51 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 52 | .rvmrc 53 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | group :development do 4 | gem "vagrant", git: "https://github.com/mitchellh/vagrant.git" 5 | end 6 | 7 | group :plugins do 8 | gem "vagrant-openbsd-provider", path: "." 9 | end 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2017, Philipp Buehler (rootnexus.net) 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dying archive, code will be merged into https://github.com/double-p/vagrant-openbsd 2 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require "bundler/setup" 3 | Bundler::GemHelper.install_tasks 4 | -------------------------------------------------------------------------------- /bhyveCon-WIP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/double-p/vagrant-openbsd-provider/55d34cb36fbf7c778e3613e15ef6f4284e33b5cb/bhyveCon-WIP.pdf -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider.rb: -------------------------------------------------------------------------------- 1 | # taken from mitchellh/vagrant-rackspace 2 | require "pathname" 3 | 4 | require "vagrant-openbsd-provider/plugin" 5 | 6 | module VagrantPlugins 7 | module ProviderOpenBSD 8 | lib_path = Pathname.new(File.expand_path("../vagrant-openbsd-provider", __FILE__)) 9 | autoload :Errors, lib_path.join("errors") 10 | 11 | # This initializes the i18n load path so that the plugin-specific 12 | # translations work. 13 | def self.init_i18n 14 | I18n.load_path << File.expand_path("locales/en.yml", source_root) 15 | I18n.reload! 16 | end 17 | 18 | # This initializes the logging so that our logs are outputted at 19 | # the same level as Vagrant core logs. 20 | def self.init_logging 21 | # Initialize logging 22 | level = nil 23 | begin 24 | level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase) 25 | rescue NameError 26 | # This means that the logging constant wasn't found, 27 | # which is fine. We just keep `level` as `nil`. But 28 | # we tell the user. 29 | level = nil 30 | end 31 | 32 | # Some constants, such as "true" resolve to booleans, so the 33 | # above error checking doesn't catch it. This will check to make 34 | # sure that the log level is an integer, as Log4r requires. 35 | level = nil if !level.is_a?(Integer) 36 | 37 | # Set the logging level on all "vagrant" namespaced 38 | # logs as long as we have a valid level. 39 | if level 40 | logger = Log4r::Logger.new("vagrant_openbsd_provider") 41 | logger.outputters = Log4r::Outputter.stderr 42 | logger.level = level 43 | logger = nil 44 | end 45 | end 46 | 47 | # This returns the path to the source of this plugin. 48 | # 49 | # @return [Pathname] 50 | def self.source_root 51 | @source_root ||= Pathname.new(File.expand_path("../../", __FILE__)) 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/action/ACTIONABLE_TASKS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/double-p/vagrant-openbsd-provider/55d34cb36fbf7c778e3613e15ef6f4284e33b5cb/lib/vagrant-openbsd-provider/action/ACTIONABLE_TASKS -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/command/VAGRANT_COMMANDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/double-p/vagrant-openbsd-provider/55d34cb36fbf7c778e3613e15ef6f4284e33b5cb/lib/vagrant-openbsd-provider/command/VAGRANT_COMMANDS -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/driver.rb: -------------------------------------------------------------------------------- 1 | require "log4r" 2 | #require "fileutils" 3 | #require "digest/md5" 4 | #require "io/console" 5 | #require "ruby_expect" 6 | 7 | 8 | module VagrantPlugins 9 | module ProviderOpenBSD 10 | class Driver 11 | 12 | #birth 13 | def initialize(machine) 14 | @logger = Log4r::Logger.new("vagrant_openbsd_provider::driver") 15 | @machine = machine 16 | @data_dir = @machine.data_dir 17 | @executor = Executor::Exec.new 18 | 19 | if Process.uid == 0 20 | @sudo = '' 21 | else 22 | @sudo = 'doas' 23 | end 24 | end 25 | 26 | def check_vmm_support 27 | result = File.exist?("/dev/vmm") 28 | raise Errors::SystemVersionIsTooLow if result == 0 29 | result = execute(true, "#{@sudo} /usr/sbin/rcctl -f check vmd" 30 | raise Errors::SystemCPUincapable if result == 1 31 | end 32 | 33 | def import(machine, ui) 34 | #do we need this, no img-based .box for now 35 | end 36 | 37 | def boot(machine, ui) 38 | directory = @data_dir 39 | config = machine.provider_config 40 | vmconfig = machine.config 41 | image = config.image 42 | 43 | vmctl_cmd = "#{@sudo} /usr/sbin/vmctl start -c -L " 44 | vmctl_cmd += "#{vmconfig.vm_name}" #XXX dump a vm-config-hash 45 | vmctl_cmd += " -b #{image}" 46 | vmctl_cmd += " -m #{config.memory}" 47 | vmctl_cmd += " -i #{config.nif}" 48 | #XXX need a hash, vmd can connect multiple; also this might come from a box 49 | # that has multiple IMGs (supported already?) - get it running with one first 50 | vmctl_cmd += " -d #{config.disk}" 51 | end 52 | 53 | def pf_enabled? 54 | return execute(true, "#{@sudo} /sbin/pfctl -si | grep Enabled") == 0 55 | return false 56 | end 57 | 58 | def ip_ready? 59 | #vm-id = tapN; ifconfig status 'UP' should be sufficient 60 | end 61 | 62 | def ssh_ready?(ssh_info) 63 | if ssh_info 64 | return execute(true, "nc -z #{ssh_info[:host]} #{ssh_info[:port]}") == 0 65 | end 66 | return false 67 | end 68 | 69 | def create_network_device(device_name, device_type) 70 | end 71 | 72 | def enable_nat(bridge, ui) 73 | # -L is doing that for us ; sysctl for forwarding? 74 | # inject anchor in pf.conf or let to user 75 | # use pfctl -a anyway 76 | end 77 | 78 | def get_ip_address(interface_name, type=:guest) 79 | # tapN having it or via switch/bridge? 80 | end 81 | 82 | def forward_port(forward_information, tap_device) 83 | # as enable_nat; forcefully inject or docs? 84 | end 85 | 86 | #lifecycle 87 | def state(vm_name) 88 | # vmctl status 89 | end 90 | 91 | def execute(*cmd, **opts, &block) 92 | # not needed? 93 | end 94 | 95 | def get_mac_address(vm_name) 96 | # tapN? 97 | end 98 | 99 | def get_interface_name(device_name) 100 | # implicit 101 | end 102 | 103 | # deathrays 104 | def shutdown(ui) 105 | end 106 | 107 | def destroy 108 | end 109 | 110 | def cleanup 111 | end 112 | end 113 | end 114 | end 115 | -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/errors.rb: -------------------------------------------------------------------------------- 1 | require "vagrant" 2 | 3 | module VagrantPlugins 4 | module ProviderOpenBSD 5 | module Errors 6 | class VagrantProviderOpenBSDError < Vagrant::Errors::VagrantError 7 | error_namespace('vagrant_openbsd_provider.errors') 8 | end 9 | 10 | class SystemVersionIsTooLow < VagrantProviderOpenBSDError 11 | error_key(:system_version_too_low) 12 | end 13 | 14 | class SystemCPUincapable < VagrantProviderOpenBSDError 15 | error_key(:system_cpu_incapable) 16 | end 17 | 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/executor.rb: -------------------------------------------------------------------------------- 1 | require "vagrant/util/busy" 2 | require "vagrant/util/subprocess" 3 | 4 | module VagrantPlugins 5 | module ProviderOpenBSD 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 39 | -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/plugin.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require "vagrant" 3 | rescue LoadError 4 | raise "The OpenBSD provider must be run within Vagrant." 5 | end 6 | 7 | # This is a sanity check to make sure no one is attempting to install 8 | # this into an early Vagrant version. 9 | if Vagrant::VERSION < "1.1.0" 10 | raise "This OpenBSD provider is only compatible with Vagrant 1.1+" 11 | end 12 | 13 | module VagrantPlugins 14 | module ProviderOpenBSD 15 | class Plugin < Vagrant.plugin("2") 16 | name "OpenBSD vmd(8)" 17 | description <<-DESC 18 | This plugin enables Vagrant to manage machines with OpenBSD's vmd(8) 19 | DESC 20 | 21 | config("vagrant-openbsd-provider", :provider) do 22 | require_relative "config" 23 | Config 24 | end 25 | 26 | provider "vagrant-openbsd-provider" do 27 | # Setup some things 28 | ProviderOpenBSD.init_i18n 29 | ProviderOpenBSD.init_logging 30 | 31 | # Load the actual provider 32 | require_relative "provider" 33 | Provider 34 | end 35 | 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/provider.rb: -------------------------------------------------------------------------------- 1 | require "vagrant" 2 | 3 | require "vagrant-openbsd-provider/action" 4 | 5 | module VagrantPlugins 6 | module ProviderOpenBSD 7 | class Provider < Vagrant.plugin("2", :provider) 8 | def initialize(machine) 9 | @machine = machine 10 | end 11 | 12 | def initialize(machine) 13 | @logger = Log4r::Logger.new("vagrant::provider::bhyve") 14 | @machine = machine 15 | end 16 | 17 | def driver 18 | return @driver if @driver 19 | @driver = Driver.new(@machine) 20 | end 21 | 22 | def ssh_info 23 | # We just return nil if were not able to identify the VM's IP and 24 | # let Vagrant core deal with it like docker provider does 25 | return nil if state.id != :running 26 | tap_device = driver.get_attr('tap') 27 | ip = driver.get_ip_address(tap_device) unless tap_device.length == 0 28 | return nil if !ip 29 | ssh_info = { 30 | host: ip, 31 | port: 22, 32 | } 33 | end 34 | 35 | def action(name) 36 | # Attrmpt to get the action method from the Action class if it 37 | # exists, otherwise return nil to show that we don't support the 38 | # given action 39 | action_method = "action_#{name}" 40 | return Action.send(action_method) if Action.respond_to?(action_method) 41 | nil 42 | end 43 | 44 | # This should return the state of the machine within this provider. 45 | # The state must be an instance of {MachineState}. Please read the 46 | # documentation of that class for more information. 47 | # 48 | # @return [MachineState] 49 | def state 50 | state_id = nil 51 | if @machine.id 52 | vm_name = driver.get_attr('vm_name') 53 | if vm_name.nil? 54 | state_id = :uncreated 55 | else 56 | state_id = driver.state(vm_name) 57 | end 58 | else 59 | state_id = :uncreated 60 | end 61 | short = state_id.to_s.gsub("_", " ") 62 | long = I18n.t("vagrant_bhyve.states.#{state_id}") 63 | # If we're not created, then specify the special ID flag 64 | state_id = Vagrant::MachineState::NOT_CREATED_ID if state_id == :uncreated 65 | # Return the MachineState object 66 | Vagrant::MachineState.new(state_id, short, long) 67 | end 68 | 69 | def to_s 70 | "OpenBSD Provider" 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/vagrant-openbsd-provider/version.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins 2 | module ProviderOpenBSD 3 | VERSION = "0.1.0" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | vagrant_openbsd_provider: 3 | system_version_too_low: |- 4 | VMM support was added in 5.9 - please upgrade OpenBSD. 5 | system_cpu_incapable: |- 6 | CPU cannot VT-d - running within virtualization? 7 | -------------------------------------------------------------------------------- /vagrant-openbsd-provider.gemspec: -------------------------------------------------------------------------------- 1 | 2 | lib = File.expand_path("../lib", __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require "vagrant-openbsd-provider/version" 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "vagrant-openbsd-provider" 8 | spec.version = VagrantPlugins::ProviderOpenBSD::VERSION 9 | spec.authors = ["Philipp Buehler"] 10 | spec.email = ["pbuehler@sysfive.com"] 11 | 12 | spec.summary = %q{OpenBSD vmd(8) vagrant provider.} 13 | spec.description = %q{his is a Vagrant 1.5+ plugin that adds an OpenBSD vmd(4) provider to Vagrant, allowing Vagrant to control and provision machines on OpenBSD.} 14 | spec.homepage = "https://github.com/double-p/vagrant-openbsd-provider" 15 | 16 | # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' 17 | # to allow pushing to a single host or delete this section to allow pushing to any host. 18 | if spec.respond_to?(:metadata) 19 | spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" 20 | else 21 | raise "RubyGems 2.0 or newer is required to protect against " \ 22 | "public gem pushes." 23 | end 24 | 25 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 26 | f.match(%r{^(test|spec|features)/}) 27 | end 28 | spec.bindir = "exe" 29 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 30 | spec.require_paths = ["lib"] 31 | 32 | spec.add_development_dependency "bundler", "~> 1.16" 33 | spec.add_development_dependency "rake", "~> 10.0" 34 | spec.add_development_dependency "vagrant-spec", "~> 1.4.0" 35 | end 36 | --------------------------------------------------------------------------------