mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-07 12:44:06 +08:00
⛄ Sync 2026-04-23 20:32:35
This commit is contained in:
1 parent
17738c6f79
commit
fe51d2b304
206 files changed
+725671
No files matched your search
@@ -0,0 +1,386 @@
|
||||
'use strict';
|
||||
'require view';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require rpc';
|
||||
'require form';
|
||||
|
||||
const callBlockDevices = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getBlockDevices',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
const callMountPoints = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getMountPoints',
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
const callBlockDetect = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'setBlockDetect',
|
||||
expect: { result: false }
|
||||
});
|
||||
|
||||
function device_textvalue(devices, section_id) {
|
||||
let v = (uci.get('fstab', section_id, 'uuid') || '').toLowerCase();
|
||||
let e = Object.keys(devices).filter(function(dev) { return (devices[dev].uuid || '-').toLowerCase() == v })[0];
|
||||
|
||||
if (v) {
|
||||
this.section.devices[section_id] = devices[e];
|
||||
|
||||
if (e && devices[e].size)
|
||||
return E('span', 'UUID: %h (%s, %1024.2mB)'.format(v, devices[e].dev, devices[e].size));
|
||||
else if (e)
|
||||
return E('span', 'UUID: %h (%s)'.format(v, devices[e].dev));
|
||||
else
|
||||
return E('span', 'UUID: %h (<em>%s</em>)'.format(v, _('not present')));
|
||||
}
|
||||
|
||||
v = uci.get('fstab', section_id, 'label');
|
||||
e = Object.keys(devices).filter(function(dev) { return devices[dev].label == v })[0];
|
||||
|
||||
if (v) {
|
||||
this.section.devices[section_id] = this.section.devices[section_id] || devices[e];
|
||||
|
||||
if (e && devices[e].size)
|
||||
return E('span', 'Label: %h (%s, %1024.2mB)'.format(v, devices[e].dev, devices[e].size));
|
||||
else if (e)
|
||||
return E('span', 'Label: %h (%s)'.format(v, devices[e].dev));
|
||||
else
|
||||
return E('span', 'Label: %h (<em>%s</em>)'.format(v, _('not present')));
|
||||
}
|
||||
|
||||
v = uci.get('fstab', section_id, 'device');
|
||||
e = Object.keys(devices).filter(function(dev) { return devices[dev].dev == v })[0];
|
||||
|
||||
if (v) {
|
||||
this.section.devices[section_id] = this.section.devices[section_id] || devices[e];
|
||||
|
||||
if (e && devices[e].size)
|
||||
return E('span', '%h (%1024.2mB)'.format(v, devices[e].size));
|
||||
else if (e)
|
||||
return E('span', '%h'.format(v));
|
||||
else
|
||||
return E('span', '%h (<em>%s</em>)'.format(v, _('not present')));
|
||||
}
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
handleDetect(m, ev) {
|
||||
return callBlockDetect()
|
||||
.then(L.bind(uci.unload, uci, 'fstab'))
|
||||
.then(L.bind(m.render, m));
|
||||
},
|
||||
|
||||
handleMountAll(m, ev) {
|
||||
return fs.exec('/sbin/block', ['mount'])
|
||||
.then(function(res) {
|
||||
if (res.code != 0)
|
||||
ui.addNotification(null, E('p', _('The <em>block mount</em> command failed with code %d').format(res.code)));
|
||||
})
|
||||
.then(L.bind(uci.unload, uci, 'fstab'))
|
||||
.then(L.bind(m.render, m));
|
||||
},
|
||||
|
||||
handleUmount(m, path, ev) {
|
||||
return fs.exec('/bin/umount', [path])
|
||||
.then(L.bind(uci.unload, uci, 'fstab'))
|
||||
.then(L.bind(m.render, m))
|
||||
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
|
||||
},
|
||||
|
||||
load() {
|
||||
return Promise.all([
|
||||
callBlockDevices(),
|
||||
fs.lines('/proc/filesystems'),
|
||||
fs.lines('/etc/filesystems'),
|
||||
uci.load('fstab'),
|
||||
]);
|
||||
},
|
||||
|
||||
render([devices, procfs, etcfs]) {
|
||||
let m, s, o;
|
||||
|
||||
let filesystems = {};
|
||||
|
||||
for (let p of procfs)
|
||||
if (p.match(/\S/) && !p.match(/^nodev\t/))
|
||||
filesystems[p.trim()] = true;
|
||||
|
||||
for (let e of etcfs)
|
||||
if (e.match(/\S/))
|
||||
filesystems[e.trim()] = true;
|
||||
|
||||
filesystems = Object.keys(filesystems).sort();
|
||||
|
||||
|
||||
if (!uci.sections('fstab', 'global').length)
|
||||
uci.add('fstab', 'global');
|
||||
|
||||
m = new form.Map('fstab', _('Mount Points'));
|
||||
|
||||
s = m.section(form.TypedSection, 'global', _('Global Settings'));
|
||||
s.addremove = false;
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.Button, '_detect', _('Generate Config'), _('Find all currently attached filesystems and swap and replace configuration with defaults based on what was detected'));
|
||||
o.onclick = this.handleDetect.bind(this, m);
|
||||
o.inputstyle = 'reload';
|
||||
|
||||
o = s.option(form.Button, '_mountall', _('Mount attached devices'), _('Attempt to enable configured mount points for attached devices'));
|
||||
o.onclick = this.handleMountAll.bind(this, m);
|
||||
o.inputstyle = 'reload';
|
||||
|
||||
o = s.option(form.Flag, 'anon_swap', _('Anonymous Swap'), _('Mount swap not specifically configured'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'anon_mount', _('Anonymous Mount'), _('Mount filesystems not specifically configured'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'auto_swap', _('Automount Swap'), _('Automatically mount swap on hotplug'));
|
||||
o.default = o.enabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'auto_mount', _('Automount Filesystem'), _('Automatically mount filesystems on hotplug'));
|
||||
o.default = o.enabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'check_fs', _('Check filesystems before mount'), _('Automatically check filesystem for errors before mounting'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
|
||||
// Mount status table
|
||||
o = s.option(form.DummyValue, '_mtab');
|
||||
|
||||
o.load = function(section_id) {
|
||||
return callMountPoints().then(L.bind(function(mounts) {
|
||||
this.mounts = mounts;
|
||||
}, this));
|
||||
};
|
||||
|
||||
o.render = L.bind(function(view, section_id) {
|
||||
const table = E('table', { 'class': 'table' }, [
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', { 'class': 'th' }, _('Filesystem')),
|
||||
E('th', { 'class': 'th' }, _('Mount Point')),
|
||||
E('th', { 'class': 'th center' }, _('Available')),
|
||||
E('th', { 'class': 'th center' }, _('Used')),
|
||||
E('th', { 'class': 'th' }, _('Unmount'))
|
||||
])
|
||||
]);
|
||||
|
||||
const rows = [];
|
||||
|
||||
for (let tm of this.mounts) {
|
||||
var used = tm.size - tm.free,
|
||||
umount = true;
|
||||
|
||||
if (/^\/(overlay|rom|tmp(?:\/.+)?|dev(?:\/.+)?|)$/.test(tm.mount))
|
||||
umount = false;
|
||||
|
||||
rows.push([
|
||||
tm.device,
|
||||
tm.mount,
|
||||
'%1024.2mB / %1024.2mB'.format(tm.avail, tm.size),
|
||||
'%.2f%% (%1024.2mB)'.format(100 / tm.size * used, used),
|
||||
umount ? E('button', {
|
||||
'class': 'btn cbi-button-remove',
|
||||
'click': ui.createHandlerFn(view, 'handleUmount', m, tm.mount),
|
||||
'disabled': this.map.readonly || null
|
||||
}, [ _('Unmount') ]) : '-'
|
||||
]);
|
||||
}
|
||||
|
||||
cbi_update_table(table, rows, E('em', _('Unable to obtain mount information')));
|
||||
|
||||
return E([], [ E('h3', _('Mounted file systems')), table ]);
|
||||
}, o, this);
|
||||
|
||||
|
||||
// Mounts
|
||||
s = m.section(form.GridSection, 'mount', _('Mount Points'), _('Mount Points define at which point a memory device will be attached to the filesystem'));
|
||||
s.modaltitle = _('Mount Points - Mount Entry');
|
||||
s.anonymous = true;
|
||||
s.addremove = true;
|
||||
s.sortable = true;
|
||||
s.devices = {};
|
||||
|
||||
s.renderHeaderRows = function(/* ... */) {
|
||||
var trEls = form.GridSection.prototype.renderHeaderRows.apply(this, arguments);
|
||||
return trEls.childNodes[0];
|
||||
}
|
||||
|
||||
s.tab('general', _('General Settings'));
|
||||
s.tab('advanced', _('Advanced Settings'));
|
||||
|
||||
o = s.taboption('general', form.Flag, 'enabled', _('Enabled'));
|
||||
o.rmempty = false;
|
||||
o.default = true;
|
||||
o.editable = true;
|
||||
|
||||
o = s.taboption('general', form.DummyValue, '_device', _('Device'));
|
||||
o.rawhtml = true;
|
||||
o.modalonly = false;
|
||||
o.write = function() {};
|
||||
o.remove = function() {};
|
||||
o.textvalue = device_textvalue.bind(o, devices);
|
||||
|
||||
o = s.taboption('general', form.Value, 'uuid', _('UUID'), _('If specified, mount the device by its UUID instead of a fixed device node'));
|
||||
o.modalonly = true;
|
||||
o.value('', _('-- match by uuid --'));
|
||||
|
||||
const devs = Object.keys(devices).sort();
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.uuid && dev.size)
|
||||
o.value(dev.uuid, '%s (%s, %1024.2mB)'.format(dev.uuid, dev.dev, dev.size));
|
||||
else if (dev.uuid)
|
||||
o.value(dev.uuid, '%s (%s)'.format(dev.uuid, dev.dev));
|
||||
}
|
||||
|
||||
o = s.taboption('general', form.Value, 'label', _('Label'), _('If specified, mount the device by the partition label instead of a fixed device node'));
|
||||
o.modalonly = true;
|
||||
o.depends('uuid', '');
|
||||
o.value('', _('-- match by label --'));
|
||||
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.label && dev.size)
|
||||
o.value(dev.label, '%s (%s, %1024.2mB)'.format(dev.label, dev.dev, dev.size));
|
||||
else if (dev.label)
|
||||
o.value(dev.label, '%s (%s)'.format(dev.label, dev.dev));
|
||||
}
|
||||
|
||||
o = s.taboption('general', form.Value, 'device', _('Device'), _('The device file of the memory or partition (<abbr title="for example">e.g.</abbr> <code>/dev/sda1</code>)'));
|
||||
o.modalonly = true;
|
||||
o.depends({ uuid: '', label: '' });
|
||||
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.size)
|
||||
o.value(dev.dev, '%s (%1024.2mB)'.format(dev.dev, dev.size));
|
||||
else
|
||||
o.value(dev.dev);
|
||||
}
|
||||
|
||||
o = s.taboption('general', form.Value, 'target', _('Mount point'), _('Specifies the directory the device is attached to'));
|
||||
o.value('/', _('Use as root filesystem (/)'));
|
||||
o.value('/overlay', _('Use as external overlay (/overlay)'));
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('general', form.DummyValue, '__notice', _('Root preparation'));
|
||||
o.depends('target', '/');
|
||||
o.modalonly = true;
|
||||
o.rawhtml = true;
|
||||
o.default = '' +
|
||||
'<p>%s</p>'.format(_('Make sure to clone the root filesystem using something like the commands below:')) +
|
||||
'<pre>' +
|
||||
'mkdir -p /tmp/introot\n' +
|
||||
'mkdir -p /tmp/extroot\n' +
|
||||
'mount --bind / /tmp/introot\n' +
|
||||
'mount /dev/sda1 /tmp/extroot\n' +
|
||||
'tar -C /tmp/introot -cvf - . | tar -C /tmp/extroot -xf -\n' +
|
||||
'umount /tmp/introot\n' +
|
||||
'umount /tmp/extroot\n' +
|
||||
'</pre>'
|
||||
;
|
||||
|
||||
o = s.taboption('advanced', form.ListValue, 'fstype', _('Filesystem'));
|
||||
|
||||
o.textvalue = function(section_id) {
|
||||
const dev = this.section.devices[section_id];
|
||||
let text = this.cfgvalue(section_id) || 'auto';
|
||||
|
||||
if (dev && dev.type && dev.type != text)
|
||||
text += ' (%s)'.format(dev.type);
|
||||
|
||||
return text;
|
||||
};
|
||||
|
||||
o.value('', 'auto');
|
||||
|
||||
for (let fs of filesystems)
|
||||
o.value(fs);
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'options', _('Mount options'), _('See "mount" manpage for details'));
|
||||
o.textvalue = function(section_id) { return this.cfgvalue(section_id) || 'defaults' };
|
||||
o.placeholder = 'defaults';
|
||||
|
||||
|
||||
// Swaps
|
||||
s = m.section(form.GridSection, 'swap', _('SWAP'), _('If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable <abbr title="Random Access Memory">RAM</abbr>. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the <abbr title="Random Access Memory">RAM</abbr>.'));
|
||||
s.modaltitle = _('Mount Points - Swap Entry');
|
||||
s.anonymous = true;
|
||||
s.addremove = true;
|
||||
s.sortable = true;
|
||||
s.devices = {};
|
||||
|
||||
s.renderHeaderRows = function(/* ... */) {
|
||||
var trEls = form.GridSection.prototype.renderHeaderRows.apply(this, arguments);
|
||||
trEls.childNodes[0].childNodes[1].style.width = '90%';
|
||||
return trEls.childNodes[0];
|
||||
}
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enabled'));
|
||||
o.rmempty = false;
|
||||
o.editable = true;
|
||||
|
||||
o = s.option(form.DummyValue, '_device', _('Device'));
|
||||
o.modalonly = false;
|
||||
o.textvalue = device_textvalue.bind(o, devices);
|
||||
|
||||
o = s.option(form.Value, 'uuid', _('UUID'), _('If specified, mount the device by its UUID instead of a fixed device node'));
|
||||
o.modalonly = true;
|
||||
o.value('', _('-- match by uuid --'));
|
||||
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
|
||||
continue;
|
||||
|
||||
if (dev.uuid && dev.size)
|
||||
o.value(dev.uuid, '%s (%s, %1024.2mB)'.format(dev.uuid, dev.dev, dev.size));
|
||||
else if (dev.uuid)
|
||||
o.value(dev.uuid, '%s (%s)'.format(dev.uuid, dev.dev));
|
||||
}
|
||||
|
||||
o = s.option(form.Value, 'label', _('Label'), _('If specified, mount the device by the partition label instead of a fixed device node'));
|
||||
o.modalonly = true;
|
||||
o.depends('uuid', '');
|
||||
o.value('', _('-- match by label --'));
|
||||
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
|
||||
continue;
|
||||
|
||||
if (dev.label && dev.size)
|
||||
o.value(dev.label, '%s (%s, %1024.2mB)'.format(dev.label, dev.dev, dev.size));
|
||||
else if (dev.label)
|
||||
o.value(dev.label, '%s (%s)'.format(dev.label, dev.dev));
|
||||
}
|
||||
|
||||
o = s.option(form.Value, 'device', _('Device'), _('The device file of the memory or partition (<abbr title="for example">e.g.</abbr> <code>/dev/sda1</code>)'));
|
||||
o.modalonly = true;
|
||||
o.depends({ uuid: '', label: '' });
|
||||
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
|
||||
continue;
|
||||
|
||||
if (dev.size)
|
||||
o.value(dev.dev, '%s (%1024.2mB)'.format(dev.dev, dev.size));
|
||||
else
|
||||
o.value(dev.dev);
|
||||
}
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user