Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package faultcontrol
import (
"errors"
"fmt"
"sync"
"ascend-common/common-utils/hwlog"
"nodeD/pkg/common"
"nodeD/pkg/common/manager"
)
type NodeController struct {
faultManager manager.FaultManager
configManager manager.ConfigManager
faultLevelMap map[string]int
faultLevelMapLock *sync.Mutex
}
func NewNodeController() *NodeController {
return &NodeController{
configManager: manager.NewConfigManager(),
faultManager: manager.NewFaultManager(),
faultLevelMap: map[string]int{},
faultLevelMapLock: &sync.Mutex{},
}
}
func (nc *NodeController) Name() string {
return common.PluginControlFault
}
func (nc *NodeController) UpdateConfig(faultConfig *common.FaultConfig) *common.FaultConfig {
if faultConfig == nil {
return nil
}
if err := nc.updateFaultLevelMap(faultConfig.FaultTypeCode); err != nil {
return nil
}
nc.configManager.SetFaultConfig(faultConfig)
return faultConfig
}
func (nc *NodeController) Control(fcInfo *common.FaultAndConfigInfo) *common.FaultAndConfigInfo {
if fcInfo.FaultDevInfo != nil {
fcInfo.FaultDevInfo = nc.updateFault(fcInfo.FaultDevInfo)
}
if fcInfo.FaultConfig != nil {
fcInfo.FaultConfig = nc.UpdateConfig(fcInfo.FaultConfig)
}
return fcInfo
}
func (nc *NodeController) updateFault(faultDevInfo *common.FaultDevInfo) *common.FaultDevInfo {
faultDevs := nc.getSupportFaultDev(faultDevInfo)
var nodeFaultLevel int64
for _, faultDev := range faultDevs {
faultLevelStr, faultLevelInt := nc.getFaultLevel(faultDev.FaultCode)
faultDev.FaultLevel = faultLevelStr
if faultLevelInt > nodeFaultLevel {
nodeFaultLevel = faultLevelInt
}
}
nc.faultManager.SetFaultDevList(faultDevs)
nc.faultManager.SetNodeStatus(nc.getNodeStatus(nodeFaultLevel))
return nc.faultManager.GetFaultDevInfo()
}
func (nc *NodeController) getSupportFaultDev(faultDevInfo *common.FaultDevInfo) []*common.FaultDev {
faultDevs := make([]*common.FaultDev, 0)
for _, faultDev := range faultDevInfo.FaultDevList {
tmpFaultDev := &common.FaultDev{
DeviceType: faultDev.DeviceType,
DeviceId: faultDev.DeviceId,
FaultCode: nc.filterNotSupportFaultCodes(faultDev.FaultCode),
FaultLevel: faultDev.FaultLevel,
}
if len(tmpFaultDev.FaultCode) > 0 {
faultDevs = append(faultDevs, tmpFaultDev)
}
}
return faultDevs
}
func (nc *NodeController) filterNotSupportFaultCodes(faultCodes []string) []string {
newFaultCodes := make([]string, 0)
for _, faultCode := range faultCodes {
if _, ok := nc.faultLevelMap[faultCode]; ok {
newFaultCodes = append(newFaultCodes, faultCode)
}
}
return newFaultCodes
}
func (nc *NodeController) updateFaultLevelMap(faultTypeCode *common.FaultTypeCode) error {
if faultTypeCode == nil {
hwlog.RunLog.Error("fault type code is nil")
return errors.New("fault type code is nil")
}
newFaultLevelMap := make(map[string]int, 0)
for _, notHandleFaultCode := range faultTypeCode.NotHandleFaultCodes {
if _, ok := newFaultLevelMap[notHandleFaultCode]; ok {
hwlog.RunLog.Errorf("update not handle fault code failed, code %s is conflict", notHandleFaultCode)
return fmt.Errorf("not handle code %s is conflict, "+
"please check whether the code not just configured at not handle level", notHandleFaultCode)
}
newFaultLevelMap[notHandleFaultCode] = common.NotHandleFaultLevel
}
for _, preSeparateFaultCode := range faultTypeCode.PreSeparateFaultCodes {
if _, ok := newFaultLevelMap[preSeparateFaultCode]; ok {
hwlog.RunLog.Errorf("update pre separate fault code failed, "+
"code %s is conflict", preSeparateFaultCode)
return fmt.Errorf("pre separate code %s is conflict, "+
"please check whether the code not just configured at pre separate level", preSeparateFaultCode)
}
newFaultLevelMap[preSeparateFaultCode] = common.PreSeparateFaultLevel
}
for _, separateFaultCode := range faultTypeCode.SeparateFaultCodes {
if _, ok := newFaultLevelMap[separateFaultCode]; ok {
hwlog.RunLog.Errorf("update separate fault code failed, "+
"code %s is conflict", separateFaultCode)
return fmt.Errorf("separate fault code %s is conflict, "+
"please check whether the code not just configured at separate level", separateFaultCode)
}
newFaultLevelMap[separateFaultCode] = common.SeparateFaultLevel
}
nc.faultLevelMapLock.Lock()
nc.faultLevelMap = newFaultLevelMap
nc.faultLevelMapLock.Unlock()
hwlog.RunLog.Debugf("new fault level map is %v", newFaultLevelMap)
return nil
}
func (nc *NodeController) getFaultLevel(faultCodes []string) (string, int64) {
maxLevel := 0
for _, faultCode := range faultCodes {
if level, ok := nc.faultLevelMap[faultCode]; ok {
if level > maxLevel {
maxLevel = level
}
}
}
switch maxLevel {
case common.PreSeparateFaultLevel:
return common.PreSeparateFault, common.PreSeparateFaultLevel
case common.SeparateFaultLevel:
return common.SeparateFault, common.SeparateFaultLevel
default:
return common.NotHandleFault, common.NotHandleFaultLevel
}
}
func (nc *NodeController) getNodeStatus(nodeFaultLevel int64) string {
switch nodeFaultLevel {
case common.NodeUnHealthyLevel:
return common.NodeUnHealthy
case common.NodeSubHealthyLevel:
return common.PreSeparate
case common.NodeHealthyLevel:
return common.NodeHealthy
default:
return ""
}
}