From 16f8c25d84b7b4a68b28d0daae6a18e718d009e2 Mon Sep 17 00:00:00 2001 From: Cheng Sun Date: Fri, 2 Jan 2015 16:22:36 +0000 Subject: [PATCH] Fix shutdown_command bug Fixes the somewhat embarrassing bug where the shutdown_command would be run on the host rather than the guest. This commit also rejigs things so that it is easier to do SSH commands on either the host or the guest --- builder/xenserver/common/ssh.go | 45 +++++++++++++------ builder/xenserver/common/step_get_vnc_port.go | 4 +- .../common/step_shutdown_and_export.go | 2 +- .../xenserver/common/step_start_on_himn.go | 3 +- .../common/step_type_boot_command.go | 2 +- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/builder/xenserver/common/ssh.go b/builder/xenserver/common/ssh.go index d7a9a6b..8500a58 100644 --- a/builder/xenserver/common/ssh.go +++ b/builder/xenserver/common/ssh.go @@ -20,9 +20,11 @@ func SSHAddress(state multistep.StateBag) (string, error) { } func SSHLocalAddress(state multistep.StateBag) (string, error) { - sshLocalPort := state.Get("local_ssh_port").(uint) + sshLocalPort, ok := state.Get("local_ssh_port").(uint) + if !ok { + return "", fmt.Errorf("SSH port forwarding hasn't been set up yet") + } conn_str := fmt.Sprintf("%s:%d", "127.0.0.1", sshLocalPort) - log.Printf("sshLocalAddress: %s", conn_str) return conn_str, nil } @@ -49,24 +51,14 @@ func SSHConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { }, nil } -func execute_ssh_cmd(cmd, host, port, username, password string) (stdout string, err error) { - // Setup connection config - config := &gossh.ClientConfig{ - User: username, - Auth: []gossh.AuthMethod{ - gossh.Password(password), - }, - } - - client, err := gossh.Dial("tcp", host+":"+port, config) - +func doExecuteSSHCmd(cmd, target string, config *gossh.ClientConfig) (stdout string, err error) { + client, err := gossh.Dial("tcp", target, config) if err != nil { return "", err } //Create session session, err := client.NewSession() - if err != nil { return "", err } @@ -82,6 +74,31 @@ func execute_ssh_cmd(cmd, host, port, username, password string) (stdout string, return strings.Trim(b.String(), "\n"), nil } +func ExecuteHostSSHCmd(state multistep.StateBag, cmd string) (stdout string, err error) { + config := state.Get("commonconfig").(CommonConfig) + // Setup connection config + sshConfig := &gossh.ClientConfig{ + User: config.Username, + Auth: []gossh.AuthMethod{ + gossh.Password(config.Password), + }, + } + return doExecuteSSHCmd(cmd, config.HostIp+":22", sshConfig) +} + +func ExecuteGuestSSHCmd(state multistep.StateBag, cmd string) (stdout string, err error) { + localAddress, err := SSHLocalAddress(state) + if err != nil { + return + } + sshConfig, err := SSHConfig(state) + if err != nil { + return + } + + return doExecuteSSHCmd(cmd, localAddress, sshConfig) +} + func forward(local_conn net.Conn, config *gossh.ClientConfig, server, remote_dest string, remote_port uint) error { defer local_conn.Close() diff --git a/builder/xenserver/common/step_get_vnc_port.go b/builder/xenserver/common/step_get_vnc_port.go index 4dd208c..88afba2 100644 --- a/builder/xenserver/common/step_get_vnc_port.go +++ b/builder/xenserver/common/step_get_vnc_port.go @@ -10,8 +10,6 @@ import ( type StepGetVNCPort struct{} func (self *StepGetVNCPort) Run(state multistep.StateBag) multistep.StepAction { - - config := state.Get("commonconfig").(CommonConfig) ui := state.Get("ui").(packer.Ui) ui.Say("Step: forward the instances VNC port over SSH") @@ -19,7 +17,7 @@ func (self *StepGetVNCPort) Run(state multistep.StateBag) multistep.StepAction { domid := state.Get("domid").(string) cmd := fmt.Sprintf("xenstore-read /local/domain/%s/console/vnc-port", domid) - remote_vncport, err := execute_ssh_cmd(cmd, config.HostIp, "22", config.Username, config.Password) + remote_vncport, err := ExecuteHostSSHCmd(state, cmd) if err != nil { ui.Error(fmt.Sprintf("Unable to get VNC port (is the VM running?): %s", err.Error())) return multistep.ActionHalt diff --git a/builder/xenserver/common/step_shutdown_and_export.go b/builder/xenserver/common/step_shutdown_and_export.go index c49edfe..39fe0d6 100644 --- a/builder/xenserver/common/step_shutdown_and_export.go +++ b/builder/xenserver/common/step_shutdown_and_export.go @@ -63,7 +63,7 @@ func (StepShutdownAndExport) Run(state multistep.StateBag) multistep.StepAction if config.ShutdownCommand != "" { ui.Say("Executing shutdown command...") - _, err := execute_ssh_cmd(config.ShutdownCommand, config.HostIp, "22", config.Username, config.Password) + _, err := ExecuteGuestSSHCmd(state, config.ShutdownCommand) if err != nil { ui.Error(fmt.Sprintf("Shutdown command failed: %s", err.Error())) return false diff --git a/builder/xenserver/common/step_start_on_himn.go b/builder/xenserver/common/step_start_on_himn.go index fbc0ae8..816c228 100644 --- a/builder/xenserver/common/step_start_on_himn.go +++ b/builder/xenserver/common/step_start_on_himn.go @@ -23,7 +23,6 @@ func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction ui := state.Get("ui").(packer.Ui) client := state.Get("client").(XenAPIClient) - config := state.Get("commonconfig").(CommonConfig) ui.Say("Step: Start VM on the Host Internal Mangement Network") @@ -96,7 +95,7 @@ func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction err = InterruptibleWait{ Predicate: func() (success bool, err error) { ui.Message(fmt.Sprintf("Attempting to ping interface: %s", ping_cmd)) - _, err = execute_ssh_cmd(ping_cmd, config.HostIp, "22", config.Username, config.Password) + _, err = ExecuteHostSSHCmd(state, ping_cmd) switch err.(type) { case nil: diff --git a/builder/xenserver/common/step_type_boot_command.go b/builder/xenserver/common/step_type_boot_command.go index d1e1f69..76afcb9 100644 --- a/builder/xenserver/common/step_type_boot_command.go +++ b/builder/xenserver/common/step_type_boot_command.go @@ -61,7 +61,7 @@ func (self *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAct log.Printf("Connected to the VNC console: %s", c.DesktopName) // find local ip - envVar, err := execute_ssh_cmd("echo $SSH_CLIENT", config.HostIp, "22", config.Username, config.Password) + envVar, err := ExecuteHostSSHCmd(state, "echo $SSH_CLIENT") if err != nil { ui.Error(fmt.Sprintf("Error detecting local IP: %s", err)) return multistep.ActionHalt