* Copyright (c) KylinSoft Co., Ltd. 2024.All rights reserved.
* ha-api licensed under the Mulan Permissive Software License, Version 2.
* See LICENSE file for more details.
* Author: bixiaoyan <bixiaoyan@kylinos.cn>
* Date: Thu Mar 27 09:32:28 2025 +0800
*/
package models
import (
"bufio"
"encoding/json"
"encoding/xml"
"fmt"
"slices"
"strings"
"gitee.com/openeuler/ha-api/utils"
"github.com/chai2010/gettext-go"
)
type TagInfo struct {
ID string `json:"id"`
TagsRsc interface{} `json:"tagsrsc"`
}
type Tag struct {
ID string `xml:"id,attr"`
ObjRefs []ObjRef `xml:"obj_ref"`
}
type ObjRef struct {
ID string `xml:"id,attr"`
}
type Tags struct {
Tags []Tag `xml:"tag"`
}
type TagPostData struct {
ID string `json:"id"`
Tag_resource []string `json:"tag_resource"`
}
type TagGetResult struct {
Action bool `json:"action"`
Data []TagInfo `json:"data"`
ResList []string `json:"res_list"`
Error string `json:"error,omitempty"`
}
func GetOneTag(tagName string) map[string]interface{} {
result := make(map[string]interface{})
var data TagPostData
cmd := "pcs tag config " + tagName
out, err := utils.RunCommand(cmd)
if err != nil {
result["action"] = false
result["error"] = "Can not get the tag!"
return result
}
scanner := bufio.NewScanner(strings.NewReader(string(out)))
scanner.Scan()
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line != "" {
data.Tag_resource = append(data.Tag_resource, line)
}
}
data.ID = tagName
result["action"] = true
result["data"] = data
return result
}
func GetTag() TagGetResult {
resList := []string{}
cmd := "cibadmin --query --scope tags"
rsc_info := GetResourceInfo()
for _, res := range rsc_info["data"].([]map[string]interface{}) {
resList = append(resList, res["id"].(string))
}
out, err := utils.RunCommand(cmd)
if err != nil {
if strings.Contains(string(out), "No such device or address") {
return TagGetResult{Action: true, Data: []TagInfo{}, ResList: resList}
} else {
return TagGetResult{Action: false, Error: gettext.Gettext("Get tag failed")}
}
}
var tags Tags
if err := xml.Unmarshal([]byte(out), &tags); err != nil {
return TagGetResult{Action: false, Error: gettext.Gettext("Parsing JSON failed")}
}
tagInfos := make([]TagInfo, len(tags.Tags))
for i, tag := range tags.Tags {
var tagList []interface{}
for _, test := range tag.ObjRefs {
for _, res := range rsc_info["data"].([]map[string]interface{}) {
if res["id"].(string) == test.ID {
tagList = append(tagList, res)
break
}
}
}
tagInfos[i] = TagInfo{
ID: tag.ID,
TagsRsc: tagList,
}
}
return TagGetResult{Action: true, Data: tagInfos, ResList: resList}
}
func SetTag(data []byte) utils.GeneralResponse {
var result utils.GeneralResponse
if len(data) == 0 {
result.Action = false
result.Error = gettext.Gettext("No input data")
return result
}
var TagData TagPostData
err := json.Unmarshal(data, &TagData)
if err != nil {
result.Action = false
result.Error = gettext.Gettext("Cannot convert data to json map")
return result
}
nameCmd := "pcs resource config |awk '/Resource|Group|Bundle/ {print $2}'"
names, _ := utils.RunCommand(nameCmd)
standards := strings.Split(strings.TrimSpace(string(names)), "\n")
nameCmd = "pcs tag |awk '!/^[ \t]/'"
names, _ = utils.RunCommand(nameCmd)
tagNames := strings.Split(strings.TrimSpace(string(names)), "\n")
standards = append(standards, tagNames...)
if slices.Contains(standards, TagData.ID) {
result.Action = false
result.Error = fmt.Sprintf(gettext.Gettext("The tag name %s is already in the cluster!"), TagData.ID)
return result
}
cmd := "pcs tag create " + TagData.ID
for _, res := range TagData.Tag_resource {
cmd = cmd + " " + string(res)
}
out, err := utils.RunCommand(cmd)
if err == nil {
result.Action = true
result.Info = gettext.Gettext("Add tag success")
} else {
result.Action = false
result.Error = string(out)
}
return result
}
func UpdateTag(tagName string, data []byte) utils.GeneralResponse {
var result utils.GeneralResponse
if len(data) == 0 {
result.Action = false
result.Error = gettext.Gettext("No input data")
return result
}
var TagData TagPostData
err := json.Unmarshal(data, &TagData)
if err != nil {
result.Action = false
result.Error = gettext.Gettext("Cannot convert data to json map")
return result
}
cmd_create := "pcs tag create " + string(tagName)
cmd_delete := "pcs tag delete " + string(tagName)
for _, res := range TagData.Tag_resource {
cmd_create = cmd_create + " " + string(res)
}
out1, err1 := utils.RunCommand(cmd_delete)
if err1 == nil {
out2, err2 := utils.RunCommand(cmd_create)
if err2 == nil {
result.Action = true
result.Info = gettext.Gettext("Update tag success")
} else {
result.Action = false
result.Error = string(out2)
}
} else {
result.Action = false
result.Error = string(out1)
}
return result
}
func TagAction(tagName string, action string) utils.GeneralResponse {
var result utils.GeneralResponse
cmd := "pcs resource "
if action == "delete" {
return DeleteTag(tagName)
} else if action == "start" {
cmd = cmd + "enable " + tagName
} else if action == "stop" {
cmd = cmd + "disable " + tagName
}
print(cmd)
out, err := utils.RunCommand(cmd)
if err == nil {
result.Action = true
result.Info = gettext.Gettext("Tag action success")
} else {
result.Action = false
result.Error = string(out)
}
return result
}
func DeleteTag(tagName string) utils.GeneralResponse {
var result utils.GeneralResponse
cmd := "pcs tag delete " + tagName
out, err := utils.RunCommand(cmd)
if err == nil {
result.Action = true
result.Info = gettext.Gettext("Delete tag success")
} else {
result.Action = false
result.Error = string(out)
}
return result
}