luci-app-advanced-reboot: initial commit

Signed-off-by: Stan Grishin <stangri@melmac.net>
This commit is contained in:
Stan Grishin 2017-07-12 22:51:41 -07:00
parent 00ae50134b
commit f6505fc01c
7 changed files with 423 additions and 0 deletions

View file

@ -0,0 +1,20 @@
# Copyright (c) 2017 Stan Grishin (stangri@melmac.net)
# This is free software, licensed under the GNU General Public License v3.
include $(TOPDIR)/rules.mk
PKG_LICENSE:=GPL-3.0+
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.net>
LUCI_TITLE:=Advanced Linksys Reboot Web UI
LUCI_DESCRIPTION:=Provides Web UI (found under System/Advanced Reboot) to reboot supported Linksys routers to\
an altnerative partition. Also provides Web UI to shut down (power off) your device. Supported dual-partition\
routers are listed at https://github.com/stangri/openwrt-luci/blob/luci-app-advanced-reboot/applications/luci-app-advanced-reboot/README.md
LUCI_DEPENDS:=+luci
LUCI_PKGARCH:=all
PKG_RELEASE:=23
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -0,0 +1,35 @@
# Advanced Reboot Web UI (luci-app-advanced-reboot)
## Description
This package allows you to reboot to an alternative partition on supported (dual-partition) routers and to power off (power down) your OpenWrt/LEDE Project device.
## Supported Devices
Currently supported dual-partition devices include:
- Linksys WRT1200AC
- Linksys WRT1900AC
- Linksys WRT1900ACv2
- Linksys WRT1900ACS
- Linksys WRT3200ACM
- Linksys E4200v2
- Linksys EA4500
- Linksys EA8500
If you're interested in having your device supported, please post in [LEDE Project Forum Support Thread](https://forum.lede-project.org/t/web-ui-to-reboot-to-another-partition-dual-partition-routers/3423).
## Screenshot (luci-app-advanced-reboot)
![screenshot](https://raw.githubusercontent.com/stangri/screenshots/master/luci-app-advanced-reboot/screenshot01.png "screenshot")
## How to install
Install ```luci-app-advanced-reboot``` from Web UI or connect to your router via ssh and run the following commands:
```sh
opkg update
opkg install luci-app-advanced-reboot
```
## Notes/Known Issues
- When you reboot to a different partition, your current settings (WiFi SSID/password, etc.) will not apply to a different partition. Different partitions might have completely different settings and even firmware.
- If you reboot to a partition which doesn't allow you to switch boot partitions (like stock Linksys firmware), you might not be able to boot back to OpenWrt/LEDE Project unless you reflash it, loosing all the settings.
- Some devices allow you to trigger reboot to alternative partition by interrupting boot 3 times in a row (by resetting/switching off the device or pulling power). As these methods might be different for different devices, do your own homework.
## Thanks
I'd like to thank everyone who helped create, test and troubleshoot this package. Without contributions from [@hnyman](https://github.com/hnyman) and [@jpstyves](https://github.com/jpstyves) it wouldn't have been possible.

View file

@ -0,0 +1,120 @@
-- Copyright 2017 Stan Grishin <stangri@melmac.net>
-- Licensed to the public under the Apache License 2.0.
module("luci.controller.advanced_reboot", package.seeall)
-- device, board_name, part1, part2, offset, env_var_1, value_1_1, value_1_2, env_var_2, value_2_1, value_2_2
devices = {
{"Linksys WRT1200AC", "armada-385-linksys-caiman", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT1900AC", "armada-xp-linksys-mamba", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT1900ACv2", "armada-385-linksys-cobra", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT1900ACS", "armada-385-linksys-shelby", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT3200ACM", "armada-385-linksys-rango", "mtd5", "mtd7", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys E4200v2/EA4500", "linksys-viper", "mtd3", "mtd5", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys EA8500", "ea8500", "mtd13", "mtd15", 32, "boot_part", 1, 2}
}
board_name = luci.util.trim(luci.sys.exec("cat /tmp/sysinfo/board_name"))
for i=1, #devices do
if board_name and devices[i][2] == board_name then
device_name = devices[i][1]
partition_one_mtd = devices[i][3] or nil
partition_two_mtd = devices[i][4] or nil
partition_skip = devices[i][5] or nil
boot_envvar1 = devices[i][6] or nil
boot_envvar1_partition_one = tonumber(devices[i][7]) or nil
boot_envvar1_partition_two = tonumber(devices[i][8]) or nil
boot_envvar2 = devices[i][9] or nil
boot_envvar2_partition_one = devices[i][10] or nil
boot_envvar2_partition_two = devices[i][11] or nil
if partition_one_mtd and partition_skip then
partition_one_label = luci.util.trim(luci.sys.exec("dd if=/dev/" .. partition_one_mtd .. " bs=1 skip=" .. partition_skip .. " count=25" .. " 2>/dev/null"))
n, partition_one_version = string.match(partition_one_label, '(Linux)-([%d|.]+)')
end
if partition_two_mtd and partition_skip then
partition_two_label = luci.util.trim(luci.sys.exec("dd if=/dev/" .. partition_two_mtd .. " bs=1 skip=" .. partition_skip .. " count=25" .. " 2>/dev/null"))
n, partition_two_version = string.match(partition_two_label, '(Linux)-([%d|.]+)')
end
if string.find(partition_one_label, "LEDE") then partition_one_os = "LEDE" end
if string.find(partition_one_label, "OpenWrt") then partition_one_os = "OpenWrt" end
if string.find(partition_one_label, "Linksys") then partition_one_os = "Linksys" end
if string.find(partition_two_label, "LEDE") then partition_two_os = "LEDE" end
if string.find(partition_two_label, "OpenWrt") then partition_two_os = "OpenWrt" end
if string.find(partition_two_label, "Linksys") then partition_two_os = "Linksys" end
if not partition_one_os then partition_one_os = "Unknown" end
if not partition_two_os then partition_two_os = "Unknown" end
if partition_one_os and partition_one_version then partition_one_os = partition_one_os .. " (Linux " .. partition_one_version .. ")" end
if partition_two_os and partition_two_version then partition_two_os = partition_two_os .. " (Linux " .. partition_two_version .. ")" end
if nixio.fs.access("/usr/sbin/fw_printenv") and nixio.fs.access("/usr/sbin/fw_setenv") then
current_partition = tonumber(luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar1)))
other_partition = current_partition == boot_envvar1_partition_one and boot_envvar1_partition_two or boot_envvar1_partition_one
end
end
end
function index()
entry({"admin", "system", "advanced_reboot"}, template("advanced_reboot/advanced_reboot"), _("Advanced Reboot"), 90)
entry({"admin", "system", "advanced_reboot", "reboot"}, post("action_reboot"))
-- if device_name then entry({"admin", "system", "advanced_reboot", "altreboot"}, post("action_altreboot")) end
entry({"admin", "system", "advanced_reboot", "alternative_reboot"}, post("action_altreboot"))
entry({"admin", "system", "advanced_reboot", "power_off"}, post("action_poweroff"))
end
function action_reboot()
luci.template.render("admin_system/applyreboot", {
title = luci.i18n.translate("Rebooting..."),
msg = luci.i18n.translate("The system is rebooting now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings."),
addr = luci.ip.new(uci.cursor():get("network", "lan", "ipaddr")) or "192.168.1.1"
})
luci.sys.reboot()
end
function action_altreboot()
if luci.http.formvalue("cancel") then
luci.http.redirect(luci.dispatcher.build_url('admin/system/advanced_reboot'))
return
end
local step = tonumber(luci.http.formvalue("step") or 1)
if step == 1 then
if device_name and nixio.fs.access("/usr/sbin/fw_printenv") and nixio.fs.access("/usr/sbin/fw_setenv") then
luci.template.render("advanced_reboot/alternative_reboot",{})
else
luci.template.render("advanced_reboot/advanced_reboot",{})
end
elseif step == 2 then
luci.template.render("admin_system/applyreboot", {
title = luci.i18n.translate("Rebooting..."),
msg = luci.i18n.translate("The system is rebooting to an alternative partition now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings."),
addr = luci.ip.new(uci.cursor():get("network", "lan", "ipaddr")) or "192.168.1.1"
})
if boot_envvar1 then env1 = tonumber(luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar1))) end
if boot_envvar2 then env2 = luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar2)) end
if env1 and env1 == boot_envvar1_partition_one then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar1 .. " " .. boot_envvar1_partition_two) end
if env1 and env1 == boot_envvar1_partition_two then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar1 .. " " .. boot_envvar1_partition_one) end
if env2 and env2 == boot_envvar2_partition_one then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar2 .. " '" .. boot_envvar2_partition_two .. "'") end
if env2 and env2 == boot_envvar2_partition_two then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar2 .. " '" .. boot_envvar2_partition_one .. "'") end
luci.sys.reboot()
end
end
function action_poweroff()
if luci.http.formvalue("cancel") then
luci.http.redirect(luci.dispatcher.build_url('admin/system/advanced_reboot'))
return
end
local step = tonumber(luci.http.formvalue("step") or 1)
if step == 1 then
if nixio.fs.access("/sbin/poweroff") then
luci.template.render("advanced_reboot/power_off",{})
else
luci.template.render("advanced_reboot/advanced_reboot",{})
end
elseif step == 2 then
luci.template.render("admin_system/applyreboot", {
title = luci.i18n.translate("Shutting down..."),
msg = luci.i18n.translate("The system is shutting down now.<br /> DO NOT POWER OFF THE DEVICE!<br /> It might be necessary to renew the address of your computer to reach the device again, depending on your settings."),
addr = luci.ip.new(uci.cursor():get("network", "lan", "ipaddr")) or "192.168.1.1"
})
luci.sys.call("/sbin/poweroff")
end
end

