-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathInvoke-PackerBuildVbVm.psm1
238 lines (178 loc) · 7.03 KB
/
Invoke-PackerBuildVbVm.psm1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<#
.SYNOPSIS
Invokes packer build using a packer JSON file with a virtualbox-iso builder to create a local VirtualBox virtual machine.
.DESCRIPTION
Invokes packer build using a packer JSON file with a virtualbox-iso builder to create a local VirtualBox virtual machine.
Requires that Packer and VirtualBox are both installed and in your System PATH.
Recommended Packer JSON file settings:
* Set the communicator to none since SSH often times out.
* Configure a second NIC because using SSH to a host-only adapter is more reliable than depending on port forwarding, especially if you're in a corporate enviroment. You'll need to configure a static IP of the 192.168.56.x format.
To easily create a Packer VirtualBox file which sets the communicator to none and configures a host-only NIC, use New-PackerVbFile.
.PARAMETER PackerFile
Packer JSON file.
.PARAMETER Overwrite
Use Overwrite switch if you want to remove the VirtualBox machine if it already exists.
.PARAMETER StartLog
Switch. Use this if you want an independent log when this script runs.
.PARAMETER LogFile
Path to log file. If not specified, defaults to "logs\$ModuleName-$LogDate.log".
.EXAMPLE
Invoke-PackerBuildVbVm -File "packer-local-ubuntu.json" -Overwrite
.EXAMPLE
Invoke-PackerBuildVbVm -File "packer-local-ubuntu.json" -Overwrite -StartLog
.EXAMPLE
Invoke-PackerBuildVbVm -File "packer-local-ubuntu.json" -Overwrite -StartLog -LogFile "mylog.log"
.INPUTS
None. You cannot pipe objects to Invoke-PackerBuildVbVm
.OUTPUTS
VirtualBox virtual machine.
.NOTES
Due to bugs I encountered with the -force flag, this has an option to remove the VirtualBox machine manually.
For more information on Packer VirtualBox-ISO builder see:
https://www.packer.io/docs/builders/virtualbox/iso
.LINK
New-PackerVbFile
.LINK
https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7
.LINK
https://www.virtualbox.org/
.LINK
https://www.packer.io/
.LINK
https://www.packer.io/docs/builders/virtualbox/iso
.LINK
https://github.com/simplenotsimpler/New-Autoinstall
.LINK
https://github.com/simplenotsimpler/New-PackerVbFile
.LINK
https://github.com/simplenotsimpler/Invoke-PackerBuildVbVm
.LINK
https://github.com/simplenotsimpler/Deploy-VbVm
#>
function Invoke-PackerBuildVbVm {
[CmdletBinding()]
param (
[Alias('File')]
[System.IO.FileInfo]$PackerFile,
[switch]$Overwrite,
[Switch]$StartLog,
[String]$LogFile
)
begin{
$ErrorActionPreference = 'Stop'
$VerbosePreference = "Continue"
$ModuleName=$MyInvocation.MyCommand
$PSDefaultParameterValues = @{"*:Verbose"=$True}
$LogDate=(Get-Date -Format 'yyyy-MM-dd-HHmm')
if(!$LogFile){
$LogFile="logs\$ModuleName-$LogDate.log"
}
$Separator="================================"
if($StartLog){
Start-Transcript $LogFile -Append
}
Write-Verbose $Separator
Write-Verbose " Begin $ModuleName Log"
Write-Verbose $Separator
#Validate $PackerFile
try{
if( -Not ($PackerFile | Test-Path -PathType Leaf) ){
throw "$PackerFile does not exist"
}
if (-Not ((Get-Content -Path $PackerFile -Raw) | Test-Json -ErrorAction Ignore )){
throw "$PackerFile is not valid JSON"
}
}
catch{
Write-Error "$ModuleName::$_"
}
Write-Verbose "Checking for Packer and VBoxManage"
try {
if( -Not([bool] (Get-Command -ErrorAction Ignore -Type Application packer)) ){
throw "Unable to find Packer executable. Please add it to your System Path."
}
if( -Not([bool] (Get-Command -ErrorAction Ignore -Type Application VBoxManage)) ){
throw "Unable to find VBoxManage executable. Please add it to your System Path."
}
}
catch {
Write-Error "$ModuleName::$_"
}
$env:PACKER_LOG=1
$env:PACKER_LOG_PATH="logs\packer-details-$LogDate.log"
}
process{
#region get initial values from PackerFile
#get hashtable from PackerFile so can use multiple values
$PackerFileHash = (Get-Content -Path $PackerFile -Raw | ConvertFrom-Json -AsHashtable)
#because this is nested, you have to use the builders array
$VbVmName= $PackerFileHash.builders.vm_name
$VbVmMachineFolder = $PackerFileHash.builders.output_directory
#endregion get initial values from File
#region check if machine exists
Write-Verbose "$ModuleName::Checking if machine exists: $VbVmName"
$VbVmList=(VBoxManage list vms)
if ($VbVmList | Select-String $VbVmName -Quiet) {
$VbVmExists=$true
}
else {
$VbVmExists=$false
}
#check to make sure machine folder does not exist either
#if there are errors, machine could be removed from VBox list but not from the machine location
if (Test-Path $VbVmMachineFolder){
$VbVmMachineFolderExists=$true
}
else {
$VbVmMachineFolderExists=$false
}
# endregion check if machine exists
if ($VbVmExists -or $VbVmMachineFolderExists) {
try {
if(!$Overwrite){
$ErrorMessage="{0} or {0} folder already exists. Use the Overwrite switch if you want to replace it." -f $VbVmName
throw $ErrorMessage
}
else {
#manually remove VirtualBox machine due to bug with packer build -force not working
#region check powered off
Write-Verbose "$ModuleName::Checking if $VbVmName powered off"
$VbVmnfo = VBoxManage showvminfo $VbVmName -machinereadable
$VbVmProperties = @{}
$VbVmnfo | ForEach-Object {$key, $value = $_.Split('=', 2); $VbVmProperties[$key.Trim()] = $value.Trim('" ')}
if($VbVmProperties.VMState -ne 'poweroff'){
Write-Error ('$ModuleName::{0} is not off. Please power machine off before proceeding.' -f $VbVmName) -ErrorAction Stop
}
#endregion check powered off
#region remove machine and clean up
Write-Verbose "$ModuleName::Removing $VbVmName"
Start-Process VBoxManage -ArgumentList "unregistervm $VbVmName --delete" -Wait
if ($VbVmMachineFolderExists) {
Remove-Item -recurse "$VbVmMachineFolder\*" -force
}
#endregion remove machine and clean up
}
}
catch {
Write-Error "$ModuleName::$_"
}
}
Write-Verbose "$ModuleName::Starting Packer Build"
#Remember that with packer the options go before the template file!!
packer build -only=virtualbox-iso -timestamp-ui $PackerFile| Out-Host
}
end{
Write-Verbose "$ModuleName::Cleaning up"
#region clean up and remove packer_cache folder
if (Test-Path packer_cache) {
Remove-Item -recurse "packer_cache" -force
}
#endregion clean up and remove packer_cache folder
Write-Verbose $Separator
Write-Verbose " End $ModuleName"
Write-Verbose $Separator
if($StartLog){
Stop-Transcript
}
}
}