This is read once at start of cAdvisor. We can use this to report machine state as well as return logical name for block devices in UI. Signed-off-by: Rohit Jnagal <jnagal@google.com> (github: rjnagal)
109 lines
2.9 KiB
Go
109 lines
2.9 KiB
Go
// Copyright 2014 Google Inc. All Rights Reserved.
|
|
//
|
|
// 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 sysfs
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/google/cadvisor/info"
|
|
)
|
|
|
|
const BlockDir = "/sys/block"
|
|
|
|
// Abstracts the lowest level calls to sysfs.
|
|
type SysFs interface {
|
|
// Get directory information for available block devices.
|
|
GetBlockDevices() ([]os.FileInfo, error)
|
|
// Get Size of a given block device.
|
|
GetBlockDeviceSize(string) (string, error)
|
|
// Get device major:minor number string.
|
|
GetBlockDeviceNumbers(string) (string, error)
|
|
}
|
|
|
|
type realSysFs struct{}
|
|
|
|
func NewRealSysFs() (SysFs, error) {
|
|
return &realSysFs{}, nil
|
|
}
|
|
|
|
func (self *realSysFs) GetBlockDevices() ([]os.FileInfo, error) {
|
|
return ioutil.ReadDir(BlockDir)
|
|
}
|
|
|
|
func (self *realSysFs) GetBlockDeviceNumbers(name string) (string, error) {
|
|
dev, err := ioutil.ReadFile(path.Join(BlockDir, name, "/dev"))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(dev), nil
|
|
}
|
|
|
|
func (self *realSysFs) GetBlockDeviceSize(name string) (string, error) {
|
|
size, err := ioutil.ReadFile(path.Join(BlockDir, name, "/size"))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(size), nil
|
|
}
|
|
|
|
// Get information about block devices present on the system.
|
|
// Uses the passed in system interface to retrieve the low level OS information.
|
|
func GetBlockDeviceInfo(sysfs SysFs) (map[string]info.DiskInfo, error) {
|
|
disks, err := sysfs.GetBlockDevices()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
diskMap := make(map[string]info.DiskInfo)
|
|
for _, disk := range disks {
|
|
name := disk.Name()
|
|
// Ignore loopback and ram devices.
|
|
if strings.HasPrefix(name, "loop") || strings.HasPrefix(name, "ram") {
|
|
continue
|
|
}
|
|
disk_info := info.DiskInfo{
|
|
Name: name,
|
|
}
|
|
dev, err := sysfs.GetBlockDeviceNumbers(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
n, err := fmt.Sscanf(dev, "%d:%d", &disk_info.Major, &disk_info.Minor)
|
|
if err != nil || n != 2 {
|
|
return nil, fmt.Errorf("could not parse device numbers from %s for device %s", dev, name)
|
|
}
|
|
out, err := sysfs.GetBlockDeviceSize(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Remove trailing newline before conversion.
|
|
size, err := strconv.ParseUint(strings.TrimSpace(out), 10, 64)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// size is in 512 bytes blocks.
|
|
disk_info.Size = size * 512
|
|
|
|
device := fmt.Sprintf("%d:%d", disk_info.Major, disk_info.Minor)
|
|
diskMap[device] = disk_info
|
|
}
|
|
return diskMap, nil
|
|
}
|