-
Notifications
You must be signed in to change notification settings - Fork 3
/
lsblk.go
106 lines (87 loc) · 2.78 KB
/
lsblk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package backup
import (
"encoding/json"
"fmt"
"naksu/log"
"naksu/mebroutines"
)
// LsblkOutput represents the parsed JSON output of an lsblk -J command.
type LsblkOutput struct {
BlockDevices []BlockDevice `json:"blockdevices"`
}
// BlockDevice represents a single block device entry in the JSON output of an
// lsblk -J command.
type BlockDevice struct {
Name string `json:"name"`
FileSystem string `json:"fstype"`
MountPoint string `json:"mountpoint"`
Vendor string `json:"vendor"`
Model string `json:"model"`
HotPlug interface{} `json:"hotplug"`
Children []BlockDevice `json:"children"`
}
// ListBlockDevices generates a listing of the available block devices using
// lsblk. Usable only on Linux hosts.
func ListBlockDevices() (*LsblkOutput, error) {
runParams := []string{"lsblk", "-J", "-o", "NAME,FSTYPE,MOUNTPOINT,VENDOR,MODEL,HOTPLUG"}
lsblkJSON, lsblkErr := mebroutines.RunAndGetOutput(runParams)
log.Debug("lsblk says:")
log.Debug(lsblkJSON)
if lsblkErr != nil {
log.Debug("Failed to run lsblk")
return &LsblkOutput{}, lsblkErr
}
output, jsonErr := ParseLsblkJSON(lsblkJSON)
if jsonErr != nil {
log.Debug("Unable to unmarshal lsblk response:")
log.Debug(fmt.Sprintf("%s", jsonErr))
return &LsblkOutput{}, lsblkErr
}
return output, nil
}
// GetRemovableDisks processes lsblk output to return a listing of connected
// removable devices. The return value is a map from mount points to block
// device names.
func (blk *LsblkOutput) GetRemovableDisks() map[string]string {
media := map[string]string{}
if blk.BlockDevices == nil {
return media
}
for blockdeviceIndex := range blk.BlockDevices {
thisBlockdevice := blk.BlockDevices[blockdeviceIndex]
if thisBlockdevice.IsRemovable() && thisBlockdevice.Children != nil {
thisChildren := thisBlockdevice.Children
for thisChildIndex := range thisChildren {
thisChild := thisChildren[thisChildIndex]
thisMountpoint := thisChild.MountPoint
if thisMountpoint != "" {
media[thisMountpoint] = fmt.Sprintf("%s, %s", thisBlockdevice.Vendor, thisBlockdevice.Model)
}
}
}
}
return media
}
// IsRemovable returns true if the block device is a removable device (e.g. a
// USB drive) and false otherwise.
func (bd *BlockDevice) IsRemovable() bool {
switch hotplug := bd.HotPlug.(type) {
case bool:
return hotplug
case string:
switch hotplug {
case "0":
return false
case "1":
return true
}
}
log.Debug(fmt.Sprintf("Unknown format for hotplug field in lsblk output: %v", bd.HotPlug))
return false
}
// ParseLsblkJSON parses JSON output from an lsblk -J command.
func ParseLsblkJSON(lsblkJSON string) (*LsblkOutput, error) {
var jsonData LsblkOutput
jsonErr := json.Unmarshal([]byte(lsblkJSON), &jsonData)
return &jsonData, jsonErr
}