OpenWrt Forum Archive

Topic: [SOLVED] Add new element to LuCI Web Interface on a flashed router

The content of this topic has been archived on 19 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

What I want to do is to add a sub-tab element called "OpenVPN Log" under "Services" tab:
http://i.imgur.com/AD67tWp.png

Following this wiki article, I went to "/overlay/upper/usr/lib/lua/luci/controller/openvpn.lua" and changed it to:

module("luci.controller.openvpn", package.seeall)

function index()
    entry( {"admin", "services", "openvpn"}, cbi("openvpn"), _("OpenVPN") )
    entry( {"admin", "services", "openvpn", "log"}, cbi("openvpn"), _("OpenVPN Log") ) -- new sub-tab element
    entry( {"admin", "services", "openvpn", "basic"},    cbi("openvpn-basic"),    nil ).leaf = true
    entry( {"admin", "services", "openvpn", "advanced"}, cbi("openvpn-advanced"), nil ).leaf = true
end

but it is not shown in the web interfeace and if I go to http://192.168.1.1/cgi-bin/luci/;stok=. … penvpn/log I get:

No page is registered at '/admin/services/openvpn/log'.
If this url belongs to an extension, make sure it is properly installed.
If the extension was recently installed, try removing the /tmp/luci-indexcache file.

Where exactly do I have to register the page ?

(Last edited by Chris_DB on 28 Jul 2015, 17:32)

Here is what I've ended up doing.
This is quiet an easy way to add custom pages to LuCI web interface.

First I went to "/usr/lib/lua/luci/controller/admin/status.lua" and modified it by adding a new entry for "OpenVPN Log" in index() function so that it shows up in the "Status" tab menu at the admin web interface.

entry({"admin", "status", "openvpn"}, call("action_openvpnlog"), _("OpenVPN Log"), 4) -- don't forget to accommodate the order (here 4) for the other entries too

This is the result:
OpenVPN Log menu
Then I had to add a new function that retrieves the OpenVPN log and writes it into the webpage by rendering a template:

function action_openvpnlog()
    local openvpnlog = luci.sys.exec("cat /tmp/openvpn.log")
    luci.template.render("admin_status/openvpnlog", {openvpnlog=openvpnlog})
end

Finally I had to make a copy of "/usr/lib/lua/luci/view/admin_status/syslog.htm" template, name it "openvpnlog.html" and update the heading to "OpenVPN Log" and the variable name syslog to openvpnlog (don't change the textarea id, leave it "syslog"; the template applies some CSS to it; if you change it you'll have to set its width to fit the browser width):

<%+header%>
<h2><a id="content" name="content"><%:OpenVPN Log%></a></h2>
<div id="content_syslog">
<textarea readonly="readonly" wrap="off" rows="<%=openvpnlog:cmatch("\n")+2%>" id="syslog"><%=openvpnlog:pcdata()%></textarea>
</div>
<%+footer%>

This is the result:
OpenVPN Log

Nice! It would be nice if someone submitted this as a patch for luci-app-openvpn. I don't use OpenVPN, but this seems like it would be useful to all users of that tool.

This is great!

I will add two notes
I had to reboot to make the menu work.  I expected I would only need to refresh the page.
It may be necessary to mod the path in the function for your log file path\name.

It also works with the OpenWRT theme

I would like to extend this for multiple connections, but am not clear on which elements in the function would change for logs called 'vpntap.log' and 'vpntun.log' and functions of similar names.

function action_vpntun()
    local openvpnlog = luci.sys.exec("cat /tmp/vpntun.log")
    luci.template.render("admin_status/openvpnlog", {openvpnlog=openvpnlog})
end

I expect I would use 'vpntap' and 'vpntun' in the two HTML pages.

Thanks for this gem!!

(Last edited by RangerZ on 29 Jul 2015, 01:09)

Yes, I forgot to mention you have to reboot for changes to take effect.

For multiple logs you can use the same HTML template:

"/usr/lib/lua/luci/controller/admin/status.lua"

