system: migrate services page to MVC #6376

Widget is next.  While here set configd to 'locked'.
This commit is contained in:
Franco Fichtner 2023-03-15 12:28:05 +01:00
parent 3111b79d99
commit 03ac997fa4
12 changed files with 311 additions and 116 deletions

4
plist
View File

@ -269,12 +269,14 @@
/usr/local/opnsense/mvc/app/controllers/OPNsense/CaptivePortal/forms/dialogZone.xml
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/MenuController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/ServiceController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/Api/SystemController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/FirmwareController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/HaltController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/IndexController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/LicenseController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/RebootController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Core/ServiceController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Cron/Api/ServiceController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Cron/Api/SettingsController.php
/usr/local/opnsense/mvc/app/controllers/OPNsense/Cron/IndexController.php
@ -668,6 +670,7 @@
/usr/local/opnsense/mvc/app/views/OPNsense/Core/license.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/not_found.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/reboot.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Core/service.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Cron/index.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/arp.volt
/usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/dns_diagnostics.volt
@ -1957,7 +1960,6 @@
/usr/local/www/status_interfaces.php
/usr/local/www/status_ntpd.php
/usr/local/www/status_openvpn.php
/usr/local/www/status_services.php
/usr/local/www/status_wireless.php
/usr/local/www/system_advanced_admin.php
/usr/local/www/system_advanced_firewall.php

View File

@ -68,6 +68,7 @@ function core_services()
'stop' => array('/usr/local/etc/rc.d/configd stop'),
),
'name' => 'configd',
'locked' => true,
);
$services[] = array(
@ -124,8 +125,8 @@ function core_services()
'php' => array(
'restart' => array('webgui_configure_delayed')
),
'locked' => true,
'name' => 'webgui',
'locked' => true,
);
return $services;

View File

