FIrst draft of packaging of Hyper-V boxes. Need to refactor the package_* files since right now they are copies of the virtualbox versions, might just put them in general.

This commit is contained in:
Bjorn Brala 2016-10-05 13:48:48 +02:00
parent d96dc95076
commit be2e9e79aa
9 changed files with 261 additions and 0 deletions

View File

@ -64,6 +64,33 @@ module VagrantPlugins
end
end
# This action packages the virtual machine into a single box file.
def self.action_package
Vagrant::Action::Builder.new.tap do |b|
b.use CheckEnabled
b.use Call, IsState, :not_created do |env1, b2|
@logger = Log4r::Logger.new("vagrant::action::builtin::is_state")
@logger.debug("Whats the state?")
@logger.debug(env1[:result].to_s)
@logger.debug(env1.to_s)
if env1[:result]
b2.use Message, I18n.t("vagrant_hyperv.message_not_created")
next
end
b2.use PackageSetupFolders
b2.use PackageSetupFiles
b2.use action_halt
b2.use SyncedFolderCleanup
b2.use Package
b2.use Export
b2.use PackageVagrantfile
end
end
end
def self.action_provision
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
@ -261,9 +288,15 @@ module VagrantPlugins
# The autoload farm
action_root = Pathname.new(File.expand_path("../action", __FILE__))
autoload :PackageSetupFolders, action_root.join("package_setup_folders")
autoload :PackageSetupFiles, action_root.join("package_setup_files")
autoload :PackageVagrantfile, action_root.join("package_vagrantfile")
autoload :Export, action_root.join("export")
autoload :CheckEnabled, action_root.join("check_enabled")
autoload :DeleteVM, action_root.join("delete_vm")
autoload :Import, action_root.join("import")
autoload :Package, action_root.join("package")
autoload :IsWindows, action_root.join("is_windows")
autoload :ReadState, action_root.join("read_state")
autoload :ResumeVM, action_root.join("resume_vm")

View File

@ -0,0 +1,39 @@
require "fileutils"
module VagrantPlugins
module HyperV
module Action
class Export
def initialize(app, env)
@app = app
end
def call(env)
@env = env
@env[:ui].info @env[:machine].state.id.to_s
raise Vagrant::Errors::VMPowerOffToPackage if
@env[:machine].state.id != :off
export
@app.call(env)
end
def export
@env[:ui].info I18n.t("vagrant.actions.vm.export.exporting")
@env[:machine].provider.driver.export(@env["export.temp_dir"]) do |progress|
@env[:ui].clear_line
@env[:ui].report_progress(progress.percent, 100, false)
end
# Clear the line a final time so the next data can appear
# alone on the line.
@env[:ui].clear_line
end
end
end
end
end

View File

@ -0,0 +1,16 @@
require_relative "../../../../lib/vagrant/action/general/package"
module VagrantPlugins
module HyperV
module Action
class Package < Vagrant::Action::General::Package
# Doing this so that we can test that the parent is properly
# called in the unit tests.
alias_method :general_call, :call
def call(env)
general_call(env)
end
end
end
end
end

View File

@ -0,0 +1,51 @@
module VagrantPlugins
module HyperV
module Action
class PackageSetupFiles
def initialize(app, env)
@app = app
env["package.include"] ||= []
env["package.vagrantfile"] ||= nil
end
def call(env)
files = {}
env["package.include"].each do |file|
source = Pathname.new(file)
dest = nil
# If the source is relative then we add the file as-is to the include
# directory. Otherwise, we copy only the file into the root of the
# include directory. Kind of strange, but seems to match what people
# expect based on history.
if source.relative?
dest = source
else
dest = source.basename
end
# Assign the mapping
files[file] = dest
end
if env["package.vagrantfile"]
# Vagrantfiles are treated special and mapped to a specific file
files[env["package.vagrantfile"]] = "_Vagrantfile"
end
# Verify the mapping
files.each do |from, _|
raise Vagrant::Errors::PackageIncludeMissing,
file: from if !File.exist?(from)
end
# Save the mapping
env["package.files"] = files
@app.call(env)
end
end
end
end
end

View File

@ -0,0 +1,38 @@
require "fileutils"
require_relative "../../../../lib/vagrant/action/general/package"
module VagrantPlugins
module HyperV
module Action
class PackageSetupFolders
include Vagrant::Util::Presence
def initialize(app, env)
@app = app
end
def call(env)
env["package.output"] ||= "package.box"
env["package.directory"] ||= Dir.mktmpdir("vagrant-package-", env[:tmp_path])
# Match up a couple environmental variables so that the other parts of
# Vagrant will do the right thing.
env["export.temp_dir"] = env["package.directory"]
Vagrant::Action::General::Package.validate!(
env["package.output"], env["package.directory"])
@app.call(env)
end
def recover(env)
dir = env["package.directory"]
if File.exist?(dir)
FileUtils.rm_rf(dir)
end
end
end
end
end
end

View File

@ -0,0 +1,33 @@
require 'vagrant/util/template_renderer'
module VagrantPlugins
module HyperV
module Action
class PackageVagrantfile
# For TemplateRenderer
include Vagrant::Util
def initialize(app, env)
@app = app
end
def call(env)
@env = env
create_vagrantfile
@app.call(env)
end
# This method creates the auto-generated Vagrantfile at the root of the
# box. This Vagrantfile contains the MAC address so that the user doesn't
# have to worry about it.
def create_vagrantfile
File.open(File.join(@env["export.temp_dir"], "Vagrantfile"), "w") do |f|
f.write(TemplateRenderer.render("package_Vagrantfile", {
base_mac: @env[:machine].provider.driver.read_mac_address
}))
end
end
end
end
end
end

View File

@ -53,10 +53,18 @@ module VagrantPlugins
execute('delete_vm.ps1', { VmId: vm_id })
end
def export(path)
execute('export_vm.ps1', {VmId: vm_id, Path: path})
end
def read_guest_ip
execute('get_network_config.ps1', { VmId: vm_id })
end
def read_mac_address
execute('get_network_mac.ps1', { VmId: vm_id })
end
def resume
execute('resume_vm.ps1', { VmId: vm_id })
end

View File

@ -0,0 +1,15 @@
Param(
[Parameter(Mandatory=$true)]
[string]$VmId,
[Parameter(Mandatory=$true)]
[string]$Path
)
$vm = Get-VM -Id $VmId -ErrorAction "Stop"
$vm | Export-VM -Path $Path
# 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

View File

@ -0,0 +1,28 @@
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"))
$ip_address = ""
$vm = Get-VM -Id $VmId -ErrorAction "Stop"
$networks = 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"
}
$result = ConvertTo-Json $resultHash
Write-Output-Message $result