import glob import os import re import subprocess import sys import tempfile import time import datetime import platform import traceback import FileIface import notify_activity import ntplib import Activity import WGDBus import json import fsio import FilePaths import syslog import logConfig from subprocess import call import status_mod import channel_mod import m7z_mod AUTH_UPDATE_JSON = '/home/tool/web2py/applications/BS350/config/auth_update/auth_update.json' TOOL_CONFIG_TIMEZONE = '/home/tool/config/timezone' CONFIG_PATH = '/home/tool/config' WHITE_LIST_NAME = 'cfg_choice_importer_whitelist.json' # Fake globals for syntax check if False: response = None request = None session = None db = None status_mod.sessionUserMgr.setLastVisit(session, request) if logConfig.settingsSessFrgt: if request.function != 'settime' and request.function != 'settimezone' and request.function != 'restoretimezone' and request.function != 'setNTPTime': session.forget(response) @auth.requires(request.ajax==True, requires_login=True) def auth_version(): version = "No version found" try: version = db.executesql('SELECT version FROM auth_version')[0][0] except: a, b, c = sys.exc_info() syslog.syslog(syslog.LOG_ERR, str(b)) return version @auth.requires(request.ajax==True, requires_login=True) def auth_version_should(): if os.path.isfile(AUTH_UPDATE_JSON): try: return str(json.load(open(AUTH_UPDATE_JSON)).get('auth_version')) except: syslog.syslog(syslog.LOG_ERR, "auth_update.json file is available but has wrong format") return "No version found" @auth.requires(request.ajax==True, requires_login=False) def version(): return (FilePaths.version()) @auth.requires(request.ajax==True, requires_login=True) def prevVersion(): return FilePaths.prevVersion() @auth.requires(request.ajax==True, requires_login=True) def majorVersion(): return FilePaths.getMajorVersion() @auth.requires(request.ajax==True, requires_login=True) def majorNumVersion(): return int(FilePaths.getMajorVersion()[1:]) @auth.requires(request.ajax==True, requires_login=True) def prevMajorVersion(): return FilePaths.getPrevMajorVersion() @auth.requires(request.ajax==True, requires_login=True) def prevMajorNumVersion(): return int(FilePaths.getPrevMajorVersion()[1:]) @auth.requires(request.ajax==True, requires_login=True) def prevAndCurrMajorNumVersion(): return response.json(_prevAndCurrMajorNumVersion()) @auth.requires(request.ajax==True, requires_login=True) def _prevAndCurrMajorNumVersion(): return {"prev": prevMajorNumVersion(), "curr": majorNumVersion()} @auth.requires(request.ajax==True, requires_login=True) def _isRemoveResDBRequired(): versions = _prevAndCurrMajorNumVersion() if versions.get('prev') <= 1100 and versions.get('curr') >= 1200: return True return False @auth.requires(request.ajax==True, requires_login=True) def isRemoveResDBRequired(): res = _isRemoveResDBRequired() return response.json(res) # ----------------------- # Time # ----------------------- @auth.requires(request.ajax==True, requires_login=True) def gettime(): t = time.localtime() return response.json({"year":t.tm_year, "month":t.tm_mon, "day":t.tm_mday, "hour":t.tm_hour, "min":t.tm_min, "sec":t.tm_sec}) @auth.requires(request.ajax==True, requires_login=True) def gettimeUTC(): t = time.gmtime() tz = 0 # Get timezone from date because time.altzone is not always up to date p = subprocess.Popen(['date', '+%z'], stdout=subprocess.PIPE) (stdout, stderr) = p.communicate() r = re.match('([+|-])([0-9]{2})([0-9]{2})', stdout) if r: s, h, m = r.groups() tz = int(s+'1')*int(h)*60+int(m) return response.json({"year":t.tm_year, "month":t.tm_mon, "day":t.tm_mday, "hour":t.tm_hour, "min":t.tm_min, "sec":t.tm_sec, "offset": tz}) @auth.requires(request.ajax==True, requires_login=True) def settime(): try: status_mod.sessionUserMgr.lockUserList() data = json.loads(request.body.read()) timestr = '{year}.{month}.{day}-{hour}:{min}:{sec}'.format(**data) subprocess.call(['date','-s', timestr]) subprocess.call(['hwclock', '-uw']) Activity.LOG(session, Activity.TIME_CHANGED) status_mod.sessionUserMgr.setLastVisitAll() except: pass status_mod.sessionUserMgr.releaseUserList() @auth.requires(request.ajax==True, requires_login=True) def setNTPTime(): ntpServer = request.vars.ntp runDaemon = request.vars.rund try: #first create file ntpCfg = os.path.join(CONFIG_PATH, 'ntp.cfg') if runDaemon == 'true': fsio.write(ntpCfg, ntpServer) elif os.access(ntpCfg, os.F_OK): os.remove(ntpCfg) except: if runDaemon == 'true': return 'Create file failed: ' + str(sys.exc_info()[1]) return 'Delete file failed: ' + str(sys.exc_info()[1]) #We need this when we run the deamon if runDaemon == 'true': try: status_mod.sessionUserMgr.lockUserList() #now get time from the server #subprocess.call(['ntpd', '-q', '-n', '-p', '%s' % ntpServer]) c = ntplib.NTPClient() r = c.request(ntpServer, port=123) ltime = time.localtime(r.tx_time) timestr = time.strftime('%Y.%m.%d-%H:%M:%S', ltime) subprocess.call(['date', '-s', timestr]) subprocess.call(['hwclock', '-uw']) status_mod.sessionUserMgr.setLastVisitAll() Activity.LOG(session, Activity.TIME_CHANGED) except: syslog.syslog(syslog.LOG_ERR, 'setNTPTime: File created but change time failed -- ' + str(sys.exc_info()[1])) return '' finally: status_mod.sessionUserMgr.releaseUserList() return 'ok' @auth.requires(request.ajax==True, requires_login=True) def getntpcfg(): data = '0.0.0.0' ntpCfg = os.path.join(CONFIG_PATH, 'ntp.cfg') if os.access(ntpCfg, os.F_OK): data = fsio.read(ntpCfg) return data @auth.requires(request.ajax==True, requires_login=True) def timezones(): from Timezones import tz return response.json(tz) @auth.requires(request.ajax==True, requires_login=True) def timezone(): try: link = os.readlink('/etc/localtime') except: link = '/usr/share/zoneinfo/Europe/Berlin' return link[20:] @auth.requires(request.ajax==True, requires_login=True) def settimezone(): try: status_mod.sessionUserMgr.lockUserList() tz = request.vars.tz fsio.write(TOOL_CONFIG_TIMEZONE, tz) call("mount -o remount,rw,sync /", shell=True) os.remove('/etc/localtime') os.symlink(os.path.join('/usr/share/zoneinfo', tz), '/etc/localtime') call("mount -o remount,ro /", shell=True) status_mod.sessionUserMgr.setLastVisitAll() Activity.LOG(session, Activity.TIME_CHANGED) except: pass status_mod.sessionUserMgr.releaseUserList() @auth.requires(request.ajax==True, requires_login=True) def restoretimezone(): try: status_mod.sessionUserMgr.lockUserList() tz = fsio.read(TOOL_CONFIG_TIMEZONE) tz = tz.strip() os.remove('/etc/localtime') os.symlink(os.path.join('/usr/share/zoneinfo', tz), '/etc/localtime') status_mod.sessionUserMgr.setLastVisitAll() except: syslog.syslog(syslog.LOG_ERR, "Could not restore timezone") finally: status_mod.sessionUserMgr.releaseUserList() def getRawFileValue(filename=None, default='-'): value = None try: value = fsio.read(filename=filename) finally: if value and len(value.strip()) > 0: try: return value except: pass return default def getFileValue(filename=None, default='-'): value = None try: value = fsio.read(filename=filename) finally: if value: try: return str(int(round(float(value)))) + " °C" except: pass return default def getFileFloatValue(filename=None, default='-', factor=1, genauigkeit=0): value = None try: value = fsio.read(filename=filename) finally: if value: try: return "{0:.{1}f}".format(float(value)*factor, genauigkeit) except: pass return default @auth.requires(request.ajax==True, requires_login=True) def getTempValue(): return getFileValue(filename=FileIface.TEMPERATURE) @auth.requires(request.ajax==True, requires_login=True) def getTempHeatSinkLtValue(): return getFileValue(filename=FileIface.TEMPERATURE_HEAT_SINK_LT) @auth.requires(request.ajax==True, requires_login=True) def getTempMotorValue(): return getFileValue(filename=FileIface.TEMPERATURE_MOTOR) @auth.requires(request.ajax==True, requires_login=True) def getTempMotorLtValue(): return getFileValue(filename=FileIface.TEMPERATURE_MOTOR_LT) def getLoadCycleCounterValue(factor, genauigkeit): return getFileFloatValue(filename=FileIface.LOAD_CYCLE_COUNTER, factor=factor, genauigkeit=genauigkeit) def getAvgLoadTorqueValue(factor, genauigkeit): return getFileFloatValue(filename=FileIface.AVG_LOAD_TORQUE, factor=factor, genauigkeit=genauigkeit) @auth.requires(request.ajax==True, requires_login=True) def getAvgStartLoadTorqueValue(): return getRawFileValue(filename=FileIface.AVG_START_LOAD_TORQUE) @auth.requires(request.ajax==True, requires_login=True) def getTempPlatineValue(): return getFileValue(filename=FileIface.TEMPERATURE_PLATINE) @auth.requires(request.ajax==True, requires_login=True) def infoHardware(): factors = channel_mod.get_torque_unit_factors() index = int(factors.get('Aktiv')) for f in factors.get('Faktoren'): if f.get('Id') == index: factor = f.get('Wert') einheit = f.get('Einheit') genauigkeit = f.get('Genauigkeit') break info = {'items': []} items = info['items'] items.append({'name': 'Code', 'value': fsio.readNb(FileIface.CODE_FILENAME)}) items.append({'name': 'Platform', 'value': platform.machine() + platform.processor()}) items.append({'name': 'Address', 'value': request.env.http_host}) items = items + _ifconfig() # items.append({'name': "Card Temperature for GUI", 'value': getTempValue()}) # CR12481: items.append({'name': "Estimated Motor Temperature from Card", 'value': getTempMotorValue()}) items.append({'name': "Card Temperature", 'value': getTempPlatineValue()}) items.append({'name': "Heat Sink Temperature (LT)", 'value': getTempHeatSinkLtValue()}) items.append({'name': "Estimated Motor Temperature (LT)", 'value': getTempMotorLtValue()}) # CR9280 Anzeige ohne Nachkommastellen: items.append({'name': "Avg. Load Torque", 'value': "{0} {1}".format(getAvgLoadTorqueValue(factor, 3), einheit)}) items.append({'name': "Avg. Start Load Torque Calculation", 'value': "{0}".format(getAvgStartLoadTorqueValue())}) return response.json(items) @auth.requires(request.ajax==True, requires_login=True) def infoSoftware(): info = {'items': []} items = info['items'] items.append({'name': 'Python', 'value': sys.version }) items.append({'name': 'Kernel', 'value': platform.system() + ' ' + platform.release()}) items.append({'name': 'Webserver', 'value': request.env.server_software}) items.append({'name': 'Web2Py', 'value': '%d.%d.%d' % (request.env.web2py_version[0], request.env.web2py_version[1], request.env.web2py_version[2]) }) items.append({'name': 'NEXO-OS', 'value': version() }) return response.json(items) @auth.requires(request.ajax==True, requires_login=True) def generatePassword(): newPwd = request.vars.pwd return db.auth_user['password'].validate(newPwd)[0] @auth.requires(request.ajax==True, requires_login=True) def setpassword(): import base64 newPwd = base64.b64decode(request.vars.pwd) userId = request.vars.id res = 'FAIL' if userId == None: return res if userId == '': return res entry = db(db.auth_user.id == userId) newPwd = db.auth_user['password'].validate(newPwd)[0] #CR10648 empty password is allowed #if newPwd: try: entry.update(password=newPwd) Activity.LOG(session, Activity.PASSWORD_CHANGED) res = 'OK' except: pass return res @auth.requires(request.ajax==True, requires_login=True) def reboot(): subprocess.call(['/etc/reboot/reboot.sh']) @auth.requires(request.ajax==True, requires_login=True) def restorentp(): if os.path.exists("/home/tool/config/ntp.cfg"): call("sh /etc/ntp/ntp.sh", shell=True) @auth.requires(request.ajax==True, requires_login=True) def postImportExecution(): active = request.vars.active if active == 'true': call("cp /etc/init.d/web2py_https.sh /etc/init.d/web2py.sh", shell=True) else: call("cp /etc/init.d/web2py_normal.sh /etc/init.d/web2py.sh", shell=True) restoretimezone() restorentp() call("sh /etc/reboot/reboot.sh", shell=True) @auth.requires(request.ajax==True, requires_login=True) def removeresultdb(): if (os.path.isfile("/mnt/data/ResDB.sq3")): os.remove("/mnt/data/ResDB.sq3") @auth.requires(request.ajax==True, requires_login=True) def getmajorversion(): version = FilePaths.version() result = {} result['downgrade_warning'] = False major = int(version[6:10]) result['majorversion'] = major if major >= 1200: result['downgrade_warning'] = True return response.json(result) @auth.requires(request.ajax==True, requires_login=True) def beforefwupload(): subprocess.check_call(['/etc/fwupdate/1-before-Upload.sh']) @auth.requires(request.ajax==True, requires_login=True) def performUpdate(): res = {'success': True, 'msg': ':-)'} try: subprocess.check_call(['/etc/fwupdate/2-after-Upload.sh']) except: res = {'success': False, 'msg': 'fw update sh failure none zero exit'} return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def switchPrevFW(): res = {'success': True, 'msg': ':-)', 'successDBRem': True} ret = -1 try: ret = subprocess.check_call(['/etc/fwupdate/switchParSystem.sh']) if _isRemoveResDBRequired(): os.remove("/mnt/data/ResDB.sq3") except: if ret == 0: res = {'success': True, 'msg': 'resdb.sq3 removal failed', 'successDBRem': False} else: res = {'success': False, 'msg': 'switch to previous fw part sh failure none zero exit', 'successDBRem': True} return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def batteryStatus(): value = WGDBus.getBatteryPower() # Offline hack if value == 0: value = 100 return value @auth.requires_login() def powerFirmware(): filename = tempfile.mktemp(suffix='.bin', prefix="nxltfw_") #'/boot/NxLtFw.bin' try: # only to check if file is accessible: fp = open(filename, 'wb') except: return response.json({'success': False, 'msg': 'Cannot open file'}) finally: fp.close() try: fsio.write(filename, request.vars.fileupload.value) except: return response.json({'success': False, 'msg': 'Cannot write file'}) # default is /boot/NxLtFw.bin, first parameter specifies absolute filename, if alternative filename is needed subprocess.Popen(['/home/tool/bin/NxLtUpdate.elf', filename]) notify_activity.configChanged(filename, Activity.FILE_UPLOAD, session=session) return response.json({'success': True, 'msg': 'Servo amplifier firmware update started'}) @auth.requires(request.ajax==True, requires_login=True) def _ifconfig(): p = subprocess.Popen(['/sbin/ifconfig'], stdout=subprocess.PIPE) (stdout, stderr) = p.communicate() res = stdout def extractData(input): m = re.search(r'^(?Peth0|tiwlan0|wlan0)\s+' + r'(Link encap:(?P\S+)\s+)?' + r'(HWaddr\s(?P[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2})\s+)?' + r'((inet addr:(?P[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))?\s)?', input, re.MULTILINE) if m is None: return None return m.groupdict() i = [extractData(interface) for interface in res.split('\n\n') if interface.strip() ] intermediateResult = [ e for e in i if e is not None ] result = [] s = lambda s: str(s or ' - ') wirelessFound = False wiredFound = False for e in intermediateResult: if e['interface'] == 'tiwlan0' or e['interface'] == 'wlan0': result.append({'name': 'Wireless Adapter', 'value': s(e['ip_address']) + ' / ' + s(e['hardware_address']) }) wirelessFound = True elif e['interface'] == 'eth0': result.append({'name': 'Wired Adapter', 'value': s(e['ip_address']) + ' / ' + s(e['hardware_address'])}) wiredFound = True if not wirelessFound: result.append({'name': 'Wireless Adapter', 'value': '- / -' }) if not wiredFound: result.insert(0,{'name': 'Wired Adapter', 'value': '- / -' }) return result @auth.requires(request.ajax==True, requires_login=True) def _getinterfaceip(ifname): oscmd='/sbin/ifconfig '+ifname+' | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1' f=os.popen(oscmd) ip = f.read() return ip.rstrip() @auth.requires(request.ajax==True, requires_login=True) def _genCfgFileName(): return _genFileNameToExport("", ".nxcfg") def _genFileNameToExport(prefix, extension): ip=_getinterfaceip("tiwlan0") if not ip: ip=_getinterfaceip("eth0") ts = time.time() dateStamp = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d%H%M%S') if not ip: return prefix + version().strip() + '-' + dateStamp + extension else: return ip + "_" + prefix + version().strip() + '-' + dateStamp + extension @auth.requires(request.ajax==True, requires_login=True) def _genLogFileName(): return _genFileNameToExport("Logs_", ".nxlgx") @auth.requires(request.ajax==True, requires_login=True) def exportSD(): res = {'success': False, 'msg': 'Unknown error'} # Ensure that only one client exports fsio.fsXngLock.acquire() try: res = {'success': True, 'msg': ''} expfname = '/' + FilePaths.SD_CFG_DIR_NAME + '/' + _genCfgFileName() pwd = FilePaths.generateCfgPwd() syslog.syslog(syslog.LOG_INFO, "START setting.exportSD.subprocess to " + expfname + " at " + time.asctime()) p = subprocess.Popen(['{0}/cfg_exporter.sh'.format(FilePaths.SH_TOOL_PATH), pwd, expfname], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() syslog.syslog(syslog.LOG_INFO, "DONE setting.exportSD.subprocess to " + expfname + " at " + time.asctime()) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportSD.subprocess to stdout: " + str(stdout)) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportSD.subprocess to stderr: " + str(stderr)) if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def importSD(): res = {'success': True, 'msg': ''} fsio.fsXngLock.acquire() try: pwd = FilePaths.generateCfgPwd() cfgfile = '/' + FilePaths.SD_CFG_DIR_NAME + '/' + request.vars.cfgname p = subprocess.Popen(['{0}/cfg_importer.sh'.format(FilePaths.SH_TOOL_PATH), pwd, cfgfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def exportFile(): res = {'success': False, 'msg': 'Unknown error'} fsio.fsXngLock.acquire() try: expfname = _genCfgFileName() res = {'success': True, 'msg': '/tmp/' + expfname} pwd = FilePaths.generateCfgPwd() syslog.syslog(syslog.LOG_INFO, "Start setting.exportFile.subprocess to " + expfname + " at " + time.asctime()) p = subprocess.Popen(['{0}/cfg_exporter.sh'.format(FilePaths.SH_TOOL_PATH), pwd, expfname, '/tmp'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() syslog.syslog(syslog.LOG_INFO, "DONE setting.exportFile.subprocess to " + expfname + " at " + time.asctime()) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportFile.subprocess to stdout: " + str(stdout)) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportFile.subprocess to stderr: " + str(stderr)) if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def log_passwd(): return FilePaths.generateLogPwd() @auth.requires(request.ajax==True, requires_login=True) def exportSDLogs(): res = {'success': False, 'msg': 'Unknown error'} # Ensure that only one client exports fsio.fsXngLock.acquire() try: res = {'success': True, 'msg': ''} expfname = FilePaths.SD_LOGS_DIR_NAME + '/' + _genLogFileName() pwd = log_passwd() file_list = file_list_logs_export() syslog.syslog(syslog.LOG_INFO, "START setting.exportSDLogs.subprocess to " + expfname + " at " + time.asctime()) p = subprocess.Popen(['{0}/log_exporter.sh'.format(FilePaths.SH_TOOL_PATH), pwd, expfname, file_list], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() syslog.syslog(syslog.LOG_INFO, "DONE setting.exportSDLogs.subprocess to " + expfname + " at " + time.asctime()) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportSDLogs.subprocess to stdout: " + str(stdout)) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportSDLogs.subprocess to stderr: " + str(stderr)) if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def file_list_logs_export(): syslogs = glob.glob("/var/log/*") syslogs_str = " ".join(syslogs) #errors = glob.glob("/home/tool/web2py/applications/BS350/errors/*") #errors_str = " ".join(errors) var_run_diag = glob.glob("/var/run/diag/*") var_run_diag_str = " ".join(var_run_diag) file_list = syslogs_str + " " + var_run_diag_str + " /etc/version" return file_list @auth.requires(request.ajax==True, requires_login=True) def exportFileLogs(): res = {'success': False, 'msg': 'Unknown error'} fsio.fsXngLock.acquire() try: expfname = _genLogFileName() res = {'success': True, 'msg': '/tmp/' + expfname} pwd = log_passwd() # FilePaths.generatePwd() file_list = file_list_logs_export() syslog.syslog(syslog.LOG_INFO, "START setting.exportFileLogs.subprocess to " + expfname + " at " + time.asctime()) p = subprocess.Popen(['{0}/log_exporter.sh'.format(FilePaths.SH_TOOL_PATH), pwd, expfname, file_list, '/tmp'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() syslog.syslog(syslog.LOG_INFO, "DONE setting.exportFileLogs.subprocess to " + expfname + " at " + time.asctime()) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportFileLogs.subprocess to stdout: " + str(stdout)) syslog.syslog(syslog.LOG_INFO, "RESULT setting.exportFileLogs.subprocess to stderr: " + str(stderr)) if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() return response.json(res) #NO AJAX CHECK HERE CAUSE FORM SUBMIT @auth.requires_login() def importFile(): res = {'success': True, 'msg': ''} fsio.fsXngLock.acquire() try: with open('/tmp/config.cfg', 'w') as f: f.write(request.vars.cfg.value) pwd = FilePaths.generateCfgPwd() p = subprocess.Popen(['{0}/cfg_importer.sh'.format(FilePaths.SH_TOOL_PATH), pwd, 'config.cfg', '/tmp/'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() return response.json(res) def parseCfgInfo(res, selFlag=False): data = res['msg'].split('\n') # pattern of a single item to match: 2014-07-10 16:00:42 ....A 30 263552 idcode pattern = '\s*([\d]{4}-[\d]{2}-[\d]{2})\s*([\d]{2}:[\d]{2}:[\d]{2})\s*([.|A-Z|a-z]*)\s*([\d]*)\s*([\d]*)\s*(.*)' nameList = [] def getGroup(fullname): if type(fullname) != type('str'): return 'other' i = fullname.find('/') if i > -1: return (fullname[0:i]) return 'other' for d in data: matchs = re.match (pattern, d) if matchs: #print 'match', matchs.group(1), matchs.group(2), matchs.group(3), matchs.group(4), matchs.group(6) if matchs.group(3)[0] == 'D': continue #skip dir we do not need them now nameList.append({'name': matchs.group(6), 'select': selFlag, 'group': getGroup(matchs.group(6))}) else: pass#print '----no match---!!!!!', d if nameList == []: res['success'] = False res['msg'] = 'File empty' else: res['data'] = nameList res['msg'] = 'ok' def getKey(item): if item['name'].startswith("srbprg/prg"): m = re.match("(srbprg/prg)([0-9]*)\.lua", item['name']) return int(m.groups()[1]) if item['name'].startswith("jobs/job"): m = re.match("(jobs/job)([0-9]*)\.lua", item['name']) if m == None: return item return int(m.groups()[1]) else: return item def applyWhiteListFilter(srcList): try: whiteList = fsio.jsonloadordered(FilePaths.SH_TOOL_PATH+'/'+WHITE_LIST_NAME) excludedFileList = [] destList = [] filesfound = [] filesrequired = [] for grp in whiteList.keys(): additionltrgtfiles = whiteList[grp]["additional-target-files"].keys() filesrequired = filesrequired + [f for f in additionltrgtfiles if whiteList[grp]["additional-target-files"][f] == True] for item in sorted(srcList, key=getKey): if item['name'] in additionltrgtfiles: item['select'] = True destList.append({'name': item['name'], 'select': True, 'group': grp, 'expand': whiteList[grp]["expandable"], 'itemtext': whiteList[grp]["item-text"], 'grpEmpty': False}) filesfound.append(item['name']) elif item['group'] == whiteList[grp]["target-dir"]: if whiteList[grp]["filter"] == "": if whiteList[grp]["root-only"]: if whiteList[grp]["target-dir"]+'/'+whiteList[grp]["filter"] == item['name']: item['select'] = True destList.append({'name': item['name'], 'select': True, 'group': grp, 'expand': whiteList[grp]["expandable"], 'itemtext': whiteList[grp]["item-text"], 'grpEmpty': False}) else: item['select'] = True destList.append({'name': item['name'], 'select': True, 'group': grp, 'expand': whiteList[grp]["expandable"], 'itemtext': whiteList[grp]["item-text"], 'grpEmpty': False}) else: if whiteList[grp]["root-only"]: if re.match(whiteList[grp]["target-dir"]+'/'+whiteList[grp]["filter"], item['name']): item['select'] = True destList.append({'name': item['name'], 'select': True, 'group': grp, 'expand': whiteList[grp]["expandable"], 'itemtext': whiteList[grp]["item-text"], 'grpEmpty': False}) else: filename = os.path.basename(item['name']) if re.match(whiteList[grp]["filter"], filename): item['select'] = True destList.append({'name': item['name'], 'select': True, 'group': grp, 'expand': whiteList[grp]["expandable"], 'itemtext': whiteList[grp]["item-text"], 'grpEmpty': False}) for fitem in filesrequired: if fitem not in filesfound: raise Exception("At least one required file not found in cfg [" + "missing " + fitem + "]") for item in srcList: if item['select'] == False: excludedFileList.append(item['name']) #add missing groups as faked foundGrps = [item['group'] for item in destList] for grp in whiteList.keys(): if grp not in foundGrps: if grp not in ["Jobs", "Programs"]: destList.append({'name': grp+"/faked#1", 'select': True, 'group': grp, 'expand': False, 'itemtext': grp+"/faked#1", 'grpEmpty': True}) #from pprint import pprint #pprint(destList) except: traceback.print_exc() traceback.print_stack() return destList, excludedFileList #NO AJAX CHECK HERE CAUSE FORM SUBMIT @auth.requires_login() def getZipFileInfo(): res = {'success': False, 'msg': '', 'data': [], 'rmvList': []} fsio.fsXngLock.acquire() try: with open('/tmp/config.cfg', 'w') as f: import hashlib syslog.syslog(syslog.LOG_DEBUG, "TYPE: " + type(request.vars.cfg.value).__name__) syslog.syslog(syslog.LOG_DEBUG, "md5sum request value: " + str(hashlib.md5(request.vars.cfg.value).hexdigest())) f.write(request.vars.cfg.value) os.fsync(f) with open('/tmp/config.cfg', 'r') as f: syslog.syslog(syslog.LOG_DEBUG, "md5sum config.cfg: " + str(hashlib.md5(f.read()).hexdigest())) pwd = FilePaths.generateCfgPwd() p = subprocess.Popen(['{0}/cfg_info.sh'.format(FilePaths.SH_TOOL_PATH), pwd, 'config.cfg', '/tmp/'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) else: res['success'] = True res['msg'] = str(stdout) except Exception, e: syslog.syslog(syslog.LOG_ERR, str(traceback.format_exc())) syslog.syslog(syslog.LOG_ERR, str(traceback.format_stack())) res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() try: if res['success'] == True: parseCfgInfo(res) if res['success'] == True: import base64 res['filedata'] = base64.b64encode(request.vars.cfg.value) fliteredData, rmvlist = applyWhiteListFilter(res['data']) res['data'] = fliteredData res['rmvList'] = rmvlist #print 'data', res except Exception, e: syslog.syslog(syslog.LOG_ERR, traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, traceback.format_stack()) res['success'] = False res['msg'] = str(e) #print 'exit', res return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def getZipFileInfoSD(): res = {'success': False, 'msg': '', 'data': [], 'rmvList': []} fsio.fsXngLock.acquire() try: cfgfile = '/' + FilePaths.SD_CFG_DIR_NAME + '/' + request.vars.cfgname pwd = FilePaths.generateCfgPwd() p = subprocess.Popen(['{0}/cfg_info.sh'.format(FilePaths.SH_TOOL_PATH), pwd, cfgfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) else: res['success'] = True res['msg'] = str(stdout) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() try: if res['success'] == True: parseCfgInfo(res) if res['success'] == True: fliteredData, rmvlist = applyWhiteListFilter(res['data']) res['data'] = fliteredData res['rmvList'] = rmvlist #print 'data', res except Exception, e: res['success'] = False res['msg'] = str(e) #print 'exit', res return response.json(res) @auth.requires(request.ajax==True, requires_login=True) def getSecurity(): try: if os.path.isfile(FilePaths.SECURITY_FILENAME): res = fsio.jsonload(FilePaths.SECURITY_FILENAME) if res != None: if 'database' in res.keys(): if 'https' in res['database'].keys(): return res['database']['https'] except: syslog.syslog(syslog.LOG_ERR, 'Failed to read new ' + FilePaths.SECURITY_FILENAME) return False @auth.requires(request.ajax==True, requires_login=True) def importSelectedFiles(): res = {'success': True, 'msg': '', 'https': False} cfgName = 'config.cfg' flistName = 'filelist.txt' trgtPath = '/tmp' fsio.fsXngLock.acquire() try: import base64, hashlib filedata = base64.b64decode(request.vars.filedata) dig = hashlib.md5(filedata).hexdigest() with open(trgtPath + '/' + cfgName, 'w') as f: f.write(filedata) with open(trgtPath + '/' + cfgName, 'r') as f: dig2 = hashlib.md5(f.read()).hexdigest() if dig != dig2: syslog.syslog(syslog.LOG_DEBUG, "md5sum differ !!!! {0} != {1}".format(dig, dig2)) excludeList = request.vars.excludeList namesdata = retrofitExcludeList(excludeList) with open(trgtPath + '/' + flistName, 'w') as f: f.write(namesdata) pwd = FilePaths.generateCfgPwd() p = subprocess.Popen( ['{0}/cfg_choice_importer.sh'.format(FilePaths.SH_TOOL_PATH), pwd, flistName, cfgName, trgtPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode != 0: syslog.syslog(syslog.LOG_ERR, stdout) syslog.syslog(syslog.LOG_ERR, stderr) # Failure res['success'] = False res['msg'] = str(stderr) else: res['https'] = getSecurity() except Exception, e: syslog.syslog(syslog.LOG_ERR, traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, traceback.format_stack()) res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() #print 'exit', res return response.json(res) def retrofitExcludeList(excludeList): namesdata = "" if excludeList is None: excludeList = [] if isinstance(excludeList, str): if len(excludeList) > 0: excludeList = excludeList.split("\n") else: excludeList = [] if isinstance(excludeList, list): for name in excludeList: if not name.startswith("mfu/"): namesdata = namesdata + name + '\n' else: syslog.syslog(syslog.LOG_ERR, "import selected files not possible: excludeList is not valid!") return namesdata @auth.requires(request.ajax==True, requires_login=True) def importSelectedFilesSD(): res = {'success': True, 'msg': '', 'https': False} fsio.fsXngLock.acquire() try: pwd = FilePaths.generateCfgPwd() cfgfile = '/' + FilePaths.SD_CFG_DIR_NAME + '/' + request.vars.cfgname flistName = '/tmp/filelist.txt' excludeList = request.vars.excludeList namesdata = retrofitExcludeList(excludeList) syslog.syslog(syslog.LOG_DEBUG, namesdata) with open(flistName, 'w') as f: f.write(namesdata) p = subprocess.Popen(['{0}/cfg_choice_importer.sh'.format(FilePaths.SH_TOOL_PATH), pwd, flistName, cfgfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode != 0: syslog.syslog(syslog.LOG_ERR, stdout) syslog.syslog(syslog.LOG_ERR, stderr) # Failure res['success'] = False res['msg'] = str(stderr) else: res['https'] = getSecurity() except Exception, e: syslog.syslog(syslog.LOG_ERR, traceback.format_exc()) syslog.syslog(syslog.LOG_ERR, traceback.format_stack()) res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() #print 'exit', res return response.json(res) @auth.requires_login() def getJobsZipContent(): return getZipContent(FileIface.CFG_LIST_JOB_000) @auth.requires_login() def getPrgsZipContent(): return getZipContent(FileIface.CFG_LIST_PRG_0) @auth.requires_login() def getZipContent(rev_filepath): try: filename = request.vars.fileupload.filename.split("\\")[-1] except: return response.json({'success': False, 'msg': 'Invalid parameters'}) res = {'success': False, 'msg': 'Unknown Error', 'data': []} trgtfile = '/tmp/package.zip' fsio.fsXngLock.acquire() try: with open(trgtfile, 'w') as f: f.write(request.vars.fileupload.value) pwd = FilePaths.gen_rev_pwd(rev_filepath) returncode = m7z_mod.test_pwd(trgtfile, pwd) if returncode != 0: return response.json(m7z_mod.get_import_impossible_msg()) p = subprocess.Popen(['/home/tool/bin/7za', 'l', trgtfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() if p.returncode != 0: # Failure res['success'] = False res['msg'] = str(stderr) if res['msg'] == "": res['msg'] = 'System Error' else: res['success'] = True res['msg'] = str(stdout) except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() try: if res['success'] == True: parseCfgInfo(res, True) if res['success'] == True: import base64 res['filedata'] = base64.b64encode(request.vars.fileupload.value) #print 'data', res except Exception, e: res['success'] = False res['msg'] = str(e) #print 'exit', res['msg'] return response.json(res) def getDirContent(trgtPath): res = {'success': False, 'msg': 'Unknown Error', 'data': []} fsio.fsXngLock.acquire() try: nameList = [] file_list = glob.glob(trgtPath) res['msg'] = ":-)" res['success'] = True for f in file_list: nameList.append({'name': f, 'select': True, 'group': trgtPath}) res['data'] = nameList except Exception, e: res['success'] = False res['msg'] = str(e) finally: fsio.fsXngLock.release() #print 'exit', res return response.json(res) @auth.requires_login() def getPrgDirContent(): return getDirContent(CONFIG_PATH + "/srbprg/prg*.lua") @auth.requires_login() def getJobDirContent(): return getDirContent(CONFIG_PATH + "/jobs/job*.lua")