503 lines
16 KiB
Python
503 lines
16 KiB
Python
from modules.pastafari2 import pastafari_app
|
|
from paramecio2.modules.admin.models.admin import UserAdmin
|
|
from paramecio2.libraries.mtemplates import PTemplate, env_theme
|
|
from paramecio2.libraries.i18n import I18n, PGetText
|
|
from paramecio2.libraries.db import corefields
|
|
from typing import Annotated
|
|
from modules.pastafari2.models.tasks import Task, LogTask, TaskDb as TaskDbModel
|
|
from modules.pastafari2.libraries.configtask import config_task
|
|
from modules.pastafari2.models.pastafari2 import ServerGroup, ServerDbTask as ServerModel, UpdateServerScripts
|
|
from settings import config
|
|
#from modules.cuchulucp.libraries.tokenplugin import token_plugin
|
|
#from bottle import request, response
|
|
from paramecio2.libraries.responsesapi import ResponseItems, ListItem, StandardResponse
|
|
from paramecio2.libraries.db.simplequery import insert, select
|
|
from modules.pastafari2.libraries.task import Task as SSHTask
|
|
from paramecio2.libraries.db.extrafields.ipfield import IpField
|
|
from paramecio2.libraries.db.extrafields.arrayfield import ArrayField
|
|
from paramecio2.libraries.db.extrafields.parentfield import ParentField
|
|
from paramecio2.libraries.db.extrafields.datefield import DateField
|
|
from paramecio2.libraries.db.extrafields.dictfield import DictField
|
|
from paramecio2.libraries.db.extrafields.jsonfield import JsonValueField
|
|
from paramecio2.libraries.formsutils import check_form
|
|
from modules.pastafari2.libraries.authplugin import auth_plugin
|
|
from paramecio2.modules.admin.libraries.check_login_tries import check_login_tries
|
|
from paramecio2.libraries.datetime import now, format_local_strtime, timestamp_to_datetime, obtain_timestamp, TimeClass
|
|
from importlib import import_module, reload
|
|
#from paramecio2.libraries.sessionplugin import SessionPlugin, get_session
|
|
from paramecio2.libraries.keyutils import create_key_encrypt
|
|
from modules.pastafari2 import pastafari_app
|
|
from paramecio2.libraries.plugins import db
|
|
from flask import g
|
|
import socket
|
|
|
|
try:
|
|
import ujson as json
|
|
except:
|
|
import json
|
|
|
|
env=env_theme(__file__)
|
|
|
|
t=PTemplate(env)
|
|
|
|
gtext=PGetText(__file__)
|
|
|
|
_=gtext.gettext
|
|
|
|
api_key=''
|
|
|
|
if hasattr(config, 'cuchulu_api_key'):
|
|
api_key=config.cuchulu_api_key
|
|
|
|
if hasattr(config, 'cuchulu_ssh_private_key'):
|
|
config_task.ssh_private_key=config.cuchulu_ssh_private_key
|
|
|
|
if hasattr(config, 'cuchulu_ssh_private_key_password'):
|
|
config_task.ssh_private_key_password=config.cuchulu_ssh_private_key_password
|
|
|
|
if hasattr(config, 'cuchulu_ssh_public_key'):
|
|
config_task.ssh_public_key=config.cuchulu_ssh_public_key
|
|
|
|
class ServerGroups(ListItem):
|
|
|
|
group=corefields.CharField('group')
|
|
code_group=corefields.CharField('code_group')
|
|
|
|
class ResponseGroups(ResponseItems):
|
|
|
|
groups=ServerGroups()
|
|
|
|
class Server:
|
|
|
|
server_host=corefields.CharField('server_host')
|
|
server_username=corefields.CharField('server_username')
|
|
server_password=corefields.CharField('server_password')
|
|
group_id=corefields.IntegerField('group_id')
|
|
|
|
class UserAdminFields:
|
|
|
|
username=corefields.CharField('username')
|
|
password=corefields.CharField('password')
|
|
|
|
class TaskLogs(ListItem):
|
|
|
|
task_id=corefields.IntegerField('task_id')
|
|
server=IpField('server')
|
|
progress=corefields.DoubleField('progress')
|
|
no_progress=corefields.BooleanField('no_progress')
|
|
message=corefields.LongTextField('message')
|
|
error=corefields.BooleanField('error')
|
|
status=corefields.BooleanField('status')
|
|
|
|
code_error=corefields.BooleanField('code_error')
|
|
|
|
class ResponseLog(ResponseItems):
|
|
|
|
log=TaskLogs()
|
|
|
|
class TaskExec:
|
|
|
|
taskdb_id=corefields.IntegerField('taskdb_id')
|
|
server_id=corefields.IntegerField('server_id')
|
|
data=DictField('data', corefields.CharField('data'))
|
|
|
|
class TaskDb:
|
|
|
|
name=corefields.CharField('name')
|
|
path=corefields.CharField('path', 4096)
|
|
|
|
class TokenResponse(StandardResponse):
|
|
|
|
token=corefields.CharField('token')
|
|
|
|
groupdb=ServerGroup(None)
|
|
|
|
@pastafari_app.get('/api/v1/get_groups')
|
|
@db
|
|
def get_groups(tag='groups') -> ResponseGroups:
|
|
|
|
db=g.connection
|
|
|
|
arr_group=select(groupdb, db)
|
|
|
|
resp=ResponseGroups()
|
|
|
|
resp.groups=arr_group
|
|
|
|
return resp.toDict()
|
|
|
|
@pastafari_app.post('/api/v1/add_group')
|
|
@db
|
|
def add_group(post: Annotated[ServerGroups, 'Add group to the cuchulucp system'] = ServerGroups, tag='groups'):
|
|
|
|
db=g.connection
|
|
|
|
error=True
|
|
message=_('Cannot insert the new group')
|
|
code_error=1
|
|
|
|
json_post=request.get_json()
|
|
|
|
if json_post:
|
|
post=json_post
|
|
|
|
if insert(groupdb, db, post):
|
|
code_error=0
|
|
error=False
|
|
message=_('Success')
|
|
|
|
return {'error': error, 'message': message, 'code_error': code_error}
|
|
|
|
|
|
@pastafari_app.post('/api/v1/add_server')
|
|
@db
|
|
def add_server(post: Annotated[Server, 'Add server to the cuchulucp system'] = Server, tag='servers'):
|
|
|
|
db=g.connection
|
|
|
|
error_form={}
|
|
|
|
json_post=request.get_json()
|
|
|
|
if json_post:
|
|
|
|
server_host=json_post.get('server_host', '')
|
|
server_username=json_post.get('server_username', '')
|
|
server_password=json_post.get('server_password', '')
|
|
|
|
group_id=json_post.get('group_id', '')
|
|
private_key=config_task.ssh_private_key
|
|
password_key=config_task.ssh_private_key_password
|
|
public_key=config_task.ssh_public_key
|
|
remote_path=config_task.remote_path
|
|
task_id=0
|
|
ip=''
|
|
error=0
|
|
data={}
|
|
ssh_user=config_task.remote_user
|
|
ssh_port=config_task.port
|
|
|
|
try:
|
|
|
|
tmp_port=int(json_post.get('ssh_port', '22'))
|
|
|
|
ssh_port=tmp_port
|
|
|
|
except:
|
|
pass
|
|
ssh_port='22'
|
|
|
|
|
|
#make ping to server
|
|
|
|
if server_host=='':
|
|
error=1
|
|
error_form['#server_host_error']=_('Error: you need enter a valid hostname')
|
|
|
|
if server_username=='':
|
|
error=1
|
|
error_form['#server_username_error']=_('Error: you need enter a valid username for the server')
|
|
|
|
txt_error=''
|
|
|
|
try:
|
|
|
|
ip=socket.gethostbyname(server_host)
|
|
pass
|
|
except socket.error as err_msg:
|
|
error=1
|
|
error_form['#server_host_error']=_('Error: ')+err_msg.__str__()
|
|
|
|
if not error:
|
|
|
|
group_name=''
|
|
|
|
if group_id!='':
|
|
server_group=ServerGroup(db)
|
|
arr_group=server_group.set_conditions('WHERE id=%s', [group_id]).select_a_row_where()
|
|
group_name=arr_group['code_group']
|
|
|
|
|
|
data={'ssh_user': ssh_user, 'pub_key': public_key, 'hostname': server_host, 'ip': ip, 'group_id': group_id, 'group_name': group_name}
|
|
|
|
with SSHTask(server_host, db, remote_user=server_username, remote_password=server_password, private_key=private_key, password_key=password_key, remote_path=remote_path, task_id=task_id, data=data, port=ssh_port) as ssh_task:
|
|
if not ssh_task.prepare_connection():
|
|
error=1
|
|
txt_error=ssh_task.txt_error #_('Error: cannot connect to server')
|
|
error_form['#server_host_error']=txt_error #_('Error: cannot connect to server')
|
|
else:
|
|
# Prepare task for install monit
|
|
|
|
task=Task(db)
|
|
|
|
task_id=0
|
|
|
|
path_task='modules.cuchulucp.tasks.system.task'
|
|
|
|
if not task.run_task(ip, path_task, 'Add new server', 'add_new_server', 'Task for add a new server', user=server_username, password=server_password, where_sql_server='', url='', data=data, send_task=True, ssh_port=ssh_port):
|
|
|
|
error=1
|
|
error_form['#server_host_error']=_('Error: cannot execute the task ')+task.txt_error
|
|
txt_error=_('Error: cannot execute the task ')+task.txt_error
|
|
|
|
task_id=task.task_id
|
|
|
|
else:
|
|
error=1
|
|
txt_error=_('Error: json malformed')
|
|
error_form={}
|
|
task_id=0
|
|
|
|
return {'error': error, 'message': txt_error, 'error_form': error_form, 'task_id': task_id}
|
|
|
|
# Make task in server.
|
|
|
|
serverdb=ServerModel()
|
|
taskdb=TaskDbModel(None)
|
|
|
|
@pastafari_app.post('/api/v1/task')
|
|
@db
|
|
def make_task(post: Annotated[TaskExec, 'Task to execute'] = TaskExec, tag='tasks'):
|
|
|
|
db=g.connection
|
|
|
|
error=1
|
|
|
|
txt_error=_('Cannot execute the task')
|
|
error_form={}
|
|
|
|
task_id=0
|
|
|
|
json_post=request.get_json()
|
|
|
|
if json_post:
|
|
|
|
server_id=json_post.get('server_id', '0')
|
|
taskdb_id=json_post.get('taskdb_id', '0')
|
|
data=json_post.get('data', {})
|
|
|
|
if type(data) is not dict:
|
|
data={}
|
|
|
|
arr_server=select(serverdb, db, dict_fields=[], where_sql='WHERE id=%s', limit='', dict_values=[server_id])
|
|
|
|
if arr_server:
|
|
|
|
arr_task=select(taskdb, db, dict_fields=[], where_sql='where id=%s', limit='', dict_values=[taskdb_id])
|
|
|
|
task_file=arr_task[0]['path']
|
|
|
|
path_task=task_file
|
|
|
|
task_execute=import_module(task_file)
|
|
|
|
if config.reloader:
|
|
reload(task_execute)
|
|
|
|
user=config_task.remote_user
|
|
|
|
task_first=task_execute.ServerTask('', db, remote_user=user, remote_password='', private_key=config_task.ssh_private_key, password_key='', remote_path='cuchulucp', task_id=0, data=data)
|
|
|
|
server_host=arr_server[0]['ip']
|
|
|
|
ssh_key_priv=config_task.ssh_private_key
|
|
ssh_key_password=config_task.ssh_private_key_password
|
|
|
|
where_sql=''
|
|
|
|
task=Task(db)
|
|
|
|
# Check post
|
|
|
|
check_form_done=True
|
|
|
|
if hasattr(task_first, 'check_form'):
|
|
check_form_done=task_first.check_form(data)
|
|
|
|
if check_form_done:
|
|
|
|
if not task.run_task(server_host, path_task, task_first.name_task, task_first.codename_task, task_first.description_task, user=user, password='', where_sql_server=where_sql, ssh_key_priv=ssh_key_priv, ssh_key_password=ssh_key_password, url=task_first.url_return, data=data, send_task=True):
|
|
|
|
error=1
|
|
error_form['#server_host_error']=_('Error: cannot execute the task')
|
|
txt_error=task.txt_error
|
|
else:
|
|
error=0
|
|
txt_error=_('Success')
|
|
task_id=task.task_id
|
|
|
|
else:
|
|
error=1
|
|
|
|
for k, form in task_first.arr_form.items():
|
|
if form.error:
|
|
error_form[k]=form.txt_error
|
|
|
|
txt_error=task.txt_error
|
|
|
|
|
|
else:
|
|
txt_error=_('Error: server not exists')
|
|
|
|
else:
|
|
txt_error=_('Error: json malformed')
|
|
|
|
return {'error': error, 'message': txt_error, 'error_form': error_form, 'task_id': task_id}
|
|
|
|
@pastafari_app.get('/api/v1/get_progress_task/<int:task_id>/<int:position>')
|
|
@db
|
|
def get_progress_task(task_id, position=0, tag='tasks') -> ResponseLog:
|
|
|
|
db=g.connection
|
|
|
|
task=Task(db)
|
|
logtask=LogTask(db)
|
|
|
|
arr_task=task.select_a_row(task_id)
|
|
|
|
arr_rows={'wait': 1}
|
|
|
|
if arr_task:
|
|
|
|
logtask.set_limit([position, 50])
|
|
|
|
logtask.set_order({'id': 0})
|
|
|
|
logtask.conditions=['WHERE task_id=%s', [task_id]]
|
|
|
|
server=request.query.get('server', '')
|
|
|
|
if server!='':
|
|
logtask.conditions=['WHERE task_id=%s', [task_id]]
|
|
|
|
logtask.yes_reset_conditions=False
|
|
|
|
c=0
|
|
|
|
arr_rows=[]
|
|
|
|
with logtask.select([], True) as cursor:
|
|
for arr_row in cursor:
|
|
arr_rows.append(arr_row)
|
|
c+=1
|
|
|
|
if c==0:
|
|
arr_rows=[]
|
|
|
|
c_error=logtask.set_conditions('WHERE task_id=%s and logtask.error=%s and logtask.status=%s', [task_id, 1, 1]).select_count()
|
|
|
|
if c_error==0:
|
|
|
|
arr_rows={'wait': 1}
|
|
else:
|
|
logtask.limit=''
|
|
|
|
with logtask.set_conditions('WHERE task_id=%s and logtask.error=%s and logtask.status=%s', [task_id, 1, 1]).select([], True) as cursor:
|
|
for arr_row in cursor:
|
|
arr_rows.append(arr_row)
|
|
|
|
else:
|
|
|
|
arr_rows=[{'task_id': task_id, 'progress': 100, 'message': 'Error: no exists task', 'error': 1, 'status': 1}]
|
|
|
|
|
|
return { "code_error": 1, "error": 0, "log": arr_rows, "message": _('Successfully')}
|
|
|
|
|
|
# Add task to db for use with api, for not send python paths directly.
|
|
|
|
@pastafari_app.post('/api/v1/add_task_db')
|
|
@db
|
|
def add_task_db(post: Annotated[TaskDb, 'Add a new task to db'] = TaskDb, tag='tasks') -> StandardResponse:
|
|
|
|
db=g.connection
|
|
|
|
taskdb.conn(db)
|
|
|
|
taskdb.create_forms()
|
|
|
|
error=1
|
|
txt_error='Cannot insert the task'
|
|
error_form={}
|
|
taskdb_id=0
|
|
|
|
post=request.get_json()
|
|
|
|
if post:
|
|
|
|
if taskdb.insert(post):
|
|
error=0
|
|
txt_error=_('Success')
|
|
taskdb_id=taskdb.insert_id()
|
|
else:
|
|
|
|
error_form=taskdb.collect_errors()
|
|
|
|
else:
|
|
txt_error=_('Error: json malformed')
|
|
|
|
return {'error': error, 'message': txt_error, 'error_form': error_form, 'taskdb_id': taskdb_id}
|
|
|
|
|
|
@pastafari_app.post('/api/v1/login')
|
|
@db
|
|
def check_login_admin(post: Annotated[UserAdminFields, 'Login']=UserAdminFields, tag='login') -> TokenResponse:
|
|
|
|
db=g.connection
|
|
|
|
usermodel=UserAdmin(db)
|
|
|
|
error=1
|
|
|
|
message=_('Invalid user and password')
|
|
|
|
no_login=check_login_tries(request, db)
|
|
|
|
code_error=0
|
|
|
|
error_form={}
|
|
|
|
error_form['no_login']=no_login
|
|
|
|
json_post=request.get_json()
|
|
|
|
if json_post:
|
|
|
|
username=json_post.get('username')
|
|
password=json_post.get('password')
|
|
|
|
token_auth=''
|
|
|
|
if username!='' and password!='' and not no_login:
|
|
|
|
with db.query('select * from useradmin WHERE username=%s', [username]) as cursor:
|
|
result=cursor.fetchone()
|
|
|
|
if result:
|
|
|
|
if usermodel.fields['password'].verify(password, result['password']):
|
|
|
|
now_str=now()
|
|
date_now=format_local_strtime('YYYY-MM-DD HH:mm:ss', now_str)
|
|
|
|
with db.query('select * from usertoken WHERE user_id=%s', [result['id']]) as cursor:
|
|
|
|
arr_token=cursor.fetchone()
|
|
|
|
if not arr_token:
|
|
#print('insert token')
|
|
token_auth=create_key_encrypt(48)
|
|
|
|
if db.query('insert into usertoken (user_id, token, last_login) VALUES (%s, %s, %s)', [result['id'], token_auth, date_now]):
|
|
error=0
|
|
message=_('Success')
|
|
|
|
else:
|
|
token_auth=arr_token['token']
|
|
error=0
|
|
message=_('Success')
|
|
|
|
else:
|
|
message=_('Error: json malformed')
|
|
|
|
return {'error': error, 'message': message, 'code_error': code_error, 'error_form': error_form, 'token': token_auth}
|