Uncategorized

Real-time Capture and Display of Ansible Output Logs in HTML via Flask and Python


I have a question; I’m experimenting with an Ansible playbook that I execute from a Flask application, and I want to capture the output logs in real-time and send them to my HTML using Socket.IO. I’ve tried things like setting quiet=False and playing with runner.events, but haven’t achieved any results he only send the logs after the playbook is done. I’m completely new to the Ansible Python story. Thx

#
# Ansible code
# 
@app.route('/generate_ansible_inventory', methods=['GET'])
def generate_ansible_inventory():
    # Load data from TinyDB
    vm_data_list = load_vm_from_db()

    # Create an empty inventory dictionary
    inventory = {"all": {"hosts": {}, "vars": {}}}

    # Loop through VMs in the TinyDB
    for vm_data in vm_data_list:
        # Add an inventory host
        inventory["all"]["hosts"][vm_data["vm_name"]] = {
            "ansible_host": vm_data["vm_ipv4_address"],
            "ansible_user": "bart",
            "ansible_ssh_pass": "bart",
            "ansible_become_pass": "bart"
        }

    # Save the inventory dictionary to a json file in the Ansible directory
    with open('ansible/inventory.json', 'w') as file:
        json.dump(inventory, file, indent=4)

    return jsonify(inventory)

# Run Ansible playbook asynchronously
def run_ansible_playbook_async(playbook_path, inventory_path):
    try:
        # Read the inventory from the JSON file
        with open(inventory_path, 'r') as file:
            inventory = json.load(file)

        # Run the playbook
        runner = ansible_runner.run(
            playbook=playbook_path,
            inventory=inventory,
            quiet=False,  # Set quiet to False to capture logs
        )

        # Emit each log line to connected clients
        for event in runner.events:
            if event['event'] == 'runner_on_ok' and 'stdout' in event['stdout']:
                socketio.emit('ansible_output', {'log_message': event['stdout']['stdout_lines'][0]})
            elif event['event'] == 'runner_on_failed' and 'stderr' in event['stdout']:
                socketio.emit('ansible_output', {'log_message': event['stdout']['stdout_lines'][0]})

        # Print the output
        print("Playbook run status:", runner.status)
        print("Playbook run stats:", runner.stats)

    except Exception as e:
        print("Error running the Ansible playbook:", e)


# Route for running Ansible playbook
@app.route('/run_ansible_playbook', methods=['GET'])
def run_ansible_playbook():
    try:
        # Define playbook and inventory paths
        playbook_path = os.path.join(os.getcwd(), 'ansible', 'playbook.yml')
        inventory_path = os.path.join(os.getcwd(), 'ansible', 'inventory.json')

        # Start a new thread for running Ansible playbook asynchronously
        ansible_thread = Thread(target=run_ansible_playbook_async, args=(playbook_path, inventory_path))
        ansible_thread.start()

        return jsonify({"status": "Ansible playbook execution started in the background"})

    except Exception as e:
        return jsonify({"status": f"Error running Ansible playbook: {str(e)}"})

@app.route('/ansible_logs', methods=['GET'])
def ansible_logs():
    return render_template('ansible_logs.html')



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *