parent
d6abdb246b
commit
c250cd9b89
@ -19,6 +19,7 @@
|
|||||||
- [Plugin/load-balancer] Limit concurrent VM migrations to 2 (configurable) to avoid long paused VMs [#7084](https://github.com/vatesfr/xen-orchestra/issues/7084) (PR [#7297](https://github.com/vatesfr/xen-orchestra/pull/7297))
|
- [Plugin/load-balancer] Limit concurrent VM migrations to 2 (configurable) to avoid long paused VMs [#7084](https://github.com/vatesfr/xen-orchestra/issues/7084) (PR [#7297](https://github.com/vatesfr/xen-orchestra/pull/7297))
|
||||||
- [Tags] Admin can create colored tags (PR [#7262](https://github.com/vatesfr/xen-orchestra/pull/7262))
|
- [Tags] Admin can create colored tags (PR [#7262](https://github.com/vatesfr/xen-orchestra/pull/7262))
|
||||||
- [Tags] Add tooltips on `xo:no-bak` and `xo:notify-on-snapshot` tags (PR [#7335](https://github.com/vatesfr/xen-orchestra/pull/7335))
|
- [Tags] Add tooltips on `xo:no-bak` and `xo:notify-on-snapshot` tags (PR [#7335](https://github.com/vatesfr/xen-orchestra/pull/7335))
|
||||||
|
- [VM] Custom notes [#5792](https://github.com/vatesfr/xen-orchestra/issues/5792) (PR [#7322](https://github.com/vatesfr/xen-orchestra/pull/7322))
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|
||||||
|
@ -694,6 +694,8 @@ set.params = {
|
|||||||
|
|
||||||
name_description: { type: 'string', minLength: 0, optional: true },
|
name_description: { type: 'string', minLength: 0, optional: true },
|
||||||
|
|
||||||
|
notes: { type: ['string', 'null'], maxLength: 2048, optional: true },
|
||||||
|
|
||||||
high_availability: {
|
high_availability: {
|
||||||
optional: true,
|
optional: true,
|
||||||
enum: getHaValues(),
|
enum: getHaValues(),
|
||||||
|
@ -401,6 +401,7 @@ const TRANSFORMS = {
|
|||||||
installTime: metrics && toTimestamp(metrics.install_time),
|
installTime: metrics && toTimestamp(metrics.install_time),
|
||||||
name_description: obj.name_description,
|
name_description: obj.name_description,
|
||||||
name_label: obj.name_label,
|
name_label: obj.name_label,
|
||||||
|
notes: otherConfig['xo:notes'],
|
||||||
other: otherConfig,
|
other: otherConfig,
|
||||||
os_version: (guestMetrics && guestMetrics.os_version) || null,
|
os_version: (guestMetrics && guestMetrics.os_version) || null,
|
||||||
parent: link(obj, 'parent'),
|
parent: link(obj, 'parent'),
|
||||||
|
@ -382,6 +382,11 @@ const methods = {
|
|||||||
|
|
||||||
nameLabel: true,
|
nameLabel: true,
|
||||||
|
|
||||||
|
notes: {
|
||||||
|
get: vm => vm.other_config['xo:notes'],
|
||||||
|
set: (value, vm) => vm.update_other_config('xo:notes', value),
|
||||||
|
},
|
||||||
|
|
||||||
PV_args: true,
|
PV_args: true,
|
||||||
|
|
||||||
tags: true,
|
tags: true,
|
||||||
|
@ -123,6 +123,7 @@
|
|||||||
"relative-luminance": "^2.0.1",
|
"relative-luminance": "^2.0.1",
|
||||||
"reselect": "^2.5.4",
|
"reselect": "^2.5.4",
|
||||||
"rimraf": "^5.0.1",
|
"rimraf": "^5.0.1",
|
||||||
|
"sanitize-html": "^2.11.0",
|
||||||
"sass": "^1.38.1",
|
"sass": "^1.38.1",
|
||||||
"semver": "^6.0.0",
|
"semver": "^6.0.0",
|
||||||
"strip-ansi": "^5.2.0",
|
"strip-ansi": "^5.2.0",
|
||||||
|
@ -1197,6 +1197,9 @@ const messages = {
|
|||||||
'Enabling this will allow the VM to automatically install Citrix PV drivers from Windows Update. This only includes drivers, the Citrix management agent must still be separately installed.',
|
'Enabling this will allow the VM to automatically install Citrix PV drivers from Windows Update. This only includes drivers, the Citrix management agent must still be separately installed.',
|
||||||
windowsToolsModalWarning:
|
windowsToolsModalWarning:
|
||||||
'If you have previously installed XCP-ng tools instead of Citrix tools, this option will break your VM.',
|
'If you have previously installed XCP-ng tools instead of Citrix tools, this option will break your VM.',
|
||||||
|
editVmNotes: 'Edit VM notes',
|
||||||
|
supportsMarkdown: 'Supports Markdown syntax',
|
||||||
|
vmNotesTooLong: 'VM notes cannot be longer than 2048 characters',
|
||||||
|
|
||||||
// ----- VM stat tab -----
|
// ----- VM stat tab -----
|
||||||
statsCpu: 'CPU usage',
|
statsCpu: 'CPU usage',
|
||||||
|
36
packages/xo-web/src/common/xo/edit-vm-notes-modal/index.js
Normal file
36
packages/xo-web/src/common/xo/edit-vm-notes-modal/index.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import _ from 'intl'
|
||||||
|
import Icon from 'icon'
|
||||||
|
import clamp from 'lodash/clamp'
|
||||||
|
import Component from 'base-component'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export default class EditVmNotesModalBody extends Component {
|
||||||
|
get value() {
|
||||||
|
return { notes: this.state.notes ?? this.props.vm.notes ?? '' }
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<textarea
|
||||||
|
autoFocus
|
||||||
|
rows={clamp(this.value.notes.split('\n').length, 5, 20)}
|
||||||
|
onChange={this.linkState('notes')}
|
||||||
|
value={this.value.notes}
|
||||||
|
className='form-control'
|
||||||
|
/>
|
||||||
|
{this.value.notes.length > 2048 && (
|
||||||
|
<em className='text-warning'>
|
||||||
|
<Icon icon='alarm' /> {_('vmNotesTooLong')}
|
||||||
|
</em>
|
||||||
|
)}
|
||||||
|
<em>
|
||||||
|
<Icon icon='info' />{' '}
|
||||||
|
<a href='https://commonmark.org/help/' target='_blank' rel='noreferrer'>
|
||||||
|
{_('supportsMarkdown')}
|
||||||
|
</a>
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1524,6 +1524,18 @@ export const changeVirtualizationMode = vm =>
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import EditVmNotesModalBody from './edit-vm-notes-modal' // eslint-disable-line import/first
|
||||||
|
export const editVmNotes = async vm => {
|
||||||
|
const { notes } = await confirm({
|
||||||
|
icon: 'edit',
|
||||||
|
title: _('editVmNotes'),
|
||||||
|
body: <EditVmNotesModalBody vm={vm} />,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove notes if `''` is passed
|
||||||
|
await _call('vm.set', { id: resolveId(vm), notes: notes || null })
|
||||||
|
}
|
||||||
|
|
||||||
export const createKubernetesCluster = params => _call('xoa.recipe.createKubernetesCluster', params)
|
export const createKubernetesCluster = params => _call('xoa.recipe.createKubernetesCluster', params)
|
||||||
|
|
||||||
export const deleteTemplates = templates =>
|
export const deleteTemplates = templates =>
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
import _ from 'intl'
|
import _ from 'intl'
|
||||||
|
import ActionButton from 'action-button'
|
||||||
import Copiable from 'copiable'
|
import Copiable from 'copiable'
|
||||||
import decorate from 'apply-decorators'
|
import decorate from 'apply-decorators'
|
||||||
import defined, { get } from '@xen-orchestra/defined'
|
import defined, { get } from '@xen-orchestra/defined'
|
||||||
import Icon from 'icon'
|
import Icon from 'icon'
|
||||||
import isEmpty from 'lodash/isEmpty'
|
import isEmpty from 'lodash/isEmpty'
|
||||||
import map from 'lodash/map'
|
import map from 'lodash/map'
|
||||||
|
import marked from 'marked'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import HomeTags from 'home-tags'
|
import HomeTags from 'home-tags'
|
||||||
import renderXoItem, { VmTemplate } from 'render-xo-item'
|
import renderXoItem, { VmTemplate } from 'render-xo-item'
|
||||||
|
import sanitizeHtml from 'sanitize-html'
|
||||||
import Tooltip from 'tooltip'
|
import Tooltip from 'tooltip'
|
||||||
import { addTag, editVm, removeTag, subscribeUsers } from 'xo'
|
import { addTag, editVm, editVmNotes, removeTag, subscribeUsers } from 'xo'
|
||||||
import { BlockLink } from 'link'
|
import { BlockLink } from 'link'
|
||||||
import { FormattedRelative, FormattedDate } from 'react-intl'
|
import { FormattedRelative, FormattedDate } from 'react-intl'
|
||||||
import { Container, Row, Col } from 'grid'
|
import { Container, Row, Col } from 'grid'
|
||||||
@ -31,6 +34,18 @@ const CREATED_VM_STYLES = {
|
|||||||
whiteSpace: 'pre-line',
|
whiteSpace: 'pre-line',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NOTES_STYLE = {
|
||||||
|
maxWidth: '70%',
|
||||||
|
margin: 'auto',
|
||||||
|
border: 'dashed 1px #999',
|
||||||
|
padding: '1em',
|
||||||
|
borderRadius: '10px',
|
||||||
|
}
|
||||||
|
|
||||||
|
const SANITIZE_OPTIONS = {
|
||||||
|
allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']),
|
||||||
|
}
|
||||||
|
|
||||||
const GuestToolsDetection = ({ vm }) => {
|
const GuestToolsDetection = ({ vm }) => {
|
||||||
if (vm.power_state !== 'Running' || vm.pvDriversDetected === undefined) {
|
if (vm.power_state !== 'Running' || vm.pvDriversDetected === undefined) {
|
||||||
return null
|
return null
|
||||||
@ -276,6 +291,20 @@ const GeneralTab = decorate([
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
<Row className='mt-1'>
|
||||||
|
<div style={NOTES_STYLE}>
|
||||||
|
{vm.notes !== undefined && (
|
||||||
|
<p
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: sanitizeHtml(marked(vm.notes), SANITIZE_OPTIONS),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<ActionButton icon='edit' handler={editVmNotes} handlerParam={vm}>
|
||||||
|
{_('editVmNotes')}
|
||||||
|
</ActionButton>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
21
yarn.lock
21
yarn.lock
@ -11876,7 +11876,7 @@ htmlparser2@^6.1.0:
|
|||||||
domutils "^2.5.2"
|
domutils "^2.5.2"
|
||||||
entities "^2.0.0"
|
entities "^2.0.0"
|
||||||
|
|
||||||
htmlparser2@^8.0.1:
|
htmlparser2@^8.0.0, htmlparser2@^8.0.1:
|
||||||
version "8.0.2"
|
version "8.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21"
|
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21"
|
||||||
integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
|
integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
|
||||||
@ -16395,6 +16395,11 @@ parse-passwd@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
|
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
|
||||||
integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==
|
integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==
|
||||||
|
|
||||||
|
parse-srcset@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1"
|
||||||
|
integrity sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==
|
||||||
|
|
||||||
parse5-htmlparser2-tree-adapter@^7.0.0:
|
parse5-htmlparser2-tree-adapter@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1"
|
resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1"
|
||||||
@ -17179,7 +17184,7 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2
|
|||||||
picocolors "^0.2.1"
|
picocolors "^0.2.1"
|
||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
|
|
||||||
postcss@^8.4.14, postcss@^8.4.32, postcss@^8.4.33:
|
postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.32, postcss@^8.4.33:
|
||||||
version "8.4.33"
|
version "8.4.33"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742"
|
||||||
integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
|
integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
|
||||||
@ -18951,6 +18956,18 @@ safe-regex@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
|
||||||
|
sanitize-html@^2.11.0:
|
||||||
|
version "2.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.11.0.tgz#9a6434ee8fcaeddc740d8ae7cd5dd71d3981f8f6"
|
||||||
|
integrity sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==
|
||||||
|
dependencies:
|
||||||
|
deepmerge "^4.2.2"
|
||||||
|
escape-string-regexp "^4.0.0"
|
||||||
|
htmlparser2 "^8.0.0"
|
||||||
|
is-plain-object "^5.0.0"
|
||||||
|
parse-srcset "^1.0.2"
|
||||||
|
postcss "^8.3.11"
|
||||||
|
|
||||||
sasl-anonymous@^0.1.0:
|
sasl-anonymous@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/sasl-anonymous/-/sasl-anonymous-0.1.0.tgz#f544c7e824df2a40d9ad4733829572cc8d9ed5a5"
|
resolved "https://registry.yarnpkg.com/sasl-anonymous/-/sasl-anonymous-0.1.0.tgz#f544c7e824df2a40d9ad4733829572cc8d9ed5a5"
|
||||||
|
Loading…
Reference in New Issue
Block a user