Example #1
0
// 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()
}
Example #2
0
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
}