feat(xo-web/VM/advanced): VTPM management (#7085)
See #7066 See #6802 See #7074
This commit is contained in:
parent
8752487280
commit
1a1dd0531d
@ -10,6 +10,7 @@
|
||||
- [Host/Advanced] Allow to force _Smart reboot_ if some resident VMs have the suspend operation blocked [Forum#7136](https://xcp-ng.org/forum/topic/7136/suspending-vms-during-host-reboot/23) (PR [#7025](https://github.com/vatesfr/xen-orchestra/pull/7025))
|
||||
- [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))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -25,6 +25,7 @@ const messages = {
|
||||
esxiImportStopOnErrorDescription: 'Stop on the first error when importing VMs',
|
||||
nImportVmsInParallel: 'Number of VMs to import in parallel',
|
||||
stopOnError: 'Stop on error',
|
||||
uuid: 'UUID',
|
||||
vmSrUsage: 'Storage: {used} used of {total} ({free} free)',
|
||||
|
||||
notDefined: 'Not defined',
|
||||
@ -1367,6 +1368,9 @@ const messages = {
|
||||
logAction: 'Action',
|
||||
|
||||
// ----- VM advanced tab -----
|
||||
createVtpm: 'Create a VTPM',
|
||||
deleteVtpm: 'Delete the VTPM',
|
||||
deleteVtpmWarning: 'If the VTPM is in use, removing it will result in a dangerous data loss. Are you sure you want to remove the VTPM?',
|
||||
vmRemoveButton: 'Remove',
|
||||
vmConvertToTemplateButton: 'Convert to template',
|
||||
vmSwitchVirtualizationMode: 'Convert to {mode}',
|
||||
@ -1396,9 +1400,12 @@ const messages = {
|
||||
srHaTooltip: 'SR used for High Availability',
|
||||
nestedVirt: 'Nested virtualization',
|
||||
vmAffinityHost: 'Affinity host',
|
||||
vmNeedToBeHalted: 'The VM needs to be halted',
|
||||
vmVga: 'VGA',
|
||||
vmVideoram: 'Video RAM',
|
||||
vmNicType: 'NIC type',
|
||||
vtpm: 'VTPM',
|
||||
vtpmRequireUefi: 'A UEFI boot firmware is necessary to use a VTPM',
|
||||
noAffinityHost: 'None',
|
||||
originalTemplate: 'Original template',
|
||||
unknownOsName: 'Unknown',
|
||||
@ -1644,8 +1651,10 @@ const messages = {
|
||||
newVmNetworkConfigDoc: 'Network config documentation',
|
||||
templateHasBiosStrings: 'The template already contains the BIOS strings',
|
||||
secureBootLinkToDocumentationMessage: 'Click for more information about Guest UEFI Secure Boot.',
|
||||
seeVtpmDocumentation: 'See VTPM documentation',
|
||||
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.',
|
||||
|
||||
// ----- Self -----
|
||||
resourceSets: 'Resource sets',
|
||||
|
@ -2155,6 +2155,11 @@ export const deleteAclRule = ({ protocol = undefined, port = undefined, ipRange
|
||||
vifId: resolveId(vif),
|
||||
})
|
||||
|
||||
// VTPM -----------------------------------------------------------
|
||||
|
||||
export const createVtpm = vm => _call('vtpm.create', { id: resolveId(vm) })
|
||||
export const deleteVtpm = vtpm => _call('vtpm.destroy', { id: resolveId(vtpm) })
|
||||
|
||||
// Network -----------------------------------------------------------
|
||||
|
||||
export const editNetwork = (network, props) => _call('network.set', { ...props, id: resolveId(network) })
|
||||
|
@ -2,6 +2,7 @@ import _ from 'intl'
|
||||
import ActionButton from 'action-button'
|
||||
import Component from 'base-component'
|
||||
import decorate from 'apply-decorators'
|
||||
import Copiable from 'copiable'
|
||||
import defined, { get } from '@xen-orchestra/defined'
|
||||
import getEventValue from 'get-event-value'
|
||||
import Icon from 'icon'
|
||||
@ -28,8 +29,10 @@ import {
|
||||
cloneVm,
|
||||
convertVmToTemplate,
|
||||
createVgpu,
|
||||
createVtpm,
|
||||
deleteVgpu,
|
||||
deleteVm,
|
||||
deleteVtpm,
|
||||
editVm,
|
||||
getVmsHaValues,
|
||||
isVmRunning,
|
||||
@ -450,9 +453,48 @@ export default class TabAdvanced extends Component {
|
||||
|
||||
_onNicTypeChange = value => editVm(this.props.vm, { nicType: value === '' ? null : value })
|
||||
|
||||
_getDisabledAddVtpmReason = createSelector(
|
||||
() => this.props.vm,
|
||||
() => this.props.pool,
|
||||
(vm, pool) => {
|
||||
if (!pool.vtpmSupported) {
|
||||
return _('vtpmNotSupported')
|
||||
}
|
||||
if (vm.boot.firmware !== 'uefi') {
|
||||
return _('vtpmRequireUefi')
|
||||
}
|
||||
if (vm.power_state !== 'Halted') {
|
||||
return _('vmNeedToBeHalted')
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
_getDisabledDeleteVtpmReason = () => {
|
||||
if (this.props.vm.power_state !== 'Halted') {
|
||||
return _('vmNeedToBeHalted')
|
||||
}
|
||||
}
|
||||
|
||||
_handleDeleteVtpm = async vtpm => {
|
||||
await confirm({
|
||||
icon: 'delete',
|
||||
title: _('deleteVtpm'),
|
||||
body: <p>{_('deleteVtpmWarning')}</p>,
|
||||
strongConfirm: {
|
||||
messageId: 'deleteVtpm',
|
||||
},
|
||||
})
|
||||
return deleteVtpm(vtpm)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { container, isAdmin, vgpus, vm, vmPool } = this.props
|
||||
const isWarmMigrationAvailable = getXoaPlan().value >= PREMIUM.value
|
||||
const addVtpmTooltip = this._getDisabledAddVtpmReason()
|
||||
const deleteVtpmTooltip = this._getDisabledDeleteVtpmReason()
|
||||
const isAddVtpmAvailable = addVtpmTooltip === undefined
|
||||
const isDeleteVtpmAvailable = deleteVtpmTooltip === undefined
|
||||
const vtpmId = vm.VTPMs[0]
|
||||
return (
|
||||
<Container>
|
||||
<Row>
|
||||
@ -798,6 +840,59 @@ export default class TabAdvanced extends Component {
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
<th>{_('vtpm')}</th>
|
||||
<td>
|
||||
{/*
|
||||
FIXME: add documentation link
|
||||
<a
|
||||
className='text-muted'
|
||||
href='#'
|
||||
rel='noopener noreferrer'
|
||||
style={{ display: 'block' }}
|
||||
target='_blank'
|
||||
>
|
||||
<Icon icon='info' /> {_('seeVtpmDocumentation')}
|
||||
</a> */}
|
||||
{vtpmId === undefined ? (
|
||||
<Tooltip content={addVtpmTooltip}>
|
||||
<ActionButton
|
||||
btnStyle='primary'
|
||||
disabled={!isAddVtpmAvailable}
|
||||
handler={createVtpm}
|
||||
handlerParam={vm}
|
||||
icon='add'
|
||||
>
|
||||
{_('createVtpm')}
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<div>
|
||||
<Tooltip content={deleteVtpmTooltip}>
|
||||
<ActionButton
|
||||
btnStyle='danger'
|
||||
disabled={!isDeleteVtpmAvailable}
|
||||
handler={this._handleDeleteVtpm}
|
||||
handlerParam={vtpmId}
|
||||
icon='delete'
|
||||
>
|
||||
{_('deleteVtpm')}
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
<table className='table mt-1'>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{_('uuid')}</th>
|
||||
<Copiable tagName='td' data={vtpmId}>
|
||||
{vtpmId.slice(0, 4)}
|
||||
</Copiable>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
{vm.boot.firmware === 'uefi' && (
|
||||
<tr>
|
||||
<th>{_('secureBoot')}</th>
|
||||
|
Loading…
Reference in New Issue
Block a user