def worker(job: ExportdJob, request_user: UserModel): from flask import make_response as make_res from cmdb.exportd.exporter_base import ExportdManagerBase from cmdb.event_management.event import Event try: event = Event( "cmdb.exportd.run_manual", { "id": job.get_public_id(), "user_id": request_user.get_public_id(), "event": 'manuel' }) content = ExportdManagerBase(job, object_manager, log_manager, event).execute( request_user.public_id, request_user.get_display_name(), False) response = make_res(content.data, content.status) response.headers['Content-Type'] = '%s; charset=%s' % ( content.mimetype, content.charset) return response except Exception as err: LOGGER.error(err) return abort(404)
def delete_job(public_id: int, request_user: UserModel): try: try: job_instance = exportd_manager.get_job(public_id) log_params = { 'job_id': job_instance.get_public_id(), 'state': True, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'event': LogAction.DELETE.name, 'message': '', } log_manager.insert_log(action=LogAction.DELETE, log_type=ExportdJobLog.__name__, **log_params) except (ExportdJobManagerGetError, LogManagerInsertError) as err: LOGGER.error(err) return abort(404) ack = exportd_manager.delete_job(public_id=public_id, request_user=request_user) except ExportdJobManagerDeleteError: return abort(400) except CMDBError: return abort(500) resp = make_response(ack) return resp
def delete_object(public_id: int, request_user: UserModel): try: current_object_instance = object_manager.get_object(public_id) current_type_instance = object_manager.get_type( current_object_instance.get_type_id()) current_object_render_result = CmdbRender( object_instance=current_object_instance, object_manager=object_manager, type_instance=current_type_instance, render_user=request_user).result() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) try: ack = object_manager.delete_object( public_id=public_id, user=request_user, permission=AccessControlPermission.DELETE) except ObjectManagerGetError as err: return abort(400, err.message) except AccessDeniedError as err: return abort(403, err.message) except ObjectDeleteError: return abort(400) except CMDBError: return abort(500) try: # generate log log_data = { 'object_id': public_id, 'version': current_object_render_result.object_information['version'], 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': 'Object was deleted', 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8') } log_manager.insert(action=LogAction.DELETE, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) resp = make_response(ack) return resp
def add_job(request_user: UserModel): from bson import json_util add_data_dump = json.dumps(request.json) try: new_job_data = json.loads(add_data_dump, object_hook=json_util.object_hook) new_job_data['public_id'] = exportd_manager.get_new_id( ExportdJob.COLLECTION) new_job_data['last_execute_date'] = datetime.utcnow() new_job_data['author_id'] = request_user.get_public_id() new_job_data['author_name'] = request_user.get_display_name() new_job_data['state'] = ExecuteState.SUCCESSFUL.name except TypeError as e: LOGGER.warning(e) abort(400) try: job_instance = ExportdJob(**new_job_data) except CMDBError as e: LOGGER.debug(e) return abort(400) try: ack = exportd_manager.insert_job(job_instance) except ExportdJobManagerInsertError: return abort(500) # Generate new insert log try: log_params = { 'job_id': job_instance.get_public_id(), 'state': True, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'event': LogAction.CREATE.name, 'message': '', } log_manager.insert_log(action=LogAction.CREATE, log_type=ExportdJobLog.__name__, **log_params) except LogManagerInsertError as err: LOGGER.error(err) resp = make_response(ack) return resp
def update_job(request_user: UserModel): from bson import json_util add_data_dump = json.dumps(request.json) new_job_data = None try: new_job_data = json.loads(add_data_dump, object_hook=json_util.object_hook) except TypeError as e: LOGGER.warning(e) abort(400) try: state = new_job_data["state"] update_job_instance = ExportdJob(**new_job_data) except CMDBError: return abort(400) try: exportd_manager.update_job(update_job_instance, request_user, False) except ExportdJobManagerUpdateError: return abort(500) # Generate new insert log if state not in ExecuteState.RUNNING.name: try: log_params = { 'job_id': update_job_instance.get_public_id(), 'state': True, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'event': LogAction.EDIT.name, 'message': '', } log_manager.insert_log(action=LogAction.EDIT, log_type=ExportdJobLog.__name__, **log_params) except LogManagerInsertError as err: LOGGER.error(err) resp = make_response(update_job_instance) return resp
def update_object_state(public_id: int, request_user: UserModel): if isinstance(request.json, bool): state = request.json else: return abort(400) try: founded_object = object_manager.get_object(public_id=public_id) except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) if founded_object.active == state: return make_response(False, 204) try: founded_object.active = state update_ack = object_manager.update_object( founded_object, user=request_user, permission=AccessControlPermission.READ) except AccessDeniedError as err: return abort(403, err.message) except ObjectManagerUpdateError as err: LOGGER.error(err) return abort(500) # get current object state try: current_type_instance = object_manager.get_type( founded_object.get_type_id()) current_object_render_result = CmdbRender( object_instance=founded_object, object_manager=object_manager, type_instance=current_type_instance, render_user=request_user).result() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) try: # generate log change = {'old': not state, 'new': state} log_data = { 'object_id': public_id, 'version': founded_object.version, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8'), 'comment': 'Active status has changed', 'changes': change, } log_manager.insert(action=LogAction.ACTIVE_CHANGE, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) return make_response(update_ack)
def delete_many_objects(public_ids, request_user: UserModel): try: ids = [] operator_in = {'$in': []} filter_public_ids = {'public_id': {}} for v in public_ids.split(","): try: ids.append(int(v)) except (ValueError, TypeError): return abort(400) operator_in.update({'$in': ids}) filter_public_ids.update({'public_id': operator_in}) ack = [] objects = object_manager.get_objects_by(**filter_public_ids) for current_object_instance in objects: try: current_type_instance = object_manager.get_type( current_object_instance.get_type_id()) current_object_render_result = CmdbRender( object_instance=current_object_instance, object_manager=object_manager, type_instance=current_type_instance, render_user=request_user).result() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) try: ack.append( object_manager.delete_object( public_id=current_object_instance.get_public_id(), user=request_user, permission=AccessControlPermission.DELETE)) except ObjectDeleteError: return abort(400) except AccessDeniedError as err: return abort(403, err.message) except CMDBError: return abort(500) try: # generate log log_data = { 'object_id': current_object_instance.get_public_id(), 'version': current_object_render_result.object_information['version'], 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': 'Object was deleted', 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8') } log_manager.insert(action=LogAction.DELETE, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) resp = make_response({'successfully': ack}) return resp except ObjectDeleteError as e: return jsonify(message='Delete Error', error=e.message) except CMDBError: return abort(500)
def update_object(public_id: int, request_user: UserModel): object_ids = request.args.getlist('objectIDs') if len(object_ids) > 0: object_ids = list(map(int, object_ids)) else: object_ids = [public_id] update_ack = None for obj_id in object_ids: # get current object state try: current_object_instance = object_manager.get_object(obj_id) current_type_instance = object_manager.get_type( current_object_instance.get_type_id()) current_object_render_result = CmdbRender( object_instance=current_object_instance, type_instance=current_type_instance, render_user=request_user, object_manager=object_manager, ref_render=True).result() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) update_comment = '' # load put data try: # get data as str add_data_dump = json.dumps(request.json) # convert into python dict put_data = json.loads(add_data_dump, object_hook=object_hook) # check for comment try: put_data['public_id'] = obj_id put_data[ 'creation_time'] = current_object_instance.creation_time put_data['author_id'] = current_object_instance.author_id old_fields = list( map( lambda x: {k: v for k, v in x.items() if k in ['name', 'value']}, current_type_instance.get_fields())) new_fields = put_data['fields'] for item in new_fields: for old in old_fields: if item['name'] == old['name']: old['value'] = item['value'] put_data['fields'] = old_fields if 'active' not in put_data: put_data['active'] = current_object_instance.active if 'version' not in put_data: put_data['version'] = current_object_instance.version update_comment = put_data['comment'] del put_data['comment'] except (KeyError, IndexError, ValueError): update_comment = '' except TypeError as e: LOGGER.warning(e) return abort(400) # update edit time put_data['last_edit_time'] = datetime.now(timezone.utc) try: update_object_instance = CmdbObject(**put_data) except ObjectManagerUpdateError as err: LOGGER.error(err) return abort(400) # calc version changes = current_object_instance / update_object_instance if len(changes['new']) == 1: update_object_instance.update_version( update_object_instance.VERSIONING_PATCH) elif len(changes['new']) == len(update_object_instance.fields): update_object_instance.update_version( update_object_instance.VERSIONING_MAJOR) elif len(changes['new']) > (len(update_object_instance.fields) / 2): update_object_instance.update_version( update_object_instance.VERSIONING_MINOR) else: update_object_instance.update_version( update_object_instance.VERSIONING_PATCH) # insert object try: update_ack = object_manager.update_object( update_object_instance, request_user, AccessControlPermission.UPDATE) except ManagerGetError as err: return abort(404, err.message) except AccessDeniedError as err: return abort(403, err.message) except CMDBError as e: LOGGER.warning(e) return abort(500) try: # generate log log_data = { 'object_id': obj_id, 'version': current_object_render_result.object_information['version'], 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': update_comment, 'changes': changes, 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8') } log_manager.insert(action=LogAction.EDIT, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) return make_response(update_ack)
def insert_object(request_user: UserModel): from bson import json_util add_data_dump = json.dumps(request.json) try: new_object_data = json.loads(add_data_dump, object_hook=json_util.object_hook) if not 'public_id' in new_object_data: new_object_data['public_id'] = object_manager.get_new_id( CmdbObject.COLLECTION) if not 'active' in new_object_data: new_object_data['active'] = True new_object_data['creation_time'] = datetime.now(timezone.utc) new_object_data['views'] = 0 new_object_data['version'] = '1.0.0' # default init version except TypeError as e: LOGGER.warning(e) abort(400) try: new_object_id = object_manager.insert_object( new_object_data, user=request_user, permission=AccessControlPermission.CREATE) except ManagerGetError as err: return abort(404, err.message) except AccessDeniedError as err: return abort(403, err.message) except ObjectInsertError as err: LOGGER.error(err) return abort(400, str(err)) # get current object state try: current_type_instance = object_manager.get_type( new_object_data['type_id']) current_object = object_manager.get_object(new_object_id) current_object_render_result = CmdbRender( object_instance=current_object, object_manager=object_manager, type_instance=current_type_instance, render_user=request_user).result() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) # Generate new insert log try: log_params = { 'object_id': new_object_id, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': 'Object was created', 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8'), 'version': current_object.version } log_ack = log_manager.insert(action=LogAction.CREATE, log_type=CmdbObjectLog.__name__, **log_params) except LogManagerInsertError as err: LOGGER.error(err) resp = make_response(new_object_id) return resp
def update_object(public_id: int, data: dict, request_user: UserModel): object_ids = request.args.getlist('objectIDs') if len(object_ids) > 0: object_ids = list(map(int, object_ids)) else: object_ids = [public_id] manager = ObjectManager(database_manager=current_app.database_manager, event_queue=current_app.event_queue) results: [dict] = [] failed = [] for obj_id in object_ids: # deep copy active_state = request.get_json().get('active', None) new_data = copy.deepcopy(data) try: current_object_instance = manager.get( obj_id, user=request_user, permission=AccessControlPermission.READ) current_type_instance = type_manager.get( current_object_instance.get_type_id()) current_object_render_result = CmdbRender( object_instance=current_object_instance, object_manager=object_manager, type_instance=current_type_instance, render_user=request_user).result() update_comment = '' try: # check for comment new_data['public_id'] = obj_id new_data[ 'creation_time'] = current_object_instance.creation_time new_data['author_id'] = current_object_instance.author_id new_data[ 'active'] = active_state if active_state else current_object_instance.active if 'version' not in data: new_data['version'] = current_object_instance.version old_fields = list( map( lambda x: {k: v for k, v in x.items() if k in ['name', 'value']}, current_object_render_result.fields)) new_fields = data['fields'] for item in new_fields: for old in old_fields: if item['name'] == old['name']: old['value'] = item['value'] new_data['fields'] = old_fields update_comment = data['comment'] del new_data['comment'] except (KeyError, IndexError, ValueError): update_comment = '' except TypeError as err: LOGGER.error( f'Error: {str(err.args)} Object: {json.dumps(new_data, default=default)}' ) failed.append( ResponseFailedMessage(error_message=str(err.args), status=400, public_id=obj_id, obj=new_data).to_dict()) continue # update edit time new_data['last_edit_time'] = datetime.now(timezone.utc) new_data['editor_id'] = request_user.public_id update_object_instance = CmdbObject( **json.loads(json.dumps(new_data, default=json_util.default), object_hook=object_hook)) # calc version changes = current_object_instance / update_object_instance if len(changes['new']) == 1: new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_PATCH) elif len(changes['new']) == len(update_object_instance.fields): new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_MAJOR) elif len( changes['new']) > (len(update_object_instance.fields) / 2): new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_MINOR) else: new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_PATCH) manager.update(obj_id, new_data, request_user, AccessControlPermission.UPDATE) results.append(new_data) # Generate log entry try: log_data = { 'object_id': obj_id, 'version': update_object_instance.get_version(), 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': update_comment, 'changes': changes, 'render_state': json.dumps(update_object_instance, default=default).encode('UTF-8') } log_manager.insert(action=LogAction.EDIT, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) except AccessDeniedError as err: LOGGER.error(err) return abort(403) except ObjectManagerGetError as err: LOGGER.error(err) failed.append( ResponseFailedMessage(error_message=err.message, status=400, public_id=obj_id, obj=new_data).to_dict()) continue except (ManagerGetError, ObjectManagerUpdateError) as err: LOGGER.error(err) failed.append( ResponseFailedMessage(error_message=err.message, status=404, public_id=obj_id, obj=new_data).to_dict()) continue except (CMDBError, RenderError) as e: LOGGER.warning(e) failed.append( ResponseFailedMessage(error_message=str(e.__repr__), status=500, public_id=obj_id, obj=new_data).to_dict()) continue api_response = UpdateMultiResponse(results=results, failed=failed, url=request.url, model=CmdbObject.MODEL) return api_response.make_response()
def import_objects(request_user: UserModel): # Check if file exists if not request.files: return abort(400, 'No import file was provided') request_file: FileStorage = get_file_in_request('file', request.files) filename = secure_filename(request_file.filename) working_file = f'/tmp/{filename}' request_file.save(working_file) # Load file format file_format = request.form.get('file_format', None) # Load parser config parser_config: dict = get_element_from_data_request('parser_config', request) or {} if parser_config == {}: LOGGER.info('No parser config was provided - using default parser config') # Check for importer config importer_config_request: dict = get_element_from_data_request('importer_config', request) or None if not importer_config_request: return abort(400, 'No import config was provided') # Check if type exists try: type_manager = TypeManager(database_manager=current_app.database_manager) type_ = type_manager.get(importer_config_request.get('type_id')) if not type_.active: raise AccessDeniedError(f'Objects cannot be created because type `{type_.name}` is deactivated.') verify_import_access(user=request_user, _type=type_, _manager=type_manager) except ObjectManagerGetError as err: return abort(404, err.message) except AccessDeniedError as err: return abort(403, err.message) # Load parser try: parser_class = load_parser_class('object', file_format) except ParserLoadError as ple: return abort(406, ple.message) parser = parser_class(parser_config) LOGGER.info(f'Parser {parser_class} was loaded') # Load importer config try: importer_config_class = load_importer_config_class('object', file_format) except ImporterLoadError as ile: return abort(406, ile.message) importer_config = importer_config_class(**importer_config_request) LOGGER.debug(importer_config_request) # Load importer try: importer_class = load_importer_class('object', file_format) except ImporterLoadError as ile: return abort(406, ile.message) importer = importer_class(working_file, importer_config, parser, object_manager, request_user) LOGGER.info(f'Importer {importer_class} was loaded') try: import_response: ImporterObjectResponse = importer.start_import() except ImportRuntimeError as ire: LOGGER.error(f'Error while importing objects: {ire.message}') return abort(500, ire.message) except AccessDeniedError as err: return abort(403, err.message) # close request file request_file.close() # log all successful imports for message in import_response.success_imports: try: # get object state of every imported object current_type_instance = object_manager.get_type(importer_config_request.get('type_id')) current_object = object_manager.get_object(message.public_id) current_object_render_result = CmdbRender(object_instance=current_object, type_instance=current_type_instance, render_user=request_user, object_manager=object_manager).result() # insert object create log log_params = { 'object_id': message.public_id, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': 'Object was imported', 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8'), 'version': current_object.version } log_manager.insert(action=LogAction.CREATE, log_type=CmdbObjectLog.__name__, **log_params) except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) except LogManagerInsertError as err: LOGGER.error(err) return make_response(import_response)