Overhaul the Hyper-V provider

This commit is contained in:
Chris Roberts 2018-05-24 09:57:55 -07:00
parent dbba41a7ec
commit e6457d5061
36 changed files with 1510 additions and 813 deletions

View File

@ -47,13 +47,17 @@ module Vagrant
if opts.delete(:sudo) || opts.delete(:runas)
powerup_command(path, args, opts)
else
env = opts.delete(:env)
if env
env = env.map{|k,v| "$env:#{k}=#{v}"}.join(";") + "; "
end
command = [
executable,
"-NoLogo",
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy", "Bypass",
"&('#{path}')",
"#{env}&('#{path}')",
args
].flatten

View File

@ -140,6 +140,8 @@ module VagrantPlugins
end
b2.use Provision
b2.use Configure
b2.use SetName
b2.use NetSetVLan
b2.use NetSetMac
b2.use StartInstance
@ -288,6 +290,7 @@ module VagrantPlugins
autoload :Export, action_root.join("export")
autoload :CheckEnabled, action_root.join("check_enabled")
autoload :Configure, action_root.join("configure")
autoload :DeleteVM, action_root.join("delete_vm")
autoload :Import, action_root.join("import")
autoload :Package, action_root.join("package")
@ -304,6 +307,7 @@ module VagrantPlugins
autoload :SnapshotDelete, action_root.join("snapshot_delete")
autoload :SnapshotRestore, action_root.join("snapshot_restore")
autoload :SnapshotSave, action_root.join("snapshot_save")
autoload :SetName, action_root.join("set_name")
end
end
end

View File

@ -0,0 +1,102 @@
require "fileutils"
require "log4r"
module VagrantPlugins
module HyperV
module Action
class Configure
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::hyperv::configure")
end
def call(env)
switches = env[:machine].provider.driver.execute(:get_switches)
if switches.empty?
raise Errors::NoSwitches
end
switch = nil
env[:machine].config.vm.networks.each do |type, opts|
next if type != :public_network && type != :private_network
if opts[:bridge]
@logger.debug("Looking for switch with name or ID: #{opts[:bridge]}")
switch = switches.find{ |s|
s["Name"].downcase == opts[:bridge] ||
s["Id"].downcase == opts[:bridge]
}
if switch
@logger.debug("Found switch - Name: #{switch["Name"]} ID: #{switch["Id"]}")
switch = switch["Id"]
break
end
end
end
# If we already configured previously don't prompt for switch
sentinel = env[:machine].data_dir.join("action_configure")
if !switch && !sentinel.file?
if switches.length > 1
env[:ui].detail(I18n.t("vagrant_hyperv.choose_switch") + "\n ")
switches.each_index do |i|
switch = switches[i]
env[:ui].detail("#{i+1}) #{switch["Name"]}")
end
env[:ui].detail(" ")
switch = nil
while !switch
switch = env[:ui].ask("What switch would you like to use? ")
next if !switch
switch = switch.to_i - 1
switch = nil if switch < 0 || switch >= switches.length
end
switch = switches[switch]["Id"]
else
switch = switches.first["Id"]
@logger.debug("Only single switch available so using that.")
end
end
options = {
"VMID" => env[:machine].id,
"SwitchID" => switch,
"Memory" => env[:machine].provider_config.memory,
"MaxMemory" => env[:machine].provider_config.maxmemory,
"Processors" => env[:machine].provider_config.cpus,
"AutoStartAction" => env[:machine].provider_config.auto_start_action,
"AutoStopAction" => env[:machine].provider_config.auto_stop_action,
"EnableCheckpoints" => env[:machine].provider_config.enable_checkpoints,
"VirtualizationExtensions" => !!env[:machine].provider_config.enable_virtualization_extensions,
}
options.delete_if{|_,v| v.nil? }
env[:ui].detail("Configuring the VM...")
env[:machine].provider.driver.execute(:configure_vm, options)
# Create the sentinel
sentinel.open("w") do |f|
f.write(Time.now.to_i.to_s)
end
if env[:machine].provider_config.vm_integration_services
env[:ui].detail("Setting VM Integration Services")
env[:machine].provider_config.vm_integration_services.each do |key, value|
state = value ? "enabled" : "disabled"
env[:ui].output("#{key} is #{state}")
end
env[:machine].provider.driver.set_vm_integration_services(
env[:machine].provider_config.vm_integration_services)
end
@app.call(env)
end
end
end
end
end

View File

@ -1,11 +1,13 @@
require "fileutils"
require "log4r"
module VagrantPlugins
module HyperV
module Action
class Import
VALID_HD_EXTENSIONS = [".vhd".freeze, ".vhdx".freeze].freeze
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::hyperv::import")
@ -14,160 +16,64 @@ module VagrantPlugins
def call(env)
vm_dir = env[:machine].box.directory.join("Virtual Machines")
hd_dir = env[:machine].box.directory.join("Virtual Hard Disks")
memory = env[:machine].provider_config.memory
maxmemory = env[:machine].provider_config.maxmemory
cpus = env[:machine].provider_config.cpus
vmname = env[:machine].provider_config.vmname
differencing_disk = env[:machine].provider_config.differencing_disk
auto_start_action = env[:machine].provider_config.auto_start_action
auto_stop_action = env[:machine].provider_config.auto_stop_action
enable_virtualization_extensions = env[:machine].provider_config.enable_virtualization_extensions
vm_integration_services = env[:machine].provider_config.vm_integration_services
env[:ui].output("Configured Dynamic memory allocation, maxmemory is #{maxmemory}") if maxmemory
env[:ui].output("Configured startup memory is #{memory}") if memory
env[:ui].output("Configured cpus number is #{cpus}") if cpus
env[:ui].output("Configured enable virtualization extensions is #{enable_virtualization_extensions}") if enable_virtualization_extensions
env[:ui].output("Configured vmname is #{vmname}") if vmname
env[:ui].output("Configured differencing disk instead of cloning") if differencing_disk
env[:ui].output("Configured automatic start action is #{auto_start_action}") if auto_start_action
env[:ui].output("Configured automatic stop action is #{auto_stop_action}") if auto_stop_action
if !vm_dir.directory? || !hd_dir.directory?
@logger.error("Required virtual machine directory not found!")
raise Errors::BoxInvalid
end
valid_config_ext = [".xml"]
if env[:machine].provider.driver.has_vmcx_support?
valid_config_ext << ".vmcx"
end
config_path = nil
config_type = nil
vm_dir.each_child do |f|
if f.extname.downcase == '.xml'
@logger.debug("Found XML config...")
config_path = f
config_type = 'xml'
vm_dir.each_child do |file|
if valid_config_ext.include?(file.extname.downcase)
config_path = file
break
end
end
vmcx_support = env[:machine].provider.driver.execute("has_vmcx_support.ps1", {})['result']
if vmcx_support
vm_dir.each_child do |f|
if f.extname.downcase == '.vmcx'
@logger.debug("Found VMCX config and support...")
config_path = f
config_type = 'vmcx'
break
end
end
if !config_path
@logger.error("Failed to locate box configuration path")
raise Errors::BoxInvalid
else
@logger.info("Found box configuration path: #{config_path}")
end
image_path = nil
image_ext = nil
image_filename = nil
hd_dir.each_child do |f|
if %w{.vhd .vhdx}.include?(f.extname.downcase)
image_path = f
image_ext = f.extname.downcase
image_filename = File.basename(f, image_ext)
hd_dir.each_child do |file|
if VALID_HD_EXTENSIONS.include?(file.extname.downcase)
image_path = file
break
end
end
if !config_path || !image_path
if !image_path
@logger.error("Failed to locate box image path")
raise Errors::BoxInvalid
else
@logger.info("Found box image path: #{image_path}")
end
env[:ui].output("Importing a Hyper-V instance")
dest_path = env[:machine].data_dir.join("Virtual Hard Disks").join(image_path.basename).to_s
switches = env[:machine].provider.driver.execute("get_switches.ps1", {})
raise Errors::NoSwitches if switches.empty?
switch = nil
env[:machine].config.vm.networks.each do |type, opts|
next if type != :public_network && type != :private_network
switchToFind = opts[:bridge]
if switchToFind
@logger.debug("Looking for switch with name: #{switchToFind}")
switch = switches.find { |s| s["Name"].downcase == switchToFind.downcase }["Id"]
@logger.debug("Found switch: #{switch}")
end
end
if switch.nil?
if switches.length > 1
env[:ui].detail(I18n.t("vagrant_hyperv.choose_switch") + "\n ")
switches.each_index do |i|
switch = switches[i]
env[:ui].detail("#{i+1}) #{switch["Name"]}")
end
env[:ui].detail(" ")
switch = nil
while !switch
switch = env[:ui].ask("What switch would you like to use? ")
next if !switch
switch = switch.to_i - 1
switch = nil if switch < 0 || switch >= switches.length
end
switch = switches[switch]["Id"]
else
switch = switches[0]["Id"]
end
end
env[:ui].detail("Cloning virtual hard drive...")
source_path = image_path.to_s
dest_path = env[:machine].data_dir.join("Virtual Hard Disks").join("#{image_filename}#{image_ext}").to_s
# Still hard copy the disk of old XML configurations
if config_type == 'xml'
if differencing_disk
env[:machine].provider.driver.execute("clone_vhd.ps1", {Source: source_path, Destination: dest_path})
else
FileUtils.mkdir_p(env[:machine].data_dir.join("Virtual Hard Disks"))
FileUtils.cp(source_path, dest_path)
end
end
image_path = dest_path
# We have to normalize the paths to be Windows paths since
# we're executing PowerShell.
options = {
vm_config_file: config_path.to_s.gsub("/", "\\"),
vm_config_type: config_type,
source_path: source_path.to_s,
dest_path: dest_path,
data_path: env[:machine].data_dir.to_s.gsub("/", "\\")
"VMConfigFile" => config_path.to_s.gsub("/", "\\"),
"DestinationPath" => dest_path.to_s.gsub("/", "\\"),
"DataPath" => env[:machine].data_dir.to_s.gsub("/", "\\"),
"LinkedClone" => !!env[:machine].provider_config.linked_clone,
"SourcePath" => image_path.to_s.gsub("/", "\\"),
"VMName" => env[:machine].provider_config.vmname,
}
options[:switchid] = switch if switch
options[:memory] = memory if memory
options[:maxmemory] = maxmemory if maxmemory
options[:cpus] = cpus if cpus
options[:vmname] = vmname if vmname
options[:auto_start_action] = auto_start_action if auto_start_action
options[:auto_stop_action] = auto_stop_action if auto_stop_action
options[:differencing_disk] = differencing_disk if differencing_disk
options[:enable_virtualization_extensions] = "True" if enable_virtualization_extensions and enable_virtualization_extensions == true
env[:ui].detail("Creating and registering the VM...")
server = env[:machine].provider.driver.import(options)
env[:ui].detail("Setting VM Integration Services")
vm_integration_services.each do |key, value|
state = false
if value === true
state = "enabled"
elsif value === false
state = "disabled"
end
env[:ui].output("#{key} is #{state}") if state
end
vm_integration_services[:VmId] = server["id"]
env[:machine].provider.driver.set_vm_integration_services(vm_integration_services)
env[:ui].detail("Successfully imported a VM with name: #{server['name']}")
env[:ui].detail("Successfully imported VM")
env[:machine].id = server["id"]
@app.call(env)
end

