Created
July 2, 2018 23:57
-
-
Save DanHam/edea482abf362c271748599b96d4fd7c to your computer and use it in GitHub Desktop.
Coverage report for builder/vmware/vmx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
<style> | |
body { | |
background: black; | |
color: rgb(80, 80, 80); | |
} | |
body, pre, #legend span { | |
font-family: Menlo, monospace; | |
font-weight: bold; | |
} | |
#topbar { | |
background: black; | |
position: fixed; | |
top: 0; left: 0; right: 0; | |
height: 42px; | |
border-bottom: 1px solid rgb(80, 80, 80); | |
} | |
#content { | |
margin-top: 50px; | |
} | |
#nav, #legend { | |
float: left; | |
margin-left: 10px; | |
} | |
#legend { | |
margin-top: 12px; | |
} | |
#nav { | |
margin-top: 10px; | |
} | |
#legend span { | |
margin: 0 5px; | |
} | |
.cov0 { color: rgb(192, 0, 0) } | |
.cov1 { color: rgb(128, 128, 128) } | |
.cov2 { color: rgb(116, 140, 131) } | |
.cov3 { color: rgb(104, 152, 134) } | |
.cov4 { color: rgb(92, 164, 137) } | |
.cov5 { color: rgb(80, 176, 140) } | |
.cov6 { color: rgb(68, 188, 143) } | |
.cov7 { color: rgb(56, 200, 146) } | |
.cov8 { color: rgb(44, 212, 149) } | |
.cov9 { color: rgb(32, 224, 152) } | |
.cov10 { color: rgb(20, 236, 155) } | |
</style> | |
</head> | |
<body> | |
<div id="topbar"> | |
<div id="nav"> | |
<select id="files"> | |
<option value="file0">github.com/hashicorp/packer/builder/vmware/vmx/builder.go (16.7%)</option> | |
<option value="file1">github.com/hashicorp/packer/builder/vmware/vmx/config.go (89.7%)</option> | |
<option value="file2">github.com/hashicorp/packer/builder/vmware/vmx/step_clone_vmx.go (78.4%)</option> | |
</select> | |
</div> | |
<div id="legend"> | |
<span>not tracked</span> | |
<span class="cov0">not covered</span> | |
<span class="cov8">covered</span> | |
</div> | |
</div> | |
<div id="content"> | |
<pre class="file" id="file0" style="display: none">package vmx | |
import ( | |
"errors" | |
"fmt" | |
"log" | |
"time" | |
vmwcommon "github.com/hashicorp/packer/builder/vmware/common" | |
"github.com/hashicorp/packer/common" | |
"github.com/hashicorp/packer/helper/communicator" | |
"github.com/hashicorp/packer/helper/multistep" | |
"github.com/hashicorp/packer/packer" | |
) | |
// Builder implements packer.Builder and builds the actual VMware | |
// images. | |
type Builder struct { | |
config *Config | |
runner multistep.Runner | |
} | |
// Prepare processes the build configuration parameters. | |
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) <span class="cov8" title="1">{ | |
c, warnings, errs := NewConfig(raws...) | |
if errs != nil </span><span class="cov8" title="1">{ | |
return warnings, errs | |
}</span> | |
<span class="cov8" title="1">b.config = c | |
return warnings, nil</span> | |
} | |
// Run executes a Packer build and returns a packer.Artifact representing | |
// a VMware image. | |
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) <span class="cov0" title="0">{ | |
driver, err := vmwcommon.NewDriver(&b.config.DriverConfig, &b.config.SSHConfig) | |
if err != nil </span><span class="cov0" title="0">{ | |
return nil, fmt.Errorf("Failed creating VMware driver: %s", err) | |
}</span> | |
// Setup the directory | |
<span class="cov0" title="0">dir := new(vmwcommon.LocalOutputDir) | |
dir.SetOutputDir(b.config.OutputDir) | |
// Set up the state. | |
state := new(multistep.BasicStateBag) | |
state.Put("config", b.config) | |
state.Put("debug", b.config.PackerDebug) | |
state.Put("dir", dir) | |
state.Put("driver", driver) | |
state.Put("hook", hook) | |
state.Put("ui", ui) | |
// Build the steps. | |
steps := []multistep.Step{ | |
&vmwcommon.StepPrepareTools{ | |
RemoteType: b.config.RemoteType, | |
ToolsUploadFlavor: b.config.ToolsUploadFlavor, | |
}, | |
&vmwcommon.StepOutputDir{ | |
Force: b.config.PackerForce, | |
}, | |
&common.StepCreateFloppy{ | |
Files: b.config.FloppyConfig.FloppyFiles, | |
Directories: b.config.FloppyConfig.FloppyDirectories, | |
}, | |
&StepCloneVMX{ | |
OutputDir: b.config.OutputDir, | |
Path: b.config.SourcePath, | |
VMName: b.config.VMName, | |
}, | |
&vmwcommon.StepConfigureVMX{ | |
CustomData: b.config.VMXData, | |
}, | |
&vmwcommon.StepSuppressMessages{}, | |
&common.StepHTTPServer{ | |
HTTPDir: b.config.HTTPDir, | |
HTTPPortMin: b.config.HTTPPortMin, | |
HTTPPortMax: b.config.HTTPPortMax, | |
}, | |
&vmwcommon.StepConfigureVNC{ | |
Enabled: !b.config.DisableVNC, | |
VNCBindAddress: b.config.VNCBindAddress, | |
VNCPortMin: b.config.VNCPortMin, | |
VNCPortMax: b.config.VNCPortMax, | |
VNCDisablePassword: b.config.VNCDisablePassword, | |
}, | |
&vmwcommon.StepRun{ | |
DurationBeforeStop: 5 * time.Second, | |
Headless: b.config.Headless, | |
}, | |
&vmwcommon.StepTypeBootCommand{ | |
BootWait: b.config.BootWait, | |
VNCEnabled: !b.config.DisableVNC, | |
BootCommand: b.config.FlatBootCommand(), | |
VMName: b.config.VMName, | |
Ctx: b.config.ctx, | |
}, | |
&communicator.StepConnect{ | |
Config: &b.config.SSHConfig.Comm, | |
Host: driver.CommHost, | |
SSHConfig: vmwcommon.SSHConfigFunc(&b.config.SSHConfig), | |
}, | |
&vmwcommon.StepUploadTools{ | |
RemoteType: b.config.RemoteType, | |
ToolsUploadFlavor: b.config.ToolsUploadFlavor, | |
ToolsUploadPath: b.config.ToolsUploadPath, | |
Ctx: b.config.ctx, | |
}, | |
&common.StepProvision{}, | |
&vmwcommon.StepShutdown{ | |
Command: b.config.ShutdownCommand, | |
Timeout: b.config.ShutdownTimeout, | |
}, | |
&vmwcommon.StepCleanFiles{}, | |
&vmwcommon.StepCompactDisk{ | |
Skip: b.config.SkipCompaction, | |
}, | |
&vmwcommon.StepConfigureVMX{ | |
CustomData: b.config.VMXDataPost, | |
SkipFloppy: true, | |
}, | |
&vmwcommon.StepCleanVMX{ | |
RemoveEthernetInterfaces: b.config.VMXConfig.VMXRemoveEthernet, | |
VNCEnabled: !b.config.DisableVNC, | |
}, | |
} | |
// Run the steps. | |
b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state) | |
b.runner.Run(state) | |
// Report any errors. | |
if rawErr, ok := state.GetOk("error"); ok </span><span class="cov0" title="0">{ | |
return nil, rawErr.(error) | |
}</span> | |
// If we were interrupted or cancelled, then just exit. | |
<span class="cov0" title="0">if _, ok := state.GetOk(multistep.StateCancelled); ok </span><span class="cov0" title="0">{ | |
return nil, errors.New("Build was cancelled.") | |
}</span> | |
<span class="cov0" title="0">if _, ok := state.GetOk(multistep.StateHalted); ok </span><span class="cov0" title="0">{ | |
return nil, errors.New("Build was halted.") | |
}</span> | |
<span class="cov0" title="0">return vmwcommon.NewLocalArtifact(b.config.VMName, b.config.OutputDir)</span> | |
} | |
// Cancel. | |
func (b *Builder) Cancel() <span class="cov0" title="0">{ | |
if b.runner != nil </span><span class="cov0" title="0">{ | |
log.Println("Cancelling the step runner...") | |
b.runner.Cancel() | |
}</span> | |
} | |
</pre> | |
<pre class="file" id="file1" style="display: none">package vmx | |
import ( | |
"fmt" | |
"os" | |
vmwcommon "github.com/hashicorp/packer/builder/vmware/common" | |
"github.com/hashicorp/packer/common" | |
"github.com/hashicorp/packer/common/bootcommand" | |
"github.com/hashicorp/packer/helper/config" | |
"github.com/hashicorp/packer/packer" | |
"github.com/hashicorp/packer/template/interpolate" | |
) | |
// Config is the configuration structure for the builder. | |
type Config struct { | |
common.PackerConfig `mapstructure:",squash"` | |
common.HTTPConfig `mapstructure:",squash"` | |
common.FloppyConfig `mapstructure:",squash"` | |
bootcommand.VNCConfig `mapstructure:",squash"` | |
vmwcommon.DriverConfig `mapstructure:",squash"` | |
vmwcommon.OutputConfig `mapstructure:",squash"` | |
vmwcommon.RunConfig `mapstructure:",squash"` | |
vmwcommon.ShutdownConfig `mapstructure:",squash"` | |
vmwcommon.SSHConfig `mapstructure:",squash"` | |
vmwcommon.ToolsConfig `mapstructure:",squash"` | |
vmwcommon.VMXConfig `mapstructure:",squash"` | |
RemoteType string `mapstructure:"remote_type"` | |
SkipCompaction bool `mapstructure:"skip_compaction"` | |
SourcePath string `mapstructure:"source_path"` | |
VMName string `mapstructure:"vm_name"` | |
ctx interpolate.Context | |
} | |
func NewConfig(raws ...interface{}) (*Config, []string, error) <span class="cov8" title="1">{ | |
c := new(Config) | |
err := config.Decode(c, &config.DecodeOpts{ | |
Interpolate: true, | |
InterpolateContext: &c.ctx, | |
InterpolateFilter: &interpolate.RenderFilter{ | |
Exclude: []string{ | |
"boot_command", | |
"tools_upload_path", | |
}, | |
}, | |
}, raws...) | |
if err != nil </span><span class="cov0" title="0">{ | |
return nil, nil, err | |
}</span> | |
// Defaults | |
<span class="cov8" title="1">if c.VMName == "" </span><span class="cov8" title="1">{ | |
c.VMName = fmt.Sprintf( | |
"packer-%s-%d", c.PackerBuildName, interpolate.InitTime.Unix()) | |
}</span> | |
// Prepare the errors | |
<span class="cov8" title="1">var errs *packer.MultiError | |
errs = packer.MultiErrorAppend(errs, c.DriverConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...) | |
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.VMXConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...) | |
errs = packer.MultiErrorAppend(errs, c.VNCConfig.Prepare(&c.ctx)...) | |
if c.SourcePath == "" </span><span class="cov8" title="1">{ | |
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is blank, but is required")) | |
}</span> else<span class="cov8" title="1"> { | |
if _, err := os.Stat(c.SourcePath); err != nil </span><span class="cov8" title="1">{ | |
errs = packer.MultiErrorAppend(errs, | |
fmt.Errorf("source_path is invalid: %s", err)) | |
}</span> | |
} | |
// Warnings | |
<span class="cov8" title="1">var warnings []string | |
if c.ShutdownCommand == "" </span><span class="cov0" title="0">{ | |
warnings = append(warnings, | |
"A shutdown_command was not specified. Without a shutdown command, Packer\n"+ | |
"will forcibly halt the virtual machine, which may result in data loss.") | |
}</span> | |
<span class="cov8" title="1">if c.Headless && c.DisableVNC </span><span class="cov0" title="0">{ | |
warnings = append(warnings, | |
"Headless mode uses VNC to retrieve output. Since VNC has been disabled,\n"+ | |
"you won't be able to see any output.") | |
}</span> | |
// Check for any errors. | |
<span class="cov8" title="1">if errs != nil && len(errs.Errors) > 0 </span><span class="cov8" title="1">{ | |
return nil, warnings, errs | |
}</span> | |
<span class="cov8" title="1">return c, warnings, nil</span> | |
} | |
</pre> | |
<pre class="file" id="file2" style="display: none">package vmx | |
import ( | |
"context" | |
"fmt" | |
"log" | |
"path/filepath" | |
"regexp" | |
vmwcommon "github.com/hashicorp/packer/builder/vmware/common" | |
"github.com/hashicorp/packer/helper/multistep" | |
"github.com/hashicorp/packer/packer" | |
) | |
// StepCloneVMX takes a VMX file and clones the VM into the output directory. | |
type StepCloneVMX struct { | |
OutputDir string | |
Path string | |
VMName string | |
} | |
func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction <span class="cov8" title="1">{ | |
driver := state.Get("driver").(vmwcommon.Driver) | |
ui := state.Get("ui").(packer.Ui) | |
// Set the path we want for the new .vmx file and clone | |
vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx") | |
ui.Say("Cloning source VM...") | |
log.Printf("Cloning from: %s", s.Path) | |
log.Printf("Cloning to: %s", vmxPath) | |
if err := driver.Clone(vmxPath, s.Path); err != nil </span><span class="cov0" title="0">{ | |
state.Put("error", err) | |
return multistep.ActionHalt | |
}</span> | |
// Read in the machine configuration from the cloned VMX file | |
// | |
// * The main driver needs the path to the vmx (set above) and the | |
// network type so that it can work out things like IP's and MAC | |
// addresses | |
// * The disk compaction step needs the paths to all attached disks | |
<span class="cov8" title="1">vmxData, err := vmwcommon.ReadVMX(vmxPath) | |
if err != nil </span><span class="cov0" title="0">{ | |
state.Put("error", err) | |
return multistep.ActionHalt | |
}</span> | |
<span class="cov8" title="1">var diskFilenames []string | |
// The VMX file stores the path to a configured disk, and information | |
// about that disks attachment to a virtual adapter/controller, as a | |
// key/value pair. | |
// For a virtual disk attached to bus ID 3 of the virtual machines | |
// first SCSI adapter the key/value pair would look something like: | |
// scsi0:3.fileName = "relative/path/to/scsiDisk.vmdk" | |
// The supported adapter types and configuration maximums for each type | |
// vary according to the VMware platform type and version, and the | |
// Virtual Machine Hardware version used. See the 'Virtual Machine | |
// Maximums' section within VMware's 'Configuration Maximums' | |
// documentation for each platform: | |
// https://kb.vmware.com/s/article/1003497 | |
// Information about the supported Virtual Machine Hardware versions: | |
// https://kb.vmware.com/s/article/1003746 | |
// The following regexp is used to match all possible disk attachment | |
// points that may be found in the VMX file across all VMware | |
// platforms/versions and Virtual Machine Hardware versions | |
diskPathKeyRe := regexp.MustCompile(`(?i)^(scsi|sata|ide|nvme)[[:digit:]]:[[:digit:]]{1,2}\.fileName`) | |
for k, v := range vmxData </span><span class="cov8" title="1">{ | |
match := diskPathKeyRe.FindString(k) | |
if match != "" && filepath.Ext(v) == ".vmdk" </span><span class="cov8" title="1">{ | |
diskFilenames = append(diskFilenames, v) | |
}</span> | |
} | |
// Write out the relative, host filesystem paths to the disks | |
<span class="cov8" title="1">var diskFullPaths []string | |
for _, diskFilename := range diskFilenames </span><span class="cov8" title="1">{ | |
log.Printf("Found attached disk with filename: %s", diskFilename) | |
diskFullPaths = append(diskFullPaths, filepath.Join(s.OutputDir, diskFilename)) | |
}</span> | |
<span class="cov8" title="1">if len(diskFullPaths) == 0 </span><span class="cov0" title="0">{ | |
state.Put("error", fmt.Errorf("Could not enumerate disk info from the vmx file")) | |
return multistep.ActionHalt | |
}</span> | |
// Determine the network type by reading out of the .vmx | |
<span class="cov8" title="1">var networkType string | |
if _, ok := vmxData["ethernet0.connectiontype"]; ok </span><span class="cov8" title="1">{ | |
networkType = vmxData["ethernet0.connectiontype"] | |
log.Printf("Discovered the network type: %s", networkType) | |
}</span> | |
<span class="cov8" title="1">if networkType == "" </span><span class="cov0" title="0">{ | |
networkType = "nat" | |
log.Printf("Defaulting to network type: %s", networkType) | |
}</span> | |
// Stash all required information in our state bag | |
<span class="cov8" title="1">state.Put("vmx_path", vmxPath) | |
state.Put("disk_full_paths", diskFullPaths) | |
state.Put("vmnetwork", networkType) | |
return multistep.ActionContinue</span> | |
} | |
func (s *StepCloneVMX) Cleanup(state multistep.StateBag) {<span class="cov0" title="0"> | |
}</span> | |
</pre> | |
</div> | |
</body> | |
<script> | |
(function() { | |
var files = document.getElementById('files'); | |
var visible; | |
files.addEventListener('change', onChange, false); | |
function select(part) { | |
if (visible) | |
visible.style.display = 'none'; | |
visible = document.getElementById(part); | |
if (!visible) | |
return; | |
files.value = part; | |
visible.style.display = 'block'; | |
location.hash = part; | |
} | |
function onChange() { | |
select(files.value); | |
window.scrollTo(0, 0); | |
} | |
if (location.hash != "") { | |
select(location.hash.substr(1)); | |
} | |
if (!visible) { | |
select("file0"); | |
} | |
})(); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment