// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT package stores import ( "bufio" "fmt" "log" "os" "regexp" "strings" "sync" "time" . "github.com/aws/amazon-cloudwatch-agent/internal/containerinsightscommon" "github.com/aws/amazon-cloudwatch-agent/internal/mapWithExpiry" ) type nodeStats struct { podCnt int containerCnt int cpuReq int64 memReq int64 } type nodeInfo struct { nodeStats nodeStats // ebsIds for persistent volume of pod ebsIds *mapWithExpiry.MapWithExpiry // mutex for ebsIds sync.RWMutex *NodeCapacity } func (n *nodeInfo) refreshEbsId() { // rootfs is mounted with the root dir on host file, err := os.Open("/rootfs/proc/mounts") if err != nil { log.Printf("D! cannot open /rootfs/proc/mounts %v", err) return } defer file.Close() reader := bufio.NewReader(file) n.Lock() defer n.Unlock() n.extractEbsId(reader) } func (n *nodeInfo) extractEbsId(reader *bufio.Reader) { ebsMountPointRegex := regexp.MustCompile(`kubernetes.io/aws-ebs/mounts/aws/(.+)/(vol-\w+)`) for { line, isPrefix, err := reader.ReadLine() // err could be EOF in normal case if err != nil { break } // isPrefix is set when a line exceeding 4KB which we treat it as error when reading mount file if isPrefix { break } lineStr := string(line) if strings.TrimSpace(lineStr) == "" { continue } //example line: /dev/nvme1n1 /var/lib/kubelet/plugins/kubernetes.io/aws-ebs/mounts/aws/us-west-2b/vol-0d9f0816149eb2050 ext4 rw,relatime,data=ordered 0 0 keys := strings.Split(lineStr, " ") if len(keys) < 2 { continue } matches := ebsMountPointRegex.FindStringSubmatch(keys[1]) if len(matches) > 0 { // Set {"/dev/nvme1n1": "aws://us-west-2b/vol-0d9f0816149eb2050"} n.ebsIds.Set(keys[0], fmt.Sprintf("aws://%s/%s", matches[1], matches[2])) } } } func (n *nodeInfo) getEbsVolumeId(devName string) string { n.RLock() defer n.RUnlock() if volId, ok := n.ebsIds.Get(devName); ok { return volId.(string) } return "" } func (n *nodeInfo) cleanUp(now time.Time) { n.ebsIds.CleanUp(now) } func newNodeInfo() *nodeInfo { nc := &nodeInfo{ebsIds: mapWithExpiry.NewMapWithExpiry(2 * refreshInterval), NodeCapacity: NewNodeCapacity()} return nc } func (n *nodeInfo) getCPUCapacity() int64 { return n.CPUCapacity * 1000 } func (n *nodeInfo) getMemCapacity() int64 { return n.MemCapacity }