feat(xo-web/new VM): allow admin to create VM in resource set (#10259)

This commit is contained in:
Pierre Donias
2026-08-31 10:55:00 +02:00
committed by GitHub
parent d2d2d57c81
commit 62cc3e3f5d
3 changed files with 42 additions and 4 deletions

View File

@@ -12,6 +12,8 @@
> Users must be able to say: "Nice enhancement, I'm eager to test it" > Users must be able to say: "Nice enhancement, I'm eager to test it"
- [XO6/Host] Add possibility to detach an host (PR [#10179](https://github.com/vatesfr/xen-orchestra/pull/10179)) - [XO6/Host] Add possibility to detach an host (PR [#10179](https://github.com/vatesfr/xen-orchestra/pull/10179))
- [XO5/New VM] Ability to add the VM to a resource set and to share it during creation (PR [#10259](https://github.com/vatesfr/xen-orchestra/pull/10259))
### Bug fixes ### Bug fixes
@@ -34,5 +36,7 @@
<!--packages-start--> <!--packages-start-->
- @xen-orchestra/web minor - @xen-orchestra/web minor
- xo-server minor
- xo-web minor
<!--packages-end--> <!--packages-end-->

View File

@@ -167,7 +167,9 @@ export const create = defer(async function ($defer, params) {
let checkLimits let checkLimits
if (resourceSet) { if (resourceSet) {
await this.checkResourceSetConstraints(resourceSet, user.id, objectIds) // an admin can add the created VM to a resource set even if the objects it
// uses (template, SRs, networks) are not part of this resource set
await this.checkResourceSetConstraints(resourceSet, user.id, user.permission === 'admin' ? undefined : objectIds)
checkLimits = async limits2 => { checkLimits = async limits2 => {
const _limits = assignWith({}, limits, limits2, (l1 = 0, l2) => l1 + l2) const _limits = assignWith({}, limits, limits2, (l1 = 0, l2) => l1 + l2)
await this.allocateLimitsInResourceSet(_limits, resourceSet) await this.allocateLimitsInResourceSet(_limits, resourceSet)

View File

@@ -304,9 +304,12 @@ export default class NewVm extends BaseComponent {
this._initTemplate(template) this._initTemplate(template)
} }
// as an admin, the resource set is selected in the advanced settings and
// `share` is initialized by `_setResourceSet`, it must not be overridden here
if ( if (
!isEqual(prevProps.resourceSets, this.props.resourceSets) || this.state.state.resourceSet === undefined &&
prevProps.location.query.resourceSet !== this.props.location.query.resourceSet (!isEqual(prevProps.resourceSets, this.props.resourceSets) ||
prevProps.location.query.resourceSet !== this.props.location.query.resourceSet)
) { ) {
this._setState({ this._setState({
share: this._getResourceSet()?.shareByDefault ?? false, share: this._getResourceSet()?.shareByDefault ?? false,
@@ -385,6 +388,7 @@ export default class NewVm extends BaseComponent {
nameLabels: map(Array(NB_VMS_MIN), (_, index) => `VM_${index + 1}`), nameLabels: map(Array(NB_VMS_MIN), (_, index) => `VM_${index + 1}`),
namePattern: '{name}%', namePattern: '{name}%',
nbVms: NB_VMS_MIN, nbVms: NB_VMS_MIN,
resourceSet: undefined,
VDIs: [], VDIs: [],
VIFs: [], VIFs: [],
secureBoot: false, secureBoot: false,
@@ -501,7 +505,9 @@ export default class NewVm extends BaseComponent {
return _vif return _vif
}) })
const resourceSet = this._getResourceSet() // - self user: resource set ID in the URL,
// - admin: resource set in state
const resourceSet = this._getResourceSet() ?? state.resourceSet
const { template } = this.props const { template } = this.props
// Either use `memory` OR `memory*` params // Either use `memory` OR `memory*` params
@@ -844,6 +850,14 @@ export default class NewVm extends BaseComponent {
}) })
this._reset() this._reset()
} }
// admin only
_setResourceSet = resourceSet => {
this._setState({
// the select gives `null` when cleared, `undefined` is expected by `vm.create`
resourceSet: resourceSet ?? undefined,
share: resourceSet?.shareByDefault ?? false,
})
}
_selectPool = pool => { _selectPool = pool => {
const { pathname } = this.props.location const { pathname } = this.props.location
@@ -1634,6 +1648,7 @@ export default class NewVm extends BaseComponent {
nameLabels, nameLabels,
namePattern, namePattern,
nbVms, nbVms,
resourceSet,
secureBoot, secureBoot,
seqStart, seqStart,
share, share,
@@ -1948,6 +1963,23 @@ export default class NewVm extends BaseComponent {
</Container> </Container>
</SectionContent> </SectionContent>
), ),
isAdmin && this._getResourceSet() === undefined && (
<SectionContent key='resourceSet'>
<Item label={_('resourceSet')}>
<SelectResourceSet onChange={this._setResourceSet} value={resourceSet} />
</Item>
<label className='align-self-center'>
<input
checked={share}
disabled={resourceSet == null}
onChange={this._linkState('share')}
type='checkbox'
/>
&nbsp;
{_('newVmShare')}
</label>
</SectionContent>
),
]} ]}
</Section> </Section>
) )