#750: Using PEP 8 Style Guide for Python in new module; implementing basic {{{getconfig}}} operation.

remotes/github/oglive^2^2^2
Ramón M. Gómez 2018-06-18 20:47:35 +02:00
parent e20838c641
commit 0a085de592
5 changed files with 155 additions and 160 deletions

View File

@ -0,0 +1,7 @@
#!/bin/bash
cd $(dirname "$0")
# Build package
dpkg-buildpackage -b -d

View File

@ -1,11 +0,0 @@
#!/bin/bash
cd $(dirname "$0")
top=`pwd`
[ -r ../src/VERSION ] && VERSION="$(cat ../src/VERSION)" || VERSION="1.1.0"
RELEASE="1"
# Debian based
dpkg-buildpackage -b -d

View File

@ -25,29 +25,27 @@
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
''' """
@author: Ramón M. Gómez, ramongomez at us dot es @author: Ramón M. Gómez, ramongomez at us dot es
''' """
from __future__ import unicode_literals from __future__ import unicode_literals
import subprocess
import threading
import thread
import os import os
import platform
import time
import random import random
import string import string
import threading
import time
import urllib import urllib
from opengnsys.workers import ServerWorker from opengnsys import REST
from opengnsys import REST, RESTError
from opengnsys import operations from opengnsys import operations
from opengnsys.log import logger from opengnsys.log import logger
from opengnsys.scriptThread import ScriptExecutorThread from opengnsys.scriptThread import ScriptExecutorThread
from opengnsys.workers import ServerWorker
# Error handler decorator. # Error handler decorator.
def catchBackgroundError(fnc): def catch_background_error(fnc):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
this = args[0] this = args[0]
try: try:
@ -56,18 +54,45 @@ def catchBackgroundError(fnc):
this.REST.sendMessage('error?id={}'.format(kwargs.get('requestId', 'error')), {'error': '{}'.format(e)}) this.REST.sendMessage('error?id={}'.format(kwargs.get('requestId', 'error')), {'error': '{}'.format(e)})
return wrapper return wrapper
def check_locked_partition(sync=False):
"""
Decorator to check if a partition is locked
"""
def outer(fnc):
def wrapper(*args, **kwargs):
part_id = 'None'
try:
this, path, get_params, post_params = args # @UnusedVariable
part_id = post_params['disk'] + post_params['part']
if this.locked.get(part_id, False):
this.locked[part_id] = True
fnc(*args, **kwargs)
else:
return 'partition locked'
except Exception as e:
this.locked[part_id] = False
return 'error {}'.format(e)
finally:
if sync is True:
this.locked[part_id] = False
logger.debug('Lock status: {} {}'.format(fnc, this.locked))
return wrapper
return outer
class OpenGnSysWorker(ServerWorker): class OpenGnSysWorker(ServerWorker):
name = 'opengnsys' name = 'opengnsys'
interface = None # Binded interface for OpenGnsys interface = None # Binded interface for OpenGnsys
loggedin = False # User session flag loggedin = False # User session flag
locked = {} locked = {} # Locked partitions
random = None # Random string for secure connections random = None # Random string for secure connections
length = 32 # Random string length length = 32 # Random string length
def checkSecret(self, server): def checkSecret(self, server):
''' """
Checks for received secret key and raise exception if it isn't valid. Checks for received secret key and raise exception if it isn't valid.
''' """
try: try:
if self.random != server.headers['Authorization']: if self.random != server.headers['Authorization']:
raise Exception('Unauthorized operation') raise Exception('Unauthorized operation')
@ -76,9 +101,9 @@ class OpenGnSysWorker(ServerWorker):
raise Exception(e) raise Exception(e)
def onActivation(self): def onActivation(self):
''' """
Sends OGAgent activation notification to OpenGnsys server Sends OGAgent activation notification to OpenGnsys server
''' """
self.cmd = None self.cmd = None
# Ensure cfg has required configuration variables or an exception will be thrown # Ensure cfg has required configuration variables or an exception will be thrown
self.REST = REST(self.service.config.get('opengnsys', 'remote')) self.REST = REST(self.service.config.get('opengnsys', 'remote'))
@ -107,52 +132,59 @@ class OpenGnSysWorker(ServerWorker):
# Generate random secret to send on activation # Generate random secret to send on activation
self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length)) self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length))
# Send initalization message # Send initalization message
self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip, 'secret': self.random, 'ostype': operations.osType, 'osversion': operations.osVersion}) self.REST.sendMessage('ogagent/started', {'mac': self.interface.mac, 'ip': self.interface.ip,
'secret': self.random, 'ostype': operations.os_type,
'osversion': operations.os_version})
def onDeactivation(self): def onDeactivation(self):
''' """
Sends OGAgent stopping notification to OpenGnsys server Sends OGAgent stopping notification to OpenGnsys server
''' """
logger.debug('onDeactivation') logger.debug('onDeactivation')
self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip, 'ostype': operations.osType, 'osversion': operations.osVersion}) self.REST.sendMessage('ogagent/stopped', {'mac': self.interface.mac, 'ip': self.interface.ip,
'ostype': operations.os_type, 'osversion': operations.os_version})
def processClientMessage(self, message, data): def processClientMessage(self, message, data):
logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data)) logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data))
def onLogin(self, userData): def onLogin(self, userData):
''' """
Sends session login notification to OpenGnsys server Sends session login notification to OpenGnsys server
''' """
user, sep, language = userData.partition(',') user, sep, language = userData.partition(',')
logger.debug('Received login for {} with language {}'.format(user, language)) logger.debug('Received login for {} with language {}'.format(user, language))
self.loggedin = True self.loggedin = True
self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'language': language, 'ostype': operations.osType, 'osversion': operations.osVersion}) self.REST.sendMessage('ogagent/loggedin', {'ip': self.interface.ip, 'user': user, 'language': language,
'ostype': operations.os_type, 'osversion': operations.os_version})
def onLogout(self, user): def onLogout(self, user):
''' """
Sends session logout notification to OpenGnsys server Sends session logout notification to OpenGnsys server
''' """
logger.debug('Received logout for {}'.format(user)) logger.debug('Received logout for {}'.format(user))
self.loggedin = False self.loggedin = False
self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user}) self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user})
def process_ogclient(self, path, getParams, postParams, server): def process_ogclient(self, path, getParams, postParams, server):
''' """
This method can be overriden to provide your own message proccessor, or better you can his method can be overriden to provide your own message proccessor, or better you can implement a
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 method that is called exactly as "process_" + path[0] (module name has been removed from patharray) and
this default processMessage will invoke it
* Example: * Example:
Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z
The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this: The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this:
module.processMessage(["mazinger","Z"], getParams, postParams) module.processMessage(["mazinger","Z"], getParams, postParams)
This method will process "mazinger", and look for a "self" method that is called "process_mazinger", and invoke it this way: This method will process "mazinger", and look for a "self" method that is called "process_mazinger",
and invoke it this way:
return self.process_mazinger(["Z"], getParams, postParams) return self.process_mazinger(["Z"], getParams, postParams)
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 In the case path is empty (that is, the path is composed only by the module name, like in
will be invoked directly "http://example.com/Sample", the "process" method will be invoked directly
The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json, basic type are) The methods must return data that can be serialized to json (i.e. Ojects are not serializable to json,
''' basic type are)
"""
if not path: if not path:
return "ok" return "ok"
try: try:
@ -162,34 +194,27 @@ class OpenGnSysWorker(ServerWorker):
return operation(path[1:], getParams, postParams) return operation(path[1:], getParams, postParams)
def process_status(self, path, getParams, postParams, server): def process_status(self, path, getParams, postParams, server):
''' """
Returns client status. Returns client status.
''' """
res = {'status': '', 'loggedin': self.loggedin} st = {'linux': 'LNX', 'macos': 'OSX', 'oglive': 'OPG', 'windows': 'WIN'}
if platform.system() == 'Linux': # GNU/Linux res = {'loggedin': self.loggedin}
# Check if it's OpenGnsys Client. try:
if os.path.exists('/scripts/oginit'): res['status'] = st[operations.os_type.lower()]
# Check if OpenGnsys Client is busy. except KeyError:
if self.locked: res['status'] = ''
# Check if OpenGnsys Client is busy
if res['status'] == 'OPG' and self.locked:
res['status'] = 'BSY' res['status'] = 'BSY'
else:
res['status'] = 'OPG'
else:
# Check if there is an active session.
res['status'] = 'LNX'
elif platform.system() == 'Windows': # Windows
# Check if there is an active session.
res['status'] = 'WIN'
elif platform.system() == 'Darwin': # Mac OS X ??
res['status'] = 'OSX'
return res return res
def process_reboot(self, path, getParams, postParams, server): def process_reboot(self, path, getParams, postParams, server):
''' """
Launches a system reboot operation. Launches a system reboot operation.
''' """
logger.debug('Received reboot operation') logger.debug('Received reboot operation')
self.checkSecret(server) self.checkSecret(server)
# Rebooting thread. # Rebooting thread.
def rebt(): def rebt():
operations.reboot() operations.reboot()
@ -197,11 +222,12 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'} return {'op': 'launched'}
def process_poweroff(self, path, getParams, postParams, server): def process_poweroff(self, path, getParams, postParams, server):
''' """
Launches a system power off operation. Launches a system power off operation.
''' """
logger.debug('Received poweroff operation') logger.debug('Received poweroff operation')
self.checkSecret(server) self.checkSecret(server)
# Powering off thread. # Powering off thread.
def pwoff(): def pwoff():
time.sleep(2) time.sleep(2)
@ -210,9 +236,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'} return {'op': 'launched'}
def process_script(self, path, getParams, postParams, server): def process_script(self, path, getParams, postParams, server):
''' """
Processes an script execution (script should be encoded in base64) Processes an script execution (script should be encoded in base64)
''' """
logger.debug('Processing script request') logger.debug('Processing script request')
self.checkSecret(server) self.checkSecret(server)
# Decoding script. # Decoding script.
@ -227,9 +253,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'} return {'op': 'launched'}
def process_logoff(self, path, getParams, postParams, server): def process_logoff(self, path, getParams, postParams, server):
''' """
Closes user session. Closes user session.
''' """
logger.debug('Received logoff operation') logger.debug('Received logoff operation')
self.checkSecret(server) self.checkSecret(server)
# Sending log off message to OGAgent client. # Sending log off message to OGAgent client.
@ -237,9 +263,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'sended to client'} return {'op': 'sended to client'}
def process_popup(self, path, getParams, postParams, server): def process_popup(self, path, getParams, postParams, server):
''' """
Shows a message popup on the user's session. Shows a message popup on the user's session.
''' """
logger.debug('Received message operation') logger.debug('Received message operation')
self.checkSecret(server) self.checkSecret(server)
# Sending popup message to OGAgent client. # Sending popup message to OGAgent client.
@ -248,3 +274,17 @@ class OpenGnSysWorker(ServerWorker):
def process_client_popup(self, params): def process_client_popup(self, params):
self.REST.sendMessage('popup_done', params) self.REST.sendMessage('popup_done', params)
def process_getconfig(self, path, get_params, post_params, server):
"""
Returns client configuration
:param path:
:param get_params:
:param post_params:
:param server:
:return: object
"""
logger.debug('Recieved getconfig operation')
self.checkSecret(server)
# Returns raw data
return {'config': operations.get_disk_config()}

View File

@ -26,17 +26,14 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
''' """
@author: Ramón M. Gómez, ramongomez at us dot es @author: Ramón M. Gómez, ramongomez at us dot es
''' """
from __future__ import unicode_literals from __future__ import unicode_literals
import socket import socket
import platform import platform
import fcntl import fcntl
import os
import ctypes # @UnusedImport
import ctypes.util
import subprocess import subprocess
import struct import struct
import array import array
@ -44,37 +41,11 @@ import six
from opengnsys import utils from opengnsys import utils
def checkLockedPartition(sync=False):
'''
Decorator to check if a partition is locked
'''
def outer(fnc):
def wrapper(*args, **kwargs):
partId = 'None'
try:
this, path, getParams, postParams = args # @UnusedVariable
partId = postParams['disk'] + postParams['part']
if this.locked.get(partId, False):
this.locked[partId] = True
fnc(*args, **kwargs)
else:
return 'partition locked'
except Exception as e:
this.locked[partId] = False
return 'error {}'.format(e)
finally:
if sync is True:
this.locked[partId] = False
logger.debug('Lock status: {} {}'.format(fnc, this.locked))
return wrapper
return outer
def _getMacAddr(ifname): def _getMacAddr(ifname):
''' """
Returns the mac address of an interface Returns the mac address of an interface
Mac is returned as unicode utf-8 encoded Mac is returned as unicode utf-8 encoded
''' """
if isinstance(ifname, list): if isinstance(ifname, list):
return dict([(name, _getMacAddr(name)) for name in ifname]) return dict([(name, _getMacAddr(name)) for name in ifname])
if isinstance(ifname, six.text_type): if isinstance(ifname, six.text_type):
@ -88,10 +59,10 @@ def _getMacAddr(ifname):
def _getIpAddr(ifname): def _getIpAddr(ifname):
''' """
Returns the ip address of an interface Returns the ip address of an interface
Ip is returned as unicode utf-8 encoded Ip is returned as unicode utf-8 encoded
''' """
if isinstance(ifname, list): if isinstance(ifname, list):
return dict([(name, _getIpAddr(name)) for name in ifname]) return dict([(name, _getIpAddr(name)) for name in ifname])
if isinstance(ifname, six.text_type): if isinstance(ifname, six.text_type):
@ -108,9 +79,9 @@ def _getIpAddr(ifname):
def _getInterfaces(): def _getInterfaces():
''' """
Returns a list of interfaces names coded in utf-8 Returns a list of interfaces names coded in utf-8
''' """
max_possible = 128 # arbitrary. raise if needed. max_possible = 128 # arbitrary. raise if needed.
space = max_possible * 16 space = max_possible * 16
if platform.architecture()[0] == '32bit': if platform.architecture()[0] == '32bit':
@ -134,32 +105,32 @@ def _getInterfaces():
def _getIpAndMac(ifname): def _getIpAndMac(ifname):
ip, mac = _getIpAddr(ifname), _getMacAddr(ifname) ip, mac = _getIpAddr(ifname), _getMacAddr(ifname)
return (ip, mac) return ip, mac
def _exec_ogcommand(self, ogcmd): def _exec_ogcommand(ogcmd):
''' """
Loads OpenGnsys environment variables, executes the command and returns the result Loads OpenGnsys environment variables, executes the command and returns the result
''' """
ret = subprocess.check_output('source /opt/opengnsys/etc/preinit/loadenviron.sh >/dev/null; {}'.format(ogcmd), shell=True) ret = subprocess.check_output(ogcmd, shell=True)
return ret return ret
def getComputerName(): def getComputerName():
''' """
Returns computer name, with no domain Returns computer name, with no domain
''' """
return socket.gethostname().split('.')[0] return socket.gethostname().split('.')[0]
def getNetworkInfo(): def getNetworkInfo():
''' """
Obtains a list of network interfaces Obtains a list of network interfaces
@return: A "generator" of elements, that are dict-as-object, with this elements: :return: A "generator" of elements, that are dict-as-object, with this elements:
name: Name of the interface name: Name of the interface
mac: mac of the interface mac: mac of the interface
ip: ip of the interface ip: ip of the interface
''' """
for ifname in _getInterfaces(): for ifname in _getInterfaces():
ip, mac = _getIpAndMac(ifname) ip, mac = _getIpAndMac(ifname)
if mac != '00:00:00:00:00:00': # Skips local interfaces if mac != '00:00:00:00:00:00': # Skips local interfaces
@ -170,56 +141,44 @@ def getDomainName():
return '' return ''
def getOgliveVersion(): def get_oglive_version():
lv = platform.linux_distribution() """
return lv[0] + ', ' + lv[1] Returns ogLive Kernel version and architecture
:return: kernel version
"""
kv = platform.os.uname()
return kv[2] + ', ' + kv[4]
def reboot(): def reboot():
''' """
Simple reboot using OpenGnsys script Simple reboot using OpenGnsys script
''' """
# Workaround for dummy thread # Workaround for dummy thread
if six.PY3 is False: if six.PY3 is False:
import threading import threading
threading._DummyThread._Thread__stop = lambda x: 42 threading._DummyThread._Thread__stop = lambda x: 42
_exec_ogcommand('/opt/opengnsys/scripts/reboot', shell=True) _exec_ogcommand('/opt/opengnsys/scripts/reboot')
def poweroff(): def poweroff():
''' """
Simple poweroff using OpenGnsys script Simple poweroff using OpenGnsys script
''' """
# Workaround for dummy thread # Workaround for dummy thread
if six.PY3 is False: if six.PY3 is False:
import threading import threading
threading._DummyThread._Thread__stop = lambda x: 42 threading._DummyThread._Thread__stop = lambda x: 42
_exec_ogcommand('/opt/opengnsys/scripts/poweroff', shell=True) _exec_ogcommand('/opt/opengnsys/scripts/poweroff')
def logoff(): def get_disk_config():
pass """
Returns disk configuration
Warning: this operation may take some time
def renameComputer(newName): """
pass
def joinDomain(domain, ou, account, password, executeInOneStep=False):
pass
def changeUserPassword(user, oldPassword, newPassword):
pass
def diskconfig():
'''
Returns disk configuration.
Warning: this operation may take some time.
'''
try: try:
_exec_ogcommand('/opt/opengnsys/interfaceAdm/getConfiguration') _exec_ogcommand('/opt/opengnsys/interfaceAdm/getConfiguration')
# Returns content of configuration file. # Returns content of configuration file.

View File

@ -26,9 +26,9 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
''' """
@author: Adolfo Gómez, dkmaster at dkmon dot com @author: Ramón M. Gómez, ramongomez at us dot es
''' """
# pylint: disable=unused-wildcard-import,wildcard-import # pylint: disable=unused-wildcard-import,wildcard-import
from __future__ import unicode_literals from __future__ import unicode_literals
@ -39,19 +39,19 @@ import os
# Importing platform operations and getting operating system data. # Importing platform operations and getting operating system data.
if sys.platform == 'win32': if sys.platform == 'win32':
from .windows.operations import * # @UnusedWildImport from .windows.operations import * # @UnusedWildImport
osType = 'Windows' os_type = 'Windows'
osVersion = getWindowsVersion() os_version = getWindowsVersion()
else: else:
if sys.platform == 'darwin': if sys.platform == 'darwin':
from .macos.operations import * # @UnusedWildImport from .macos.operations import * # @UnusedWildImport
osType = 'MacOS' os_type = 'MacOS'
osVersion = getMacosVersion().replace(',','') os_version = getMacosVersion().replace(',', '')
else: else:
if os.path.exists('/scripts/oginit'): if os.path.exists('/scripts/oginit'):
from .oglive.operations import * # @UnusedWildImport from .oglive.operations import * # @UnusedWildImport
osType = 'ogLive' os_type = 'ogLive'
osVersion = getOgliveVersion().replace(',','') os_version = get_oglive_version()
else: else:
from .linux.operations import * # @UnusedWildImport from .linux.operations import * # @UnusedWildImport
osType = 'Linux' os_type = 'Linux'
osVersion = getLinuxVersion().replace(',','') os_version = getLinuxVersion().replace(',', '')