p2p/simulations: add mocker functionality (#15207)

This commit adds mocker functionality to p2p/simulations. A
mocker allows to starting/stopping of nodes via the HTTP API.
This commit is contained in:
holisticode
2017-12-12 13:10:41 -05:00
committed by Felix Lange
parent 3da1bf8ca1
commit fd777bb210
5 changed files with 480 additions and 2 deletions

View File

@ -27,6 +27,7 @@ import (
"net/http"
"strconv"
"strings"
"sync"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
@ -263,8 +264,10 @@ func (c *Client) Send(method, path string, in, out interface{}) error {
// Server is an HTTP server providing an API to manage a simulation network
type Server struct {
router *httprouter.Router
network *Network
router *httprouter.Router
network *Network
mockerStop chan struct{} // when set, stops the current mocker
mockerMtx sync.Mutex // synchronises access to the mockerStop field
}
// NewServer returns a new simulation API server
@ -278,6 +281,10 @@ func NewServer(network *Network) *Server {
s.GET("/", s.GetNetwork)
s.POST("/start", s.StartNetwork)
s.POST("/stop", s.StopNetwork)
s.POST("/mocker/start", s.StartMocker)
s.POST("/mocker/stop", s.StopMocker)
s.GET("/mocker", s.GetMockers)
s.POST("/reset", s.ResetNetwork)
s.GET("/events", s.StreamNetworkEvents)
s.GET("/snapshot", s.CreateSnapshot)
s.POST("/snapshot", s.LoadSnapshot)
@ -318,6 +325,59 @@ func (s *Server) StopNetwork(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusOK)
}
// StartMocker starts the mocker node simulation
func (s *Server) StartMocker(w http.ResponseWriter, req *http.Request) {
s.mockerMtx.Lock()
defer s.mockerMtx.Unlock()
if s.mockerStop != nil {
http.Error(w, "mocker already running", http.StatusInternalServerError)
return
}
mockerType := req.FormValue("mocker-type")
mockerFn := LookupMocker(mockerType)
if mockerFn == nil {
http.Error(w, fmt.Sprintf("unknown mocker type %q", mockerType), http.StatusBadRequest)
return
}
nodeCount, err := strconv.Atoi(req.FormValue("node-count"))
if err != nil {
http.Error(w, "invalid node-count provided", http.StatusBadRequest)
return
}
s.mockerStop = make(chan struct{})
go mockerFn(s.network, s.mockerStop, nodeCount)
w.WriteHeader(http.StatusOK)
}
// StopMocker stops the mocker node simulation
func (s *Server) StopMocker(w http.ResponseWriter, req *http.Request) {
s.mockerMtx.Lock()
defer s.mockerMtx.Unlock()
if s.mockerStop == nil {
http.Error(w, "stop channel not initialized", http.StatusInternalServerError)
return
}
close(s.mockerStop)
s.mockerStop = nil
w.WriteHeader(http.StatusOK)
}
// GetMockerList returns a list of available mockers
func (s *Server) GetMockers(w http.ResponseWriter, req *http.Request) {
list := GetMockerList()
s.JSON(w, http.StatusOK, list)
}
// ResetNetwork resets all properties of a network to its initial (empty) state
func (s *Server) ResetNetwork(w http.ResponseWriter, req *http.Request) {
s.network.Reset()
w.WriteHeader(http.StatusOK)
}
// StreamNetworkEvents streams network events as a server-sent-events stream
func (s *Server) StreamNetworkEvents(w http.ResponseWriter, req *http.Request) {
events := make(chan *Event)