Search code examples
pythonpython-2.7twistedautobahn

Check server status on Twisted


While I was writing simple message-based fileserver and client, I got the idea about checking fileserver status, but don't know how to realize this: just try to connect and disconnect from server (and how disconnect immediately, when server is not running, if using this way?) or maybe twisted/autobahn have some things, which help to get server status without creating "full connection"?

a) fileserver.py

import os
import sys
import json

from twisted.internet import reactor
from autobahn.twisted.websocket import WebSocketServerFactory, WebSocketServerProtocol, listenWS

CONFIG_TEMPLATE = ''
CONFIG_DATA = {}

class MessageBasedServerProtocol(WebSocketServerProtocol):
    """
Message-based WebSockets server
Template contains some parts as string:
[USER_ID:OPERATION_NAME:FILE_ID] - 15 symbols for USER_ID,
10 symbols for OPERATION_NAME,
25 symbols for FILE_ID
other - some data
"""
    def __init__(self):
        path = CONFIG_DATA['path']
        base_dir = CONFIG_DATA['base_dir']
        # prepare to working with files...
        if os.path.exists(path) and os.path.isdir(path):
            os.chdir(path)
            if not os.path.exists(base_dir) or not os.path.isdir(base_dir):
                os.mkdir(base_dir)
                os.chdir(base_dir)
        else:
            os.makedir(path)
            os.chdir(path)
            os.mkdir(base_dir)
            os.chdir(base_dir)
        # init some things
        self.fullpath = path + '/' + base_dir

    def __checkUserCatalog(self, user_id):
        # prepare to working with files...
        os.chdir(self.fullpath)
        if not os.path.exists(user_id) or not os.path.isdir(user_id):
            os.mkdir(user_id)
            os.chdir(user_id)
        else:
            os.chdir(self.fullpath + '/' + user_id)

    def onOpen(self):
        print "[USER] User with %s connected" % (self.transport.getPeer())

    def connectionLost(self, reason):
        print '[USER] Lost connection from %s' % (self.transport.getPeer())

    def onMessage(self, payload, isBinary):
        """
Processing request from user and send response
"""
        user_id, cmd, file_id = payload[:54].replace('[', '').replace(']','').split(':')
        data = payload[54:]
        operation = "UNK" # WRT - Write, REA -> Read, DEL -> Delete, UNK -> Unknown
        status = "C" # C -> Complete, E -> Error in operation
        commentary = 'Succesfull!'
        # write file into user storage
        if cmd == 'WRITE_FILE':
            self.__checkUserCatalog(user_id)
            operation = "WRT"
            try:
                f = open(file_id, "wb")
                f.write(data)
            except IOError, argument:
                status = "E"
                commentary = argument
            except Exception, argument:
                status = "E"
                commentary = argument
                raise Exception(argument)
            finally:
                f.close()
        # read some file
        elif cmd == 'READU_FILE':
            self.__checkUserCatalog(user_id)
            operation = "REA"
            try:
                f = open(file_id, "rb")
                commentary = f.read()
            except IOError, argument:
                status = "E"
                commentary = argument
            except Exception, argument:
                status = "E"
                commentary = argument
                raise Exception(argument)
            finally:
                f.close()
        # delete file from storage (and in main server, in parallel delete from DB)
        elif cmd == 'DELET_FILE':
            self.__checkUserCatalog(user_id)
            operation = "DEL"
            try:
                os.remove(file_id)
            except IOError, argument:
                status = "E"
                commentary = argument
            except Exception, argument:
                status = "E"
                commentary = argument
                raise Exception(argument)
        self.sendMessage('[%s][%s]%s' % (operation, status, commentary), isBinary=True)

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print "using python fileserver_client.py [PATH_TO_config.json_FILE]"
    else:
        # read config file
        CONFIG_TEMPLATE = sys.argv[1]
        with open(CONFIG_TEMPLATE, "r") as f:
            CONFIG_DATA = json.load(f)
        # create server
        factory = WebSocketServerFactory("ws://localhost:9000")
        factory.protocol = MessageBasedServerProtocol
        listenWS(factory)
        reactor.run()

