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
- [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/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

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))
}
if (params.createVtpm) {
const vtpmRef = await xapi.VTPM_create({ VM: xapiVm.$ref })
$defer.onFailure(() => xapi.call('VTPM.destroy', vtpmRef))
}
if (params.bootAfterCreate) {
startVmAndDestroyCloudConfigVdi(xapi, xapiVm, cloudConfigVdiUuid, params)
}
@ -258,6 +263,11 @@ create.params = {
optional: true,
},
createVtpm: {
type: 'boolean',
default: false,
},
networkConfig: {
type: 'string',
optional: true,

View File

@ -1582,6 +1582,7 @@ const messages = {
createVmModalWarningMessage:
"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',
enableVtpm: 'Enable VTPM',
newVmCreateNewVmOn: 'Create a new VM on {select}',
newVmCreateNewVmNoPermission: 'You have no permission to create a VM',
newVmInfoPanel: 'Info',
@ -1655,6 +1656,7 @@ const messages = {
vmBootFirmwareIsUefi: 'The boot firmware is UEFI',
destroyCloudConfigVdiAfterBoot: 'Destroy cloud config drive after first boot',
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 -----
resourceSets: 'Resource sets',

View File

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

View File

@ -346,6 +346,7 @@ export default class NewVm extends BaseComponent {
seqStart: 1,
share: this._getResourceSet()?.shareByDefault ?? false,
tags: [],
createVtpm: this._templateNeedsVtpm(),
},
callback
)
@ -493,6 +494,7 @@ export default class NewVm extends BaseComponent {
bootAfterCreate: state.bootAfterCreate,
copyHostBiosStrings:
state.hvmBootFirmware !== 'uefi' && !this._templateHasBiosStrings() && state.copyHostBiosStrings,
createVtpm: state.createVtpm,
destroyCloudConfigVdiAfterBoot: state.destroyCloudConfigVdiAfterBoot,
secureBoot: state.secureBoot,
share: state.share,
@ -599,6 +601,7 @@ export default class NewVm extends BaseComponent {
}),
// settings
secureBoot: template.secureBoot,
createVtpm: this._templateNeedsVtpm(),
})
if (this._isCoreOs()) {
@ -748,6 +751,8 @@ export default class NewVm extends BaseComponent {
template => template && template.virtualizationMode === 'hvm'
)
_templateNeedsVtpm = () => this.props.template?.platform?.vtpm === 'true'
// On change -------------------------------------------------------------------
_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}`)
_handleBootFirmware = value => this._setState({ hvmBootFirmware: value, secureBoot: false })
_handleBootFirmware = value =>
this._setState({
hvmBootFirmware: value,
secureBoot: false,
createVtpm: value === 'uefi' ? this._templateNeedsVtpm() : false,
})
// MAIN ------------------------------------------------------------------------
@ -1531,6 +1541,7 @@ export default class NewVm extends BaseComponent {
cpuCap,
cpusMax,
cpuWeight,
createVtpm,
destroyCloudConfigVdiAfterBoot,
hvmBootFirmware,
installMethod,
@ -1565,6 +1576,8 @@ export default class NewVm extends BaseComponent {
</label>
) : null
const isVtpmSupported = pool.vtpmSupported
return (
<Section icon='new-vm-advanced' title='newVmAdvancedPanel' done={this._isAdvancedDone()}>
<SectionContent column>
@ -1769,6 +1782,23 @@ export default class NewVm extends BaseComponent {
<Item label={_('secureBoot')}>
<Toggle onChange={this._toggleState('secureBoot')} value={secureBoot} />
</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>
),
isAdmin && isHvm && (