providers/hyperv: wait for IP on boot
This commit is contained in:
parent
64abd95c6f
commit
5d19285774
|
@ -66,6 +66,7 @@ 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 WaitForIPAddress
|
||||||
#b.use ShareFolders
|
#b.use ShareFolders
|
||||||
#b.use SyncFolders
|
#b.use SyncFolders
|
||||||
end
|
end
|
||||||
|
@ -139,9 +140,10 @@ module VagrantPlugins
|
||||||
autoload :MessageAlreadyCreated, action_root.join('message_already_created')
|
autoload :MessageAlreadyCreated, action_root.join('message_already_created')
|
||||||
autoload :MessageNotRunning, action_root.join('message_not_running')
|
autoload :MessageNotRunning, action_root.join('message_not_running')
|
||||||
autoload :SyncFolders, action_root.join('sync_folders')
|
autoload :SyncFolders, action_root.join('sync_folders')
|
||||||
autoload :WaitForState, action_root.join('wait_for_state')
|
|
||||||
autoload :ReadGuestIP, action_root.join('read_guest_ip')
|
autoload :ReadGuestIP, action_root.join('read_guest_ip')
|
||||||
autoload :ShareFolders, action_root.join('share_folders')
|
autoload :ShareFolders, action_root.join('share_folders')
|
||||||
|
autoload :WaitForIPAddress, action_root.join("wait_for_ip_address")
|
||||||
|
autoload :WaitForState, action_root.join('wait_for_state')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,10 +44,10 @@ module VagrantPlugins
|
||||||
vhdx_path: vhdx_path.to_s.gsub("/", "\\")
|
vhdx_path: vhdx_path.to_s.gsub("/", "\\")
|
||||||
}
|
}
|
||||||
|
|
||||||
env[:ui].info "Importing a Hyper-V instance"
|
env[:ui].output("Importing a Hyper-V instance")
|
||||||
server = env[:machine].provider.driver.execute(
|
server = env[:machine].provider.driver.execute(
|
||||||
'import_vm.ps1', options)
|
'import_vm.ps1', options)
|
||||||
env[:ui].info "Successfully imported a VM with name: #{server['name']}"
|
env[:ui].detail("Successfully imported a VM with name: #{server['name']}")
|
||||||
env[:machine].id = server["id"]
|
env[:machine].id = server["id"]
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
# All Rights Reserved. Licensed under the MIT License.
|
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
require "log4r"
|
require "log4r"
|
||||||
require "timeout"
|
require "timeout"
|
||||||
|
|
||||||
|
@ -23,13 +19,14 @@ module VagrantPlugins
|
||||||
|
|
||||||
def read_host_ip(env)
|
def read_host_ip(env)
|
||||||
return nil if env[:machine].id.nil?
|
return nil if env[:machine].id.nil?
|
||||||
|
|
||||||
# Get Network details from WMI Provider
|
# Get Network details from WMI Provider
|
||||||
# Wait for 120 sec By then the machine should be ready
|
# Wait for 120 sec By then the machine should be ready
|
||||||
host_ip = nil
|
host_ip = nil
|
||||||
begin
|
begin
|
||||||
Timeout.timeout(120) do
|
Timeout.timeout(120) do
|
||||||
begin
|
begin
|
||||||
options = { vm_id: env[:machine].id }
|
options = { VmId: env[:machine].id }
|
||||||
network_info = env[:machine].provider.driver.execute('get_network_config.ps1', options)
|
network_info = env[:machine].provider.driver.execute('get_network_config.ps1', options)
|
||||||
host_ip = network_info["ip"]
|
host_ip = network_info["ip"]
|
||||||
sleep 10 if host_ip.empty?
|
sleep 10 if host_ip.empty?
|
||||||
|
|
|
@ -7,15 +7,10 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
env[:ui].info('Starting the Machine')
|
env[:ui].output('Starting the machine...')
|
||||||
options = { vm_id: env[:machine].id }
|
options = { vm_id: env[:machine].id }
|
||||||
begin
|
response = env[:machine].provider.driver.execute('start_vm.ps1', options)
|
||||||
response = env[:machine].provider.driver.execute('start_vm.ps1', options)
|
|
||||||
env[:ui].info "Machine #{response["name"]} started"
|
|
||||||
rescue Error::SubprocessError => e
|
|
||||||
env[:ui].info e.message
|
|
||||||
return
|
|
||||||
end
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
require "timeout"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module HyperV
|
||||||
|
module Action
|
||||||
|
class WaitForIPAddress
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
timeout = env[:machine].provider_config.ip_address_timeout
|
||||||
|
|
||||||
|
env[:ui].output("Waiting for the machine to report its IP address...")
|
||||||
|
env[:ui].detail("Timeout: #{timeout} seconds")
|
||||||
|
|
||||||
|
guest_ip = nil
|
||||||
|
Timeout.timeout(timeout) do
|
||||||
|
while true
|
||||||
|
# If a ctrl-c came through, break out
|
||||||
|
return if env[:interrupted]
|
||||||
|
|
||||||
|
# Try to get the IP
|
||||||
|
network_info = env[:machine].provider.driver.execute(
|
||||||
|
"get_network_config.ps1", VmId: env[:machine].id)
|
||||||
|
guest_ip = network_info["ip"]
|
||||||
|
break if guest_ip && guest_ip != ""
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# If we were interrupted then return now
|
||||||
|
return if env[:interrupted]
|
||||||
|
|
||||||
|
env[:ui].detail("IP: #{guest_ip}")
|
||||||
|
|
||||||
|
@app.call(env)
|
||||||
|
rescue Timeout::Error
|
||||||
|
raise Errors::IPAddrTimeout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,34 +1,32 @@
|
||||||
require "vagrant"
|
require "vagrant"
|
||||||
require_relative "guest_config/config"
|
|
||||||
require_relative "host_share/config"
|
require_relative "host_share/config"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module HyperV
|
module HyperV
|
||||||
class Config < Vagrant.plugin("2", :config)
|
class Config < Vagrant.plugin("2", :config)
|
||||||
# If set to `true`, then VirtualBox will be launched with a GUI.
|
# The timeout to wait for an IP address when booting the machine,
|
||||||
|
# in seconds.
|
||||||
#
|
#
|
||||||
# @return [Boolean]
|
# @return [Integer]
|
||||||
attr_accessor :gui
|
attr_accessor :ip_address_timeout
|
||||||
|
|
||||||
attr_reader :host_share, :guest
|
attr_reader :host_share
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@ip_address_timeout = UNSET_VALUE
|
||||||
|
@host_share = HostShare::Config.new
|
||||||
|
end
|
||||||
|
|
||||||
def host_config(&block)
|
def host_config(&block)
|
||||||
block.call(@host_share)
|
block.call(@host_share)
|
||||||
end
|
end
|
||||||
|
|
||||||
def guest_config(&block)
|
|
||||||
block.call(@guest)
|
|
||||||
end
|
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
@gui = nil if @gui == UNSET_VALUE
|
if @ip_address_timeout == UNSET_VALUE
|
||||||
|
@ip_address_timeout = 120
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(region_specific=false)
|
|
||||||
@gui = UNSET_VALUE
|
|
||||||
@host_share = HostShare::Config.new
|
|
||||||
@guest = GuestConfig::Config.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
errors = _detected_errors
|
errors = _detected_errors
|
||||||
|
@ -36,10 +34,6 @@ module VagrantPlugins
|
||||||
unless host_share.valid_config?
|
unless host_share.valid_config?
|
||||||
errors << host_share.errors.flatten.join(" ")
|
errors << host_share.errors.flatten.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
unless guest.valid_config?
|
|
||||||
errors << guest.errors.flatten.join(" ")
|
|
||||||
end
|
|
||||||
=end
|
=end
|
||||||
{ "HyperV" => errors }
|
{ "HyperV" => errors }
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,10 @@ module VagrantPlugins
|
||||||
error_key(:box_invalid)
|
error_key(:box_invalid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class IPAddrTimeout < HyperVError
|
||||||
|
error_key(:ip_addr_timeout)
|
||||||
|
end
|
||||||
|
|
||||||
class PowerShellError < HyperVError
|
class PowerShellError < HyperVError
|
||||||
error_key(:powershell_error)
|
error_key(:powershell_error)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
# All Rights Reserved. Licensed under the MIT License.
|
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
module VagrantPlugins
|
|
||||||
module HyperV
|
|
||||||
module GuestConfig
|
|
||||||
class Config < Vagrant.plugin("2", :config)
|
|
||||||
attr_accessor :username, :password
|
|
||||||
|
|
||||||
def errors
|
|
||||||
@errors
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate
|
|
||||||
@errors = []
|
|
||||||
if username.nil?
|
|
||||||
@errors << "Please configure a Guest VM's username"
|
|
||||||
end
|
|
||||||
if password.nil?
|
|
||||||
@errors << "Please configure a Guest VM's password"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def valid_config?
|
|
||||||
validate
|
|
||||||
errors.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,28 +1,17 @@
|
||||||
#-------------------------------------------------------------------------
|
Param(
|
||||||
# Copyright (c) Microsoft Open Technologies, Inc.
|
[Parameter(Mandatory=$true)]
|
||||||
# All Rights Reserved. Licensed under the MIT License.
|
[string]$VmId
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
param (
|
|
||||||
[string]$vm_id = $(throw "-vm_id is required.")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Include the following modules
|
# Include the following modules
|
||||||
$presentDir = Split-Path -parent $PSCommandPath
|
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
||||||
$modules = @()
|
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
||||||
$modules += $presentDir + "\utils\write_messages.ps1"
|
|
||||||
forEach ($module in $modules) { . $module }
|
|
||||||
|
|
||||||
try {
|
$vm = Get-VM -Id $VmId -ErrorAction "Stop"
|
||||||
$vm = Get-VM -Id $vm_id -ErrorAction "stop"
|
$network = Get-VMNetworkAdapter -VM $vm
|
||||||
$network = Get-VMNetworkAdapter -VM $vm
|
$ip_address = $network.IpAddresses[0]
|
||||||
$ip_address = $network.IpAddresses[0]
|
$resultHash = @{
|
||||||
$resultHash = @{
|
|
||||||
ip = "$ip_address"
|
ip = "$ip_address"
|
||||||
}
|
|
||||||
$result = ConvertTo-Json $resultHash
|
|
||||||
Write-Output-Message $result
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error-Message "Failed to obtain network info of VM $_"
|
|
||||||
}
|
}
|
||||||
|
$result = ConvertTo-Json $resultHash
|
||||||
|
Write-Output-Message $result
|
||||||
|
|
|
@ -20,6 +20,16 @@ en:
|
||||||
these directories or does not contain the files expected. Verify
|
these directories or does not contain the files expected. Verify
|
||||||
that you added the correct box. If this problem persists,
|
that you added the correct box. If this problem persists,
|
||||||
please contact the creator of the box for assistance.
|
please contact the creator of the box for assistance.
|
||||||
|
ip_addr_timeout: |-
|
||||||
|
Hyper-V failed to determine your machine's IP address within the
|
||||||
|
configured timeout. Please verify the machine properly booted and
|
||||||
|
the network works. To do this, open the Hyper-V manager, find your
|
||||||
|
virtual machine, and connect to it.
|
||||||
|
|
||||||
|
The most common cause for this error is that the running virtual
|
||||||
|
machine doesn't have the latest Hyper-V integration drivers. Please
|
||||||
|
research for your operating system how to install these in order
|
||||||
|
for the VM to properly communicate its IP address to Hyper-V.
|
||||||
powershell_error: |-
|
powershell_error: |-
|
||||||
An error occurred while executing a PowerShell script. This error
|
An error occurred while executing a PowerShell script. This error
|
||||||
is shown below. Please read the error message and see if this is
|
is shown below. Please read the error message and see if this is
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
require_relative "../../../base"
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/providers/hyperv/config")
|
||||||
|
|
||||||
|
describe VagrantPlugins::HyperV::Config do
|
||||||
|
describe "#ip_address_timeout" do
|
||||||
|
it "can be set" do
|
||||||
|
subject.ip_address_timeout = 180
|
||||||
|
subject.finalize!
|
||||||
|
expect(subject.ip_address_timeout).to eq(180)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "defaults to a number" do
|
||||||
|
subject.finalize!
|
||||||
|
expect(subject.ip_address_timeout).to eq(120)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue