#!/usr/bin/env python3 #************************************************************************** # Copyright (C) 2017-2019 by Walter Brisken * # * # This program is free software; you can redistribute it and/or modify * # it under the terms of the GNU 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 General Public License for more details. * # * # You should have received a copy of the GNU General Public License * # along with this program; if not, write to the * # Free Software Foundation, Inc., * # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * #************************************************************************** #=========================================================================== # SVN properties (DO NOT CHANGE) # # $Id$ # $HeadURL: $ # $LastChangedRevision$ # $Author$ # $LastChangedDate$ # #============================================================================ # Note: this utility can run under python2.7 or python3 from sys import exit from os import getenv, umask, environ import socket import struct import subprocess import signal import sys from xml.parsers import expat author = 'Walter Brisken' version = '0.3' verdate = '20191009' defaultDifxMessagePort = 50200 defaultDifxMessageGroup = '224.2.2.1' # Parse messages looking like: # # #
mark5fx01-1mk5daemonDifxAlertMessage
275Filesystem list: AVEXT-304
class MessageParser: """ Parses AlertMessage, looking specifically for filesystem list """ def __init__(self): self._parser = expat.ParserCreate() self._parser.StartElementHandler = self.start self._parser.EndElementHandler = self.end self._parser.CharacterDataHandler = self.data self.ok = False self.tmp = '' self.unit = 'unknown' self.media = [] def feed(self, sender, data): self._parser.Parse(data, 0) self.sender = sender def close(self): self._parser.Parse("", 1) # end of data del self._parser # get rid of circular references def start(self, tag, attrs): if tag == 'alertMessage': self.type = tag def parseAlertMessage(self): s = self.tmp.split() if len(s) > 2: if s[0] == 'Filesystem' and s[1] == 'list:': self.ok = True for m in s[2:]: self.media.append(m) def end(self, tag): if tag == 'from': self.unit = self.tmp.lower() if tag == 'alertMessage': self.parseAlertMessage() def data(self, data): self.tmp = data def getinfo(self): return [self.unit, self.media] def sendRequest(destination, command): src = socket.gethostname() dest = '%s' %(destination) message = \ '\n' \ '' \ '
' \ '%s' \ '%s' \ '-1' \ 'listmedia' \ 'DifxCommand' \ '
' \ '' \ '0' \ '' \ '%s' \ '' \ '' \ '
' % (src, dest, command) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) sock.sendto(message.encode('utf-8'), (group, port)) return message def getMediaListByMulticast(maxtime, verbose): dt = 0.2 t = 0.0 # Open receiving socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('', port)) mreq = struct.pack("4sl", socket.inet_aton(group), socket.INADDR_ANY) s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) s.settimeout(dt) # Send out a call for media sendRequest("all", "listfs") # Now listen for responses, until time runs out results = {} while t < maxtime: try: message, address = s.recvfrom(8000) message = message.decode('utf-8') sender = socket.gethostbyaddr(address[0])[0].split('.')[0] if verbose > 1: print(message) print('') p = MessageParser() p.feed(sender, message) info = p.getinfo() p.close() if p.ok: results[info[0]] = info[1] except socket.timeout: t += dt except socket.herror: print('Weird: cannot gethostbyaddr for %s' % address[0]) return results def printResults(results): print('Attached media by unit:') keys = sorted(results.keys()) for key in keys: if len(results[key]) > 0: media = '' for m in results[key]: media += (m + ' ') print('%-10s %s' % (key, media)) #---------------------- port = getenv('DIFX_MESSAGE_PORT') if port == None: port = defaultDifxMessagePort else: port = int(port) group = getenv('DIFX_MESSAGE_GROUP') if group == None: group = defaultDifxMessageGroup results = getMediaListByMulticast(1, 1) printResults(results)