diff --git a/library/notification/irc b/library/notification/irc index 1948d54c0db..11bdc4a95ec 100644 --- a/library/notification/irc +++ b/library/notification/irc @@ -61,10 +61,16 @@ options: description: - Server password required: false + timeout: + description: + - Timeout to use while waiting for successful registration and join + messages, this is to prevent an endless loop + default: 30 + version_added: 1.5 # informational: requirements for nodes requirements: [ socket ] -author: Jan-Piet Mens +author: Jan-Piet Mens, Matt Martz ''' EXAMPLES = ''' @@ -81,19 +87,22 @@ EXAMPLES = ''' # IRC module support methods. # -from time import sleep +import re import socket +from time import sleep + + def send_msg(channel, msg, server='localhost', port='6667', - nick="ansible", color='black', passwd=False): + nick="ansible", color='black', passwd=False, timeout=30): '''send message to IRC''' colornumbers = { - 'black' : "01", - 'red' : "04", - 'green' : "09", - 'yellow' : "08", - 'blue' : "12", + 'black': "01", + 'red': "04", + 'green': "09", + 'yellow': "08", + 'blue': "12", } try: @@ -103,18 +112,37 @@ def send_msg(channel, msg, server='localhost', port='6667', message = "\x03" + colornumber + msg - irc = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) - irc.connect( ( server, int(port) ) ) + irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + irc.connect((server, int(port))) if passwd: - irc.send( 'PASS %s\r\n' % passwd ) - irc.send( 'NICK %s\r\n' % nick ) - irc.send( 'USER %s %s %s :ansible IRC\r\n' % (nick, nick, nick)) - time.sleep(1) - irc.send( 'JOIN %s\r\n' % channel ) - irc.send( 'PRIVMSG %s :%s\r\n' % (channel, message)) + irc.send('PASS %s\r\n' % passwd) + irc.send('NICK %s\r\n' % nick) + irc.send('USER %s %s %s :ansible IRC\r\n' % (nick, nick, nick)) + motd = '' + start = time.time() + while 1: + motd += irc.recv(1024) + if re.search('^:\S+ 00[1-4] %s :' % nick, motd, flags=re.M): + break + elif time.time() - start > timeout: + raise Exception('Timeout waiting for IRC server welcome response') + time.sleep(0.5) + + irc.send('JOIN %s\r\n' % channel) + join = '' + start = time.time() + while 1: + join += irc.recv(1024) + if re.search('^:\S+ 366 %s %s :' % (nick, channel), join, flags=re.M): + break + elif time.time() - start > timeout: + raise Exception('Timeout waiting for IRC JOIN response') + time.sleep(0.5) + + irc.send('PRIVMSG %s :%s\r\n' % (channel, message)) time.sleep(1) - irc.send( 'PART %s\r\n' % channel) - irc.send( 'QUIT\r\n' ) + irc.send('PART %s\r\n' % channel) + irc.send('QUIT\r\n') time.sleep(1) irc.close() @@ -122,32 +150,34 @@ def send_msg(channel, msg, server='localhost', port='6667', # Main # -def main(): +def main(): module = AnsibleModule( argument_spec=dict( - server = dict(default='localhost'), - port = dict(default = 6667), - nick = dict(default = 'ansible'), - msg = dict(required = True), - color = dict(default="black", choices=["yellow", "red", "green", - "blue", "black"]), - channel = dict(required = True), - passwd = dict() + server=dict(default='localhost'), + port=dict(default=6667), + nick=dict(default='ansible'), + msg=dict(required=True), + color=dict(default="black", choices=["yellow", "red", "green", + "blue", "black"]), + channel=dict(required=True), + passwd=dict(), + timeout=dict(type='int', default=30) ), supports_check_mode=True ) - server = module.params["server"] - port = module.params["port"] - nick = module.params["nick"] - msg = module.params["msg"] - color = module.params["color"] + server = module.params["server"] + port = module.params["port"] + nick = module.params["nick"] + msg = module.params["msg"] + color = module.params["color"] channel = module.params["channel"] - passwd = module.params["passwd"] + passwd = module.params["passwd"] + timeout = module.params["timeout"] try: - send_msg(channel, msg, server, port, nick, color, passwd) + send_msg(channel, msg, server, port, nick, color, passwd, timeout) except Exception, e: module.fail_json(msg="unable to send to IRC: %s" % e)