feat: add Smart service control backend
This commit is contained in:
@@ -10,6 +10,19 @@
|
||||
# Generated files
|
||||
##############
|
||||
|
||||
# systemd itself is detected by the top-level systemdservice.cmake.
|
||||
# This webui submodule only consumes WITH_SYSTEMD and SYSTEMD_SERVICES_INSTALL_DIR.
|
||||
if(NOT DEFINED MARS_NWE_SYSTEMD_SERVICE)
|
||||
set(MARS_NWE_SYSTEMD_SERVICE "mars-nwe-serv.service" CACHE STRING "MARS_NWE systemd service name")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED SYSTEMCTL_EXECUTABLE)
|
||||
find_program(SYSTEMCTL_EXECUTABLE systemctl)
|
||||
endif()
|
||||
if(NOT SYSTEMCTL_EXECUTABLE)
|
||||
set(SYSTEMCTL_EXECUTABLE "/usr/bin/systemctl")
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/config.h"
|
||||
@@ -25,6 +38,11 @@ configure_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/smart"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/control.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/control"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/static/start.html.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/static/start.html"
|
||||
@@ -74,6 +92,7 @@ target_link_libraries(check_login
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/smart.conf DESTINATION ${MARS_NWE_INSTALL_FULL_CONFDIR})
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/smart DESTINATION ${MARS_NWE_INSTALL_FULL_LIBEXECDIR})
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/control DESTINATION ${MARS_NWE_INSTALL_FULL_LIBEXECDIR})
|
||||
install(FILES smart.pamd DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME smart)
|
||||
|
||||
install(PROGRAMS apply.pl DESTINATION ${MARS_NWE_INSTALL_FULL_LIBEXECDIR})
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
#define NWWEBUI_VERSION "@MARS_NWE_VERSION@"
|
||||
|
||||
#define DEFAULT_SMART_CONF "@MARS_NWE_INSTALL_FULL_CONFDIR@/smart.conf"
|
||||
#define DEFAULT_SMART_PERL "@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/smart"
|
||||
#define DEFAULT_SMART_PERL "@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/smart"
|
||||
#define DEFAULT_CONTROL_PERL "@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/control"
|
||||
#define DEFAULT_MARS_SERVICE "@MARS_NWE_SYSTEMD_SERVICE@"
|
||||
#define DEFAULT_SYSTEMCTL_PATH "@SYSTEMCTL_EXECUTABLE@"
|
||||
|
||||
#define LOG_PATH_DEFAULT "@MARS_NWE_LOG_DIR@/nwwebui.log"
|
||||
|
||||
|
||||
127
control.cmake
Normal file
127
control.cmake
Normal file
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# SMArT service control helper for MARS_NWE systemd unit.
|
||||
# Installed next to the other SMArT perl helpers.
|
||||
#
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our ($server_id, $mars_nwe_service, $smart_systemctl_path, $cc, %p);
|
||||
|
||||
sub html_escape($)
|
||||
{
|
||||
my ($s) = @_;
|
||||
$s = '' unless defined $s;
|
||||
$s =~ s/&/&/g;
|
||||
$s =~ s/</</g;
|
||||
$s =~ s/>/>/g;
|
||||
$s =~ s/"/"/g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub handle_request()
|
||||
{
|
||||
my $service = $mars_nwe_service || '@MARS_NWE_SYSTEMD_SERVICE@';
|
||||
my $systemctl = $smart_systemctl_path || '@SYSTEMCTL_EXECUTABLE@';
|
||||
my $query = defined($cc) ? $cc : '';
|
||||
my $action = '';
|
||||
|
||||
$query =~ s/^\?//;
|
||||
|
||||
if( $query =~ /^(start|stop|restart|status)$/ )
|
||||
{
|
||||
$action = $1;
|
||||
}
|
||||
elsif( $query =~ /(?:^|&)action=(start|stop|restart|status)(?:&|$)/ )
|
||||
{
|
||||
$action = $1;
|
||||
}
|
||||
elsif( defined($p{action}) && $p{action} =~ /^(start|stop|restart|status)$/ )
|
||||
{
|
||||
$action = $1;
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
HTTP/1.0 200 OK
|
||||
Content-Type: text/html
|
||||
$server_id
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>MARS_NWE service control</title>
|
||||
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
|
||||
<style>
|
||||
body{margin:0;padding:22px;background:#f6f1ea;color:#342a25;font-family:Arial,Helvetica,sans-serif}
|
||||
a{color:#9f1f1f;text-decoration:none;font-weight:bold}a:hover{text-decoration:underline}
|
||||
.box{max-width:900px;margin:0 auto;background:#fffdfa;border:1px solid #e5d6c6;border-radius:16px;padding:22px;box-shadow:0 10px 30px rgba(60,30,10,.10)}
|
||||
h1{margin-top:0;color:#9f1f1f}.meta{padding:12px 14px;background:#fbf6ef;border:1px solid #ecdcc8;border-radius:12px;margin-bottom:14px}
|
||||
pre{background:#2b241f;color:#f8eadc;padding:16px;border-radius:12px;overflow:auto;white-space:pre-wrap}.ok{color:#2f6f35;font-weight:bold}.bad{color:#9f1f1f;font-weight:bold}
|
||||
.actions a{display:inline-block;margin:5px 8px 5px 0;padding:9px 12px;border-radius:10px;background:#9f1f1f;color:#fff}.actions a.secondary{background:#6f5b4f}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="box">
|
||||
<h1>MARS_NWE service control</h1>
|
||||
EOF
|
||||
|
||||
if( $action eq '' )
|
||||
{
|
||||
print "<p class=\"bad\">Invalid action.</p>\n";
|
||||
print "<p>Allowed actions: start, stop, restart, status</p>\n";
|
||||
print "<p><a href=\"/static/start.html\">Back</a></p>\n";
|
||||
print "</div></body></html>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
print '<div class="meta">Action: <b>' . html_escape($action) . '</b><br>' . "\n";
|
||||
print 'Service: <b>' . html_escape($service) . '</b><br>' . "\n";
|
||||
print 'systemctl: <b>' . html_escape($systemctl) . '</b></div>' . "\n";
|
||||
print "<pre>\n";
|
||||
|
||||
my @cmd = ( $systemctl, $action, $service );
|
||||
my $fh;
|
||||
if( ! open( $fh, '-|', @cmd ) )
|
||||
{
|
||||
print 'Could not execute systemctl: ' . html_escape($!) . "\n";
|
||||
print "</pre><p class=\"bad\">Failed.</p>\n";
|
||||
print "<p><a href=\"/static/start.html\">Back</a></p>\n";
|
||||
print "</div></body></html>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
while( my $line = <$fh> )
|
||||
{
|
||||
print html_escape($line);
|
||||
}
|
||||
|
||||
close($fh);
|
||||
my $rc = $? >> 8;
|
||||
|
||||
if( $rc == 0 )
|
||||
{
|
||||
print "</pre><p class=\"ok\">Command completed successfully.</p>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
print "</pre><p class=\"bad\">Command failed with exit code $rc.</p>\n";
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
<div class="actions">
|
||||
<a href="/cgi-bin/control?status" class="secondary">Status</a>
|
||||
<a href="/cgi-bin/control?start">Start</a>
|
||||
<a href="/cgi-bin/control?stop" class="secondary">Stop</a>
|
||||
<a href="/cgi-bin/control?restart">Restart</a>
|
||||
</div>
|
||||
<p><a href="/static/start.html">Back</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -19,6 +19,7 @@ RestartSec=2
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
ReadWritePaths=@MARS_NWE_INSTALL_FULL_CONFDIR@
|
||||
ProtectHome=true
|
||||
|
||||
[Install]
|
||||
|
||||
21
smart.cmake
21
smart.cmake
@@ -38,11 +38,17 @@ $ENV{HOME} = '@MARS_NWE_INSTALL_FULL_CONFDIR@';
|
||||
$smart_libexec_dir = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@';
|
||||
$smart_libexec_dir =~ s#/*$##;
|
||||
|
||||
$smart_control_path = $smart_libexec_dir . '/control' unless defined $smart_control_path;
|
||||
$mars_nwe_service = '@MARS_NWE_SYSTEMD_SERVICE@' unless defined $mars_nwe_service;
|
||||
$smart_systemctl_path = '@SYSTEMCTL_EXECUTABLE@' unless defined $smart_systemctl_path;
|
||||
|
||||
$l = <STDIN>;
|
||||
$l =~ s/[\n\r]//g;
|
||||
$request_uri = "";
|
||||
@c = split( ' ', $l );
|
||||
if( scalar( @c ) > 2 )
|
||||
{
|
||||
$request_uri = $c[1];
|
||||
while( keys( %h ) < 15 ) # Who would ever want to send more headers???
|
||||
{
|
||||
$l = <STDIN>;
|
||||
@@ -104,7 +110,20 @@ foreach $p ( @p )
|
||||
}
|
||||
@c = split( '/', $c );
|
||||
|
||||
if( $c[0] eq 'apply' )
|
||||
if( ( $c[0] eq 'service' && $c[1] eq 'control' ) ||
|
||||
( $c[0] eq 'cgi-bin' && $c[1] eq 'control' ) )
|
||||
{
|
||||
# Service control must run before drop_root().
|
||||
# /service/control is the preferred path; /cgi-bin/control is kept as a legacy alias.
|
||||
my $rv = do( $smart_control_path );
|
||||
if( ! defined $rv )
|
||||
{
|
||||
error( 500 );
|
||||
}
|
||||
handle_request();
|
||||
exit;
|
||||
}
|
||||
elsif( $c[0] eq 'apply' )
|
||||
{
|
||||
do( $smart_libexec_dir . '/readconfig.pl' );
|
||||
do( $smart_libexec_dir . '/apply.pl' );
|
||||
|
||||
@@ -64,6 +64,16 @@ $smart_log_path = '@MARS_NWE_LOG_DIR@/smart.log';
|
||||
# Path to the PAM-based login helper used for root authentication.
|
||||
$smart_check_login = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/check_login';
|
||||
|
||||
|
||||
# Path to the SMArT service-control helper.
|
||||
$smart_control_path = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/control';
|
||||
|
||||
# systemd unit controlled by the SMArT service-control page.
|
||||
$mars_nwe_service = '@MARS_NWE_SYSTEMD_SERVICE@';
|
||||
|
||||
# systemctl executable used by the service-control helper.
|
||||
$smart_systemctl_path = '@SYSTEMCTL_EXECUTABLE@';
|
||||
|
||||
# Optional explicit path to the main SMArT Perl program.
|
||||
# This is normally not required, because nwwebui already has a built-in default.
|
||||
# Uncomment and adjust only if a non-standard location must be used.
|
||||
|
||||
@@ -100,8 +100,12 @@
|
||||
<DIV CLASS="actions">
|
||||
<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0">
|
||||
<TR>
|
||||
<TD WIDTH="50%"><A CLASS="action" HREF="/cgi-bin/control?start">Start <TT>MARS_NWE</TT></A></TD>
|
||||
<TD WIDTH="50%"><A CLASS="action secondary" HREF="/cgi-bin/control?stop">Stop <TT>MARS_NWE</TT></A></TD>
|
||||
<TD WIDTH="50%"><A CLASS="action" HREF="/service/control?start">Start <TT>MARS_NWE</TT></A></TD>
|
||||
<TD WIDTH="50%"><A CLASS="action secondary" HREF="/service/control?stop">Stop <TT>MARS_NWE</TT></A></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD WIDTH="50%"><A CLASS="action secondary" HREF="/service/control?restart">Restart <TT>MARS_NWE</TT></A></TD>
|
||||
<TD WIDTH="50%"><A CLASS="action secondary" HREF="/service/control?status">Status <TT>MARS_NWE</TT></A></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</DIV>
|
||||
|
||||
Reference in New Issue
Block a user