Skip to content

Commit d23aa8b

Browse files
committed
feat(disk): add methods to retrieve block disk health info
longhorn/longhorn-12016 Signed-off-by: Chin-Ya Huang <[email protected]>
1 parent 083a57c commit d23aa8b

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

pkg/api/disk.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,27 @@ type DiskMetrics struct {
3535
ReadIOPS uint64
3636
WriteIOPS uint64
3737
}
38+
39+
type DiskHealth struct {
40+
ModelNumber string
41+
SerialNumber string
42+
FirmwareRevision string
43+
Traddr string
44+
CriticalWarning uint32
45+
TemperatureCelsius float64
46+
AvailableSparePercentage uint32
47+
AvailableSpareThresholdPercentage uint32
48+
PercentageUsed uint32
49+
DataUnitsRead uint64
50+
DataUnitsWritten uint64
51+
HostReadCommands uint64
52+
HostWriteCommands uint64
53+
ControllerBusyTime uint64
54+
PowerCycles uint64
55+
PowerOnHours uint64
56+
UnsafeShutdowns uint64
57+
MediaErrors uint64
58+
NumErrLogEntries uint64
59+
WarningTemperatureTimeMinutes uint64
60+
CriticalCompositeTemperatureTimeMinutes uint64
61+
}

pkg/client/disk.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,56 @@ func (c *DiskServiceClient) DiskGet(diskType, diskName, diskPath, diskDriver str
172172
}, nil
173173
}
174174

