Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
packer
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kristopher Ruzic
packer
Commits
48a3892c
Commit
48a3892c
authored
Jun 12, 2013
by
Mitchell Hashimoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
builder/virtualbox: graceful shutdown
parent
52391bb1
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
136 additions
and
0 deletions
+136
-0
builder/virtualbox/builder.go
builder/virtualbox/builder.go
+13
-0
builder/virtualbox/builder_test.go
builder/virtualbox/builder_test.go
+19
-0
builder/virtualbox/driver.go
builder/virtualbox/driver.go
+32
-0
builder/virtualbox/step_shutdown.go
builder/virtualbox/step_shutdown.go
+72
-0
No files found.
builder/virtualbox/builder.go
View file @
48a3892c
...
@@ -32,6 +32,8 @@ type config struct {
...
@@ -32,6 +32,8 @@ type config struct {
ISOMD5
string
`mapstructure:"iso_md5"`
ISOMD5
string
`mapstructure:"iso_md5"`
ISOUrl
string
`mapstructure:"iso_url"`
ISOUrl
string
`mapstructure:"iso_url"`
OutputDir
string
`mapstructure:"output_directory"`
OutputDir
string
`mapstructure:"output_directory"`
ShutdownCommand
string
`mapstructure:"shutdown_command"`
ShutdownTimeout
time
.
Duration
``
SSHHostPortMin
uint
`mapstructure:"ssh_host_port_min"`
SSHHostPortMin
uint
`mapstructure:"ssh_host_port_min"`
SSHHostPortMax
uint
`mapstructure:"ssh_host_port_max"`
SSHHostPortMax
uint
`mapstructure:"ssh_host_port_max"`
SSHPassword
string
`mapstructure:"ssh_password"`
SSHPassword
string
`mapstructure:"ssh_password"`
...
@@ -41,6 +43,7 @@ type config struct {
...
@@ -41,6 +43,7 @@ type config struct {
VMName
string
`mapstructure:"vm_name"`
VMName
string
`mapstructure:"vm_name"`
RawBootWait
string
`mapstructure:"boot_wait"`
RawBootWait
string
`mapstructure:"boot_wait"`
RawShutdownTimeout
string
`mapstructure:"shutdown_timeout"`
RawSSHWaitTimeout
string
`mapstructure:"ssh_wait_timeout"`
RawSSHWaitTimeout
string
`mapstructure:"ssh_wait_timeout"`
}
}
...
@@ -140,6 +143,15 @@ func (b *Builder) Prepare(raw interface{}) error {
...
@@ -140,6 +143,15 @@ func (b *Builder) Prepare(raw interface{}) error {
}
}
}
}
if
b
.
config
.
RawShutdownTimeout
==
""
{
b
.
config
.
RawShutdownTimeout
=
"5m"
}
b
.
config
.
ShutdownTimeout
,
err
=
time
.
ParseDuration
(
b
.
config
.
RawShutdownTimeout
)
if
err
!=
nil
{
errs
=
append
(
errs
,
fmt
.
Errorf
(
"Failed parsing shutdown_timeout: %s"
,
err
))
}
if
b
.
config
.
SSHHostPortMin
>
b
.
config
.
SSHHostPortMax
{
if
b
.
config
.
SSHHostPortMin
>
b
.
config
.
SSHHostPortMax
{
errs
=
append
(
errs
,
errors
.
New
(
"ssh_host_port_min must be less than ssh_host_port_max"
))
errs
=
append
(
errs
,
errors
.
New
(
"ssh_host_port_min must be less than ssh_host_port_max"
))
}
}
...
@@ -183,6 +195,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
...
@@ -183,6 +195,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
new
(
stepTypeBootCommand
),
new
(
stepTypeBootCommand
),
new
(
stepWaitForSSH
),
new
(
stepWaitForSSH
),
new
(
stepProvision
),
new
(
stepProvision
),
new
(
stepShutdown
),
}
}
// Setup the state bag
// Setup the state bag
...
...
builder/virtualbox/builder_test.go
View file @
48a3892c
...
@@ -171,6 +171,25 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
...
@@ -171,6 +171,25 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
}
}
}
}
func
TestBuilderPrepare_ShutdownTimeout
(
t
*
testing
.
T
)
{
var
b
Builder
config
:=
testConfig
()
// Test with a bad value
config
[
"shutdown_timeout"
]
=
"this is not good"
err
:=
b
.
Prepare
(
config
)
if
err
==
nil
{
t
.
Fatal
(
"should have error"
)
}
// Test with a good one
config
[
"shutdown_timeout"
]
=
"5s"
err
=
b
.
Prepare
(
config
)
if
err
!=
nil
{
t
.
Fatalf
(
"should not have error: %s"
,
err
)
}
}
func
TestBuilderPrepare_SSHHostPort
(
t
*
testing
.
T
)
{
func
TestBuilderPrepare_SSHHostPort
(
t
*
testing
.
T
)
{
var
b
Builder
var
b
Builder
config
:=
testConfig
()
config
:=
testConfig
()
...
...
builder/virtualbox/driver.go
View file @
48a3892c
...
@@ -12,6 +12,12 @@ import (
...
@@ -12,6 +12,12 @@ import (
// A driver is able to talk to VirtualBox and perform certain
// A driver is able to talk to VirtualBox and perform certain
// operations with it.
// operations with it.
type
Driver
interface
{
type
Driver
interface
{
// Checks if the VM with the given name is running.
IsRunning
(
string
)
(
bool
,
error
)
// Stop stops a running machine, forcefully.
Stop
(
string
)
error
// SuppressMessages should do what needs to be done in order to
// SuppressMessages should do what needs to be done in order to
// suppress any annoying popups from VirtualBox.
// suppress any annoying popups from VirtualBox.
SuppressMessages
()
error
SuppressMessages
()
error
...
@@ -30,6 +36,32 @@ type VBox42Driver struct {
...
@@ -30,6 +36,32 @@ type VBox42Driver struct {
VBoxManagePath
string
VBoxManagePath
string
}
}
func
(
d
*
VBox42Driver
)
IsRunning
(
name
string
)
(
bool
,
error
)
{
var
stdout
bytes
.
Buffer
cmd
:=
exec
.
Command
(
d
.
VBoxManagePath
,
"showvminfo"
,
name
,
"--machinereadable"
)
cmd
.
Stdout
=
&
stdout
if
err
:=
cmd
.
Run
();
err
!=
nil
{
return
false
,
err
}
for
_
,
line
:=
range
strings
.
Split
(
stdout
.
String
(),
"
\n
"
)
{
if
line
==
`VMState="running"`
{
return
true
,
nil
}
}
return
false
,
nil
}
func
(
d
*
VBox42Driver
)
Stop
(
name
string
)
error
{
if
err
:=
d
.
VBoxManage
(
"controlvm"
,
name
,
"poweroff"
);
err
!=
nil
{
return
err
}
return
nil
}
func
(
d
*
VBox42Driver
)
SuppressMessages
()
error
{
func
(
d
*
VBox42Driver
)
SuppressMessages
()
error
{
extraData
:=
map
[
string
]
string
{
extraData
:=
map
[
string
]
string
{
"GUI/RegistrationData"
:
"triesLeft=0"
,
"GUI/RegistrationData"
:
"triesLeft=0"
,
...
...
builder/virtualbox/step_shutdown.go
0 → 100644
View file @
48a3892c
package
virtualbox
import
(
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"time"
)
// This step shuts down the machine. It first attempts to do so gracefully,
// but ultimately forcefully shuts it down if that fails.
//
// Uses:
// communicator packer.Communicator
// config *config
// driver Driver
// ui packer.Ui
// vmName string
//
// Produces:
// <nothing>
type
stepShutdown
struct
{}
func
(
s
*
stepShutdown
)
Run
(
state
map
[
string
]
interface
{})
multistep
.
StepAction
{
comm
:=
state
[
"communicator"
]
.
(
packer
.
Communicator
)
config
:=
state
[
"config"
]
.
(
*
config
)
driver
:=
state
[
"driver"
]
.
(
Driver
)
ui
:=
state
[
"ui"
]
.
(
packer
.
Ui
)
vmName
:=
state
[
"vmName"
]
.
(
string
)
if
config
.
ShutdownCommand
!=
""
{
ui
.
Say
(
"Gracefully halting virtual machine..."
)
log
.
Printf
(
"Executing shutdown command: %s"
,
config
.
ShutdownCommand
)
cmd
:=
&
packer
.
RemoteCmd
{
Command
:
config
.
ShutdownCommand
}
if
err
:=
comm
.
Start
(
cmd
);
err
!=
nil
{
ui
.
Error
(
fmt
.
Sprintf
(
"Failed to send shutdown command: %s"
,
err
))
return
multistep
.
ActionHalt
}
// Wait for the command to run
cmd
.
Wait
()
// Wait for the machine to actually shut down
log
.
Printf
(
"Waiting max %s for shutdown to complete"
,
config
.
ShutdownTimeout
)
shutdownTimer
:=
time
.
After
(
config
.
ShutdownTimeout
)
for
{
running
,
_
:=
driver
.
IsRunning
(
vmName
)
if
!
running
{
break
}
select
{
case
<-
shutdownTimer
:
ui
.
Error
(
"Timeout while waiting for machine to shut down."
)
return
multistep
.
ActionHalt
default
:
time
.
Sleep
(
1
*
time
.
Second
)
}
}
}
else
{
if
err
:=
driver
.
Stop
(
vmName
);
err
!=
nil
{
ui
.
Error
(
fmt
.
Sprintf
(
"Error stopping VM: %s"
,
err
))
return
multistep
.
ActionHalt
}
}
log
.
Println
(
"VM shut down."
)
return
multistep
.
ActionContinue
}
func
(
s
*
stepShutdown
)
Cleanup
(
state
map
[
string
]
interface
{})
{}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment