func()

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
}