* 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: bizhiyuan <bizhiyuan@kylinos.cn>
* Date: Tue Mar 12 10:13:58 2024 +0800
*/
package models
import (
"fmt"
"log/slog"
"gitee.com/openeuler/ha-api/utils"
"gitee.com/openeuler/ha-api/validations"
"github.com/beevik/etree"
"github.com/chai2010/gettext-go"
)
type Rule struct {
Rsc string `json:"rsc"`
RuleId string `json:"ruleid"`
Score string `json:"score"`
Attribute string `json:"attribute"`
Operation string `json:"operation"`
Value string `json:"value"`
}
type RuleGetResponse struct {
utils.GeneralResponse
Data []Rule `json:"data"`
}
func RulesGet(rscName string) RuleGetResponse {
var doc *etree.Document
var rules []*etree.Element
rulelist := []Rule{}
out, err := utils.RunCommand(utils.CmdQueryConstraints)
if err != nil {
goto ret
}
doc = etree.NewDocument()
if err = doc.ReadFromBytes(out); err != nil {
slog.Error("RulesGet: Read xml failed", "error", err)
goto ret
}
rules = doc.FindElements("/constraints/rsc_location")
for _, ruleElem := range rules {
if rsc := ruleElem.SelectAttrValue("rsc", ""); rsc == rscName {
rule := ruleElem.SelectElement("rule")
if rule != nil {
expr := rule.SelectElement("expression")
r := Rule{
Rsc: rsc,
RuleId: rule.SelectAttrValue("id", ""),
Score: rule.SelectAttrValue("score", ""),
}
if expr != nil {
r.Attribute = expr.SelectAttrValue("attribute", "")
r.Operation = expr.SelectAttrValue("operation", "")
r.Value = expr.SelectAttrValue("value", "")
}
rulelist = append(rulelist, r)
}
}
}
return RuleGetResponse{
Data: rulelist,
GeneralResponse: utils.GeneralResponse{
Action: true,
},
}
ret:
return RuleGetResponse{
GeneralResponse: utils.GeneralResponse{
Action: false,
Error: gettext.Gettext("Get rule failed"),
},
}
}
type RuleDeleteResponse struct {
Action bool `json:"action"`
Info string `json:"info,omitempty"`
Error []map[string]interface{} `json:"error,omitempty"`
}
func RulesDelete(ruleids *validations.DeleteRuleS) RuleDeleteResponse {
ruleIdList := ruleids.RuleIDs
slog.Debug("RulesDelete", "ids", ruleIdList)
var res []map[string]interface{}
for _, id := range ruleIdList {
delRuleCmd := fmt.Sprintf(utils.CmdRuleDelete, utils.ShellEscape(id))
_, err := utils.RunCommand(delRuleCmd)
if err != nil {
res = append(res, map[string]interface{}{
"id": id,
"error": fmt.Sprintf(gettext.Gettext("Rule %s could not be found"), id),
})
}
}
if len(res) != 0 {
return RuleDeleteResponse{
Action: false,
Error: res,
}
}
return RuleDeleteResponse{
Action: true,
Info: gettext.Gettext("Delete rule success"),
}
}
func RuleAdd(data *validations.RuleS) utils.GeneralResponse {
slog.Debug("RuleAdd",
"id", data.RuleID,
"value", data.Value,
)
var cmdAddRule string
if data.RuleID != "" {
cmdAddRule = fmt.Sprintf(utils.CmdRuleAddWithId, utils.ShellEscape(data.Rsc), utils.ShellEscape(data.Score), utils.ShellEscape(data.RuleID))
} else {
cmdAddRule = fmt.Sprintf(utils.CmdRuleAdd, utils.ShellEscape(data.Rsc), utils.ShellEscape(data.Score))
}
if data.Value != "" {
cmdAddRule = cmdAddRule + " " + utils.ShellEscape(data.Attribute) + " " + utils.ShellEscape(data.Operation) + " " + utils.ShellEscape(data.Value)
} else {
cmdAddRule = cmdAddRule + " " + utils.ShellEscape(data.Operation) + " " + utils.ShellEscape(data.Attribute)
}
_, err := utils.RunCommand(cmdAddRule)
if err != nil {
return utils.HandleCmdError(gettext.Gettext("Add rule failed, duplicate constraint already exists"), false)
}
slog.Info("Add rule success", "id", data.RuleID)
return utils.GeneralResponse{
Action: true,
Info: gettext.Gettext("Add rule success"),
}
}
func RuleUpdate(data *validations.RuleS) utils.GeneralResponse {
out, err := utils.RunCommand(utils.CmdQueryConstraints)
if err != nil {
return utils.HandleCmdError(err.Error(), false)
}
oldRule := new(validations.RuleS)
doc := etree.NewDocument()
if err := doc.ReadFromBytes(out); err != nil {
return utils.HandleXmlError(err.Error(), false)
}
rules := doc.FindElements("//rsc_location/rule")
for _, ruleElem := range rules {
ruleId := ruleElem.SelectAttrValue("id", "")
if ruleId == data.RuleID {
if parent := ruleElem.Parent(); parent != nil {
oldRule.Rsc = parent.SelectAttrValue("rsc", "")
}
oldRule.RuleID = ruleElem.SelectAttrValue("id", "")
oldRule.Score = ruleElem.SelectAttrValue("score", "")
if expr := ruleElem.SelectElement("expression"); expr != nil {
oldRule.Attribute = expr.SelectAttrValue("attribute", "")
oldRule.Operation = expr.SelectAttrValue("operation", "")
oldRule.Value = expr.SelectAttrValue("value", "")
}
}
}
deleteRuleCmd := fmt.Sprintf(utils.CmdRuleDelete, utils.ShellEscape(data.RuleID))
_, err = utils.RunCommand(deleteRuleCmd)
if err != nil {
return utils.HandleCmdError(
fmt.Sprintf(gettext.Gettext("Update rule failed, rule %s not found"), data.RuleID), false)
}
resp := RuleAdd(data)
if !resp.Action {
RuleAdd(oldRule)
return utils.HandleCmdError(gettext.Gettext("Update rule failed, duplicate constraint already exists"), false)
}
slog.Info("Update rule success", "id", data.RuleID)
return utils.GeneralResponse{
Action: true,
Info: gettext.Gettext("Update rule success"),
}
}