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

browser-nuevodecorare-oglive-methodsexec-ogbrowserfix-urlfixes-winlgromero-filebeatlog-sess-lenmainmodulesnew-browserno-ptt-paramno-tlsogadmcliogadmclient-statusogagent-jobsogagent-macosogagentuser-sigtermogcore1oggitoggit-notlsogliveoglogoglog2override-moduleping1ping2ping3ping4py3-winpython3qndtestreport-progresssched-tasktlstls-againunification2unification3versionswindows-fixes
Last change on this file since cac2e5f was 44e1e4c, checked in by ramon <ramongomez@…>, 9 years ago

#718: Mejoras en operaciones REST de OGAgent:

  • Envíar datos de SO en operaciones de activación y desactivación.
  • Operaciones de modificación deben recibir la clave secreta generada en la activación.
  • Más comentarios en el código.

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

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