@ -0,0 +1,129 @@
<?php
/*
* Copyright (C) 2023 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Core\Api;
use OPNsense\Base\ApiControllerBase;
use OPNsense\Core\Backend;
use OPNsense\Core\Config;
/**
* Class SessionsController
* @package OPNsense\IPsec\Api
*/
class ServiceController extends ApiControllerBase
{
private function list_status()
{
return json_decode((new Backend())->configdRun('service list'), true);
}
/**
* Search phase 1 session entries
* @return array
*/
public function searchAction()
{
$this->sessionClose();
$data = $this->list_status();
$records = [];
$phase1s = [];
if (!empty($data)) {
foreach ($data as $service) {
$record = [
'id' => $service['name'] . (array_key_exists('id', $service) ? '/' . $service['id'] : ''),
'locked' => !empty($service['locked']) || !empty($service['nocheck']) ? 1 : 0,
'running' => strpos($service['status'], 'is running') !== false ? 1 : 0,
'description' => $service['description'],
'name' => $service['name'],
];
$records[] = $record;
}
}
return $this->searchRecordsetBase($records);
}
/**
* start a service
* @param string $name to identify the service
* @param string $id to identify the service instance
* @return array
*/
public function startAction($name, $id = '')
{
if (!$this->request->isPost()) {
return ['result' => 'failed'];
}
$this->sessionClose();
(new Backend())-> configdpRun('service start', [$name, $id]);
return ['result' => 'ok'];
}
/**
* restart a service
* @param string $name to identify the service
* @param string $id to identify the service instance
* @return array
*/
public function restartAction($name, $id = '')
{
if (!$this->request->isPost()) {
return ['result' => 'failed'];
}
$this->sessionClose();
(new Backend())-> configdpRun('service restart', [$name, $id]);
return ['result' => 'ok'];
}
/**
* stop a service
* @param string $name to identify the service
* @param string $id to identify the service instance
* @return array
*/
public function stopAction($name, $id = '')
{
if (!$this->request->isPost()) {
return ['result' => 'failed'];
}
$this->sessionClose();
(new Backend())-> configdpRun('service stop', [$name, $id]);
return ['result' => 'ok'];
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
* Copyright (C) 2023 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Core;
/**
* Class ServiceController controller for service core actions
* @package OPNsense\Core
*/
class ServiceController extends \OPNsense\Base\IndexController
{
/**
* return to / for non existent actions
*/
public function indexAction()
{
$this->view->pick('OPNsense/Core/service');
}
}

View File

@ -520,7 +520,8 @@
<page-status-services>
<name>Status: Services</name>
<patterns>
<pattern>status_services.php*</pattern>
<pattern>ui/core/service/*</pattern>
<pattern>api/core/service/*</pattern>
</patterns>
</page-status-services>
<page-status-systemlogs-portalauth>

View File

@ -98,9 +98,7 @@
<WebGUI VisibleName="Web GUI" url="/ui/diagnostics/log/core/lighttpd"/>
</LogFiles>
<Diagnostics order="160" cssClass="fa fa-medkit fa-fw">
<Services url="/status_services.php">
<All url="/status_services.php?*" visibility="hidden"/>
</Services>
<Services url="/ui/core/service"/>
</Diagnostics>
</System>
<Interfaces order="30" cssClass="fa fa-sitemap">

View File

@ -0,0 +1,105 @@
{#
# Copyright (c) 2023 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#}
<script>
'use strict';
$( document ).ready(function () {
let grid_service = $("#grid-service").UIBootgrid({
search:'/api/core/service/search',
options:{
multiSelect: false,
rowSelect: true,
selection: true,
formatters:{
commands: function (column, row) {
if (row['locked']) {
return '<button type="button" class="btn btn-xs btn-default command-restart" data-toggle="tooltip" title="{{ lang._('Restart') }}" data-row-id="' + row.name + '"><span class="fa fa-repeat fa-fw"></span></button>';
} else if (row['running']) {
return '<button type="button" class="btn btn-xs btn-default command-restart" data-toggle="tooltip" title="{{ lang._('Restart') }}" data-row-id="' + row.name + '"><span class="fa fa-repeat fa-fw"></span></button>' +
'<button type="button" class="btn btn-xs btn-default command-stop" data-toggle="tooltip" title="{{ lang._('Stop') }}" data-row-id="' + row.name + '"><span class="fa fa-stop fa-fw"></span></button>';
} else {
return '<button type="button" class="btn btn-xs btn-default command-start" data-toggle="tooltip" title="{{ lang._('Start') }}" data-row-id="' + row.name + '"><span class="fa fa-play fa-fw"></span></button>';
}
},
status: function (column, row) {
if (row['running']) {
return '<span class="label label-opnsense label-opnsense-xs label-success pull-right" data-toggle="tooltip" title="{{ lang._('Running') }}"><i class="fa fa-play fa-fw"></i></span>';
} else {
return '<span class="label label-opnsense label-opnsense-xs label-danger pull-right" data-toggle="tooltip" title="{{ lang._('Stopped') }}"><i class="fa fa-stop fa-fw"></i></span>';
}
}
}
}
});
grid_service.on('loaded.rs.jquery.bootgrid', function () {
$('[data-toggle="tooltip"]').tooltip();
let ids = $("#grid-service").bootgrid("getCurrentRows");
if (ids.length > 0) {
$("#grid-service").bootgrid('select', [ids[0].name]);
}
$('.command-stop').click(function () {
$(this).toggleClass('disabled');
$(this).children().toggleClass('fa-stop fa-spinner fa-pulse');
ajaxCall("/api/core/service/stop/" + $(this).data('row-id'), {}, function () {
$('#grid-service').bootgrid('reload');
});
});
$('.command-start').click(function () {
$(this).toggleClass('disabled');
$(this).children().toggleClass('fa-start fa-spinner fa-pulse');
ajaxCall("/api/core/service/start/" + $(this).data('row-id'), {}, function () {
$('#grid-service').bootgrid('reload');
});
});
$('.command-restart').click(function () {
$(this).toggleClass('disabled');
$(this).children().toggleClass('fa-repeat fa-spinner fa-pulse');
ajaxCall("/api/core/service/restart/" + $(this).data('row-id'), {}, function () {
$('#grid-service').bootgrid('reload');
});
});
});
});
</script>
<div class="tab-content content-box __mb">
<table id="grid-service" class="table table-condensed table-hover table-striped table-responsive">
<thead>
<tr>
<th data-column-id="id" data-type="string" data-sortable="false" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="name" data-type="string">{{ lang._('Name') }}</th>
<th data-column-id="description" data-type="string">{{ lang._('Description') }}</th>
<th data-column-id="locked" data-type="string" data-sortable="false" data-visible="false"></th>
<th data-column-id="running" data-type="string" data-width="3em" data-formatter="status" data-sortable="false"></th>
<th data-column-id="commands" data-width="6em" data-formatter="commands" data-sortable="false"></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>

View File

@ -15,3 +15,21 @@ command:/usr/local/sbin/pluginctl -S
parameters:%s %s
type:script_output
message:Fetching service list (%s %s)
[start]
command:/usr/local/sbin/pluginctl -s
parameters:%s start %s
type:script
message:Starting service (%s %s)
[restart]
command:/usr/local/sbin/pluginctl -s
parameters:%s restart %s
type:script
message:Restarting service (%s %s)
[stop]
command:/usr/local/sbin/pluginctl -s
parameters:%s stop %s
type:script
message:Stopping service (%s %s)

View File

@ -86,12 +86,12 @@ $product = product::getInstance();
$( document ).ready(function() {
$('.srv_status_act').click(function(event){
event.preventDefault();
let params = {};
params['action'] = $(this).data('service_action');
params['service'] = $(this).data('service');
params['id'] = $(this).data('service_id');
let url = '/api/core/service/' + $(this).data('service_action') + '/' + $(this).data('service');
if ($(this).data('service_id') != '') {
url += '/' + $(this).data('service_id');
}
$("#OPNsenseStdWaitDialog").modal('show');
$.post('/status_services.php',params, function(data) {
$.post(url, {}, function (data) {
// refresh page after service action via server
location.reload(true);
});

View File

@ -219,7 +219,7 @@ include("head.inc");
elseif (count($ntpq_servers) == 0): ?>
<tr>
<td colspan="11">
<?= sprintf(gettext('No peers found, %sis the ntp service running%s?'), '<a href="status_services.php">','</a>') ?>
<?= gettext('No peers found.') ?>
</td>
</tr>
<?php

View File

@ -1,103 +0,0 @@
<?php
/*
* Copyright (C) 2014-2015 Deciso B.V.
* Copyright (C) 2005-2006 Colin Smith <ethethlay@gmail.com>
* Copyright (C) 2004-2005 Scott Ullrich <sullrich@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INClUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
require_once("guiconfig.inc");
require_once("system.inc");
require_once("filter.inc");
require_once("interfaces.inc");
if (!empty($_POST['service'])) {
$service_name = $_POST['service'];
switch ($_POST['action']) {
case 'restart':
echo service_control_restart($service_name, $_POST);
break;
case 'start':
echo service_control_start($service_name, $_POST);
break;
case 'stop':
echo service_control_stop($service_name, $_POST);
break;
}
exit;
}
$services = plugins_services();
include("head.inc");
?>
<body>
<?php include("fbegin.inc"); ?>
<section class="page-content-main">
<div class="container-fluid">
<div class="row">
<?php if (isset($savemsg)) print_info_box($savemsg); ?>
<section class="col-xs-12">
<div class="content-box">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<td><?=gettext("Service");?></td>
<td><?=gettext("Description");?></td>
<td><?=gettext("Status");?></td>
</tr>
</thead>
<tbody>
<?php
if (count($services) > 0):
foreach($services as $service):?>
<tr>
<td><?=$service['name'];?></td>
<td><?=$service['description'];?></td>
<td>
<?= service_control_icon($service); ?>
<?= service_control_links($service); ?>
</td>
</tr>
<?php
endforeach;
else:?>
<tr>
<td colspan="3"> <?=gettext("No services found");?></td>
</tr>
<?php
endif;?>
</tbody>
</table>
</div>
</div>
</section>
</div>
</div>
</section>
<?php include("foot.inc"); ?>

View File

@ -1,4 +1,4 @@
<?php
$services_status_title = gettext('Services');
$services_status_title_link = 'status_services.php';
$services_status_title_link = 'ui/core/service';