You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-3-core/pym/core/server/baseClass.py

404 lines
15 KiB

# -*- coding: utf-8 -*-
# Copyright 2012-2016 Mir Calculate. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
from spyne import rpc
from spyne import Service
from spyne import String, Integer, Array
from calculate.core.server.core_interfaces import CoreServiceInterface
from calculate.lib.utils.files import readFile
_ = lambda x: x
from calculate.lib.cl_lang import getLazyLocalTranslate, setLocalTranslate
setLocalTranslate('cl_core3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
from clean import sid_monitor, monitor
from tasks import restart, dbus_stop
from loaded_methods import LoadedMethods
from api_types import Message, ReturnProgress, Table
import post_cert
import post_request
import send_cert
# class Basic(CoreServiceInterface):
class Basic(Service, CoreServiceInterface):
""" Basic server class """
SERV_VERS = 0.11
glob_process_dict = {}
process_pid = {}
glob_progress_dict = {}
glob_table_dict = {}
glob_frame_list = {}
manager = None
data_path = None
certbase = None
rights = None
sids = None
pids = None
sids_file = None
ssl_certificate = None
ssl_private_key = None
cachedict = {}
#workaround: Spyne won't let us use self ref in @rpc,
# and ctx leads to original service class (Basic in this case)
# but some methods are gathered from CoreWsdl classes, so we need
# a ref to combined class
comb_class_ref = None
# function getting object from cache
@staticmethod
def get_cache(sid, meth_name, obj_name):
if sid in Basic.cachedict:
if meth_name in Basic.cachedict[sid]:
if obj_name in Basic.cachedict[sid][meth_name]:
return Basic.cachedict[sid][meth_name][obj_name]
return None
# function placing object in cache
@staticmethod
def set_cache(sid, meth_name, obj_name, obj, smart=True):
try:
if sid not in Basic.cachedict:
Basic.cachedict[sid] = {}
if meth_name not in Basic.cachedict[sid]:
Basic.cachedict[sid][meth_name] = {}
if obj_name not in Basic.cachedict[sid][meth_name]:
Basic.cachedict[sid][meth_name][obj_name] = obj
return True
if smart:
for var_name, var_value in obj.__dict__.viewitems():
if var_value is not None:
setattr(Basic.cachedict[sid][meth_name][obj_name],
var_name, var_value)
else:
Basic.cachedict[sid][meth_name][obj_name] = obj
return True
except Exception as e:
if isinstance(e, SyntaxError):
raise
return False
@staticmethod
def clear_cache(sid, meth_name=None, obj_name=None):
if sid not in Basic.cachedict:
return True
if meth_name:
if meth_name not in Basic.cachedict[sid]:
return True
if obj_name:
if obj_name not in Basic.cachedict[sid][meth_name]:
return True
else:
obj = Basic.cachedict[sid][meth_name].pop(obj_name, None)
if hasattr(obj, 'close'):
obj.close()
else:
method_dict = Basic.cachedict[sid].pop(meth_name, None)
for val_obj in method_dict.values():
if hasattr(val_obj, 'close'):
val_obj.close()
else:
session_dict = Basic.cachedict.pop(sid, None)
for method_dict in session_dict.values():
for val_obj in method_dict.values():
if hasattr(val_obj, 'close'):
val_obj.close()
@staticmethod
def clear_cache_method(method=None):
for k, v in Basic.cachedict.items():
Basic.clear_cache(k, method)
@staticmethod
def set_paths(data_path, certbase, serv_certbase, rights,
group_rights, sids, pids, sids_pids, sids_file, pids_file,
max_sid, max_pid, cert_path, log_filename,
cert="server.crt", key="server.key"):
""" set system path for main class """
Basic.data_path = data_path
Basic.certbase = certbase
Basic.serv_certbase = serv_certbase
Basic.rights = rights
Basic.group_rights = group_rights
Basic.sids = sids
Basic.pids = pids
Basic.sids_pids = sids_pids
Basic.sids_file = sids_file
Basic.pids_file = pids_file
Basic.ssl_certificate = cert
Basic.ssl_private_key = key
Basic.cert_path = cert_path
Basic.max_sid = int(max_sid)
Basic.max_pid = int(max_pid)
Basic.log_filename = log_filename
@staticmethod
def set_comb_class_ref(comb_class_ref):
Basic.comb_class_ref = comb_class_ref
@staticmethod
def run_tasks():
"""
Запуситить регулярные задачи
"""
import threading
# start monitor and sid_monitor threads
monitoring = threading.Thread(target=monitor,
args=(Basic.certbase, Basic.sids_file))
sid_mon = threading.Thread(target=sid_monitor,
args=(Basic.sids_file, Basic.sids, Basic.comb_class_ref))
restart_watchdog = threading.Thread(target=restart,
args=(Basic.comb_class_ref.glob_process_dict,))
dbus_stop_mon = threading.Thread(target=dbus_stop,
args=(Basic.comb_class_ref.glob_process_dict, Basic.comb_class_ref.sids, Basic.comb_class_ref))
threads = []
for thread, success, failed in (
(monitoring, _("General monitoring started"),
_("Monitoring error")),
(sid_mon, _("Session monitoring started"),
_("Session monitoring failed")),
(restart_watchdog, _("Restart watchdog started"),
_("Restart watchdog failed")),
(dbus_stop_mon, _("Inactive watchdog started"),
_("Inactive watchdog failed"))):
try:
threads.append(thread)
thread.daemon = True
thread.start()
print success
except Exception:
print failed
print
@staticmethod
def killall():
sys.stdout.write('\n' + _('Closing all processes') + '...')
sys.stdout.flush()
import time
# Waiting for closing
for pid in Basic.process_pid.keys():
try:
os.kill(Basic.process_pid[pid].pid, 2)
except OSError:
pass
while True:
num_active_process = 0
for pid in Basic.process_pid.keys():
if Basic.process_pid[pid].is_alive():
num_active_process += 1
if num_active_process:
sys.stdout.write('.')
sys.stdout.flush()
else:
print '\n' + _('All processes are closed.')
return 0
time.sleep(0.5)
@rpc(_returns=Array(Integer))
def post_cert(ctx):
# import post_cert
returns = post_cert.serv_post_cert(Basic.comb_class_ref)
return returns
@rpc(Integer, _returns=Integer)
def clear_session_cache(ctx, sid):
check_sid = Basic.comb_class_ref.check_sid_cert(Basic.comb_class_ref, sid)
if not check_sid:
return 1
# clear cache
Basic.clear_cache(sid)
return 0
@rpc(Integer, String, _returns=Integer)
def clear_method_cache(ctx, sid, method_name):
check_sid = Basic.comb_class_ref.check_sid_cert(Basic.comb_class_ref, sid)
if not check_sid:
return 1
# clear cache
Basic.clear_cache(sid, method_name)
return 0
@rpc(Integer, Integer, _returns=Integer)
def clear_pid_cache(ctx, sid, pid):
if not Basic.comb_class_ref.check_sid_cert(Basic.comb_class_ref, sid):
return 1
if pid in Basic.comb_class_ref.find_sid_pid_file(Basic.comb_class_ref, sid):
# clear pid cache
Basic.comb_class_ref.delete_pid(Basic.comb_class_ref, sid, pid)
return 0
return 2
@rpc(Integer, Integer, String, _returns=Array(Integer))
def post_sid(self, sid, cert_id, lang):
return Basic.comb_class_ref.sid_cmp(Basic.comb_class_ref, sid, cert_id, lang)
@rpc(Integer, String, _returns=(Array(Integer), Array(Integer)))
def init_session(ctx, sid, lang):
return Basic.comb_class_ref.serv_init_session(Basic.comb_class_ref, sid, lang)
@rpc(Integer, _returns=Array(String))
# @Dec.check_permissions(['del_sid'])
def del_sid(self, sid):
flag = Basic.comb_class_ref.del_sid_pid(Basic.comb_class_ref, sid)
Basic.comb_class_ref.clear_cache(int(sid))
if not flag:
return Basic.comb_class_ref.del_sid_from_file(Basic.comb_class_ref,
sid)
else:
return ['-1']
@rpc(Integer, Integer, _returns=Integer)
def pid_kill(ctx, pid, sid):
return Basic.comb_class_ref.serv_pid_kill(Basic.comb_class_ref, pid, sid)
@rpc(Integer, _returns=Array(Integer))
def list_pid(ctx, sid):
return Basic.comb_class_ref.find_sid_pid_file(Basic.comb_class_ref, sid)
@rpc(Integer, String, _returns=Array(Array(String)))
def get_methods(ctx, sid, client_type):
return map(lambda x: map(str, x),
Basic.comb_class_ref.serv_get_methods(Basic.comb_class_ref, client_type))
@rpc(Integer, _returns=Array(String))
@LoadedMethods.core_method(rights=["get-sessions"])
# @Dec.console('list-session')
def get_sessions(ctx, sid):
if not Basic.comb_class_ref.check_sid_cert(Basic.comb_class_ref, sid):
return ['']
return Basic.comb_class_ref.serv_get_sessions(Basic.comb_class_ref)
@rpc(Integer, Integer, _returns=Array(String))
# @Dec.check_permissions(["pid_info"])
def pid_info(ctx, sid, pid):
return Basic.comb_class_ref.serv_pid_info(Basic.comb_class_ref, sid, pid)
@rpc(Integer, _returns=Array(String))
@LoadedMethods.core_method(rights=["session_info"])
def sid_info(ctx, sid):
return Basic.comb_class_ref.serv_sid_info(Basic.comb_class_ref, sid)
@rpc(Integer, String, _returns=Array(String))
@LoadedMethods.check_permissions(["view_cert_right"])
# @Dec.console('view-cert-right')
# @Dec.gui('System')
def view_cert_right(ctx, cert_id, client_type):
return Basic.comb_class_ref.serv_view_cert_right(Basic.comb_class_ref,
cert_id, Basic.data_path, client_type)
@rpc(Integer, _returns=Integer)
def active_client(ctx, sid):
return Basic.comb_class_ref.active_clients(Basic.comb_class_ref, sid)
@rpc(String, String, String, String, _returns=String)
def post_client_request(ctx, request, ip, mac, client_type):
res = post_request.serv_post_client_request(request, Basic.data_path,
ip, mac, client_type,
Basic.certbase,
Basic.cert_path)
return res
@rpc(String, String, _returns=Array(String))
def get_client_cert(ctx, req_id, request):
res = post_request.serv_get_client_cert(req_id, request,
Basic.data_path, Basic.certbase,
Basic.cert_path)
return res
@rpc(String, String, String, _returns=String)
def post_server_request(ctx, request, ip, mac):
res = post_request.serv_post_server_request(request, Basic.data_path,
ip, mac, Basic.serv_certbase,
Basic.cert_path)
return res
@rpc(String, String, _returns=Array(String))
def get_server_cert(ctx, req_id, request):
res = post_request.serv_get_server_request(req_id, request,
Basic.data_path,
Basic.serv_certbase,
Basic.cert_path)
return res
@rpc(_returns=String)
def get_crl(self):
if os.path.exists(Basic.data_path + '/server_certs/ca.crl'):
return readFile(Basic.data_path + '/server_certs/ca.crl')
return ' '
@rpc(_returns=String)
def get_server_host_name(ctx):
import OpenSSL
cert = readFile(Basic.ssl_certificate)
cert_obj = OpenSSL.crypto.load_certificate(
OpenSSL.SSL.FILETYPE_PEM, cert)
subject = cert_obj.get_subject().get_components()
for subj in subject:
if subj[0] == 'CN':
return subj[1]
return ''
@rpc(_returns=String)
def get_ca(ctx):
return send_cert.get_ca(Basic.cert_path)
#moved here from api_types:
@rpc(Integer, Integer, String, _returns=Array(Message))
# @Dec.check_permissions()
def get_frame(ctx, sid, pid, client_type):
return Basic.comb_class_ref.client_get_frame(Basic.comb_class_ref, sid, pid, client_type)
@rpc(Integer, Integer, _returns=Array(Message))
def get_entire_frame(self, sid, pid):
return Basic.comb_class_ref.client_get_entire_frame(Basic.comb_class_ref, sid, pid)
@rpc(Integer, Integer, Integer, _returns=ReturnProgress)
# @Dec.check_permissions()
def get_progress(self, sid, pid, id):
return Basic.comb_class_ref.client_get_progress(Basic.comb_class_ref, sid, pid, id)
@rpc(Integer, Integer, Integer, _returns=Table)
# @Dec.check_permissions()
def get_table(self, sid, pid, id):
return Basic.comb_class_ref.client_get_table(Basic.comb_class_ref, sid, pid, id)
# get messages, transferred from client
@rpc(Integer, Integer, String, _returns=Message)
# @Dec.check_permissions()
def send_message(self, sid, pid, text):
return Basic.comb_class_ref.client_send_message(Basic.comb_class_ref, sid, pid, text)