source: ogAgent-Git/src/opengnsys/modules/server/OpenGnSys/__init__.py @ e21cba1

decorare-oglive-methodsfix-urlfixes-winlgromero-filebeatmainmodulesnew-browserno-ptt-paramogadmcliogadmclient-statusogagent-jobsogagent-macosogcore1ogliveoglogoglog2override-moduleping1ping2ping3ping4py3-winpython3qndtestreport-progresssched-tasktlsunification2unification3versionswindows-fixes
Last change on this file since e21cba1 was 02399e9, checked in by ramon <ramongomez@…>, 8 years ago

#718: Volver a poner nivel de log por defecto a DEBUG para OGAgent.

git-svn-id: https://opengnsys.es/svn/branches/version1.1@5244 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 10.1 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: Ramón M. Gómez, ramongomez at us dot es
30'''
31from __future__ import unicode_literals
32
33from opengnsys.workers import ServerWorker
34
35from opengnsys import REST, RESTError
36from opengnsys import operations
37from opengnsys.log import logger
38from opengnsys.scriptThread import ScriptExecutorThread
39
40import subprocess
41import threading
42import thread
43import os
44import platform
45import time
46import random
47import string
48import urllib
49
50# Error handler decorator.
51def catchBackgroundError(fnc):
52    def wrapper(*args, **kwargs):
53        this = args[0]
54        try:
55            fnc(*args, **kwargs)
56        except Exception as e:
57            this.REST.sendMessage('error?id={}'.format(kwargs.get('requestId', 'error')), {'error': '{}'.format(e)})
58    return wrapper
59
60class OpenGnSysWorker(ServerWorker):
61    name = 'opengnsys'
62    interface = None  # Binded interface for OpenGnsys
63    loggedin = False  # User session flag
64    locked = {}
65    random = None     # Random string for secure connections
66    length = 32       # Random string length
67   
68    def checkSecret(self, server):
69        '''
70        Checks for received secret key and raise exception if it isn't valid.
71        '''
72        try:
73            if self.random != server.headers['Authorization']:
74                raise Exception('Unauthorized operation')
75        except Exception as e:
76            logger.error(e)
77            raise Exception(e)
78
79    def onActivation(self):
80        '''
81        Sends OGAgent activation notification to OpenGnsys server
82        '''
83        self.cmd = None
84        # Ensure cfg has required configuration variables or an exception will be thrown
85        self.REST = REST(self.service.config.get('opengnsys', 'remote'))
86        # Get network interfaces until they are active or timeout (30 sec)
87        for t in range(0,30):
88            try:
89                self.interface = list(operations.getNetworkInfo())[0]  # Get first network interface
90            except Exception as e:
91                # Wait 1 sec. and retry
92                time.sleep(1)
93            finally:
94                # Exit loop if interface is active
95                if self.interface:
96                    if t > 0:
97                        logger.debug("Fetch connection data after {} tries".format(t))
98                    break
99        # Raise error after timeout
100        if not self.interface:
101            raise e
102        # Generate random secret to send on activation
103        self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length))
104        # Send initalization message
105        self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip, 'secret': self.random, 'ostype': operations.osType, 'osversion': operations.osVersion})
106       
107    def onDeactivation(self):
108        '''
109        Sends OGAgent stopping notification to OpenGnsys server
110        '''
111        logger.debug('onDeactivation')
112        self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip, 'ostype': operations.osType, 'osversion': operations.osVersion})
113   
114    def processClientMessage(self, message, data):
115        logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data))
116   
117    def onLogin(self, user):
118        '''
119        Sends session login notification to OpenGnsys server
120        '''
121        logger.debug('Received login for {}'.format(user))
122        self.loggedin = True
123        self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'ostype': operations.osType, 'osversion': operations.osVersion})       
124
125    def onLogout(self, user):
126        '''
127        Sends session logout notification to OpenGnsys server
128        '''
129        logger.debug('Received logout for {}'.format(user))
130        self.loggedin = False
131        self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user})
132
133    def process_ogclient(self, path, getParams, postParams, server):
134        '''
135        This method can be overriden to provide your own message proccessor, or better you can
136        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
137        * Example:
138            Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z
139            The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this:
140            module.processMessage(["mazinger","Z"], getParams, postParams)
141           
142            This method will process "mazinger", and look for a "self" method that is called "process_mazinger", and invoke it this way:
143               return self.process_mazinger(["Z"], getParams, postParams)
144               
145            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
146            will be invoked directly
147           
148            The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are)
149        '''
150        if len(path) == 0:
151            return "ok"
152        try:
153            operation = getattr(self, 'ogclient_' + path[0])
154        except Exception:
155            raise Exception('Message processor for "{}" not found'.format(path[0]))
156       
157        return operation(path[1:], getParams, postParams)
158       
159    def process_status(self, path, getParams, postParams, server):
160        '''
161        Returns client status.
162        '''
163        res = { 'status': '', 'loggedin': self.loggedin }
164        if platform.system() == 'Linux':        # GNU/Linux
165            # Check if it's OpenGnsys Client.
166            if os.path.exists('/scripts/oginit'):
167                # Check if OpenGnsys Client is busy.
168                if self.locked:
169                    res['status'] = 'BSY'
170                else:
171                    res['status'] = 'OPG'
172            else:
173                # Check if there is an active session.
174                res['status'] = 'LNX'
175        elif platform.system() == 'Windows':    # Windows
176            # Check if there is an active session.
177            res['status'] = 'WIN'
178        elif platform.system() == 'Darwin':     # Mac OS X  ??
179            res['status'] = 'OSX'
180        return res
181   
182    def process_reboot(self, path, getParams, postParams, server):
183        '''
184        Launches a system reboot operation.
185        '''
186        logger.debug('Received reboot operation')
187        self.checkSecret(server)
188        # Rebooting thread.
189        def rebt():
190            operations.reboot()
191        threading.Thread(target=rebt).start()
192        return {'op': 'launched'}
193
194    def process_poweroff(self, path, getParams, postParams, server):
195        '''
196        Launches a system power off operation.
197        '''
198        logger.debug('Received poweroff operation')
199        self.checkSecret(server)
200        # Powering off thread.
201        def pwoff():
202            time.sleep(2)
203            operations.poweroff()
204        threading.Thread(target=pwoff).start()
205        return {'op': 'launched'}
206
207    def process_script(self, path, getParams, postParams, server):
208        '''
209        Processes an script execution (script should be encoded in base64)
210        '''
211        logger.debug('Processing script request')
212        self.checkSecret(server)
213        # Decoding script.
214        script = urllib.unquote(postParams.get('script').decode('base64')).decode('utf8')
215        script = 'import subprocess; subprocess.check_output("""{}""",shell=True)'.format(script)
216        # Executing script.
217        if postParams.get('client', 'false') == 'false':
218            thr = ScriptExecutorThread(script)
219            thr.start()
220        else:
221            self.sendClientMessage('script', {'code': script})
222        return {'op': 'launched'}
223   
224    def process_logoff(self, path, getParams, postParams, server):
225        '''
226        Closes user session.
227        '''
228        logger.debug('Received logoff operation')
229        self.checkSecret(server)
230        # Sending log off message to OGAgent client.
231        self.sendClientMessage('logoff', {})
232        return {'op': 'sended to client'}
233
234    def process_popup(self, path, getParams, postParams, server):
235        '''
236        Shows a message popup on the user's session.
237        '''
238        logger.debug('Received message operation')
239        self.checkSecret(server)
240        # Sending popup message to OGAgent client.
241        self.sendClientMessage('popup', postParams)
242        return {'op': 'launched'}
243
244    def process_client_popup(tself, params):
245        self.REST.sendMessage('popup_done', params)
246   
Note: See TracBrowser for help on using the repository browser.