Skip to content

Commit

Permalink
feat(xo-server/rest-api): export host audit and system logs
Browse files Browse the repository at this point in the history
See #3968
  • Loading branch information
julien-f committed Sep 26, 2023
1 parent a30d962 commit d384c74
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- [Netbox] Don't delete VMs that have been created manually in XO-synced cluster [Forum#7639](https://xcp-ng.org/forum/topic/7639) (PR [#7008](https://github.com/vatesfr/xen-orchestra/pull/7008))
- [Kubernetes] *Search domains* field is now optional [#7028](https://github.com/vatesfr/xen-orchestra/pull/7028)
- [Patches] Support new XenServer Updates system. See [our documentation](https://xen-orchestra.com/docs/updater.html#xenserver-updates). (PR [#7044](https://github.com/vatesfr/xen-orchestra/pull/7044))
- [REST API] Hosts' audit and system logs can be downloaded [#3968](https://github.com/vatesfr/xen-orchestra/issues/3968) (PR [#7048](https://github.com/vatesfr/xen-orchestra/pull/7048))

### Bug fixes

Expand Down
36 changes: 35 additions & 1 deletion packages/xo-server/src/xo-mixins/rest-api.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { asyncEach } from '@vates/async-each'
import { createGzip } from 'node:zlib'
import { every } from '@vates/predicates'
import { ifDef } from '@xen-orchestra/defined'
import { featureUnauthorized, invalidCredentials, noSuchObject } from 'xo-common/api-errors.js'
Expand All @@ -12,6 +13,25 @@ import { VDI_FORMAT_RAW, VDI_FORMAT_VHD } from '@xen-orchestra/xapi'
const { join } = path.posix
const noop = Function.prototype

function compressMaybe(req, res) {
let transform

const acceptEncoding = req.headers['accept-encoding']
if (
acceptEncoding !== undefined &&
acceptEncoding.split(',').some(_ => _.split(';')[0].trim().toLocaleLowerCase() === 'gzip')
) {
res.setHeader('content-encoding', 'gzip')
transform = createGzip()
}

if (transform !== undefined) {
pipeline(transform, res).catch(noop)
return transform
}
return res
}

async function* makeObjectsStream(iterable, makeResult, json) {
// use Object.values() on non-iterable objects
if (
Expand Down Expand Up @@ -160,6 +180,20 @@ export default class RestApi {
collections.hosts.routes = {
__proto__: null,

async 'audit.txt'(req, res) {
const host = req.xapiObject

res.setHeader('content-type', 'text/plain')
await pipeline(await host.$xapi.getResource('/audit_log', { host }), compressMaybe(req, res))
},

async 'logs.tar'(req, res) {
const host = req.xapiObject

res.setHeader('content-type', 'application/x-tar')
await pipeline(await host.$xapi.getResource('/host_logs_download', { host }), compressMaybe(req, res))
},

async missing_patches(req, res) {
await app.checkFeatureAuthorization('LIST_MISSING_PATCHES')

Expand Down Expand Up @@ -412,7 +446,7 @@ export default class RestApi {
if (routes !== undefined) {
result = { ...result }
for (const route of Object.keys(routes)) {
result[route + '_href'] = join(req.baseUrl, req.path, route)
result[route.split('.')[0] + '_href'] = join(req.baseUrl, req.path, route)
}
}

Expand Down

0 comments on commit d384c74

Please sign in to comment.