Compare commits
21 Commits
log-v0.1.2
...
fs-v0.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
093bda7039 | ||
|
|
4e35b19ac5 | ||
|
|
244d8a51e8 | ||
|
|
9d6cc77cc8 | ||
|
|
d5e0150880 | ||
|
|
5cf29a98b3 | ||
|
|
165c2262c0 | ||
|
|
74f5d2e0cd | ||
|
|
2d93456f52 | ||
|
|
fd401ca335 | ||
|
|
97ba93a9ad | ||
|
|
0788c25710 | ||
|
|
82bba951db | ||
|
|
6efd611b80 | ||
|
|
b7d43b42b9 | ||
|
|
801b71d9ae | ||
|
|
0ff7c2188a | ||
|
|
bc1667440f | ||
|
|
227b464a8e | ||
|
|
f6c43650b4 | ||
|
|
597689fde0 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xen-orchestra/fs",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.1",
|
||||
"license": "AGPL-3.0",
|
||||
"description": "The File System for Xen Orchestra backups.",
|
||||
"keywords": [],
|
||||
@@ -25,7 +25,7 @@
|
||||
"fs-extra": "^7.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"through2": "^2.0.3",
|
||||
"tmp": "^0.0.33",
|
||||
"xo-remote-parser": "^0.5.0"
|
||||
|
||||
@@ -17,11 +17,13 @@ type File = FileDescriptor | string
|
||||
|
||||
const checksumFile = file => file + '.checksum'
|
||||
|
||||
export const DEFAULT_TIMEOUT = 10000
|
||||
const DEFAULT_TIMEOUT = 6e5 // 10 min
|
||||
|
||||
export default class RemoteHandlerAbstract {
|
||||
_remote: Object
|
||||
constructor (remote: any) {
|
||||
_timeout: number
|
||||
|
||||
constructor (remote: any, options: Object = {}) {
|
||||
if (remote.url === 'test://') {
|
||||
this._remote = remote
|
||||
} else {
|
||||
@@ -30,6 +32,7 @@ export default class RemoteHandlerAbstract {
|
||||
throw new Error('Incorrect remote type')
|
||||
}
|
||||
}
|
||||
;({ timeout: this._timeout = DEFAULT_TIMEOUT } = options)
|
||||
}
|
||||
|
||||
get type (): string {
|
||||
@@ -127,7 +130,7 @@ export default class RemoteHandlerAbstract {
|
||||
newPath: string,
|
||||
{ checksum = false }: Object = {}
|
||||
) {
|
||||
let p = timeout.call(this._rename(oldPath, newPath), DEFAULT_TIMEOUT)
|
||||
let p = timeout.call(this._rename(oldPath, newPath), this._timeout)
|
||||
if (checksum) {
|
||||
p = Promise.all([
|
||||
p,
|
||||
@@ -148,7 +151,7 @@ export default class RemoteHandlerAbstract {
|
||||
prependDir = false,
|
||||
}: { filter?: (name: string) => boolean, prependDir?: boolean } = {}
|
||||
): Promise<string[]> {
|
||||
let entries = await timeout.call(this._list(dir), DEFAULT_TIMEOUT)
|
||||
let entries = await timeout.call(this._list(dir), this._timeout)
|
||||
if (filter !== undefined) {
|
||||
entries = entries.filter(filter)
|
||||
}
|
||||
@@ -172,7 +175,7 @@ export default class RemoteHandlerAbstract {
|
||||
): Promise<LaxReadable> {
|
||||
const path = typeof file === 'string' ? file : file.path
|
||||
const streamP = timeout
|
||||
.call(this._createReadStream(file, options), DEFAULT_TIMEOUT)
|
||||
.call(this._createReadStream(file, options), this._timeout)
|
||||
.then(stream => {
|
||||
// detect early errors
|
||||
let promise = fromEvent(stream, 'readable')
|
||||
@@ -233,7 +236,7 @@ export default class RemoteHandlerAbstract {
|
||||
|
||||
async openFile (path: string, flags?: string): Promise<FileDescriptor> {
|
||||
return {
|
||||
fd: await timeout.call(this._openFile(path, flags), DEFAULT_TIMEOUT),
|
||||
fd: await timeout.call(this._openFile(path, flags), this._timeout),
|
||||
path,
|
||||
}
|
||||
}
|
||||
@@ -243,7 +246,7 @@ export default class RemoteHandlerAbstract {
|
||||
}
|
||||
|
||||
async closeFile (fd: FileDescriptor): Promise<void> {
|
||||
await timeout.call(this._closeFile(fd.fd), DEFAULT_TIMEOUT)
|
||||
await timeout.call(this._closeFile(fd.fd), this._timeout)
|
||||
}
|
||||
|
||||
async _closeFile (fd: mixed): Promise<void> {
|
||||
@@ -268,7 +271,7 @@ export default class RemoteHandlerAbstract {
|
||||
flags: 'wx',
|
||||
...options,
|
||||
}),
|
||||
DEFAULT_TIMEOUT
|
||||
this._timeout
|
||||
)
|
||||
|
||||
if (!checksum) {
|
||||
@@ -304,7 +307,7 @@ export default class RemoteHandlerAbstract {
|
||||
ignoreErrors.call(this._unlink(checksumFile(file)))
|
||||
}
|
||||
|
||||
await timeout.call(this._unlink(file), DEFAULT_TIMEOUT)
|
||||
await timeout.call(this._unlink(file), this._timeout)
|
||||
}
|
||||
|
||||
async _unlink (file: mixed): Promise<void> {
|
||||
@@ -312,7 +315,7 @@ export default class RemoteHandlerAbstract {
|
||||
}
|
||||
|
||||
async getSize (file: mixed): Promise<number> {
|
||||
return timeout.call(this._getSize(file), DEFAULT_TIMEOUT)
|
||||
return timeout.call(this._getSize(file), this._timeout)
|
||||
}
|
||||
|
||||
async _getSize (file: mixed): Promise<number> {
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
import { TimeoutError } from 'promise-toolbox'
|
||||
|
||||
import AbstractHandler, { DEFAULT_TIMEOUT } from './abstract'
|
||||
import AbstractHandler from './abstract'
|
||||
|
||||
const TIMEOUT = 10e3
|
||||
|
||||
class TestHandler extends AbstractHandler {
|
||||
constructor (impl) {
|
||||
super({ url: 'test://' })
|
||||
super({ url: 'test://' }, { timeout: TIMEOUT })
|
||||
|
||||
Object.keys(impl).forEach(method => {
|
||||
this[`_${method}`] = impl[method]
|
||||
@@ -15,97 +17,97 @@ class TestHandler extends AbstractHandler {
|
||||
}
|
||||
|
||||
describe('rename()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
rename: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.rename('oldPath', 'newPath')
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('list()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
list: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.list()
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('createReadStream()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
createReadStream: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.createReadStream('file')
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('openFile()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
openFile: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.openFile('path')
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('closeFile()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
closeFile: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.closeFile({ fd: undefined, path: '' })
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('createOutputStream()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
createOutputStream: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.createOutputStream('File')
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('unlink()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
unlink: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.unlink('')
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getSize()', () => {
|
||||
it(`return TimeoutError after ${DEFAULT_TIMEOUT} ms`, async () => {
|
||||
it(`throws in case of timeout`, async () => {
|
||||
const testHandler = new TestHandler({
|
||||
getSize: () => new Promise(() => {}),
|
||||
})
|
||||
|
||||
const promise = testHandler.getSize('')
|
||||
jest.advanceTimersByTime(DEFAULT_TIMEOUT)
|
||||
jest.advanceTimersByTime(TIMEOUT)
|
||||
await expect(promise).rejects.toThrowError(TimeoutError)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ const HANDLERS = {
|
||||
nfs: RemoteHandlerNfs,
|
||||
}
|
||||
|
||||
export const getHandler = (remote: Remote): RemoteHandler => {
|
||||
export const getHandler = (remote: Remote, ...rest: any): RemoteHandler => {
|
||||
// FIXME: should be done in xo-remote-parser.
|
||||
const type = remote.url.split('://')[0]
|
||||
|
||||
@@ -22,5 +22,5 @@ export const getHandler = (remote: Remote): RemoteHandler => {
|
||||
if (!Handler) {
|
||||
throw new Error('Unhandled remote type')
|
||||
}
|
||||
return new Handler(remote)
|
||||
return new Handler(remote, ...rest)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
import execa from 'execa'
|
||||
import fs from 'fs-extra'
|
||||
import { join } from 'path'
|
||||
import { tmpdir } from 'os'
|
||||
|
||||
import LocalHandler from './local'
|
||||
|
||||
const DEFAULT_NFS_OPTIONS = 'vers=3'
|
||||
|
||||
export default class NfsHandler extends LocalHandler {
|
||||
constructor (
|
||||
remote,
|
||||
{ mountsDir = join(tmpdir(), 'xo-fs-mounts'), ...opts } = {}
|
||||
) {
|
||||
super(remote, opts)
|
||||
|
||||
this._realPath = join(mountsDir, remote.id)
|
||||
}
|
||||
|
||||
get type () {
|
||||
return 'nfs'
|
||||
}
|
||||
|
||||
_getRealPath () {
|
||||
return `/run/xo-server/mounts/${this._remote.id}`
|
||||
return this._realPath
|
||||
}
|
||||
|
||||
async _mount () {
|
||||
|
||||
@@ -23,8 +23,8 @@ const normalizeError = error => {
|
||||
}
|
||||
|
||||
export default class SmbHandler extends RemoteHandlerAbstract {
|
||||
constructor (remote) {
|
||||
super(remote)
|
||||
constructor (remote, opts) {
|
||||
super(remote, opts)
|
||||
this._forget = noop
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xen-orchestra/log",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.4",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4",
|
||||
"promise-toolbox": "^0.10.1"
|
||||
"promise-toolbox": "^0.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.0.0",
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = require('./dist/transports/console.js')
|
||||
module.exports = require('../dist/transports/console.js')
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = require('./dist/transports/email.js')
|
||||
module.exports = require('../dist/transports/email.js')
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = require('./dist/transports/memory.js')
|
||||
module.exports = require('../dist/transports/memory.js')
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = require('./dist/transports/syslog.js')
|
||||
module.exports = require('../dist/transports/syslog.js')
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- [Backup NG] Increase timeout in stale remotes detection to limit false positives (PR [#3632](https://github.com/vatesfr/xen-orchestra/pull/3632))
|
||||
|
||||
### Released packages
|
||||
|
||||
- xo-server v5.30.0
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"jest": "^23.0.1",
|
||||
"lodash": "^4.17.4",
|
||||
"prettier": "^1.10.2",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"sorted-object": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"node": ">=6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xen-orchestra/fs": "^0.4.0",
|
||||
"@xen-orchestra/fs": "^0.4.1",
|
||||
"cli-progress": "^2.0.0",
|
||||
"exec-promise": "^0.7.0",
|
||||
"struct-fu": "^1.2.0",
|
||||
@@ -40,7 +40,7 @@
|
||||
"cross-env": "^5.1.3",
|
||||
"execa": "^1.0.0",
|
||||
"index-modules": "^0.3.0",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"tmp": "^0.0.33"
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"from2": "^2.3.0",
|
||||
"fs-extra": "^7.0.0",
|
||||
"limit-concurrency-decorator": "^0.4.0",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"struct-fu": "^1.2.0",
|
||||
"uuid": "^3.0.1"
|
||||
},
|
||||
@@ -34,7 +34,7 @@
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@xen-orchestra/fs": "^0.4.0",
|
||||
"@xen-orchestra/fs": "^0.4.1",
|
||||
"babel-plugin-lodash": "^3.3.2",
|
||||
"cross-env": "^5.1.3",
|
||||
"execa": "^1.0.0",
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"make-error": "^1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"ms": "^2.1.1",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"pw": "0.0.4",
|
||||
"xmlrpc": "^1.3.2",
|
||||
"xo-collection": "^0.4.1"
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"nice-pipe": "0.0.0",
|
||||
"pretty-ms": "^4.0.0",
|
||||
"progress-stream": "^2.0.0",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"pump": "^3.0.0",
|
||||
"pw": "^0.0.4",
|
||||
"strip-indent": "^2.0.0",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"inquirer": "^6.0.0",
|
||||
"ldapjs": "^1.0.1",
|
||||
"lodash": "^4.17.4",
|
||||
"promise-toolbox": "^0.10.1"
|
||||
"promise-toolbox": "^0.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.0.0",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"dependencies": {
|
||||
"nodemailer": "^4.4.1",
|
||||
"nodemailer-markdown": "^1.0.1",
|
||||
"promise-toolbox": "^0.10.1"
|
||||
"promise-toolbox": "^0.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.0.0",
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"node": ">=6"
|
||||
},
|
||||
"dependencies": {
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"slack-node": "^0.1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"html-minifier": "^3.5.8",
|
||||
"human-format": "^0.10.0",
|
||||
"lodash": "^4.17.4",
|
||||
"promise-toolbox": "^0.10.1"
|
||||
"promise-toolbox": "^0.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.0.0",
|
||||
|
||||
@@ -34,6 +34,12 @@
|
||||
// Necessary for external authentication providers.
|
||||
"createUserOnFirstSignin": true,
|
||||
|
||||
"remoteOptions": {
|
||||
"mountsDir": "/run/xo-server/mounts",
|
||||
|
||||
"timeout": 600e3
|
||||
},
|
||||
|
||||
// Whether API logs should contains the full request/response on
|
||||
// errors.
|
||||
//
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xo-server",
|
||||
"version": "5.29.0",
|
||||
"version": "5.29.2",
|
||||
"license": "AGPL-3.0",
|
||||
"description": "Server part of Xen-Orchestra",
|
||||
"keywords": [
|
||||
@@ -34,8 +34,8 @@
|
||||
"@xen-orchestra/async-map": "^0.0.0",
|
||||
"@xen-orchestra/cron": "^1.0.3",
|
||||
"@xen-orchestra/emit-async": "^0.0.0",
|
||||
"@xen-orchestra/fs": "^0.4.0",
|
||||
"@xen-orchestra/log": "^0.1.2",
|
||||
"@xen-orchestra/fs": "^0.4.1",
|
||||
"@xen-orchestra/log": "^0.1.4",
|
||||
"@xen-orchestra/mixin": "^0.0.0",
|
||||
"ajv": "^6.1.1",
|
||||
"app-conf": "^0.5.0",
|
||||
@@ -95,7 +95,7 @@
|
||||
"passport": "^0.4.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"pretty-format": "^23.0.0",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"proxy-agent": "^3.0.0",
|
||||
"pug": "^2.0.0-rc.4",
|
||||
"pump": "^3.0.0",
|
||||
|
||||
15
packages/xo-server/src/schemas/log/taskInfo.js
Normal file
15
packages/xo-server/src/schemas/log/taskInfo.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export default {
|
||||
$schema: 'http://json-schema.org/draft-04/schema#',
|
||||
type: 'object',
|
||||
properties: {
|
||||
event: {
|
||||
enum: ['task.info'],
|
||||
},
|
||||
taskId: {
|
||||
type: 'string',
|
||||
description: 'identifier of the parent task or job',
|
||||
},
|
||||
data: {},
|
||||
},
|
||||
required: ['event', 'taskId'],
|
||||
}
|
||||
@@ -129,6 +129,13 @@ export default {
|
||||
data: data.data,
|
||||
message,
|
||||
})
|
||||
} else if (event === 'task.info') {
|
||||
const parent = started[data.taskId]
|
||||
parent !== undefined &&
|
||||
(parent.infos || (parent.infos = [])).push({
|
||||
data: data.data,
|
||||
message,
|
||||
})
|
||||
} else if (event === 'jobCall.start') {
|
||||
const parent = started[data.runJobId]
|
||||
if (parent !== undefined) {
|
||||
|
||||
@@ -521,31 +521,30 @@ export default class BackupNg {
|
||||
vmsId !== undefined ||
|
||||
(vmsId = extractIdsFromSimplePattern(vmsPattern)) !== undefined
|
||||
) {
|
||||
vms = vmsId
|
||||
.map(id => {
|
||||
try {
|
||||
return app.getObject(id, 'VM')
|
||||
} catch (error) {
|
||||
const taskId: string = logger.notice(
|
||||
`Starting backup of ${id}. (${job.id})`,
|
||||
{
|
||||
event: 'task.start',
|
||||
parentId: runJobId,
|
||||
data: {
|
||||
type: 'VM',
|
||||
id,
|
||||
},
|
||||
}
|
||||
)
|
||||
logger.error(`Backuping ${id} has failed. (${job.id})`, {
|
||||
event: 'task.end',
|
||||
taskId,
|
||||
status: 'failure',
|
||||
result: serializeError(error),
|
||||
})
|
||||
}
|
||||
})
|
||||
.filter(vm => vm !== undefined)
|
||||
vms = {}
|
||||
vmsId.forEach(id => {
|
||||
try {
|
||||
vms[id] = app.getObject(id, 'VM')
|
||||
} catch (error) {
|
||||
const taskId: string = logger.notice(
|
||||
`Starting backup of ${id}. (${job.id})`,
|
||||
{
|
||||
event: 'task.start',
|
||||
parentId: runJobId,
|
||||
data: {
|
||||
type: 'VM',
|
||||
id,
|
||||
},
|
||||
}
|
||||
)
|
||||
logger.error(`Backuping ${id} has failed. (${job.id})`, {
|
||||
event: 'task.end',
|
||||
taskId,
|
||||
status: 'failure',
|
||||
result: serializeError(error),
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
vms = app.getObjects({
|
||||
filter: createPredicate({
|
||||
@@ -646,6 +645,13 @@ export default class BackupNg {
|
||||
])
|
||||
if (concurrency !== 0) {
|
||||
handleVm = limitConcurrency(concurrency)(handleVm)
|
||||
logger.notice('vms', {
|
||||
event: 'task.info',
|
||||
taskId: runJobId,
|
||||
data: {
|
||||
vms: Object.keys(vms),
|
||||
},
|
||||
})
|
||||
}
|
||||
await asyncMap(vms, handleVm)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ import { Remotes } from '../models/remote'
|
||||
// ===================================================================
|
||||
|
||||
export default class {
|
||||
constructor (xo) {
|
||||
constructor (xo, { remoteOptions }) {
|
||||
this._remoteOptions = remoteOptions
|
||||
this._remotes = new Remotes({
|
||||
connection: xo._redis,
|
||||
prefix: 'xo:remote',
|
||||
@@ -57,7 +58,7 @@ export default class {
|
||||
const handlers = this._handlers
|
||||
let handler = handlers[id]
|
||||
if (handler === undefined) {
|
||||
handler = handlers[id] = getHandler(remote)
|
||||
handler = handlers[id] = getHandler(remote, this._remoteOptions)
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"child-process-promise": "^2.0.3",
|
||||
"core-js": "3.0.0-beta.3",
|
||||
"pipette": "^0.9.3",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"tmp": "^0.0.33",
|
||||
"vhd-lib": "^0.4.0"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": false,
|
||||
"name": "xo-web",
|
||||
"version": "5.29.0",
|
||||
"version": "5.29.1",
|
||||
"license": "AGPL-3.0",
|
||||
"description": "Web interface client for Xen-Orchestra",
|
||||
"keywords": [
|
||||
@@ -94,7 +94,7 @@
|
||||
"moment": "^2.20.1",
|
||||
"moment-timezone": "^0.5.14",
|
||||
"notifyjs": "^3.0.0",
|
||||
"promise-toolbox": "^0.10.1",
|
||||
"promise-toolbox": "^0.11.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"random-password": "^0.1.2",
|
||||
"reaclette": "^0.7.0",
|
||||
|
||||
@@ -359,13 +359,13 @@ class XoaUpdater extends EventEmitter {
|
||||
log (level, message) {
|
||||
message = (message != null && message.message) || String(message)
|
||||
const date = new Date()
|
||||
this._log.unshift({
|
||||
this._log.push({
|
||||
date: date.toLocaleString(),
|
||||
level,
|
||||
message,
|
||||
})
|
||||
while (this._log.length > 10) {
|
||||
this._log.pop()
|
||||
this._log.shift()
|
||||
}
|
||||
this.emit('log', map(this._log, item => assign({}, item)))
|
||||
}
|
||||
|
||||
@@ -113,13 +113,16 @@ const Updates = decorate([
|
||||
body: (
|
||||
<p>
|
||||
{_('alreadyRegisteredModalText', {
|
||||
email: this.props.registration.email,
|
||||
email: this.props.xoaRegisterState.email,
|
||||
})}
|
||||
</p>
|
||||
),
|
||||
})
|
||||
} catch (_) {
|
||||
return
|
||||
} catch (error) {
|
||||
if (error === null) {
|
||||
return
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +167,7 @@ const Updates = decorate([
|
||||
isProxyConfigEdited: state =>
|
||||
PROXY_ENTRIES.some(entry => state[entry] !== undefined),
|
||||
isRegistered: (_, { xoaRegisterState }) =>
|
||||
xoaRegisterState.state === 'register',
|
||||
xoaRegisterState.state === 'registered',
|
||||
isTrialAllowed: (_, { xoaTrialState }) =>
|
||||
xoaTrialState.state === 'default' && exposeTrial(xoaTrialState.trial),
|
||||
isTrialAvailable: (_, { xoaTrialState }) =>
|
||||
@@ -251,9 +254,9 @@ const Updates = decorate([
|
||||
: _('downgrade')}
|
||||
</ActionButton>
|
||||
<hr />
|
||||
<div>
|
||||
<pre>
|
||||
{map(xoaUpdaterLog, (log, key) => (
|
||||
<p key={key}>
|
||||
<div key={key}>
|
||||
<span className={LEVELS_TO_CLASSES[log.level]}>
|
||||
{log.date}
|
||||
</span>
|
||||
@@ -263,9 +266,9 @@ const Updates = decorate([
|
||||
__html: ansiUp.ansi_to_html(log.message),
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</pre>
|
||||
</CardBlock>
|
||||
</Card>
|
||||
</Col>
|
||||
@@ -388,14 +391,13 @@ const Updates = decorate([
|
||||
</ActionButton>
|
||||
</form>
|
||||
) : (
|
||||
<ActionButton
|
||||
<Button
|
||||
btnStyle='primary'
|
||||
handler={effects.toggleState}
|
||||
icon='edit'
|
||||
name='askRegisterAgain'
|
||||
onClick={effects.toggleState}
|
||||
>
|
||||
{_('editRegistration')}
|
||||
</ActionButton>
|
||||
<Icon fixedWidth icon='edit' /> {_('editRegistration')}
|
||||
</Button>
|
||||
)}
|
||||
{+process.env.XOA_PLAN === 1 && (
|
||||
<div>
|
||||
|
||||
@@ -10323,6 +10323,13 @@ promise-toolbox@^0.10.1:
|
||||
dependencies:
|
||||
make-error "^1.3.2"
|
||||
|
||||
promise-toolbox@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/promise-toolbox/-/promise-toolbox-0.11.0.tgz#9ed928355355395072dace3f879879504e07d1bc"
|
||||
integrity sha512-bjHk0kq+Ke3J3zbkbbJH6kXCyQZbFHwOTrE/Et7vS0uS0tluoV+PLqU/kEyxl8aARM7v04y2wFoDo/wWAEPvjA==
|
||||
dependencies:
|
||||
make-error "^1.3.2"
|
||||
|
||||
promise-toolbox@^0.8.0:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/promise-toolbox/-/promise-toolbox-0.8.3.tgz#b757232a21d246d8702df50da6784932dd0f5348"
|
||||
|
||||
Reference in New Issue
Block a user