Przeglądaj źródła

Merge pull request #2032 from fcrisciani/debug-client

Diagnostic client
Flavio Crisciani 7 lat temu
rodzic
commit
2459e6fbd3

+ 1 - 0
libnetwork/Makefile

@@ -28,6 +28,7 @@ build-local:
 	@mkdir -p "bin"
 	@mkdir -p "bin"
 	go build -tags experimental -o "bin/dnet" ./cmd/dnet
 	go build -tags experimental -o "bin/dnet" ./cmd/dnet
 	go build -o "bin/docker-proxy" ./cmd/proxy
 	go build -o "bin/docker-proxy" ./cmd/proxy
+	GOOS=linux go build -o "./cmd/diagnostic/diagnosticClient" ./cmd/diagnostic
 
 
 clean:
 clean:
 	@echo "🐳 $@"
 	@echo "🐳 $@"

+ 2 - 2
libnetwork/agent.go

@@ -297,8 +297,8 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr, d
 		return err
 		return err
 	}
 	}
 
 
-	// Register the diagnose handlers
-	c.DiagnoseServer.RegisterHandler(nDB, networkdb.NetDbPaths2Func)
+	// Register the diagnostic handlers
+	c.DiagnosticServer.RegisterHandler(nDB, networkdb.NetDbPaths2Func)
 
 
 	var cancelList []func()
 	var cancelList []func()
 	ch, cancel := nDB.Watch(libnetworkEPTable, "", "")
 	ch, cancel := nDB.Watch(libnetworkEPTable, "", "")

+ 4 - 0
libnetwork/cmd/diagnostic/Dockerfile.client

@@ -0,0 +1,4 @@
+FROM alpine
+RUN apk add --no-cache curl
+COPY diagnosticClient /usr/local/bin/diagnosticClient
+ENTRYPOINT ["/usr/local/bin/diagnosticClient"]

+ 4 - 0
libnetwork/cmd/diagnostic/Dockerfile.dind

@@ -0,0 +1,4 @@
+FROM docker:17.12-dind
+RUN apk add --no-cache curl
+COPY daemon.json /etc/docker/daemon.json
+COPY diagnosticClient /usr/local/bin/diagnosticClient

+ 252 - 0
libnetwork/cmd/diagnostic/README.md

@@ -0,0 +1,252 @@
+---
+description: Learn to use the built-in network debugger to debug overlay networking problems
+keywords: network, troubleshooting, debug
+title: Debug overlay or swarm networking issues
+---
+
+**WARNING**
+This tool can change the internal state of the libnetwork API, be really mindful
+on its use and read carefully the following guide. Improper use of it will damage
+or permanently destroy the network configuration.
+
+
+Docker CE 17.12 and higher introduce a network debugging tool designed to help
+debug issues with overlay networks and swarm services running on Linux hosts.
+When enabled, a network diagnostic server listens on the specified port and
+provides diagnostic information. The network debugging tool should only be
+started to debug specific issues, and should not be left running all the time.
+
+Information about networks is stored in the database, which can be examined using
+the API. Currently the database contains information about the overlay network
+as well as the service discovery data.
+
+The Docker API exposes endpoints to query and control the network debugging
+tool. CLI integration is provided as a preview, but the implementation is not
+yet considered stable and commands and options may change without notice.
+
+The tool is available into 2 forms:
+1) client only: dockereng/network-diagnostic:onlyclient
+2) docker in docker version: dockereng/network-diagnostic:17.12-dind
+The latter allows to use the tool with a cluster running an engine older than 17.12
+
+## Enable the diagnostic server
+
+The tool currently only works on Docker hosts running on Linux. To enable it on a node
+follow the step below.
+
+1.  Set the `network-diagnostic-port` to a port which is free on the Docker
+    host, in the `/etc/docker/daemon.json` configuration file.
+
+    ```json
+    “network-diagnostic-port”: <port>
+    ```
+
+2.  Get the process ID (PID) of the `dockerd` process. It is the second field in
+    the output, and is typically a number from 2 to 6 digits long.
+
+    ```bash
+    $ ps aux |grep dockerd | grep -v grep
+    ```
+
+3.  Reload the Docker configuration without restarting Docker, by sending the
+    `HUP` signal to the PID you found in the previous step.
+
+    ```bash
+    kill -HUP <pid-of-dockerd>
+    ```
+
+If systemd is used the command `systemctl reload docker` will be enough
+
+
+A message like the following will appear in the Docker host logs:
+
+```none
+Starting the diagnostic server listening on <port> for commands
+```
+
+## Disable the diagnostic tool
+
+Repeat these steps for each node participating in the swarm.
+
+1.  Remove the `network-diagnostic-port` key from the `/etc/docker/daemon.json`
+    configuration file.
+
+2.  Get the process ID (PID) of the `dockerd` process. It is the second field in
+    the output, and is typically a number from 2 to 6 digits long.
+
+    ```bash
+    $ ps aux |grep dockerd | grep -v grep
+    ```
+
+3.  Reload the Docker configuration without restarting Docker, by sending the
+    `HUP` signal to the PID you found in the previous step.
+
+    ```bash
+    kill -HUP <pid-of-dockerd>
+    ```
+
+A message like the following will appear in the Docker host logs:
+
+```none
+Disabling the diagnostic server
+```
+
+## Access the diagnostic tool's API
+
+The network diagnostic tool exposes its own RESTful API. To access the API,
+send a HTTP request to the port where the tool is listening. The following
+commands assume the tool is listening on port 2000.
+
+Examples are not given for every endpoint.
+
+### Get help
+
+```bash
+$ curl localhost:2000/help
+
+OK
+/updateentry
+/getentry
+/gettable
+/leavenetwork
+/createentry
+/help
+/clusterpeers
+/ready
+/joinnetwork
+/deleteentry
+/networkpeers
+/
+/join
+```
+
+### Join or leave the network database cluster
+
+```bash
+$ curl localhost:2000/join?members=ip1,ip2,...
+```
+
+```bash
+$ curl localhost:2000/leave?members=ip1,ip2,...
+```
+
+`ip1`, `ip2`, ... are the swarm node ips (usually one is enough)
+
+### Join or leave a network
+
+```bash
+$ curl localhost:2000/joinnetwork?nid=<network id>
+```
+
+```bash
+$ curl localhost:2000/leavenetwork?nid=<network id>
+```
+
+`network id` can be retrieved on the manager with `docker network ls --no-trunc` and has
+to be the full length identifier
+
+### List cluster peers
+
+```bash
+$ curl localhost:2000/clusterpeers
+```
+
+### List nodes connected to a given network
+
+```bash
+$ curl localhost:2000/networkpeers?nid=<network id>
+```
+`network id` can be retrieved on the manager with `docker network ls --no-trunc` and has
+to be the full length identifier
+
+### Dump database tables
+
+The tables are called `endpoint_table` and `overlay_peer_table`.
+The `overlay_peer_table` contains all the overlay forwarding information
+The `endpoint_table` contains all the service discovery information
+
+```bash
+$ curl localhost:2000/gettable?nid=<network id>&tname=<table name>
+```
+
+### Interact with a specific database table
+
+The tables are called `endpoint_table` and `overlay_peer_table`.
+
+```bash
+$ curl localhost:2000/<method>?nid=<network id>&tname=<table name>&key=<key>[&value=<value>]
+```
+
+Note:
+operations on tables have node ownership, this means that are going to remain persistent till
+the node that inserted them is part of the cluster
+
+## Access the diagnostic tool's CLI
+
+The CLI is provided as a preview and is not yet stable. Commands or options may
+change at any time.
+
+The CLI executable is called `diagnosticClient` and is made available using a
+standalone container.
+
+`docker run --net host dockereng/network-diagnostic:onlyclient -v -net <full network id> -t sd`
+
+The following flags are supported:
+
+| Flag          | Description                                     |
+|---------------|-------------------------------------------------|
+| -t <string>   | Table one of `sd` or `overlay`.                 |
+| -ip <string>  | The IP address to query. Defaults to 127.0.0.1. |
+| -net <string> | The target network ID.                          |
+| -port <int>   | The target port. (default port is 2000)         |
+| -v            | Enable verbose output.                          |
+
+### Container version of the diagnostic tool
+
+The CLI is provided as a container with a 17.12 engine that needs to run using privileged mode.
+*NOTE*
+Remember that table operations have ownership, so any `create entry` will be persistent till
+the diagnostic container is part of the swarm.
+
+1.  Make sure that the node where the diagnostic client will run is not part of the swarm, if so do `docker swarm leave -f`
+
+2.  To run the container, use a command like the following:
+
+    ```bash
+    $ docker container run --name net-diagnostic -d --privileged --network host dockereng/network-diagnostic:17.12-dind
+    ```
+
+3.  Connect to the container using `docker exec -it <container-ID> sh`,
+    and start the server using the following command:
+
+    ```bash
+    $ kill -HUP 1
+    ```
+
+4.  Join the diagnostic container to the swarm, then run the diagnostic CLI within the container.
+
+    ```bash
+    $ ./diagnosticClient <flags>...
+    ```
+
+4.  When finished debugging, leave the swarm and stop the container.
+
+### Examples
+
+The following commands dump the service discovery table and verify node
+ownership.
+
+*NOTE*
+Remember to use the full network ID, you can easily find that with `docker network ls --no-trunc`
+
+**Service discovery and load balancer:**
+
+```bash
+$ diagnostiClient -c sd -v -net n8a8ie6tb3wr2e260vxj8ncy4
+```
+
+**Overlay network:**
+
+```bash
+$ diagnostiClient -port 2001 -c overlay -v -net n8a8ie6tb3wr2e260vxj8ncy4
+```

