source: ogAgent-Git/src/opengnsys/workers/server_worker.py @ 67d5e81

configure-ptt-chedecorare-oglive-methodsejecutarscript-b64fix-cfg2objfixes-winlgromero-filebeatmainmodulesnew-browserno-ptt-paramogadmcliogadmclient-statusogcore1oglogoglog2override-moduleping1ping2ping3ping4report-progresstlsunification2unification3
Last change on this file since 67d5e81 was 9525724, checked in by Ramón M. Gómez <ramongomez@…>, 5 years ago

#940: Convert some docstring as defined in PEP 257.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (c) 2014 Virtual Cable S.L.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without modification,
7# are permitted provided that the following conditions are met:
8#
9#    * Redistributions of source code must retain the above copyright notice,
10#      this list of conditions and the following disclaimer.
11#    * Redistributions in binary form must reproduce the above copyright notice,
12#      this list of conditions and the following disclaimer in the documentation
13#      and/or other materials provided with the distribution.
14#    * Neither the name of Virtual Cable S.L. nor the names of its contributors
15#      may be used to endorse or promote products derived from this software
16#      without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28"""
29@author: Adolfo Gómez, dkmaster at dkmon dot com
30"""
31# pylint: disable=unused-wildcard-import,wildcard-import
32
33
34class ServerWorker(object):
35    """
36    A ServerWorker is a server module that "works" for service
37    Most method are invoked inside their own thread, except onActivation & onDeactivation.
38    This two methods are invoked inside main service thread, take that into account when creating them
39
40    * You must provide a module name (override name on your class), so we can identify the module by a "valid" name.
41      A valid name is like a valid python variable (do not use spaces, etc...)
42    * The name of the module is used as REST message destination id:
43      https://sampleserver:8888/[name]/....
44      Remember that module names and REST path are case sensitive!!!
45
46    """
47    name = None
48    service = None
49    locked = False
50   
51    def __init__(self, service):
52        self.service = service
53       
54    def activate(self):
55        """
56        Convenient method to wrap onActivation, so we can include easyly custom common logic for activation in a future
57        """
58        self.onActivation()
59       
60    def deactivate(self):
61        """
62        Convenient method to wrap onActivation, so we can include easyly custom common logic for deactivation in a future
63        """
64        self.onDeactivation()
65       
66    def process(self, getParams, postParams, server):
67        """
68        This method is invoked on a message received with an empty path (that means a message with only the module name, like in "http://example.com/Sample"
69        Override it if you expect messages with that pattern
70
71        Overriden method must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are)
72        """
73        raise NotImplementedError('Generic message processor is not supported')
74       
75    def processServerMessage(self, path, getParams, postParams, server):
76        """
77        This method can be overriden to provide your own message proccessor, or better you can
78        implement a method that is called exactly as "process_" + path[0] (module name has been removed from path array) and this default processMessage will invoke it
79        * Example:
80            Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z
81            The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this:
82            module.processMessage(["mazinger","Z"], getParams, postParams)
83
84            This method will process "mazinguer", and look for a "self" method that is called "process_mazinger", and invoke it this way:
85               return self.process_mazinger(["Z"], getParams, postParams)
86
87            In the case path is empty (that is, the path is composed only by the module name, like in "http://example.com/Sample", the "process" method
88            will be invoked directly
89
90            The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are)
91        """
92        if self.locked is True:
93            raise Exception('system is busy')
94       
95        if len(path) == 0:
96            return self.process(getParams, postParams, server)
97        try:
98            operation = getattr(self, 'process_' + path[0])
99        except Exception:
100            raise Exception('Message processor for "{}" not found'.format(path[0]))
101       
102        return operation(path[1:], getParams, postParams, server)
103       
104       
105    def processClientMessage(self, message, data):
106        """
107        Invoked by Service when a client message is received (A message from user space Agent)
108
109        This method can be overriden to provide your own message proccessor, or better you can
110        implement a method that is called exactly "process_client_" + message (module name has been removed from path) and this default processMessage will invoke it
111        * Example:
112            We got a message from OGAgent "Mazinger", with json params
113            module.processClientMessage("mazinger", jsonParams)
114
115            This method will process "mazinguer", and look for a "self" method that is called "process_client_mazinger", and invoke it this way:
116               self.process_client_mazinger(jsonParams)
117
118            The methods returns nothing (client communications are done asynchronously)
119        """
120        try:
121            operation = getattr(self, 'process_client_' + message)
122        except Exception:
123            raise Exception('Message processor for "{}" not found'.format(message))
124       
125        operation(data)
126       
127        # raise NotImplementedError('Got a client message but no proccessor is implemented')
128       
129   
130    def onActivation(self):
131        """
132        Invoked by Service for activation.
133        This MUST be overridden by modules!
134        This method is invoked inside main thread, so if it "hangs", complete service will hang
135        This should be no problem, but be advised about this
136        """
137        pass
138   
139    def onDeactivation(self):
140        """
141        Invoked by Service before unloading service
142        This MUST be overridden by modules!
143        This method is invoked inside main thread, so if it "hangs", complete service will hang
144        This should be no problem, but be advised about this
145        """
146        pass
147   
148   
149    def onLogin(self, user):
150        """
151        Invoked by Service when an user login is detected
152        This CAN be overridden by modules
153        This method is invoked whenever the client (user space agent) notifies the server (Service) that a user has logged in.
154        This method is run on its own thread
155        """
156        pass
157   
158    def onLogout(self, user):
159        """
160        Invoked by Service when an user login is detected
161        This CAN be overridden by modules
162        This method is invoked whenever the client (user space agent) notifies the server (Service) that a user has logged in.
163        This method is run on its own thread
164        """
165        pass
166   
167    # *************************************
168    # * Helper, convenient helper methods *
169    # *************************************
170    def sendClientMessage(self, message, data):
171        """
172        Sends a message to connected ipc clients
173        By convenience, it uses the "current" moduel name as destination module name also.
174        If you need to send a message to a different module, you can use self.service.sendClientMessage(module, message, data) instead
175        og this helmer
176        """
177        self.service.sendClientMessage(self.name, message, data)
178       
179    def sendScriptMessage(self, script):
180        self.service.sendScriptMessage(script)
181   
182    def sendLogoffMessage(self):
183        self.service.sendLogoffMessage()
184   
185    def sendPopupMessage(self):
186        self.service.sendPopupMessage()
Note: See TracBrowser for help on using the repository browser.