XCP-ng
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    XCP Pulse collects XCP-ng and Xen Orchestra logs

    Scheduled Pinned Locked Moved Xen Orchestra
    2 Posts 1 Posters 39 Views 1 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • acebmxerA Online
      acebmxer
      last edited by

      While this project is more for myself it is open to others to use. Please use at your own risk. As always review the code before using in a production environment. Please leave any feedback or suggestions. https://github.com/acebmxer/xcp_pulse

      XCP Pulse collects XCP-ng and Xen Orchestra logs, bundles them for download, analyses them, and reports findings — for your own troubleshooting or to attach to a Vates support ticket. Everything goes through the Xen Orchestra REST API — nothing is installed on your hosts, and it only ever reads.

      It runs as a container with a web UI. Being built in stages, and v0.5.1 is where it is today — so this is an early look rather than a finished tool. Log collection itself is the next big piece.

      What works today

      Version What it does
      v0.1.0 Container, login, sessions, healthcheck
      v0.2.0 Connect to Xen Orchestra — URL and API token, token encrypted at rest, "Test connection"
      v0.3.0 Pools and hosts listed on the dashboard, grouped by pool
      v0.4.0 Background jobs with live progress and history, and stored results
      v0.5.0 Redaction — masks addresses, tokens and credentials out of log text, with a preview page
      v0.5.1 Each redaction rule can be switched on or off

      Redaction came before any download button on purpose. A real log bundle is full of internal addresses, usernames and session tokens, and the point of the download is sending that file to Vates — shipping collection first would have meant a headline feature that leaks credentials. One real xensource.log I tested against had 8,359 lines matching password, secret or session patterns.

      What is coming

      • Collect the full log bundle per host, as a background job, redacted, with a download. Measured on my own XCP-ng 8.3 pool: about 433 MB and 100 seconds per host, 603 files.
      • Collect individual categories — XAPI, storage, audit, security, kernel and the rest — pulled out of the cached bundle instead of downloading again. Current logs only comes to roughly 35 MB instead of 433 MB.
      • Date ranges — of that 433 MB, 418 MB is rotated history, so asking for the last three days is a large saving.
      • Findings — failed tasks, alarms, missing patches, storage errors, HA fencing, clock skew, with the evidence behind each one.
      • A Vates support package — one file with the redacted bundle, findings and a manifest of what was masked.
      • Multiple users, docs in the web UI, and self-update.

      Full list with status: https://github.com/acebmxer/xcp_pulse/blob/main/docs/roadmap.md

      Quick start

      No clone and no build — the image is published to GHCR, so the compose file and an env file are the whole deployment:

      mkdir xcp-pulse && cd xcp-pulse
      curl -o compose.yaml https://raw.githubusercontent.com/acebmxer/xcp_pulse/main/compose.yaml.example
      curl -o xcp-pulse.env https://raw.githubusercontent.com/acebmxer/xcp_pulse/main/xcp-pulse.env.example
      

      Generate the admin password hash — XCP Pulse stores a hash, never a password, and refuses to start without one:

      docker compose run --rm xcp-pulse python -m app.hashpw
      

      Paste the printed XCP_PULSE_ADMIN_PASSWORD_HASH=... line into xcp-pulse.env, then:

      docker compose up -d
      

      Open http://localhost:8080 and sign in with admin and the password you chose.

      The env file has to be called xcp-pulse.env and not .env — compose treats a file of that name as its own variable source and mangles the Argon2 hash.

      A note on the XO account

      Inventory and API-based findings work fine with a Read only role. Downloading logs does not — /hosts/{id}/logs.tgz requires export:logs on host, and on the instance I measured (XO CE, @xen-orchestra/rest-api 0.39.0) that privilege was not in the grantable catalogue at all. The only role that could download logs was Administrator.

      So for log collection you currently need an admin token. XCP Pulse reads the privilege catalogue from your instance and tells you what it can actually grant, rather than assuming — and asks which account type you gave it so it can name the missing privilege instead of showing a bare 403.

      Security

      XCP Pulse holds a token that can read every log on your pool, and stores files containing session tokens and internal network topology. Run it on a trusted management network behind a reverse proxy — the compose file binds to 127.0.0.1 by default for that reason. Not exposed to the internet.

      MIT licensed. This is an independent tool and is not affiliated with or endorsed by Vates.

      Screenshot_20260907_091915-1.png
      Screenshot_20260907_092108.png
      Screenshot_20260907_092146.png

      1 Reply Last reply Reply Quote 3
      • acebmxerA Online
        acebmxer
        last edited by

        v0.6.0 — log collection is in. This was the piece the first post said was next, and it works end to end now.

        A new Collect page runs a per-host collection as a background job: it pulls logs.tgz and the XAPI audit trail from Xen Orchestra, keeps the raw copies, and produces a redacted copy of each. On my own XCP-ng 8.3 pool that came to 434 MiB for the bundle and 769 MiB for the audit trail, 2.3 GiB stored across the five files, with 2,542,805 values masked — almost all of them session tokens.

        The download is streamed a megabyte at a time and never held in memory, and every chunk is a cancellation point, so Cancel actually stops a transfer rather than waiting it out. A failed or cancelled download deletes its partial file instead of leaving a half-written bundle sitting there looking like a collection.

        Both copies are kept and marked redacted — safe to send or raw — unmasked. Redaction is lossy, and the raw copy is the only thing that can answer "what did that used to say?" afterwards. Each collection writes the same redaction report the preview page produces, so you can see which rules fired — and which were switched off — before anything leaves the box. In the screenshot I had IPv4, MAC, UUIDs and hostnames turned off, and they show as off rather than as zero hits. That is deliberate: a partly-masked bundle should be obvious before you attach it to a ticket.

        There is also a retention policy. The newest n collections are kept whatever their age, and only what is left is judged on age — a long gap in collecting can't empty the store. It shows you what a cleanup would delete and how much space that returns before you press the button.

        Expect bugs. This is still very much a work in progress and it has only ever run against my own pool. If you try it in a different environment, assume things will break — please tell me what did. Known issues right now:

        • The red "This connection uses a restricted account" warning on the Collect page shows for every connection, including an administrator one. It is a wrong condition in the template, not a real permission check — ignore it if your account is admin. The screenshot below has it, over a collection that succeeded.
        • The Collect page says to expect "433 MB and 100 seconds per host". The 100 seconds is the download only; a full collection also fetches the audit trail and redacts both copies, which took 203 seconds on my pool. Budget three to four minutes.

        Two more things worth flagging if you try this.

        logs.tgz sends no Content-Length, so a reverse proxy that buffers will happily hand you a truncated archive with HTTP 200. Mine did. It now detects that and reports the bundle as cut short rather than as a protocol error, and repacks whatever did arrive instead of throwing the lot away. If you are behind Nginx Proxy Manager, proxy_buffering off; and proxy_max_temp_file_size 0; are what fixed the stall for me.

        The account requirement from the first post has not changed — the log download needs export:logs on host, and on the instance I measured that is only reachable via Administrator. Inventory still works fine on Read only.

        Next up: individual log categories pulled out of the cached bundle (~35 MB instead of 434 MiB), date ranges, and then findings.

        https://github.com/acebmxer/xcp_pulse

        Screenshot_20260907_160937.png

        1 Reply Last reply Reply Quote 0

        Hello! It looks like you're interested in this conversation, but you don't have an account yet.

        Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

        With your input, this post could be even better 💗

        Register Login
        • First post
          Last post