in pkg/mgmapi/mgmapi.go [389:485]
func (mci *mgmClientImpl) GetStatus() (ClusterStatus, error) {
// command :
// get status
// reply :
// node status
// nodes: 13
// node.2.type: NDB
// node.2.status: STARTED
// node.2.version: 524314
// .....
// send the command and read the reply
reply, err := mci.executeCommand(
"get status", nil, false,
[]string{"node status", "nodes"})
if err != nil {
return nil, err
}
nodeCount, err := strconv.Atoi(reply["nodes"])
if err != nil {
klog.Error("failed to parse nodes value in node status reply : ", err)
return nil, debug.InternalError("'nodes' value in node status reply unexpected format")
}
delete(reply, "nodes")
// loop all values in reply and put them in a ClusterStatus object
cs := NewClusterStatus(nodeCount)
for aggregateKey, value := range reply {
// the key is of form node.3.version
keyTokens := strings.SplitN(aggregateKey, ".", 3)
if len(keyTokens) != 3 || keyTokens[0] != "node" {
return nil, debug.InternalError("node status reply has unexpected format")
}
// extract node id and the actual key
nodeId, err := strconv.Atoi(keyTokens[1])
if err != nil {
return nil, debug.InternalError("node status reply has unexpected format")
}
key := keyTokens[2]
// update nodestatus based on the key
ns := cs.ensureNode(nodeId)
switch key {
case "type":
ns.setNodeTypeFromTLA(value)
// Read and set status here.
// This is done here and not in a separate case as
// setting status depends on the type and if it is
// handled in a separate case, there is no guarantee
// that the type would have been set, due to the
// arbitrary looping order of the 'reply' map.
statusKey := fmt.Sprintf("node.%d.status", nodeId)
statusValue := reply[statusKey]
// for data node, STARTED => connected
// for mgm/api nodes, CONNECTED => connected
if (ns.IsDataNode() && statusValue == "STARTED") ||
(!ns.IsDataNode() && statusValue == "CONNECTED") {
ns.IsConnected = true
}
// In a similar manner, set node group for the data node. It is set
// in get status reply only if the data node is connected.
if ns.IsDataNode() {
if ns.IsConnected {
// Extract the NodeGroup from reply
nodeGroupKey := fmt.Sprintf("node.%d.node_group", nodeId)
ns.NodeGroup, err = strconv.Atoi(reply[nodeGroupKey])
if err != nil {
return nil, debug.InternalError("node_group in node status reply has unexpected format")
}
} else {
// NodeGroup is not set in reply as the node is not connected yet.
// Retrieve the NodeGroup using 'get config' command
nodeGroupValue, err := mci.getConfig(nodeId, cfgSectionTypeNDB, dbCfgNodegroup, true)
if err != nil {
return nil, debug.InternalError("node_group was not found in data node config " + keyTokens[1])
}
ns.NodeGroup = int(nodeGroupValue.(uint32))
}
}
case "version":
versionNumber, err := strconv.Atoi(value)
if err != nil {
return nil, debug.InternalError("version in node status reply has unexpected format")
}
ns.SoftwareVersion = getMySQLVersionString(versionNumber)
}
}
return cs, nil
}