167 lines
5.2 KiB
Python
167 lines
5.2 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
from optparse import OptionParser
|
|
|
|
import sys
|
|
import logging
|
|
import time
|
|
|
|
import sleekxmpp
|
|
from sleekxmpp import Iq
|
|
from sleekxmpp.exceptions import StanzaError
|
|
from sleekxmpp.xmlstream import register_stanza_plugin, ElementBase
|
|
|
|
# Global variable for storing exit code:
|
|
# 0 - focus shutdown OK
|
|
# 1 - unexpected error occurred
|
|
exitCode = 0
|
|
|
|
# Python versions before 3.0 do not use UTF-8 encoding
|
|
# by default. To ensure that Unicode is handled properly
|
|
# throughout SleekXMPP, we will set the default encoding
|
|
# ourselves to UTF-8.
|
|
if sys.version_info < (3, 0):
|
|
from sleekxmpp.util.misc_ops import setdefaultencoding
|
|
setdefaultencoding('utf8')
|
|
else:
|
|
raw_input = input
|
|
|
|
|
|
def get_conferences(stats_xml):
|
|
for stat in stats_xml.findall('{http://jitsi.org/protocol/colibri}stat'):
|
|
name = stat.get('name')
|
|
value = stat.get('value')
|
|
if name == 'conferences':
|
|
return value
|
|
return -1
|
|
|
|
|
|
class ColibriStats(ElementBase):
|
|
|
|
name = 'stats'
|
|
|
|
namespace = 'http://jitsi.org/protocol/colibri'
|
|
|
|
plugin_attrib = 'colibri-stats'
|
|
|
|
|
|
class GracefulShutdown(ElementBase):
|
|
|
|
name = 'graceful-shutdown'
|
|
|
|
namespace = 'http://jitsi.org/protocol/colibri'
|
|
|
|
plugin_attrib = 'graceful-shutdown'
|
|
|
|
|
|
class FocusShutdownUserBot(sleekxmpp.ClientXMPP):
|
|
|
|
def __init__(self, jid, password, focus):
|
|
sleekxmpp.ClientXMPP.__init__(self, jid, password)
|
|
|
|
self.focus = focus
|
|
|
|
self.add_event_handler(
|
|
"session_start", self.shutdown_focus, threaded=True)
|
|
|
|
register_stanza_plugin(Iq, GracefulShutdown)
|
|
register_stanza_plugin(Iq, ColibriStats)
|
|
|
|
def create_request_stats_iq(self):
|
|
statsIq = self.Iq()
|
|
statsIq['to'] = self.focus
|
|
statsIq['type'] = 'get'
|
|
statsIq.set_payload(ColibriStats())
|
|
return statsIq
|
|
|
|
def shutdown_focus(self, event):
|
|
|
|
shutdown_accepted = False
|
|
|
|
iq = self.Iq()
|
|
iq['to'] = self.focus
|
|
iq['type'] = 'set'
|
|
iq.set_payload(GracefulShutdown())
|
|
|
|
try:
|
|
resp = iq.send()
|
|
if resp['type'] == 'result':
|
|
logging.info('Shutdown accepted')
|
|
shutdown_accepted = True
|
|
while True:
|
|
stats_iq = self.create_request_stats_iq()
|
|
resp = stats_iq.send()
|
|
stats = resp['colibri-stats']
|
|
conf_count = get_conferences(stats)
|
|
logging.info(
|
|
'There are ' + str(conf_count) + ' conferences in '
|
|
'progress')
|
|
if conf_count == '0':
|
|
break
|
|
else:
|
|
time.sleep(10)
|
|
logging.info('End of shutdown procedure')
|
|
# The wait=True delays the disconnect until the queue
|
|
# of stanzas to be sent becomes empty.
|
|
self.disconnect(wait=True)
|
|
except StanzaError as error:
|
|
if not shutdown_accepted and\
|
|
error.etype != 'wait' and\
|
|
error.condition != 'service-unavailable':
|
|
global exitCode
|
|
exitCode = 1
|
|
logging.error('There was an error sending shutdown request.')
|
|
self.disconnect(wait=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Setup the command line arguments.
|
|
optp = OptionParser()
|
|
|
|
# Output verbosity options.
|
|
optp.add_option('-q', '--quiet', help='set logging to ERROR',
|
|
action='store_const', dest='loglevel',
|
|
const=logging.ERROR, default=logging.INFO)
|
|
optp.add_option('-d', '--debug', help='set logging to DEBUG',
|
|
action='store_const', dest='loglevel',
|
|
const=logging.DEBUG, default=logging.INFO)
|
|
optp.add_option('-v', '--verbose', help='set logging to COMM',
|
|
action='store_const', dest='loglevel',
|
|
const=5, default=logging.INFO)
|
|
# JID and password options.
|
|
optp.add_option("-s", "--server", dest="server",
|
|
help="JID to use")
|
|
optp.add_option("-j", "--jid", dest="jid",
|
|
help="JID to use")
|
|
optp.add_option("-p", "--password", dest="password",
|
|
help="password to use")
|
|
optp.add_option("-f", "--focus", dest="focus",
|
|
help="JID of the focus component")
|
|
opts, args = optp.parse_args()
|
|
|
|
# Setup logging.
|
|
logging.basicConfig(level=opts.loglevel,
|
|
format='%(levelname)-8s %(message)s')
|
|
if opts.server is None:
|
|
sys.stderr.write("No XMPP server name specified")
|
|
exit(1)
|
|
if opts.jid is None:
|
|
sys.stderr.write("No user JID specified")
|
|
exit(1)
|
|
if opts.password is None:
|
|
sys.stderr.write("No user password specified")
|
|
exit(1)
|
|
if opts.focus is None:
|
|
sys.stderr.write("No focus JID specified")
|
|
exit(1)
|
|
|
|
xmpp = FocusShutdownUserBot(opts.jid, opts.password, opts.focus)
|
|
|
|
if xmpp.connect(address=(opts.server, 5222)):
|
|
xmpp.process(block=True)
|
|
logging.info("Done")
|
|
else:
|
|
logging.error("Unable to connect.")
|
|
|
|
exit(exitCode)
|