View file

@ -0,0 +1,92 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
Copyright 2017 Stan Grishin <stangri@melmac.net>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Advanced Reboot%></h2>
<br />
<%- local c = require("luci.model.uci").cursor():changes(); if c and next(c) then -%>
<p class="alert-message warning"><%:Warning: There are unsaved changes that will get lost on reboot!%></p>
<%- end -%>
<%- if device_name then -%>
<fieldset class="cbi-section">
<legend><%=device_name%><%: Partitions%></legend>
<table class="cbi-section-table" id="partitions">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Partition%></th>
<th class="cbi-section-table-cell"><%:Status%></th>
<th class="cbi-section-table-cell"><%:Firmware/OS (Kernel)%></th>
<th class="cbi-section-table-cell"><%:Action%></th>
</tr>
<tr class="cbi-section-table-row">
<td>
<%=boot_envvar1_partition_one%>
</td>
<td>
<%- if boot_envvar1_partition_one == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%>
</td>
<td>
<%=partition_one_os%>
</td>
<td>
<%- if boot_envvar1_partition_one == current_partition then -%>
<form method="post" action="<%=url('admin/system/advanced_reboot/reboot')%>">
<input type="hidden" name="token" value="<%=token%>" />
<input id="reboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to current partition%>" />
</form>
<%- else -%>
<form method="post" action="<%=url('admin/system/advanced_reboot/alternative_reboot')%>">
<input type="hidden" name="token" value="<%=token%>" />
<input id="altreboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to alternative partition...%>" />
</form>
<%- end -%>
</td>
</tr>
<tr class="cbi-section-table-row">
<td>
<%=boot_envvar1_partition_two%>
</td>
<td>
<%- if boot_envvar1_partition_two == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%>
</td>
<td>
<%=partition_two_os%>
</td>
<td>
<%- if boot_envvar1_partition_two == current_partition then -%>
<form method="post" action="<%=url('admin/system/advanced_reboot/reboot')%>">
<input type="hidden" name="token" value="<%=token%>" />
<input id="reboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to current partition%>" />
</form>
<%- else -%>
<form method="post" action="<%=url('admin/system/advanced_reboot/alternative_reboot')%>">
<input type="hidden" name="token" value="<%=token%>" />
<input id="altreboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to alternative partition...%>" />
</form>
<%- end -%>
</td>
</tr>
</table>
</fieldset>
<%- else -%>
<p class="alert-message warning"><%:Warning: This system does not have two partitions!%></p>
<%- end -%>
<hr />
<%- if nixio.fs.access("/sbin/poweroff") then -%>
<form method="post" action="<%=url('admin/system/advanced_reboot/power_off')%>">
<input type="hidden" name="token" value="<%=token%>" />
<input id="poweroff-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Perform power off...%>" />
</form>
<%- else -%>
<p class="alert-message warning"><%:Warning: This system does not support powering off!%></p>
<%- end -%>
<%+footer%>

