chore: format with Prettier

Introduced by 059843f03
This commit is contained in:
Julien Fontanet 2021-06-03 12:12:59 +02:00
parent ec4dde86f5
commit 6d39512576
64 changed files with 1108 additions and 863 deletions

View File

@ -7,7 +7,9 @@ const { execFile } = require('child_process')
const parse = createParser({
keyTransform: key => key.slice(5).toLowerCase(),
})
const makeFunction = command => async (fields, ...args) => {
const makeFunction =
command =>
async (fields, ...args) => {
const info = await fromCallback(execFile, command, [
'--noheading',
'--nosuffix',

View File

@ -20,36 +20,8 @@ if (process.stdout !== undefined && process.stdout.isTTY && process.stderr !== u
}
const NAMESPACE_COLORS = [
196,
202,
208,
214,
220,
226,
190,
154,
118,
82,
46,
47,
48,
49,
50,
51,
45,
39,
33,
27,
21,
57,
93,
129,
165,
201,
200,
199,
198,
197,
196, 202, 208, 214, 220, 226, 190, 154, 118, 82, 46, 47, 48, 49, 50, 51, 45, 39, 33, 27, 21, 57, 93, 129, 165, 201,
200, 199, 198, 197,
]
formatNamespace = namespace => {
// https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/

View File

@ -28,7 +28,8 @@ export default {
buffer.toString('hex', offset + 5, offset + 6),
stringToEth: (string, buffer, offset) => {
const eth = /^([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2})$/.exec(
const eth =
/^([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2}):([0-9A-Fa-f]{2})$/.exec(
string
)
assert(eth !== null)
@ -50,7 +51,8 @@ export default {
),
stringToip4: (string, buffer, offset) => {
const ip = /^([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])$/.exec(
const ip =
/^([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])$/.exec(
string
)
assert(ip !== null)

View File

@ -36,7 +36,14 @@ async function main(argv) {
const { hostname = 'localhost', port } = config?.http?.listen?.https ?? {}
const { _: args, file, help, host, raw, token } = getopts(argv, {
const {
_: args,
file,
help,
host,
raw,
token,
} = getopts(argv, {
alias: { file: 'f', help: 'h' },
boolean: ['help', 'raw'],
default: {

View File

@ -93,10 +93,7 @@ declare namespace event {
snapshot: Task
}
function from(_: {
token: string = ''
timeout?: number
}): {
function from(_: { token: string = ''; timeout?: number }): {
events: Event[]
token: string
}
@ -146,13 +143,13 @@ declare namespace backup {
streamLogs: boolean = false
}): string
function listPoolMetadataBackups(_: {
remotes: { [id: string]: Remote }
}): { [remoteId: string]: { [poolUuid: string]: object[] } }
function listPoolMetadataBackups(_: { remotes: { [id: string]: Remote } }): {
[remoteId: string]: { [poolUuid: string]: object[] }
}
function listVmBackups(_: {
remotes: { [remoteId: string]: Remote }
}): { [remoteId: string]: { [vmUuid: string]: object[] } }
function listVmBackups(_: { remotes: { [remoteId: string]: Remote } }): {
[remoteId: string]: { [vmUuid: string]: object[] }
}
function listXoMetadataBackups(_: { remotes: { [id: string]: Remote } }): { [remoteId: string]: object[] }

View File

@ -320,6 +320,7 @@ You can learn more about XenServer [resource management on the Citrix Website](h
:::tip
XCP-ng doesn't limit VMs to 32 vCPU
:::
### VDI live migration
Thanks to Xen Storage Motion, it's easy to move a VM disk from one storage location to another, while the VM is running! This feature can help you migrate from your local storage to a SAN, or just upgrade your SAN without any downtime.
@ -491,10 +492,12 @@ If you are behind a proxy, please update your `xo-server` configuration to add a
::: danger
As specified in the [documentation](https://xcp-ng.org/docs/requirements.html#pool-requirements) your pool shouldn't consist of hosts from different CPU vendors.
:::
::: warning
- Even with matching CPU vendors, in the case of different CPU models XCP-ng will scale the pool CPU ability to the CPU having the least instructions.
- All the hosts in a pool must run the same XCP-ng version.
:::
### Creating a pool
First you should add your new host to XOA by going to New > Server as described in [the relevant chapter](manage_infrastructure.md#add-a-host).

View File

@ -59,9 +59,11 @@ While creating a standard backup job from your main Xen Orchestra appliance, you
Login is disabled by default on proxy appliances.
If you need to login for some reason, you need to set a password for the xoa user via the XenStore of the VM. The following is to be ran on your XCP-ng host:
```
xe vm-param-set uuid=<UUID> xenstore-data:vm-data/system-account-xoa-password=<password>
```
Where UUID is the uuid of your proxy VM.
Then you need to restart the proxy VM.
@ -74,15 +76,19 @@ First you will need to add a second VIF to your Proxy VM. This can be done in th
After adding the VIF you will need to set an IP for the new NIC, for that you will first need to SSH to the VM [as describe before](/proxy.md#enabling-login-to-proxy-appliance).
Then set the new IP:
```
$ xoa network static eth1
? Static IP for this machine 192.168.100.120
? Network mask (eg 255.255.255.0) 255.255.255.0
```
If you want to set a static address.
```
$ xoa network dhcp eth1
```
If you prefer using DHCP.
:::tip
As XOA uses the first IP address reported by XAPI to contact the proxy appliance, you may have to switch the network card order if you want your proxy to be connected through a specific IP address.

View File

@ -19,9 +19,11 @@ XOA uses HVM mode. If your physical host doesn't support virtualization extensio
## Set or recover XOA VM password
As no password is set for the xoa system user by default, you will need to set your own. This can be done via the XenStore data of the VM. The following is to be ran on your XCP-ng host:
```
xe vm-param-set uuid=<UUID> xenstore-data:vm-data/system-account-xoa-password=<password>
```
Where UUID is the uuid of your XOA VM.
Then you need to restart the VM.

View File

@ -15,7 +15,9 @@ const authorized = () => true // eslint-disable-line no-unused-vars
const forbiddden = () => false // eslint-disable-line no-unused-vars
// eslint-disable-next-line no-unused-vars
const and = (...checkers) => (object, permission) => {
const and =
(...checkers) =>
(object, permission) => {
for (const checker of checkers) {
if (!checker(object, permission)) {
return false
@ -25,7 +27,9 @@ const and = (...checkers) => (object, permission) => {
}
// eslint-disable-next-line no-unused-vars
const or = (...checkers) => (object, permission) => {
const or =
(...checkers) =>
(object, permission) => {
for (const checker of checkers) {
if (checker(object, permission)) {
return true

View File

@ -7,10 +7,7 @@ import execPromise = require('exec-promise')
import through2 = require('through2')
import Xo from 'xo-lib'
const parseBoolean = (
value: string,
defaultValue?: boolean
): boolean | undefined => {
const parseBoolean = (value: string, defaultValue?: boolean): boolean | undefined => {
if (value === undefined || value === '') {
return defaultValue
}
@ -49,12 +46,7 @@ execPromise(
const errors: any[] = []
const stream = process.stdin.pipe(csvParser()).pipe(
through2.obj(
(
{ allowUnauthorized, autoConnect, host, label, password, username },
_,
next
) => {
through2.obj(({ allowUnauthorized, autoConnect, host, label, password, username }, _, next) => {
console.log('server', host)
xo.call('server.add', {
@ -71,8 +63,7 @@ execPromise(
return next()
}
)
}
)
})
)
await new Promise((resolve, reject) => {

View File

@ -445,18 +445,14 @@ class Netbox {
this.#makeRequest('/virtualization/interfaces/', 'DELETE', interfacesToDelete),
isEmpty(interfacesToCreateByVif)
? {}
: this.#makeRequest(
'/virtualization/interfaces/',
'POST',
Object.values(interfacesToCreateByVif)
).then(interfaces => zipObject(Object.keys(interfacesToCreateByVif), interfaces)),
: this.#makeRequest('/virtualization/interfaces/', 'POST', Object.values(interfacesToCreateByVif)).then(
interfaces => zipObject(Object.keys(interfacesToCreateByVif), interfaces)
),
isEmpty(interfacesToUpdateByVif)
? {}
: this.#makeRequest(
'/virtualization/interfaces/',
'PATCH',
Object.values(interfacesToUpdateByVif)
).then(interfaces => zipObject(Object.keys(interfacesToUpdateByVif), interfaces)),
: this.#makeRequest('/virtualization/interfaces/', 'PATCH', Object.values(interfacesToUpdateByVif)).then(
interfaces => zipObject(Object.keys(interfacesToUpdateByVif), interfaces)
),
])
)
.slice(1)

View File

@ -24,7 +24,10 @@ getMethodsInfo.permission = null // user does not need to be authenticated
// -------------------------------------------------------------------
export const getServerTimezone = (tz => () => tz)(moment.tz.guess())
export const getServerTimezone = (
tz => () =>
tz
)(moment.tz.guess())
getServerTimezone.description = 'return the timezone server'
// -------------------------------------------------------------------

View File

@ -40,7 +40,9 @@ export const mergeObjects = objects => Object.assign({}, ...objects)
//
// Ex: crossProduct([ [ { a: 2 }, { b: 3 } ], [ { c: 5 }, { d: 7 } ] ] )
// => [ { a: 2, c: 5 }, { b: 3, c: 5 }, { a: 2, d: 7 }, { b: 3, d: 7 } ]
export const crossProduct = (vectors, mergeFn = mergeObjects) => cb =>
export const crossProduct =
(vectors, mergeFn = mergeObjects) =>
cb =>
combine(vectors)(vector => {
cb(mergeFn(vector))
})

View File

@ -99,13 +99,16 @@ export default class Xapi extends XapiBase {
this._snapshotVm = limitConcurrency(vmSnapshotConcurrency)(this._snapshotVm)
// Patch getObject to resolve _xapiId property.
this.getObject = (getObject => (...args) => {
this.getObject = (
getObject =>
(...args) => {
let tmp
if ((tmp = args[0]) != null && (tmp = tmp._xapiId) != null) {
args[0] = tmp
}
return getObject.apply(this, args)
})(this.getObject)
}
)(this.getObject)
}
// Wait for an object to be in a given state.

View File

@ -68,7 +68,9 @@ export default class IpPools {
if (await store.has(id)) {
await Promise.all(
(await this._app.getAllResourceSets()).map(async set => {
(
await this._app.getAllResourceSets()
).map(async set => {
await this._app.removeLimitFromResourceSet(`ipPool:${id}`, set.id)
return this._app.removeIpPoolFromResourceSet(id, set.id)
})

View File

@ -177,7 +177,9 @@ export default class {
await Promise.all(
difference(set.subjects, subjects).map(async subjectId =>
Promise.all(
(await this._app.getAclsForSubject(subjectId)).map(async acl => {
(
await this._app.getAclsForSubject(subjectId)
).map(async acl => {
try {
const object = this._app.getObject(acl.object)
if ((object.type === 'VM' || object.type === 'VM-snapshot') && object.resourceSet === id) {

View File

@ -131,7 +131,9 @@ const CustomFields = decorate([
}),
provideState({
effects: {
addCustomField: () => (state, { object: { id } }) => {
addCustomField:
() =>
(state, { object: { id } }) => {
const dateTimeUtc = moment.utc()
return form({
component: CustomFieldModal,
@ -149,9 +151,13 @@ const CustomFields = decorate([
),
}).then(params => checkParamsAndCallMethod(addCustomField, id, params))
},
removeCustomField: (_, { currentTarget: { dataset } }) => (_, { object: { id } }) =>
removeCustomField:
(_, { currentTarget: { dataset } }) =>
(_, { object: { id } }) =>
removeCustomField(id, dataset.name),
setCustomField: (effects, { name, value }) => (state, { object: { id } }) => {
setCustomField:
(effects, { name, value }) =>
(state, { object: { id } }) => {
const isDate = PATTERN_DATE_TIME_UTC.test(value)
const dateTimeUtc = isDate ? moment(value).utc() : undefined
return form({

View File

@ -4,13 +4,17 @@ export const generateId = () => `i${Math.random().toString(36).slice(2)}`
// TODO: remove these functions once the PR: https://github.com/JsCommunity/reaclette/pull/5 has been merged
// It only supports native inputs
export const linkState = (_, { target }) => () => ({
export const linkState =
(_, { target }) =>
() => ({
[target.name]:
target.nodeName.toLowerCase() === 'input' && target.type.toLowerCase() === 'checkbox'
? target.checked
: target.value,
})
export const toggleState = (_, { currentTarget: { name } }) => state => ({
export const toggleState =
(_, { currentTarget: { name } }) =>
state => ({
[name]: !state[name],
})

View File

@ -635,7 +635,10 @@ const renderXoItem = (item, { className, type: xoType, ...props } = {}) => {
export { renderXoItem as default }
export const getRenderXoItemOfType = type => (item, options = {}) => renderXoItem(item, { ...options, type })
export const getRenderXoItemOfType =
type =>
(item, options = {}) =>
renderXoItem(item, { ...options, type })
const GenericXoItem = connectStore(() => {
const getObject = createGetObject()

View File

@ -193,7 +193,9 @@ class ToggleTd extends Component {
const TableSelect = decorate([
provideState({
effects: {
onChange: (_, tdId, add) => (_, { value, onChange, options }) => {
onChange:
(_, tdId, add) =>
(_, { value, onChange, options }) => {
let newValue = [...value]
const index = sortedIndex(newValue, tdId)
if (add) {
@ -207,7 +209,9 @@ const TableSelect = decorate([
}
onChange(newValue)
},
selectAll: () => ({ optionsValues }, { onChange }) => {
selectAll:
() =>
({ optionsValues }, { onChange }) => {
onChange(optionsValues)
},
},
@ -258,7 +262,9 @@ TableSelect.propTypes = {
const TimePicker = decorate([
provideState({
effects: {
onChange: (_, value) => ({ optionsValues }, { onChange }) => {
onChange:
(_, value) =>
({ optionsValues }, { onChange }) => {
if (Array.isArray(value)) {
value = value.length === optionsValues.length ? '*' : value.join(',')
} else {

View File

@ -524,7 +524,9 @@ export const SelectTag = decorate([
editing: false,
}),
effects: {
addTag: (effects, newTag) => ({ value }, { multi, onChange }) => {
addTag:
(effects, newTag) =>
({ value }, { multi, onChange }) => {
if (newTag === value || (multi && includes(value, newTag))) {
return
}

View File

@ -287,7 +287,9 @@ export const isAdmin = (...args) => {
// Common selector creators.
// Creates an object selector from an id selector.
export const createGetObject = (idSelector = _getId) => (state, props, useResourceSet) => {
export const createGetObject =
(idSelector = _getId) =>
(state, props, useResourceSet) => {
const object = state.objects.all[idSelector(state, props)]
if (!object) {
return
@ -462,7 +464,10 @@ export const createDoesHostNeedRestart = hostSelector => {
const patchRequiresReboot = createGetObjectsOfType('patch')
.pick(create(hostSelector, host => host.patches))
.find(
create(hostSelector, host => ({ guidance, time, upgrade }) =>
create(
hostSelector,
host =>
({ guidance, time, upgrade }) =>
time > host.startTime &&
(upgrade || some(guidance, action => action === 'restartHost' || action === 'restartXapi'))
)

View File

@ -140,7 +140,10 @@ const Action = decorate([
computed: {
disabled: ({ items }, { disabled, userData }) =>
typeof disabled === 'function' ? disabled(items, userData) : disabled,
handler: ({ items }, { handler, userData }) => () => handler(items, userData),
handler:
({ items }, { handler, userData }) =>
() =>
handler(items, userData),
icon: ({ items }, { icon, userData }) => (typeof icon === 'function' ? icon(items, userData) : icon),
items: (_, { items, grouped }) => (Array.isArray(items) || !grouped ? items : [items]),
label: ({ items }, { label, userData }) => (typeof label === 'function' ? label(items, userData) : label),

View File

@ -7,7 +7,9 @@ import * as actions from './actions'
// ===================================================================
const createAsyncHandler = ({ error, next }) => (state, payload, action) => {
const createAsyncHandler =
({ error, next }) =>
(state, payload, action) => {
if (action.error) {
if (error) {
return error(state, payload, action)

View File

@ -576,7 +576,9 @@ export const downloadLog = ({ log, date, type }) => {
// ])
// )
// ```
export const createCompare = criterias => (...items) => {
export const createCompare =
criterias =>
(...items) => {
let res = 0
// Array.find to stop when the result is != 0
criterias.find(fn => {

View File

@ -1368,7 +1368,9 @@ export const createVms = (args, nameLabels, cloudConfigs) =>
body: _('newVmCreateVmsConfirm', { nbVms: nameLabels.length }),
}).then(() =>
Promise.all(
map(nameLabels, (
map(
nameLabels,
(
name_label, // eslint-disable-line camelcase
i
) =>

View File

@ -25,7 +25,14 @@ import { ejectCd, isSrWritable, setDefaultSr } from 'xo'
return {
pool: getPool,
poolMaster: createGetObject(createSelector(getPool, ({ master }) => master)),
vbds: createGetObjectsOfType('VBD').filter(createSelector(getPool, ({ id }) => vbd => vbd.$pool === id)),
vbds: createGetObjectsOfType('VBD').filter(
createSelector(
getPool,
({ id }) =>
vbd =>
vbd.$pool === id
)
),
}
},
{ withRef: true }

View File

@ -70,7 +70,9 @@ export default class MigrateVmModalBody extends BaseComponent {
this._getHostPredicate = createSelector(
() => this.props.vm,
({ $container }) => host => host.id !== $container
({ $container }) =>
host =>
host.id !== $container
)
this._getSrPredicate = createSelector(

View File

@ -11,7 +11,11 @@ import { Sr } from '../../render-xo-item'
@connectStore(
{
srIds: createSelector(
createGetObjectsOfType('PBD').filter((_, { hostIds }) => pbd => hostIds.includes(pbd.host)),
createGetObjectsOfType('PBD').filter(
(_, { hostIds }) =>
pbd =>
hostIds.includes(pbd.host)
),
pbds => {
const srIds = new Set([])
for (const id in pbds) {

View File

@ -8,7 +8,11 @@ import { isLatestXosanPackInstalled, connectStore, findLatestPack } from 'utils'
@connectStore(
{
hosts: createGetObjectsOfType('host').filter((_, { pool }) => host => host.$pool === pool.id),
hosts: createGetObjectsOfType('host').filter(
(_, { pool }) =>
host =>
host.$pool === pool.id
),
},
{ withRef: true }
)

View File

@ -264,17 +264,8 @@ export default class RestoreFileModalBody extends Component {
render() {
const { backups } = this.props
const {
backup,
disk,
partition,
partitions,
path,
scanDiskError,
listFilesError,
scanningFiles,
selectedFiles,
} = this.state
const { backup, disk, partition, partitions, path, scanDiskError, listFilesError, scanningFiles, selectedFiles } =
this.state
const noPartitions = isEmpty(partitions)
const redundantFiles = this._getRedundantFiles()

View File

@ -93,14 +93,18 @@ const Schedules = decorate([
delete settings[id]
props.handlerSettings(settings)
},
showModal: (effects, { id = generateRandomId(), name, cron, timezone } = DEFAULT_SCHEDULE) => async (
state,
props
) => {
showModal:
(effects, { id = generateRandomId(), name, cron, timezone } = DEFAULT_SCHEDULE) =>
async (state, props) => {
const schedule = get(() => props.schedules[id])
const setting = get(() => props.settings[id])
const { cron: newCron, name: newName, timezone: newTimezone, ...newSetting } = await form({
const {
cron: newCron,
name: newName,
timezone: newTimezone,
...newSetting
} = await form({
defaultValue: setDefaultRetentions({ cron, name, timezone, ...setting }, state.retentions),
render: props => <NewSchedule retentions={state.retentions} {...props} />,
header: (
@ -135,7 +139,9 @@ const Schedules = decorate([
},
})
},
toggleScheduleState: (_, id) => (state, { handlerSchedules, schedules }) => {
toggleScheduleState:
(_, id) =>
(state, { handlerSchedules, schedules }) => {
const schedule = schedules[id]
handlerSchedules({
...schedules,
@ -148,7 +154,9 @@ const Schedules = decorate([
},
computed: {
columns: (_, { retentions }) => [...COLUMNS, ...retentions.map(({ defaultValue, ...props }) => props)],
rowTransform: (_, { settings = {}, retentions }) => schedule => {
rowTransform:
(_, { settings = {}, retentions }) =>
schedule => {
schedule = { ...schedule, ...settings[schedule.id] }
return setDefaultRetentions(schedule, retentions)
},

View File

@ -14,19 +14,25 @@ import { areRetentionsMissing } from '.'
export default decorate([
provideState({
effects: {
setSchedule: (_, params) => (_, { value, onChange }) => {
setSchedule:
(_, params) =>
(_, { value, onChange }) => {
onChange({
...value,
...params,
})
},
setCronTimezone: ({ setSchedule }, { cronPattern: cron, timezone }) => () => {
setCronTimezone:
({ setSchedule }, { cronPattern: cron, timezone }) =>
() => {
setSchedule({
cron,
timezone,
})
},
setName: ({ setSchedule }, { target: { value } }) => () => {
setName:
({ setSchedule }, { target: { value } }) =>
() => {
setSchedule({
name: value.trim() === '' ? null : value,
})

View File

@ -212,7 +212,8 @@ const DeleteOldBackupsFirst = ({ handler, handlerParam, value }) => (
)
const New = decorate([
New => props => (
New => props =>
(
<Upgrade place='newBackup' required={2}>
<New {...props} />
</Upgrade>
@ -349,11 +350,15 @@ const New = decorate([
vms: state.smartMode ? state.vmsSmartPattern : constructPattern(state.vms),
})
},
toggleMode: (_, { mode }) => state => ({
toggleMode:
(_, { mode }) =>
state => ({
...state,
[mode]: !state[mode],
}),
setCheckboxValue: (_, { target: { checked, name } }) => state => ({
setCheckboxValue:
(_, { target: { checked, name } }) =>
state => ({
...state,
[name]: checked,
}),
@ -367,11 +372,15 @@ const New = decorate([
},
},
}),
setName: (_, { target: { value } }) => state => ({
setName:
(_, { target: { value } }) =>
state => ({
...state,
name: value,
}),
setTargetDeleteFirst: (_, id) => ({ propSettings, settings = propSettings }) => ({
setTargetDeleteFirst:
(_, id) =>
({ propSettings, settings = propSettings }) => ({
settings: settings.set(id, {
deleteFirst: !settings.getIn([id, 'deleteFirst']),
}),
@ -403,7 +412,9 @@ const New = decorate([
}
},
setVms: (_, vms) => state => ({ ...state, vms }),
updateParams: () => (_, { job, schedules }) => {
updateParams:
() =>
(_, { job, schedules }) => {
const remotes = job.remotes !== undefined ? destructPattern(job.remotes) : []
const srs = job.srs !== undefined ? destructPattern(job.srs) : []
@ -421,7 +432,9 @@ const New = decorate([
...destructVmsPattern(job.vms),
}
},
showScheduleModal: ({ saveSchedule }, storedSchedule = DEFAULT_SCHEDULE) => async (
showScheduleModal:
({ saveSchedule }, storedSchedule = DEFAULT_SCHEDULE) =>
async (
{ copyMode, exportMode, deltaMode, isDelta, propSettings, settings = propSettings, snapshotMode },
{ intl: { formatMessage } }
) => {
@ -461,7 +474,9 @@ const New = decorate([
id: storedSchedule.id || generateRandomId(),
})
},
deleteSchedule: (_, schedule) => ({ schedules: oldSchedules, propSettings, settings = propSettings }) => {
deleteSchedule:
(_, schedule) =>
({ schedules: oldSchedules, propSettings, settings = propSettings }) => {
const id = resolveId(schedule)
const schedules = { ...oldSchedules }
delete schedules[id]
@ -470,10 +485,12 @@ const New = decorate([
settings: settings.delete(id),
}
},
saveSchedule: (
saveSchedule:
(
_,
{ copyRetention, cron, enabled = true, exportRetention, fullInterval, id, name, snapshotRetention, timezone }
) => ({ propSettings, schedules, settings = propSettings }) => ({
) =>
({ propSettings, schedules, settings = propSettings }) => ({
schedules: {
...schedules,
[id]: {
@ -509,7 +526,9 @@ const New = decorate([
notValues,
},
}),
resetJob: ({ updateParams }) => (state, { job }) => {
resetJob:
({ updateParams }) =>
(state, { job }) => {
if (job !== undefined) {
updateParams()
}
@ -520,10 +539,14 @@ const New = decorate([
setProxy(_, id) {
this.state._proxyId = id
},
toggleDisplayAdvancedSettings: () => ({ displayAdvancedSettings }) => ({
toggleDisplayAdvancedSettings:
() =>
({ displayAdvancedSettings }) => ({
_displayAdvancedSettings: !displayAdvancedSettings,
}),
setGlobalSettings: (_, globalSettings) => ({ propSettings, settings = propSettings }) => ({
setGlobalSettings:
(_, globalSettings) =>
({ propSettings, settings = propSettings }) => ({
settings: settings.update('', setting => ({
...setting,
...globalSettings,
@ -545,17 +568,23 @@ const New = decorate([
reportRecipients: (reportRecipients.splice(key, 1), reportRecipients),
})
},
setReportWhen: ({ setGlobalSettings }, { value }) => () => {
setReportWhen:
({ setGlobalSettings }, { value }) =>
() => {
setGlobalSettings({
reportWhen: value,
})
},
setConcurrency: ({ setGlobalSettings }, concurrency) => () => {
setConcurrency:
({ setGlobalSettings }, concurrency) =>
() => {
setGlobalSettings({
concurrency,
})
},
setTimeout: ({ setGlobalSettings }, value) => () => {
setTimeout:
({ setGlobalSettings }, value) =>
() => {
setGlobalSettings({
timeout: value && value * 3600e3,
})
@ -565,7 +594,9 @@ const New = decorate([
fullInterval,
})
},
setOfflineBackup: ({ setGlobalSettings }, { target: { checked: offlineBackup } }) => () => {
setOfflineBackup:
({ setGlobalSettings }, { target: { checked: offlineBackup } }) =>
() => {
setGlobalSettings({
offlineBackup,
})
@ -618,7 +649,9 @@ const New = decorate([
...vmsPattern,
tags: constructSmartPattern(tags, normalizeTagValues),
}),
vmPredicate: ({ isDelta }, { hostsById, poolsById }) => ({ $container }) =>
vmPredicate:
({ isDelta }, { hostsById, poolsById }) =>
({ $container }) =>
!isDelta ||
canDeltaBackup(
get(() => hostsById[$container].version) || get(() => hostsById[poolsById[$container].master].version)
@ -639,8 +672,13 @@ const New = decorate([
)
)
},
srPredicate: ({ srs }) => sr => isSrWritable(sr) && !includes(srs, sr.id),
remotePredicate: ({ proxyId, remotes }) => remote => {
srPredicate:
({ srs }) =>
sr =>
isSrWritable(sr) && !includes(srs, sr.id),
remotePredicate:
({ proxyId, remotes }) =>
remote => {
if (proxyId === null) {
proxyId = undefined
}

View File

@ -72,7 +72,8 @@ const getInitialState = () => ({
})
export default decorate([
New => props => (
New => props =>
(
<Upgrade place='newMetadataBackup' required={3}>
<New {...props} />
</Upgrade>
@ -166,7 +167,9 @@ export default decorate([
setSettings: (_, _settings) => () => ({
_settings,
}),
setGlobalSettings: ({ setSettings }, name, value) => ({ settings = {} }) => {
setGlobalSettings:
({ setSettings }, name, value) =>
({ settings = {} }) => {
setSettings({
...settings,
[GLOBAL_SETTING_KEY]: {
@ -178,10 +181,14 @@ export default decorate([
setReportWhen({ setGlobalSettings }, { value }) {
setGlobalSettings('reportWhen', value)
},
toggleMode: (_, { mode }) => state => ({
toggleMode:
(_, { mode }) =>
state => ({
[`_${mode}`]: !state[mode],
}),
addRemote: (_, { id }) => state => ({
addRemote:
(_, { id }) =>
state => ({
_remotes: [...state.remotes, id],
}),
deleteRemote: (_, key) => state => {
@ -227,7 +234,9 @@ export default decorate([
})
),
remotes: ({ _remotes }, { job }) => defined(_remotes, () => destructPattern(job.remotes), []),
remotesPredicate: ({ proxyId, remotes }) => remote => {
remotesPredicate:
({ proxyId, remotes }) =>
remote => {
if (proxyId === null) {
proxyId = undefined
}

View File

@ -20,34 +20,46 @@ const New = decorate([
idInputName: generateId,
},
effects: {
setSchedule: (_, params) => (_, { value, onChange }) => {
setSchedule:
(_, params) =>
(_, { value, onChange }) => {
onChange({
...value,
...params,
})
},
setExportRetention: ({ setSchedule }, exportRetention) => () => {
setExportRetention:
({ setSchedule }, exportRetention) =>
() => {
setSchedule({
exportRetention,
})
},
setCopyRetention: ({ setSchedule }, copyRetention) => () => {
setCopyRetention:
({ setSchedule }, copyRetention) =>
() => {
setSchedule({
copyRetention,
})
},
setSnapshotRetention: ({ setSchedule }, snapshotRetention) => () => {
setSnapshotRetention:
({ setSchedule }, snapshotRetention) =>
() => {
setSchedule({
snapshotRetention,
})
},
setCronTimezone: ({ setSchedule }, { cronPattern: cron, timezone }) => () => {
setCronTimezone:
({ setSchedule }, { cronPattern: cron, timezone }) =>
() => {
setSchedule({
cron,
timezone,
})
},
setName: ({ setSchedule }, { target: { value } }) => () => {
setName:
({ setSchedule }, { target: { value } }) =>
() => {
setSchedule({
name: value.trim() === '' ? null : value,
})

View File

@ -39,7 +39,9 @@ export default decorate([
level: 'danger',
},
],
rowTransform: ({ propSettings, settings = propSettings }) => schedule => ({
rowTransform:
({ propSettings, settings = propSettings }) =>
schedule => ({
...schedule,
...settings.get(schedule.id),
}),

View File

@ -27,7 +27,9 @@ const SmartBackup = decorate([
}),
provideState({
effects: {
setPattern: (_, value) => (_, { pattern, onChange }) => {
setPattern:
(_, value) =>
(_, { pattern, onChange }) => {
onChange({
...pattern,
...value,
@ -38,7 +40,9 @@ const SmartBackup = decorate([
power_state: powerState === 'All' ? undefined : powerState,
})
},
setPoolPattern: ({ setPattern }, { values, notValues }) => ({ pools }) => {
setPoolPattern:
({ setPattern }, { values, notValues }) =>
({ pools }) => {
setPattern({
$pool: constructSmartPattern(
{
@ -57,7 +61,9 @@ const SmartBackup = decorate([
},
},
computed: {
poolPredicate: (_, { deltaMode, hosts }) => pool =>
poolPredicate:
(_, { deltaMode, hosts }) =>
pool =>
!deltaMode || canDeltaBackup(get(() => hosts[pool.master].version)),
pools: (_, { pattern }) => (pattern.$pool !== undefined ? destructSmartPattern(pattern.$pool) : {}),
},

View File

@ -238,7 +238,9 @@ const AttachedVdisTable = decorate([
vdis: createGetObjectsOfType('VDI'),
vdiSnapshots: createGetObjectsOfType('VDI-snapshot'),
}),
({ columns, rowTransform }) => ({ pools, srs, vbds, vdis, vdiSnapshots }) => (
({ columns, rowTransform }) =>
({ pools, srs, vbds, vdis, vdiSnapshots }) =>
(
<NoObjects
actions={CONTROL_DOMAIN_VDIS_ACTIONS}
collection={vbds}

View File

@ -71,7 +71,9 @@ const DiskImport = decorate([
)
return { disks: disks.filter(disk => disk !== undefined), loadingDisks: false }
},
import: () => async ({ disks, mapDescriptions, mapNames, sr }) => {
import:
() =>
async ({ disks, mapDescriptions, mapNames, sr }) => {
await importDisks(
disks.map(({ id, name, ...disk }) => ({
...disk,
@ -82,11 +84,15 @@ const DiskImport = decorate([
)
},
linkState,
onChangeDescription: (_, { target: { name, value } }) => ({ mapDescriptions }) => {
onChangeDescription:
(_, { target: { name, value } }) =>
({ mapDescriptions }) => {
mapDescriptions[name] = value
return { mapDescriptions }
},
onChangeName: (_, { target: { name, value } }) => ({ mapNames }) => {
onChangeName:
(_, { target: { name, value } }) =>
({ mapNames }) => {
mapNames[name] = value
return { mapNames }
},

View File

@ -928,14 +928,8 @@ export default class Home extends Component {
} = this.state
const options = OPTIONS[type]
const {
filters,
mainActions,
otherActions,
showHostsSelector,
showPoolsSelector,
showResourceSetsSelector,
} = options
const { filters, mainActions, otherActions, showHostsSelector, showPoolsSelector, showResourceSetsSelector } =
options
return (
<Container>

View File

@ -53,18 +53,32 @@ const isRunning = host => host && host.power_state === 'Running'
const getPool = createGetObject((state, props) => getHost(state, props).$pool)
const getVmController = createGetObjectsOfType('VM-controller').find(
createSelector(getHost, ({ id }) => obj => obj.$container === id)
createSelector(
getHost,
({ id }) =>
obj =>
obj.$container === id
)
)
const getHostVms = createGetObjectsOfType('VM').filter(
createSelector(getHost, ({ id }) => obj => obj.$container === id)
createSelector(
getHost,
({ id }) =>
obj =>
obj.$container === id
)
)
const getNumberOfVms = getHostVms.count()
const getLogs = createGetObjectsOfType('message')
.filter(
createSelector(getHost, getVmController, (host, controller) => ({ $object }) =>
createSelector(
getHost,
getVmController,
(host, controller) =>
({ $object }) =>
$object === host.id || $object === (controller !== undefined && controller.id)
)
)

View File

@ -88,7 +88,9 @@ const SetControlDomainMemory = ({ value, onChange }) => (
const MultipathableSrs = decorate([
connectStore({
pbds: createGetObjectsOfType('PBD').filter((_, { hostId }) => pbd =>
pbds: createGetObjectsOfType('PBD').filter(
(_, { hostId }) =>
pbd =>
pbd.host === hostId && Boolean(pbd.otherConfig.multipathed)
),
}),

View File

@ -44,8 +44,14 @@ export default decorate([
},
},
computed: {
networkPredicate: (_, { value: { pool } }) => network => pool.id === network.$pool,
srPredicate: (_, { value }) => sr => sr.$pool === get(() => value.pool.id) && isSrWritable(sr),
networkPredicate:
(_, { value: { pool } }) =>
network =>
pool.id === network.$pool,
srPredicate:
(_, { value }) =>
sr =>
sr.$pool === get(() => value.pool.id) && isSrWritable(sr),
},
}),
injectState,

View File

@ -47,15 +47,8 @@ export default decorate([
}),
effects: {
async install() {
const {
id,
name,
namespace,
markHubResourceAsInstalled,
markHubResourceAsInstalling,
templates,
version,
} = this.props
const { id, name, namespace, markHubResourceAsInstalled, markHubResourceAsInstalling, templates, version } =
this.props
const { isTemplateInstalled } = this.state
const resourceParams = await form({
defaultValue: {
@ -227,9 +220,13 @@ export default decorate([
isTemplateInstalledOnAllPools: ({ installedTemplates }, { pools }) =>
installedTemplates.length > 0 &&
pools.every(pool => installedTemplates.find(template => template.$pool === pool.id) !== undefined),
isTemplateInstalled: ({ installedTemplates }) => pool =>
isTemplateInstalled:
({ installedTemplates }) =>
pool =>
installedTemplates.find(template => template.$pool === pool.id) === undefined,
isPoolCreated: ({ installedTemplates }) => pool =>
isPoolCreated:
({ installedTemplates }) =>
pool =>
installedTemplates.find(template => template.$pool === pool.id) !== undefined,
},
}),

View File

@ -307,7 +307,9 @@ export default decorate([
this.state._status = status
this.state.page = 1
},
restartVmJob: (_, params) => async (_, { log: { scheduleId, jobId } }) => {
restartVmJob:
(_, params) =>
async (_, { log: { scheduleId, jobId } }) => {
await runBackupNgJob({
force: get(() => params.force),
id: jobId,
@ -361,7 +363,10 @@ export default decorate([
const start = (page - 1) * ITEMS_PER_PAGE
return tasksFilteredByStatus.slice(start, start + ITEMS_PER_PAGE)
},
optionRenderer: ({ countByStatus }) => ({ label, value }) => (
optionRenderer:
({ countByStatus }) =>
({ label, value }) =>
(
<span>
{_(label)} ({countByStatus[value] || 0})
</span>

View File

@ -27,9 +27,13 @@ export default decorate([
})),
provideState({
effects: {
_downloadLog: () => ({ formattedLog }, { log }) =>
_downloadLog:
() =>
({ formattedLog }, { log }) =>
downloadLog({ log: formattedLog, date: log.start, type: 'backup NG' }),
restartFailedVms: (_, params) => async (_, { log: { jobId: id, scheduleId: schedule, tasks, infos } }) => {
restartFailedVms:
(_, params) =>
async (_, { log: { jobId: id, scheduleId: schedule, tasks, infos } }) => {
let vms
if (tasks !== undefined) {
const scheduledVms = get(() => infos.find(({ message }) => message === 'vms').data.vms)

View File

@ -260,7 +260,7 @@ export default class NewVm extends BaseComponent {
() => this.props.resourceSets,
createSelector(
() => this.props.location.query.resourceSet,
resourceSetId => resourceSet => (resourceSet !== undefined ? resourceSetId === resourceSet.id : undefined)
resourceSetId => resourceSet => resourceSet !== undefined ? resourceSetId === resourceSet.id : undefined
)
)
@ -582,7 +582,9 @@ export default class NewVm extends BaseComponent {
const { pool } = this.props
return pool && pool.id
},
poolId => ({ $pool }) => $pool === poolId
poolId =>
({ $pool }) =>
$pool === poolId
)
_getIsInResourceSet = createSelector(
() => {
@ -592,8 +594,10 @@ export default class NewVm extends BaseComponent {
objectsIds => id => includes(objectsIds, id)
)
_getVmPredicate = createSelector(this._getIsInPool, this._getIsInResourceSet, (isInPool, isInResourceSet) => vm =>
isInResourceSet(vm.id) || isInPool(vm)
_getVmPredicate = createSelector(
this._getIsInPool,
this._getIsInResourceSet,
(isInPool, isInResourceSet) => vm => isInResourceSet(vm.id) || isInPool(vm)
)
_getSrPredicate = createSelector(
this._getIsInPool,

View File

@ -102,7 +102,10 @@ const NewNetwork = decorate([
initialize: async () => ({ bondModes: await getBondModes() }),
linkState,
onChangeMode: (_, bondMode) => ({ bondMode }),
onChangePif: (_, value) => ({ bonded }) => (bonded ? { pifs: value } : { pif: value }),
onChangePif:
(_, value) =>
({ bonded }) =>
bonded ? { pifs: value } : { pif: value },
onChangeEncapsulation(_, encapsulation) {
return { encapsulation: encapsulation.value }
},
@ -144,12 +147,25 @@ const NewNetwork = decorate([
value: mode,
}))
: [],
hostPredicate: ({ networks }, { pool }) => host =>
hostPredicate:
({ networks }, { pool }) =>
host =>
host.$pool === pool.id || networks.some(({ pool }) => pool !== undefined && pool.id === host.$pool),
pifPredicate: (_, { pool }) => pif => !pif.isBondSlave && pif.vlan === -1 && pif.$host === (pool && pool.master),
pifPredicateSdnController: (_, { pool }) => pif => canSupportPrivateNetwork(pool, pif),
networkPifPredicate: ({ networks }) => (pif, key) => canSupportPrivateNetwork(networks[key].pool, pif),
networkPoolPredicate: ({ networks }, { pool: rootPool }) => (pool, index) =>
pifPredicate:
(_, { pool }) =>
pif =>
!pif.isBondSlave && pif.vlan === -1 && pif.$host === (pool && pool.master),
pifPredicateSdnController:
(_, { pool }) =>
pif =>
canSupportPrivateNetwork(pool, pif),
networkPifPredicate:
({ networks }) =>
(pif, key) =>
canSupportPrivateNetwork(networks[key].pool, pif),
networkPoolPredicate:
({ networks }, { pool: rootPool }) =>
(pool, index) =>
pool.id !== rootPool.id &&
!networks.some(
({ pool: networksPool = {} }, networksIndex) => pool.id === networksPool.id && index !== networksIndex

View File

@ -35,23 +35,56 @@ import TabPatches from './tab-patches'
const getMaster = createGetObject((state, props) => getPool(state, props).master)
const getNetworks = createGetObjectsOfType('network')
.filter(createSelector(getPool, ({ id }) => network => network.$pool === id))
.filter(
createSelector(
getPool,
({ id }) =>
network =>
network.$pool === id
)
)
.sort()
const getPifs = createGetObjectsOfType('PIF')
.filter(createSelector(getPool, ({ id }) => pif => pif.$pool === id))
.filter(
createSelector(
getPool,
({ id }) =>
pif =>
pif.$pool === id
)
)
.sort()
const getHosts = createGetObjectsOfType('host')
.filter(createSelector(getPool, ({ id }) => obj => obj.$pool === id))
.filter(
createSelector(
getPool,
({ id }) =>
obj =>
obj.$pool === id
)
)
.sort()
const getPoolSrs = createGetObjectsOfType('SR')
.filter(createSelector(getPool, ({ id }) => sr => sr.$pool === id))
.filter(
createSelector(
getPool,
({ id }) =>
sr =>
sr.$pool === id
)
)
.sort()
const getNumberOfVms = createGetObjectsOfType('VM').count(
createSelector(getPool, ({ id }) => obj => obj.$pool === id)
createSelector(
getPool,
({ id }) =>
obj =>
obj.$pool === id
)
)
const getLogs = createGetObjectMessages(getPool)

View File

@ -61,7 +61,12 @@ class PoolMaster extends Component {
.sort()
return {
hosts: getHosts,
hostsByMultipathing: createGroupBy(getHosts, () => ({ multipathing }) => (multipathing ? 'enabled' : 'disabled')),
hostsByMultipathing: createGroupBy(
getHosts,
() =>
({ multipathing }) =>
multipathing ? 'enabled' : 'disabled'
),
gpuGroups: createGetObjectsOfType('gpuGroup')
.filter((_, { pool }) => ({ $pool: pool.id }))
.sort(),

View File

@ -79,7 +79,9 @@ const Modal = decorate([
idSelectSr: generateId,
isStaticMode: (state, { value }) => value.networkMode === 'static',
srPredicate: (state, { pbds, hosts }) => sr =>
srPredicate:
(state, { pbds, hosts }) =>
sr =>
isSrWritable(sr) && sr.$PBDs.some(pbd => get(() => hosts[pbds[pbd].host].hvmCapable)),
networkPredicate: (state, { value }) => value.sr && (network => value.sr.$pool === network.$pool),
},

View File

@ -145,7 +145,9 @@ export default class Acls extends Component {
_getObjectPredicate = createSelector(
() => this.state.typeFilters,
() => this.state.someTypeFilters,
(typeFilters, someTypeFilters) => ({ type }) => !someTypeFilters || typeFilters[type]
(typeFilters, someTypeFilters) =>
({ type }) =>
!someTypeFilters || typeFilters[type]
)
_selectAll = () => {

View File

@ -62,7 +62,9 @@ export default decorate([
provideState({
initialState: () => initialParams,
effects: {
setInputValue: (_, { target: { name, value } }) => state => ({
setInputValue:
(_, { target: { name, value } }) =>
state => ({
...state,
[name]: value,
}),
@ -70,18 +72,24 @@ export default decorate([
...state,
...initialParams,
}),
createCloudConfig: ({ reset }) => async ({ name, template = DEFAULT_CLOUD_CONFIG_TEMPLATE }) => {
createCloudConfig:
({ reset }) =>
async ({ name, template = DEFAULT_CLOUD_CONFIG_TEMPLATE }) => {
await createCloudConfig({ name, template })
reset()
},
editCloudConfig: ({ reset }) => async ({ name, template, cloudConfigToEditId }, { cloudConfigs }) => {
editCloudConfig:
({ reset }) =>
async ({ name, template, cloudConfigToEditId }, { cloudConfigs }) => {
const oldCloudConfig = find(cloudConfigs, { id: cloudConfigToEditId })
if (oldCloudConfig.name !== name || oldCloudConfig.template !== template) {
await editCloudConfig(cloudConfigToEditId, { name, template })
}
reset()
},
populateForm: (_, { id, name, template }) => state => ({
populateForm:
(_, { id, name, template }) =>
state => ({
...state,
name,
cloudConfigToEditId: id,

View File

@ -51,7 +51,9 @@ export default decorate([
setProxy(_, proxy) {
this.state.proxyId = resolveId(proxy)
},
editRemote: ({ reset }) => state => {
editRemote:
({ reset }) =>
state => {
const {
remote,
domain = remote.domain || '',
@ -88,7 +90,9 @@ export default decorate([
proxy: proxyId,
}).then(reset)
},
createRemote: ({ reset }) => async (state, { remotes }) => {
createRemote:
({ reset }) =>
async (state, { remotes }) => {
if (some(remotes, { name: state.name })) {
return alert(
<span>

View File

@ -210,7 +210,9 @@ export default class TabGeneral extends Component {
}
)
_getGenerateLink = createSelector(this._getDiskGroups, diskGroups => ids =>
_getGenerateLink = createSelector(
this._getDiskGroups,
diskGroups => ids =>
`#/srs/${this.props.sr.id}/disks?s=${encodeURIComponent(
`id:|(${flattenDeep(
map(pick(keyBy(diskGroups, 'id'), ids), ({ id, baseCopies, vdis, snapshots, type }) =>

View File

@ -79,7 +79,11 @@ const Field = ({ title, children }) => (
})
class Node extends Component {
_replaceBrick = async ({ brick, vm }) => {
const { sr, brickSize, onSameVm = false } = await confirm({
const {
sr,
brickSize,
onSameVm = false,
} = await confirm({
icon: 'refresh',
title: _('xosanReplace'),
body: <ReplaceBrickModalBody vm={vm} />,

View File

@ -87,8 +87,9 @@ const shareVmProxy = vm => shareVm(vm, vm.resourceSet)
const getSrs = createGetObjectsOfType('SR').pick(createSelector(getVdis, vdis => uniq(map(vdis, '$SR'))))
const getSrsContainers = createSelector(getSrs, srs => uniq(map(srs, '$container')))
const getAffinityHostPredicate = createSelector(getSrsContainers, containers => host =>
every(containers, container => container === host.$pool || container === host.id)
const getAffinityHostPredicate = createSelector(
getSrsContainers,
containers => host => every(containers, container => container === host.$pool || container === host.id)
)
return {
@ -275,7 +276,9 @@ class AddAclsModal extends Component {
_getPredicate = createSelector(
() => this.props.acls,
() => this.props.vm,
(acls, object) => ({ id: subject, permission }) => permission !== 'admin' && !some(acls, { object, subject })
(acls, object) =>
({ id: subject, permission }) =>
permission !== 'admin' && !some(acls, { object, subject })
)
render() {
@ -306,7 +309,9 @@ const Acls = decorate([
}),
provideState({
effects: {
addAcls: () => (state, { acls, vm }) =>
addAcls:
() =>
(state, { acls, vm }) =>
confirm({
title: _('vmAddAcls'),
body: <AddAclsModal acls={acls} vm={vm} />,
@ -319,7 +324,9 @@ const Acls = decorate([
return Promise.all(map(subjects, subject => addAcl({ subject, object: vm, action })))
})
.catch(err => err && error(_('addAclsErrorTitle'), err.message || String(err))),
removeAcl: (_, { currentTarget: { dataset } }) => (_, { vm: object }) =>
removeAcl:
(_, { currentTarget: { dataset } }) =>
(_, { vm: object }) =>
removeAcl({
action: dataset.action,
object,

View File

@ -18,7 +18,10 @@ const BackupTab = decorate([
provideState({
computed: {
jobIds: ({ predicate }, { jobs }) => filter(jobs, predicate).map(_ => _.id),
predicate: (_, { vm }) => ({ vms }) => vms !== undefined && createPredicate(omit(vms, 'power_state'))(vm),
predicate:
(_, { vm }) =>
({ vms }) =>
vms !== undefined && createPredicate(omit(vms, 'power_state'))(vm),
},
}),
injectState,

View File

@ -565,7 +565,9 @@ export default class TabDisks extends Component {
}
)
_getCheckSr = createSelector(this._getRequiredHost, requiredHost => sr =>
_getCheckSr = createSelector(
this._getRequiredHost,
requiredHost => sr =>
sr === undefined || isSrShared(sr) || requiredHost === undefined || sr.$container === requiredHost
)
@ -597,7 +599,9 @@ export default class TabDisks extends Component {
)
)
_getGenerateWarningBeforeMigrate = createSelector(this._getCheckSr, check => sr =>
_getGenerateWarningBeforeMigrate = createSelector(
this._getCheckSr,
check => sr =>
check(sr) ? null : (
<span className='text-warning'>
<Icon icon='alarm' /> {_('warningVdiSr')}

View File

@ -129,9 +129,10 @@ export default class Xosan extends Component {
}
)
_getAvailableLicenses = createFilter(() => this.props.xosanLicenses, [
({ boundObjectId, expires }) => boundObjectId === undefined && (expires === undefined || expires > Date.now()),
])
_getAvailableLicenses = createFilter(
() => this.props.xosanLicenses,
[({ boundObjectId, expires }) => boundObjectId === undefined && (expires === undefined || expires > Date.now())]
)
_getKnownXosans = createSelector(
createSelector(

View File

@ -237,8 +237,10 @@ const XOSAN_INDIVIDUAL_ACTIONS = [
return hostsNeedRestartByPool
})
const getPoolPredicate = createSelector(getXosanSrs, getHosts, (srs, hosts) => pool =>
hosts[pool.master].productBrand !== 'XCP-ng' && every(srs, sr => sr.$pool !== pool.id)
const getPoolPredicate = createSelector(
getXosanSrs,
getHosts,
(srs, hosts) => pool => hosts[pool.master].productBrand !== 'XCP-ng' && every(srs, sr => sr.$pool !== pool.id)
)
return {