Files
scrutiny/vendor/github.com/jaypipes/ghw/block.go
T
2020-08-21 06:31:48 +00:00

249 lines
7.1 KiB
Go

//
// Use and distribution licensed under the Apache license version 2.
//
// See the COPYING file in the root project directory for full text.
//
package ghw
import (
"fmt"
"math"
"strings"
)
// DriveType describes the general category of drive device
type DriveType int
const (
DRIVE_TYPE_UNKNOWN DriveType = iota
DRIVE_TYPE_HDD // Hard disk drive
DRIVE_TYPE_FDD // Floppy disk drive
DRIVE_TYPE_ODD // Optical disk drive
DRIVE_TYPE_SSD // Solid-state drive
)
var (
driveTypeString = map[DriveType]string{
DRIVE_TYPE_UNKNOWN: "Unknown",
DRIVE_TYPE_HDD: "HDD",
DRIVE_TYPE_FDD: "FDD",
DRIVE_TYPE_ODD: "ODD",
DRIVE_TYPE_SSD: "SSD",
}
)
func (dt DriveType) String() string {
return driveTypeString[dt]
}
// NOTE(jaypipes): since serialized output is as "official" as we're going to
// get, let's lowercase the string output when serializing, in order to
// "normalize" the expected serialized output
func (dt DriveType) MarshalJSON() ([]byte, error) {
return []byte("\"" + strings.ToLower(dt.String()) + "\""), nil
}
// StorageController is a category of block storage controller/driver. It
// represents more of the physical hardware interface than the storage
// protocol, which represents more of the software interface.
//
// See discussion on https://github.com/jaypipes/ghw/issues/117
type StorageController int
const (
STORAGE_CONTROLLER_UNKNOWN StorageController = iota
STORAGE_CONTROLLER_IDE // Integrated Drive Electronics
STORAGE_CONTROLLER_SCSI // Small computer system interface
STORAGE_CONTROLLER_NVME // Non-volatile Memory Express
STORAGE_CONTROLLER_VIRTIO // Virtualized storage controller/driver
STORAGE_CONTROLLER_MMC // Multi-media controller (used for mobile phone storage devices)
)
var (
storageControllerString = map[StorageController]string{
STORAGE_CONTROLLER_UNKNOWN: "Unknown",
STORAGE_CONTROLLER_IDE: "IDE",
STORAGE_CONTROLLER_SCSI: "SCSI",
STORAGE_CONTROLLER_NVME: "NVMe",
STORAGE_CONTROLLER_VIRTIO: "virtio",
STORAGE_CONTROLLER_MMC: "MMC",
}
)
func (sc StorageController) String() string {
return storageControllerString[sc]
}
// NOTE(jaypipes): since serialized output is as "official" as we're going to
// get, let's lowercase the string output when serializing, in order to
// "normalize" the expected serialized output
func (sc StorageController) MarshalJSON() ([]byte, error) {
return []byte("\"" + strings.ToLower(sc.String()) + "\""), nil
}
// Disk describes a single disk drive on the host system. Disk drives provide
// raw block storage resources.
type Disk struct {
Name string `json:"name"`
SizeBytes uint64 `json:"size_bytes"`
PhysicalBlockSizeBytes uint64 `json:"physical_block_size_bytes"`
DriveType DriveType `json:"drive_type"`
IsRemovable bool `json:"removable"`
StorageController StorageController `json:"storage_controller"`
// NOTE(jaypipes): BusType is DEPRECATED. Use the DriveType and
// StorageController fields instead
BusType BusType `json:"-"`
BusPath string `json:"bus_path"`
// TODO(jaypipes): Convert this to a TopologyNode struct pointer and then
// add to serialized output as "numa_node,omitempty"
NUMANodeID int `json:"-"`
Vendor string `json:"vendor"`
Model string `json:"model"`
SerialNumber string `json:"serial_number"`
WWN string `json:"wwn"`
Partitions []*Partition `json:"partitions"`
// TODO(jaypipes): Add PCI field for accessing PCI device information
// PCI *PCIDevice `json:"pci"`
}
// Partition describes a logical division of a Disk.
type Partition struct {
Disk *Disk `json:"-"`
Name string `json:"name"`
Label string `json:"label"`
MountPoint string `json:"mount_point"`
SizeBytes uint64 `json:"size_bytes"`
Type string `json:"type"`
IsReadOnly bool `json:"read_only"`
}
// BlockInfo describes all disk drives and partitions in the host system.
type BlockInfo struct {
// TODO(jaypipes): Deprecate this field and replace with TotalSizeBytes
TotalPhysicalBytes uint64 `json:"total_size_bytes"`
Disks []*Disk `json:"disks"`
Partitions []*Partition `json:"-"`
}
// Block returns a BlockInfo struct that describes the block storage resources
// of the host system.
func Block(opts ...*WithOption) (*BlockInfo, error) {
mergeOpts := mergeOptions(opts...)
ctx := &context{
chroot: *mergeOpts.Chroot,
}
info := &BlockInfo{}
if err := ctx.blockFillInfo(info); err != nil {
return nil, err
}
return info, nil
}
func (i *BlockInfo) String() string {
tpbs := UNKNOWN
if i.TotalPhysicalBytes > 0 {
tpb := i.TotalPhysicalBytes
unit, unitStr := unitWithString(int64(tpb))
tpb = uint64(math.Ceil(float64(tpb) / float64(unit)))
tpbs = fmt.Sprintf("%d%s", tpb, unitStr)
}
dplural := "disks"
if len(i.Disks) == 1 {
dplural = "disk"
}
return fmt.Sprintf("block storage (%d %s, %s physical storage)",
len(i.Disks), dplural, tpbs)
}
func (d *Disk) String() string {
sizeStr := UNKNOWN
if d.SizeBytes > 0 {
size := d.SizeBytes
unit, unitStr := unitWithString(int64(size))
size = uint64(math.Ceil(float64(size) / float64(unit)))
sizeStr = fmt.Sprintf("%d%s", size, unitStr)
}
atNode := ""
if d.NUMANodeID >= 0 {
atNode = fmt.Sprintf(" (node #%d)", d.NUMANodeID)
}
vendor := ""
if d.Vendor != "" {
vendor = " vendor=" + d.Vendor
}
model := ""
if d.Model != UNKNOWN {
model = " model=" + d.Model
}
serial := ""
if d.SerialNumber != UNKNOWN {
serial = " serial=" + d.SerialNumber
}
wwn := ""
if d.WWN != UNKNOWN {
wwn = " WWN=" + d.WWN
}
removable := ""
if d.IsRemovable {
removable = " removable=true"
}
return fmt.Sprintf(
"%s %s (%s) %s [@%s%s]%s%s%s%s%s",
d.Name,
d.DriveType.String(),
sizeStr,
d.StorageController.String(),
d.BusPath,
atNode,
vendor,
model,
serial,
wwn,
removable,
)
}
func (p *Partition) String() string {
typeStr := ""
if p.Type != "" {
typeStr = fmt.Sprintf("[%s]", p.Type)
}
mountStr := ""
if p.MountPoint != "" {
mountStr = fmt.Sprintf(" mounted@%s", p.MountPoint)
}
sizeStr := UNKNOWN
if p.SizeBytes > 0 {
size := p.SizeBytes
unit, unitStr := unitWithString(int64(size))
size = uint64(math.Ceil(float64(size) / float64(unit)))
sizeStr = fmt.Sprintf("%d%s", size, unitStr)
}
return fmt.Sprintf(
"%s (%s) %s%s",
p.Name,
sizeStr,
typeStr,
mountStr,
)
}
// simple private struct used to encapsulate block information in a top-level
// "block" YAML/JSON map/object key
type blockPrinter struct {
Info *BlockInfo `json:"block" yaml:"block"`
}
// YAMLString returns a string with the block information formatted as YAML
// under a top-level "block:" key
func (i *BlockInfo) YAMLString() string {
return safeYAML(blockPrinter{i})
}
// JSONString returns a string with the block information formatted as JSON
// under a top-level "block:" key
func (i *BlockInfo) JSONString(indent bool) string {
return safeJSON(blockPrinter{i}, indent)
}