View file

@ -0,0 +1,29 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2009 Jo-Philipp Wich <jow@openwrt.org>
Copyright 2017 Stan Grishin <stangri@melmac.net>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Reboot Device to an Alternative Partition%> - <%:Confirm%></h2>
<p>
<%_ WARNING: An alternative partition might have its own settings and completely different firmware.<br /><br />
As your network configuration and WiFi SSID/password on alternative partition might be different,
you might have to adjust your computer settings to be able to access your device once it reboots.<br /><br />
Please also be aware that alternative partition firmware might not provide an easy way to switch active partition
and boot back to the currently active partition.<br /><br />
Click "Proceed" below to reboot device to an alternative partition. %>
</p>
<div class="cbi-page-actions right">
<form class="inline" action="<%=REQUEST_URI%>" method="post">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="step" value="2" />
<input class="cbi-button cbi-button-reset" name="cancel" type="submit" value="<%:Cancel%>" />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Proceed%>" />
</form>
</div>
<%+footer%>

View file

@ -0,0 +1,25 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2009 Jo-Philipp Wich <jow@openwrt.org>
Copyright 2017 Stan Grishin <stangri@melmac.net>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Power Off Device%> - <%:Confirm%></h2>
<p>
<%_ WARNING: Power off might result in a reboot on a device which doesn't support power off.<br /><br />
Click "Proceed" below to power off your device. %>
</p>
<div class="cbi-page-actions right">
<form class="inline" action="<%=REQUEST_URI%>" method="post">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="step" value="2" />
<input class="cbi-button cbi-button-reset" name="cancel" type="submit" value="<%:Cancel%>" />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Proceed%>" />
</form>
</div>
<%+footer%>

