IP snooping
This commit is contained in:
parent
6ffa99d624
commit
176c4ad7a3
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
@ -21,9 +22,30 @@ import (
|
||||
// Produces:
|
||||
// http_port int - The port the HTTP server started on.
|
||||
type StepHTTPServer struct {
|
||||
Chan chan<- string
|
||||
|
||||
l net.Listener
|
||||
}
|
||||
|
||||
type IPSnooper struct {
|
||||
ch chan<- string
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func (snooper IPSnooper) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||
log.Printf("HTTP: %s %s %s", req.RemoteAddr, req.Method, req.URL)
|
||||
ip, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||
if err == nil && ip != "" {
|
||||
select {
|
||||
case snooper.ch <- ip:
|
||||
log.Printf("Remembering remote address '%s'", ip)
|
||||
default:
|
||||
// if ch is already full, don't block waiting to send the address, just drop it
|
||||
}
|
||||
}
|
||||
snooper.handler.ServeHTTP(resp, req)
|
||||
}
|
||||
|
||||
func (s *StepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("commonconfig").(CommonConfig)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
@ -45,7 +67,13 @@ func (s *StepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
|
||||
|
||||
// Start the HTTP server and run it in the background
|
||||
fileServer := http.FileServer(http.Dir(config.HTTPDir))
|
||||
server := &http.Server{Addr: fmt.Sprintf(":%d", httpPort), Handler: fileServer}
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", httpPort),
|
||||
Handler: IPSnooper{
|
||||
ch: s.Chan,
|
||||
handler: fileServer,
|
||||
},
|
||||
}
|
||||
go server.Serve(s.l)
|
||||
|
||||
// Save the address into the state so it can be accessed in the future
|
||||
|
@ -1,40 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
type StepRemoveDevices struct{}
|
||||
|
||||
func (self *StepRemoveDevices) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
client := state.Get("client").(XenAPIClient)
|
||||
|
||||
ui.Say("Step: Remove devices from VM")
|
||||
|
||||
instance_id := state.Get("instance_uuid").(string)
|
||||
instance, err := client.GetVMByUuid(instance_id)
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Could not get VM from UUID %s", instance_id))
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Destroy all connected VIFs
|
||||
vifs, err := instance.GetVIFs()
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Could not get VIFs"))
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
for _, vif := range vifs {
|
||||
ui.Message("Destroying VIF " + vif.Ref)
|
||||
vif.Destroy()
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (self *StepRemoveDevices) Cleanup(state multistep.StateBag) {}
|
45
builder/xenserver/common/step_wait_for_http_request.go
Normal file
45
builder/xenserver/common/step_wait_for_http_request.go
Normal file
@ -0,0 +1,45 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
type StepWaitForHTTPRequest struct {
|
||||
Chan <-chan string
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
func (self *StepWaitForHTTPRequest) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Step: Wait for install to complete.")
|
||||
|
||||
timeout := time.After(self.Timeout)
|
||||
var ip string
|
||||
select {
|
||||
case ip = <-self.Chan:
|
||||
case <-timeout:
|
||||
ui.Error("Timed out. Giving up waiting for installation to complete.")
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Got IP address '%s'", ip))
|
||||
state.Put("instance_ssh_address", ip)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (self *StepWaitForHTTPRequest) Cleanup(state multistep.StateBag) {}
|
||||
|
||||
func InstanceSSHIP(state multistep.StateBag) (string, error) {
|
||||
ip := state.Get("instance_ssh_address").(string)
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
func InstanceSSHPort(state multistep.StateBag) (uint, error) {
|
||||
return 22, nil
|
||||
}
|
@ -186,6 +186,8 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
httpReqChan := make(chan string, 1)
|
||||
|
||||
//Build the steps
|
||||
steps := []multistep.Step{
|
||||
&common.StepDownload{
|
||||
@ -202,7 +204,9 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
||||
&common.StepCreateFloppy{
|
||||
Files: self.config.FloppyFiles,
|
||||
},
|
||||
new(xscommon.StepHTTPServer),
|
||||
&xscommon.StepHTTPServer{
|
||||
Chan: httpReqChan,
|
||||
},
|
||||
&xscommon.StepUploadVdi{
|
||||
VdiName: "Packer-floppy-disk",
|
||||
ImagePathFunc: func() string {
|
||||
@ -250,18 +254,13 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
||||
&xscommon.StepTypeBootCommand{
|
||||
Tpl: self.config.tpl,
|
||||
},
|
||||
new(stepWait),
|
||||
&xscommon.StepDetachVdi{
|
||||
VdiUuidKey: "floppy_vdi_uuid",
|
||||
&xscommon.StepWaitForHTTPRequest{
|
||||
Chan: httpReqChan,
|
||||
Timeout: self.config.InstallTimeout, // @todo change this
|
||||
},
|
||||
&xscommon.StepDetachVdi{
|
||||
VdiUuidKey: "iso_vdi_uuid",
|
||||
},
|
||||
new(xscommon.StepRemoveDevices),
|
||||
new(xscommon.StepStartOnHIMN),
|
||||
&xscommon.StepForwardPortOverSSH{
|
||||
RemotePort: xscommon.HimnSSHPort,
|
||||
RemoteDest: xscommon.HimnSSHIP,
|
||||
RemotePort: xscommon.InstanceSSHPort,
|
||||
RemoteDest: xscommon.InstanceSSHIP,
|
||||
HostPortMin: self.config.HostPortMin,
|
||||
HostPortMax: self.config.HostPortMax,
|
||||
ResultKey: "local_ssh_port",
|
||||
|
@ -1,52 +0,0 @@
|
||||
package iso
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
xscommon "github.com/rdobson/packer-builder-xenserver/builder/xenserver/common"
|
||||
)
|
||||
|
||||
type stepWait struct{}
|
||||
|
||||
func (self *stepWait) Run(state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(config)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
client := state.Get("client").(xscommon.XenAPIClient)
|
||||
|
||||
ui.Say("Step: Wait for install to complete.")
|
||||
|
||||
instance_id := state.Get("instance_uuid").(string)
|
||||
instance, err := client.GetVMByUuid(instance_id)
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Could not get VM from UUID %s", instance_id))
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
//Expect install to be configured to shutdown on completion
|
||||
err = xscommon.InterruptibleWait{
|
||||
Predicate: func() (bool, error) {
|
||||
log.Printf("Waiting for install to complete.")
|
||||
power_state, err := instance.GetPowerState()
|
||||
return power_state == "Halted", err
|
||||
},
|
||||
PredicateInterval: 30 * time.Second,
|
||||
Timeout: config.InstallTimeout,
|
||||
}.Wait(state)
|
||||
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
ui.Error("Giving up waiting for installation to complete.")
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say("Install has completed. Moving on.")
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (self *stepWait) Cleanup(state multistep.StateBag) {}
|
@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/common"
|
||||
@ -112,6 +113,8 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
httpReqChan := make(chan string, 1)
|
||||
|
||||
//Build the steps
|
||||
steps := []multistep.Step{
|
||||
&xscommon.StepPrepareOutputDir{
|
||||
@ -145,11 +148,26 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
||||
VdiUuidKey: "tools_vdi_uuid",
|
||||
VdiType: xscommon.CD,
|
||||
},
|
||||
new(xscommon.StepRemoveDevices),
|
||||
new(xscommon.StepStartOnHIMN),
|
||||
new(xscommon.StepStartVmPaused),
|
||||
new(xscommon.StepGetVNCPort),
|
||||
&xscommon.StepForwardPortOverSSH{
|
||||
RemotePort: xscommon.HimnSSHPort,
|
||||
RemoteDest: xscommon.HimnSSHIP,
|
||||
RemotePort: xscommon.InstanceVNCPort,
|
||||
RemoteDest: xscommon.InstanceVNCIP,
|
||||
HostPortMin: self.config.HostPortMin,
|
||||
HostPortMax: self.config.HostPortMax,
|
||||
ResultKey: "local_vnc_port",
|
||||
},
|
||||
new(xscommon.StepBootWait),
|
||||
&xscommon.StepTypeBootCommand{
|
||||
Tpl: self.config.tpl,
|
||||
},
|
||||
&xscommon.StepWaitForIP{
|
||||
Chan: httpReqChan,
|
||||
Timeout: 300 * time.Minute /*self.config.InstallTimeout*/, // @todo change this
|
||||
},
|
||||
&xscommon.StepForwardPortOverSSH{
|
||||
RemotePort: xscommon.InstanceSSHPort,
|
||||
RemoteDest: xscommon.InstanceSSHIP,
|
||||
HostPortMin: self.config.HostPortMin,
|
||||
HostPortMax: self.config.HostPortMax,
|
||||
ResultKey: "local_ssh_port",
|
||||
|
Loading…
Reference in New Issue
Block a user