forked from shaba/openuds
More fixes for WOL on Phisical Machines
This commit is contained in:
parent
26aa9f6db7
commit
93a12c180e
@ -35,9 +35,12 @@ import typing
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
import dns.resolver
|
||||
|
||||
from uds.core import services
|
||||
from uds.core.util.state import State
|
||||
from uds.core.util.auto_attributes import AutoAttributes
|
||||
from uds.core.util import net
|
||||
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
@ -69,12 +72,22 @@ class IPMachineDeployed(services.UserDeployment, AutoAttributes):
|
||||
def getIp(self) -> str:
|
||||
# If single machine, ip is IP~counter,
|
||||
# If multiple and has a ';' on IP, the values is IP;MAC
|
||||
return self._ip.split('~')[0].split(';')[0]
|
||||
ip = self._ip.split('~')[0].split(';')[0]
|
||||
# If ip is in fact a hostname...
|
||||
if not net.ipToLong(ip):
|
||||
# Try to resolve name...
|
||||
try:
|
||||
res = dns.resolver.resolve(ip)
|
||||
ip = res[0].address
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return ip
|
||||
|
||||
def getName(self) -> str:
|
||||
# If single machine, ip is IP~counter,
|
||||
# If multiple and has a ';' on IP, the values is IP;MAC
|
||||
return _("IP ") + self._ip.replace('~', ':')
|
||||
return self._ip.replace('~', ':')
|
||||
|
||||
def getUniqueId(self) -> str:
|
||||
# If single machine, ip is IP~counter,
|
||||
|
@ -36,6 +36,8 @@ import typing
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
|
||||
import dns.resolver
|
||||
|
||||
from uds.core import services
|
||||
from uds.core.ui.user_interface import gui
|
||||
from uds.core.util import net
|
||||
@ -47,15 +49,28 @@ 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,
|
||||
length=8192,
|
||||
multiline=6,
|
||||
label=_('Advanced configuration'),
|
||||
order=3,
|
||||
tooltip=_('Advanced configuration data for the provider'),
|
||||
required=True, tab=gui.ADVANCED_TAB
|
||||
required=True,
|
||||
tab=gui.ADVANCED_TAB,
|
||||
)
|
||||
|
||||
def initialize(self, values: 'Module.ValuesType') -> None:
|
||||
"""checks and initializes values
|
||||
|
||||
Args:
|
||||
values (Module.ValuesType): List of values on initialization (maybe None)
|
||||
|
||||
Raises:
|
||||
services.ServiceProvider.ValidationException
|
||||
"""
|
||||
if values is None:
|
||||
return
|
||||
|
||||
@ -67,23 +82,30 @@ class PhysicalMachinesProvider(services.ServiceProvider):
|
||||
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))
|
||||
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)
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
raise services.ServiceProvider.ValidationException(
|
||||
_('Invalid url in advanced configuration: ') + key
|
||||
)
|
||||
|
||||
# What services do we offer?
|
||||
typeName = _('Static IP Machines Provider')
|
||||
@ -93,22 +115,46 @@ class PhysicalMachinesProvider(services.ServiceProvider):
|
||||
|
||||
from .service_multi import IPMachinesService
|
||||
from .service_single import IPSingleMachineService
|
||||
|
||||
offers = [IPMachinesService, IPSingleMachineService]
|
||||
|
||||
def wolURL(self, ip: str):
|
||||
if not self.config.value or not ip:
|
||||
def wolURL(self, ip: str, mac: str) -> str:
|
||||
"""Tries to get WOL server for indicated IP
|
||||
|
||||
Args:
|
||||
ip (str): ip of target machine
|
||||
|
||||
Returns:
|
||||
str: URL of WOL server or empty ('') if no server for the ip is found
|
||||
"""
|
||||
if not self.config.value or not ip or not mac:
|
||||
return ''
|
||||
|
||||
# If ip is in fact a hostname...
|
||||
if not net.ipToLong(ip):
|
||||
# Try to resolve name...
|
||||
try:
|
||||
res = dns.resolver.resolve(ip)
|
||||
ip = res[0].address
|
||||
except Exception:
|
||||
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]
|
||||
return (
|
||||
config['wol'][key]
|
||||
.replace('{MAC}', mac)
|
||||
.replace('{IP}', ip)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error('Error parsing advanced configuration: %s', e)
|
||||
|
||||
|
||||
return ''
|
||||
|
||||
def __str__(self):
|
||||
return "Physical Machines Provider"
|
||||
|
@ -34,39 +34,26 @@ import requests
|
||||
import logging
|
||||
import typing
|
||||
|
||||
import dns.resolver
|
||||
|
||||
from uds.core import services
|
||||
from uds.core.util import net
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from . import provider
|
||||
|
||||
class IPServiceBase(services.Service):
|
||||
|
||||
class IPServiceBase(services.Service):
|
||||
@staticmethod
|
||||
def getIp(ipData: str) -> str:
|
||||
ip = ipData.split('~')[0].split(';')[0]
|
||||
# If ip is in fact a hostname...
|
||||
if not net.ipToLong(ip):
|
||||
# Try to resolve name...
|
||||
try:
|
||||
res = dns.resolver.resolve(ip)
|
||||
ip = res[0].address
|
||||
except Exception:
|
||||
return ''
|
||||
|
||||
return ip
|
||||
|
||||
return ipData.split('~')[0].split(';')[0]
|
||||
|
||||
@staticmethod
|
||||
def getMac(ipData: str) -> typing.Optional[str]:
|
||||
def getMac(ipData: str) -> str:
|
||||
try:
|
||||
return ipData.split('~')[0].split(';')[1]
|
||||
except Exception:
|
||||
return None
|
||||
return ''
|
||||
|
||||
def parent(self) -> 'provider.PhysicalMachinesProvider':
|
||||
return typing.cast('provider.PhysicalMachinesProvider', super().parent())
|
||||
@ -79,7 +66,10 @@ class IPServiceBase(services.Service):
|
||||
|
||||
def wakeup(self, ip: str, mac: typing.Optional[str]) -> None:
|
||||
if mac:
|
||||
wolurl = self.parent().wolURL(ip).replace('{MAC}', mac or '').replace('{IP}', ip or '')
|
||||
wolurl = (
|
||||
self.parent()
|
||||
.wolURL(ip, mac)
|
||||
)
|
||||
if wolurl:
|
||||
logger.info('Launching WOL: %s', wolurl)
|
||||
try:
|
||||
|
@ -31,7 +31,6 @@
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
import pickle
|
||||
import subprocess
|
||||
import logging
|
||||
import typing
|
||||
|
||||
@ -197,18 +196,6 @@ class IPMachinesService(IPServiceBase):
|
||||
consideredFreeTime = now - config.GlobalConfig.SESSION_EXPIRE_TIME.getInt(force=False) * 3600
|
||||
for ip in self._ips:
|
||||
theIP = IPServiceBase.getIp(ip)
|
||||
if not theIP:
|
||||
self.parent().doLog(
|
||||
log.WARN,
|
||||
'Hostname in {} could not be resolved. Skipped.'.format(
|
||||
ip
|
||||
),
|
||||
)
|
||||
logger.warning(
|
||||
'Hostname in %s could not be resolved. Skipped.', ip
|
||||
)
|
||||
continue
|
||||
|
||||
theMAC = IPServiceBase.getMac(ip)
|
||||
locked = self.storage.getPickle(theIP)
|
||||
if not locked or locked < consideredFreeTime:
|
||||
@ -216,7 +203,7 @@ class IPMachinesService(IPServiceBase):
|
||||
continue # The check failed not so long ago, skip it...
|
||||
self.storage.putPickle(theIP, now)
|
||||
# Is WOL enabled?
|
||||
wolENABLED = bool(theMAC and self.parent().wolURL(theIP))
|
||||
wolENABLED = bool(self.parent().wolURL(theIP, theMAC))
|
||||
# Now, check if it is available on port, if required...
|
||||
if self._port > 0 and not wolENABLED: # If configured WOL, check is a nonsense
|
||||
if (
|
||||
@ -277,9 +264,6 @@ class IPMachinesService(IPServiceBase):
|
||||
IPMachineDeployed, userDeployment
|
||||
)
|
||||
theIP = IPServiceBase.getIp(assignableId)
|
||||
if not theIP:
|
||||
return userServiceInstance.error('Hostname could not be resolved')
|
||||
|
||||
if self.storage.readData(theIP) is None:
|
||||
self.storage.saveData(theIP, theIP)
|
||||
return userServiceInstance.assign(theIP)
|
||||
|
Loading…
x
Reference in New Issue
Block a user