+ 4 - 0
libnetwork/cmd/diagnostic/daemon.json

@@ -0,0 +1,4 @@
+{
+  "debug": true,
+  "network-diagnostic-port": 2000
+}

+ 191 - 0
libnetwork/cmd/diagnostic/main.go

@@ -0,0 +1,191 @@
+package main
+
+import (
+	"bufio"
+	"encoding/base64"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"strings"
+
+	"github.com/docker/libnetwork"
+	"github.com/docker/libnetwork/diagnostic"
+	"github.com/docker/libnetwork/drivers/overlay"
+	"github.com/sirupsen/logrus"
+)
+
+const (
+	readyPath    = "http://%s:%d/ready"
+	joinNetwork  = "http://%s:%d/joinnetwork?nid=%s"
+	leaveNetwork = "http://%s:%d/leavenetwork?nid=%s"
+	clusterPeers = "http://%s:%d/clusterpeers?json"
+	networkPeers = "http://%s:%d/networkpeers?nid=%s&json"
+	dumpTable    = "http://%s:%d/gettable?nid=%s&tname=%s&json"
+	deleteEntry  = "http://%s:%d/deleteentry?nid=%s&tname=%s&key=%s&json"
+)
+
+func httpIsOk(body io.ReadCloser) {
+	b, err := ioutil.ReadAll(body)
+	if err != nil {
+		logrus.Fatalf("Failed the body parse %s", err)
+	}
+	if !strings.Contains(string(b), "OK") {
+		logrus.Fatalf("Server not ready %s", b)
+	}
+	body.Close()
+}
+
+func main() {
+	ipPtr := flag.String("ip", "127.0.0.1", "ip address")
+	portPtr := flag.Int("port", 2000, "port")
+	networkPtr := flag.String("net", "", "target network")
+	tablePtr := flag.String("t", "", "table to process <sd/overlay>")
+	remediatePtr := flag.Bool("r", false, "perform remediation deleting orphan entries")
+	verbosePtr := flag.Bool("v", false, "verbose output")
+
+	flag.Parse()
+
+	if *verbosePtr {
+		logrus.SetLevel(logrus.DebugLevel)
+	}
+
+	logrus.Infof("Connecting to %s:%d checking ready", *ipPtr, *portPtr)
+	resp, err := http.Get(fmt.Sprintf(readyPath, *ipPtr, *portPtr))
+	if err != nil {
+		logrus.WithError(err).Fatalf("The connection failed")
+	}
+	httpIsOk(resp.Body)
+
+	clusterPeers := fetchNodePeers(*ipPtr, *portPtr, "")
+	var networkPeers map[string]string
+	var joinedNetwork bool
+	if *networkPtr != "" {
+		logrus.Infof("Joining the network:%s", *networkPtr)
+		resp, err = http.Get(fmt.Sprintf(joinNetwork, *ipPtr, *portPtr, *networkPtr))
+		if err != nil {
+			logrus.WithError(err).Fatalf("Failed joining the network")
+		}
+		httpIsOk(resp.Body)
+		networkPeers = fetchNodePeers(*ipPtr, *portPtr, *networkPtr)
+		joinedNetwork = true
+	}
+
+	switch *tablePtr {
+	case "sd":
+		fetchTable(*ipPtr, *portPtr, *networkPtr, "endpoint_table", clusterPeers, networkPeers, *remediatePtr)
+	case "overlay":
+		fetchTable(*ipPtr, *portPtr, *networkPtr, "overlay_peer_table", clusterPeers, networkPeers, *remediatePtr)
+	}
+
+	if joinedNetwork {
+		resp, err = http.Get(fmt.Sprintf(leaveNetwork, *ipPtr, *portPtr, *networkPtr))
+		if err != nil {
+			logrus.WithError(err).Fatalf("Failed leaving the network")
+		}
+		httpIsOk(resp.Body)
+	}
+}
+
+func fetchNodePeers(ip string, port int, network string) map[string]string {
+	logrus.Infof("Fetch peers %s", network)
+	var path string
+	if network != "" {
+		path = fmt.Sprintf(networkPeers, ip, port, network)
+	} else {
+		path = fmt.Sprintf(clusterPeers, ip, port)
+	}
+
+	resp, err := http.Get(path)
+	if err != nil {
+		logrus.WithError(err).Fatalf("Failed fetching path")
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		logrus.WithError(err).Fatalf("Failed the body parse")
+	}
+
+	output := diagnostic.HTTPResult{Details: &diagnostic.TablePeersResult{}}
+	err = json.Unmarshal(body, &output)
+	if err != nil {
+		logrus.WithError(err).Fatalf("Failed the json unmarshalling")
+	}
+
+	logrus.Debugf("Parsing JSON response")
+	result := make(map[string]string, output.Details.(*diagnostic.TablePeersResult).Length)
+	for _, v := range output.Details.(*diagnostic.TablePeersResult).Elements {
+		logrus.Debugf("name:%s ip:%s", v.Name, v.IP)
+		result[v.Name] = v.IP
+	}
+	return result
+}
+
+func fetchTable(ip string, port int, network, tableName string, clusterPeers, networkPeers map[string]string, remediate bool) {
+	logrus.Infof("Fetch %s table and check owners", tableName)
+	resp, err := http.Get(fmt.Sprintf(dumpTable, ip, port, network, tableName))
+	if err != nil {
+		logrus.WithError(err).Fatalf("Failed fetching endpoint table")
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		logrus.WithError(err).Fatalf("Failed the body parse")
+	}
+
+	output := diagnostic.HTTPResult{Details: &diagnostic.TableEndpointsResult{}}
+	err = json.Unmarshal(body, &output)
+	if err != nil {
+		logrus.WithError(err).Fatalf("Failed the json unmarshalling")
+	}
+
+	logrus.Debug("Parsing data structures")
+	var orphanKeys []string
+	for _, v := range output.Details.(*diagnostic.TableEndpointsResult).Elements {
+		decoded, err := base64.StdEncoding.DecodeString(v.Value)
+		if err != nil {
+			logrus.WithError(err).Errorf("Failed decoding entry")
+			continue
+		}
+		switch tableName {
+		case "endpoint_table":
+			var elem libnetwork.EndpointRecord
+			elem.Unmarshal(decoded)
+			logrus.Debugf("key:%s value:%+v owner:%s", v.Key, elem, v.Owner)
+		case "overlay_peer_table":
+			var elem overlay.PeerRecord
+			elem.Unmarshal(decoded)
+			logrus.Debugf("key:%s value:%+v owner:%s", v.Key, elem, v.Owner)
+		}
+
+		if _, ok := networkPeers[v.Owner]; !ok {
+			logrus.Warnf("The element with key:%s does not belong to any node on this network", v.Key)
+			orphanKeys = append(orphanKeys, v.Key)
+		}
+		if _, ok := clusterPeers[v.Owner]; !ok {
+			logrus.Warnf("The element with key:%s does not belong to any node on this cluster", v.Key)
+		}
+	}
+
+	if len(orphanKeys) > 0 && remediate {
+		logrus.Warnf("The following keys:%v results as orphan, do you want to proceed with the deletion (this operation is irreversible)? [Yes/No]", orphanKeys)
+		reader := bufio.NewReader(os.Stdin)
+		text, _ := reader.ReadString('\n')
+		text = strings.Replace(text, "\n", "", -1)
+		if strings.Compare(text, "Yes") == 0 {
+			for _, k := range orphanKeys {
+				resp, err := http.Get(fmt.Sprintf(deleteEntry, ip, port, network, tableName, k))
+				if err != nil {
+					logrus.WithError(err).Errorf("Failed deleting entry k:%s", k)
+					break
+				}
+				resp.Body.Close()
+			}
+		} else {
+			logrus.Infof("Deletion skipped")
+		}
+	}
+}

+ 28 - 28
libnetwork/controller.go

@@ -61,7 +61,7 @@ import (
 	"github.com/docker/libnetwork/cluster"
 	"github.com/docker/libnetwork/cluster"
 	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/datastore"
 	"github.com/docker/libnetwork/datastore"
-	"github.com/docker/libnetwork/diagnose"
+	"github.com/docker/libnetwork/diagnostic"
 	"github.com/docker/libnetwork/discoverapi"
 	"github.com/docker/libnetwork/discoverapi"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/drvregistry"
 	"github.com/docker/libnetwork/drvregistry"
@@ -136,12 +136,12 @@ type NetworkController interface {
 	// SetKeys configures the encryption key for gossip and overlay data path
 	// SetKeys configures the encryption key for gossip and overlay data path
 	SetKeys(keys []*types.EncryptionKey) error
 	SetKeys(keys []*types.EncryptionKey) error
 
 
-	// StartDiagnose start the network diagnose mode
-	StartDiagnose(port int)
-	// StopDiagnose start the network diagnose mode
-	StopDiagnose()
-	// IsDiagnoseEnabled returns true if the diagnose is enabled
-	IsDiagnoseEnabled() bool
+	// StartDiagnostic start the network diagnostic mode
+	StartDiagnostic(port int)
+	// StopDiagnostic start the network diagnostic mode
+	StopDiagnostic()
+	// IsDiagnosticEnabled returns true if the diagnostic is enabled
+	IsDiagnosticEnabled() bool
 }
 }
 
 
 // NetworkWalker is a client provided function which will be used to walk the Networks.
 // NetworkWalker is a client provided function which will be used to walk the Networks.
@@ -176,7 +176,7 @@ type controller struct {
 	agentStopDone          chan struct{}
 	agentStopDone          chan struct{}
 	keys                   []*types.EncryptionKey
 	keys                   []*types.EncryptionKey
 	clusterConfigAvailable bool
 	clusterConfigAvailable bool
-	DiagnoseServer         *diagnose.Server
+	DiagnosticServer       *diagnostic.Server
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
@@ -188,16 +188,16 @@ type initializer struct {
 // New creates a new instance of network controller.
 // New creates a new instance of network controller.
 func New(cfgOptions ...config.Option) (NetworkController, error) {
 func New(cfgOptions ...config.Option) (NetworkController, error) {
 	c := &controller{
 	c := &controller{
-		id:              stringid.GenerateRandomID(),
-		cfg:             config.ParseConfigOptions(cfgOptions...),
-		sandboxes:       sandboxTable{},
-		svcRecords:      make(map[string]svcInfo),
-		serviceBindings: make(map[serviceKey]*service),
-		agentInitDone:   make(chan struct{}),
-		networkLocker:   locker.New(),
-		DiagnoseServer:  diagnose.New(),
+		id:               stringid.GenerateRandomID(),
+		cfg:              config.ParseConfigOptions(cfgOptions...),
+		sandboxes:        sandboxTable{},
+		svcRecords:       make(map[string]svcInfo),
+		serviceBindings:  make(map[serviceKey]*service),
+		agentInitDone:    make(chan struct{}),
+		networkLocker:    locker.New(),
+		DiagnosticServer: diagnostic.New(),
 	}
 	}
-	c.DiagnoseServer.Init()
+	c.DiagnosticServer.Init()
 
 
 	if err := c.initStores(); err != nil {
 	if err := c.initStores(); err != nil {
 		return nil, err
 		return nil, err
@@ -1307,27 +1307,27 @@ func (c *controller) Stop() {
 	osl.GC()
 	osl.GC()
 }
 }
 
 
-// StartDiagnose start the network diagnose mode
-func (c *controller) StartDiagnose(port int) {
+// StartDiagnostic start the network dias mode
+func (c *controller) StartDiagnostic(port int) {
 	c.Lock()
 	c.Lock()
-	if !c.DiagnoseServer.IsDebugEnable() {
-		c.DiagnoseServer.EnableDebug("127.0.0.1", port)
+	if !c.DiagnosticServer.IsDiagnosticEnabled() {
+		c.DiagnosticServer.EnableDiagnostic("127.0.0.1", port)
 	}
 	}
 	c.Unlock()
 	c.Unlock()
 }
 }
 
 
-// StopDiagnose start the network diagnose mode
-func (c *controller) StopDiagnose() {
+// StopDiagnostic start the network dias mode
+func (c *controller) StopDiagnostic() {
 	c.Lock()
 	c.Lock()
-	if c.DiagnoseServer.IsDebugEnable() {
-		c.DiagnoseServer.DisableDebug()
+	if c.DiagnosticServer.IsDiagnosticEnabled() {
+		c.DiagnosticServer.DisableDiagnostic()
 	}
 	}
 	c.Unlock()
 	c.Unlock()
 }
 }
 
 
-// IsDiagnoseEnabled returns true if the diagnose is enabled
-func (c *controller) IsDiagnoseEnabled() bool {
+// IsDiagnosticEnabled returns true if the dias is enabled
+func (c *controller) IsDiagnosticEnabled() bool {
 	c.Lock()
 	c.Lock()
 	defer c.Unlock()
 	defer c.Unlock()
-	return c.DiagnoseServer.IsDebugEnable()
+	return c.DiagnosticServer.IsDiagnosticEnabled()
 }
 }

+ 14 - 14
libnetwork/diagnose/server.go → libnetwork/diagnostic/server.go

@@ -1,4 +1,4 @@
-package diagnose
+package diagnostic
 
 
 import (
 import (
 	"context"
 	"context"
@@ -44,7 +44,7 @@ type Server struct {
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
-// New creates a new diagnose server
+// New creates a new diagnostic server
 func New() *Server {
 func New() *Server {
 	return &Server{
 	return &Server{
 		registeredHanders: make(map[string]bool),
 		registeredHanders: make(map[string]bool),
@@ -78,8 +78,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	s.mux.ServeHTTP(w, r)
 	s.mux.ServeHTTP(w, r)
 }
 }
 
 
-// EnableDebug opens a TCP socket to debug the passed network DB
-func (s *Server) EnableDebug(ip string, port int) {
+// EnableDiagnostic opens a TCP socket to debug the passed network DB
+func (s *Server) EnableDiagnostic(ip string, port int) {
 	s.Lock()
 	s.Lock()
 	defer s.Unlock()
 	defer s.Unlock()
 
 
@@ -90,7 +90,7 @@ func (s *Server) EnableDebug(ip string, port int) {
 		return
 		return
 	}
 	}
 
 
-	logrus.Infof("Starting the diagnose server listening on %d for commands", port)
+	logrus.Infof("Starting the diagnostic server listening on %d for commands", port)
 	srv := &http.Server{Addr: fmt.Sprintf("%s:%d", ip, port), Handler: s}
 	srv := &http.Server{Addr: fmt.Sprintf("%s:%d", ip, port), Handler: s}
 	s.srv = srv
 	s.srv = srv
 	s.enable = 1
 	s.enable = 1
@@ -103,19 +103,19 @@ func (s *Server) EnableDebug(ip string, port int) {
 	}(s)
 	}(s)
 }
 }
 
 
-// DisableDebug stop the dubug and closes the tcp socket
-func (s *Server) DisableDebug() {
+// DisableDiagnostic stop the dubug and closes the tcp socket
+func (s *Server) DisableDiagnostic() {
 	s.Lock()
 	s.Lock()
 	defer s.Unlock()
 	defer s.Unlock()
 
 
 	s.srv.Shutdown(context.Background())
 	s.srv.Shutdown(context.Background())
 	s.srv = nil
 	s.srv = nil
 	s.enable = 0
 	s.enable = 0
-	logrus.Info("Disabling the diagnose server")
+	logrus.Info("Disabling the diagnostic server")
 }
 }
 
 
-// IsDebugEnable returns true when the debug is enabled
-func (s *Server) IsDebugEnable() bool {
+// IsDiagnosticEnabled returns true when the debug is enabled
+func (s *Server) IsDiagnosticEnabled() bool {
 	s.Lock()
 	s.Lock()
 	defer s.Unlock()
 	defer s.Unlock()
 	return s.enable == 1
 	return s.enable == 1
@@ -127,7 +127,7 @@ func notImplemented(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	rsp := WrongCommand("not implemented", fmt.Sprintf("URL path: %s no method implemented check /help\n", r.URL.Path))
 	rsp := WrongCommand("not implemented", fmt.Sprintf("URL path: %s no method implemented check /help\n", r.URL.Path))
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("command not implemented done")
 	log.Info("command not implemented done")
 
 
 	HTTPReply(w, rsp, json)
 	HTTPReply(w, rsp, json)
@@ -138,7 +138,7 @@ func help(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	_, json := ParseHTTPFormOptions(r)
 	_, json := ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("help done")
 	log.Info("help done")
 
 
 	n, ok := ctx.(*Server)
 	n, ok := ctx.(*Server)
@@ -156,7 +156,7 @@ func ready(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	_, json := ParseHTTPFormOptions(r)
 	_, json := ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("ready done")
 	log.Info("ready done")
 	HTTPReply(w, CommandSucceed(&StringCmd{Info: "OK"}), json)
 	HTTPReply(w, CommandSucceed(&StringCmd{Info: "OK"}), json)
 }
 }
@@ -166,7 +166,7 @@ func stackTrace(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	_, json := ParseHTTPFormOptions(r)
 	_, json := ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("stack trace")
 	log.Info("stack trace")
 
 
 	path, err := stackdump.DumpStacks("/tmp/")
 	path, err := stackdump.DumpStacks("/tmp/")

+ 2 - 2
libnetwork/diagnose/types.go → libnetwork/diagnostic/types.go

@@ -1,4 +1,4 @@
-package diagnose
+package diagnostic
 
 
 import "fmt"
 import "fmt"
 
 
@@ -31,7 +31,7 @@ func WrongCommand(message, usage string) *HTTPResult {
 	}
 	}
 }
 }
 
 
-// HTTPResult Diagnose Server HTTP result operation
+// HTTPResult Diagnostic Server HTTP result operation
 type HTTPResult struct {
 type HTTPResult struct {
 	Message string          `json:"message"`
 	Message string          `json:"message"`
 	Details StringInterface `json:"details"`
 	Details StringInterface `json:"details"`

+ 3 - 0
libnetwork/networkdb/networkdb.go

@@ -328,6 +328,9 @@ func (nDB *NetworkDB) GetEntry(tname, nid, key string) ([]byte, error) {
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
+	if entry != nil && entry.deleting {
+		return nil, types.NotFoundErrorf("entry in table %s network id %s and key %s deleted and pending garbage collection", tname, nid, key)
+	}
 
 
 	return entry.value, nil
 	return entry.value, nil
 }
 }

+ 7 - 0
libnetwork/networkdb/networkdb_test.go

@@ -7,6 +7,7 @@ import (
 	"log"
 	"log"
 	"net"
 	"net"
 	"os"
 	"os"
+	"strings"
 	"sync/atomic"
 	"sync/atomic"
 	"testing"
 	"testing"
 	"time"
 	"time"
@@ -446,6 +447,12 @@ func TestNetworkDBCRUDMediumCluster(t *testing.T) {
 		dbs[i].verifyEntryExistence(t, "test_table", "network1", "test_key", "", false)
 		dbs[i].verifyEntryExistence(t, "test_table", "network1", "test_key", "", false)
 	}
 	}
 
 
+	for i := 1; i < n; i++ {
+		_, err = dbs[i].GetEntry("test_table", "network1", "test_key")
+		assert.Error(t, err)
+		assert.True(t, strings.Contains(err.Error(), "deleted and pending garbage collection"))
+	}
+
 	closeNetworkDBInstances(dbs)
 	closeNetworkDBInstances(dbs)
 }
 }
 
 

+ 89 - 89
libnetwork/networkdb/networkdbdiagnose.go → libnetwork/networkdb/networkdbdiagnostic.go

@@ -7,7 +7,7 @@ import (
 	"strings"
 	"strings"
 
 
 	"github.com/docker/libnetwork/common"
 	"github.com/docker/libnetwork/common"
-	"github.com/docker/libnetwork/diagnose"
+	"github.com/docker/libnetwork/diagnostic"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 )
 )
 
 
@@ -17,7 +17,7 @@ const (
 )
 )
 
 
 // NetDbPaths2Func TODO
 // NetDbPaths2Func TODO
-var NetDbPaths2Func = map[string]diagnose.HTTPHandlerFunc{
+var NetDbPaths2Func = map[string]diagnostic.HTTPHandlerFunc{
 	"/join":         dbJoin,
 	"/join":         dbJoin,
 	"/networkpeers": dbPeers,
 	"/networkpeers": dbPeers,
 	"/clusterpeers": dbClusterPeers,
 	"/clusterpeers": dbClusterPeers,
@@ -32,17 +32,17 @@ var NetDbPaths2Func = map[string]diagnose.HTTPHandlerFunc{
 
 
 func dbJoin(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbJoin(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	_, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	_, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("join cluster")
 	log.Info("join cluster")
 
 
 	if len(r.Form["members"]) < 1 {
 	if len(r.Form["members"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?members=ip1,ip2,...", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?members=ip1,ip2,...", r.URL.Path))
 		log.Error("join cluster failed, wrong input")
 		log.Error("join cluster failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -50,88 +50,88 @@ func dbJoin(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	if ok {
 	if ok {
 		err := nDB.Join(strings.Split(r.Form["members"][0], ","))
 		err := nDB.Join(strings.Split(r.Form["members"][0], ","))
 		if err != nil {
 		if err != nil {
-			rsp := diagnose.FailCommand(fmt.Errorf("%s error in the DB join %s", r.URL.Path, err))
+			rsp := diagnostic.FailCommand(fmt.Errorf("%s error in the DB join %s", r.URL.Path, err))
 			log.WithError(err).Error("join cluster failed")
 			log.WithError(err).Error("join cluster failed")
-			diagnose.HTTPReply(w, rsp, json)
+			diagnostic.HTTPReply(w, rsp, json)
 			return
 			return
 		}
 		}
 
 
 		log.Info("join cluster done")
 		log.Info("join cluster done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(nil), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	_, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	_, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("network peers")
 	log.Info("network peers")
 
 
 	if len(r.Form["nid"]) < 1 {
 	if len(r.Form["nid"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=test", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=test", r.URL.Path))
 		log.Error("network peers failed, wrong input")
 		log.Error("network peers failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
 	nDB, ok := ctx.(*NetworkDB)
 	nDB, ok := ctx.(*NetworkDB)
 	if ok {
 	if ok {
 		peers := nDB.Peers(r.Form["nid"][0])
 		peers := nDB.Peers(r.Form["nid"][0])
-		rsp := &diagnose.TableObj{Length: len(peers)}
+		rsp := &diagnostic.TableObj{Length: len(peers)}
 		for i, peerInfo := range peers {
 		for i, peerInfo := range peers {
-			rsp.Elements = append(rsp.Elements, &diagnose.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP})
+			rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP})
 		}
 		}
 		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("network peers done")
 		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("network peers done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(rsp), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbClusterPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbClusterPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	_, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	_, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("cluster peers")
 	log.Info("cluster peers")
 
 
 	nDB, ok := ctx.(*NetworkDB)
 	nDB, ok := ctx.(*NetworkDB)
 	if ok {
 	if ok {
 		peers := nDB.ClusterPeers()
 		peers := nDB.ClusterPeers()
-		rsp := &diagnose.TableObj{Length: len(peers)}
+		rsp := &diagnostic.TableObj{Length: len(peers)}
 		for i, peerInfo := range peers {
 		for i, peerInfo := range peers {
-			rsp.Elements = append(rsp.Elements, &diagnose.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP})
+			rsp.Elements = append(rsp.Elements, &diagnostic.PeerEntryObj{Index: i, Name: peerInfo.Name, IP: peerInfo.IP})
 		}
 		}
 		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("cluster peers done")
 		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("cluster peers done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(rsp), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbCreateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbCreateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	unsafe, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("create entry")
 	log.Info("create entry")
 
 
 	if len(r.Form["tname"]) < 1 ||
 	if len(r.Form["tname"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["key"]) < 1 ||
 		len(r.Form["key"]) < 1 ||
 		len(r.Form["value"]) < 1 {
 		len(r.Form["value"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path))
 		log.Error("create entry failed, wrong input")
 		log.Error("create entry failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -145,7 +145,7 @@ func dbCreateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 		decodedValue, err = base64.StdEncoding.DecodeString(value)
 		decodedValue, err = base64.StdEncoding.DecodeString(value)
 		if err != nil {
 		if err != nil {
 			log.WithError(err).Error("create entry failed")
 			log.WithError(err).Error("create entry failed")
-			diagnose.HTTPReply(w, diagnose.FailCommand(err), json)
+			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
 			return
 			return
 		}
 		}
 	}
 	}
@@ -153,34 +153,34 @@ func dbCreateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	nDB, ok := ctx.(*NetworkDB)
 	nDB, ok := ctx.(*NetworkDB)
 	if ok {
 	if ok {
 		if err := nDB.CreateEntry(tname, nid, key, decodedValue); err != nil {
 		if err := nDB.CreateEntry(tname, nid, key, decodedValue); err != nil {
-			rsp := diagnose.FailCommand(err)
-			diagnose.HTTPReply(w, rsp, json)
+			rsp := diagnostic.FailCommand(err)
+			diagnostic.HTTPReply(w, rsp, json)
 			log.WithError(err).Error("create entry failed")
 			log.WithError(err).Error("create entry failed")
 			return
 			return
 		}
 		}
 		log.Info("create entry done")
 		log.Info("create entry done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(nil), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbUpdateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbUpdateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	unsafe, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("update entry")
 	log.Info("update entry")
 
 
 	if len(r.Form["tname"]) < 1 ||
 	if len(r.Form["tname"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["key"]) < 1 ||
 		len(r.Form["key"]) < 1 ||
 		len(r.Form["value"]) < 1 {
 		len(r.Form["value"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k&value=v", r.URL.Path))
 		log.Error("update entry failed, wrong input")
 		log.Error("update entry failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -194,7 +194,7 @@ func dbUpdateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 		decodedValue, err = base64.StdEncoding.DecodeString(value)
 		decodedValue, err = base64.StdEncoding.DecodeString(value)
 		if err != nil {
 		if err != nil {
 			log.WithError(err).Error("update entry failed")
 			log.WithError(err).Error("update entry failed")
-			diagnose.HTTPReply(w, diagnose.FailCommand(err), json)
+			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
 			return
 			return
 		}
 		}
 	}
 	}
@@ -203,31 +203,31 @@ func dbUpdateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	if ok {
 	if ok {
 		if err := nDB.UpdateEntry(tname, nid, key, decodedValue); err != nil {
 		if err := nDB.UpdateEntry(tname, nid, key, decodedValue); err != nil {
 			log.WithError(err).Error("update entry failed")
 			log.WithError(err).Error("update entry failed")
-			diagnose.HTTPReply(w, diagnose.FailCommand(err), json)
+			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
 			return
 			return
 		}
 		}
 		log.Info("update entry done")
 		log.Info("update entry done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(nil), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbDeleteEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbDeleteEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	_, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	_, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("delete entry")
 	log.Info("delete entry")
 
 
 	if len(r.Form["tname"]) < 1 ||
 	if len(r.Form["tname"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["key"]) < 1 {
 		len(r.Form["key"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path))
 		log.Error("delete entry failed, wrong input")
 		log.Error("delete entry failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -240,31 +240,31 @@ func dbDeleteEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 		err := nDB.DeleteEntry(tname, nid, key)
 		err := nDB.DeleteEntry(tname, nid, key)
 		if err != nil {
 		if err != nil {
 			log.WithError(err).Error("delete entry failed")
 			log.WithError(err).Error("delete entry failed")
-			diagnose.HTTPReply(w, diagnose.FailCommand(err), json)
+			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
 			return
 			return
 		}
 		}
 		log.Info("delete entry done")
 		log.Info("delete entry done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(nil), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbGetEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbGetEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	unsafe, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("get entry")
 	log.Info("get entry")
 
 
 	if len(r.Form["tname"]) < 1 ||
 	if len(r.Form["tname"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["nid"]) < 1 ||
 		len(r.Form["key"]) < 1 {
 		len(r.Form["key"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id&key=k", r.URL.Path))
 		log.Error("get entry failed, wrong input")
 		log.Error("get entry failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -277,7 +277,7 @@ func dbGetEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 		value, err := nDB.GetEntry(tname, nid, key)
 		value, err := nDB.GetEntry(tname, nid, key)
 		if err != nil {
 		if err != nil {
 			log.WithError(err).Error("get entry failed")
 			log.WithError(err).Error("get entry failed")
-			diagnose.HTTPReply(w, diagnose.FailCommand(err), json)
+			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
 			return
 			return
 		}
 		}
 
 
@@ -288,27 +288,27 @@ func dbGetEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 			encodedValue = base64.StdEncoding.EncodeToString(value)
 			encodedValue = base64.StdEncoding.EncodeToString(value)
 		}
 		}
 
 
-		rsp := &diagnose.TableEntryObj{Key: key, Value: encodedValue}
-		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("update entry done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(rsp), json)
+		rsp := &diagnostic.TableEntryObj{Key: key, Value: encodedValue}
+		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get entry done")
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbJoinNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbJoinNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	_, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	_, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("join network")
 	log.Info("join network")
 
 
 	if len(r.Form["nid"]) < 1 {
 	if len(r.Form["nid"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path))
 		log.Error("join network failed, wrong input")
 		log.Error("join network failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -318,29 +318,29 @@ func dbJoinNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	if ok {
 	if ok {
 		if err := nDB.JoinNetwork(nid); err != nil {
 		if err := nDB.JoinNetwork(nid); err != nil {
 			log.WithError(err).Error("join network failed")
 			log.WithError(err).Error("join network failed")
-			diagnose.HTTPReply(w, diagnose.FailCommand(err), json)
+			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
 			return
 			return
 		}
 		}
 		log.Info("join network done")
 		log.Info("join network done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(nil), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbLeaveNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbLeaveNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	_, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	_, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("leave network")
 	log.Info("leave network")
 
 
 	if len(r.Form["nid"]) < 1 {
 	if len(r.Form["nid"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?nid=network_id", r.URL.Path))
 		log.Error("leave network failed, wrong input")
 		log.Error("leave network failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -350,30 +350,30 @@ func dbLeaveNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	if ok {
 	if ok {
 		if err := nDB.LeaveNetwork(nid); err != nil {
 		if err := nDB.LeaveNetwork(nid); err != nil {
 			log.WithError(err).Error("leave network failed")
 			log.WithError(err).Error("leave network failed")
-			diagnose.HTTPReply(w, diagnose.FailCommand(err), json)
+			diagnostic.HTTPReply(w, diagnostic.FailCommand(err), json)
 			return
 			return
 		}
 		}
 		log.Info("leave network done")
 		log.Info("leave network done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(nil), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(nil), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }
 
 
 func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
-	unsafe, json := diagnose.ParseHTTPFormOptions(r)
+	diagnostic.DebugHTTPForm(r)
+	unsafe, json := diagnostic.ParseHTTPFormOptions(r)
 
 
 	// audit logs
 	// audit logs
-	log := logrus.WithFields(logrus.Fields{"component": "diagnose", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
+	log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
 	log.Info("get table")
 	log.Info("get table")
 
 
 	if len(r.Form["tname"]) < 1 ||
 	if len(r.Form["tname"]) < 1 ||
 		len(r.Form["nid"]) < 1 {
 		len(r.Form["nid"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id", r.URL.Path))
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name&nid=network_id", r.URL.Path))
 		log.Error("get table failed, wrong input")
 		log.Error("get table failed, wrong input")
-		diagnose.HTTPReply(w, rsp, json)
+		diagnostic.HTTPReply(w, rsp, json)
 		return
 		return
 	}
 	}
 
 
@@ -383,7 +383,7 @@ func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	nDB, ok := ctx.(*NetworkDB)
 	nDB, ok := ctx.(*NetworkDB)
 	if ok {
 	if ok {
 		table := nDB.GetTableByNetwork(tname, nid)
 		table := nDB.GetTableByNetwork(tname, nid)
-		rsp := &diagnose.TableObj{Length: len(table)}
+		rsp := &diagnostic.TableObj{Length: len(table)}
 		var i = 0
 		var i = 0
 		for k, v := range table {
 		for k, v := range table {
 			var encodedValue string
 			var encodedValue string
@@ -393,7 +393,7 @@ func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 				encodedValue = base64.StdEncoding.EncodeToString(v.Value)
 				encodedValue = base64.StdEncoding.EncodeToString(v.Value)
 			}
 			}
 			rsp.Elements = append(rsp.Elements,
 			rsp.Elements = append(rsp.Elements,
-				&diagnose.TableEntryObj{
+				&diagnostic.TableEntryObj{
 					Index: i,
 					Index: i,
 					Key:   k,
 					Key:   k,
 					Value: encodedValue,
 					Value: encodedValue,
@@ -402,8 +402,8 @@ func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 			i++
 			i++
 		}
 		}
 		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get table done")
 		log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get table done")
-		diagnose.HTTPReply(w, diagnose.CommandSucceed(rsp), json)
+		diagnostic.HTTPReply(w, diagnostic.CommandSucceed(rsp), json)
 		return
 		return
 	}
 	}
-	diagnose.HTTPReply(w, diagnose.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
+	diagnostic.HTTPReply(w, diagnostic.FailCommand(fmt.Errorf("%s", dbNotAvailable)), json)
 }
 }

+ 5 - 5
libnetwork/test/networkDb/dbserver/ndbServer.go

@@ -9,17 +9,17 @@ import (
 	"os"
 	"os"
 	"strconv"
 	"strconv"
 
 
-	"github.com/docker/libnetwork/diagnose"
+	"github.com/docker/libnetwork/diagnostic"
 	"github.com/docker/libnetwork/networkdb"
 	"github.com/docker/libnetwork/networkdb"
 	"github.com/docker/libnetwork/test/networkDb/dummyclient"
 	"github.com/docker/libnetwork/test/networkDb/dummyclient"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 )
 )
 
 
 var nDB *networkdb.NetworkDB
 var nDB *networkdb.NetworkDB
-var server *diagnose.Server
+var server *diagnostic.Server
 var ipAddr string
 var ipAddr string
 
 
-var testerPaths2Func = map[string]diagnose.HTTPHandlerFunc{
+var testerPaths2Func = map[string]diagnostic.HTTPHandlerFunc{
 	"/myip": ipaddress,
 	"/myip": ipaddress,
 }
 }
 
 
@@ -49,7 +49,7 @@ func Server(args []string) {
 	ipAddr = ip
 	ipAddr = ip
 	logrus.Infof("%s uses IP %s\n", localNodeName, ipAddr)
 	logrus.Infof("%s uses IP %s\n", localNodeName, ipAddr)
 
 
-	server = diagnose.New()
+	server = diagnostic.New()
 	server.Init()
 	server.Init()
 	conf := networkdb.DefaultConfig()
 	conf := networkdb.DefaultConfig()
 	conf.Hostname = localNodeName
 	conf.Hostname = localNodeName
@@ -65,7 +65,7 @@ func Server(args []string) {
 	server.RegisterHandler(nDB, networkdb.NetDbPaths2Func)
 	server.RegisterHandler(nDB, networkdb.NetDbPaths2Func)
 	server.RegisterHandler(nil, testerPaths2Func)
 	server.RegisterHandler(nil, testerPaths2Func)
 	server.RegisterHandler(nDB, dummyclient.DummyClientPaths2Func)
 	server.RegisterHandler(nDB, dummyclient.DummyClientPaths2Func)
-	server.EnableDebug("", port)
+	server.EnableDiagnostic("", port)
 	// block here
 	// block here
 	select {}
 	select {}
 }
 }

+ 8 - 8
libnetwork/test/networkDb/dummyclient/dummyClient.go

@@ -6,13 +6,13 @@ import (
 	"net/http"
 	"net/http"
 
 
 	events "github.com/docker/go-events"
 	events "github.com/docker/go-events"
-	"github.com/docker/libnetwork/diagnose"
+	"github.com/docker/libnetwork/diagnostic"
 	"github.com/docker/libnetwork/networkdb"
 	"github.com/docker/libnetwork/networkdb"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 )
 )
 
 
 // DummyClientPaths2Func exported paths for the client
 // DummyClientPaths2Func exported paths for the client
-var DummyClientPaths2Func = map[string]diagnose.HTTPHandlerFunc{
+var DummyClientPaths2Func = map[string]diagnostic.HTTPHandlerFunc{
 	"/watchtable":          watchTable,
 	"/watchtable":          watchTable,
 	"/watchedtableentries": watchTableEntries,
 	"/watchedtableentries": watchTableEntries,
 }
 }
@@ -30,10 +30,10 @@ var clientWatchTable = map[string]tableHandler{}
 
 
 func watchTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func watchTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
+	diagnostic.DebugHTTPForm(r)
 	if len(r.Form["tname"]) < 1 {
 	if len(r.Form["tname"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name", r.URL.Path))
-		diagnose.HTTPReply(w, rsp, &diagnose.JSONOutput{})
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name", r.URL.Path))
+		diagnostic.HTTPReply(w, rsp, &diagnostic.JSONOutput{})
 		return
 		return
 	}
 	}
 
 
@@ -55,10 +55,10 @@ func watchTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 
 
 func watchTableEntries(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 func watchTableEntries(ctx interface{}, w http.ResponseWriter, r *http.Request) {
 	r.ParseForm()
 	r.ParseForm()
-	diagnose.DebugHTTPForm(r)
+	diagnostic.DebugHTTPForm(r)
 	if len(r.Form["tname"]) < 1 {
 	if len(r.Form["tname"]) < 1 {
-		rsp := diagnose.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name", r.URL.Path))
-		diagnose.HTTPReply(w, rsp, &diagnose.JSONOutput{})
+		rsp := diagnostic.WrongCommand(missingParameter, fmt.Sprintf("%s?tname=table_name", r.URL.Path))
+		diagnostic.HTTPReply(w, rsp, &diagnostic.JSONOutput{})
 		return
 		return
 	}
 	}