View File

@ -0,0 +1,43 @@
require "log4r"
module VagrantPlugins
module HyperV
module Action
class SetName
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::hyperv::set_name")
end
def call(env)
name = env[:machine].provider_config.vmname
# If we already set the name before, then don't do anything
sentinel = env[:machine].data_dir.join("action_set_name")
if !name && sentinel.file?
@logger.info("Default name was already set before, not doing it again.")
return @app.call(env)
end
# If no name was manually set, then use a default
if !name
prefix = "#{env[:root_path].basename.to_s}_#{env[:machine].name}"
prefix.gsub!(/[^-a-z0-9_]/i, "")
# milliseconds + random number suffix to allow for simultaneous
# `vagrant up` of the same box in different dirs
name = prefix + "_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
end
env[:machine].provider.driver.set_name(name)
# Create the sentinel
sentinel.open("w") do |f|
f.write(Time.now.to_i.to_s)
end
@app.call(env)
end
end
end
end
end

View File

@ -3,18 +3,49 @@ require "vagrant"
module VagrantPlugins
module HyperV
class Config < Vagrant.plugin("2", :config)
attr_accessor :ip_address_timeout # Time to wait for an IP address when booting, in seconds @return [Integer]
attr_accessor :memory # Memory size in mb @return [Integer]
attr_accessor :maxmemory # Maximal memory size in mb enables dynamical memory allocation @return [Integer]
attr_accessor :cpus # Number of cpu's @return [Integer]
attr_accessor :vmname # Name that will be shoen in Hyperv Manager @return [String]
attr_accessor :vlan_id # VLAN ID for network interface for the virtual machine. @return [Integer]
attr_accessor :mac # MAC address for network interface for the virtual machine. @return [String]
attr_accessor :differencing_disk # Create differencing disk instead of cloning whole VHD [Boolean]
attr_accessor :auto_start_action #action on automatic start of VM. Values: Nothing, StartIfRunning, Start
attr_accessor :auto_stop_action #action on automatic stop of VM. Values: ShutDown, TurnOff, Save
attr_accessor :enable_virtualization_extensions # Enable virtualization extensions (nested virtualization). Values: true, false
attr_accessor :vm_integration_services # Options for VMServiceIntegration [Hash]
# Allowed automatic start actions for VM
ALLOWED_AUTO_START_ACTIONS = [
"Nothing".freeze,
"StartIfRunning".freeze,
"Start".freeze
].freeze
# Allowed automatic stop actions for VM
ALLOWED_AUTO_STOP_ACTIONS = [
"ShutDown".freeze,
"TurnOff".freeze,
"Save".freeze
].freeze
# @return [Integer] Seconds to wait for an IP address when booting
attr_accessor :ip_address_timeout
# @return [Integer] Memory size in MB
attr_accessor :memory
# @return [Integer] Maximum memory size in MB. Enables dynamic memory.
attr_accessor :maxmemory
# @return [Integer] Number of CPUs
attr_accessor :cpus
# @return [String] Name of the VM (Shown in the Hyper-V Manager)
attr_accessor :vmname
# @return [Integer] VLAN ID for network interface
attr_accessor :vlan_id
# @return [String] MAC address for network interface
attr_accessor :mac
# @return [Boolean] Create linked clone instead of full clone
# @note **DEPRECATED** use #linked_clone instead
attr_accessor :differencing_disk
# @return [Boolean] Create linked clone instead of full clone
attr_accessor :linked_clone
# @return [String] Automatic action on start of host. Default: Nothing (Nothing, StartIfRunning, Start)
attr_accessor :auto_start_action
# @return [String] Automatic action on stop of host. Default: ShutDown (ShutDown, TurnOff, Save)
attr_accessor :auto_stop_action
# @return [Boolean] Enable automatic checkpoints. Default: false
attr_accessor :enable_checkpoints
# @return [Boolean] Enable virtualization extensions
attr_accessor :enable_virtualization_extensions
# @return [Hash] Options for VMServiceIntegration
attr_accessor :vm_integration_services
def initialize
@ip_address_timeout = UNSET_VALUE
@ -24,10 +55,12 @@ module VagrantPlugins
@vmname = UNSET_VALUE
@vlan_id = UNSET_VALUE
@mac = UNSET_VALUE
@linked_clone = UNSET_VALUE
@differencing_disk = UNSET_VALUE
@auto_start_action = UNSET_VALUE
@auto_stop_action = UNSET_VALUE
@enable_virtualization_extensions = UNSET_VALUE
@enable_checkpoints = UNSET_VALUE
@vm_integration_services = {
guest_service_interface: UNSET_VALUE,
heartbeat: UNSET_VALUE,
@ -39,6 +72,10 @@ module VagrantPlugins
end
def finalize!
@linked_clone = false if @linked_clone == UNSET_VALUE
@differencing_disk = false if @differencing_disk == UNSET_VALUE
@linked_clone ||= @differencing_disk
@differencing_disk ||= @linked_clone
if @ip_address_timeout == UNSET_VALUE
@ip_address_timeout = 120
end
@ -48,20 +85,32 @@ module VagrantPlugins
@vmname = nil if @vmname == UNSET_VALUE
@vlan_id = nil if @vlan_id == UNSET_VALUE
@mac = nil if @mac == UNSET_VALUE
@differencing_disk = false if @differencing_disk == UNSET_VALUE
@auto_start_action = nil if @auto_start_action == UNSET_VALUE
@auto_stop_action = nil if @auto_stop_action == UNSET_VALUE
@enable_virtualization_extensions = false if @enable_virtualization_extensions == UNSET_VALUE # TODO will this work?
@vm_integration_services.each { |key, value|
@vm_integration_services[key] = nil if value == UNSET_VALUE
}
@vm_integration_services = nil if @vm_integration_services.length == 0
@auto_start_action = "Nothing" if @auto_start_action == UNSET_VALUE
@auto_stop_action = "ShutDown" if @auto_stop_action == UNSET_VALUE
@enable_virtualization_extensions = false if @enable_virtualization_extensions == UNSET_VALUE
if @enable_checkpoints == UNSET_VALUE
@enable_checkpoints = false
else
@enable_checkpoints = !!@enable_checkpoints
end
@vm_integration_services.delete_if{|_, v| v == UNSET_VALUE }
@vm_integration_services = nil if @vm_integration_services.empty?
end
def validate(machine)
errors = _detected_errors
if !ALLOWED_AUTO_START_ACTIONS.include?(auto_start_action)
errors << I18n.t("vagrant.hyperv.config.invalid_auto_start_action", action: auto_start_action,
allowed_actions: ALLOWED_AUTO_START_ACTIONS.join(", "))
end
if !ALLOWED_AUTO_STOP_ACTIONS.include?(auto_stop_action)
errors << I18n.t("vagrant.hyperv.config.invalid_auto_stop_action", action: auto_stop_action,
allowed_actions: ALLOWED_AUTO_STOP_ACTIONS.join(", "))
end
{"Hyper-V" => errors}
end
end

View File

@ -10,19 +10,41 @@ module VagrantPlugins
ERROR_REGEXP = /===Begin-Error===(.+?)===End-Error===/m
OUTPUT_REGEXP = /===Begin-Output===(.+?)===End-Output===/m
# Name mapping for integration services for nicer keys
INTEGRATION_SERVICES_MAP = {
guest_service_interface: "Guest Service Interface",
heartbeat: "Heartbeat",
key_value_pair_exchange: "Key-Value Pair Exchange",
shutdown: "Shutdown",
time_synchronization: "Time Synchronization",
vss: "VSS",
}
# @return [String] VM ID
attr_reader :vm_id
def initialize(id)
@vm_id = id
end
def execute(path, options)
r = execute_powershell(path, options)
if r.exit_code != 0
raise Errors::PowerShellError,
script: path,
stderr: r.stderr
# @return [Boolean] Supports VMCX
def has_vmcx_support?
!!execute(:has_vmcx_support)["result"]
end
# Execute a PowerShell command and process the results
#
# @param [String] path Path to PowerShell script
# @param [Hash] options Options to pass to command
#
# @return [Object, nil] If the command returned JSON content
# it will be parsed and returned, otherwise
# nil will be returned
def execute(path, options={})
if path.is_a?(Symbol)
path = "#{path}.ps1"
end
r = execute_powershell(path, options)
# We only want unix-style line endings within Vagrant
r.stdout.gsub!("\r\n", "\n")
@ -40,104 +62,185 @@ module VagrantPlugins
stderr: data["error"]
end
if r.exit_code != 0
raise Errors::PowerShellError,
script: path,
stderr: r.stderr
end
# Nothing
return nil if !output_match
return JSON.parse(output_match[1])
end
# Fetch current state of the VM
#
# @return [Hash<state, status>]
def get_current_state
execute('get_vm_status.ps1', { VmId: vm_id })
execute(:get_vm_status, { VmId: vm_id })
end
def delete_vm
execute('delete_vm.ps1', { VmId: vm_id })
end
# Delete the VM
#
# @return [nil]
def delete_vm
execute(:delete_vm, { VmId: vm_id })
end
# Export the VM to the given path
#
# @param [String] path Path for export
# @return [nil]
def export(path)
execute('export_vm.ps1', {VmId: vm_id, Path: path})
execute(:export_vm, {VmId: vm_id, Path: path})
end
def read_guest_ip
execute('get_network_config.ps1', { VmId: vm_id })
end
# Get the IP address of the VM
#
# @return [Hash<ip>]
def read_guest_ip
execute(:get_network_config, { VmId: vm_id })
end
# Get the MAC address of the VM
#
# @return [Hash<mac>]
def read_mac_address
execute('get_network_mac.ps1', { VmId: vm_id })
execute(:get_network_mac, { VmId: vm_id })
end
def resume
execute('resume_vm.ps1', { VmId: vm_id })
end
# Resume the VM from suspension
#
# @return [nil]
def resume
execute(:resume_vm, { VmId: vm_id })
end
def start
execute('start_vm.ps1', { VmId: vm_id })
end
# Start the VM
#
# @return [nil]
def start
execute(:start_vm, { VmId: vm_id })
end
def stop
execute('stop_vm.ps1', { VmId: vm_id })
end
# Stop the VM
#
# @return [nil]
def stop
execute(:stop_vm, { VmId: vm_id })
end
def suspend
execute("suspend_vm.ps1", { VmId: vm_id })
end
# Suspend the VM
#
# @return [nil]
def suspend
execute(:suspend_vm, { VmId: vm_id })
end
def import(options)
config_type = options.delete(:vm_config_type)
if config_type === "vmcx"
execute('import_vm_vmcx.ps1', options)
else
options.delete(:data_path)
options.delete(:source_path)
options.delete(:differencing_disk)
execute('import_vm_xml.ps1', options)
end
end
# Import a new VM
#
# @param [Hash] options Configuration options
# @return [Hash<id>] New VM ID
def import(options)
execute(:import_vm, options)
end
def net_set_vlan(vlan_id)
execute("set_network_vlan.ps1", { VmId: vm_id, VlanId: vlan_id })
end
# Set the VLAN ID
#
# @param [String] vlan_id VLAN ID
# @return [nil]
def net_set_vlan(vlan_id)
execute(:set_network_vlan, { VmId: vm_id, VlanId: vlan_id })
end
def net_set_mac(mac_addr)
execute("set_network_mac.ps1", { VmId: vm_id, Mac: mac_addr })
end
# Set the VM adapter MAC address
#
# @param [String] mac_addr MAC address
# @return [nil]
def net_set_mac(mac_addr)
execute(:set_network_mac, { VmId: vm_id, Mac: mac_addr })
end
def create_snapshot(snapshot_name)
execute("create_snapshot.ps1", { VmId: vm_id, SnapName: (snapshot_name) } )
end
# Create a new snapshot with the given name
#
# @param [String] snapshot_name Name of the new snapshot
# @return [nil]
def create_snapshot(snapshot_name)
execute(:create_snapshot, { VmId: vm_id, SnapName: (snapshot_name) } )
end
def restore_snapshot(snapshot_name)
execute("restore_snapshot.ps1", { VmId: vm_id, SnapName: (snapshot_name) } )
end
# Restore the given snapshot
#
# @param [String] snapshot_name Name of snapshot to restore
# @return [nil]
def restore_snapshot(snapshot_name)
execute(:restore_snapshot, { VmId: vm_id, SnapName: (snapshot_name) } )
end
def list_snapshots()
snaps = execute("list_snapshots.ps1", { VmID: vm_id } )
snaps.map { |s| s['Name'] }
end
# Get list of current snapshots
#
# @return [Array<String>] snapshot names
def list_snapshots
snaps = execute(:list_snapshots, { VmID: vm_id } )
snaps.map { |s| s['Name'] }
end
def delete_snapshot(snapshot_name)
execute("delete_snapshot.ps1", {VmID: vm_id, SnapName: snapshot_name})
end
# Delete snapshot with the given name
#
# @param [String] snapshot_name Name of snapshot to delete
# @return [nil]
def delete_snapshot(snapshot_name)
execute(:delete_snapshot, {VmID: vm_id, SnapName: snapshot_name})
end
# Enable or disable VM integration services
#
# @param [Hash] config Integration services to enable or disable
# @return [nil]
# @note Keys in the config hash will be remapped if found in the
# INTEGRATION_SERVICES_MAP. If they are not, the name will
# be passed directly. This allows new integration services
# to configurable even if Vagrant is not aware of them.
def set_vm_integration_services(config)
execute("set_vm_integration_services.ps1", config)
config.each_pair do |srv_name, srv_enable|
args = {VMID: vm_id, Name: INTEGRATION_SERVICES_MAP.fetch(srv_name.to_sym, srv_name)}
args[:Name] = true if srv_enable
execute(:set_vm_integration_services, args)
end
end
# Set the name of the VM
#
# @param [String] vmname Name of the VM
# @return [nil]
def set_name(vmname)
execute(:set_name, VMID: vm_id, VMName: vmname)
end
protected
def execute_powershell(path, options, &block)
lib_path = Pathname.new(File.expand_path("../scripts", __FILE__))
mod_path = lib_path.join("utils").to_s.gsub("/", "\\")
path = lib_path.join(path).to_s.gsub("/", "\\")
options = options || {}
ps_options = []
options.each do |key, value|
next if value == false
ps_options << "-#{key}"
# If the value is a TrueClass assume switch
next if value == true
ps_options << "'#{value}'"
end
# Always have a stop error action for failures
ps_options << "-ErrorAction" << "Stop"
opts = { notify: [:stdout, :stderr, :stdin] }
# Include our module path so we can nicely load helper modules
opts = {
notify: [:stdout, :stderr, :stdin],
env: {"PSModulePath" => "$env:PSModulePath+';#{mod_path}'"}
}
Vagrant::Util::PowerShell.execute(path, *ps_options, **opts, &block)
end
end

View File

@ -1,8 +1,6 @@
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
#Requires -Modules VagrantMessages
$check = $(-Not (-Not (Get-Command "Hyper-V\Get-VMSwitch" -errorAction SilentlyContinue)))
$check = $(-Not (-Not (Get-Command "Hyper-V\Get-VMSwitch" -ErrorAction SilentlyContinue)))
$result = @{
result = $check
}

View File

@ -1,4 +1,6 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$Source,
@ -6,4 +8,11 @@ Param(
[string]$Destination
)
Hyper-V\New-VHD -Path $Destination -ParentPath $Source -ErrorAction Stop
$ErrorActionPreference = "Stop"
try {
Hyper-V\New-VHD -Path $Destination -ParentPath $Source
} catch {
Write-Error-Message "Failed to clone drive: ${PSItem}"
exit 1
}

View File

@ -0,0 +1,95 @@
#Requires -Modules VagrantVM, VagrantMessages
param(
[parameter (Mandatory=$true)]
[Guid] $VMID,
[parameter (Mandatory=$false)]
[string] $SwitchID=$null,
[parameter (Mandatory=$false)]
[string] $Memory=$null,
[parameter (Mandatory=$false)]
[string] $MaxMemory=$null,
[parameter (Mandatory=$false)]
[string] $Processors=$null,
[parameter (Mandatory=$false)]
[string] $AutoStartAction=$null,
[parameter (Mandatory=$false)]
[string] $AutoStopAction=$null,
[parameter (Mandatory=$false)]
[switch] $VirtualizationExtensions,
[parameter (Mandatory=$false)]
[switch] $EnableCheckpoints
)
$ErrorActionPreference = "Stop"
try {
$VM = Hyper-V\Get-VM -Id $VMID
} catch {
Write-Error-Message "Failed to locate VM: ${PSItem}"
exit 1
}
if($Processors) {
try {
Set-VagrantVMCPUS -VM $VM -CPUCount ($Processors -as [int])
} catch {
Write-Error-Message "Failed to configure CPUs: ${PSItem}"
exit 1
}
}
if($Memory -or $MaxMemory) {
try {
Set-VagrantVMMemory -VM $VM -Memory $Memory -MaxMemory $MaxMemory
} catch {
Write-Error-Message "Failed to configure memory: ${PSItem}"
exit 1
}
}
if($AutoStartAction -or $AutoStopAction) {
try {
Set-VagrantVMAutoActions -VM $VM -AutoStartAction $AutoStartAction -AutoStopAction $AutoStopAction
} catch {
Write-Error-Message "Failed to configure automatic actions: ${PSItem}"
exit 1
}
}
if($VirtualizationExtensions) {
$virtex = $true
} else {
$virtex = $false
}
try {
Set-VagrantVMVirtExtensions -VM $VM -Enabled $virtex
} catch {
Write-Error-Message "Failed to configure virtualization extensions: ${PSItem}"
exit 1
}
if($SwitchID) {
try {
$SwitchName = Get-VagrantVMSwitch -NameOrID $SwitchID
Set-VagrantVMSwitch -VM $VM -SwitchName $SwitchName
} catch {
Write-Error-Message "Failed to configure network adapter: ${PSItem}"
}
}
if($EnableCheckpoints) {
$checkpoints = "Standard"
$CheckpointAction = "enable"
} else {
$checkpoints = "Disabled"
$CheckpointAction = "disable"
}
try {
Hyper-V\Set-VM -VM $VM -CheckpointType $checkpoints
} catch {
Write-Error-Message "Failed to ${CheckpointAction} checkpoints on VM: ${PSItem}"
exit 1
}

View File

@ -1,8 +1,17 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId,
[string]$SnapName
)
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
Hyper-V\Checkpoint-VM $VM -SnapshotName $SnapName
$ErrorActionPreference = "Stop"
try {
$VM = Hyper-V\Get-VM -Id $VmId
Hyper-V\Checkpoint-VM $VM -SnapshotName $SnapName
} catch {
Write-Error-Message "Failed to create snapshot: ${PSItem}"
exit 1
}

