mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-09-10 22:14:48 -05:00
feat(xo-web/new VM): allow admin to create VM in resource set (#10259)
This commit is contained in:
@@ -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-->
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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'
|
||||||
|
/>
|
||||||
|
|
||||||
|
{_('newVmShare')}
|
||||||
|
</label>
|
||||||
|
</SectionContent>
|
||||||
|
),
|
||||||
]}
|
]}
|
||||||
</Section>
|
</Section>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user