providers/hyperv: shuffle things around
This commit is contained in:
parent
3d8971b15f
commit
a1958ee12f
|
@ -0,0 +1,36 @@
|
||||||
|
require_relative "subprocess"
|
||||||
|
require_relative "which"
|
||||||
|
|
||||||
|
module Vagrant
|
||||||
|
module Util
|
||||||
|
# Executes PowerShell scripts.
|
||||||
|
#
|
||||||
|
# This is primarily a convenience wrapper around Subprocess that
|
||||||
|
# properly sets powershell flags for you.
|
||||||
|
class PowerShell
|
||||||
|
def self.available?
|
||||||
|
!!Which.which("powershell")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Execute a powershell script.
|
||||||
|
#
|
||||||
|
# @param [String] path Path to the PowerShell script to execute.
|
||||||
|
# @return [Subprocess::Result]
|
||||||
|
def self.execute(path, *args, **opts, &block)
|
||||||
|
command = [
|
||||||
|
"powershell",
|
||||||
|
"-NoProfile",
|
||||||
|
"-ExecutionPolicy", "Bypass",
|
||||||
|
path,
|
||||||
|
args
|
||||||
|
].flatten
|
||||||
|
|
||||||
|
# Append on the options hash since Subprocess doesn't use
|
||||||
|
# Ruby 2.0 style options yet.
|
||||||
|
command << opts
|
||||||
|
|
||||||
|
Subprocess.execute(*command, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -44,8 +44,8 @@ module VagrantPlugins
|
||||||
def self.action_start
|
def self.action_start
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
b.use StartInstance
|
b.use StartInstance
|
||||||
b.use ShareFolders
|
#b.use ShareFolders
|
||||||
b.use SyncFolders
|
#b.use SyncFolders
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
# All Rights Reserved. Licensed under the MIT License.
|
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
require "debugger"
|
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module HyperV
|
module HyperV
|
||||||
module Action
|
module Action
|
||||||
|
@ -19,7 +15,7 @@ module VagrantPlugins
|
||||||
options = { vm_id: env[:machine].id }
|
options = { vm_id: env[:machine].id }
|
||||||
response = env[:machine].provider.driver.execute('get_vm_status.ps1', options)
|
response = env[:machine].provider.driver.execute('get_vm_status.ps1', options)
|
||||||
env[:machine_state_id] = response["state"].downcase.to_sym
|
env[:machine_state_id] = response["state"].downcase.to_sym
|
||||||
rescue Error::SubprocessError => e
|
rescue Error::SubprocessError
|
||||||
env[:machine].id = nil
|
env[:machine].id = nil
|
||||||
env[:ui].info "Could not find a machine, assuming it to be deleted or terminated."
|
env[:ui].info "Could not find a machine, assuming it to be deleted or terminated."
|
||||||
env[:machine_state_id] = :not_created
|
env[:machine_state_id] = :not_created
|
||||||
|
@ -29,7 +25,6 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,6 +32,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
errors = _detected_errors
|
errors = _detected_errors
|
||||||
|
=begin
|
||||||
unless host_share.valid_config?
|
unless host_share.valid_config?
|
||||||
errors << host_share.errors.flatten.join(" ")
|
errors << host_share.errors.flatten.join(" ")
|
||||||
end
|
end
|
||||||
|
@ -39,6 +40,7 @@ module VagrantPlugins
|
||||||
unless guest.valid_config?
|
unless guest.valid_config?
|
||||||
errors << guest.errors.flatten.join(" ")
|
errors << guest.errors.flatten.join(" ")
|
||||||
end
|
end
|
||||||
|
=end
|
||||||
{ "HyperV" => errors }
|
{ "HyperV" => errors }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,95 @@
|
||||||
#-------------------------------------------------------------------------
|
require "json"
|
||||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
# All Rights Reserved. Licensed under the MIT License.
|
require "vagrant/util/powershell"
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module HyperV
|
module HyperV
|
||||||
module Driver
|
class Driver
|
||||||
lib_path = Pathname.new(File.expand_path("../driver", __FILE__))
|
attr_reader :vmid
|
||||||
autoload :Base, lib_path.join("base")
|
|
||||||
|
def initialize(id=nil)
|
||||||
|
@vmid = id
|
||||||
|
@output = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(path, options)
|
||||||
|
execute_powershell(path, options) do |type, data|
|
||||||
|
process_output(type, data)
|
||||||
|
end
|
||||||
|
if success?
|
||||||
|
JSON.parse(json_output[:success].join) unless json_output[:success].empty?
|
||||||
|
else
|
||||||
|
message = json_output[:error].join unless json_output[:error].empty?
|
||||||
|
raise Error::SubprocessError, message if message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def raw_execute(command)
|
||||||
|
command = [command , {notify: [:stdout, :stderr, :stdin]}].flatten
|
||||||
|
clear_output_buffer
|
||||||
|
Vagrant::Util::Subprocess.execute(*command) do |type, data|
|
||||||
|
process_output(type, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def json_output
|
||||||
|
return @json_output if @json_output
|
||||||
|
json_success_begin = false
|
||||||
|
json_error_begin = false
|
||||||
|
success = []
|
||||||
|
error = []
|
||||||
|
@output.split("\n").each do |line|
|
||||||
|
json_error_begin = false if line.include?("===End-Error===")
|
||||||
|
json_success_begin = false if line.include?("===End-Output===")
|
||||||
|
message = ""
|
||||||
|
if json_error_begin || json_success_begin
|
||||||
|
message = line.gsub("\\'","\"")
|
||||||
|
end
|
||||||
|
success << message if json_success_begin
|
||||||
|
error << message if json_error_begin
|
||||||
|
json_success_begin = true if line.include?("===Begin-Output===")
|
||||||
|
json_error_begin = true if line.include?("===Begin-Error===")
|
||||||
|
end
|
||||||
|
@json_output = { :success => success, :error => error }
|
||||||
|
end
|
||||||
|
|
||||||
|
def success?
|
||||||
|
@error_messages.empty? && json_output[:error].empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_output(type, data)
|
||||||
|
if type == :stdout
|
||||||
|
@output = data.gsub("\r\n", "\n")
|
||||||
|
end
|
||||||
|
if type == :stdin
|
||||||
|
# $stdin.gets.chomp || ""
|
||||||
|
end
|
||||||
|
if type == :stderr
|
||||||
|
@error_messages = data.gsub("\r\n", "\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_output_buffer
|
||||||
|
@output = ""
|
||||||
|
@error_messages = ""
|
||||||
|
@json_output = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_powershell(path, options, &block)
|
||||||
|
lib_path = Pathname.new(File.expand_path("../../scripts", __FILE__))
|
||||||
|
path = lib_path.join(path).to_s.gsub("/", "\\")
|
||||||
|
options = options || {}
|
||||||
|
ps_options = []
|
||||||
|
options.each do |key, value|
|
||||||
|
ps_options << "-#{key}"
|
||||||
|
ps_options << "'#{value}'"
|
||||||
|
end
|
||||||
|
clear_output_buffer
|
||||||
|
opts = { notify: [:stdout, :stderr, :stdin] }
|
||||||
|
Vagrant::Util::PowerShell.execute(path, *ps_options, **opts, &block)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
require "json"
|
|
||||||
require "vagrant/util/which"
|
|
||||||
require "vagrant/util/subprocess"
|
|
||||||
|
|
||||||
module VagrantPlugins
|
|
||||||
module HyperV
|
|
||||||
module Driver
|
|
||||||
class Base
|
|
||||||
attr_reader :vmid
|
|
||||||
|
|
||||||
def initialize(id=nil)
|
|
||||||
@vmid = id
|
|
||||||
check_power_shell
|
|
||||||
@output = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute(path, options)
|
|
||||||
r = execute_powershell(path, options) do |type, data|
|
|
||||||
process_output(type, data)
|
|
||||||
end
|
|
||||||
if success?
|
|
||||||
JSON.parse(json_output[:success].join) unless json_output[:success].empty?
|
|
||||||
else
|
|
||||||
message = json_output[:error].join unless json_output[:error].empty?
|
|
||||||
raise Error::SubprocessError, message if message
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def raw_execute(command)
|
|
||||||
command = [command , {notify: [:stdout, :stderr, :stdin]}].flatten
|
|
||||||
clear_output_buffer
|
|
||||||
Vagrant::Util::Subprocess.execute(*command) do |type, data|
|
|
||||||
process_output(type, data)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def json_output
|
|
||||||
return @json_output if @json_output
|
|
||||||
json_success_begin = false
|
|
||||||
json_error_begin = false
|
|
||||||
success = []
|
|
||||||
error = []
|
|
||||||
@output.split("\n").each do |line|
|
|
||||||
json_error_begin = false if line.include?("===End-Error===")
|
|
||||||
json_success_begin = false if line.include?("===End-Output===")
|
|
||||||
message = ""
|
|
||||||
if json_error_begin || json_success_begin
|
|
||||||
message = line.gsub("\\'","\"")
|
|
||||||
end
|
|
||||||
success << message if json_success_begin
|
|
||||||
error << message if json_error_begin
|
|
||||||
json_success_begin = true if line.include?("===Begin-Output===")
|
|
||||||
json_error_begin = true if line.include?("===Begin-Error===")
|
|
||||||
end
|
|
||||||
@json_output = { :success => success, :error => error }
|
|
||||||
end
|
|
||||||
|
|
||||||
def success?
|
|
||||||
@error_messages.empty? && json_output[:error].empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_output(type, data)
|
|
||||||
if type == :stdout
|
|
||||||
@output = data.gsub("\r\n", "\n")
|
|
||||||
end
|
|
||||||
if type == :stdin
|
|
||||||
# $stdin.gets.chomp || ""
|
|
||||||
end
|
|
||||||
if type == :stderr
|
|
||||||
@error_messages = data.gsub("\r\n", "\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def clear_output_buffer
|
|
||||||
@output = ""
|
|
||||||
@error_messages = ""
|
|
||||||
@json_output = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_power_shell
|
|
||||||
unless Vagrant::Util::Which.which('powershell')
|
|
||||||
raise "Power Shell not found"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute_powershell(path, options, &block)
|
|
||||||
lib_path = Pathname.new(File.expand_path("../../scripts", __FILE__))
|
|
||||||
path = lib_path.join(path).to_s.gsub("/", "\\")
|
|
||||||
options = options || {}
|
|
||||||
ps_options = []
|
|
||||||
options.each do |key, value|
|
|
||||||
ps_options << "-#{key}"
|
|
||||||
ps_options << "'#{value}'"
|
|
||||||
end
|
|
||||||
clear_output_buffer
|
|
||||||
command = ["powershell", "-NoProfile", "-ExecutionPolicy",
|
|
||||||
"Bypass", path, ps_options, {notify: [:stdout, :stderr, :stdin]}].flatten
|
|
||||||
Vagrant::Util::Subprocess.execute(*command, &block)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,13 +0,0 @@
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
# All Rights Reserved. Licensed under the MIT License.
|
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
module VagrantPlugins
|
|
||||||
module HyperV
|
|
||||||
module Error
|
|
||||||
lib_path = Pathname.new(File.expand_path("../error", __FILE__))
|
|
||||||
autoload :SubprocessError, lib_path.join("subprocess_error")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,24 +0,0 @@
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
# All Rights Reserved. Licensed under the MIT License.
|
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
require "json"
|
|
||||||
require "vagrant/util/which"
|
|
||||||
require "vagrant/util/subprocess"
|
|
||||||
|
|
||||||
module VagrantPlugins
|
|
||||||
module HyperV
|
|
||||||
module Error
|
|
||||||
class SubprocessError < RuntimeError
|
|
||||||
def initialize(message)
|
|
||||||
@message = JSON.parse(message) if message
|
|
||||||
end
|
|
||||||
|
|
||||||
def message
|
|
||||||
@message["error"]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module HyperV
|
||||||
|
module Errors
|
||||||
|
# A convenient superclass for all our errors.
|
||||||
|
class HyperVError < Vagrant::Errors::VagrantError
|
||||||
|
error_namespace("vagrant_hyperv.errors")
|
||||||
|
end
|
||||||
|
|
||||||
|
class PowerShellRequired < HyperVError
|
||||||
|
error_key(:powershell_required)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,8 @@
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module HyperV
|
module HyperV
|
||||||
|
autoload :Action, File.expand_path("../action", __FILE__)
|
||||||
|
autoload :Errors, File.expand_path("../errors", __FILE__)
|
||||||
|
|
||||||
class Plugin < Vagrant.plugin("2")
|
class Plugin < Vagrant.plugin("2")
|
||||||
name "Hyper-V provider"
|
name "Hyper-V provider"
|
||||||
description <<-DESC
|
description <<-DESC
|
||||||
|
@ -9,13 +12,25 @@ module VagrantPlugins
|
||||||
|
|
||||||
provider(:hyperv, parallel: true) do
|
provider(:hyperv, parallel: true) do
|
||||||
require_relative "provider"
|
require_relative "provider"
|
||||||
|
init!
|
||||||
Provider
|
Provider
|
||||||
end
|
end
|
||||||
|
|
||||||
config(:hyperv, :provider) do
|
config(:hyperv, :provider) do
|
||||||
require_relative "config"
|
require_relative "config"
|
||||||
|
init!
|
||||||
Config
|
Config
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def self.init!
|
||||||
|
return if defined?(@_init)
|
||||||
|
I18n.load_path << File.expand_path(
|
||||||
|
"templates/locales/providers_hyperv.yml", Vagrant.source_root)
|
||||||
|
I18n.reload!
|
||||||
|
@_init = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,22 @@
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
|
require_relative "driver"
|
||||||
|
require_relative "plugin"
|
||||||
|
|
||||||
|
require "vagrant/util/powershell"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module HyperV
|
module HyperV
|
||||||
class Provider < Vagrant.plugin("2", :provider)
|
class Provider < Vagrant.plugin("2", :provider)
|
||||||
|
attr_reader :driver
|
||||||
|
|
||||||
def initialize(machine)
|
def initialize(machine)
|
||||||
|
@driver = Driver.new
|
||||||
@machine = machine
|
@machine = machine
|
||||||
|
|
||||||
|
if !Vagrant::Util::PowerShell.available?
|
||||||
|
raise Errors::PowerShellRequired
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def action(name)
|
def action(name)
|
||||||
|
@ -45,10 +57,6 @@ module VagrantPlugins
|
||||||
env[:machine_ssh_info].merge!(:port => 22)
|
env[:machine_ssh_info].merge!(:port => 22)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def driver
|
|
||||||
@driver ||= Driver::Base.new()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
en:
|
||||||
|
vagrant_hyperv:
|
||||||
|
errors:
|
||||||
|
powershell_required: |-
|
||||||
|
The Vagrant Hyper-V provider requires PowerShell to be available.
|
||||||
|
Please make sure "powershell.exe" is available on your PATH.
|
|
@ -0,0 +1,24 @@
|
||||||
|
require_relative "../../../base"
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/providers/hyperv/provider")
|
||||||
|
|
||||||
|
describe VagrantPlugins::HyperV::Provider do
|
||||||
|
let(:machine) { double("machine") }
|
||||||
|
let(:powershell) { double("powershell") }
|
||||||
|
|
||||||
|
subject { described_class.new(machine) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_const("Vagrant::Util::PowerShell", powershell)
|
||||||
|
powershell.stub(available?: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#initialize" do
|
||||||
|
it "raises an exception if powershell is not available" do
|
||||||
|
powershell.stub(available?: false)
|
||||||
|
|
||||||
|
expect { subject }.
|
||||||
|
to raise_error(VagrantPlugins::HyperV::Errors::PowerShellRequired)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue