// computeDistance returns the distance between the two network coordinates in // seconds. If either of the coordinates is nil then this will return positive // infinity. func computeDistance(a *coordinate.Coordinate, b *coordinate.Coordinate) float64 { if a == nil || b == nil { return math.Inf(1.0) } return a.DistanceTo(b).Seconds() }
func (c *RTTCommand) Run(args []string) int { var wan bool cmdFlags := flag.NewFlagSet("rtt", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.BoolVar(&wan, "wan", false, "wan") httpAddr := HTTPAddrFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { return 1 } // They must provide at least one node. nodes := cmdFlags.Args() if len(nodes) < 1 || len(nodes) > 2 { c.Ui.Error("One or two node names must be specified") c.Ui.Error("") c.Ui.Error(c.Help()) return 1 } // Create and test the HTTP client. conf := api.DefaultConfig() conf.Address = *httpAddr client, err := api.NewClient(conf) if err != nil { c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) return 1 } coordClient := client.Coordinate() var source string var coord1, coord2 *coordinate.Coordinate if wan { source = "WAN" // Default the second node to the agent if none was given. if len(nodes) < 2 { agent := client.Agent() self, err := agent.Self() if err != nil { c.Ui.Error(fmt.Sprintf("Unable to look up agent info: %s", err)) return 1 } node, dc := self["Config"]["NodeName"], self["Config"]["Datacenter"] nodes = append(nodes, fmt.Sprintf("%s.%s", node, dc)) } // Parse the input nodes. parts1 := strings.Split(nodes[0], ".") parts2 := strings.Split(nodes[1], ".") if len(parts1) != 2 || len(parts2) != 2 { c.Ui.Error("Node names must be specified as <node name>.<datacenter> with -wan") return 1 } node1, dc1 := parts1[0], parts1[1] node2, dc2 := parts2[0], parts2[1] // Pull all the WAN coordinates. dcs, err := coordClient.Datacenters() if err != nil { c.Ui.Error(fmt.Sprintf("Error getting coordinates: %s", err)) return 1 } // See if the requested nodes are in there. for _, dc := range dcs { for _, entry := range dc.Coordinates { if dc.Datacenter == dc1 && entry.Node == node1 { coord1 = entry.Coord } if dc.Datacenter == dc2 && entry.Node == node2 { coord2 = entry.Coord } if coord1 != nil && coord2 != nil { goto SHOW_RTT } } } } else { source = "LAN" // Default the second node to the agent if none was given. if len(nodes) < 2 { agent := client.Agent() node, err := agent.NodeName() if err != nil { c.Ui.Error(fmt.Sprintf("Unable to look up agent info: %s", err)) return 1 } nodes = append(nodes, node) } // Pull all the LAN coordinates. entries, _, err := coordClient.Nodes(nil) if err != nil { c.Ui.Error(fmt.Sprintf("Error getting coordinates: %s", err)) return 1 } // See if the requested nodes are in there. for _, entry := range entries { if entry.Node == nodes[0] { coord1 = entry.Coord } if entry.Node == nodes[1] { coord2 = entry.Coord } if coord1 != nil && coord2 != nil { goto SHOW_RTT } } } // Make sure we found both coordinates. if coord1 == nil { c.Ui.Error(fmt.Sprintf("Could not find a coordinate for node %q", nodes[0])) return 1 } if coord2 == nil { c.Ui.Error(fmt.Sprintf("Could not find a coordinate for node %q", nodes[1])) return 1 } SHOW_RTT: // Report the round trip time. dist := fmt.Sprintf("%.3f ms", coord1.DistanceTo(coord2).Seconds()*1000.0) c.Ui.Output(fmt.Sprintf("Estimated %s <-> %s rtt: %s (using %s coordinates)", nodes[0], nodes[1], dist, source)) return 0 }