|
@@ -1,12 +1,12 @@
|
|
|
package diagnose
|
|
|
|
|
|
import (
|
|
|
+ "context"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
- "log"
|
|
|
- "net"
|
|
|
"net/http"
|
|
|
"sync"
|
|
|
+ "sync/atomic"
|
|
|
|
|
|
stackdump "github.com/docker/docker/pkg/signal"
|
|
|
"github.com/docker/libnetwork/common"
|
|
@@ -36,7 +36,8 @@ var diagPaths2Func = map[string]HTTPHandlerFunc{
|
|
|
// Server when the debug is enabled exposes a
|
|
|
// This data structure is protected by the Agent mutex so does not require and additional mutex here
|
|
|
type Server struct {
|
|
|
- sk net.Listener
|
|
|
+ enable int32
|
|
|
+ srv *http.Server
|
|
|
port int
|
|
|
mux *http.ServeMux
|
|
|
registeredHanders map[string]bool
|
|
@@ -71,6 +72,10 @@ func (n *Server) RegisterHandler(ctx interface{}, hdlrs map[string]HTTPHandlerFu
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func (n *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
+ n.mux.ServeHTTP(w, r)
|
|
|
+}
|
|
|
+
|
|
|
// EnableDebug opens a TCP socket to debug the passed network DB
|
|
|
func (n *Server) EnableDebug(ip string, port int) {
|
|
|
n.Lock()
|
|
@@ -78,37 +83,41 @@ func (n *Server) EnableDebug(ip string, port int) {
|
|
|
|
|
|
n.port = port
|
|
|
|
|
|
- if n.sk != nil {
|
|
|
+ if n.enable == 1 {
|
|
|
logrus.Info("The server is already up and running")
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- logrus.Infof("Starting the server listening on %d for commands", port)
|
|
|
- // Create the socket
|
|
|
- var err error
|
|
|
- n.sk, err = net.Listen("tcp", fmt.Sprintf("%s:%d", ip, port))
|
|
|
- if err != nil {
|
|
|
- log.Fatal(err)
|
|
|
- }
|
|
|
+ logrus.Infof("Starting the diagnose server listening on %d for commands", port)
|
|
|
+ srv := &http.Server{Addr: fmt.Sprintf("127.0.0.1:%d", port), Handler: n}
|
|
|
+ n.srv = srv
|
|
|
+ n.enable = 1
|
|
|
+ go func(n *Server) {
|
|
|
+ // Ingore ErrServerClosed that is returned on the Shutdown call
|
|
|
+ if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
|
+ logrus.Errorf("ListenAndServe error: %s", err)
|
|
|
+ atomic.SwapInt32(&n.enable, 0)
|
|
|
+ }
|
|
|
+ }(n)
|
|
|
|
|
|
- go func() {
|
|
|
- http.Serve(n.sk, n.mux)
|
|
|
- }()
|
|
|
}
|
|
|
|
|
|
// DisableDebug stop the dubug and closes the tcp socket
|
|
|
func (n *Server) DisableDebug() {
|
|
|
n.Lock()
|
|
|
defer n.Unlock()
|
|
|
- n.sk.Close()
|
|
|
- n.sk = nil
|
|
|
+
|
|
|
+ n.srv.Shutdown(context.Background())
|
|
|
+ n.srv = nil
|
|
|
+ n.enable = 0
|
|
|
+ logrus.Info("Disabling the diagnose server")
|
|
|
}
|
|
|
|
|
|
// IsDebugEnable returns true when the debug is enabled
|
|
|
func (n *Server) IsDebugEnable() bool {
|
|
|
n.Lock()
|
|
|
defer n.Unlock()
|
|
|
- return n.sk != nil
|
|
|
+ return n.enable == 1
|
|
|
}
|
|
|
|
|
|
func notImplemented(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
|
@@ -197,6 +206,7 @@ func ParseHTTPFormOptions(r *http.Request) (bool, *JSONOutput) {
|
|
|
func HTTPReply(w http.ResponseWriter, r *HTTPResult, j *JSONOutput) (int, error) {
|
|
|
var response []byte
|
|
|
if j.enable {
|
|
|
+ w.Header().Set("Content-Type", "application/json")
|
|
|
var err error
|
|
|
if j.prettyPrint {
|
|
|
response, err = json.MarshalIndent(r, "", " ")
|