Compare commits
3 Commits
fix-ips-ba
...
new-vm-aut
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbdfccb716 | ||
|
|
d605e9740d | ||
|
|
00d2a88da3 |
@@ -5,9 +5,6 @@
|
||||
- [VM/general] Display 'Started... ago' instead of 'Halted... ago' for paused state [#3750](https://github.com/vatesfr/xen-orchestra/issues/3750) (PR [#4170](https://github.com/vatesfr/xen-orchestra/pull/4170))
|
||||
- [Metadata backup] Ability to define when the backup report will be sent (PR [#4149](https://github.com/vatesfr/xen-orchestra/pull/4149))
|
||||
- [XOA/Update] Ability to select release channel [#4200](https://github.com/vatesfr/xen-orchestra/issues/4200) (PR [#4202](https://github.com/vatesfr/xen-orchestra/pull/4202))
|
||||
- [User] Forget connection tokens on password change or on demand [#4214](https://github.com/vatesfr/xen-orchestra/issues/4214) (PR [#4224](https://github.com/vatesfr/xen-orchestra/pull/4224))
|
||||
- [Settings/Logs] LICENCE_RESTRICTION errors: suggest XCP-ng as an Open Source alternative [#3876](https://github.com/vatesfr/xen-orchestra/issues/3876) (PR [#4238](https://github.com/vatesfr/xen-orchestra/pull/4238))
|
||||
- [VM/Migrate] Display VDI size on migrate modal [#2534](https://github.com/vatesfr/xen-orchestra/issues/2534) (PR [#4250](https://github.com/vatesfr/xen-orchestra/pull/4250))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
@@ -16,8 +13,6 @@
|
||||
- [Upgrade] Fix alert before upgrade while running backup jobs (PR [#4235](https://github.com/vatesfr/xen-orchestra/pull/4235))
|
||||
- [Import] Fix import OVA files (PR [#4232](https://github.com/vatesfr/xen-orchestra/pull/4232))
|
||||
- [VM/network] Fix duplicate IPv4 (PR [#4239](https://github.com/vatesfr/xen-orchestra/pull/4239))
|
||||
- [Remotes] Fix disconnected remotes which may appear to work
|
||||
- [Host] Fix incorrect hypervisor name [#4246](https://github.com/vatesfr/xen-orchestra/issues/4246) (PR [#4248](https://github.com/vatesfr/xen-orchestra/pull/4248))
|
||||
|
||||
### Released packages
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "xo-server",
|
||||
"version": "5.42.0",
|
||||
"version": "5.41.0",
|
||||
"license": "AGPL-3.0",
|
||||
"description": "Server part of Xen-Orchestra",
|
||||
"keywords": [
|
||||
|
||||
@@ -34,25 +34,3 @@ delete_.permission = 'admin'
|
||||
delete_.params = {
|
||||
token: { type: 'string' },
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export async function deleteAll({ except }) {
|
||||
await this.deleteAuthenticationTokens({
|
||||
filter: {
|
||||
user_id: this.session.get('user_id'),
|
||||
id: {
|
||||
__not: except,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
deleteAll.description =
|
||||
'delete all tokens of the current user except the current one'
|
||||
|
||||
deleteAll.permission = ''
|
||||
|
||||
deleteAll.params = {
|
||||
except: { type: 'string', optional: true },
|
||||
}
|
||||
|
||||
@@ -603,7 +603,7 @@ set.params = {
|
||||
// Switch from Cirrus video adaptor to VGA adaptor
|
||||
vga: { type: 'string', optional: true },
|
||||
|
||||
videoram: { type: 'number', optional: true },
|
||||
videoram: { type: ['string', 'number'], optional: true },
|
||||
|
||||
coresPerSocket: { type: ['string', 'number', 'null'], optional: true },
|
||||
|
||||
|
||||
@@ -1574,6 +1574,13 @@ export default class Xapi extends XapiBase {
|
||||
return /* await */ this._snapshotVm(this.getObject(vmId), nameLabel)
|
||||
}
|
||||
|
||||
async setVcpuWeight(vmId, weight) {
|
||||
await this.getObject(vmId).update_VCPUs_params(
|
||||
'weight',
|
||||
weight || null // Take all falsy values as a removal (0 included)
|
||||
)
|
||||
}
|
||||
|
||||
async _startVm(vm, host, force) {
|
||||
log.debug(`Starting VM ${vm.name_label}`)
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ export default {
|
||||
|
||||
coresPerSocket: {
|
||||
set: (coresPerSocket, vm) =>
|
||||
vm.update_platform('cores-per-socket', String(coresPerSocket)),
|
||||
vm.update_platform('cores-per-socket', coresPerSocket),
|
||||
},
|
||||
|
||||
CPUs: 'cpus',
|
||||
@@ -318,7 +318,7 @@ export default {
|
||||
|
||||
cpuCap: {
|
||||
get: vm => vm.VCPUs_params.cap && +vm.VCPUs_params.cap,
|
||||
set: (cap, vm) => vm.update_VCPUs_params('cap', String(cap)),
|
||||
set: (cap, vm) => vm.update_VCPUs_params('cap', cap),
|
||||
},
|
||||
|
||||
cpuMask: {
|
||||
@@ -341,11 +341,7 @@ export default {
|
||||
|
||||
cpuWeight: {
|
||||
get: vm => vm.VCPUs_params.weight && +vm.VCPUs_params.weight,
|
||||
set: (weight, vm) =>
|
||||
vm.update_VCPUs_params(
|
||||
'weight',
|
||||
weight === null ? null : String(weight)
|
||||
),
|
||||
set: (weight, vm) => vm.update_VCPUs_params('weight', weight),
|
||||
},
|
||||
|
||||
highAvailability: {
|
||||
@@ -447,7 +443,7 @@ export default {
|
||||
`The different values that the video RAM can take are: ${XEN_VIDEORAM_VALUES}`
|
||||
)
|
||||
}
|
||||
return vm.update_platform('videoram', String(videoram))
|
||||
return vm.update_platform('videoram', videoram)
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import createLogger from '@xen-orchestra/log'
|
||||
import { createPredicate } from 'value-matcher'
|
||||
import { ignoreErrors } from 'promise-toolbox'
|
||||
import { invalidCredentials, noSuchObject } from 'xo-common/api-errors'
|
||||
|
||||
@@ -194,14 +193,6 @@ export default class {
|
||||
}
|
||||
}
|
||||
|
||||
async deleteAuthenticationTokens({ filter }) {
|
||||
return Promise.all(
|
||||
(await this._tokens.get())
|
||||
.filter(createPredicate(filter))
|
||||
.map(({ id }) => this.deleteAuthenticationToken(id))
|
||||
)
|
||||
}
|
||||
|
||||
async getAuthenticationToken(id) {
|
||||
let token = await this._tokens.first(id)
|
||||
if (token === undefined) {
|
||||
|
||||
@@ -67,7 +67,7 @@ export default class {
|
||||
const handlers = this._handlers
|
||||
let handler = handlers[id]
|
||||
if (handler === undefined) {
|
||||
handler = getHandler(remote, this._remoteOptions)
|
||||
handler = handlers[id] = getHandler(remote, this._remoteOptions)
|
||||
|
||||
try {
|
||||
await handler.sync()
|
||||
@@ -76,8 +76,6 @@ export default class {
|
||||
ignoreErrors.call(this._updateRemote(id, { error: error.message }))
|
||||
throw error
|
||||
}
|
||||
|
||||
handlers[id] = handler
|
||||
}
|
||||
|
||||
return handler
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "xo-web",
|
||||
"version": "5.42.0",
|
||||
"version": "5.41.0",
|
||||
"license": "AGPL-3.0",
|
||||
"description": "Web interface client for Xen-Orchestra",
|
||||
"keywords": [
|
||||
|
||||
@@ -1839,11 +1839,6 @@ const messages = {
|
||||
pwdChangeErrorBody:
|
||||
'The old password provided is incorrect. Your password has not been changed.',
|
||||
changePasswordOk: 'OK',
|
||||
forgetTokens: 'Forget all connection tokens',
|
||||
forgetTokensExplained:
|
||||
'This will prevent other clients from authenticating with existing tokens but will not kill active sessions',
|
||||
forgetTokensSuccess: 'Successfully forgot connection tokens',
|
||||
forgetTokensError: 'Error while forgetting connection tokens',
|
||||
sshKeys: 'SSH keys',
|
||||
newSshKey: 'New SSH key',
|
||||
deleteSshKey: 'Delete',
|
||||
@@ -1872,7 +1867,6 @@ const messages = {
|
||||
// ----- Logs -----
|
||||
logUser: 'User',
|
||||
logMessage: 'Message',
|
||||
logSuggestXcpNg: 'Use XCP-ng to get rid of restrictions',
|
||||
logError: 'Error',
|
||||
logTitle: 'Logs',
|
||||
logDisplayDetails: 'Display details',
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import forEach from 'lodash/forEach'
|
||||
import forEachRight from 'lodash/forEachRight'
|
||||
import head from 'lodash/head'
|
||||
import forEach from 'lodash/forEach'
|
||||
import isArray from 'lodash/isArray'
|
||||
import isIp from 'is-ip'
|
||||
import last from 'lodash/last'
|
||||
import some from 'lodash/some'
|
||||
|
||||
export { isIp }
|
||||
@@ -84,9 +82,6 @@ export const formatIps = ips => {
|
||||
if (ips.length === 0) {
|
||||
return []
|
||||
}
|
||||
if (ips.length === 1) {
|
||||
return ips
|
||||
}
|
||||
const sortedIps = ips.sort((ip1, ip2) => {
|
||||
const splitIp1 = ip1.split('.')
|
||||
const splitIp2 = ip2.split('.')
|
||||
@@ -104,8 +99,24 @@ export const formatIps = ips => {
|
||||
(splitIp1[0] - splitIp2[0]) * 256 * 256 * 256
|
||||
)
|
||||
})
|
||||
const range = { first: '', last: '' }
|
||||
const formattedIps = []
|
||||
let index = 0
|
||||
forEach(sortedIps, ip => {
|
||||
if (ip !== getNextIpV4(range.last)) {
|
||||
if (range.first) {
|
||||
formattedIps[index] =
|
||||
range.first === range.last ? range.first : { ...range }
|
||||
index++
|
||||
}
|
||||
range.first = range.last = ip
|
||||
} else {
|
||||
range.last = ip
|
||||
}
|
||||
})
|
||||
formattedIps[index] = range.first === range.last ? range.first : range
|
||||
|
||||
return [{ first: head(sortedIps), last: last(sortedIps) }]
|
||||
return formattedIps
|
||||
}
|
||||
|
||||
export const parseIpPattern = pattern => {
|
||||
|
||||
@@ -283,7 +283,7 @@ export const Vdi = decorate([
|
||||
sr: getSr(state, props),
|
||||
})
|
||||
}),
|
||||
({ id, showSize, showSr, sr, vdi }) => {
|
||||
({ id, sr, vdi }) => {
|
||||
if (vdi === undefined) {
|
||||
return unknowItem(id, 'VDI')
|
||||
}
|
||||
@@ -291,12 +291,9 @@ export const Vdi = decorate([
|
||||
return (
|
||||
<span>
|
||||
<Icon icon='disk' /> {vdi.name_label}
|
||||
{sr !== undefined && showSr && (
|
||||
{sr !== undefined && (
|
||||
<span className='text-muted'> - {sr.name_label}</span>
|
||||
)}
|
||||
{showSize && (
|
||||
<span className='text-muted'> ({formatSize(vdi.size)})</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
},
|
||||
@@ -305,13 +302,10 @@ export const Vdi = decorate([
|
||||
Vdi.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
self: PropTypes.bool,
|
||||
showSize: PropTypes.bool,
|
||||
}
|
||||
|
||||
Vdi.defaultProps = {
|
||||
self: false,
|
||||
showSize: false,
|
||||
showSr: false,
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
@@ -438,8 +432,8 @@ const xoItemToRender = {
|
||||
// XO objects.
|
||||
pool: ({ id }) => <Pool id={id} />,
|
||||
|
||||
VDI: ({ id }) => <Vdi id={id} showSr />,
|
||||
'VDI-resourceSet': ({ id }) => <Vdi id={id} self showSr />,
|
||||
VDI: ({ id }) => <Vdi id={id} />,
|
||||
'VDI-resourceSet': ({ id }) => <Vdi id={id} self />,
|
||||
|
||||
// Pool objects.
|
||||
'VM-template': ({ id }) => <VmTemplate id={id} />,
|
||||
|
||||
@@ -59,7 +59,7 @@ export const constructSmartPattern = (
|
||||
|
||||
const valueToComplexMatcher = pattern => {
|
||||
if (typeof pattern === 'string') {
|
||||
return new CM.RegExpNode(`^${escapeRegExp(pattern)}$`, 'i')
|
||||
return new CM.RegExpNode(`^${escapeRegExp(pattern)}$`)
|
||||
}
|
||||
|
||||
if (Array.isArray(pattern)) {
|
||||
|
||||
@@ -3,7 +3,6 @@ import Component from 'base-component'
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import { map } from 'lodash'
|
||||
import { Vdi } from 'render-xo-item'
|
||||
|
||||
import _ from '../../intl'
|
||||
import SingleLineRow from '../../single-line-row'
|
||||
@@ -86,9 +85,7 @@ export default class ChooseSrForEachVdisModal extends Component {
|
||||
</SingleLineRow>
|
||||
{map(props.vdis, vdi => (
|
||||
<SingleLineRow key={vdi.uuid}>
|
||||
<Col size={6}>
|
||||
<Vdi id={vdi.id} showSize />
|
||||
</Col>
|
||||
<Col size={6}>{vdi.name_label || vdi.name}</Col>
|
||||
<Col size={6}>
|
||||
<SelectSr
|
||||
onChange={sr =>
|
||||
|
||||
@@ -376,7 +376,7 @@ export const dismissNotification = id => {
|
||||
export const subscribeNotifications = createSubscription(async () => {
|
||||
const { user, xoaUpdaterState } = store.getState()
|
||||
if (
|
||||
+process.env.XOA_PLAN === 5 ||
|
||||
process.env.XOA_PLAN === 5 ||
|
||||
xoaUpdaterState === 'disconnected' ||
|
||||
xoaUpdaterState === 'error'
|
||||
) {
|
||||
@@ -2508,25 +2508,14 @@ export const editUser = (user, { email, password, permission }) =>
|
||||
subscribeUsers.forceRefresh
|
||||
)
|
||||
|
||||
const _signOutFromEverywhereElse = () =>
|
||||
_call('token.deleteAll', { except: cookies.get('token') })
|
||||
|
||||
export const signOutFromEverywhereElse = () =>
|
||||
_signOutFromEverywhereElse().then(
|
||||
() => success(_('forgetTokens'), _('forgetTokensSuccess')),
|
||||
() => error(_('forgetTokens'), _('forgetTokensError'))
|
||||
)
|
||||
|
||||
export const changePassword = (oldPassword, newPassword) =>
|
||||
_call('user.changePassword', {
|
||||
oldPassword,
|
||||
newPassword,
|
||||
})
|
||||
.then(_signOutFromEverywhereElse)
|
||||
.then(
|
||||
() => success(_('pwdChangeSuccess'), _('pwdChangeSuccessBody')),
|
||||
() => error(_('pwdChangeError'), _('pwdChangeErrorBody'))
|
||||
)
|
||||
}).then(
|
||||
() => success(_('pwdChangeSuccess'), _('pwdChangeSuccessBody')),
|
||||
() => error(_('pwdChangeError'), _('pwdChangeErrorBody'))
|
||||
)
|
||||
|
||||
const _setUserPreferences = preferences =>
|
||||
_call('user.set', {
|
||||
|
||||
@@ -750,8 +750,7 @@ export default class Home extends Component {
|
||||
new ComplexMatcher.Or(
|
||||
map(
|
||||
tags,
|
||||
tag =>
|
||||
new ComplexMatcher.RegExp(`^${escapeRegExp(tag.id)}$`, 'i')
|
||||
tag => new ComplexMatcher.RegExp(`^${escapeRegExp(tag.id)}$`)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -118,9 +118,7 @@ export default ({ statsOverview, host, nVms, vmController, vms }) => {
|
||||
<Usage total={host.memory.size}>
|
||||
<UsageElement
|
||||
highlight
|
||||
tooltip={`${host.productBrand} (${formatSize(
|
||||
vmController.memory.size
|
||||
)})`}
|
||||
tooltip={`XenServer (${formatSize(vmController.memory.size)})`}
|
||||
value={vmController.memory.size}
|
||||
/>
|
||||
{map(vms, vm => (
|
||||
|
||||
@@ -547,9 +547,7 @@ export default class NewVm extends BaseComponent {
|
||||
const vif = getObject(storeState, vifId, resourceSet)
|
||||
VIFs.push({
|
||||
network:
|
||||
pool || isInResourceSet(vif.$network)
|
||||
? vif.$network
|
||||
: defaultNetworkIds[0],
|
||||
pool || isInResourceSet(vif.$network) ? vif.$network : undefined,
|
||||
})
|
||||
})
|
||||
if (VIFs.length === 0) {
|
||||
@@ -708,7 +706,7 @@ export default class NewVm extends BaseComponent {
|
||||
}
|
||||
|
||||
const automaticNetworks = this._getAutomaticNetworks()
|
||||
if (automaticNetworks.length !== 0) {
|
||||
if (automaticNetworks.length > 0) {
|
||||
return automaticNetworks
|
||||
}
|
||||
|
||||
|
||||
@@ -51,20 +51,9 @@ const COLUMNS = [
|
||||
{
|
||||
name: _('logMessage'),
|
||||
itemRenderer: log => (
|
||||
<span>
|
||||
<pre className={styles.widthLimit}>
|
||||
{log.data.error && log.data.error.message}
|
||||
</pre>
|
||||
{log.data.error && log.data.error.code === 'LICENCE_RESTRICTION' && (
|
||||
<a
|
||||
href='https://xcp-ng.org/'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
{_('logSuggestXcpNg')}
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
<pre className={styles.widthLimit}>
|
||||
{log.data.error && log.data.error.message}
|
||||
</pre>
|
||||
),
|
||||
sortCriteria: log => log.data.error && log.data.error.message,
|
||||
},
|
||||
|
||||
@@ -7,7 +7,6 @@ import Icon from 'icon'
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import SortedTable from 'sorted-table'
|
||||
import Tooltip from 'tooltip'
|
||||
import { Text } from 'editable'
|
||||
import { alert } from 'modal'
|
||||
import { Container, Row, Col } from 'grid'
|
||||
@@ -25,7 +24,6 @@ import {
|
||||
editCustomFilter,
|
||||
removeCustomFilter,
|
||||
setDefaultHomeFilter,
|
||||
signOutFromEverywhereElse,
|
||||
subscribeCurrentUser,
|
||||
} from 'xo'
|
||||
|
||||
@@ -402,20 +400,6 @@ export default class User extends Component {
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col smallSize={10} offset={2}>
|
||||
<Tooltip content={_('forgetTokensExplained')}>
|
||||
<ActionButton
|
||||
btnStyle='danger'
|
||||
handler={signOutFromEverywhereElse}
|
||||
icon='disconnect'
|
||||
>
|
||||
{_('forgetTokens')}
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col smallSize={2}>
|
||||
<strong>{_('language')}</strong>
|
||||
|
||||
@@ -301,7 +301,7 @@ export default class NewXosan extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (+process.env.XOA_PLAN === 5) {
|
||||
if (process.env.XOA_PLAN === 5) {
|
||||
return (
|
||||
<em>
|
||||
{_('xosanSourcesDisclaimer', {
|
||||
|
||||
Reference in New Issue
Block a user