#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,
# 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.
'''
"""
@author: Ramón M. Gómez, ramongomez at us dot es
'''
"""
from __future__ import unicode_literals
import subprocess
import threading
import thread
import os
import platform
import time
import random
import string
import threading
import time
import urllib
from opengnsys.workers import ServerWorker
from opengnsys import REST, RESTError
from opengnsys import REST
from opengnsys import operations
from opengnsys.log import logger
from opengnsys.scriptThread import ScriptExecutorThread
from opengnsys.workers import ServerWorker
# Error handler decorator.
def catchBackgroundError(fnc):
def catch_background_error(fnc):
def wrapper(*args, **kwargs):
this = args[0]
try:
@ -56,18 +54,45 @@ def catchBackgroundError(fnc):
this.REST.sendMessage('error?id={}'.format(kwargs.get('requestId', 'error')), {'error': '{}'.format(e)})
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):
name = 'opengnsys'
interface = None # Binded interface for OpenGnsys
loggedin = False # User session flag
locked = {}
locked = {} # Locked partitions
random = None # Random string for secure connections
length = 32 # Random string length
def checkSecret(self, server):
'''
"""
Checks for received secret key and raise exception if it isn't valid.
'''
"""
try:
if self.random != server.headers['Authorization']:
raise Exception('Unauthorized operation')
@ -76,9 +101,9 @@ class OpenGnSysWorker(ServerWorker):
raise Exception(e)
def onActivation(self):
'''
"""
Sends OGAgent activation notification to OpenGnsys server
'''
"""
self.cmd = None
# Ensure cfg has required configuration variables or an exception will be thrown
self.REST = REST(self.service.config.get('opengnsys', 'remote'))
@ -107,52 +132,59 @@ class OpenGnSysWorker(ServerWorker):
# Generate random secret to send on activation
self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length))
# 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):
'''
"""
Sends OGAgent stopping notification to OpenGnsys server
'''
"""
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):
logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data))
def onLogin(self, userData):
'''
"""
Sends session login notification to OpenGnsys server
'''
"""
user, sep, language = userData.partition(',')
logger.debug('Received login for {} with language {}'.format(user, language))
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):
'''
"""
Sends session logout notification to OpenGnsys server
'''
"""
logger.debug('Received logout for {}'.format(user))
self.loggedin = False
self.REST.sendMessage('ogagent/loggedout', {'ip': self.interface.ip, 'user': user})
def process_ogclient(self, path, getParams, postParams, server):
'''
This method can be overriden to provide your own message proccessor, or better you can
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
"""
his method can be overriden to provide your own message proccessor, or better you can implement a
method that is called exactly as "process_" + path[0] (module name has been removed from patharray) and
this default processMessage will invoke it
* Example:
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:
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)
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
will be invoked directly
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 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:
return "ok"
try:
@ -162,34 +194,27 @@ class OpenGnSysWorker(ServerWorker):
return operation(path[1:], getParams, postParams)
def process_status(self, path, getParams, postParams, server):
'''
"""
Returns client status.
'''
res = {'status': '', 'loggedin': self.loggedin}
if platform.system() == 'Linux': # GNU/Linux
# Check if it's OpenGnsys Client.
if os.path.exists('/scripts/oginit'):
# Check if OpenGnsys Client is busy.
if self.locked:
"""
st = {'linux': 'LNX', 'macos': 'OSX', 'oglive': 'OPG', 'windows': 'WIN'}
res = {'loggedin': self.loggedin}
try:
res['status'] = st[operations.os_type.lower()]
except KeyError:
res['status'] = ''
# Check if OpenGnsys Client is busy
if res['status'] == 'OPG' and self.locked:
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
def process_reboot(self, path, getParams, postParams, server):
'''
"""
Launches a system reboot operation.
'''
"""
logger.debug('Received reboot operation')
self.checkSecret(server)
# Rebooting thread.
def rebt():
operations.reboot()
@ -197,11 +222,12 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'}
def process_poweroff(self, path, getParams, postParams, server):
'''
"""
Launches a system power off operation.
'''
"""
logger.debug('Received poweroff operation')
self.checkSecret(server)
# Powering off thread.
def pwoff():
time.sleep(2)
@ -210,9 +236,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'}
def process_script(self, path, getParams, postParams, server):
'''
"""
Processes an script execution (script should be encoded in base64)
'''
"""
logger.debug('Processing script request')
self.checkSecret(server)
# Decoding script.
@ -227,9 +253,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'launched'}
def process_logoff(self, path, getParams, postParams, server):
'''
"""
Closes user session.
'''
"""
logger.debug('Received logoff operation')
self.checkSecret(server)
# Sending log off message to OGAgent client.
@ -237,9 +263,9 @@ class OpenGnSysWorker(ServerWorker):
return {'op': 'sended to client'}
def process_popup(self, path, getParams, postParams, server):
'''
"""
Shows a message popup on the user's session.
'''
"""
logger.debug('Received message operation')
self.checkSecret(server)
# Sending popup message to OGAgent client.
@ -248,3 +274,17 @@ class OpenGnSysWorker(ServerWorker):
def process_client_popup(self, 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
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
"""
@author: Ramón M. Gómez, ramongomez at us dot es
'''
"""
from __future__ import unicode_literals
import socket
import platform
import fcntl
import os
import ctypes # @UnusedImport
import ctypes.util
import subprocess
import struct
import array
@ -44,37 +41,11 @@ import six
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):
'''
"""
Returns the mac address of an interface
Mac is returned as unicode utf-8 encoded
'''
"""
if isinstance(ifname, list):
return dict([(name, _getMacAddr(name)) for name in ifname])
if isinstance(ifname, six.text_type):
@ -88,10 +59,10 @@ def _getMacAddr(ifname):
def _getIpAddr(ifname):
'''
"""
Returns the ip address of an interface
Ip is returned as unicode utf-8 encoded
'''
"""
if isinstance(ifname, list):
return dict([(name, _getIpAddr(name)) for name in ifname])
if isinstance(ifname, six.text_type):
@ -108,9 +79,9 @@ def _getIpAddr(ifname):
def _getInterfaces():
'''
"""
Returns a list of interfaces names coded in utf-8
'''
"""
max_possible = 128 # arbitrary. raise if needed.
space = max_possible * 16
if platform.architecture()[0] == '32bit':
@ -134,32 +105,32 @@ def _getInterfaces():
def _getIpAndMac(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
'''
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
def getComputerName():
'''
"""
Returns computer name, with no domain
'''
"""
return socket.gethostname().split('.')[0]
def getNetworkInfo():
'''
"""
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
mac: mac of the interface
ip: ip of the interface
'''
"""
for ifname in _getInterfaces():
ip, mac = _getIpAndMac(ifname)
if mac != '00:00:00:00:00:00': # Skips local interfaces
@ -170,56 +141,44 @@ def getDomainName():
return ''
def getOgliveVersion():
lv = platform.linux_distribution()
return lv[0] + ', ' + lv[1]
def get_oglive_version():
"""
Returns ogLive Kernel version and architecture
:return: kernel version
"""
kv = platform.os.uname()
return kv[2] + ', ' + kv[4]
def reboot():
'''
"""
Simple reboot using OpenGnsys script
'''
"""
# Workaround for dummy thread
if six.PY3 is False:
import threading
threading._DummyThread._Thread__stop = lambda x: 42
_exec_ogcommand('/opt/opengnsys/scripts/reboot', shell=True)
_exec_ogcommand('/opt/opengnsys/scripts/reboot')
def poweroff():
'''
"""
Simple poweroff using OpenGnsys script
'''
"""
# Workaround for dummy thread
if six.PY3 is False:
import threading
threading._DummyThread._Thread__stop = lambda x: 42
_exec_ogcommand('/opt/opengnsys/scripts/poweroff', shell=True)
_exec_ogcommand('/opt/opengnsys/scripts/poweroff')
def logoff():
pass
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.
'''
def get_disk_config():
"""
Returns disk configuration
Warning: this operation may take some time
"""
try:
_exec_ogcommand('/opt/opengnsys/interfaceAdm/getConfiguration')
# 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
# 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
from __future__ import unicode_literals
@ -39,19 +39,19 @@ import os
# Importing platform operations and getting operating system data.
if sys.platform == 'win32':
from .windows.operations import * # @UnusedWildImport
osType = 'Windows'
osVersion = getWindowsVersion()
os_type = 'Windows'
os_version = getWindowsVersion()
else:
if sys.platform == 'darwin':
from .macos.operations import * # @UnusedWildImport
osType = 'MacOS'
osVersion = getMacosVersion().replace(',','')
os_type = 'MacOS'
os_version = getMacosVersion().replace(',', '')
else:
if os.path.exists('/scripts/oginit'):
from .oglive.operations import * # @UnusedWildImport
osType = 'ogLive'
osVersion = getOgliveVersion().replace(',','')
os_type = 'ogLive'
os_version = get_oglive_version()
else:
from .linux.operations import * # @UnusedWildImport
osType = 'Linux'
osVersion = getLinuxVersion().replace(',','')
os_type = 'Linux'
os_version = getLinuxVersion().replace(',', '')