Seite 1 von 1
WOL-Broadcast überarbeiten
Verfasst: 02 Nov 2021, 15:39
von volfo
Hallo uib,
wir in Ulm haben das WOL - Problem, dass wir maximal 10 Clients gleichzeitig über configed auswählen und WakeOnLan ausführen können.
Jeder weitere Aufruf wird von den Routern gedropped. Der Packageburst überschreitet den Maximalwert.
Beim Debuggen sind wir final im
Opsi-WOL Code an dieser for-Schleife hängen geblieben:
Code: Alles auswählen
Line 294 for broadcastAddress, targetPorts in self._broadcastAddresses.items():
Auch wenn die Clients in unterschiedlichen Subnetzen sind (bei uns 21 Stück) wird an alle der WOL-Befehl gesendet.
Könntet ihr hier eine Vorauswahl einbauen?
zB. könnte in der hostcontrol.conf die
broadcastAddresses noch durch die jeweilige Subnetmask erweitert werden und dann könnte
die for-Schleife durch eine switch-Anweisung ersetzt und die passende Broadcast-Addresse gewählt werden. (irgendwie so zumindest)
Den Burst hier zu reduzieren wäre sicher eine feine Sache.
Viele Grüße aus Ulm
Volker
Re: WOL-Broadcast überarbeiten
Verfasst: 13 Jan 2022, 16:17
von volfo
Hier eine Präzisierung der WOL-Überarbeitung:
für unsere Zwecke habe ich ein WOL - pythonskript geschrieben, dass directed broadcasts für WOL verwendet.
Es läuft auf unserem opsi-server mit opsi-python, wäre also wahrscheinlich recht einfach in opsi zu übernehmen.
Entgegen meinem ersten Post benötigt es keine weiteren Daten, nur eine passende Sortierung im Ipaddress-Format.
Das macht den WakeOnLan-Aufruf viel performanter,
bei uns reduziert es den WOL-Traffic etwa um den Faktor 20 (abhängig von der Anzahl an Subnetzen und Clients).
unter Verwendung von
nehme ich alle broadcast-Addressen aus der hostcontrol.conf und sortiere sie:
Code: Alles auswählen
for adr in broadcasts:
bcas.append(ipaddress.ip_address(adr))
bcas.sort()
dann kann man für die ClientIP aus den sortierten broadcast-Addressen leicht die passende herausfinden:
Code: Alles auswählen
ipadr = ipaddress.ip_address(ip)
#getting broadcast-address for ip
a = iter(bcas)
for bca in bcas:
if ((ipadr<bca) and (ipadr>next(a))):
ownbca=bca
break
und somit kann man aus einem Broadcast über alle Broadcast-Addressen einen directed broadcast in das passende Subnetz machen.
Re: WOL-Broadcast überarbeiten
Verfasst: 13 Jan 2022, 17:08
von j.schneider
Hallo,
sieht gut aus, wir bauen das gerne ein, vielen Dank!
Bitte einmal das komplette Skript posten oder per E-Mail an uns.
Danke!
Grüße
Jan Schneider
Re: WOL-Broadcast überarbeiten
Verfasst: 13 Jan 2022, 17:55
von volfo
Bitte sehr:
Code: Alles auswählen
#!/usr/bin/opsi-python
# -*- coding: utf-8 -*-
# This file is part of the kiz-opsi-infrastructure
# WakeUpScript - WakeOnLan
# working on Opsi4.2-Server without using Opsi-Server-Api
# Copyright (C) 2020 kiz - Ulm University <kiz@uni-ulm.de>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import subprocess
import time
import json
import ipaddress
import logging
from logging.handlers import RotatingFileHandler
### setting up logging ###
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-8.8s] %(message)s", datefmt="%Y/%m/%d %H:%M:%S")
rootLogger = logging.getLogger(__name__)
rootLogger.setLevel(logging.INFO)
fileHandler = RotatingFileHandler("wakeup.log", maxBytes=2000000, backupCount=3)
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
### basic configs ###
#DataBase-Dumb with host_getHashes(attributes=[])
allClients= "setup/allClients.json"
#ClientList to WakeUp
clientlisttxt= "clientsList.txt"
#Broadcast-Addresses (extracted from etc/opsi/hostcontrol.conf)
broadcasts= ["134.60.1.255",
"134.60.2.255",
"134.60.15.255",
"134.60.32.255",
"134.60.39.255",
"134.60.40.255",
"134.60.46.255",
"134.60.55.255",
"134.60.101.255",
"134.60.112.63",
"134.60.127.255",
"134.60.128.255",
"134.60.130.255",
"134.60.132.255",
"134.60.133.255",
"134.60.193.255",
"134.60.194.255",
"134.60.202.255",
"134.60.205.255",
"134.60.206.255",
"134.60.215.255"]
### MAIN() ###
def main():
#Preparing DataSet
errorClients=[]
jsonclients= __readJsonClients(allClients)
clientList= __readClientList(clientlisttxt)
clientsToWakeUp= __setClientsToWakeUp(clientList,jsonclients,broadcasts,errorClients)
#logging malfunctional Clients
if len(errorClients)>0:
rootLogger.warning("Found {} malfunctional Clients in DataSet: ".format(len(errorClients)))
for r in errorClients:
rootLogger.warning("ID={} MAC={} IP={}".format(r["id"], r["hardwareAddress"], r["ipAddress"]))
#checking ClientList
rootLogger.info("Reading Clients from file: {}".format(clientlisttxt))
for r in clientList:
# item does not exist
if not any(d['id'] == r for d in clientsToWakeUp):
rootLogger.warning("ClientID from ClientList does not exists in DataSet: {}".format(r))
print("Error with: {}".format(r))
#starting Mainroutine
rootLogger.info("Prepared {} Clients. Starting procedure".format(len(clientsToWakeUp)))
for client in clientsToWakeUp:
rootLogger.info("Checking client: {}".format(client["id"]))
if __isPingable(client):
rootLogger.info("Client pings, next one...")
else:
rootLogger.info("Sending Wol to {}".format(client["id"]))
__powerOn(client)
time.sleep(2)
rootLogger.info("Skript finished - see you next time")
def __isPingable(client):
p = subprocess.Popen(['ping', '-c', '1', client["id"]], stdout=subprocess.PIPE)
p.wait()
if p.poll():
return False
else:
return True
def __powerOn(client):
with subprocess.Popen(['wakeonlan', '-i', str(client["bca"]), '-p', '12287', client["mac"]], stdout=subprocess.PIPE) as proc:
rootLogger.debug(proc.stdout.read())
proc.wait()
return proc.poll()
def __readClientList(clientlist):
with open(os.path.dirname(os.path.realpath(__file__)) + '/' + clientlist) as f:
clients = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
clients = [client.strip() for client in clients]
return clients
def __readJsonClients(allClients):
with open(os.path.dirname(os.path.realpath(__file__)) + '/' + allClients, 'r') as json_file:
jsonClients = json.load(json_file)
return jsonClients
def __setClientsToWakeUp(clientList, jsonClients, broadcasts,errorClients):
#prepare broadcast-addresses
bcas=[]
for adr in broadcasts:
bcas.append(ipaddress.ip_address(adr))
bcas.sort()
#get data from allClients
clientsToWakeUp=[]
for dic in jsonClients:
id = dic.get("id")
ip = dic.get("ipAddress")
mac = dic.get("hardwareAddress")
ownbca=""
if ip==None:
ipadr=None
errorClients.append(dic)
else:
ipadr = ipaddress.ip_address(ip)
#getting broadcast-address for ip
a = iter(bcas)
for bca in bcas:
if ((ipadr<bca) and (ipadr>next(a))):
ownbca=bca
break
if id in clientList:
clientsToWakeUp.append({"id":id, "ip":ipadr,"mac":mac,"bca":ownbca})
return clientsToWakeUp
if __name__ == "__main__":
# execute only if run as a script
main()
Re: WOL-Broadcast überarbeiten
Verfasst: 17 Jan 2022, 07:40
von j.schneider
Danke für das Skript, ich habe mir das angeschaut.
Ich würde vorschlagen, die hostcontrol.conf so zu ändern, dass man steuern kann für welche Netzwerkadresse welche Broadcast-Adressen verwendet werden sollen. Hierbei wird dann der Eintrag ausgewählt, der für die hinterlegte IP-Adresse des Clients am besten passt.
Ein Beispiel:
Code: Alles auswählen
config = {
"broadcastAddresses": {
"0.0.0.0/0": {
"255.255.255.255": [7, 9, 12287]
},
"10.10.0.0/16": {
"10.10.1.255": [12287],
"10.10.2.255": [12287]
},
"10.10.3.0/24": {
"10.10.3.255": [12287]
},
"192.168.1.0/24": {
"192.168.1.255": [12287, 9, 12287]
}
}
}
Was haltet ihr davon?
Re: WOL-Broadcast überarbeiten
Verfasst: 20 Jan 2022, 09:15
von volfo
Den Vorschlag finde ich gut, damit wäre es das Verhalten auch in der config sichtbar und verständlich.
Re: WOL-Broadcast überarbeiten
Verfasst: 20 Jan 2022, 16:09
von j.schneider
Wir haben das jetzt so umgesetzt.
Folgende Pakete werden dafür benötigt (aktuell in experimental):
opsi-utils 4.2.0.149-1
opsiconfd 4.2.0.228-1
opsi-server 4.2.0.61-1
Die Dokumentation dazu ist in Arbeit.