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
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use StartInstance
|
||||
b.use ShareFolders
|
||||
b.use SyncFolders
|
||||
#b.use ShareFolders
|
||||
#b.use SyncFolders
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
||||
# All Rights Reserved. Licensed under the MIT License.
|
||||
#--------------------------------------------------------------------------
|
||||
require "debugger"
|
||||
require "log4r"
|
||||
|
||||
module VagrantPlugins
|
||||
module HyperV
|
||||
module Action
|
||||
|
@ -19,7 +15,7 @@ module VagrantPlugins
|
|||
options = { vm_id: env[:machine].id }
|
||||
response = env[:machine].provider.driver.execute('get_vm_status.ps1', options)
|
||||
env[:machine_state_id] = response["state"].downcase.to_sym
|
||||
rescue Error::SubprocessError => e
|
||||
rescue Error::SubprocessError
|
||||
env[:machine].id = nil
|
||||
env[:ui].info "Could not find a machine, assuming it to be deleted or terminated."
|
||||
env[:machine_state_id] = :not_created
|
||||
|
@ -29,7 +25,6 @@ module VagrantPlugins
|
|||
end
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,7 @@ module VagrantPlugins
|
|||
|
||||
def validate(machine)
|
||||
errors = _detected_errors
|
||||
=begin
|
||||
unless host_share.valid_config?
|
||||
errors << host_share.errors.flatten.join(" ")
|
||||
end
|
||||
|
@ -39,6 +40,7 @@ module VagrantPlugins
|
|||
unless guest.valid_config?
|
||||
errors << guest.errors.flatten.join(" ")
|
||||
end
|
||||
=end
|
||||
{ "HyperV" => errors }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,13 +1,95 @@
|
|||
#-------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
||||
# All Rights Reserved. Licensed under the MIT License.
|
||||
#--------------------------------------------------------------------------
|
||||
require "json"
|
||||
|
||||
require "vagrant/util/powershell"
|
||||
|
||||
module VagrantPlugins
|
||||
module HyperV
|
||||
module Driver
|
||||
lib_path = Pathname.new(File.expand_path("../driver", __FILE__))
|
||||
autoload :Base, lib_path.join("base")
|
||||
class Driver
|
||||
attr_reader :vmid
|
||||
|
||||
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
|
||||
|
|
|
@ -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 HyperV
|
||||
autoload :Action, File.expand_path("../action", __FILE__)
|
||||
autoload :Errors, File.expand_path("../errors", __FILE__)
|
||||
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "Hyper-V provider"
|
||||
description <<-DESC
|
||||
|
@ -9,13 +12,25 @@ module VagrantPlugins
|
|||
|
||||
provider(:hyperv, parallel: true) do
|
||||
require_relative "provider"
|
||||
init!
|
||||
Provider
|
||||
end
|
||||
|
||||
config(:hyperv, :provider) do
|
||||
require_relative "config"
|
||||
init!
|
||||
Config
|
||||
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
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
require "log4r"
|
||||
|
||||
require_relative "driver"
|
||||
require_relative "plugin"
|
||||
|
||||
require "vagrant/util/powershell"
|
||||
|
||||
module VagrantPlugins
|
||||
module HyperV
|
||||
class Provider < Vagrant.plugin("2", :provider)
|
||||
attr_reader :driver
|
||||
|
||||
def initialize(machine)
|
||||
@driver = Driver.new
|
||||
@machine = machine
|
||||
|
||||
if !Vagrant::Util::PowerShell.available?
|
||||
raise Errors::PowerShellRequired
|
||||
end
|
||||
end
|
||||
|
||||
def action(name)
|
||||
|
@ -45,10 +57,6 @@ module VagrantPlugins
|
|||
env[:machine_ssh_info].merge!(:port => 22)
|
||||
end
|
||||
end
|
||||
|
||||
def driver
|
||||
@driver ||= Driver::Base.new()
|
||||
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