luci-app-diskman: sync with upstream source
This commit is contained in:
parent
bc0f4f7a6e
commit
e8a224f2a7
@ -43,4 +43,4 @@ define Package/$(PKG_NAME)/install
|
||||
po2lmo ./po/pl/diskman.po $(1)/usr/lib/lua/luci/i18n/diskman.pl.lmo
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
@ -1 +1 @@
|
||||
e2fsprogs parted smartmontools blkid
|
||||
e2fsprogs parted smartmontools blkid mdadm btrfs-progs util-linux mergerfs snapraid
|
||||
@ -29,6 +29,7 @@ function index()
|
||||
entry({"admin", "system", "diskman"}, alias("admin", "system", "diskman", "disks"), _("Disk Man"), 55)
|
||||
entry({"admin", "system", "diskman", "disks"}, form("diskman/disks"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "partition"}, form("diskman/partition"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "btrfs"}, form("diskman/btrfs"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "get_disk_info"}, call("get_disk_info"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "mk_p_table"}, call("mk_p_table"), nil).leaf = true
|
||||
entry({"admin", "system", "diskman", "smartdetail"}, call("smart_detail"), nil).leaf = true
|
||||
|
||||
@ -0,0 +1,167 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2019 lisaac <https://github.com/lisaac/luci-app-diskman>
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
require "luci.util"
|
||||
require("luci.tools.webadmin")
|
||||
local dm = require "luci.model.diskman"
|
||||
local uuid = arg[1]
|
||||
|
||||
if not uuid then luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman")) end
|
||||
|
||||
m = SimpleForm("btrfs", translate("Btrfs"), translate("Manage Btrfs."))
|
||||
m.submit = false
|
||||
m.reset = false
|
||||
m.redirect = luci.dispatcher.build_url("admin/system/diskman")
|
||||
|
||||
-- subvolume
|
||||
local subvolume_list, mount_point = dm.get_btrfs_subv(uuid)
|
||||
subvolume_list["_"] = { ID = 0 }
|
||||
table_subvolume = m:section(Table, subvolume_list, translate("SubVolumes"))
|
||||
table_subvolume:option(DummyValue, "id", translate("ID"))
|
||||
table_subvolume:option(DummyValue, "top_level", translate("Top Level"))
|
||||
table_subvolume:option(DummyValue, "uuid", translate("UUID"))
|
||||
table_subvolume:option(DummyValue, "otime", translate("Otime"))
|
||||
table_subvolume:option(DummyValue, "snapshots", translate("Snapshots"))
|
||||
local v_path = table_subvolume:option(Value, "path", translate("Path"))
|
||||
v_path.forcewrite = true
|
||||
v_path.render = function(self, section, scope)
|
||||
if subvolume_list[section].ID == 0 then
|
||||
self.template = "cbi/value"
|
||||
self.placeholder = "/my_subvolume"
|
||||
self.forcewrite = true
|
||||
Value.render(self, section, scope)
|
||||
else
|
||||
self.template = "cbi/dvalue"
|
||||
DummyValue.render(self, section, scope)
|
||||
end
|
||||
end
|
||||
local value_path
|
||||
v_path.write = function(self, section, value)
|
||||
value_path = value
|
||||
end
|
||||
local btn_set_default = table_subvolume:option(Button, "_subv_set_default", translate("Set Default"))
|
||||
btn_set_default.forcewrite = true
|
||||
btn_set_default.inputstyle = "edit"
|
||||
btn_set_default.template = "diskman/cbi/disabled_button"
|
||||
btn_set_default.render = function(self, section, scope)
|
||||
if subvolume_list[section].default_subvolume then
|
||||
self.view_disabled = true
|
||||
self.inputtitle = translate("Set Default")
|
||||
elseif subvolume_list[section].ID == 0 then
|
||||
self.template = "cbi/dvalue"
|
||||
else
|
||||
self.inputtitle = translate("Set Default")
|
||||
self.view_disabled = false
|
||||
end
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
btn_set_default.write = function(self, section, value)
|
||||
local cmd
|
||||
if value == translate("Set Default") then
|
||||
cmd = dm.command.btrfs .. " subvolume set-default " .. mount_point..subvolume_list[section].path
|
||||
else
|
||||
cmd = dm.command.btrfs .. " subvolume set-default " .. mount_point.."/"
|
||||
end
|
||||
local res = luci.util.exec(cmd.. " 2>&1")
|
||||
if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
m.errmessage = res
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
end
|
||||
end
|
||||
local btn_remove = table_subvolume:option(Button, "_subv_remove")
|
||||
btn_remove.forcewrite = true
|
||||
btn_remove.render = function(self, section, scope)
|
||||
if subvolume_list[section].ID == 0 then
|
||||
btn_remove.inputtitle = translate("Create")
|
||||
btn_remove.inputstyle = "add"
|
||||
else
|
||||
btn_remove.inputtitle = translate("Delete")
|
||||
btn_remove.inputstyle = "remove"
|
||||
end
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
|
||||
btn_remove.write = function(self, section, value)
|
||||
local cmd
|
||||
if value == translate("Delete") then
|
||||
cmd = dm.command.btrfs .. " subvolume delete " .. mount_point .. subvolume_list[section].path
|
||||
elseif value == translate("Create") and value_path then
|
||||
luci.util.perror(mount_point)
|
||||
cmd = dm.command.btrfs .. " subvolume create " .. mount_point .. value_path
|
||||
end
|
||||
local res = luci.util.exec(cmd.. " 2>&1")
|
||||
if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
m.errmessage = res
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
end
|
||||
end
|
||||
-- snapshot
|
||||
-- local snapshot_list = dm.get_btrfs_subv(uuid, 1)
|
||||
-- table_snapshot = m:section(Table, snapshot_list, translate("Snapshots"))
|
||||
-- table_snapshot:option(DummyValue, "id", translate("ID"))
|
||||
-- table_snapshot:option(DummyValue, "top_level", translate("Top Level"))
|
||||
-- table_snapshot:option(DummyValue, "uuid", translate("UUID"))
|
||||
-- table_snapshot:option(DummyValue, "otime", translate("Otime"))
|
||||
-- table_snapshot:option(DummyValue, "path", translate("Path"))
|
||||
-- local snp_remove = table_snapshot:option(Button, "_snp_remove")
|
||||
-- snp_remove.inputtitle = translate("Delete")
|
||||
-- snp_remove.inputstyle = "remove"
|
||||
-- snp_remove.write = function(self, section, value)
|
||||
-- local cmd = dm.command.btrfs .. " subvolume delete " .. mount_point .. snapshot_list[section].path
|
||||
-- local res = luci.util.exec(cmd.. " 2>&1")
|
||||
-- if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
-- m.errmessage = res
|
||||
-- else
|
||||
-- luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- new snapshots
|
||||
local s_snapshot = m:section(SimpleSection, "New Snapshot")
|
||||
local value_sorce, value_dest, value_readonly
|
||||
local v_sorce = s_snapshot:option(Value, "_source", translate("Source Path"))
|
||||
v_sorce.placeholder = "/data"
|
||||
v_sorce.write = function(self, section, value)
|
||||
value_sorce = value
|
||||
end
|
||||
|
||||
local v_readonly = s_snapshot:option(Flag, "_readonly", translate("Readonly"))
|
||||
v_readonly.disabled = 0
|
||||
v_readonly.enabled = 1
|
||||
v_readonly.default = 1
|
||||
v_readonly.write = function(self, section, value)
|
||||
value_readonly = value
|
||||
end
|
||||
local v_dest = s_snapshot:option(Value, "_dest", translate("Destination Path (optional)"))
|
||||
v_dest.placeholder = "/.snapshot/202002051538"
|
||||
v_dest.write = function(self, section, value)
|
||||
value_dest = value
|
||||
end
|
||||
local btn_snp_create = s_snapshot:option(Button, "_snp_create")
|
||||
btn_snp_create.title = " "
|
||||
btn_snp_create.inputtitle = translate("Create Snapshot")
|
||||
btn_snp_create.inputstyle = "add"
|
||||
btn_snp_create.write = function(self, section, value)
|
||||
if value_sorce and value_sorce:match("^/") then
|
||||
if not value_dest then value_dest = "/.snapshot"..value_sorce.."/"..os.date("%Y%m%d%H%M%S") end
|
||||
nixio.fs.mkdirr(mount_point..value_dest:match("(.-)[^/]+$"))
|
||||
local cmd = dm.command.btrfs .. " subvolume snapshot " .. (value_readonly == 1 and " -r " or " ") .. mount_point..value_sorce .. " " .. mount_point..value_dest
|
||||
local res = luci.util.exec(cmd .. " 2>&1")
|
||||
if res and (res:match("ERR") or res:match("not enough arguments")) then
|
||||
m.errmessage = res
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman/btrfs/" .. uuid))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
@ -77,7 +77,18 @@ if dm.command.mdadm then
|
||||
-- end
|
||||
r.extedit = luci.dispatcher.build_url("admin/system/diskman/partition/%s")
|
||||
end
|
||||
end
|
||||
|
||||
-- btrfs devices
|
||||
if dm.command.btrfs then
|
||||
btrfs_devices = dm.list_btrfs_devices()
|
||||
local table_btrfs = m:section(Table, btrfs_devices, translate("Btrfs"))
|
||||
table_btrfs:option(DummyValue, "uuid", translate("UUID"))
|
||||
table_btrfs:option(DummyValue, "label", translate("Label"))
|
||||
table_btrfs:option(DummyValue, "devices", translate("Devices"))
|
||||
table_btrfs:option(DummyValue, "size_formated", translate("Size"))
|
||||
table_btrfs:option(DummyValue, "used_formated", translate("Usage"))
|
||||
table_btrfs.extedit = luci.dispatcher.build_url("admin/system/diskman/btrfs/%s")
|
||||
end
|
||||
|
||||
--tabs
|
||||
@ -95,12 +106,12 @@ if dm.command.mdadm then
|
||||
local r = m:section(SimpleSection, translate("RAID Creation"))
|
||||
r.template="diskman/cbi/xnullsection"
|
||||
r.config = "raid"
|
||||
local r_name = r:option(Value, "_name", translate("Raid Name"))
|
||||
local r_name = r:option(Value, "_rname", translate("Raid Name"))
|
||||
r_name.placeholder = "/dev/md0"
|
||||
r_name.write = function(self, section, value)
|
||||
rname = value
|
||||
end
|
||||
local r_level = r:option(ListValue, "_level", translate("Raid Level"))
|
||||
local r_level = r:option(ListValue, "_rlevel", translate("Raid Level"))
|
||||
local valid_raid = luci.util.exec("lsmod | grep md_mod")
|
||||
if valid_raid:match("linear") then
|
||||
r_level:value("linear", "Linear")
|
||||
@ -121,7 +132,7 @@ if dm.command.mdadm then
|
||||
r_level.write = function(self, section, value)
|
||||
rlevel = value
|
||||
end
|
||||
local r_member = r:option(DynamicList, "_member", translate("Raid Member"))
|
||||
local r_member = r:option(DynamicList, "_rmember", translate("Raid Member"))
|
||||
for dev, info in pairs(disks) do
|
||||
if not info.inuse and #info.partitions == 0 then
|
||||
r_member:value(info.path, info.path.. " ".. info.size_formated)
|
||||
@ -135,7 +146,7 @@ if dm.command.mdadm then
|
||||
r_member.write = function(self, section, value)
|
||||
rmembers = value
|
||||
end
|
||||
local r_create = r:option(Button, "_create")
|
||||
local r_create = r:option(Button, "_rcreate")
|
||||
r_create.render = function(self, section, scope)
|
||||
self.title = " "
|
||||
self.inputtitle = translate("Create Raid")
|
||||
@ -145,7 +156,7 @@ if dm.command.mdadm then
|
||||
r_create.write = function(self, section, value)
|
||||
-- mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=2 /dev/sdb6 /dev/sdc5
|
||||
local res = dm.create_raid(rname, rlevel, rmembers)
|
||||
if res:match("^ERR") then
|
||||
if res and res:match("^ERR") then
|
||||
m.errmessage = translate(res)
|
||||
return
|
||||
end
|
||||
@ -248,18 +259,63 @@ btn_umount.write = function(self, section, value)
|
||||
elseif value == translate("Umount") then
|
||||
res = luci.util.exec("umount "..mount_point[section].mount_point .. " 2>&1")
|
||||
end
|
||||
if res:match("^mount:") then
|
||||
if res:match("^mount:") or res:match("^umount:") then
|
||||
m.errmessage = luci.util.pcdata(res)
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman"))
|
||||
end
|
||||
end
|
||||
|
||||
-- -- btrfs
|
||||
-- btrfs
|
||||
if dm.command.btrfs then
|
||||
local blabel, bmembers, blevel
|
||||
tab_section.tabs.btrfs = translate("Btrfs")
|
||||
local btrfs_devices = {}
|
||||
local table_btrfs = m:section(Table, btrfs_devices, translate("Btrfs"))
|
||||
table_btrfs.config = "btrfs"
|
||||
local r = m:section(SimpleSection, translate("Btrfs Multiple Devices Creation"))
|
||||
r.template="diskman/cbi/xnullsection"
|
||||
r.config = "btrfs"
|
||||
local btrfs_label = r:option(Value, "_blabel", translate("Btrfs Label"))
|
||||
btrfs_label.write = function(self, section, value)
|
||||
blabel = value
|
||||
end
|
||||
local btrfs_level = r:option(ListValue, "_blevel", translate("Btrfs Raid Level"))
|
||||
btrfs_level:value("single", "Single")
|
||||
btrfs_level:value("raid0", "Raid 0")
|
||||
btrfs_level:value("raid1", "Raid 1")
|
||||
btrfs_level:value("raid10", "Raid 10")
|
||||
btrfs_level.write = function(self, section, value)
|
||||
blevel = value
|
||||
end
|
||||
|
||||
local btrfs_member = r:option(DynamicList, "_bmember", translate("Btrfs Member"))
|
||||
for dev, info in pairs(disks) do
|
||||
if not info.inuse and #info.partitions == 0 then
|
||||
btrfs_member:value(info.path, info.path.. " ".. info.size_formated)
|
||||
end
|
||||
for i, v in ipairs(info.partitions) do
|
||||
if not v.inuse then
|
||||
btrfs_member:value("/dev/".. v.name, "/dev/".. v.name .. " ".. v.size_formated)
|
||||
end
|
||||
end
|
||||
end
|
||||
btrfs_member.write = function(self, section, value)
|
||||
bmembers = value
|
||||
end
|
||||
local btrfs_create = r:option(Button, "_bcreate")
|
||||
btrfs_create.render = function(self, section, scope)
|
||||
self.title = " "
|
||||
self.inputtitle = translate("Create Btrfs")
|
||||
self.inputstyle = "add"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
btrfs_create.write = function(self, section, value)
|
||||
-- mkfs.btrfs -L label -d blevel /dev/sda /dev/sdb
|
||||
local res = dm.create_btrfs(blabel, blevel, bmembers)
|
||||
if res and res:match("^ERR") then
|
||||
m.errmessage = translate(res)
|
||||
return
|
||||
end
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/diskman"))
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
@ -40,7 +40,8 @@ s:option(DummyValue, "size_formated", translate("Size"))
|
||||
s:option(DummyValue, "sec_size", translate("Sector Size "))
|
||||
local dv_p_table = s:option(ListValue, "p_table", translate("Partition Table"))
|
||||
dv_p_table.render = function(self, section, scope)
|
||||
if not disk_info.p_table:match("Raid") and (#disk_info.partitions == 0 or (#disk_info.partitions == 1 and disk_info.partitions[1].number == -1)) then
|
||||
-- create table only if not used by raid and no partitions on disk
|
||||
if not disk_info.p_table:match("Raid") and (#disk_info.partitions == 0 or (#disk_info.partitions == 1 and disk_info.partitions[1].number == -1) or (disk_info.p_table:match("LOOP") and not disk_info.partitions[1].inuse)) then
|
||||
self:value(disk_info.p_table, disk_info.p_table)
|
||||
self:value("GPT", "GPT")
|
||||
self:value("MBR", "MBR")
|
||||
|
||||
@ -11,7 +11,7 @@ $Id$
|
||||
require "luci.util"
|
||||
local ver = require "luci.version"
|
||||
|
||||
local CMD = {"parted", "mdadm", "blkid", "smartctl", "df", "sgdisk", "btrfs"}
|
||||
local CMD = {"parted", "mdadm", "blkid", "smartctl", "df", "sgdisk", "btrfs", "mergerfs", "snapraid", "lsblk"}
|
||||
|
||||
local d = {command ={}}
|
||||
for _, cmd in ipairs(CMD) do
|
||||
@ -537,4 +537,136 @@ d.gen_mdadm_config = function()
|
||||
luci.util.exec("/etc/init.d/mdadm enable")
|
||||
end
|
||||
|
||||
-- list btrfs filesystem device
|
||||
-- {uuid={uuid, label, devices, size, used}...}
|
||||
d.list_btrfs_devices = function()
|
||||
local btrfs_device = {}
|
||||
if not d.command.btrfs then return btrfs_device end
|
||||
local line, _uuid
|
||||
for _, line in ipairs(luci.util.execl(d.command.btrfs .. " filesystem show -d --raw"))
|
||||
do
|
||||
local label, uuid = line:match("^Label:%s+([^%s]+)%s+uuid:%s+([^%s]+)")
|
||||
if label and uuid then
|
||||
_uuid = uuid
|
||||
local _label = label:match("^'([^']+)'")
|
||||
btrfs_device[_uuid] = {label = _label or label, uuid = uuid}
|
||||
-- table.insert(btrfs_device, {label = label, uuid = uuid})
|
||||
end
|
||||
local used = line:match("Total devices[%w%s]+used%s+(%d+)$")
|
||||
if used then
|
||||
btrfs_device[_uuid]["used"] = tonumber(used)
|
||||
btrfs_device[_uuid]["used_formated"] = byte_format(tonumber(used))
|
||||
end
|
||||
local size, device = line:match("devid[%w.%s]+size%s+(%d+)[%w.%s]+path%s+([^%s]+)$")
|
||||
if size and device then
|
||||
btrfs_device[_uuid]["size"] = btrfs_device[_uuid]["size"] and btrfs_device[_uuid]["size"] + tonumber(size) or tonumber(size)
|
||||
btrfs_device[_uuid]["size_formated"] = byte_format(btrfs_device[_uuid]["size"])
|
||||
btrfs_device[_uuid]["devices"] = btrfs_device[_uuid]["devices"] and btrfs_device[_uuid]["devices"]..", "..device or device
|
||||
end
|
||||
end
|
||||
return btrfs_device
|
||||
end
|
||||
|
||||
d.create_btrfs = function(blabel, blevel, bmembers)
|
||||
-- mkfs.btrfs -L label -d blevel /dev/sda /dev/sdb
|
||||
if not d.command.btrfs or type(bmembers) ~= "table" or next(bmembers) == nil then return "ERR no btrfs support or no members" end
|
||||
local label = blabel and " -L " .. blabel or ""
|
||||
local cmd = "mkfs.btrfs -f " .. label .. " -d " .. blevel .. " " .. table.concat(bmembers, " ")
|
||||
return luci.util.exec(cmd)
|
||||
end
|
||||
|
||||
-- get btrfs subvolume
|
||||
-- {id={id, gen, top_level, path, snapshots, otime, default_subvolume}...}, mount_point
|
||||
d.get_btrfs_subv = function(uuid, snapshot)
|
||||
local subvolume = {}
|
||||
if not uuid or not d.command.lsblk or not d.command.btrfs then return subvolume end
|
||||
-- check mounted device & get mount point
|
||||
-- local m_point = luci.util.exec(d.command.lsblk .. " -o UUID,MOUNTPOINT | awk '{if($1==\""..uuid.."\") print $2}'")
|
||||
-- clear sapce and \n
|
||||
-- m_point = m_point and string.gsub(m_point, "[\n%s]+", "")
|
||||
-- if not m_point or m_point =="" then
|
||||
m_point = "/tmp/.btrfs_tmp"
|
||||
nixio.fs.mkdirr(m_point)
|
||||
luci.util.exec("umount "..m_point .. " >/dev/null 2>&1")
|
||||
luci.util.exec("mount -o subvol=/ -U "..uuid.." "..m_point)
|
||||
-- os.execute("sleep " .. 0.5)
|
||||
-- end
|
||||
|
||||
-- get default subvolume
|
||||
local cmd = d.command.btrfs .. " subvolume get-default " .. m_point
|
||||
local res = luci.util.exec(cmd)
|
||||
local default_subvolume_id = res:match("^ID%s+([^%s]+)")
|
||||
|
||||
-- get the root subvolume
|
||||
if not snapshot then
|
||||
local _, line, section_snap, _uuid, _otime, _id, _snap
|
||||
cmd = d.command.btrfs .. " subvolume show ".. m_point
|
||||
for _, line in ipairs(luci.util.execl(cmd)) do
|
||||
if not section_snap then
|
||||
local uuid = line:match("^%s-UUID:%s+([^%s]+)")
|
||||
local otime = line:match("^%s+Creation time:%s+(.+)")
|
||||
local id = line:match("^%s+Subvolume ID:%s+([^%s]+)")
|
||||
if uuid then
|
||||
_uuid = uuid
|
||||
elseif otime then
|
||||
_otime = otime
|
||||
elseif id then
|
||||
_id = id
|
||||
elseif line:match("^%s+(Snapshot%(s%):)") then
|
||||
section_snap = "true"
|
||||
end
|
||||
else
|
||||
local snapshot = line:match("^%s+(.+)")
|
||||
_snap = _snap and (_snap ..", /".. snapshot) or ("/"..snapshot)
|
||||
end
|
||||
end
|
||||
if _uuid and _otime and _id then
|
||||
subvolume["0".._id] = {id = _id , uuid = _uuid, otime = _otime, snapshots = _snap, path = "/"}
|
||||
if default_subvolume_id == _id then
|
||||
subvolume["0".._id].default_subvolume = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- get subvolume of btrfs
|
||||
cmd = d.command.btrfs .. " subvolume list -gcu" .. (snapshot and "s " or " ") .. m_point
|
||||
for _, line in ipairs(luci.util.execl(cmd)) do
|
||||
-- ID 259 gen 11 top level 258 uuid 26ae0c59-199a-cc4d-bd58-644eb4f65d33 path 1a/2b'
|
||||
local id, gen, top_level, uuid, path, otime, otime2
|
||||
if snapshot then
|
||||
id, gen, top_level, otime, otime2, uuid, path = line:match("^ID%s+([^%s]+)%s+gen%s+([^%s]+)%s+cgen.-top level%s+([^%s]+)%s+otime%s+([^%s]+)%s+([^%s]+)%s+uuid%s+([^%s]+)%s+path%s+([^%s]+)%s-$")
|
||||
else
|
||||
id, gen, top_level, uuid, path = line:match("^ID%s+([^%s]+)%s+gen%s+([^%s]+)%s+cgen.-top level%s+([^%s]+)%s+uuid%s+([^%s]+)%s+path%s+([^%s]+)%s-$")
|
||||
end
|
||||
if id and gen and top_level and uuid and path then
|
||||
subvolume[id] = {id = id, gen = gen, top_level = top_level, otime = (otime and otime or "") .." ".. (otime2 and otime2 or ""), uuid = uuid, path = '/'.. path}
|
||||
if not snapshot then
|
||||
-- use btrfs subv show to get snapshots
|
||||
local show_cmd = d.command.btrfs .. " subvolume show "..m_point.."/"..path
|
||||
local __, line_show, section_snap
|
||||
for __, line_show in ipairs(luci.util.execl(show_cmd)) do
|
||||
if not section_snap then
|
||||
local create_time = line_show:match("^%s+Creation time:%s+(.+)")
|
||||
if create_time then
|
||||
subvolume[id]["otime"] = create_time
|
||||
elseif line_show:match("^%s+(Snapshot%(s%):)") then
|
||||
section_snap = "true"
|
||||
end
|
||||
else
|
||||
local snapshot = line_show:match("^%s+(.+)")
|
||||
subvolume[id]["snapshots"] = subvolume[id]["snapshots"] and (subvolume[id]["snapshots"] .. ", /".. snapshot) or ("/"..snapshot)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if subvolume[default_subvolume_id] then
|
||||
subvolume[default_subvolume_id].default_subvolume = 1
|
||||
end
|
||||
-- if m_point == "/tmp/.btrfs_tmp" then
|
||||
-- luci.util.exec("umount " .. m_point)
|
||||
-- end
|
||||
return subvolume, m_point
|
||||
end
|
||||
|
||||
return d
|
||||
|
||||
Loading…
Reference in New Issue
Block a user