feat(xo-web/self): ability to share VMs by default (#6838)
See xoa-support#7420
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
- [Home/Host] Displays a warning for hosts with HVM disabled [#6823](https://github.com/vatesfr/xen-orchestra/issues/6823) (PR [#6834](https://github.com/vatesfr/xen-orchestra/pull/6834))
|
||||
- [OVA import] Workaround for OVA generated by Oracle VM with faulty size in metadata [#6824](https://github.com/vatesfr/xen-orchestra/issues/6824)
|
||||
- [REST API] _Rolling Pool Update_ action available `pools/<uuid>/actions/rolling_update`
|
||||
- [Self Service] Ability to set a default value for the "Share VM" feature for Self Service users during creation/edition (PR [#6838](https://github.com/vatesfr/xen-orchestra/pull/6838))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export function create({ name, subjects, objects, limits }) {
|
||||
return this.createResourceSet(name, subjects, objects, limits)
|
||||
export function create({ name, shareByDefault, subjects, objects, limits }) {
|
||||
return this.createResourceSet(name, subjects, objects, limits, shareByDefault)
|
||||
}
|
||||
|
||||
create.permission = 'admin'
|
||||
@@ -26,6 +26,10 @@ create.params = {
|
||||
type: 'object',
|
||||
optional: true,
|
||||
},
|
||||
shareByDefault: {
|
||||
type: 'boolean',
|
||||
optional: true,
|
||||
},
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
@@ -45,12 +49,13 @@ delete_.params = {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export function set({ id, name, subjects, objects, ipPools, limits }) {
|
||||
export function set({ id, name, shareByDefault, subjects, objects, ipPools, limits }) {
|
||||
return this.updateResourceSet(id, {
|
||||
limits,
|
||||
name,
|
||||
objects,
|
||||
ipPools,
|
||||
shareByDefault,
|
||||
subjects,
|
||||
})
|
||||
}
|
||||
@@ -65,6 +70,10 @@ set.params = {
|
||||
type: 'string',
|
||||
optional: true,
|
||||
},
|
||||
shareByDefault: {
|
||||
type: 'boolean',
|
||||
optional: true
|
||||
},
|
||||
subjects: {
|
||||
type: 'array',
|
||||
items: {
|
||||
|
||||
@@ -65,6 +65,7 @@ const normalize = set => ({
|
||||
name: set.name || '',
|
||||
objects: set.objects || [],
|
||||
subjects: set.subjects || [],
|
||||
shareByDefault: set.shareByDefault || false,
|
||||
})
|
||||
|
||||
// ===================================================================
|
||||
@@ -133,7 +134,7 @@ export default class {
|
||||
return vm.type === 'VM-snapshot' ? this.computeVmSnapshotResourcesUsage(vm) : this.computeVmResourcesUsage(vm)
|
||||
}
|
||||
|
||||
async createResourceSet(name, subjects = undefined, objects = undefined, limits = undefined) {
|
||||
async createResourceSet(name, subjects = undefined, objects = undefined, limits = undefined, shareByDefault = false) {
|
||||
const id = await this._generateId()
|
||||
const set = normalize({
|
||||
id,
|
||||
@@ -141,6 +142,7 @@ export default class {
|
||||
objects,
|
||||
subjects,
|
||||
limits,
|
||||
shareByDefault,
|
||||
})
|
||||
|
||||
await this._store.put(id, set)
|
||||
@@ -167,7 +169,14 @@ export default class {
|
||||
async updateResourceSet(
|
||||
$defer,
|
||||
id,
|
||||
{ name = undefined, subjects = undefined, objects = undefined, limits = undefined, ipPools = undefined }
|
||||
{
|
||||
name = undefined,
|
||||
shareByDefault = undefined,
|
||||
subjects = undefined,
|
||||
objects = undefined,
|
||||
limits = undefined,
|
||||
ipPools = undefined,
|
||||
}
|
||||
) {
|
||||
const set = await this.getResourceSet(id)
|
||||
if (name) {
|
||||
@@ -223,6 +232,10 @@ export default class {
|
||||
set.ipPools = ipPools
|
||||
}
|
||||
|
||||
if (shareByDefault !== undefined && shareByDefault !== set.shareByDefault) {
|
||||
set.shareByDefault = shareByDefault
|
||||
}
|
||||
|
||||
await this._save(set)
|
||||
}
|
||||
|
||||
|
||||
@@ -1633,6 +1633,7 @@ const messages = {
|
||||
availableResourceLabel: 'Available',
|
||||
resourceSetQuota: 'Used: {usage} (Total: {total})',
|
||||
resourceSetNew: 'New',
|
||||
shareVmsByDefault: 'Share VMs by default',
|
||||
|
||||
// ---- VM import ---
|
||||
fileType: 'File type:',
|
||||
|
||||
@@ -2513,13 +2513,14 @@ export const sendUsageReport = () => _call('plugin.usageReport.send')
|
||||
|
||||
// Resource set ------------------------------------------------------
|
||||
|
||||
export const createResourceSet = (name, { subjects, objects, limits } = {}) =>
|
||||
_call('resourceSet.create', { name, subjects, objects, limits })::tap(subscribeResourceSets.forceRefresh)
|
||||
export const createResourceSet = (name, { shareByDefault, subjects, objects, limits } = {}) =>
|
||||
_call('resourceSet.create', { name, shareByDefault, subjects, objects, limits })::tap(subscribeResourceSets.forceRefresh)
|
||||
|
||||
export const editResourceSet = (id, { name, subjects, objects, limits, ipPools } = {}) =>
|
||||
export const editResourceSet = (id, { name, shareByDefault, subjects, objects, limits, ipPools } = {}) =>
|
||||
_call('resourceSet.set', {
|
||||
id,
|
||||
name,
|
||||
shareByDefault,
|
||||
subjects,
|
||||
objects,
|
||||
limits,
|
||||
|
||||
@@ -28,7 +28,22 @@ import {
|
||||
} from 'cloud-config'
|
||||
import { Input as DebounceInput, Textarea as DebounceTextarea } from 'debounce-input-decorator'
|
||||
import { Limits } from 'usage'
|
||||
import { clamp, every, filter, find, forEach, includes, isEmpty, join, map, size, slice, sum, sumBy } from 'lodash'
|
||||
import {
|
||||
clamp,
|
||||
every,
|
||||
filter,
|
||||
find,
|
||||
forEach,
|
||||
includes,
|
||||
isEmpty,
|
||||
isEqual,
|
||||
join,
|
||||
map,
|
||||
size,
|
||||
slice,
|
||||
sum,
|
||||
sumBy,
|
||||
} from 'lodash'
|
||||
import {
|
||||
addSshKey,
|
||||
createVm,
|
||||
@@ -255,6 +270,15 @@ export default class NewVm extends BaseComponent {
|
||||
if (get(() => prevProps.template.id) !== get(() => this.props.template.id)) {
|
||||
this._initTemplate(this.props.template)
|
||||
}
|
||||
|
||||
if (
|
||||
!isEqual(prevProps.resourceSets, this.props.resourceSets) ||
|
||||
prevProps.location.query.resourceSet !== this.props.location.query.resourceSet
|
||||
) {
|
||||
this._setState({
|
||||
share: this._getResourceSet()?.shareByDefault ?? false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_getResourceSet = createFinder(
|
||||
@@ -320,7 +344,7 @@ export default class NewVm extends BaseComponent {
|
||||
VIFs: [],
|
||||
secureBoot: false,
|
||||
seqStart: 1,
|
||||
share: false,
|
||||
share: this._getResourceSet()?.shareByDefault ?? false,
|
||||
tags: [],
|
||||
},
|
||||
callback
|
||||
|
||||
@@ -137,6 +137,7 @@ export class Edit extends Component {
|
||||
name: '',
|
||||
networks: [],
|
||||
pools: [],
|
||||
shareByDefault: false,
|
||||
srs: [],
|
||||
subjects: [],
|
||||
templates: [],
|
||||
@@ -175,6 +176,7 @@ export class Edit extends Component {
|
||||
ipPools,
|
||||
memory: get(limits, 'memory.total', null),
|
||||
name: resourceSet.name,
|
||||
shareByDefault: resourceSet.shareByDefault || false,
|
||||
subjects: resourceSet.subjects,
|
||||
templates: objectsByType['VM-template'] || [],
|
||||
})
|
||||
@@ -182,7 +184,7 @@ export class Edit extends Component {
|
||||
}
|
||||
|
||||
_save = async () => {
|
||||
const { cpus, disk, ipPools, memory, name, networks, srs, subjects, templates } = this.state
|
||||
const { cpus, disk, ipPools, memory, name, networks, shareByDefault, srs, subjects, templates } = this.state
|
||||
|
||||
const set = this.props.resourceSet || (await createResourceSet(name))
|
||||
const objects = [...templates, ...srs, ...networks]
|
||||
@@ -203,6 +205,7 @@ export class Edit extends Component {
|
||||
...ipPoolsLimits,
|
||||
},
|
||||
objects: resolveIds(objects),
|
||||
shareByDefault,
|
||||
subjects: resolveIds(subjects),
|
||||
ipPools: resolveIds(ipPools),
|
||||
})
|
||||
@@ -220,6 +223,7 @@ export class Edit extends Component {
|
||||
memory: null,
|
||||
newIpPool: undefined,
|
||||
newIpPoolQuantity: '',
|
||||
shareByDefault: false,
|
||||
subjects: [],
|
||||
})
|
||||
}
|
||||
@@ -494,6 +498,13 @@ export class Edit extends Component {
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div className='mt-1'>
|
||||
<label>
|
||||
<input checked={state.shareByDefault} type='checkbox' onChange={this.toggleState('shareByDefault')} />
|
||||
|
||||
<strong>{_('shareVmsByDefault')}</strong>
|
||||
</label>
|
||||
</div>
|
||||
<hr />
|
||||
<Hosts excludedHosts={state.excludedHosts} eligibleHosts={state.eligibleHosts} />
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user