forked from hashicorp/packer
/
step_type_boot_command.go
116 lines (97 loc) · 2.91 KB
/
step_type_boot_command.go
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
package common
import (
"context"
"fmt"
"time"
packer_common "github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/bootcommand"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
)
type bootCommandTemplateData struct {
HTTPIP string
HTTPPort uint
Name string
}
// StepTypeBootCommand is a step that "types" the boot command into the VM via
// the prltype script, built on the Parallels Virtualization SDK - Python API.
type StepTypeBootCommand struct {
BootCommand string
BootWait time.Duration
HostInterfaces []string
VMName string
Ctx interpolate.Context
}
// Run types the boot command by sending key scancodes into the VM.
func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
debug := state.Get("debug").(bool)
httpPort := state.Get("http_port").(uint)
ui := state.Get("ui").(packer.Ui)
driver := state.Get("driver").(Driver)
// Wait the for the vm to boot.
if int64(s.BootWait) > 0 {
ui.Say(fmt.Sprintf("Waiting %s for boot...", s.BootWait.String()))
select {
case <-time.After(s.BootWait):
break
case <-ctx.Done():
return multistep.ActionHalt
}
}
var pauseFn multistep.DebugPauseFn
if debug {
pauseFn = state.Get("pauseFn").(multistep.DebugPauseFn)
}
hostIP := "0.0.0.0"
if len(s.HostInterfaces) > 0 {
// Determine the host IP
ipFinder := &IfconfigIPFinder{Devices: s.HostInterfaces}
ip, err := ipFinder.HostIP()
if err != nil {
err = fmt.Errorf("Error detecting host IP: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
hostIP = ip
}
ui.Say(fmt.Sprintf("Host IP for the Parallels machine: %s", hostIP))
packer_common.SetHTTPIP(hostIP)
s.Ctx.Data = &bootCommandTemplateData{
hostIP,
httpPort,
s.VMName,
}
sendCodes := func(codes []string) error {
return driver.SendKeyScanCodes(s.VMName, codes...)
}
d := bootcommand.NewPCXTDriver(sendCodes, -1)
ui.Say("Typing the boot command...")
command, err := interpolate.Render(s.BootCommand, &s.Ctx)
if err != nil {
err = fmt.Errorf("Error preparing boot command: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
seq, err := bootcommand.GenerateExpressionSequence(command)
if err != nil {
err := fmt.Errorf("Error generating boot command: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if err := seq.Do(ctx, d); err != nil {
err := fmt.Errorf("Error running boot command: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if pauseFn != nil {
pauseFn(multistep.DebugLocationAfterRun, fmt.Sprintf("boot_command: %s", command), state)
}
return multistep.ActionContinue
}
// Cleanup does nothing.
func (*StepTypeBootCommand) Cleanup(multistep.StateBag) {}