"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"; } } } }); }; };