View File

@ -1,8 +1,16 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId,
[string]$SnapName
)
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
Hyper-V\Remove-VMSnapshot $VM -Name $SnapName
$ErrorActionPreference = "Stop"
try {
$VM = Hyper-V\Get-VM -Id $VmId
Hyper-V\Remove-VMSnapshot $VM -Name $SnapName
} catch {
Write-Error-Message "Failed to delete snapshot: ${PSItem}"
}

View File

@ -1,7 +1,16 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
Hyper-V\Remove-VM $VM -Force
$ErrorActionPreference = "Stop"
try {
$VM = Hyper-V\Get-VM -Id $VmId
Hyper-V\Remove-VM $VM -Force
} catch {
Write-Error-Message "Failed to delete VM: ${PSItem}"
exit 1
}

View File

@ -1,15 +1,29 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId,
[Parameter(Mandatory=$true)]
[string]$Path
)
$vm = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
$vm | Hyper-V\Export-VM -Path $Path
$ErrorActionPreference = "Stop"
try {
$vm = Hyper-V\Get-VM -Id $VmId
$vm | Hyper-V\Export-VM -Path $Path
} catch {
Write-Error-Message "Failed to export VM: ${PSItem}"
exit 1
}
# Prepare directory structure for box import
$name = $vm.Name
Move-Item $Path/$name/* $Path
Remove-Item -Path $Path/Snapshots -Force -Recurse
Remove-Item -Path $Path/$name -Force
try {
$name = $vm.Name
Move-Item $Path/$name/* $Path
Remove-Item -Path $Path/Snapshots -Force -Recurse
Remove-Item -Path $Path/$name -Force
} catch {
Write-Error-Message "Failed to format exported box: ${PSItem}"
exit 1
}

View File

@ -1,22 +1,23 @@
#Requires -Modules VagrantMessages
#-------------------------------------------------------------------------
# Copyright (c) Microsoft Open Technologies, Inc.
# All Rights Reserved. Licensed under the MIT License.
#--------------------------------------------------------------------------
param (
[string]$vm_id = $(throw "-vm_id is required."),
[string]$guest_ip = $(throw "-guest_ip is required."),
[string]$username = $(throw "-guest_username is required."),
[string]$password = $(throw "-guest_password is required."),
[string]$host_path = $(throw "-host_path is required."),
[string]$guest_path = $(throw "-guest_path is required.")
)
# Include the following modules
$presentDir = Split-Path -parent $PSCommandPath
$modules = @()
$modules += $presentDir + "\utils\write_messages.ps1"
forEach ($module in $modules) { . $module }
[parameter (Mandatory=$true)]
[string]$vm_id,
[parameter (Mandatory=$true)]
[string]$guest_ip,
[parameter (Mandatory=$true)]
[string]$username,
[parameter (Mandatory=$true)]
[string]$password,
[parameter (Mandatory=$true)]
[string]$host_path,
[parameter (Mandatory=$true)]
[string]$guest_path
)
function Get-file-hash($source_path, $delimiter) {
$source_files = @()
@ -120,4 +121,3 @@ $resultHash = @{
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result

View File

@ -1,56 +1,68 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
$ErrorActionPreference = "Stop"
$vm = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
$networks = Hyper-V\Get-VMNetworkAdapter -VM $vm
foreach ($network in $networks) {
if ($network.IpAddresses.Length -gt 0) {
foreach ($ip_address in $network.IpAddresses) {
if ($ip_address.Contains(".") -And [string]::IsNullOrEmpty($ip4_address)) {
$ip4_address = $ip_address
} elseif ($ip_address.Contains(":") -And [string]::IsNullOrEmpty($ip6_address)) {
$ip6_address = $ip_address
try {
$vm = Hyper-V\Get-VM -Id $VmId
} catch {
Write-Error-Message "Failed to locate VM: ${PSItem}"
exit 1
}
try {
$networks = Hyper-V\Get-VMNetworkAdapter -VM $vm
foreach ($network in $networks) {
if ($network.IpAddresses.Length -gt 0) {
foreach ($ip_address in $network.IpAddresses) {
if ($ip_address.Contains(".") -And [string]::IsNullOrEmpty($ip4_address)) {
$ip4_address = $ip_address
} elseif ($ip_address.Contains(":") -And [string]::IsNullOrEmpty($ip6_address)) {
$ip6_address = $ip_address
}
}
}
}
}
# If no address was found in the network settings, check for
# neighbor with mac address and see if an IP exists
if (([string]::IsNullOrEmpty($ip4_address)) -And ([string]::IsNullOrEmpty($ip6_address))) {
$macaddresses = $vm | select -ExpandProperty NetworkAdapters | select MacAddress
foreach ($macaddr in $macaddresses) {
$macaddress = $macaddr.MacAddress -replace '(.{2})(?!$)', '${1}-'
$addr = Get-NetNeighbor -LinkLayerAddress $macaddress -ErrorAction SilentlyContinue | select IPAddress
if ($ip_address) {
$ip_address = $addr.IPAddress
if ($ip_address.Contains(".")) {
$ip4_address = $ip_address
} elseif ($ip_address.Contains(":")) {
$ip6_address = $ip_address
# If no address was found in the network settings, check for
# neighbor with mac address and see if an IP exists
if (([string]::IsNullOrEmpty($ip4_address)) -And ([string]::IsNullOrEmpty($ip6_address))) {
$macaddresses = $vm | select -ExpandProperty NetworkAdapters | select MacAddress
foreach ($macaddr in $macaddresses) {
$macaddress = $macaddr.MacAddress -replace '(.{2})(?!$)', '${1}-'
$addr = Get-NetNeighbor -LinkLayerAddress $macaddress -ErrorAction SilentlyContinue | select IPAddress
if ($ip_address) {
$ip_address = $addr.IPAddress
if ($ip_address.Contains(".")) {
$ip4_address = $ip_address
} elseif ($ip_address.Contains(":")) {
$ip6_address = $ip_address
}
}
}
}
}
if (-Not ([string]::IsNullOrEmpty($ip4_address))) {
$guest_ipaddress = $ip4_address
} elseif (-Not ([string]::IsNullOrEmpty($ip6_address))) {
$guest_ipaddress = $ip6_address
}
if (-Not ([string]::IsNullOrEmpty($guest_ipaddress))) {
$resultHash = @{
ip = $guest_ipaddress
if (-Not ([string]::IsNullOrEmpty($ip4_address))) {
$guest_ipaddress = $ip4_address
} elseif (-Not ([string]::IsNullOrEmpty($ip6_address))) {
$guest_ipaddress = $ip6_address
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result
} else {
Write-Error-Message "Failed to determine IP address"
if (-Not ([string]::IsNullOrEmpty($guest_ipaddress))) {
$resultHash = @{
ip = $guest_ipaddress
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result
} else {
Write-Error-Message "Failed to determine IP address"
exit 1
}
} catch {
Write-Error-Message "Unexpected error while detecting network configuration: ${PSItem}"
exit 1
}

View File

@ -1,28 +1,32 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
)
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
$ErrorActionPreference = "Stop"
$ip_address = ""
$vm = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
$networks = Hyper-V\Get-VMNetworkAdapter -VM $vm
foreach ($network in $networks) {
if ($network.MacAddress -gt 0) {
$mac_address = $network.MacAddress
if (-Not ([string]::IsNullOrEmpty($mac_address))) {
# We found our mac address!
break
try {
$ip_address = ""
$vm = Hyper-V\Get-VM -Id $VmId
$networks = Hyper-V\Get-VMNetworkAdapter -VM $vm
foreach ($network in $networks) {
if ($network.MacAddress -gt 0) {
$mac_address = $network.MacAddress
if (-Not ([string]::IsNullOrEmpty($mac_address))) {
# We found our mac address!
break
}
}
}
}
}
$resultHash = @{
mac = "$mac_address"
$resultHash = @{
mac = "$mac_address"
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result
} catch {
Write-Error-Message "Unexpected error while fetching MAC: ${PSItem}"
exit 1
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result

View File

@ -1,11 +1,9 @@
#Requires -Modules VagrantMessages
# This will have a SwitchType property. As far as I know the values are:
#
# 0 - Private
# 1 - Internal
#
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
$Switches = @(Hyper-V\Get-VMSwitch `
| Select-Object Name,SwitchType,NetAdapterInterfaceDescription,Id)

View File

@ -1,12 +1,10 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
# Make sure the exception type is loaded
try
{
@ -37,7 +35,7 @@ try {
$State = "not_created"
$Status = $State
}
else
else
{
throw;
}

View File

@ -1,6 +1,4 @@
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
#Requires -Modules VagrantMessages
# Windows version 10 and up have support for binary format
$check = [System.Environment]::OSVersion.Version.Major -ge 10

View File

@ -0,0 +1,37 @@
#Requires -Modules VagrantVM, VagrantMessages
param(
[parameter (Mandatory=$true)]
[string] $VMConfigFile,
[parameter (Mandatory=$true)]
[string] $DestinationPath,
[parameter (Mandatory=$true)]
[string] $DataPath,
[parameter (Mandatory=$true)]
[string] $SourcePath,
[parameter (Mandatory=$false)]
[switch] $LinkedClone,
[parameter (Mandatory=$false)]
[string] $VMName=$null
)
$ErrorActionPreference = "Stop"
try {
if($LinkedClone) {
$linked = $true
} else {
$linked = $false
}
$VM = New-VagrantVM -VMConfigFile $VMConfigFile -DestinationPath $DestinationPath `
-DataPath $DataPath -SourcePath $SourcePath -LinkedClone $linked -VMName $VMName
$Result = @{
id = $VM.Id.Guid;
}
Write-Output-Message (ConvertTo-Json $Result)
} catch {
Write-Error-Message "${PSItem}"
exit 1
}

View File

@ -1,165 +0,0 @@
Param(
[Parameter(Mandatory=$true)]
[string]$vm_config_file,
[Parameter(Mandatory=$true)]
[string]$source_path,
[Parameter(Mandatory=$true)]
[string]$dest_path,
[Parameter(Mandatory=$true)]
[string]$data_path,
[string]$switchid=$null,
[string]$memory=$null,
[string]$maxmemory=$null,
[string]$cpus=$null,
[string]$vmname=$null,
[string]$auto_start_action=$null,
[string]$auto_stop_action=$null,
[string]$differencing_disk=$null,
[string]$enable_virtualization_extensions=$False
)
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
$VmProperties = @{
Path = $vm_config_file
SnapshotFilePath = Join-Path $data_path 'Snapshots'
VhdDestinationPath = Join-Path $data_path 'Virtual Hard Disks'
VirtualMachinePath = $data_path
}
$vmConfig = (Hyper-V\Compare-VM -Copy -GenerateNewID @VmProperties)
$generation = $vmConfig.VM.Generation
if (!$vmname) {
# Get the name of the vm
$vm_name = $vmconfig.VM.VMName
} else {
$vm_name = $vmname
}
if (!$cpus) {
# Get the processorcount of the VM
$processors = (Hyper-V\Get-VMProcessor -VM $vmConfig.VM).Count
}else {
$processors = $cpus
}
function GetUniqueName($name) {
Hyper-V\Get-VM | ForEach-Object -Process {
if ($name -eq $_.Name) {
$name = $name + "_1"
}
}
return $name
}
do {
$name = $vm_name
$vm_name = GetUniqueName $name
} while ($vm_name -ne $name)
if (!$memory) {
$configMemory = Hyper-V\Get-VMMemory -VM $vmConfig.VM
$dynamicmemory = $configMemory.DynamicMemoryEnabled
$MemoryMaximumBytes = ($configMemory.Maximum)
$MemoryStartupBytes = ($configMemory.Startup)
$MemoryMinimumBytes = ($configMemory.Minimum)
} else {
if (!$maxmemory){
$dynamicmemory = $False
$MemoryMaximumBytes = ($memory -as [int]) * 1MB
$MemoryStartupBytes = ($memory -as [int]) * 1MB
$MemoryMinimumBytes = ($memory -as [int]) * 1MB
} else {
$dynamicmemory = $True
$MemoryMaximumBytes = ($maxmemory -as [int]) * 1MB
$MemoryStartupBytes = ($memory -as [int]) * 1MB
$MemoryMinimumBytes = ($memory -as [int]) * 1MB
}
}
if (!$switchid) {
$switchname = (Hyper-V\Get-VMNetworkAdapter -VM $vmConfig.VM).SwitchName
} else {
$switchname = $(Hyper-V\Get-VMSwitch -Id $switchid).Name
}
# Enable nested virtualization if configured
if ($enable_virtualization_extensions -eq "True") {
Hyper-V\Set-VMProcessor -VM $vmConfig.VM -ExposeVirtualizationExtensions $true
}
$vmNetworkAdapter = Hyper-V\Get-VMNetworkAdapter -VM $vmConfig.VM
Hyper-V\Connect-VMNetworkAdapter -VMNetworkAdapter $vmNetworkAdapter -SwitchName $switchname
Hyper-V\Set-VM -VM $vmConfig.VM -NewVMName $vm_name
Hyper-V\Set-VM -VM $vmConfig.VM -ErrorAction "Stop"
Hyper-V\Set-VM -VM $vmConfig.VM -ProcessorCount $processors
if ($dynamicmemory) {
Hyper-V\Set-VM -VM $vmConfig.VM -DynamicMemory
Hyper-V\Set-VM -VM $vmConfig.VM -MemoryMinimumBytes $MemoryMinimumBytes -MemoryMaximumBytes $MemoryMaximumBytes -MemoryStartupBytes $MemoryStartupBytes
} else {
Hyper-V\Set-VM -VM $vmConfig.VM -StaticMemory
Hyper-V\Set-VM -VM $vmConfig.VM -MemoryStartupBytes $MemoryStartupBytes
}
if ($notes) {
Hyper-V\Set-VM -VM $vmConfig.VM -Notes $notes
}
if ($auto_start_action) {
Hyper-V\Set-VM -VM $vmConfig.VM -AutomaticStartAction $auto_start_action
}
if ($auto_stop_action) {
Hyper-V\Set-VM -VM $vmConfig.VM -AutomaticStopAction $auto_stop_action
}
# Only set EFI secure boot for Gen 2 machines, not gen 1
if ($generation -ne 1) {
Hyper-V\Set-VMFirmware -VM $vmConfig.VM -EnableSecureBoot (Hyper-V\Get-VMFirmware -VM $vmConfig.VM).SecureBoot
}
$report = Hyper-V\Compare-VM -CompatibilityReport $vmConfig
# Stop if there are incompatibilities
if($report.Incompatibilities.Length -gt 0){
Write-Error-Message $(ConvertTo-Json $($report.Incompatibilities | Select -ExpandProperty Message))
exit 0
}
if($differencing_disk){
# Get all controller on the VM, first scsi, then IDE if it is a Gen 1 device
$controllers = Hyper-V\Get-VMScsiController -VM $vmConfig.VM
if($generation -eq 1){
$controllers = @($controllers) + @(Hyper-V\Get-VMIdeController -VM $vmConfig.VM)
}
foreach($controller in $controllers){
foreach($drive in $controller.Drives){
if([System.IO.Path]::GetFileName($drive.Path) -eq [System.IO.Path]::GetFileName($source_path)){
# Remove the old disk and replace it with a differencing version
$path = $drive.Path
Hyper-V\Remove-VMHardDiskDrive $drive
Hyper-V\New-VHD -Path $dest_path -ParentPath $source_path -ErrorAction Stop
Hyper-V\Add-VMHardDiskDrive -VM $vmConfig.VM -Path $dest_path
}
}
}
}
Hyper-V\Import-VM -CompatibilityReport $vmConfig
$vm_id = (Hyper-V\Get-VM $vm_name).id.guid
$resultHash = @{
name = $vm_name
id = $vm_id
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result

View File

@ -1,221 +0,0 @@
Param(
[Parameter(Mandatory=$true)]
[string]$vm_config_file,
[Parameter(Mandatory=$true)]
[string]$dest_path,
[string]$switchname=$null,
[string]$memory=$null,
[string]$maxmemory=$null,
[string]$cpus=$null,
[string]$vmname=$null,
[string]$auto_start_action=$null,
[string]$auto_stop_action=$null,
[string]$enable_virtualization_extensions=$False
)
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
[xml]$vmconfig = Get-Content -Path $vm_config_file
$generation = [int]($vmconfig.configuration.properties.subtype.'#text')+1
if (!$vmname) {
# Get the name of the vm
$vm_name = $vmconfig.configuration.properties.name.'#text'
}else {
$vm_name = $vmname
}
if (!$cpus) {
# Get the name of the vm
$processors = $vmconfig.configuration.settings.processors.count.'#text'
}else {
$processors = $cpus
}
function GetUniqueName($name) {
Hyper-V\Get-VM | ForEach-Object -Process {
if ($name -eq $_.Name) {
$name = $name + "_1"
}
}
return $name
}
do {
$name = $vm_name
$vm_name = GetUniqueName $name
} while ($vm_name -ne $name)
if (!$memory) {
$xmlmemory = (Select-Xml -xml $vmconfig -XPath "//memory").node.Bank
if ($xmlmemory.dynamic_memory_enabled."#text" -eq "True") {
$dynamicmemory = $True
}
else {
$dynamicmemory = $False
}
# Memory values need to be in bytes
$MemoryMaximumBytes = ($xmlmemory.limit."#text" -as [int]) * 1MB
$MemoryStartupBytes = ($xmlmemory.size."#text" -as [int]) * 1MB
$MemoryMinimumBytes = ($xmlmemory.reservation."#text" -as [int]) * 1MB
}
else {
if (!$maxmemory){
$dynamicmemory = $False
$MemoryMaximumBytes = ($memory -as [int]) * 1MB
$MemoryStartupBytes = ($memory -as [int]) * 1MB
$MemoryMinimumBytes = ($memory -as [int]) * 1MB
}
else {
$dynamicmemory = $True
$MemoryMaximumBytes = ($maxmemory -as [int]) * 1MB
$MemoryStartupBytes = ($memory -as [int]) * 1MB
$MemoryMinimumBytes = ($memory -as [int]) * 1MB
}
}
if (!$switchname) {
# Get the name of the virtual switch
$switchname = (Select-Xml -xml $vmconfig -XPath "//AltSwitchName").node."#text"
}
if ($generation -eq 1) {
# Determine boot device
Switch ((Select-Xml -xml $vmconfig -XPath "//boot").node.device0."#text") {
"Floppy" { $bootdevice = "Floppy" }
"HardDrive" { $bootdevice = "IDE" }
"Optical" { $bootdevice = "CD" }
"Network" { $bootdevice = "LegacyNetworkAdapter" }
"Default" { $bootdevice = "IDE" }
} #switch
} else {
# Determine boot device
Switch ((Select-Xml -xml $vmconfig -XPath "//boot").node.device0."#text") {
"HardDrive" { $bootdevice = "VHD" }
"Optical" { $bootdevice = "CD" }
"Network" { $bootdevice = "NetworkAdapter" }
"Default" { $bootdevice = "VHD" }
} #switch
}
# Determine secure boot options
$secure_boot_enabled = (Select-Xml -xml $vmconfig -XPath "//secure_boot_enabled").Node."#text"
# Define a hash map of parameter values for New-VM
$vm_params = @{
Name = $vm_name
NoVHD = $True
MemoryStartupBytes = $MemoryStartupBytes
SwitchName = $switchname
BootDevice = $bootdevice
ErrorAction = "Stop"
}
# Generation parameter was added in ps v4
if((get-command Hyper-V\New-VM).Parameters.Keys.Contains("generation")) {
$vm_params.Generation = $generation
}
# Create the VM using the values in the hash map
$vm = Hyper-V\New-VM @vm_params
$notes = (Select-Xml -xml $vmconfig -XPath "//notes").node.'#text'
# Set-VM parameters to configure new VM with old values
$more_vm_params = @{
ProcessorCount = $processors
MemoryStartupBytes = $MemoryStartupBytes
}
If ($dynamicmemory) {
$more_vm_params.Add("DynamicMemory",$True)
$more_vm_params.Add("MemoryMinimumBytes",$MemoryMinimumBytes)
$more_vm_params.Add("MemoryMaximumBytes", $MemoryMaximumBytes)
} else {
$more_vm_params.Add("StaticMemory",$True)
}
if ($notes) {
$more_vm_params.Add("Notes",$notes)
}
if ($auto_start_action) {
$more_vm_params.Add("AutomaticStartAction",$auto_start_action)
}
if ($auto_stop_action) {
$more_vm_params.Add("AutomaticStopAction",$auto_stop_action)
}
# Set the values on the VM
$vm | Hyper-V\Set-VM @more_vm_params -Passthru
# Add drives to the virtual machine
$controllers = Select-Xml -xml $vmconfig -xpath "//*[starts-with(name(.),'controller')]"
# Only set EFI secure boot for Gen 2 machines, not gen 1
if ($generation -ne 1) {
# Set EFI secure boot
if ($secure_boot_enabled -eq "True") {
Hyper-V\Set-VMFirmware -VM $vm -EnableSecureBoot On
} else {
Hyper-V\Set-VMFirmware -VM $vm -EnableSecureBoot Off
}
}
# Enable nested virtualization if configured
if ($enable_virtualization_extensions -eq "True") {
Hyper-V\Set-VMProcessor -VM $vm -ExposeVirtualizationExtensions $true
}
# A regular expression pattern to pull the number from controllers
[regex]$rx="\d"
foreach ($controller in $controllers) {
$node = $controller.Node
# Check for SCSI
if ($node.ParentNode.ChannelInstanceGuid) {
$ControllerType = "SCSI"
} else {
$ControllerType = "IDE"
}
$drives = $node.ChildNodes | where {$_.pathname."#text"}
foreach ($drive in $drives) {
#if drive type is ISO then set DVD Drive accordingly
$driveType = $drive.type."#text"
$addDriveParam = @{
ControllerNumber = $rx.Match($controller.node.name).value
Path = $dest_path
}
if ($drive.pool_id."#text") {
$ResourcePoolName = $drive.pool_id."#text"
$addDriveParam.Add("ResourcePoolname",$ResourcePoolName)
}
if ($drivetype -eq 'VHD') {
$addDriveParam.add("ControllerType",$ControllerType)
$vm | Hyper-V\Add-VMHardDiskDrive @AddDriveparam
}
}
}
$vm_id = (Hyper-V\Get-VM $vm_name).id.guid
$resultHash = @{
name = $vm_name
id = $vm_id
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result

View File

@ -1,12 +1,19 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
$Snapshots = @(Hyper-V\Get-VMSnapshot $VM | Select-Object Name)
$result = ConvertTo-json $Snapshots
$ErrorActionPreference = "Stop"
Write-Host "===Begin-Output==="
Write-Host $result
Write-Host "===End-Output==="
try {
$VM = Hyper-V\Get-VM -Id $VmId
$Snapshots = @(Hyper-V\Get-VMSnapshot $VM | Select-Object Name)
} catch {
Write-Error-Message "Failed to get snapshot list: ${PSItem}"
exit 1
}
$result = ConvertTo-json $Snapshots
Write-Output-Message $result

View File

@ -1,8 +1,17 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId,
[string]$SnapName
)
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
Hyper-V\Restore-VMSnapshot $VM -Name $SnapName -Confirm:$false
$ErrorActionPreference = "Stop"
try {
$VM = Hyper-V\Get-VM -Id $VmId
Hyper-V\Restore-VMSnapshot $VM -Name $SnapName -Confirm:$false
} catch {
Write-Error-Message "Failed to restore snapshot: ${PSItem}"
exit 1
}

View File

@ -1,7 +1,16 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
Hyper-V\Resume-VM $VM
$ErrorActionPreference = "Stop"
try {
$VM = Hyper-V\Get-VM -Id $VmId
Hyper-V\Resume-VM $VM
} catch {
Write-Error-Message "Failed to resume VM: ${PSItem}"
exit 1
}

View File

@ -0,0 +1,24 @@
#Requires -Modules VagrantMessages
param (
[parameter (Mandatory=$true)]
[Guid] $VMID,
[parameter (Mandatory=$true)]
[string] $VMName
)
$ErrorActionPreference = "Stop"
try {
$VM = Hyper-V\Get-VM -Id $VMID
} catch {
Write-Error-Message "Failed to locate VM: ${PSItem}"
exit 1
}
try {
Hyper-V\Set-VM -VM $VM -NewVMName $VMName
} catch {
Write-Error-Message "Failed to assign new VM name ${VMName}: ${PSItem}"
exit 1
}

View File

@ -1,18 +1,18 @@
param (
[string]$VmId = $(throw "-VmId is required."),
[string]$Mac = $(throw "-Mac ")
)
#Requires -Modules VagrantMessages
# Include the following modules
$presentDir = Split-Path -parent $PSCommandPath
$modules = @()
$modules += $presentDir + "\utils\write_messages.ps1"
forEach ($module in $modules) { . $module }
param (
[parameter (Mandatory=$true)]
[string]$VmId,
[parameter (Mandatory=$true)]
[string]$Mac
)
$ErrorActionPreference = "Stop"
try {
$vm = Hyper-V\Get-VM -Id $VmId -ErrorAction "stop"
Hyper-V\Set-VMNetworkAdapter $vm -StaticMacAddress $Mac -ErrorAction "stop"
}
catch {
Write-Error-Message "Failed to set VM's MAC address $_"
$vm = Hyper-V\Get-VM -Id $VmId
Hyper-V\Set-VMNetworkAdapter $vm -StaticMacAddress $Mac
} catch {
Write-Error-Message "Failed to set VM MAC address: ${PSItem}"
exit 1
}

View File

@ -1,7 +1,11 @@
#Requires -Modules VagrantMessages
param (
[string]$VmId = $(throw "-VmId is required."),
[int]$VlanId = $(throw "-VlanId ")
)
[parameter (Mandatory=$true)]
[string]$VmId,
[parameter (Mandatory=$true)]
[int]$VlanId
)
# Include the following modules
$presentDir = Split-Path -parent $PSCommandPath

View File

@ -1,37 +1,27 @@
#Requires -Modules VagrantVM, VagrantMessages
param (
[string] $VmId,
[string] $guest_service_interface = $null,
[string] $heartbeat = $null,
[string] $key_value_pair_exchange = $null,
[string] $shutdown = $null,
[string] $time_synchronization = $null,
[string] $vss = $null
[parameter (Mandatory=$true)]
[string] $VMID,
[parameter (Mandatory=$true)]
[string] $Name,
[parameter (Mandatory=$false)]
[switch] $Enable
)
# Include the following modules
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
$ErrorActionPreference = "Stop"
$vm = Hyper-V\Get-VM -Id $VmId -ErrorAction "stop"
# Set the service based on value
function VmSetService
{
param ([string] $Name, [string] $Value, [Microsoft.HyperV.PowerShell.VirtualMachine] $Vm)
if ($Value -ne $null){
if($Value -eq "true"){
Hyper-V\Enable-VMIntegrationService -VM $Vm -Name $Name
}
if($Value -eq "false"){
Hyper-V\Disable-VMIntegrationService -VM $Vm -Name $Name
}
}
try {
$VM = Hyper-V\Get-VM -Id $VMID
} catch {
Write-Error-Message "Failed to locate VM: ${PSItem}"
exit 1
}
VmSetService -Name "Guest Service Interface" -Value $guest_service_interface -Vm $vm
VmSetService -Name "Heartbeat" -Value $heartbeat -Vm $vm
VmSetService -Name "Key-Value Pair Exchange" -Value $key_value_pair_exchange -Vm $vm
VmSetService -Name "Shutdown" -Value $shutdown -Vm $vm
VmSetService -Name "Time Synchronization" -Value $time_synchronization -Vm $vm
VmSetService -Name "VSS" -Value $vss -Vm $vm
try {
Set-VagrantVMService -VM $VM -Name $Name -Enable $enabled
} catch {
if($enabled){ $action = "enable" } else { $action = "disable" }
Write-Error-Message "Failed to ${action} VM integration service ${Name}: ${PSItem}"
exit 1
}

View File

@ -1,27 +1,26 @@
param (
[string]$VmId = $(throw "-VmId is required.")
)
#Requires -Modules VagrantMessages
# Include the following modules
$presentDir = Split-Path -parent $PSCommandPath
$modules = @()
$modules += $presentDir + "\utils\write_messages.ps1"
forEach ($module in $modules) { . $module }
param (
[parameter (Mandatory=$true)]
[string]$VmId
)
$ErrorActionPreference = "Stop"
try {
$vm = Hyper-V\Get-VM -Id $VmId -ErrorAction "stop"
Hyper-V\Start-VM $vm -ErrorAction "stop"
$state = $vm.state
$status = $vm.status
$name = $vm.name
$resultHash = @{
state = "$state"
status = "$status"
name = "$name"
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result
$vm = Hyper-V\Get-VM -Id $VmId
Hyper-V\Start-VM $vm
$state = $vm.state
$status = $vm.status
$name = $vm.name
$resultHash = @{
state = "$state"
status = "$status"
name = "$name"
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result
} catch {
Write-Error-Message "Failed to start VM ${PSItem}"
exit 1
}
catch {
Write-Error-Message "Failed to start a VM $_"
}

View File

@ -1,8 +1,17 @@
#Requires -Modules VagrantMessages
Param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
# Shuts down virtual machine regardless of any unsaved application data
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
Hyper-V\Stop-VM $VM -Force
$ErrorActionPreference = "Stop"
try{
# Shuts down virtual machine regardless of any unsaved application data
$VM = Hyper-V\Get-VM -Id $VmId
Hyper-V\Stop-VM $VM -Force
} catch {
Write-Error-Message "Failed to stop VM: ${PSItem}"
exit 1
}

View File

@ -1,7 +1,16 @@
Param(
#Requires -Modules VagrantMessages
param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
$VM = Hyper-V\Get-VM -Id $VmId -ErrorAction "Stop"
Hyper-V\Suspend-VM $VM
$ErrorActionPreference = "Stop"
try{
$VM = Hyper-V\Get-VM -Id $VmId
Hyper-V\Suspend-VM $VM
} catch {
Write-Error-Message "Failed to suspend VM: ${PSItem}"
exit 1
}

View File

@ -0,0 +1,27 @@
#-------------------------------------------------------------------------
# Copyright (c) Microsoft Open Technologies, Inc.
# All Rights Reserved. Licensed under the MIT License.
#--------------------------------------------------------------------------
function Write-Error-Message {
param (
[parameter (Mandatory=$true,Position=0)]
[string] $Message
)
$error_message = @{
error = $Message
}
Write-Host "===Begin-Error==="
Write-Host (ConvertTo-Json $error_message)
Write-Host "===End-Error==="
}
function Write-Output-Message {
param (
[parameter (Mandatory=$true,Position=0)]
[string] $Message
)
Write-Host "===Begin-Output==="
Write-Host $Message
Write-Host "===End-Output==="
}

View File

@ -0,0 +1,616 @@
# Vagrant VM creation functions
function New-VagrantVM {
param (
[parameter(Mandatory=$true)]
[string] $VMConfigFile,
[parameter(Mandatory=$true)]
[string] $DestinationPath,
[parameter (Mandatory=$true)]
[string] $DataPath,
[parameter (Mandatory=$true)]
[string] $SourcePath,
[parameter (Mandatory=$false)]
[bool] $LinkedClone = $false,
[parameter(Mandatory=$false)]
[string] $VMName
)
if([IO.Path]::GetExtension($VMConfigFile).ToLower() -eq ".xml") {
return New-VagrantVMXML @PSBoundParameters
} else {
return New-VagrantVMVMCX @PSBoundParameters
}
<#
.SYNOPSIS
Create a new Vagrant Hyper-V VM by cloning original. This
is the general use function with will call the specialized
function based on the extension of the configuration file.
.DESCRIPTION
Using an existing Hyper-V VM a new Hyper-V VM is created
by cloning the original.
.PARAMETER VMConfigFile
Path to the original Hyper-V VM configuration file.
.PARAMETER DestinationPath
Path to new Hyper-V VM hard drive.
.PARAMETER DataPath
Directory path of the original Hyper-V VM to be cloned.
.PARAMETER SourcePath
Path to the original Hyper-V VM hard drive.
.PARAMETER LinkedClone
New Hyper-V VM should be linked clone instead of complete copy.
.PARAMETER VMName
Name of the new Hyper-V VM.
.INPUTS
None.
.OUTPUTS
VirtualMachine. The cloned Hyper-V VM.
#>
}
function New-VagrantVMVMCX {
param (
[parameter(Mandatory=$true)]
[string] $VMConfigFile,
[parameter(Mandatory=$true)]
[string] $DestinationPath,
[parameter (Mandatory=$true)]
[string] $DataPath,
[parameter (Mandatory=$true)]
[string] $SourcePath,
[parameter (Mandatory=$false)]
[bool] $LinkedClone = $false,
[parameter(Mandatory=$false)]
[string] $VMName
)
$NewVMConfig = @{
Path = $VMConfigFile;
SnapshotFilePath = Join-Path $DataPath "Snapshots";
VhdDestinationPath = Join-Path $DataPath "Virtual Hard Disks";
VirtualMachinePath = $DataPath;
}
$VMConfig = (Hyper-V\Compare-VM -Copy -GenerateNewID @NewVMConfig)
$VM = $VMConfig.VM
$Gen = $VM.Generation
# Set VM name if name has been provided
if($VMName) {
Hyper-V\Set-VM -VM $VM -NewVMName $VMName
}
# Set EFI secure boot on machines after Gen 1
if($Gen -gt 1) {
Hyper-V\Set-VMFirmware -VM $VM -EnableSecureBoot (Hyper-V\Get-VMFirmware -VM $VM).SecureBoot
}
# Verify new VM
$Report = Hyper-V\Compare-VM -CompatibilityReport $VMConfig
if($Report.Incompatibilities.Length -gt 0){
throw $(ConvertTo-Json $($Report.Incompatibilities | Select -ExpandProperty Message))
}
if($LinkedClone) {
$Controllers = Hyper-V\Get-VMScsiController -VM $VM
if($Gen -eq 1){
$Controllers = @($Controllers) + @(Hyper-V\Get-VMIdeController -VM $VM)
}
foreach($Controller in $Controllers) {
foreach($Drive in $Controller.Drives) {
if([System.IO.Path]::GetFileName($Drive.Path) -eq [System.IO.Path]::GetFileName($SourcePath)) {
$Path = $Drive.Path
Hyper-V\Remove-VMHardDiskDrive $Drive
Hyper-V\New-VHD -Path $DestinationPath -ParentPath $SourcePath
Hyper-V\AddVMHardDiskDrive -VM $VM -Path $DestinationPath
break
}
}
}
}
return Hyper-V\Import-VM -CompatibilityReport $VMConfig
<#
.SYNOPSIS
Create a new Vagrant Hyper-V VM by cloning original (VMCX based).
.DESCRIPTION
Using an existing Hyper-V VM a new Hyper-V VM is created
by cloning the original.
.PARAMETER VMConfigFile
Path to the original Hyper-V VM configuration file.
.PARAMETER DestinationPath
Path to new Hyper-V VM hard drive.
.PARAMETER DataPath
Directory path of the original Hyper-V VM to be cloned.
.PARAMETER SourcePath
Path to the original Hyper-V VM hard drive.
.PARAMETER LinkedClone
New Hyper-V VM should be linked clone instead of complete copy.
.PARAMETER VMName
Name of the new Hyper-V VM.
.INPUTS
None.
.OUTPUTS
VirtualMachine. The cloned Hyper-V VM.
#>
}
function New-VagrantVMXML {
param (
[parameter(Mandatory=$true)]
[string] $VMConfigFile,
[parameter(Mandatory=$true)]
[string] $DestinationPath,
[parameter (Mandatory=$true)]
[string] $DataPath,
[parameter (Mandatory=$true)]
[string] $SourcePath,
[parameter (Mandatory=$false)]
[bool] $LinkedClone = $false,
[parameter(Mandatory=$false)]
[string] $VMName
)
$DestinationDirectory = [System.IO.Path]::GetDirectoryName($DestinationPath)
New-Item -ItemType Directory -Force -Path $DestinationDirectory
if($LinkedClone){
Hyper-V\New-VHD -Path $DestinationPath -ParentPath $SourcePath -ErrorAction Stop
} else {
Copy-Item $SourcePath -Destination $DestinationPath -ErrorAction Stop
}
[xml]$VMConfig = Get-Content -Path $VMConfigFile
$Gen = [int]($VMConfig.configuration.properties.subtype."#text") + 1
if(!$VMName) {
$VMName = $VMConfig.configuration.properties.name."#text"
}
# Determine boot device
if($Gen -eq 1) {
Switch ((Select-Xml -xml $VMConfig -XPath "//boot").node.device0."#text") {
"Floppy" { $BootDevice = "Floppy" }
"HardDrive" { $BootDevice = "IDE" }
"Optical" { $BootDevice = "CD" }
"Network" { $BootDevice = "LegacyNetworkAdapter" }
"Default" { $BootDevice = "IDE" }
}
} else {
Switch ((Select-Xml -xml $VMConfig -XPath "//boot").node.device0."#text") {
"HardDrive" { $BootDevice = "VHD" }
"Optical" { $BootDevice = "CD" }
"Network" { $BootDevice = "NetworkAdapter" }
"Default" { $BootDevice = "VHD" }
}
}
# Determine if secure boot is enabled
$SecureBoot = (Select-Xml -XML $VMConfig -XPath "//secure_boot_enabled").Node."#text"
$NewVMConfig = @{
Name = $VMName;
NoVHD = $true;
BootDevice = $BootDevice;
}
# Generation parameter in PS4 so validate before using
if((Get-Command Hyper-V\New-VM).Parameters.Keys.Contains("generation")) {
$NewVMConfig.Generation = $Gen
}
# Create new VM instance
$VM = Hyper-V\New-VM @NewVMConfig
# Configure secure boot
if($Gen -gt 1) {
if($SecureBoot -eq "True") {
Hyper-V\Set-VMFirmware -VM $VM -EnableSecureBoot On
} else {
Hyper-V\Set-VMFirmware -VM $VM -EnableSecureBoot Off
}
}
# Configure drives
[regex]$DriveNumberMatcher = "\d"
$Controllers = Select-Xml -XML $VMConfig -XPath "//*[starts-with(name(.),'controller')]"
foreach($Controller in $Controllers) {
$Node = $Controller.Node
if($Node.ParentNode.ChannelInstanceGuid) {
$ControllerType = "SCSI"
} else {
$ControllerType = "IDE"
}
$Drives = $Node.ChildNodes | where {$_.pathname."#text"}
foreach($Drive in $Drives) {
$DriveType = $Drive.type."#text"
if($DriveType -ne "VHD") {
continue
}
$NewDriveConfig = @{
ControllerNumber = $DriveNumberMatcher.Match($Controller.node.name).value;
Path = $DestinationPath;
ControllerType = $ControllerType;
}
if($Drive.pool_id."#text") {
$NewDriveConfig.ResourcePoolname = $Drive.pool_id."#text"
}
$VM | Hyper-V\Add-VMHardDiskDrive @NewDriveConfig
}
}
# Apply original VM configuration to new VM instance
$processors = $VMConfig.configuration.settings.processors.count."#text"
$notes = (Select-Xml -XML $VMConfig -XPath "//notes").node."#text"
$memory = (Select-Xml -XML $VMConfig -XPath "//memory").node.Bank
if ($memory.dynamic_memory_enabled."#text" -eq "True") {
$dynamicmemory = $True
}
else {
$dynamicmemory = $False
}
# Memory values need to be in bytes
$MemoryMaximumBytes = ($memory.limit."#text" -as [int]) * 1MB
$MemoryStartupBytes = ($memory.size."#text" -as [int]) * 1MB
$MemoryMinimumBytes = ($memory.reservation."#text" -as [int]) * 1MB
$Config = @{
ProcessorCount = $processors;
MemoryStartupBytes = $MemoryStartupBytes
}
if($dynamicmemory) {
$Config.DynamicMemory = $true
$Config.MemoryMinimumBytes = $MemoryMinimumBytes
$Config.MemoryMaximumBytes = $MemoryMaximumBytes
} else {
$Config.StaticMemory = $true
}
if($notes) {
$Config.Notes = $notes
}
Hyper-V\Set-VM -VM $VM @Config
return $VM
<#
.SYNOPSIS
Create a new Vagrant Hyper-V VM by cloning original (XML based).
.DESCRIPTION
Using an existing Hyper-V VM a new Hyper-V VM is created
by cloning the original.
.PARAMETER VMConfigFile
Path to the original Hyper-V VM configuration file.
.PARAMETER DestinationPath
Path to new Hyper-V VM hard drive.
.PARAMETER DataPath
Directory path of the original Hyper-V VM to be cloned.
.PARAMETER SourcePath
Path to the original Hyper-V VM hard drive.
.PARAMETER LinkedClone
New Hyper-V VM should be linked clone instead of complete copy.
.PARAMETER VMName
Name of the new Hyper-V VM.
.INPUTS
None.
.OUTPUTS
VirtualMachine. The cloned Hyper-V VM.
#>
}
# Vagrant VM configuration functions
function Set-VagrantVMMemory {
param (
[parameter (Mandatory=$true)]
[Microsoft.HyperV.PowerShell.VirtualMachine] $VM,
[parameter (Mandatory=$false)]
[int] $Memory,
[parameter (Mandatory=$false)]
[int] $MaxMemory
)
$ConfigMemory = Hyper-V\Get-VMMemory -VM $VM
if(!$Memory) {
$MemoryStartupBytes = ($ConfigMemory.Startup)
$MemoryMinimumBytes = ($ConfigMemory.Minimum)
$MemoryMaximumBytes = ($ConfigMemory.Maximum)
} else {
$MemoryStartupBytes = $Memory * 1MB
$MemoryMinimumBytes = $Memory * 1MB
$MemoryMaximumBytes = $Memory * 1MB
}
if($MaxMemory) {
$DynamicMemory = $true
$MemoryMaximumBytes = $MaxMemory * 1MB
}
if($DynamicMemory) {
Hyper-V\Set-VM -VM $VM -DynamicMemory
Hyper-V\Set-VM -VM $VM -MemoryMinimumBytes $MemoryMinimumBytes -MemoryMaximumBytes `
$MemoryMaximumBytes -MemoryStartupBytes $MemoryStartupBytes
} else {
Hyper-V\Set-VM -VM $VM -StaticMemory
Hyper-V\Set-VM -VM $VM -MemoryStartupBytes $MemoryStartupBytes
}
return $VM
<#
.SYNOPSIS
Configure VM memory settings.
.DESCRIPTION
Adjusts the VM memory settings. If MaxMemory is defined, dynamic memory
is enabled on the VM.
.PARAMETER VM
Hyper-V VM for modification.
.Parameter Memory
Memory to allocate to the given VM in MB.
.Parameter MaxMemory
Maximum memory to allocate to the given VM in MB. When this value is
provided dynamic memory is enabled for the VM. The Memory value or
the currently configured memory of the VM will be used as the minimum
and startup memory value.
.Output
VirtualMachine.
#>
}
function Set-VagrantVMCPUS {
param (
[parameter (Mandatory=$true)]
[Microsoft.HyperV.PowerShell.VirtualMachine] $VM,
[parameter (Mandatory=$false)]
[int] $CPUCount
)
if($CPUCount) {
Hyper-V\Set-VM -VM $VM -ProcessorCount $CPUCount
}
return $VM
<#
.SYNOPSIS
Configure VM CPU count.
.DESCRIPTION
Configure the number of CPUs on the given VM.
.PARAMETER VM
Hyper-V VM for modification.
.PARAMETER CPUCount
Number of CPUs.
.Output
VirtualMachine.
#>
}
function Set-VagrantVMVirtExtensions {
param (
[parameter (Mandatory=$true)]
[Microsoft.HyperV.PowerShell.VirtualMachine] $VM,
[parameter (Mandatory=$false)]
[bool] $Enabled=$false
)
Hyper-V\Set-VMProcessor -VM $VM -ExposeVirtualizationExtensions $Enabled
return $VM
<#
.SYNOPSIS
Enable virtualization extensions on VM.
.PARAMETER VM
Hyper-V VM for modification.
.PARAMETER Enabled
Enable virtualization extensions on given VM.
.OUTPUT
VirtualMachine.
#>
}
function Set-VagrantVMAutoActions {
param (
[parameter (Mandatory=$true)]
[Microsoft.HyperV.PowerShell.VirtualMachine] $VM,
[parameter (Mandatory=$false)]
[string] $AutoStartAction="Nothing",
[parameter (Mandatory=$false)]
[string] $AutoStopAction="ShutDown"
)
Hyper-V\Set-VM -VM $VM -AutomaticStartAction $AutoStartAction
Hyper-V\Set-VM -VM $VM -AutomaticStopAction $AutoStopAction
return $VM
<#
.SYNOPSIS
Configure automatic start and stop actions for VM
.DESCRIPTION
Configures the automatic start and automatic stop actions for
the given VM.
.PARAMETER VM
Hyper-V VM for modification.
.PARAMETER AutoStartAction
Action the VM should automatically take when the host is started.
.PARAMETER AutoStopAction
Action the VM should automatically take when the host is stopped.
.OUTPUT
VirtualMachine.
#>
}
function Set-VagrantVMService {
param (
[parameter (Mandatory=$true)]
[Microsoft.HyperV.PowerShell.VirtualMachine] $VM,
[parameter (Mandatory=$true)]
[string] $Name,
[parameter (Mandatory=$true)]
[bool] $Enable
)
if($Enable) {
Hyper-V\Enable-VMIntegrationService -VM $VM -Name $Name
} else {
Hyper-V\Disable-VMIntegrationService -VM $VM -Name $Name
}
return $VM
<#
.SYNOPSIS
Enable or disable Hyper-V VM integration services.
.PARAMETER VM
Hyper-V VM for modification.
.PARAMETER Name
Name of the integration service.
.PARAMETER Enable
Enable or disable the service.
.OUTPUT
VirtualMachine.
#>
}
# Vagrant networking functions
function Get-VagrantVMSwitch {
param (
[parameter (Mandatory=$true)]
[string] $NameOrID
)
$SwitchName = $(Hyper-V\Get-VMSwitch -Id $NameOrID).Name
if(!$SwitchName) {
$SwitchName = $(Hyper-V\Get-VMSwitch -Name $NameOrID).Name
}
if(!$SwitchName) {
throw "Failed to locate switch with name or ID: ${NameOrID}"
}
return $SwitchName
<#
.SYNOPSIS
Get name of VMSwitch.
.DESCRIPTION
Find VMSwitch by name or ID and return name.
.PARAMETER NameOrID
Name or ID of VMSwitch.
.OUTPUT
Name of VMSwitch.
#>
}
function Set-VagrantVMSwitch {
param (
[parameter (Mandatory=$true)]
[Microsoft.HyperV.PowerShell.VirtualMachine] $VM,
[parameter (Mandatory=$true)]
[String] $SwitchName
)
$Adapter = Hyper-V\Get-VMNetworkAdapter -VM $VM
Hyper-V\Connect-VMNetworkAdapter -VMNetworkAdapter $Adapter -SwitchName $SwitchName
return $VM
<#
.SYNOPSIS
Configure VM to use given switch.
.DESCRIPTION
Configures VM adapter to use the the VMSwitch with the given name.
.PARAMETER VM
Hyper-V VM for modification.
.PARAMETER SwitchName
Name of the VMSwitch.
.OUTPUT
VirtualMachine.
#>
}

View File

@ -1,20 +0,0 @@
#-------------------------------------------------------------------------
# Copyright (c) Microsoft Open Technologies, Inc.
# All Rights Reserved. Licensed under the MIT License.
#--------------------------------------------------------------------------
function Write-Error-Message($message) {
$error_message = @{
error = "$message"
}
Write-Host "===Begin-Error==="
$result = ConvertTo-json $error_message
Write-Host $result
Write-Host "===End-Error==="
}
function Write-Output-Message($message) {
Write-Host "===Begin-Output==="
Write-Host $message
Write-Host "===End-Output==="
}