View file

@ -0,0 +1,102 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Action"
msgstr ""
msgid "Advanced Reboot"
msgstr ""
msgid "Alternative"
msgstr ""
msgid "Cancel"
msgstr ""
msgid "Confirm"
msgstr ""
msgid "Current"
msgstr ""
msgid "Firmware/OS (Kernel)"
msgstr ""
msgid "Partition"
msgstr ""
msgid "Partitions"
msgstr ""
msgid "Perform power off..."
msgstr ""
msgid "Power Off Device"
msgstr ""
msgid "Proceed"
msgstr ""
msgid "Reboot Device to an Alternative Partition"
msgstr ""
msgid "Reboot to alternative partition..."
msgstr ""
msgid "Reboot to current partition"
msgstr ""
msgid "Rebooting..."
msgstr ""
msgid "Shutting down..."
msgstr ""
msgid "Status"
msgstr ""
msgid ""
"The system is rebooting now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a "
"few minutes before you try to reconnect. It might be necessary to renew the "
"address of your computer to reach the device again, depending on your "
"settings."
msgstr ""
msgid ""
"The system is rebooting to an alternative partition now.<br /> DO NOT POWER "
"OFF THE DEVICE!<br /> Wait a few minutes before you try to reconnect. It "
"might be necessary to renew the address of your computer to reach the device "
"again, depending on your settings."
msgstr ""
msgid ""
"The system is shutting down now.<br /> DO NOT POWER OFF THE DEVICE!<br /> It "
"might be necessary to renew the address of your computer to reach the device "
"again, depending on your settings."
msgstr ""
msgid ""
"WARNING: An alternative partition might have its own settings and completely "
"different firmware.<br /><br /> As your network configuration and WiFi SSID/"
"password on alternative partition might be different, you might have to "
"adjust your computer settings to be able to access your device once it "
"reboots.<br /><br /> Please also be aware that alternative partition "
"firmware might not provide an easy way to switch active partition and boot "
"back to the currently active partition.<br /><br /> Click \"Proceed\" below "
"to reboot device to an alternative partition."
msgstr ""
msgid ""
"WARNING: Power off might result in a reboot on a device which doesn't "
"support power off.<br /><br /> Click \"Proceed\" below to power off your "
"device."
msgstr ""
msgid "Warning: There are unsaved changes that will get lost on reboot!"
msgstr ""
msgid "Warning: This system does not have two partitions!"
msgstr ""
msgid "Warning: This system does not support powering off!"
msgstr ""