From 02f890e28cbb24bd628cb5c003fa881c442b776d Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Tue, 26 Jan 2021 16:59:27 +0800 Subject: [PATCH 01/13] resource --- models/resource.go | 946 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 899 insertions(+), 47 deletions(-) diff --git a/models/resource.go b/models/resource.go index f78bc3f..27ca354 100644 --- a/models/resource.go +++ b/models/resource.go @@ -22,7 +22,7 @@ func GetResourceInfo() map[string]interface{} { return result } - constraints := GetAllConstraints() ///////////////// + constraints := GetAllConstraints() if _, ok := constraints["action"]; !ok { return constraints } @@ -39,7 +39,7 @@ func GetResourceInfo() map[string]interface{} { } t := GetResourceType(rscId) - subRscs := GetSubResources(rscId) /////////////////// + subRscs := GetSubResources(rscId) if t == "group" || t == "clone" { constraint["subrscs"] = subRscs["subrscs"] } else { @@ -189,16 +189,17 @@ func GetResourceFailedMessage() map[string]map[string]string { if len(failures) == 0 { return failInfo } else { - // TODO - // for _, failure := range failures { - // infoFail := map[string]string{} - // rscIdf := strings.Split(failure.SelectAttr("op_key").Value, "_stop_")[0] - // rscIdm := strings.Split(rscIdf, "_start_")[0] - // rscId := strings.Split(rscIdm, "_start_")[0] - // node := failure.SelectAttr("node") - // exitreason := failure.SelectAttr("exitreason") - - // } + for _, failure := range failures { + infoFail := map[string]string{} + rscIdf := strings.Split(failure.SelectAttr("op_key").Value, "_stop_")[0] + rscIdm := strings.Split(rscIdf, "_start_")[0] + rscId := strings.Split(rscIdm, "_start_")[0] + node := failure.SelectAttr("node").Value + exitreason := failure.SelectAttr("exitreason").Value + infoFail["node"] = node + infoFail["exitreason"] = exitreason + failInfo[rscId] = infoFail + } } return failInfo } @@ -319,11 +320,339 @@ func GetResourceByConstraintAndId() { } func CreateResource(data []byte) map[string]interface{} { + if data == nil || len(data) == 0 { + return map[string]interface{}{"action": false, "error": "No input data"} + } + var jsonData interface{} + err := json.Unmarshal(data, jsonData) + if err != nil { + return map[string]interface{}{"action": false, "error": "Cannot convert data to json map"} + } + jsonMap := jsonData.(map[string]interface{}) + + var rscId string + if v, ok := jsonMap["id"].(string); ok { + rscId = v + } else if v, ok := jsonMap["id"].(int); ok { + rscId = strconv.Itoa(v) + } + cate := jsonMap["category"].(string) + if cate == "primitive" { + rscIdStr := " id=\"" + rscId + "\"" + rscClass := " class=\"" + jsonMap["class"].(string) + "\"" + rscType := " type=\"" + jsonMap["type"].(string) + "\"" + cmd := "cibadmin --create -o resources --xml-text '<" + role := "pcs resource disable " + out, err := utils.RunCommand("cibadmin -Q") + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + doc := etree.NewDocument() + if err = doc.ReadFromBytes(out); err != nil { + return map[string]interface{}{"action": false, "error": "xml parse failed"} + } + primitives := doc.FindElements("primitive") + for _, primitive := range primitives { + id := primitive.SelectAttr("id").Value + resourceId := map[string]string{"id": id} + if rscId == resourceId["id"] { + return map[string]interface{}{"action": false, "error": rscId + " is exist"} + } + } + groups := doc.FindElements("group") + for _, group := range groups { + id := group.SelectAttr("id").Value + resourceId := map[string]string{"id": id} + if rscId == resourceId["id"] { + return map[string]interface{}{"action": false, "error": rscId + " is exist"} + } + } + clones := doc.FindElements("clone") + for _, clone := range clones { + id := clone.SelectAttr("id").Value + resourceId := map[string]string{"id": id} + if rscId == resourceId["id"] { + return map[string]interface{}{"action": false, "error": rscId + " is exist"} + } + } + if _, ok := jsonMap["provider"]; ok { + provider := " provider=\"" + jsonMap["provider"].(string) + "\"" + cmdStr := cmd + cate + rscIdStr + rscClass + rscType + provider + ">'" + out, err := utils.RunCommand(cmdStr) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + flag := 0 + UpdateResourcAttributes(rscId, jsonMap) + attrib := GetMetaAndInst(rscId) + for _, v := range attrib { + + } + } + } else if cate == "group" { + + } else if cate == "clone" { + + } + return map[string]interface{}{"action": true, "info": "Add " + cate + " resource success"} + +} + +// UpdateResourcAttributes updates meta_attributes and instance_attributes +func UpdateResourcAttributes(rscId string, data map[string]interface{}) map[string]interface{} { + /* + Example data: + { + "category": "primitive", + "actions":[ + { + "interval":"100", + "name":"start" + } + ], + "meta_attributes":{ + "resource-stickiness":"104", + "is-managed":"true", + "target-role":"Started" + }, + "type":"Filesystem", + "id":"iscisi", + "provider":"heartbeat", + "instance_attributes":{ + "device":"/dev/sda1", + "directory":"/var/lib/mysql", + "fstype":"ext4" + }, + "class":"ocf" + } + */ + if data == nil || len(data) == 0 { + return map[string]interface{}{"action": false, "error": "No input data"} + } + // delete all the attribute + attrib := GetMetaAndInst(rscId) + if _, ok := attrib["meta_attributes"]; ok { + metaAttri := attrib["meta_attributes"].([]string) + for _, v := range metaAttri { + cmd := "crm_resource -r " + rscId + " -m --delete-parameter " + v + out, err := utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } + } + if _, ok := attrib["instance_attributes"]; ok { + metaAttri := attrib["instance_attributes"].([]string) + for _, v := range metaAttri { + cmd := "crm_resource -r " + rscId + " -m --delete-parameter " + v + out, err := utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } + } + if data["category"] == "group" { + if _, ok := data["meta_attributes"]; ok { + metaAttri := data["meta_attributes"].(map[string]string) + for k, v := range metaAttri { + cmd := "pcs resource meta " + rscId + " " + k + "=" + v + out, err := utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } + } + } else { + if _, ok := data["meta_attributes"]; ok { + metaAttri := data["meta_attributes"].(map[string]string) + for k, v := range metaAttri { + cmd := "pcs resource update " + rscId + " meta " + k + "=" + v + " --force" + out, err := utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } + } + } + + out, err := utils.RunCommand("sleep 1") + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + + instStr := "" + if _, ok := data["instance_attributes"]; ok { + instAttri := data["instance_attributes"].(map[string]string) + for k, v := range instAttri { + instStr = instStr + k + "=" + v + " " + } + } + out, err = utils.RunCommand("pcs resource update " + rscId + " " + instStr + " --force") + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + + // change operation + if _, ok := data["actions"]; ok { + // delete all the attribute + opList := GetAllOps(rscId) + if len(opList) != 0 { + cmdDelHead := "pcs resource op delete " + rscId + for _, op := range opList { + cmdDel := cmdDelHead + " " + op + out, err = utils.RunCommand(cmdDel) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } + } + action := data["actions"].([]map[string]string) + // overwrite + cmdIn := "pcs resource update " + rscId + " op" + for _, ops := range action { + name := ops["name"] + cmdIn = cmdIn + " " + name + if v, ok := ops["interval"]; ok { + cmdIn = cmdIn + " " + "interval=" + v + } + if v, ok := ops["start-delay"]; ok { + cmdIn = cmdIn + " " + "start-delay=" + v + } + if v, ok := ops["timeout"]; ok { + cmdIn = cmdIn + " " + "timeout=" + v + } + if v, ok := ops["role"]; ok { + cmdIn = cmdIn + " " + "role=" + v + } + if v, ok := ops["requires"]; ok { + cmdIn = cmdIn + " " + "requires=" + v + } + if v, ok := ops["on-fail"]; ok { + cmdIn = cmdIn + " " + "on-fail=" + v + } + } + out, err = utils.RunCommand(cmdIn) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } + + // add group resource + if data["category"] == "group" { + /* + { + "id":"group1", + "category":"group", + "rscs":["iscisi", "test1" ], + "meta_attributes":{ + "target-role":"Started" + } + } + */ + } + return map[string]interface{}{"action": true, "info": "Update resource attributes Success"} +} + +func GetAllOps(rscId string) []string { + opList := []string{} + cmd := "crm_resource --resource " + rscId + " --query-xml" + out, err := utils.RunCommand(cmd) + if err != nil { + return opList + } + xml := strings.Split(string(out), ":\n")[1] + doc := etree.NewDocument() + if err := doc.ReadFromString(xml); err != nil { + return opList + } + e := doc.FindElement("operations") + if e != nil { + op := e.SelectElements("./op") + for _, item := range op { + opList = append(opList, item.SelectAttrValue("name", "")) + } + } + return opList +} + +func DeletePriAttrib(rscId string) error { + // delete attribute + attrib := GetMetaAndInst(rscId) + if metaAttri, ok := attrib["meta_attributes"]; ok { + metaArr := metaAttri.([]string) + for _, v := range metaArr { + cmd := "crm_resource -r " + rscId + " -m --delete-parameter " + if v == "is-managed" || v == "priority" || v == "target-role" { + cmd += v + _, err := utils.RunCommand(cmd) + if err != nil { + return err + } + } + } + } + // delete constraint + // colocation + targetId := getResourceConstraintIDs(rscId, "colocation") + err := DeleteColocationByIdAndAction(rscId, targetId) + if err != nil { + return err + } + // location + ids := getResourceConstraintIDs(rscId, "location") + for _, item := range ids { + cmd := "pcs constraint location delete " + item + _, err := utils.RunCommand(cmd) + if err != nil { + return err + } + } + // order + if findOrder(rscId) { + cmd := "pcs constraint order delete " + rscId + _, err := utils.RunCommand(cmd) + if err != nil { + return err + } + } return nil } +func GetMetaAndInst(rscId string) map[string]interface{} { + cmdStr := "crm_resource --resource " + rscId + " --query-xml" + out, err := utils.RunCommand(cmdStr) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + xml := strings.Split(string(out), ":\n")[1] + doc := etree.NewDocument() + if err = doc.ReadFromString(xml); err != nil { + return map[string]interface{}{"action": false, "error": err} + } + data := map[string]interface{}{} + eMeta := doc.FindElement("meta_attributes") + if eMeta != nil { + prop := []string{} + items := eMeta.SelectElements("./nvpair") + for _, item := range items { + prop = append(prop, item.SelectAttr("name").Value) + } + data["meta_attributes"] = prop + } + eInst := doc.FindElement("instance_attributes") + if eInst != nil { + prop := []string{} + items := eInst.SelectElements("./nvpair") + for _, item := range items { + prop = append(prop, item.SelectAttr("name").Value) + } + data["instance_attributes"] = prop + } + return data +} + func GetAllConstraints() map[string]interface{} { - rscStatus := GetAllResourceStatus() /////////////// + rscStatus := GetAllResourceStatus() var data map[string](map[string]interface{}) topRsc := GetTopResource() @@ -337,7 +666,7 @@ func GetAllConstraints() map[string]interface{} { } else { data[rsc]["status"] = "Running" data[rsc]["status_message"] = "" - data[rsc]["running_node"] = rscStatus[rsc]["running_node"] + data[rsc]["running_node"] = rscStatus["running_node"] } data[rsc]["before_rscs"] = []map[string]string{} data[rsc]["after_rscs"] = []map[string]string{} @@ -372,7 +701,7 @@ func GetAllConstraints() map[string]interface{} { score := location.SelectAttr("score").Value locationSingle := make(map[string]string) locationSingle["node"] = node - locationSingle["level"] = utils.ScoreToLevel(score) ////////// + locationSingle["level"] = ScoreToLevel(score) locationArr := []map[string]string{} for key := range data { if rscId == key { @@ -430,7 +759,7 @@ func GetAllConstraints() map[string]interface{} { } } - failureInfo := GetResourceFailedMessage() /////////////// + failureInfo := GetResourceFailedMessage() constraintMaps := []map[string]interface{}{} for rscId := range data { @@ -442,16 +771,15 @@ func GetAllConstraints() map[string]interface{} { constraint["status"] = "Stopped" constraint["status_message"] = "" constraint["running_node"] = []string{} + } else if strings.HasSuffix(rscId, "-clone") { + constraint["status"] = "Failed" + constraint["status_message"] = failureInfo[rscIDFirst]["exitreason"] + " on " + failureInfo[rscIDFirst]["node"] + constraint["running_node"] = []string{} } - } else if strings.HasSuffix(rscId, "-clone") { - constraint["status"] = "Failed" - //////////////////// - constraint["status_message"] = failureInfo[rscIDFirst]["exitreason"] + " on " + failureInfo[rscIDFirst]["node"] - constraint["running_node"] = []string{} } else { rscInfo := rscStatus[rscId] - constraint["status"] = rscInfo["status"] constraint["status_message"] = "" + constraint["status"] = rscInfo["status"] constraint["running_node"] = rscInfo["running_node"] } @@ -532,54 +860,488 @@ func GetAllMigrateResources() []string { return rscList } -func GetAllResourceStatus() map[string]map[string]string { - // rscInfo:= +func GetAllResourceStatus() map[string]map[string]interface{} { + /* + infos = { + 0:_('Running'), + 1:_('Not Running'), + 2:_('Unmanaged'), + 3:_('Failed'), + 4:_('Stop Failed'), + 5:_('running (Master)'), + 6:_('running (Slave)')} + rsc_info = { + "hj1": {"status": 0 , "status_message": "test", running_node: []} + "hj2": {"status": 0 , "status_message": "test", running_node: []} + } + */ + rscInfo := map[string]map[string]interface{}{} out, err := utils.RunCommand("crm_mon -1 --as-xml") if err != nil { - return map[string]map[string]string{} + return map[string]map[string]interface{}{} } doc := etree.NewDocument() if err = doc.ReadFromBytes(out); err != nil { - return map[string]map[string]string{} + return map[string]map[string]interface{}{} } if len(doc.SelectElements("crm_mon/resources")) == 0 { - return map[string]map[string]string{} + return map[string]map[string]interface{}{} } // allRscRun:=[]string{} // doesn't used + rscClone := doc.SelectElements("crm_mon/resources/clone") rscGroup := doc.SelectElements("crm_mon/resources/group") rscResource := doc.SelectElements("crm_mon/resources/resource") - if len(rscClone) != 0 { + // several clone if len(rscClone) != 1 { - // TODO - // for _, rsc := range rscClone { - // subRscs := rsc.FindElement("resource") - // index := 0 - // - // for _, subRsc := range subRscs { - // - // } - // } + for _, rsc := range rscClone { + // subResources is common resources + if subRscs := rsc.SelectElements("resource"); len(subRscs) != 0 { + index := 0 + cloneRunNodes := []string{} + cloneInfo := map[string]interface{}{} + for _, subRsc := range subRscs { + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + nodename := "" + if node := subRsc.FindElement("node"); node != nil { + nodename = node.SelectAttr("name").Value + } + id := subRsc.SelectAttr("id").Value + ":" + string(index) + index++ + info["running_node"] = []string{nodename} + rscInfo[id] = info + cloneRunNodes = append(cloneRunNodes, nodename) + } + cloneInfo["status"] = GetResourceStatus(rsc) + cloneInfo["status_message"] = "" + cloneInfo["running_node"] = cloneRunNodes + cloneId := rsc.SelectAttr("id").Value + rscInfo[cloneId] = cloneInfo + } + // subResources is gourp resources + if subRscs := rsc.SelectElements("group"); len(subRscs) != 0 { + cloneRunNodes := []string{} + cloneInfo := map[string]interface{}{} + for _, subRsc := range subRscs { + subRscId := subRsc.SelectAttr("id").Value + groupInfo := map[string]interface{}{} + groupRunNodes := []string{} + if innerRscs := subRsc.SelectElements("resource"); len(innerRscs) != 0 { + groupInfo["status"] = "Not Running" + if len(innerRscs) == 1 { + innerRsc := innerRscs[0] + innerRscId := innerRsc.SelectAttr("id").Value + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + if node := innerRsc.FindElement("node"); node != nil { + nodename := "" + if node := subRsc.FindElement("node"); node != nil { + nodename = node.SelectAttr("name").Value + } + info["running_node"] = []string{nodename} + groupRunNodes = append(groupRunNodes, nodename) + cloneRunNodes = append(cloneRunNodes, nodename) + groupInfo["status"] = "Running" + } + fatherId := strings.Split(subRscId, ":")[1] + id := innerRscId + ":" + fatherId + rscInfo[id] = info + } else { + for _, innerRsc := range innerRscs { + innerRscId := innerRsc.SelectAttr("id").Value + info := map[string]interface{}{} + groupInfo["status"] = "Stopped" + info["status"] = GetResourceStatus(subRsc) + if info["status"] == "Running" { + groupInfo["status"] = "Running" + } + info["status_message"] = "" + if node := innerRsc.FindElement("node"); node != nil { + nodename := node.SelectAttr("name").Value + info["running_node"] = []string{nodename} + cloneRunNodes = append(cloneRunNodes, nodename) + groupRunNodes = append(groupRunNodes, nodename) + } + fatherId := strings.Split(subRscId, ":")[1] + id := innerRscId + ":" + fatherId + rscInfo[id] = info + } + } + } + groupInfo["running_node"] = utils.RemoveDupl(groupRunNodes) + groupInfo["status_message"] = "" + groupId := subRscId + rscInfo[groupId] = groupInfo + } + cloneInfo["status"] = GetResourceStatus(rsc) + cloneInfo["status_message"] = "" + cloneInfo["running_node"] = utils.RemoveDupl(cloneRunNodes) + cloneId := rsc.SelectAttr("id").Value + rscInfo[cloneId] = cloneInfo + } + } + } else { // single clone + // clone is group resource + if rscCloneGroups := rscClone[0].SelectElements("group"); len(rscCloneGroups) != 0 { + cloneRunNodes := []string{} + cloneInfo := map[string]interface{}{} + cloneInfo["status"] = "Not Running" + for _, rscCloneGroup := range rscCloneGroups { + cloneGroupRunNodes := []string{} + cloneGroupInfo := map[string]interface{}{} + subGroupId := rscCloneGroup.SelectAttr("id").Value + index := strings.Split(subGroupId, ":")[1] + if subRscs := rscCloneGroup.SelectElements("resource"); len(subRscs) != 0 { + cloneGroupInfo["status"] = "Not Running" + + for _, subRsc := range subRscs { + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + id := subRsc.SelectAttr("id").Value + ":" + index + if node := subRsc.FindElement("node"); node != nil { + nodename := node.SelectAttr("name").Value + info["running_node"] = []string{nodename} + cloneGroupInfo["status"] = "Running" + cloneInfo["status"] = "Running" + cloneGroupRunNodes = append(cloneGroupRunNodes, nodename) + cloneRunNodes = append(cloneRunNodes, nodename) + } + rscInfo[id] = info + } + } + cloneGroupInfo["running_node"] = utils.RemoveDupl(cloneGroupRunNodes) + cloneGroupInfo["status_message"] = "" + rscInfo[subGroupId] = cloneGroupInfo + } + cloneInfo["status_message"] = "" + cloneInfo["running_node"] = utils.RemoveDupl(cloneRunNodes) + id := rscClone[0].SelectAttr("id").Value + rscInfo[id] = cloneInfo + } + // clone is common resource + if subRscs := rscClone[0].SelectElements("resource"); len(subRscs) != 0 { + index := 0 + cloneRunNodes := []string{} + cloneInfo := map[string]interface{}{} + for _, subRsc := range subRscs { + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + nodename := subRsc.FindElement("node").SelectAttr("name").Value + id := string(subRsc.SelectAttr("id").Value) + ":" + string(index) + index++ + info["running_node"] = []string{nodename} + rscInfo[id] = info + cloneRunNodes = append(cloneRunNodes, nodename) + } + cloneInfo["status"] = GetResourceStatus(rscClone[0]) + cloneInfo["status_message"] = "" + cloneInfo["running_node"] = cloneRunNodes + id := rscClone[0].SelectAttr("id").Value + rscInfo[id] = cloneInfo + } } } if len(rscGroup) != 0 { - + // several group + if len(rscGroup) != 1 { + for _, rsc := range rscGroup { + subRscs := rsc.SelectElements("resource") + // several resources in each group + if len(subRscs) > 1 { + groupRunNodes := []string{} + groupInfo := map[string]interface{}{} + groupInfo["status"] = "Not Running" + for _, subRsc := range subRscs { + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + nodename := "" + if node := subRsc.FindElement("node"); node != nil { + nodename = node.SelectAttr("name").Value + info["running_node"] = []string{nodename} + groupRunNodes = append(groupRunNodes, nodename) + groupInfo["status"] = "Running" + } + id := subRsc.SelectAttr("id").Value + rscInfo[id] = info + } + groupInfo["status_message"] = "" + groupInfo["running_node"] = groupRunNodes + id := rsc.SelectAttr("id").Value + rscInfo[id] = groupInfo + } else { + subRsc := subRscs[0] + groupRunNodes := []string{} + groupInfo := map[string]interface{}{} + groupInfo["status"] = "Not Running" + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + nodename := "" + if node := subRsc.FindElement("node"); node != nil { + nodename = node.SelectAttr("name").Value + info["running_node"] = []string{nodename} + groupRunNodes = append(groupRunNodes, nodename) + groupInfo["status"] = "Running" + } + id := subRsc.SelectAttr("id").Value + rscInfo[id] = info + groupInfo["status_message"] = "" + groupInfo["running_node"] = utils.RemoveDupl(groupRunNodes) + gid := rsc.SelectAttr("id").Value + rscInfo[gid] = groupInfo + } + } + } else { // single group + rscGroupSin := rscGroup[0] + subRscs := rscGroupSin.SelectElements("resource") + groupInfo := map[string]interface{}{} + flag := 0 + if len(subRscs) > 1 { + groupInfo["status"] = "Not Running" + for _, subRsc := range subRscs { + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + id := subRsc.SelectAttr("id").Value + if nodes := subRsc.SelectElements("node"); len(nodes) != 0 { + infoRunNode := []string{} + groupRunNodes := []string{} + for _, node := range nodes { + nodename := node.SelectAttr("name").Value + infoRunNode = append(infoRunNode, nodename) + groupRunNodes = append(groupRunNodes, nodename) + groupInfo["status"] = "Running" + } + info["running_node"] = utils.RemoveDupl(infoRunNode) + groupInfo["running_node"] = utils.RemoveDupl(groupRunNodes) + } + rscInfo[id] = info + } + groupInfo["status_message"] = "" + groupId := rscGroupSin.SelectAttr("id").Value + rscInfo[groupId] = groupInfo + } else { + subRsc := subRscs[0] + info := map[string]interface{}{} + info["status"] = GetResourceStatus(subRsc) + info["status_message"] = "" + nodename := "" + if node := subRsc.FindElement("node"); node != nil { + nodename = node.SelectAttr("name").Value + } else { + flag = 1 + } + id := subRsc.SelectAttr("id").Value + info["running_node"] = []string{nodename} + rscInfo[id] = info + groupInfo["status_message"] = "" + groupInfo["running_node"] = []string{} + if flag == 1 { + groupInfo["status"] = "Not Running" + } else { + groupInfo["status"] = "Running" + groupInfo["running_node"] = []string{nodename} + } + groupId := rscGroupSin.SelectAttr("id").Value + rscInfo[groupId] = groupInfo + } + } } if len(rscResource) != 0 { + // several common resource + if len(rscGroup) != 1 { + for _, rsc := range rscResource { + resourceInfo := map[string]interface{}{} + resourceInfo["status"] = GetResourceStatus(rsc) + runningNode := []string{} + if nodes := rsc.SelectElements("node"); len(nodes) != 0 { + for _, node := range nodes { + runningNode = append(runningNode, node.SelectAttr("name").Value) + } + } + resourceInfo["running_node"] = runningNode + resourceInfo["status_message"] = "" + id := rsc.SelectAttr("id").Value + rscInfo[id] = resourceInfo + } + } + } + + return rscInfo +} +func GetResourceStatus(rscInfo *etree.Element) string { + rscId := rscInfo.SelectAttr("id").Value + failInfo := GetResourceFailedMessage() + if _, ok := failInfo[rscId]; ok { + return "Failed" } - return map[string]map[string]string{} + if rscInfo.SelectAttr("managed").Value == "false" { + return "Unmanaged" + } + if rscInfo.SelectAttr("failed").Value == "true" { + return "Failed" + } + if role := rscInfo.SelectAttr("role"); role != nil { + if role.Value == "Started" { + return "Running" + } + if role.Value == "Stopped" { + return "Not Running" + } + + } + return "Running" } func GetSubResources(rscId string) map[string]interface{} { - // TODO - // rscStatus := GetAllResourceStatus() - // failInfo := GetResourceFailedMessage() + rscStatus := GetAllResourceStatus() + failInfo := GetResourceFailedMessage() // failure run information + var rscInfo map[string]interface{} - return nil + out, err := utils.RunCommand("cibadmin --query --scope resources") + if err != nil { + return rscInfo + } + doc := etree.NewDocument() + if err = doc.ReadFromBytes(out); err != nil { + return rscInfo + } + resJson := doc.FindElement("resources") + rscType := GetResourceType(rscId) + rscInfo["id"] = rscId + subRscs := []map[string]interface{}{} + + if rscType == "clone" { + nodeInfo, _ := GetNodesInfo() + nodeNum := len(nodeInfo) + clone := resJson.FindElements("clone") + var cloneAim *etree.Element + // find the clone resource's location + if len(clone) < 2 { + if clone[0].SelectAttr("id").Value == rscId { + cloneAim = clone[0] + } + } else { + for _, subClone := range clone { + if subClone.SelectAttr("id").Value == rscId { + cloneAim = subClone + } + } + } + // clone resource objects is group or primitive + // Parse the types of resources and assemble them into strings + if cloneGroup := cloneAim.FindElement("group"); cloneGroup != nil { + subRscId := cloneGroup.SelectAttr("id").Value + if rscPrimitive := cloneGroup.FindElements("primitive"); len(rscPrimitive) != 0 { + for i := 0; i < nodeNum; i++ { + var subRsc map[string]interface{} + subRsc["status"] = "Not Running" + subRsc["running_node"] = []string{} + subRsc["status_message"] = "" + subId := subRscId + ":" + strconv.Itoa(i) + subRsc["id"] = subId + if _, ok := rscStatus[subId]; ok { + subRsc["status"] = rscStatus[subId]["status"] + subRsc["running_node"] = rscStatus[subId]["running_node"] + } + subRsc["type"] = "group" + subSubRsc := []map[string]interface{}{} + for _, primitive := range rscPrimitive { + pid := primitive.SelectAttr("id").Value + ":" + strconv.Itoa(i) + primitiveInfo := map[string]interface{}{} + primitiveInfo["id"] = pid + primitiveInfo["status"] = "Not Running" + primitiveInfo["status_message"] = "" + primitiveInfo["running_node"] = []string{} + if _, ok := rscStatus[pid]; ok { + primitiveInfo["status"] = rscStatus[pid]["status"] + primitiveInfo["running_node"] = rscStatus[pid]["running_node"] + } + primitiveInfo["svc"] = primitive.SelectAttr("type").Value + primitiveInfo["type"] = "primitive" + subSubRsc = append(subSubRsc, primitiveInfo) + } + subRsc["subrscs"] = subSubRsc + subRscs = append(subRscs, subRsc) + } + } + } + + if clonePrimitive := cloneAim.FindElement("primitive"); clonePrimitive != nil { + subRscId := clonePrimitive.SelectAttr("id").Value + for i := 0; i < nodeNum; i++ { + var subRsc map[string]interface{} + subRsc["status"] = "Not Running" + subRsc["status_message"] = "" + subId := subRscId + ":" + strconv.Itoa(i) + subRsc["id"] = subId + if _, ok := rscStatus[subId]; ok { + subRsc["status"] = rscStatus[subId]["status"] + subRsc["running_node"] = rscStatus[subId]["running_node"] + } + // judgment failure message + if subFailInfo, ok := failInfo[subRscId]; ok { + subRsc["status_message"] = subFailInfo["exitreason"] + " on " + subFailInfo["node"] + subRsc["status"] = "Failed" + if subRscStatus, ok := rscStatus[subRscId]; ok { + subRsc["running_node"] = subRscStatus["running_node"] + } else { + subRsc["running_node"] = []string{} + } + } + subRsc["type"] = "primitive" + subRsc["svc"] = clonePrimitive.SelectAttr("type").Value + subRscs = append(subRscs, subRsc) + } + } + } + + if rscType == "group" { + groups := resJson.FindElements("group") + for _, group := range groups { + if rscId == group.SelectAttr("id").Value { + rscPrimitive := group.FindElements("primitive") + for _, primitive := range rscPrimitive { + primitiveInfo := map[string]interface{}{} + primitiveInfo["status_message"] = "" + primitiveId := primitive.SelectAttr("id").Value + primitiveInfo["id"] = primitiveId + if priRscStatus, ok := rscStatus[primitiveId]; ok { + primitiveInfo["status"] = priRscStatus["status"] + primitiveInfo["running_node"] = priRscStatus["running_node"] + } else { + primitiveInfo["status"] = "" + primitiveInfo["running_node"] = []string{} + } + // judgment failure message + if priFail, ok := failInfo[primitiveId]; ok { + primitiveInfo["status_message"] = priFail["exitreason"] + " on " + priFail["node"] + primitiveInfo["status"] = "Failed" + if priRscStatus, ok := rscStatus[primitiveId]; ok { + primitiveInfo["running_node"] = priRscStatus["running_node"] + } else { + primitiveInfo["running_node"] = []string{} + } + } + primitiveInfo["type"] = "primitive" + primitiveInfo["svc"] = primitive.SelectAttr("type").Value + subRscs = append(subRscs, primitiveInfo) + } + } + } + } + rscInfo["subrscs"] = subRscs + return rscInfo } func GetResourceSvc(rscId string) string { @@ -607,7 +1369,6 @@ func GetTopResource() []string { return result } - // TODO: check logic doc := etree.NewDocument() if err = doc.ReadFromBytes(out); err != nil { return result @@ -786,8 +1547,43 @@ func ResourceAction(rscID, action string, data []byte) error { } func getResourceConstraintIDs(rscID, action string) []string { - return nil - //TODO + ids := []string{} + out, err := utils.RunCommand("cibadmin --query --scope constraints") + if err != nil { + return ids + } + doc := etree.NewDocument() + if err = doc.ReadFromBytes(out); err != nil { + return ids + } + + if action == "colocation" { + et := doc.SelectElements("./rsc_colocation") + for _, item := range et { + rsc := item.SelectAttrValue("rsc", "") + rscWith := item.SelectAttrValue("with-rsc", "") + if rsc == rscID { + ids = append(ids, rscWith) + } + if rscWith == rscID { + ids = append(ids, rsc) + } + return ids + } + } else if action == "location" { + et := doc.SelectElements("./rsc_location") + for _, item := range et { + rsc := item.SelectAttrValue("rsc", "") + if rsc == rscID { + if item.SelectAttr("score") != nil && item.SelectAttrValue("score", "") == "-INFINITY" { + continue + } + ids = append(ids, item.SelectAttrValue("id", "")) + } + return ids + } + } + return ids } func DeleteColocationByIdAndAction(rscID string, targetIds []string) error { @@ -801,7 +1597,22 @@ func DeleteColocationByIdAndAction(rscID string, targetIds []string) error { } func findOrder(rscID string) bool { - // TODO: + out, err := utils.RunCommand("cibadmin --query --scope constraints") + if err != nil { + return false + } + doc := etree.NewDocument() + if err = doc.ReadFromBytes(out); err != nil { + return false + } + et := doc.SelectElements("./rsc_order") + for _, item := range et { + first := item.SelectAttrValue("first", "") + then := item.SelectAttrValue("then", "") + if first == rscID || then == rscID { + return true + } + } return false } @@ -1255,3 +2066,44 @@ func delPriAttrib(rscID string) interface{} { } return nil } + +func levelInit() []string { + nodeinfo, _ := GetNodesInfo() + nodeNum := len(nodeinfo) + max := nodeNum - 1 + levelScoreArr := make([]string, max) + for i := 0; i < max; i++ { + levelScoreArr[i] = strconv.Itoa(16000 - 1000*i) + } + return levelScoreArr +} + +func ScoreToLevel(score string) string { + levelScoreArr := levelInit() + if score == "20000" { + return "Master Node" + } + if score == "-INFINITY" || score == "-infinity" { + return "No Run Node" + } + + isIn := false + for _, v := range levelScoreArr { + if score == v { + isIn = true + break + } + } + if isIn == false { + return score + } + + level := 1 + for _, s := range levelScoreArr { + if s == score { + return "Slave " + strconv.Itoa(level) + } + level = level + 1 + } + return "" +} -- Gitee From 4bc85257920130be525440ace3eab80c1b62fd55 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Tue, 26 Jan 2021 19:32:54 +0800 Subject: [PATCH 02/13] CreateResource --- models/resource.go | 195 +++++++++++++++++++++++++++++++++++++++++---- utils/utils.go | 13 +++ 2 files changed, 193 insertions(+), 15 deletions(-) diff --git a/models/resource.go b/models/resource.go index 27ca354..5956aaa 100644 --- a/models/resource.go +++ b/models/resource.go @@ -377,22 +377,168 @@ func CreateResource(data []byte) map[string]interface{} { } if _, ok := jsonMap["provider"]; ok { provider := " provider=\"" + jsonMap["provider"].(string) + "\"" - cmdStr := cmd + cate + rscIdStr + rscClass + rscType + provider + ">'" - out, err := utils.RunCommand(cmdStr) + cmd = cmd + cate + rscIdStr + rscClass + rscType + provider + ">'" + } else { + cmd = cmd + cate + rscIdStr + rscClass + rscType + ">'" + } + out, err = utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + flag := 0 + UpdateResourcAttributes(rscId, jsonMap) + attrib := GetMetaAndInst(rscId) + for _, arr := range attrib { + for _, s := range arr { + if "target-role" == s { + flag = 1 + break + } + } + } + if flag == 0 { + cmd := role + rscId + out, err := utils.RunCommand(cmd) if err != nil { return map[string]interface{}{"action": false, "error": out} } - flag := 0 - UpdateResourcAttributes(rscId, jsonMap) - attrib := GetMetaAndInst(rscId) - for _, v := range attrib { - + } + if _, ok := jsonMap["provider"]; !ok { + instance := "crm_resource --resource " + class := jsonMap["class"] + if class == "stonith" { + cmdStr := instance + rscId + " --set-parameter pcmk_host_check --parameter-value static-list" + out, err := utils.RunCommand(cmdStr) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } } } } else if cate == "group" { + /* + { + "category": "group", + "id":"tomcat_group", + "rscs":[ + "tomcat6", + "tomcat7" + ], + "meta_attributes":{ + "target-role":"Stopped" + } + } + */ + rscs := jsonMap["rscs"].([]string) + role := "pcs resource disable " + for _, rsc := range rscs { + DeletePriAttrib(rsc) + } + rscId := jsonMap["id"].(string) + cmdStr := "pcs resource group add " + rscId + for _, r := range rscs { + cmdStr = cmdStr + " " + r + } + out, err := utils.RunCommand("cibadmin -Q") + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + doc := etree.NewDocument() + if err = doc.ReadFromBytes(out); err != nil { + return map[string]interface{}{"action": false, "error": "xml parse failed"} + } + primitives := doc.FindElements("primitive") + for _, primitive := range primitives { + id := primitive.SelectAttr("id").Value + resourceId := map[string]string{"id": id} + if rscId == resourceId["id"] { + return map[string]interface{}{"action": false, "error": rscId + " is exist"} + } + } + groups := doc.FindElements("group") + for _, group := range groups { + id := group.SelectAttr("id").Value + resourceId := map[string]string{"id": id} + if rscId == resourceId["id"] { + return map[string]interface{}{"action": false, "error": rscId + " is exist"} + } + } + clones := doc.FindElements("clone") + for _, clone := range clones { + id := clone.SelectAttr("id").Value + resourceId := map[string]string{"id": id} + if rscId == resourceId["id"] { + return map[string]interface{}{"action": false, "error": rscId + " is exist"} + } + } + out, err = utils.RunCommand(cmdStr) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + flag := 0 + UpdateResourcAttributes(rscId, jsonMap) + attrib := GetMetaAndInst(rscId) + for _, arr := range attrib { + for _, s := range arr { + if "target-role" == s { + flag = 1 + break + } + } + } + if flag == 0 { + cmd := role + rscId + out, err := utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } } else if cate == "clone" { - + /* + { + "category": "clone", + "id":"test5", + "rsc_id":"test4", + "meta_attributes":{ + "target-role":"Stopped" + } + } + id is unused + */ + oriId := jsonMap["rsc_id"].(string) + ids := getResourceConstraintIDs(oriId, "location") + for _, item := range ids { + cmd := "pcs constraint location delete " + item + out, err := utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } + role := "pcs resource disable " + cmdStr := "pcs resource clone " + oriId + DeleteCloneAttrib(oriId) + out, err := utils.RunCommand(cmdStr) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + flag := 0 + UpdateResourcAttributes(rscId, jsonMap) + attrib := GetMetaAndInst(rscId) + for _, arr := range attrib { + for _, s := range arr { + if "target-role" == s { + flag = 1 + break + } + } + } + if flag == 0 { + cmd := role + rscId + out, err := utils.RunCommand(cmd) + if err != nil { + return map[string]interface{}{"action": false, "error": out} + } + } } return map[string]interface{}{"action": true, "info": "Add " + cate + " resource success"} @@ -432,7 +578,7 @@ func UpdateResourcAttributes(rscId string, data map[string]interface{}) map[stri // delete all the attribute attrib := GetMetaAndInst(rscId) if _, ok := attrib["meta_attributes"]; ok { - metaAttri := attrib["meta_attributes"].([]string) + metaAttri := attrib["meta_attributes"] for _, v := range metaAttri { cmd := "crm_resource -r " + rscId + " -m --delete-parameter " + v out, err := utils.RunCommand(cmd) @@ -442,7 +588,7 @@ func UpdateResourcAttributes(rscId string, data map[string]interface{}) map[stri } } if _, ok := attrib["instance_attributes"]; ok { - metaAttri := attrib["instance_attributes"].([]string) + metaAttri := attrib["instance_attributes"] for _, v := range metaAttri { cmd := "crm_resource -r " + rscId + " -m --delete-parameter " + v out, err := utils.RunCommand(cmd) @@ -579,7 +725,7 @@ func DeletePriAttrib(rscId string) error { // delete attribute attrib := GetMetaAndInst(rscId) if metaAttri, ok := attrib["meta_attributes"]; ok { - metaArr := metaAttri.([]string) + metaArr := metaAttri for _, v := range metaArr { cmd := "crm_resource -r " + rscId + " -m --delete-parameter " if v == "is-managed" || v == "priority" || v == "target-role" { @@ -618,18 +764,37 @@ func DeletePriAttrib(rscId string) error { return nil } -func GetMetaAndInst(rscId string) map[string]interface{} { +func DeleteCloneAttrib(rscId string) error { + // delete attribute + attrib := GetMetaAndInst(rscId) + if metaAttri, ok := attrib["meta_attributes"]; ok { + metaArr := metaAttri + cmd := "crm_resource -r " + rscId + " -m --delete-parameter " + for _, v := range metaArr { + cmdStr := cmd + v + _, err := utils.RunCommand(cmdStr) + if err != nil { + return err + } + } + } + return nil +} + +func GetMetaAndInst(rscId string) map[string][]string { cmdStr := "crm_resource --resource " + rscId + " --query-xml" out, err := utils.RunCommand(cmdStr) if err != nil { - return map[string]interface{}{"action": false, "error": out} + // return map[string]interface{}{"action": false, "error": out} + return map[string][]string{} } xml := strings.Split(string(out), ":\n")[1] doc := etree.NewDocument() if err = doc.ReadFromString(xml); err != nil { - return map[string]interface{}{"action": false, "error": err} + // return map[string]interface{}{"action": false, "error": err} + return map[string][]string{} } - data := map[string]interface{}{} + data := map[string][]string{} eMeta := doc.FindElement("meta_attributes") if eMeta != nil { prop := []string{} diff --git a/utils/utils.go b/utils/utils.go index 56f43a8..2816d7c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -10,3 +10,16 @@ func IsInSlice(str string, sli []string) bool { } return false } + +// RemoveDupl remove duplicates in string array +func RemoveDupl(strs []string) []string { + strSet := map[string]bool{} + for _, v := range strs { + strSet[v] = true + } + strsDupl := []string{} + for k := range strSet { + strsDupl = append(strsDupl, k) + } + return strsDupl +} -- Gitee From fd1b3c67f3764c427ab59295ef782bb7146f04f1 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Wed, 27 Jan 2021 15:17:05 +0800 Subject: [PATCH 03/13] bug: don't have running_node --- models/resource.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/models/resource.go b/models/resource.go index 0d94a6f..99b47ea 100644 --- a/models/resource.go +++ b/models/resource.go @@ -324,7 +324,7 @@ func CreateResource(data []byte) map[string]interface{} { return map[string]interface{}{"action": false, "error": "No input data"} } var jsonData interface{} - err := json.Unmarshal(data, jsonData) + err := json.Unmarshal(data, &jsonData) if err != nil { return map[string]interface{}{"action": false, "error": "Cannot convert data to json map"} } @@ -871,7 +871,7 @@ func GetAllConstraints() map[string]interface{} { } else { data[rsc]["status"] = "Running" data[rsc]["status_message"] = "" - data[rsc]["running_node"] = rscStatus["running_node"] + data[rsc]["running_node"] = rscStatus[rsc]["running_node"] } data[rsc]["before_rscs"] = []map[string]string{} data[rsc]["after_rscs"] = []map[string]string{} @@ -1494,6 +1494,7 @@ func GetSubResources(rscId string) map[string]interface{} { for i := 0; i < nodeNum; i++ { subRsc := map[string]interface{}{} subRsc["status"] = "Not Running" + subRsc["running_node"] = []string{} subRsc["status_message"] = "" subId := subRscId + ":" + strconv.Itoa(i) subRsc["id"] = subId @@ -1533,7 +1534,6 @@ func GetSubResources(rscId string) map[string]interface{} { primitiveInfo["running_node"] = priRscStatus["running_node"] } else { primitiveInfo["status"] = "" - primitiveInfo["running_node"] = []string{} } // judgment failure message if priFail, ok := failInfo[primitiveId]; ok { -- Gitee From 9f860ffc1b31dc995a0228e9e51e811a843bdfe6 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Wed, 27 Jan 2021 15:24:24 +0800 Subject: [PATCH 04/13] bug --- models/resource.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models/resource.go b/models/resource.go index 99b47ea..d6dc10e 100644 --- a/models/resource.go +++ b/models/resource.go @@ -1534,6 +1534,7 @@ func GetSubResources(rscId string) map[string]interface{} { primitiveInfo["running_node"] = priRscStatus["running_node"] } else { primitiveInfo["status"] = "" + primitiveInfo["running_node"] = []string{} } // judgment failure message if priFail, ok := failInfo[primitiveId]; ok { -- Gitee From 9ad8359a7e988d8f65dce69e08ae44649407adc2 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 09:19:24 +0800 Subject: [PATCH 05/13] meta controller --- controllers/meta.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/controllers/meta.go b/controllers/meta.go index 0ee2c52..6f6081f 100644 --- a/controllers/meta.go +++ b/controllers/meta.go @@ -2,6 +2,7 @@ package controllers import ( "github.com/beego/beego/v2/server/web" + "openkylin.com/ha-api/models" ) type MetaController struct { @@ -9,8 +10,10 @@ type MetaController struct { } func (mc *MetaController) Get() { - // TODO - // mc.Data["json"] = models.GetResourceMetas() + rscClass := mc.Ctx.Input.Param(":rsc_class") + rscType := mc.Ctx.Input.Param(":rsc_type") + rscProvider := mc.Ctx.Input.Param(":rsc_provider") + mc.Data["json"] = models.GetResourceMetas(rscClass, rscType, rscProvider) mc.ServeJSON() } @@ -19,10 +22,6 @@ type MetasController struct { } func (mc *MetasController) Get() { - // TODO - // rscClass := mc.Ctx.Input.Param(":rsc_class") - // rscType := mc.Ctx.Input.Param(":rsc_type") - // rscProvider := mc.Ctx.Input.Param(":rsc_provider") - // mc.Data["json"] = models.GetAllResourceMetas(rscClass, rscType, rscProvider) + mc.Data["json"] = models.GetAllResourceMetas() mc.ServeJSON() } -- Gitee From 905c7c18fe18283a260508f949f55595b344607b Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 10:08:08 +0800 Subject: [PATCH 06/13] fix bug --- models/meta.go | 12 ++++++------ models/resource.go | 11 ++++++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/models/meta.go b/models/meta.go index 98c70e8..395e4fc 100644 --- a/models/meta.go +++ b/models/meta.go @@ -14,7 +14,7 @@ func GetAllResourceMetas() map[string]interface{} { out, err := utils.RunCommand("crm_resource --list-standards") if err != nil { result["action"] = false - result["error"] = out + result["error"] = err.Error() return result } standards := strings.Split(string(out), "\n") @@ -26,7 +26,7 @@ func GetAllResourceMetas() map[string]interface{} { out, err := utils.RunCommand("crm_resource --list-ocf-providers") if err != nil { result["action"] = false - result["error"] = out + result["error"] = err.Error() return result } pvds := strings.Split(string(out), "\n") @@ -34,7 +34,7 @@ func GetAllResourceMetas() map[string]interface{} { out, err := utils.RunCommand("crm_resource --list-agents ocf:" + p) if err != nil { result["action"] = false - result["error"] = out + result["error"] = err.Error() return result } ag := strings.Split(string(out), "\n") @@ -56,7 +56,7 @@ func GetAllResourceMetas() map[string]interface{} { out, err := utils.RunCommand("crm_resource --list-agents " + st) if err != nil { result["action"] = false - result["error"] = out + result["error"] = err.Error() return result } la := strings.Split(string(out), "\n") @@ -102,11 +102,11 @@ func GetResourceMetas(rscClass, rscType, rscProvider string) map[string]interfac } out, err := utils.RunCommand(cmd) if err != nil { - return map[string]interface{}{"action": false, "data": data} + return map[string]interface{}{"action": false, "data": err.Error()} } doc := etree.NewDocument() if err = doc.ReadFromBytes(out); err != nil { - return map[string]interface{}{"action": false, "data": data} + return map[string]interface{}{"action": false, "data": err.Error()} } eRoot := doc.Root() data["name"] = eRoot.SelectAttrValue("name", "") diff --git a/models/resource.go b/models/resource.go index ce17f07..6da1eb2 100644 --- a/models/resource.go +++ b/models/resource.go @@ -345,7 +345,7 @@ func CreateResource(data []byte) map[string]interface{} { role := "pcs resource disable " out, err := utils.RunCommand("cibadmin -Q") if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } doc := etree.NewDocument() if err = doc.ReadFromBytes(out); err != nil { @@ -428,7 +428,12 @@ func CreateResource(data []byte) map[string]interface{} { } } */ - rscs := jsonMap["rscs"].([]string) + // rscs := jsonMap["rscs"].([]string) + rscsArr := jsonMap["rscs"].([]interface{}) + rscs := make([]string, len(rscsArr)) + for ix, v := range rscsArr { + rscs[ix] = v.(string) + } role := "pcs resource disable " for _, rsc := range rscs { DeletePriAttrib(rsc) @@ -441,7 +446,7 @@ func CreateResource(data []byte) map[string]interface{} { } out, err := utils.RunCommand("cibadmin -Q") if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } doc := etree.NewDocument() if err = doc.ReadFromBytes(out); err != nil { -- Gitee From 8aab2b48ed9b2f90651ae85d3f676dc3d24fee9b Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 11:16:04 +0800 Subject: [PATCH 07/13] bug --- models/meta.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/models/meta.go b/models/meta.go index 395e4fc..5ac057b 100644 --- a/models/meta.go +++ b/models/meta.go @@ -9,7 +9,7 @@ import ( ) func GetAllResourceMetas() map[string]interface{} { - var result map[string]interface{} + result := map[string]interface{}{} out, err := utils.RunCommand("crm_resource --list-standards") if err != nil { @@ -29,7 +29,8 @@ func GetAllResourceMetas() map[string]interface{} { result["error"] = err.Error() return result } - pvds := strings.Split(string(out), "\n") + pvdsStr := string(out) // there's a space after last word + pvds := strings.Split(pvdsStr[0:len(pvdsStr)-1], "\n") for _, p := range pvds { out, err := utils.RunCommand("crm_resource --list-agents ocf:" + p) if err != nil { -- Gitee From 61b0bbdfa3a6a8f7c32f44edff263e6680c2dab3 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 12:37:37 +0800 Subject: [PATCH 08/13] neta bug --- models/meta.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/models/meta.go b/models/meta.go index 5ac057b..a815ff7 100644 --- a/models/meta.go +++ b/models/meta.go @@ -22,6 +22,9 @@ func GetAllResourceMetas() map[string]interface{} { res := make(map[string][]string) for _, st := range standards { + if st == "" { + continue + } if st == "ocf" { out, err := utils.RunCommand("crm_resource --list-ocf-providers") if err != nil { @@ -29,9 +32,11 @@ func GetAllResourceMetas() map[string]interface{} { result["error"] = err.Error() return result } - pvdsStr := string(out) // there's a space after last word - pvds := strings.Split(pvdsStr[0:len(pvdsStr)-1], "\n") + pvds := strings.Split(string(out), "\n") for _, p := range pvds { + if p == "" { + continue + } out, err := utils.RunCommand("crm_resource --list-agents ocf:" + p) if err != nil { result["action"] = false @@ -64,7 +69,9 @@ func GetAllResourceMetas() map[string]interface{} { // Eliminate Duplicates laMap := map[string]bool{} for _, laStr := range la { - laMap[laStr] = true + if laStr != "" { + laMap[laStr] = true + } } la = []string{} for k, _ := range laMap { -- Gitee From e97d0cdab341486bff828967f3300efc5f940fea Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 15:31:25 +0800 Subject: [PATCH 09/13] resource bug --- models/resource.go | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/models/resource.go b/models/resource.go index 6da1eb2..f3d1311 100644 --- a/models/resource.go +++ b/models/resource.go @@ -514,17 +514,17 @@ func CreateResource(data []byte) map[string]interface{} { ids := getResourceConstraintIDs(oriId, "location") for _, item := range ids { cmd := "pcs constraint location delete " + item - out, err := utils.RunCommand(cmd) + _, err := utils.RunCommand(cmd) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } } role := "pcs resource disable " cmdStr := "pcs resource clone " + oriId DeleteCloneAttrib(oriId) - out, err := utils.RunCommand(cmdStr) + _, err := utils.RunCommand(cmdStr) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } flag := 0 UpdateResourceAttributes(rscId, jsonMap) @@ -604,9 +604,9 @@ func UpdateResourceAttributes(rscId string, data map[string]interface{}) error { } if data["category"] == "group" { if _, ok := data["meta_attributes"]; ok { - metaAttri := data["meta_attributes"].(map[string]string) + metaAttri := data["meta_attributes"].(map[string]interface{}) for k, v := range metaAttri { - cmd := "pcs resource meta " + rscId + " " + k + "=" + v + cmd := "pcs resource meta " + rscId + " " + k + "=" + v.(string) _, err := utils.RunCommand(cmd) if err != nil { return err @@ -615,9 +615,9 @@ func UpdateResourceAttributes(rscId string, data map[string]interface{}) error { } } else { if _, ok := data["meta_attributes"]; ok { - metaAttri := data["meta_attributes"].(map[string]string) + metaAttri := data["meta_attributes"].(map[string]interface{}) for k, v := range metaAttri { - cmd := "pcs resource update " + rscId + " meta " + k + "=" + v + " --force" + cmd := "pcs resource update " + rscId + " meta " + k + "=" + v.(string) + " --force" _, err := utils.RunCommand(cmd) if err != nil { return err @@ -633,9 +633,9 @@ func UpdateResourceAttributes(rscId string, data map[string]interface{}) error { instStr := "" if _, ok := data["instance_attributes"]; ok { - instAttri := data["instance_attributes"].(map[string]string) + instAttri := data["instance_attributes"].(map[string]interface{}) for k, v := range instAttri { - instStr = instStr + k + "=" + v + " " + instStr = instStr + k + "=" + v.(string) + " " } } _, err = utils.RunCommand("pcs resource update " + rscId + " " + instStr + " --force") @@ -657,29 +657,30 @@ func UpdateResourceAttributes(rscId string, data map[string]interface{}) error { } } } - action := data["actions"].([]map[string]string) + action := data["actions"].([]interface{}) // overwrite cmdIn := "pcs resource update " + rscId + " op" - for _, ops := range action { - name := ops["name"] + for _, opsIf := range action { + ops := opsIf.(map[string]interface{}) + name := ops["name"].(string) cmdIn = cmdIn + " " + name if v, ok := ops["interval"]; ok { - cmdIn = cmdIn + " " + "interval=" + v + cmdIn = cmdIn + " " + "interval=" + v.(string) } if v, ok := ops["start-delay"]; ok { - cmdIn = cmdIn + " " + "start-delay=" + v + cmdIn = cmdIn + " " + "start-delay=" + v.(string) } if v, ok := ops["timeout"]; ok { - cmdIn = cmdIn + " " + "timeout=" + v + cmdIn = cmdIn + " " + "timeout=" + v.(string) } if v, ok := ops["role"]; ok { - cmdIn = cmdIn + " " + "role=" + v + cmdIn = cmdIn + " " + "role=" + v.(string) } if v, ok := ops["requires"]; ok { - cmdIn = cmdIn + " " + "requires=" + v + cmdIn = cmdIn + " " + "requires=" + v.(string) } if v, ok := ops["on-fail"]; ok { - cmdIn = cmdIn + " " + "on-fail=" + v + cmdIn = cmdIn + " " + "on-fail=" + v.(string) } } _, err = utils.RunCommand(cmdIn) -- Gitee From b815df9a38b16522051e3ccfc621fdc940c61ba0 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 16:16:08 +0800 Subject: [PATCH 10/13] bug --- models/resource.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/models/resource.go b/models/resource.go index f3d1311..22c45c3 100644 --- a/models/resource.go +++ b/models/resource.go @@ -657,11 +657,10 @@ func UpdateResourceAttributes(rscId string, data map[string]interface{}) error { } } } - action := data["actions"].([]interface{}) + action := data["actions"].([]map[string]interface{}) // overwrite cmdIn := "pcs resource update " + rscId + " op" - for _, opsIf := range action { - ops := opsIf.(map[string]interface{}) + for _, ops := range action { name := ops["name"].(string) cmdIn = cmdIn + " " + name if v, ok := ops["interval"]; ok { -- Gitee From 3c33af3bde8e2a922a3c74a1d5ad37300bc79166 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 16:38:28 +0800 Subject: [PATCH 11/13] fix out and err --- models/resource.go | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/models/resource.go b/models/resource.go index 22c45c3..0b6ed9f 100644 --- a/models/resource.go +++ b/models/resource.go @@ -349,7 +349,7 @@ func CreateResource(data []byte) map[string]interface{} { } doc := etree.NewDocument() if err = doc.ReadFromBytes(out); err != nil { - return map[string]interface{}{"action": false, "error": "xml parse failed"} + return map[string]interface{}{"action": false, "error": err.Error()} } primitives := doc.FindElements("primitive") for _, primitive := range primitives { @@ -381,9 +381,9 @@ func CreateResource(data []byte) map[string]interface{} { } else { cmd = cmd + cate + rscIdStr + rscClass + rscType + ">'" } - out, err = utils.RunCommand(cmd) + _, err = utils.RunCommand(cmd) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } flag := 0 UpdateResourceAttributes(rscId, jsonMap) @@ -398,9 +398,9 @@ func CreateResource(data []byte) map[string]interface{} { } if flag == 0 { cmd := role + rscId - out, err := utils.RunCommand(cmd) + _, err := utils.RunCommand(cmd) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } } if _, ok := jsonMap["provider"]; !ok { @@ -408,9 +408,9 @@ func CreateResource(data []byte) map[string]interface{} { class := jsonMap["class"] if class == "stonith" { cmdStr := instance + rscId + " --set-parameter pcmk_host_check --parameter-value static-list" - out, err := utils.RunCommand(cmdStr) + _, err := utils.RunCommand(cmdStr) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } } } @@ -450,7 +450,7 @@ func CreateResource(data []byte) map[string]interface{} { } doc := etree.NewDocument() if err = doc.ReadFromBytes(out); err != nil { - return map[string]interface{}{"action": false, "error": "xml parse failed"} + return map[string]interface{}{"action": false, "error": err.Error()} } primitives := doc.FindElements("primitive") for _, primitive := range primitives { @@ -478,7 +478,7 @@ func CreateResource(data []byte) map[string]interface{} { } out, err = utils.RunCommand(cmdStr) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } flag := 0 UpdateResourceAttributes(rscId, jsonMap) @@ -493,9 +493,9 @@ func CreateResource(data []byte) map[string]interface{} { } if flag == 0 { cmd := role + rscId - out, err := utils.RunCommand(cmd) + _, err := utils.RunCommand(cmd) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } } } else if cate == "clone" { @@ -539,9 +539,9 @@ func CreateResource(data []byte) map[string]interface{} { } if flag == 0 { cmd := role + rscId - out, err := utils.RunCommand(cmd) + _, err := utils.RunCommand(cmd) if err != nil { - return map[string]interface{}{"action": false, "error": out} + return map[string]interface{}{"action": false, "error": err.Error()} } } } @@ -830,13 +830,11 @@ func GetMetaAndInst(rscId string) map[string][]string { cmdStr := "crm_resource --resource " + rscId + " --query-xml" out, err := utils.RunCommand(cmdStr) if err != nil { - // return map[string]interface{}{"action": false, "error": out} return map[string][]string{} } xml := strings.Split(string(out), ":\n")[1] doc := etree.NewDocument() if err = doc.ReadFromString(xml); err != nil { - // return map[string]interface{}{"action": false, "error": err} return map[string][]string{} } data := map[string][]string{} -- Gitee From 08f5442b5c6be4a5c72bd76778d335b76a39646b Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 18:20:10 +0800 Subject: [PATCH 12/13] commit --- models/resource.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/models/resource.go b/models/resource.go index 0b6ed9f..a64d8f6 100644 --- a/models/resource.go +++ b/models/resource.go @@ -830,11 +830,13 @@ func GetMetaAndInst(rscId string) map[string][]string { cmdStr := "crm_resource --resource " + rscId + " --query-xml" out, err := utils.RunCommand(cmdStr) if err != nil { + // return map[string]interface{}{"action": false, "error": out} return map[string][]string{} } xml := strings.Split(string(out), ":\n")[1] doc := etree.NewDocument() if err = doc.ReadFromString(xml); err != nil { + // return map[string]interface{}{"action": false, "error": out} return map[string][]string{} } data := map[string][]string{} -- Gitee From 19bc77618c006662beae4eb10391cdbbe79b3659 Mon Sep 17 00:00:00 2001 From: LittleTransparent Date: Thu, 28 Jan 2021 18:25:31 +0800 Subject: [PATCH 13/13] commit --- models/resource.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/resource.go b/models/resource.go index a64d8f6..06f2d03 100644 --- a/models/resource.go +++ b/models/resource.go @@ -830,13 +830,13 @@ func GetMetaAndInst(rscId string) map[string][]string { cmdStr := "crm_resource --resource " + rscId + " --query-xml" out, err := utils.RunCommand(cmdStr) if err != nil { - // return map[string]interface{}{"action": false, "error": out} + // return map[string]interface{}{"action": false, "error": err} return map[string][]string{} } xml := strings.Split(string(out), ":\n")[1] doc := etree.NewDocument() if err = doc.ReadFromString(xml); err != nil { - // return map[string]interface{}{"action": false, "error": out} + // return map[string]interface{}{"action": false, "error": err} return map[string][]string{} } data := map[string][]string{} -- Gitee