function index()
        ...
    entry({"admin", "status", "openvpn"}, call("action_vpntunlog"), _("OpenVPN Log (tun)"), 4)
    entry({"admin", "status", "openvpn"}, call("action_vpntaplog"), _("OpenVPN Log (tap)"), 5)
        ...
end

function action_vpntunlog()
    local local_lua_log_variable = luci.sys.exec("cat /tmp/vpntun.log")
    luci.template.render("admin_status/openvpnlog", {lua_log_variable=local_lua_log_variable, lua_title_variable="OpenVPN Log (tun)"})
end

function action_vpntaplog()
    local local_lua_log_variable = luci.sys.exec("cat /tmp/vpntap.log")
    luci.template.render("admin_status/openvpnlog", {lua_log_variable=local_lua_log_variable, lua_title_variable="OpenVPN Log (tap)"})
end

"/usr/lib/lua/luci/view/admin_status/openvpnlog.htm"

<%+header%>
<h2><a id="content" name="content"><%=lua_title_variable%></a></h2>
<div id="content_syslog">
<textarea readonly="readonly" wrap="off" rows="<%=lua_log_variable:cmatch("\n")+2%>" id="syslog"><%=lua_log_variable:pcdata()%></textarea>
</div>
<%+footer%>

(Last edited by Chris_DB on 29 Jul 2015, 10:47)

Thanks for your help!!

I needed  to make one change in the menu section.  The tab names needed to be unique.

function index()
        ...
    entry({"admin", "status", "openvpntun"}, call("action_vpntunlog"), _("OpenVPN Log (tun)"), 4)
    entry({"admin", "status", "openvpntap"}, call("action_vpntaplog"), _("OpenVPN Log (tap)"), 5)
        ...
end

In addition one can not have any hyphens in the log file names (which my real ones did).

Now if we could add a restart button to the page, that would be killer!

There is already a start/stop button in Services>OpenVPN if you install luci-app-openvpn.
http://i.imgur.com/CEdubyR.png

If you really want to convert that button into a restart button, have a hack at "/overlay/upper/usr/lib/lua/luci/model/cbi/openvpn.lua" on "updown.write" function.

I have done some testing and believe that the controls on this page do not work correctly, though they may actually work to fill the need.  https://forum.openwrt.org/viewtopic.php?id=58519

I was hoping to nab the components from the system=> Startup page.
/usr/lib/lua/luci/model/cbi/admin_system/startup.lua

I can see the control buttons, but unable to figure out where the content comes from for the buttons.   In effect I think it's a button that runs /etc/init.d/openvpn/reload

I think this button code will work, but do not know how to direct it to run the string.  This is not the HTML I know.  The button could go right after the <H2> tags

<input type="submit" class="cbi-button cbi-input-apply" name="restart" value="<%:restart...%>" />

In "/overlay/upper/usr/lib/lua/luci/model/cbi/openvpn.lua" add this code

local reload = s:option( Button, "my_reload_button", translate("Reload") )
reload.redirect = luci.dispatcher.build_url("admin", "services", "openvpn")
reload.inputstyle = "reload"
function reload.write(self, section)
    local pid = sys.exec("%s | grep %s | grep openvpn | grep -v grep | awk '{print $1}'" % { psstring,section} )
    sys.process.signal(pid,15)
    luci.sys.call("/etc/init.d/openvpn start %s" % section)
    luci.http.redirect( self.redirect )
end

after

function updown.write(self, section, value)
    if self.option == "stop" then
        local pid = sys.exec("%s | grep %s | grep openvpn | grep -v grep | awk '{print $1}'" % { psstring,section} )
        sys.process.signal(pid,15)
    else
        luci.sys.call("/etc/init.d/openvpn start %s" % section)
    end
    luci.http.redirect( self.redirect )
end

This will add a new option containing a button called "Reload" in each section (OpenVPN configuration)

http://i.imgur.com/02IvIbM.png

(Last edited by Chris_DB on 31 Jul 2015, 10:57)

drawz wrote:

Nice! It would be nice if someone submitted this as a patch for luci-app-openvpn. I don't use OpenVPN, but this seems like it would be useful to all users of that tool.

Has this already been submitted as patch?

The discussion might have continued from here.