plugins/traffic-control: add status information in metadata

This patch sends the delay and packet loss values along with
the container metadata. In this way the user has a direct feedback
about the traffic control plugin status.
This commit is contained in:
Alessandro Puccetti
2016-08-09 09:16:22 +02:00
parent c5cc9814fe
commit 068c366aa8
2 changed files with 102 additions and 4 deletions

View File

@@ -13,12 +13,23 @@ type report struct {
}
type topology struct {
Nodes map[string]node `json:"nodes"`
Controls map[string]control `json:"controls"`
Nodes map[string]node `json:"nodes"`
Controls map[string]control `json:"controls"`
MetadataTemplates map[string]metadataTemplate `json:"metadata_templates,omitempty"`
}
type metadataTemplate struct {
ID string `json:"id"`
Label string `json:"label,omitempty"` // Human-readable descriptor for this row
Truncate int `json:"truncate,omitempty"` // If > 0, truncate the value to this length.
Datatype string `json:"dataType,omitempty"`
Priority float64 `json:"priority,omitempty"`
From string `json:"from,omitempty"` // Defines how to get the value from a report node
}
type node struct {
LatestControls map[string]controlEntry `json:"latestControls,omitempty"`
Latest map[string]stringEntry `json:"latest,omitempty"`
}
type controlEntry struct {
@@ -37,6 +48,11 @@ type control struct {
Rank int `json:"rank"`
}
type stringEntry struct {
Timestamp time.Time `json:"timestamp"`
Value string `json:"value"`
}
type pluginSpec struct {
ID string `json:"id"`
Label string `json:"label"`
@@ -58,8 +74,9 @@ func NewReporter(store *Store) *Reporter {
func (r *Reporter) RawReport() ([]byte, error) {
rpt := &report{
Container: topology{
Nodes: r.getContainerNodes(),
Controls: getTrafficControls(),
Nodes: r.getContainerNodes(),
Controls: getTrafficControls(),
MetadataTemplates: getMetadataTemplate(),
},
Plugins: []pluginSpec{
{
@@ -120,14 +137,34 @@ func (r *Reporter) getContainerNodes() map[string]node {
fallthrough
case Running:
nodeID := containerIDToNodeID(containerID)
latency, _ := getLatency(container.PID)
nodes[nodeID] = node{
LatestControls: getTrafficNodeControls(timestamp, dead),
Latest: map[string]stringEntry{
"traffic-control-latency": {
Timestamp: timestamp,
Value: latency,
},
},
}
}
})
return nodes
}
func getMetadataTemplate() map[string]metadataTemplate {
return map[string]metadataTemplate{
"traffic-control-latency": metadataTemplate{
ID: "traffic-control-latency",
Label: "Latency",
Truncate: 0,
Datatype: "",
Priority: 13.5,
From: "latest",
},
}
}
func getTrafficNodeControls(timestamp time.Time, dead bool) map[string]controlEntry {
controls := map[string]controlEntry{}
entry := controlEntry{

View File

@@ -46,6 +46,67 @@ func DoTrafficControl(pid int, delay uint32) error {
return nil
}
func getLatency(pid int) (string, error) {
output := "-"
var err error
if output, err = getStatus(pid); err != nil {
return "-", err
} else if output == "" {
return "-", fmt.Errorf("Error: output is empty")
}
outputSplited := split(output)
for i, s := range outputSplited {
if s == "delay" {
if i < len(outputSplited)-1 {
output = outputSplited[i+1]
} else {
output = "-"
}
return output, nil
}
}
return output, fmt.Errorf("delay not found")
}
func getPktLoss(pid int) (string, error) {
output := "-"
var err error
if output, err = getStatus(pid); err != nil {
return "-", err
} else if output == "" {
return "-", fmt.Errorf("Error: output is empty")
}
outputSplited := split(output)
for i, s := range outputSplited {
if s == "loss" {
if i < len(outputSplited)-1 {
output = outputSplited[i+1]
} else {
output = "-"
}
return output, nil
}
}
return output, fmt.Errorf("delay not found")
}
func getStatus(pid int) (string, error) {
cmd := split("tc qdisc show dev eth0")
netNS := fmt.Sprintf("/proc/%d/ns/net", pid)
var output string
err := ns.WithNetNSPath(netNS, func(hostNS ns.NetNS) error {
if cmdOut, err := exec.Command(cmd[0], cmd[1:]...).CombinedOutput(); err != nil {
log.Error(string(cmdOut))
output = "-"
return fmt.Errorf("failed to execute command: tc qdisc show dev eth0: %v", err)
} else {
output = string(cmdOut)
}
return nil
})
return output, err
}
func split(cmd string) []string {
return strings.Split(cmd, " ")
}