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, request 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 @auth_plugin def get_groups(tag='groups', bearer=True) -> 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 @auth_plugin def add_group(post: Annotated[ServerGroups, 'Add group to the cuchulucp system'] = ServerGroups, tag='groups', bearer=True): 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=0 message=_('Success') return {'error': error, 'message': message, 'code_error': code_error} @pastafari_app.post('/api/v1/add_server') @db @auth_plugin def add_server(post: Annotated[Server, 'Add server to the cuchulucp system'] = Server, tag='servers', bearer=True): 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' path_task='modules.pastafari2.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 @auth_plugin def make_task(post: Annotated[TaskExec, 'Task to execute'] = TaskExec, tag='tasks', bearer=True): 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//') @db @auth_plugin def get_progress_task(task_id, position=0, tag='tasks', bearer=True) -> 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 @auth_plugin def add_task_db(post: Annotated[TaskDb, 'Add a new task to db'] = TaskDb, tag='tasks', bearer=True) -> 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}