feat(xo-web/self): ability to share VMs by default (#6838)

See xoa-support#7420
This commit is contained in:
Mathieu
2023-05-25 09:00:04 +00:00
committed by GitHub
parent 9f3b020361
commit f4bf56f159
7 changed files with 71 additions and 11 deletions

View File

@@ -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

View File

@@ -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: {

View File

@@ -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)
}

View File

@@ -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:',

View File

@@ -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,

View File

@@ -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

View File

@@ -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')} />
&nbsp;
<strong>{_('shareVmsByDefault')}</strong>
</label>
</div>
<hr />
<Hosts excludedHosts={state.excludedHosts} eligibleHosts={state.eligibleHosts} />
</form>