github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/builder/qemu/step_http_server.go (about)

     1  package qemu
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/multistep"
     6  	"github.com/mitchellh/packer/packer"
     7  	"log"
     8  	"math/rand"
     9  	"net"
    10  	"net/http"
    11  )
    12  
    13  // This step creates and runs the HTTP server that is serving files from the
    14  // directory specified by the 'http_directory` configuration parameter in the
    15  // template.
    16  //
    17  // Uses:
    18  //   config *config
    19  //   ui     packer.Ui
    20  //
    21  // Produces:
    22  //   http_port int - The port the HTTP server started on.
    23  type stepHTTPServer struct {
    24  	l net.Listener
    25  }
    26  
    27  func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
    28  	config := state.Get("config").(*Config)
    29  	ui := state.Get("ui").(packer.Ui)
    30  
    31  	var httpPort uint = 0
    32  	if config.HTTPDir == "" {
    33  		state.Put("http_port", httpPort)
    34  		return multistep.ActionContinue
    35  	}
    36  
    37  	// Find an available TCP port for our HTTP server
    38  	var httpAddr string
    39  	portRange := int(config.HTTPPortMax - config.HTTPPortMin)
    40  	for {
    41  		var err error
    42  		var offset uint = 0
    43  
    44  		if portRange > 0 {
    45  			// Intn will panic if portRange == 0, so we do a check.
    46  			offset = uint(rand.Intn(portRange))
    47  		}
    48  
    49  		httpPort = offset + config.HTTPPortMin
    50  		httpAddr = fmt.Sprintf(":%d", httpPort)
    51  		log.Printf("Trying port: %d", httpPort)
    52  		s.l, err = net.Listen("tcp", httpAddr)
    53  		if err == nil {
    54  			break
    55  		}
    56  	}
    57  
    58  	ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
    59  
    60  	// Start the HTTP server and run it in the background
    61  	fileServer := http.FileServer(http.Dir(config.HTTPDir))
    62  	server := &http.Server{Addr: httpAddr, Handler: fileServer}
    63  	go server.Serve(s.l)
    64  
    65  	// Save the address into the state so it can be accessed in the future
    66  	state.Put("http_port", httpPort)
    67  
    68  	return multistep.ActionContinue
    69  }
    70  
    71  func (s *stepHTTPServer) Cleanup(multistep.StateBag) {
    72  	if s.l != nil {
    73  		// Close the listener so that the HTTP server stops
    74  		s.l.Close()
    75  	}
    76  }