Added config for WOL on UDS

This commit is contained in:
Adolfo Gómez García 2021-03-23 15:38:02 +01:00
parent b9ba304493
commit 8c68da806a
3 changed files with 79 additions and 24 deletions

View File

@ -30,13 +30,60 @@
"""
@author: Adolfo Gómez, dkmaster at dkmon dot com
"""
import configparser
import logging
import typing
from django.utils.translation import ugettext_noop as _
from uds.core import services
from uds.core.ui.user_interface import gui
from uds.core.util import net
if typing.TYPE_CHECKING:
from uds.core.module import Module
logger = logging.getLogger(__name__)
VALID_CONFIG_SECTIONS = set(('wol',))
class PhysicalMachinesProvider(services.ServiceProvider):
# No extra data needed
config = gui.TextField(
length=8192, multiline=6, label=_('Advanced configuration'), order=3,
tooltip=_('Advanced configuration data for the provider'),
required=True, tab=gui.ADVANCED_TAB
)
def initialize(self, values: 'Module.ValuesType') -> None:
if values is None:
return
self.config.value = self.config.value.strip()
if self.config.value:
config = configparser.ConfigParser()
try:
config.read_string(self.config.value)
# Seems a valid configuration file, let's see if all se
except Exception as e:
raise services.ServiceProvider.ValidationException(_('Invalid advanced configuration: ') + str(e))
for section in config.sections():
if section not in VALID_CONFIG_SECTIONS:
raise services.ServiceProvider.ValidationException(_('Invalid section in advanced configuration: ') + section)
# Sections are valid, check values
# wol section
for key in config['wol']:
try:
net.networksFromString(key) # Raises exception if net is invalid
except Exception:
raise services.ServiceProvider.ValidationException(_('Invalid network in advanced configuration: ') + key)
# Now check value is an url
if config['wol'][key][:4] != 'http':
raise services.ServiceProvider.ValidationException(_('Invalid url in advanced configuration: ') + key)
# What services do we offer?
typeName = _('Static IP Machines Provider')
@ -48,5 +95,20 @@ class PhysicalMachinesProvider(services.ServiceProvider):
from .service_single import IPSingleMachineService
offers = [IPMachinesService, IPSingleMachineService]
def wolURL(self, ip: str):
if not self.config.value:
return ''
url = ''
try:
config = configparser.ConfigParser()
config.read_string(self.config.value)
for key in config['wol']:
if net.ipInNetwork(ip, key):
return config['wol'][key]
except Exception as e:
logger.error('Error parsing advanced configuration: %s', e)
def __str__(self):
return "Physical Machines Provider"

View File

@ -30,7 +30,7 @@
"""
@author: Adolfo Gómez, dkmaster at dkmon dot com
"""
import subprocess
import requests
import logging
import typing
@ -38,19 +38,8 @@ from uds.core import services
logger = logging.getLogger(__name__)
# We have included a "hidden testing" for adding ip+mac as static machines list.
# (This is done using IP;MAC as IP on the IP list)
# This is a test for WOL, and to be used at your risk.
# Example:
# WOLAPP = "/usr/sbin/etherwake {MAC} -i eth0 -b"
# Remember that you MUST setuid /usr/sbin/etherwake (chmod +s ....) and allow only for uds user,
# so it allows uds user to execute "privileged" etherwake program
# Note:
# {MAC} will be replaced with the MAC if it exists
# {IP} will be replaced with the IP of the machine
# If empty, no WOL will be tried NEVER, if not empty
WOLAPP = ''
if typing.TYPE_CHECKING:
from . import provider
class IPServiceBase(services.Service):
@ -65,6 +54,9 @@ class IPServiceBase(services.Service):
except Exception:
return None
def parent(self) -> 'provider.PhysicalMachinesProvider':
return typing.cast('provider.PhysicalMachinesProvider', super().parent())
def getUnassignedMachine(self) -> typing.Optional[str]:
raise NotADirectoryError('getUnassignedMachine')
@ -72,11 +64,12 @@ class IPServiceBase(services.Service):
raise NotADirectoryError('unassignMachine')
def wakeup(self, ip: str, mac: typing.Optional[str]) -> None:
if WOLAPP and mac:
cmd = WOLAPP.replace('{MAC}', mac or '').replace('{IP}', ip or '')
logger.info('Launching WOL: %s', cmd)
try:
result = subprocess.run(cmd, shell=True, check=True)
# logger.debug('Result: %s', result)
except Exception as e:
logger.error('Error on WOL: %s', e)
if mac:
wolurl = self.parent().wolURL(ip).replace('{MAC}', mac or '').replace('{IP}', ip or '')
if wolurl:
logger.info('Launching WOL: %s', wolurl)
try:
requests.get(wolurl, verify=False)
# logger.debug('Result: %s', result)
except Exception as e:
logger.error('Error on WOL: %s', e)

View File

@ -46,7 +46,7 @@ from uds.core.util import config
from uds.core.services import types as serviceTypes
from .deployment import IPMachineDeployed
from .service_base import IPServiceBase, WOLAPP
from .service_base import IPServiceBase
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
@ -204,7 +204,7 @@ class IPMachinesService(IPServiceBase):
continue # The check failed not so long ago, skip it...
self.storage.putPickle(theIP, now)
# Now, check if it is available on port, if required...
if self._port > 0 and not WOLAPP: # If configured WOLAPP, then check port is a nonsense...
if self._port > 0 and not self.parent().wolURL(theIP): # If configured WOL, check is a nonsense
if (
connection.testServer(theIP, self._port, timeOut=0.5)
is False