mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-09-10 22:14:48 -05:00
feat(rest-api): add add_host route to pools (#9876)
This commit is contained in:
@@ -119,6 +119,12 @@ export type XsPatches = {
|
||||
}
|
||||
|
||||
export interface Xapi {
|
||||
status: string
|
||||
pool?: { uuid: string }
|
||||
sessionId: string
|
||||
_auth: { user: string; password: string }
|
||||
_url: { protocol: string; hostname: string; hostnameRaw: string; port?: string }
|
||||
|
||||
call: <ReturnType>(...args: unknown[]) => Promise<ReturnType>
|
||||
callAsync: <ReturnType>(...args: unknown[]) => Promise<ReturnType>
|
||||
|
||||
@@ -176,6 +182,7 @@ export interface Xapi {
|
||||
bypassAssert?: boolean
|
||||
}
|
||||
): Promise<void>
|
||||
joinPool(masterAddress: string, masterUsername: string, masterPassword: string, force?: boolean): Promise<void>
|
||||
listMissingPatches(host: XoHost['id']): Promise<XcpPatches[] | XsPatches[]>
|
||||
pool_emergencyShutdown(): Promise<void>
|
||||
resumeVm(id: XoVm['id']): Promise<void>
|
||||
|
||||
@@ -50,13 +50,6 @@ import {
|
||||
XoUserRole,
|
||||
} from './index.mjs'
|
||||
|
||||
export type XapiConnection = Xapi & {
|
||||
status: string
|
||||
pool?: { uuid: string }
|
||||
sessionId: string
|
||||
_url?: { protocol: string; hostname: string; port?: string }
|
||||
}
|
||||
|
||||
type FeatureCode =
|
||||
| 'BACKUP.DELTA'
|
||||
| 'BACKUP.DELTA_REPLICATION'
|
||||
@@ -376,7 +369,7 @@ export type XoApp = {
|
||||
url?: string
|
||||
}
|
||||
): Promise<XoBackupRepository>
|
||||
getAllXapis(): Record<string, XapiConnection>
|
||||
getAllXapis(): Record<string, Xapi>
|
||||
getObjects(opts?: { filter?: Record<string, unknown>; limit?: number }): Record<string, XapiXoRecord>
|
||||
getLicenses(params?: { productType?: LicenseProductType }): Promise<License[]>
|
||||
bindLicense(params: { licenseId: string; boundObjectId: string }): Promise<License>
|
||||
|
||||
@@ -6,6 +6,7 @@ export default {
|
||||
export: {
|
||||
logs: true,
|
||||
},
|
||||
'join-pool': true,
|
||||
read: true,
|
||||
update: {
|
||||
tags: true,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export default {
|
||||
'add-host': true,
|
||||
create: {
|
||||
network: true,
|
||||
vm: true,
|
||||
|
||||
@@ -808,4 +808,56 @@ export class PoolController extends XapiXoController<XoPool> {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Required privileges:
|
||||
* - resource: pool, action: add-host
|
||||
* - resource: host, action: join-pool
|
||||
*
|
||||
* Add a host to the pool.
|
||||
*
|
||||
* @example id "355ee47d-ff4c-4924-3db2-fd86ae629676"
|
||||
* @example body { "host": "c787b75c-3e0d-70fa-d0c3-cbfd382d7e33", "force": "false" }
|
||||
*/
|
||||
@Example(taskLocation)
|
||||
@Post('{id}/actions/add_host')
|
||||
@Middlewares([
|
||||
json(),
|
||||
acl([
|
||||
{ resource: 'pool', action: 'add-host', objectId: 'params.id' },
|
||||
{ resource: 'host', action: 'join-pool', objectId: 'body.host' },
|
||||
]),
|
||||
])
|
||||
@SuccessResponse(asynchronousActionResp.status, asynchronousActionResp.description)
|
||||
@Response(noContentResp.status, noContentResp.description)
|
||||
@Response(badRequestResp.status, badRequestResp.description)
|
||||
@Response(forbiddenOperationResp.status, forbiddenOperationResp.description)
|
||||
@Response(notFoundResp.status, notFoundResp.description)
|
||||
@Response(invalidParametersResp.status, invalidParametersResp.description)
|
||||
@Response(internalServerErrorResp.status, internalServerErrorResp.description)
|
||||
addHost(
|
||||
@Path() id: string,
|
||||
@Body() body: { host: string; force?: boolean },
|
||||
@Query() sync?: boolean
|
||||
): CreateActionReturnType<void> {
|
||||
const poolId = id as XoPool['id']
|
||||
const action = async () => {
|
||||
const {
|
||||
_auth: { user, password },
|
||||
_url: { hostnameRaw },
|
||||
} = this.restApi.xoApp.getXapi(poolId)
|
||||
const hostXapi = this.restApi.xoApp.getXapi(body.host as XoHost['id'])
|
||||
await hostXapi.joinPool(hostnameRaw, user, password, body.force)
|
||||
}
|
||||
|
||||
return this.createAction<void>(action, {
|
||||
sync,
|
||||
statusCode: noContentResp.status,
|
||||
taskProperties: {
|
||||
name: 'add host',
|
||||
objectId: poolId,
|
||||
params: body,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
- [XO6] live update XO tasks (PR [#9901](https://github.com/vatesfr/xen-orchestra/pull/9901))
|
||||
- [XO6/Backup] add progress for backups tasks(PR [#9901](https://github.com/vatesfr/xen-orchestra/pull/9901))
|
||||
- [REST API] add `hosts/:id/actions/join_pool` REST route (PR [#9876](https://github.com/vatesfr/xen-orchestra/pull/9876))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
||||
@@ -116,8 +116,8 @@ Actions are written using the exact string you pass in a privilege. A parent act
|
||||
| `vif` | `connect`, `create`, `delete`, `disconnect`,`read` |
|
||||
| `vbd` | `read`, `create`, `delete`, `connect`, `disconnect` |
|
||||
| `sr` | `read`, `delete`, `forget`, `reclaim-space`, `scan`, `import:vdi`, `import:vm`, `update:tags` |
|
||||
| `host` | `read`, `allow-vm`, `export:logs`, `update:tags`, `disable`, `enable`, `evacuate` |
|
||||
| `pool` | `read`, `emergency-shutdown`, `rolling-reboot`, `rolling-update`, `create:network`, `create:vm`, `update:tags` |
|
||||
| `host` | `read`, `allow-vm`, `join-pool`, `export:logs`, `update:tags`, `disable`, `enable`, `evacuate` |
|
||||
| `pool` | `add-host`, `read`, `emergency-shutdown`, `rolling-reboot`, `rolling-update`, `create:network`, `create:vm`, `update:tags` |
|
||||
| `network` | `read`, `create`, `delete`, `update:tags` |
|
||||
| `pif` | `read`, `update:management` |
|
||||
| `pbd` | `read`, `plug`, `unplug` |
|
||||
@@ -261,4 +261,4 @@ A selector is evaluated against each object's properties. If it matches, the pri
|
||||
- **Use groups.** Assigning a role to a group avoids repeating the same assignment for every user.
|
||||
- **Combine `allow` and `deny`.** When a user needs broad access with specific exceptions, grant with a wildcard privilege and carve out exceptions with `deny` + a selector.
|
||||
- **Template roles are immutable.** Copy them first before customizing.
|
||||
- **Endpoint permissions** are visible in the Swagger UI (`/rest/v0/swagger`). Endpoints without a declared privilege require admin access.
|
||||
- **Endpoint permissions** are visible in the Swagger UI (`/rest/v0/swagger`). Endpoints without a declared privilege require admin access.
|
||||
Reference in New Issue
Block a user