b) client.py

import json
import sys
import commands

from twisted.internet import reactor
from autobahn.twisted.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS

CONFIG_TEMPLATE = ''
CONFIG_DATA = {}


class MessageBasedClientProtocol(WebSocketClientProtocol):
    """
Message-based WebSockets client
Template contains some parts as string:
[USER_ID:OPERATION_NAME:FILE_ID] - 15 symbols for USER_ID,
10 symbols for OPERATION_NAME,
25 symbols for FILE_ID
other - some data
"""
    def onOpen(self):
        user_id = CONFIG_DATA['user']
        operation_name = CONFIG_DATA['cmd']
        file_id = CONFIG_DATA['file_id']
        src_file = CONFIG_DATA['src_file']
        data = '[' + str(user_id) + ':' + str(operation_name) + ':' + str(file_id) + ']'
        if operation_name == 'WRITE_FILE':
            with open(src_file, "r") as f:
                info = f.read()
            data += str(info)
        self.sendMessage(data, isBinary=True)

    def onMessage(self, payload, isBinary):
        cmd = payload[1:4]
        result_cmd = payload[6]
        if cmd in ('WRT', 'DEL'):
            print payload
        elif cmd == 'REA':
            if result_cmd == 'C':
                try:
                    data = payload[8:]
                    f = open(CONFIG_DATA['src_file'], "wb")
                    f.write(data)
                except IOError, e:
                    print e
                except Exception, e:
                    raise Exception(e)
                finally:
                    print payload[:8] + "Successfully!"
                    f.close()
            else:
                print payload
        reactor.stop()


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print "using python fileserver_client.py [PATH_TO_config.json_FILE]"
    else:
        # read config file
        CONFIG_TEMPLATE = sys.argv[1]
        with open(CONFIG_TEMPLATE, "r") as f:
            CONFIG_DATA = json.load(f)
        # connection to server
        factory = WebSocketClientFactory("ws://localhost:9000")
        factory.protocol = MessageBasedClientProtocol
        connectWS(factory)
        reactor.run()

Solution

  • Find solution this issue: using callLater or deferLater for disconnect from server, if can't connect, but when all was 'OK', just take server status, which he says.

    import sys
    
    from twisted.internet.task import deferLater
    from twisted.internet import reactor
    from autobahn.twisted.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS
    
    CONFIG_IP = ''
    CONFIG_PORT = 9000
    
    
    def isOffline(status):
        print status
    
    
    class StatusCheckerProtocol(WebSocketClientProtocol):
    
        def __init__(self):
            self.operation_name = "STATUS_SRV"
            self.user_id = 'u00000000000000'
            self.file_id = "000000000000000000000.log"
    
        def onOpen(self):
            data = '[' + str(self.user_id) + ':' + str(self.operation_name) + ':' + str(self.file_id) + ']'
            self.sendMessage(data, isBinary=True)
    
        def onMessage(self, payload, isBinary):
            cmd = payload[1:4]
            result_cmd = payload[6]
            data = payload[8:]
            print data
            reactor.stop()
    
    
    if __name__ == '__main__':
        if len(sys.argv) < 3:
            print "using python statuschecker.py [IP] [PORT]"
        else:
            # read preferences
            CONFIG_IP = sys.argv[1]
            CONFIG_PORT = int(sys.argv[2])
            server_addr = "ws://%s:%d" % (CONFIG_IP, CONFIG_PORT)
            # connection to server
            factory = WebSocketClientFactory(server_addr)
            factory.protocol = StatusCheckerProtocol
            connectWS(factory)
            # create special Deffered, which disconnect us from some server, if can't connect within 3 seconds
            d = deferLater(reactor, 3, isOffline, 'OFFLINE')
            d.addCallback(lambda ignored: reactor.stop())
            # run all system...
            reactor.run()