"use strict" ;
const Promise = require ( "bluebird" ) ;
const { createDataObject , LocalProperties , ID } = require ( "../../graphql/data-object" ) ;
const upperSnakeCase = require ( "../../upper-snake-case" ) ;
const linearizeTree = require ( "../../linearize-tree" ) ;
const deviceNameFromPath = require ( "../../device-name-from-path" ) ;
module . exports = function ( types ) {
return function Drive ( { path } ) {
return createDataObject ( {
[ LocalProperties ] : {
path : path ,
blockDevice : ( ) => {
return types . BlockDevice ( { path : path } ) ;
} ,
/* FIXME: allBlockDevices, for representing every single block device that's hosted on this physical drive, linearly. Need to figure out how that works with representation of mdraid arrays, LVM volumes, etc. */
} ,
lsblk : {
[ ID ] : deviceNameFromPath ( path ) ,
allBlockDevices : function ( rootDevice , { type } , context ) {
let devices = linearizeTree ( [ rootDevice ] )
. map ( ( device ) => types . BlockDevice ( { name : device . name } ) ) ;
if ( type != null ) {
return Promise . filter ( devices , ( device ) => {
return Promise . try ( ( ) => {
return device . type ( { } , context ) ;
} ) . then ( ( deviceType ) => {
return ( deviceType === type ) ;
} ) ;
} ) ;
} else {
return devices ;
}
}
} ,
smartctlScan : {
[ ID ] : path ,
interface : "interface"
} ,
smartctlInfo : {
[ ID ] : path ,
model : "model" ,
modelFamily : "modelFamily" ,
smartAvailable : "smartAvailable" ,
smartEnabled : "smartEnabled" ,
serialNumber : "serialNumber" ,
wwn : "wwn" ,
firmwareVersion : "firmwareVersion" ,
size : "size" ,
rpm : "rpm" ,
logicalSectorSize : ( device ) => device . sectorSizes . logical ,
physicalSectorSize : ( device ) => device . sectorSizes . physical ,
formFactor : "formFactor" ,
ataVersion : "ataVersion" ,
sataVersion : "sataVersion"
} ,
smartctlAttributes : {
[ ID ] : path ,
smartAttributes : ( attributes ) => {
return attributes . map ( ( attribute ) => {
return Object . assign ( { } , attribute , {
type : upperSnakeCase ( attribute . type ) ,
updatedWhen : upperSnakeCase ( attribute . updatedWhen )
} ) ;
} ) ;
} ,
smartHealth : ( attributes ) => {
let failed = attributes . filter ( ( item ) => {
return ( item . failingNow === true || item . failedBefore === true ) ;
} ) ;
let deteriorating = attributes . filter ( ( item ) => {
return ( item . type === "preFail" && item . worstValueSeen < 100 ) ;
} ) ;
if ( failed . length > 0 ) {
return "FAILING" ;
} else if ( deteriorating . length > 0 ) {
return "DETERIORATING" ;
} else {
return "HEALTHY" ;
}
}
}
} ) ;
} ;
} ;