net/wol: fix the ARP lookup in the least intrusive way #4192

Also make sure the wake button has some form of user feedback.
The checkmark is reset when the plugin is refreshed.  Omitted
spinner because the action only takes a fraction of a second.
This commit is contained in:
Franco Fichtner
2024-08-26 13:12:19 +02:00
parent e553f5691f
commit 40d28ac149
2 changed files with 28 additions and 7 deletions
@@ -66,27 +66,40 @@ class WolController extends ApiMutableModelControllerBase
{
$this->delBase('wolentry', $uuid);
}
public function searchHostAction()
{
return $this->searchBase('wolentry', array("interface", "mac", "descr"));
$ret = $this->searchBase('wolentry', ['interface', 'mac', 'descr']);
foreach ($ret['rows'] ?? [] as $idx => $wol) {
/* not entirely accurate naming but it's too much effor to unwind this API */
$ret['rows'][$idx]['identifier'] =
(string)$this->getModel()->getNodeByReference('wolentry.' . $wol['uuid'])->interface;
}
return $ret;
}
public function getHostAction($uuid = null)
{
$this->sessionClose();
return $this->getBase('host', 'wolentry', $uuid);
}
public function getwakeAction()
{
return $this->getBase('wake', 'wolentry', null);
}
public function addHostAction()
{
return $this->addBase('host', 'wolentry');
}
public function setHostAction($uuid)
{
return $this->setBase('host', 'wolentry', $uuid);
}
public function wakeallAction()
{
if (!$this->request->isPost()) {
@@ -100,6 +113,7 @@ class WolController extends ApiMutableModelControllerBase
}
return $results;
}
private function wakeHostByNode($wolent, &$result)
{
$backend = new Backend();
@@ -114,6 +128,7 @@ class WolController extends ApiMutableModelControllerBase
$broadcast_ip = escapeshellarg($this->calculateSubnetBroadcast($ipaddr, $cidr));
$result['status'] = trim($backend->configdRun("wol wake {$broadcast_ip} " . escapeshellarg((string)$wolent->mac)));
}
private function getInterfaceIP($if)
{
$cfg = Config::getInstance()->object();
@@ -128,6 +143,7 @@ class WolController extends ApiMutableModelControllerBase
return null;
}
}
private function getInterfaceSubnet($if)
{
$cfg = Config::getInstance()->object();
@@ -137,6 +153,7 @@ class WolController extends ApiMutableModelControllerBase
return null;
}
}
private function calculateSubnetBroadcast($ip_addr, $cidr)
{
// TODO undefined offset
@@ -50,10 +50,10 @@ export default class WakeOnLan extends BaseTableWidget {
const data = await this.ajaxCall('/api/wol/wol/searchHost');
let rows = [];
if (data.total == 0) {
if (data.total == 0) {
const empty_list = [`<b>${this.translations.msg_empty_wol}</b>`];
rows.push(empty_list);
} else {
} else {
const header = [`<b>${this.translations.h_device}</b>`,
`<b>${this.translations.h_interface}</b>`,
`<b>${this.translations.h_status}</b>`,
@@ -66,13 +66,13 @@ export default class WakeOnLan extends BaseTableWidget {
for(let it = 0; it < data.rows.length; it++){
const item = data.rows[it];
let is_active = this.checkActive(arp, item.mac, item.interface);
let is_active = this.checkActive(arp, item.mac, item.identifier);
let row = [
`${item.descr.length !== 0 ? item.descr + '<br/>': ''} ${item.mac}`,
`${item.interface}`,
`<i class="fa fa-${is_active == 1 ? "play" : "remove"} fa-fw text-${is_active == 1 ? "success" : "danger"}" ></i>
${ is_active == 1 ? "Online" : "Offline"}`,
`<button class="btn btn-primary btn-xs wakeupbtn" data-mac="${item.mac}" data-interface="${item.interface}" data-uuid="${item.uuid}">
`<button class="btn btn-primary btn-xs wakeupbtn" data-uuid="${item.uuid}">
<i class="fa fa-bolt fa-fw" title="Wake Up"></i>
</button>`
];
@@ -83,8 +83,12 @@ export default class WakeOnLan extends BaseTableWidget {
$('.wakeupbtn').on('click', async (event) => {
event.preventDefault();
let btn = $(event.currentTarget).find('i');
/* the call is quick, omit fa-spinner fa-pulse use */
const data = {uuid: $(event.currentTarget).data('uuid')};
const result = await this.ajaxCall('/api/wol/wol/set', JSON.stringify(data), 'POST');
const result = await this.ajaxCall('/api/wol/wol/set', JSON.stringify(data), 'POST').then(() => {
btn.removeClass('fa-bolt').addClass('fa-check');
});
});
}