feat(xo-server/xo-web/VM/new): VTPM creation (#7077)

See #7066
See #6802
See #7085
This commit is contained in:
Mathieu 2023-10-19 14:48:56 +00:00 committed by GitHub
parent 1a1dd0531d
commit 8834af65f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 1 deletions

View File

@ -11,6 +11,7 @@
- [Plugin/backup-report] Errors are now listed in XO tasks - [Plugin/backup-report] Errors are now listed in XO tasks
- [PIF] Show network name in PIF selectors (PR [#7081](https://github.com/vatesfr/xen-orchestra/pull/7081)) - [PIF] Show network name in PIF selectors (PR [#7081](https://github.com/vatesfr/xen-orchestra/pull/7081))
- [VM/Advanced] Possibility to create/delete VTPM [#7066](https://github.com/vatesfr/xen-orchestra/issues/7066) [Forum#6578](https://xcp-ng.org/forum/topic/6578/xcp-ng-8-3-public-alpha/109) (PR [#7085](https://github.com/vatesfr/xen-orchestra/pull/7085)) - [VM/Advanced] Possibility to create/delete VTPM [#7066](https://github.com/vatesfr/xen-orchestra/issues/7066) [Forum#6578](https://xcp-ng.org/forum/topic/6578/xcp-ng-8-3-public-alpha/109) (PR [#7085](https://github.com/vatesfr/xen-orchestra/pull/7085))
- [VM/New] Possibility to create and attach a _VTPM_ to a VM [#7066](https://github.com/vatesfr/xen-orchestra/issues/7066) [Forum#6578](https://xcp-ng.org/forum/topic/6578/xcp-ng-8-3-public-alpha/109) (PR [#7077](https://github.com/vatesfr/xen-orchestra/pull/7077))
### Bug fixes ### Bug fixes

View File

@ -238,6 +238,11 @@ export const create = defer(async function ($defer, params) {
await this.allocIpAddresses(vif.$id, concat(vif.ipv4_allowed, vif.ipv6_allowed)).catch(() => xapi.deleteVif(vif)) await this.allocIpAddresses(vif.$id, concat(vif.ipv4_allowed, vif.ipv6_allowed)).catch(() => xapi.deleteVif(vif))
} }
if (params.createVtpm) {
const vtpmRef = await xapi.VTPM_create({ VM: xapiVm.$ref })
$defer.onFailure(() => xapi.call('VTPM.destroy', vtpmRef))
}
if (params.bootAfterCreate) { if (params.bootAfterCreate) {
startVmAndDestroyCloudConfigVdi(xapi, xapiVm, cloudConfigVdiUuid, params) startVmAndDestroyCloudConfigVdi(xapi, xapiVm, cloudConfigVdiUuid, params)
} }
@ -258,6 +263,11 @@ create.params = {
optional: true, optional: true,
}, },
createVtpm: {
type: 'boolean',
default: false,
},
networkConfig: { networkConfig: {
type: 'string', type: 'string',
optional: true, optional: true,

View File

@ -1582,6 +1582,7 @@ const messages = {
createVmModalWarningMessage: createVmModalWarningMessage:
"You're about to use a large amount of resources available on the resource set. Are you sure you want to continue?", "You're about to use a large amount of resources available on the resource set. Are you sure you want to continue?",
copyHostBiosStrings: 'Copy host BIOS strings to VM', copyHostBiosStrings: 'Copy host BIOS strings to VM',
enableVtpm: 'Enable VTPM',
newVmCreateNewVmOn: 'Create a new VM on {select}', newVmCreateNewVmOn: 'Create a new VM on {select}',
newVmCreateNewVmNoPermission: 'You have no permission to create a VM', newVmCreateNewVmNoPermission: 'You have no permission to create a VM',
newVmInfoPanel: 'Info', newVmInfoPanel: 'Info',
@ -1655,6 +1656,7 @@ const messages = {
vmBootFirmwareIsUefi: 'The boot firmware is UEFI', vmBootFirmwareIsUefi: 'The boot firmware is UEFI',
destroyCloudConfigVdiAfterBoot: 'Destroy cloud config drive after first boot', destroyCloudConfigVdiAfterBoot: 'Destroy cloud config drive after first boot',
vtpmNotSupported: 'VTPM is only supported on pools running XCP-ng/XS 8.3 or later.', vtpmNotSupported: 'VTPM is only supported on pools running XCP-ng/XS 8.3 or later.',
warningVtpmRequired: 'This template requires a VTPM, if you proceed, the VM will likely not be able to boot.',
// ----- Self ----- // ----- Self -----
resourceSets: 'Resource sets', resourceSets: 'Resource sets',

View File

@ -100,6 +100,14 @@ $select-input-height: 40px; // Bootstrap input height
color: #333; color: #333;
} }
.d-inline-flex {
display: inline-flex;
}
.align-self-center {
align-self: center;
}
// COLORS ====================================================================== // COLORS ======================================================================
.xo-status-running { .xo-status-running {

View File

@ -346,6 +346,7 @@ export default class NewVm extends BaseComponent {
seqStart: 1, seqStart: 1,
share: this._getResourceSet()?.shareByDefault ?? false, share: this._getResourceSet()?.shareByDefault ?? false,
tags: [], tags: [],
createVtpm: this._templateNeedsVtpm(),
}, },
callback callback
) )
@ -493,6 +494,7 @@ export default class NewVm extends BaseComponent {
bootAfterCreate: state.bootAfterCreate, bootAfterCreate: state.bootAfterCreate,
copyHostBiosStrings: copyHostBiosStrings:
state.hvmBootFirmware !== 'uefi' && !this._templateHasBiosStrings() && state.copyHostBiosStrings, state.hvmBootFirmware !== 'uefi' && !this._templateHasBiosStrings() && state.copyHostBiosStrings,
createVtpm: state.createVtpm,
destroyCloudConfigVdiAfterBoot: state.destroyCloudConfigVdiAfterBoot, destroyCloudConfigVdiAfterBoot: state.destroyCloudConfigVdiAfterBoot,
secureBoot: state.secureBoot, secureBoot: state.secureBoot,
share: state.share, share: state.share,
@ -599,6 +601,7 @@ export default class NewVm extends BaseComponent {
}), }),
// settings // settings
secureBoot: template.secureBoot, secureBoot: template.secureBoot,
createVtpm: this._templateNeedsVtpm(),
}) })
if (this._isCoreOs()) { if (this._isCoreOs()) {
@ -748,6 +751,8 @@ export default class NewVm extends BaseComponent {
template => template && template.virtualizationMode === 'hvm' template => template && template.virtualizationMode === 'hvm'
) )
_templateNeedsVtpm = () => this.props.template?.platform?.vtpm === 'true'
// On change ------------------------------------------------------------------- // On change -------------------------------------------------------------------
_onChangeSshKeys = keys => this._setState({ sshKeys: map(keys, key => key.id) }) _onChangeSshKeys = keys => this._setState({ sshKeys: map(keys, key => key.id) })
@ -881,7 +886,12 @@ export default class NewVm extends BaseComponent {
_getRedirectionUrl = id => (this.state.state.multipleVms ? '/home' : `/vms/${id}`) _getRedirectionUrl = id => (this.state.state.multipleVms ? '/home' : `/vms/${id}`)
_handleBootFirmware = value => this._setState({ hvmBootFirmware: value, secureBoot: false }) _handleBootFirmware = value =>
this._setState({
hvmBootFirmware: value,
secureBoot: false,
createVtpm: value === 'uefi' ? this._templateNeedsVtpm() : false,
})
// MAIN ------------------------------------------------------------------------ // MAIN ------------------------------------------------------------------------
@ -1531,6 +1541,7 @@ export default class NewVm extends BaseComponent {
cpuCap, cpuCap,
cpusMax, cpusMax,
cpuWeight, cpuWeight,
createVtpm,
destroyCloudConfigVdiAfterBoot, destroyCloudConfigVdiAfterBoot,
hvmBootFirmware, hvmBootFirmware,
installMethod, installMethod,
@ -1565,6 +1576,8 @@ export default class NewVm extends BaseComponent {
</label> </label>
) : null ) : null
const isVtpmSupported = pool.vtpmSupported
return ( return (
<Section icon='new-vm-advanced' title='newVmAdvancedPanel' done={this._isAdvancedDone()}> <Section icon='new-vm-advanced' title='newVmAdvancedPanel' done={this._isAdvancedDone()}>
<SectionContent column> <SectionContent column>
@ -1769,6 +1782,23 @@ export default class NewVm extends BaseComponent {
<Item label={_('secureBoot')}> <Item label={_('secureBoot')}>
<Toggle onChange={this._toggleState('secureBoot')} value={secureBoot} /> <Toggle onChange={this._toggleState('secureBoot')} value={secureBoot} />
</Item> </Item>
<Item label={_('enableVtpm')} className='d-inline-flex'>
<Tooltip content={!isVtpmSupported ? _('vtpmNotSupported') : undefined}>
<Toggle onChange={this._toggleState('createVtpm')} value={createVtpm} disabled={!isVtpmSupported} />
</Tooltip>
{/* FIXME: link to VTPM documentation when ready */}
{/* &nbsp;
<Tooltip content={_('seeVtpmDocumentation')}>
<a className='text-info align-self-center' style={{ cursor: 'pointer' }} href='#'>
<Icon icon='info' />
</a>
</Tooltip> */}
{!createVtpm && this._templateNeedsVtpm() && (
<span className='align-self-center text-warning ml-1'>
<Icon icon='alarm' /> {_('warningVtpmRequired')}
</span>
)}
</Item>
</SectionContent> </SectionContent>
), ),
isAdmin && isHvm && ( isAdmin && isHvm && (