|
|
|
"use strict";
|
|
|
|
|
|
|
|
const Promise = require("bluebird");
|
|
|
|
const memoizee = require("memoizee");
|
|
|
|
const DataLoader = require("dataloader");
|
|
|
|
const mapObj = require("map-obj");
|
|
|
|
|
|
|
|
const lvm = require("../../packages/exec-lvm");
|
|
|
|
const All = require("../../packages/graphql-interface/symbols/all");
|
|
|
|
const nvmeCLI = require("../../packages/exec-nvme-cli");
|
|
|
|
const smartctl = require("../../packages/exec-smartctl");
|
|
|
|
const dlayerWrap = require("../../packages/dlayer-wrap");
|
|
|
|
|
|
|
|
// This generates a (memoized) source function for commands that always produce an entire list, that needs to be filtered for the desired item(s)
|
|
|
|
function makeListCommand({ command, selectResult, selectID }) {
|
|
|
|
let commandOnce = memoizee(command);
|
|
|
|
|
|
|
|
return function (ids) {
|
|
|
|
return Promise.try(() => {
|
|
|
|
return commandOnce();
|
|
|
|
}).then((result) => {
|
|
|
|
if (selectResult != null) {
|
|
|
|
return selectResult(result);
|
|
|
|
} else {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}).then((items) => {
|
|
|
|
return ids.map((id) => {
|
|
|
|
if (id === All) {
|
|
|
|
return items;
|
|
|
|
} else {
|
|
|
|
return items.find((item) => selectID(item) === id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function makeSingleCommand({ command, selectResult }) {
|
|
|
|
return function (ids) {
|
|
|
|
return Promise.map(ids, (id) => {
|
|
|
|
if (id === All) {
|
|
|
|
// FIXME: Have some sort of mechanism for making this possible?
|
|
|
|
throw new Error(`This data source does not support fetching all entries`);
|
|
|
|
} else {
|
|
|
|
return command(id);
|
|
|
|
}
|
|
|
|
}).map((result) => {
|
|
|
|
if (selectResult != null) {
|
|
|
|
return selectResult(result);
|
|
|
|
} else {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = function createSources() {
|
|
|
|
let sources = {
|
|
|
|
lvmLogicalVolumes: makeListCommand({
|
|
|
|
command: lvm.getLogicalVolumes,
|
|
|
|
selectResult: (result) => result.volumes,
|
|
|
|
selectID: (volume) => volume.path
|
|
|
|
}),
|
|
|
|
lvmPhysicalVolumes: makeListCommand({
|
|
|
|
command: lvm.getPhysicalVolumes,
|
|
|
|
selectResult: (result) => result.volumes,
|
|
|
|
selectID: (device) => device.path
|
|
|
|
}),
|
|
|
|
lvmVolumeGroups: makeListCommand({
|
|
|
|
command: lvm.getVolumeGroups,
|
|
|
|
selectResult: (result) => result.groups,
|
|
|
|
selectID: (group) => group.name
|
|
|
|
}),
|
|
|
|
nvmeIdentifyController: makeSingleCommand({
|
|
|
|
command: (path) => nvmeCLI.identifyController({ devicePath: path })
|
|
|
|
}),
|
|
|
|
nvmeListNamespaces: makeSingleCommand({
|
|
|
|
command: (path) => nvmeCLI.listNamespaces({ devicePath: path })
|
|
|
|
}),
|
|
|
|
smartctlScan: makeListCommand({
|
|
|
|
command: smartctl.scan,
|
|
|
|
selectID: (device) => device.path
|
|
|
|
}),
|
|
|
|
smartctlInfo: makeSingleCommand({
|
|
|
|
command: (path) => dlayerWrap(() => smartctl.info({ devicePath: path }), {
|
|
|
|
allowedErrors: [ smartctl.InfoError ]
|
|
|
|
})
|
|
|
|
}),
|
|
|
|
smartctlAttributes: makeSingleCommand({
|
|
|
|
command: (path) => dlayerWrap(() => smartctl.attributes({ devicePath: path }), {
|
|
|
|
allowedErrors: [ smartctl.AttributesError ]
|
|
|
|
})
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
|
|
|
let factoryModules = {
|
|
|
|
lsblk: require("./lsblk")(),
|
|
|
|
findmnt: require("./findmnt")()
|
|
|
|
};
|
|
|
|
|
|
|
|
return mapObj({ ... factoryModules, ... sources }, (name, factory) => {
|
|
|
|
return [
|
|
|
|
name,
|
|
|
|
new DataLoader(factory)
|
|
|
|
];
|
|
|
|
});
|
|
|
|
};
|