#!/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-1mk5daemonDifxAlertMessage275Filesystem 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)