175+
// DiskHealthGet returns the disk health info with the given name, path and driver.
176+
func (c *DiskServiceClient) DiskHealthGet(diskType, diskName, diskPath, diskDriver string) (*api.DiskHealth, error) {
177+
if diskName == "" {
178+
return nil, fmt.Errorf("failed to get disk health info: missing required parameter diskName")
179+
}
180+
181+
t, ok := rpc.DiskType_value[diskType]
182+
if !ok {
183+
return nil, fmt.Errorf("failed to get disk health info: invalid disk type %v", diskType)
184+
}
185+
186+
client := c.getDiskServiceClient()
187+
ctx, cancel := context.WithTimeout(context.Background(), types.GRPCServiceTimeout)
188+
defer cancel()
189+
190+
resp, err := client.DiskHealthGet(ctx, &rpc.DiskHealthGetRequest{
191+
DiskType: rpc.DiskType(t),
192+
DiskName: diskName,
193+
DiskPath: diskPath,
194+
DiskDriver: diskDriver,
195+
})
196+
if err != nil {
197+
return nil, err
198+
}
199+
200+
return &api.DiskHealth{
201+
ModelNumber: resp.GetModelNumber(),
202+
SerialNumber: resp.GetSerialNumber(),
203+
FirmwareRevision: resp.GetFirmwareRevision(),
204+
Traddr: resp.GetTraddr(),
205+
CriticalWarning: resp.GetCriticalWarning(),
206+
TemperatureCelsius: resp.GetTemperatureCelsius(),
207+
AvailableSparePercentage: resp.GetAvailableSparePercentage(),
208+
AvailableSpareThresholdPercentage: resp.GetAvailableSpareThresholdPercentage(),
209+
PercentageUsed: resp.GetPercentageUsed(),
210+
DataUnitsRead: resp.GetDataUnitsRead(),
211+
DataUnitsWritten: resp.GetDataUnitsWritten(),
212+
HostReadCommands: resp.GetHostReadCommands(),
213+
HostWriteCommands: resp.GetHostWriteCommands(),
214+
ControllerBusyTime: resp.GetControllerBusyTime(),
215+
PowerCycles: resp.GetPowerCycles(),
216+
PowerOnHours: resp.GetPowerOnHours(),
217+
UnsafeShutdowns: resp.GetUnsafeShutdowns(),
218+
MediaErrors: resp.GetMediaErrors(),
219+
NumErrLogEntries: resp.GetNumErrLogEntries(),
220+
WarningTemperatureTimeMinutes: resp.GetWarningTemperatureTimeMinutes(),
221+
CriticalCompositeTemperatureTimeMinutes: resp.GetCriticalCompositeTemperatureTimeMinutes(),
222+
}, nil
223+
}
224+
175225
// DiskDelete deletes the disk with the given name, disk name, disk UUID, disk path and disk driver.
176226
func (c *DiskServiceClient) DiskDelete(diskType, diskName, diskUUID, diskPath, diskDriver string) error {
177227
if diskName == "" {

pkg/disk/disk.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type DiskOps interface {
3333
DiskCreate(context.Context, *rpc.DiskCreateRequest) (*rpc.Disk, error)
3434
DiskDelete(*rpc.DiskDeleteRequest) (*emptypb.Empty, error)
3535
DiskGet(req *rpc.DiskGetRequest) (*rpc.Disk, error)
36+
DiskHealthGet(req *rpc.DiskHealthGetRequest) (*rpc.DiskHealthGetResponse, error)
3637
DiskReplicaInstanceList(*rpc.DiskReplicaInstanceListRequest) (*rpc.DiskReplicaInstanceListResponse, error)
3738
DiskReplicaInstanceDelete(*rpc.DiskReplicaInstanceDeleteRequest) (*emptypb.Empty, error)
3839
MetricsGet(*rpc.DiskGetRequest) (*rpc.DiskMetricsGetReply, error)
@@ -202,6 +203,53 @@ func (ops BlockDiskOps) DiskGet(req *rpc.DiskGetRequest) (*rpc.Disk, error) {
202203
return spdkDiskToDisk(ret), nil
203204
}
204205

206+
func (s *Server) DiskHealthGet(ctx context.Context, req *rpc.DiskHealthGetRequest) (*rpc.DiskHealthGetResponse, error) {
207+
if req.DiskName == "" {
208+
return nil, grpcstatus.Error(grpccodes.InvalidArgument, "disk name is required")
209+
}
210+
211+
ops, ok := s.ops[req.DiskType]
212+
if !ok {
213+
return nil, grpcstatus.Errorf(grpccodes.Unimplemented, "unsupported disk type %v", req.DiskType)
214+
}
215+
return ops.DiskHealthGet(req)
216+
}
217+
218+
func (op FilesystemDiskOps) DiskHealthGet(req *rpc.DiskHealthGetRequest) (*rpc.DiskHealthGetResponse, error) {
219+
return nil, grpcstatus.Errorf(grpccodes.Unimplemented, "unsupported disk type %v", req.DiskType)
220+
}
221+
222+
func (op BlockDiskOps) DiskHealthGet(req *rpc.DiskHealthGetRequest) (*rpc.DiskHealthGetResponse, error) {
223+
health, err := op.spdkClient.DiskHealthGet(req.DiskName, req.DiskPath, req.DiskDriver)
224+
if err != nil {
225+
return nil, grpcstatus.Error(grpccodes.Internal, err.Error())
226+
}
227+
228+
return &rpc.DiskHealthGetResponse{
229+
ModelNumber: health.ModelNumber,
230+
SerialNumber: health.SerialNumber,
231+
FirmwareRevision: health.FirmwareRevision,
232+
Traddr: health.Traddr,
233+
CriticalWarning: health.CriticalWarning,
234+
TemperatureCelsius: health.TemperatureCelsius,
235+
AvailableSparePercentage: health.AvailableSparePercentage,
236+
AvailableSpareThresholdPercentage: health.AvailableSpareThresholdPercentage,
237+
PercentageUsed: health.PercentageUsed,
238+
DataUnitsRead: health.DataUnitsRead,
239+
DataUnitsWritten: health.DataUnitsWritten,
240+
HostReadCommands: health.HostReadCommands,
241+
HostWriteCommands: health.HostWriteCommands,
242+
ControllerBusyTime: health.ControllerBusyTime,
243+
PowerCycles: health.PowerCycles,
244+
PowerOnHours: health.PowerOnHours,
245+
UnsafeShutdowns: health.UnsafeShutdowns,
246+
MediaErrors: health.MediaErrors,
247+
NumErrLogEntries: health.NumErrLogEntries,
248+
WarningTemperatureTimeMinutes: health.WarningTemperatureTimeMinutes,
249+
CriticalCompositeTemperatureTimeMinutes: health.CriticalCompositeTemperatureTimeMinutes,
250+
}, nil
251+
}
252+
205253
func (s *Server) DiskReplicaInstanceList(ctx context.Context, req *rpc.DiskReplicaInstanceListRequest) (*rpc.DiskReplicaInstanceListResponse, error) {
206254
log := logrus.WithFields(logrus.Fields{
207255
"diskType": req.DiskType,

0 commit comments

Comments
 (0)