feat: use ESLint instead of standard (#630)
This commit is contained in:
parent
d2f88d0a02
commit
4905a0310a
15
.eslintrc.js
Normal file
15
.eslintrc.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
'standard',
|
||||||
|
],
|
||||||
|
parser: 'babel-eslint',
|
||||||
|
rules: {
|
||||||
|
'comma-dangle': ['error', 'always-multiline'],
|
||||||
|
'no-var': 'error',
|
||||||
|
'node/no-extraneous-import': 'error',
|
||||||
|
'node/no-extraneous-require': 'error',
|
||||||
|
'node/no-missing-require': 'error',
|
||||||
|
'node/no-missing-import': 'error',
|
||||||
|
'prefer-const': 'error',
|
||||||
|
},
|
||||||
|
}
|
@ -2,11 +2,11 @@ Error.stackTraceLimit = 100
|
|||||||
|
|
||||||
// Removes internal modules.
|
// Removes internal modules.
|
||||||
try {
|
try {
|
||||||
var sep = require('path').sep
|
const sep = require('path').sep
|
||||||
|
|
||||||
require('stack-chain').filter.attach(function (_, frames) {
|
require('stack-chain').filter.attach(function (_, frames) {
|
||||||
var filtered = frames.filter(function (frame) {
|
const filtered = frames.filter(function (frame) {
|
||||||
var name = frame && frame.getFileName()
|
const name = frame && frame.getFileName()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// has a filename
|
// has a filename
|
||||||
|
28
gulpfile.js
28
gulpfile.js
@ -2,23 +2,23 @@
|
|||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
var gulp = require('gulp')
|
const gulp = require('gulp')
|
||||||
|
|
||||||
var babel = require('gulp-babel')
|
const babel = require('gulp-babel')
|
||||||
var coffee = require('gulp-coffee')
|
const coffee = require('gulp-coffee')
|
||||||
var plumber = require('gulp-plumber')
|
const plumber = require('gulp-plumber')
|
||||||
var rimraf = require('rimraf')
|
const rimraf = require('rimraf')
|
||||||
var sourceMaps = require('gulp-sourcemaps')
|
const sourceMaps = require('gulp-sourcemaps')
|
||||||
var watch = require('gulp-watch')
|
const watch = require('gulp-watch')
|
||||||
|
|
||||||
var join = require('path').join
|
const join = require('path').join
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
var SRC_DIR = join(__dirname, 'src')
|
const SRC_DIR = join(__dirname, 'src')
|
||||||
var DIST_DIR = join(__dirname, 'dist')
|
const DIST_DIR = join(__dirname, 'dist')
|
||||||
|
|
||||||
var PRODUCTION = process.argv.indexOf('--production') !== -1
|
const PRODUCTION = process.argv.indexOf('--production') !== -1
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
@ -26,13 +26,13 @@ function src (patterns) {
|
|||||||
return PRODUCTION
|
return PRODUCTION
|
||||||
? gulp.src(patterns, {
|
? gulp.src(patterns, {
|
||||||
base: SRC_DIR,
|
base: SRC_DIR,
|
||||||
cwd: SRC_DIR
|
cwd: SRC_DIR,
|
||||||
})
|
})
|
||||||
: watch(patterns, {
|
: watch(patterns, {
|
||||||
base: SRC_DIR,
|
base: SRC_DIR,
|
||||||
cwd: SRC_DIR,
|
cwd: SRC_DIR,
|
||||||
ignoreInitial: false,
|
ignoreInitial: false,
|
||||||
verbose: true
|
verbose: true,
|
||||||
})
|
})
|
||||||
.pipe(plumber())
|
.pipe(plumber())
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ gulp.task(function buildCoffee () {
|
|||||||
return src('**/*.coffee')
|
return src('**/*.coffee')
|
||||||
.pipe(sourceMaps.init())
|
.pipe(sourceMaps.init())
|
||||||
.pipe(coffee({
|
.pipe(coffee({
|
||||||
bare: true
|
bare: true,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Necessary to correctly compile generators.
|
// Necessary to correctly compile generators.
|
||||||
|
2
index.js
2
index.js
@ -8,4 +8,4 @@ if (process.env.DEBUG === undefined) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Import the real main module.
|
// Import the real main module.
|
||||||
module.exports = require('./dist').default
|
module.exports = require('./dist').default // eslint-disable-line node/no-missing-require
|
||||||
|
17
package.json
17
package.json
@ -125,6 +125,12 @@
|
|||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
"babel-preset-env": "^1.6.1",
|
"babel-preset-env": "^1.6.1",
|
||||||
"babel-preset-stage-0": "^6.24.1",
|
"babel-preset-stage-0": "^6.24.1",
|
||||||
|
"eslint": "^4.13.1",
|
||||||
|
"eslint-config-standard": "^11.0.0-beta.0",
|
||||||
|
"eslint-plugin-import": "^2.8.0",
|
||||||
|
"eslint-plugin-node": "^5.2.1",
|
||||||
|
"eslint-plugin-promise": "^3.6.0",
|
||||||
|
"eslint-plugin-standard": "^3.0.1",
|
||||||
"gulp": "git://github.com/gulpjs/gulp#4.0",
|
"gulp": "git://github.com/gulpjs/gulp#4.0",
|
||||||
"gulp-babel": "^7.0.0",
|
"gulp-babel": "^7.0.0",
|
||||||
"gulp-coffee": "^2.3.4",
|
"gulp-coffee": "^2.3.4",
|
||||||
@ -134,18 +140,17 @@
|
|||||||
"husky": "^0.14.3",
|
"husky": "^0.14.3",
|
||||||
"index-modules": "^0.3.0",
|
"index-modules": "^0.3.0",
|
||||||
"jest": "^21.2.1",
|
"jest": "^21.2.1",
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.2"
|
||||||
"standard": "^10.0.3"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "gulp build --production",
|
"build": "gulp build --production",
|
||||||
"commitmsg": "yarn run test",
|
"commitmsg": "yarn run test",
|
||||||
"dev": "gulp build",
|
"dev": "gulp build",
|
||||||
"dev-test": "jest --bail --watch",
|
"dev-test": "jest --bail --watch",
|
||||||
"posttest": "standard",
|
|
||||||
"prebuild": "index-modules src/api src/xapi/mixins src/xo-mixins",
|
"prebuild": "index-modules src/api src/xapi/mixins src/xo-mixins",
|
||||||
"predev": "yarn run prebuild",
|
"predev": "yarn run prebuild",
|
||||||
"prepublishOnly": "yarn run build",
|
"prepublishOnly": "yarn run build",
|
||||||
|
"pretest": "eslint --ignore-path .gitignore --fix .",
|
||||||
"start": "node bin/xo-server",
|
"start": "node bin/xo-server",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
@ -172,11 +177,5 @@
|
|||||||
"<rootDir>/src"
|
"<rootDir>/src"
|
||||||
],
|
],
|
||||||
"testRegex": "\\.spec\\.js$"
|
"testRegex": "\\.spec\\.js$"
|
||||||
},
|
|
||||||
"standard": {
|
|
||||||
"ignore": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"parser": "babel-eslint"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ add.permission = 'admin'
|
|||||||
add.params = {
|
add.params = {
|
||||||
subject: { type: 'string' },
|
subject: { type: 'string' },
|
||||||
object: { type: 'string' },
|
object: { type: 'string' },
|
||||||
action: { type: 'string' }
|
action: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
add.description = 'add a new ACL entry'
|
add.description = 'add a new ACL entry'
|
||||||
@ -43,7 +43,7 @@ remove.permission = 'admin'
|
|||||||
remove.params = {
|
remove.params = {
|
||||||
subject: { type: 'string' },
|
subject: { type: 'string' },
|
||||||
object: { type: 'string' },
|
object: { type: 'string' },
|
||||||
action: { type: 'string' }
|
action: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
remove.description = 'remove an existing ACL entry'
|
remove.description = 'remove an existing ACL entry'
|
||||||
|
@ -11,7 +11,7 @@ export function list ({ remote }) {
|
|||||||
|
|
||||||
list.permission = 'admin'
|
list.permission = 'admin'
|
||||||
list.params = {
|
list.params = {
|
||||||
remote: { type: 'string' }
|
remote: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -23,7 +23,7 @@ export function scanDisk ({ remote, disk }) {
|
|||||||
scanDisk.permission = 'admin'
|
scanDisk.permission = 'admin'
|
||||||
scanDisk.params = {
|
scanDisk.params = {
|
||||||
remote: { type: 'string' },
|
remote: { type: 'string' },
|
||||||
disk: { type: 'string' }
|
disk: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -37,7 +37,7 @@ scanFiles.params = {
|
|||||||
remote: { type: 'string' },
|
remote: { type: 'string' },
|
||||||
disk: { type: 'string' },
|
disk: { type: 'string' },
|
||||||
partition: { type: 'string', optional: true },
|
partition: { type: 'string', optional: true },
|
||||||
path: { type: 'string' }
|
path: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -80,7 +80,7 @@ export async function fetchFiles ({ format = 'zip', ...params }) {
|
|||||||
: basename(params.paths[0])
|
: basename(params.paths[0])
|
||||||
|
|
||||||
return this.registerHttpRequest(handleFetchFiles, { ...params, format }, {
|
return this.registerHttpRequest(handleFetchFiles, { ...params, format }, {
|
||||||
suffix: encodeURI(`/${fileName}`)
|
suffix: encodeURI(`/${fileName}`),
|
||||||
}).then(url => ({ $getFrom: url }))
|
}).then(url => ({ $getFrom: url }))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +93,6 @@ fetchFiles.params = {
|
|||||||
paths: {
|
paths: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: { type: 'string' },
|
items: { type: 'string' },
|
||||||
minLength: 1
|
minLength: 1,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,14 @@ export async function create ({ name, size, sr, vm, bootable, position, mode })
|
|||||||
const xapi = this.getXapi(sr)
|
const xapi = this.getXapi(sr)
|
||||||
const vdi = await xapi.createVdi(parseSize(size), {
|
const vdi = await xapi.createVdi(parseSize(size), {
|
||||||
name_label: name,
|
name_label: name,
|
||||||
sr: sr._xapiId
|
sr: sr._xapiId,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (attach) {
|
if (attach) {
|
||||||
await xapi.attachVdiToVm(vdi.$id, vm._xapiId, {
|
await xapi.attachVdiToVm(vdi.$id, vm._xapiId, {
|
||||||
bootable,
|
bootable,
|
||||||
position,
|
position,
|
||||||
readOnly: mode === 'RO'
|
readOnly: mode === 'RO',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,12 +40,12 @@ create.params = {
|
|||||||
vm: { type: 'string', optional: true },
|
vm: { type: 'string', optional: true },
|
||||||
bootable: { type: 'boolean', optional: true },
|
bootable: { type: 'boolean', optional: true },
|
||||||
mode: { type: 'string', optional: true },
|
mode: { type: 'string', optional: true },
|
||||||
position: { type: 'string', optional: true }
|
position: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
create.resolve = {
|
create.resolve = {
|
||||||
vm: ['vm', 'VM', 'administrate'],
|
vm: ['vm', 'VM', 'administrate'],
|
||||||
sr: ['sr', 'SR', false]
|
sr: ['sr', 'SR', false],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -58,9 +58,9 @@ resize.description = 'resize an existing VDI'
|
|||||||
|
|
||||||
resize.params = {
|
resize.params = {
|
||||||
id: { type: 'string' },
|
id: { type: 'string' },
|
||||||
size: { type: ['integer', 'string'] }
|
size: { type: ['integer', 'string'] },
|
||||||
}
|
}
|
||||||
|
|
||||||
resize.resolve = {
|
resize.resolve = {
|
||||||
vdi: ['id', ['VDI', 'VDI-snapshot'], 'administrate']
|
vdi: ['id', ['VDI', 'VDI-snapshot'], 'administrate'],
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,11 @@ export async function register ({vm}) {
|
|||||||
register.description = 'Register the VM for Docker management'
|
register.description = 'Register the VM for Docker management'
|
||||||
|
|
||||||
register.params = {
|
register.params = {
|
||||||
vm: { type: 'string' }
|
vm: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
register.resolve = {
|
register.resolve = {
|
||||||
vm: ['vm', 'VM', 'administrate']
|
vm: ['vm', 'VM', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -19,11 +19,11 @@ export async function deregister ({vm}) {
|
|||||||
deregister.description = 'Deregister the VM for Docker management'
|
deregister.description = 'Deregister the VM for Docker management'
|
||||||
|
|
||||||
deregister.params = {
|
deregister.params = {
|
||||||
vm: { type: 'string' }
|
vm: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
deregister.resolve = {
|
deregister.resolve = {
|
||||||
vm: ['vm', 'VM', 'administrate']
|
vm: ['vm', 'VM', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -48,13 +48,13 @@ export async function unpause ({vm, container}) {
|
|||||||
await this.getXapi(vm).unpauseDockerContainer(vm._xapiId, container)
|
await this.getXapi(vm).unpauseDockerContainer(vm._xapiId, container)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let fn of [start, stop, restart, pause, unpause]) {
|
for (const fn of [start, stop, restart, pause, unpause]) {
|
||||||
fn.params = {
|
fn.params = {
|
||||||
vm: { type: 'string' },
|
vm: { type: 'string' },
|
||||||
container: { type: 'string' }
|
container: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
fn.resolve = {
|
fn.resolve = {
|
||||||
vm: ['vm', 'VM', 'operate']
|
vm: ['vm', 'VM', 'operate'],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ export async function create ({name}) {
|
|||||||
create.description = 'creates a new group'
|
create.description = 'creates a new group'
|
||||||
create.permission = 'admin'
|
create.permission = 'admin'
|
||||||
create.params = {
|
create.params = {
|
||||||
name: {type: 'string'}
|
name: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -21,7 +21,7 @@ export {delete_ as delete}
|
|||||||
delete_.description = 'deletes an existing group'
|
delete_.description = 'deletes an existing group'
|
||||||
delete_.permission = 'admin'
|
delete_.permission = 'admin'
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -44,7 +44,7 @@ setUsers.description = 'sets the users belonging to a group'
|
|||||||
setUsers.permission = 'admin'
|
setUsers.permission = 'admin'
|
||||||
setUsers.params = {
|
setUsers.params = {
|
||||||
id: {type: 'string'},
|
id: {type: 'string'},
|
||||||
userIds: {}
|
userIds: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -58,7 +58,7 @@ addUser.description = 'adds a user to a group'
|
|||||||
addUser.permission = 'admin'
|
addUser.permission = 'admin'
|
||||||
addUser.params = {
|
addUser.params = {
|
||||||
id: {type: 'string'},
|
id: {type: 'string'},
|
||||||
userId: {type: 'string'}
|
userId: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -74,7 +74,7 @@ removeUser.description = 'removes a user from a group'
|
|||||||
removeUser.permission = 'admin'
|
removeUser.permission = 'admin'
|
||||||
removeUser.params = {
|
removeUser.params = {
|
||||||
id: {type: 'string'},
|
id: {type: 'string'},
|
||||||
userId: {type: 'string'}
|
userId: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -87,5 +87,5 @@ set.description = 'changes the properties of an existing group'
|
|||||||
set.permission = 'admin'
|
set.permission = 'admin'
|
||||||
set.params = {
|
set.params = {
|
||||||
id: { type: 'string' },
|
id: { type: 'string' },
|
||||||
name: { type: 'string', optional: true }
|
name: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export async function get (id) {
|
|||||||
get.permission = 'admin'
|
get.permission = 'admin'
|
||||||
get.description = 'Gets an existing job'
|
get.description = 'Gets an existing job'
|
||||||
get.params = {
|
get.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create ({job}) {
|
export async function create ({job}) {
|
||||||
@ -44,14 +44,14 @@ create.params = {
|
|||||||
items: {
|
items: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'object'
|
type: 'object',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function set ({job}) {
|
export async function set ({job}) {
|
||||||
@ -77,14 +77,14 @@ set.params = {
|
|||||||
items: {
|
items: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'object'
|
type: 'object',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
async function delete_ ({id}) {
|
async function delete_ ({id}) {
|
||||||
@ -94,7 +94,7 @@ async function delete_ ({id}) {
|
|||||||
delete_.permission = 'admin'
|
delete_.permission = 'admin'
|
||||||
delete_.description = 'Deletes an existing job'
|
delete_.description = 'Deletes an existing job'
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
@ -106,5 +106,5 @@ export async function runSequence ({idSequence}) {
|
|||||||
runSequence.permission = 'admin'
|
runSequence.permission = 'admin'
|
||||||
runSequence.description = 'Runs jobs sequentially, in the provided order'
|
runSequence.description = 'Runs jobs sequentially, in the provided order'
|
||||||
runSequence.params = {
|
runSequence.params = {
|
||||||
idSequence: {type: 'array', items: {type: 'string'}}
|
idSequence: {type: 'array', items: {type: 'string'}},
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export async function get ({namespace}) {
|
|||||||
|
|
||||||
get.description = 'returns logs list for one namespace'
|
get.description = 'returns logs list for one namespace'
|
||||||
get.params = {
|
get.params = {
|
||||||
namespace: { type: 'string' }
|
namespace: { type: 'string' },
|
||||||
}
|
}
|
||||||
get.permission = 'admin'
|
get.permission = 'admin'
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ async function delete_ ({namespace, id}) {
|
|||||||
delete_.description = 'deletes one or several logs from a namespace'
|
delete_.description = 'deletes one or several logs from a namespace'
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: { type: [ 'array', 'string' ] },
|
id: { type: [ 'array', 'string' ] },
|
||||||
namespace: { type: 'string' }
|
namespace: { type: 'string' },
|
||||||
}
|
}
|
||||||
delete_.permission = 'admin'
|
delete_.permission = 'admin'
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@ async function delete_ ({ message }) {
|
|||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_.resolve = {
|
delete_.resolve = {
|
||||||
message: ['id', 'message', 'administrate']
|
message: ['id', 'message', 'administrate'],
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ export async function create ({ pool, name, description, pif, mtu = 1500, vlan =
|
|||||||
description,
|
description,
|
||||||
pifId: pif && this.getObject(pif, 'PIF')._xapiId,
|
pifId: pif && this.getObject(pif, 'PIF')._xapiId,
|
||||||
mtu: +mtu,
|
mtu: +mtu,
|
||||||
vlan: +vlan
|
vlan: +vlan,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,11 +20,11 @@ create.params = {
|
|||||||
description: { type: 'string', optional: true },
|
description: { type: 'string', optional: true },
|
||||||
pif: { type: 'string', optional: true },
|
pif: { type: 'string', optional: true },
|
||||||
mtu: { type: ['integer', 'string'], optional: true },
|
mtu: { type: ['integer', 'string'], optional: true },
|
||||||
vlan: { type: ['integer', 'string'], optional: true }
|
vlan: { type: ['integer', 'string'], optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
create.resolve = {
|
create.resolve = {
|
||||||
pool: ['pool', 'pool', 'administrate']
|
pool: ['pool', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
create.permission = 'admin'
|
create.permission = 'admin'
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ export async function createBonded ({ pool, name, description, pifs, mtu = 1500,
|
|||||||
),
|
),
|
||||||
mtu: +mtu,
|
mtu: +mtu,
|
||||||
mac,
|
mac,
|
||||||
bondMode
|
bondMode,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,17 +50,17 @@ createBonded.params = {
|
|||||||
pifs: {
|
pifs: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
mtu: { type: ['integer', 'string'], optional: true },
|
mtu: { type: ['integer', 'string'], optional: true },
|
||||||
mac: { type: 'string', optional: true },
|
mac: { type: 'string', optional: true },
|
||||||
// RegExp since schema-inspector does not provide a param check based on an enumeration
|
// RegExp since schema-inspector does not provide a param check based on an enumeration
|
||||||
bondMode: { type: 'string', pattern: new RegExp(`^(${getBondModes().join('|')})$`) }
|
bondMode: { type: 'string', pattern: new RegExp(`^(${getBondModes().join('|')})$`) },
|
||||||
}
|
}
|
||||||
|
|
||||||
createBonded.resolve = {
|
createBonded.resolve = {
|
||||||
pool: ['pool', 'pool', 'administrate']
|
pool: ['pool', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
createBonded.permission = 'admin'
|
createBonded.permission = 'admin'
|
||||||
createBonded.description = 'Create a bonded network. bondMode can be balance-slb, active-backup or lacp'
|
createBonded.description = 'Create a bonded network. bondMode can be balance-slb, active-backup or lacp'
|
||||||
@ -73,35 +73,35 @@ export async function set ({
|
|||||||
name_description: nameDescription,
|
name_description: nameDescription,
|
||||||
name_label: nameLabel,
|
name_label: nameLabel,
|
||||||
defaultIsLocked,
|
defaultIsLocked,
|
||||||
id
|
id,
|
||||||
}) {
|
}) {
|
||||||
await this.getXapi(network).setNetworkProperties(network._xapiId, {
|
await this.getXapi(network).setNetworkProperties(network._xapiId, {
|
||||||
nameDescription,
|
nameDescription,
|
||||||
nameLabel,
|
nameLabel,
|
||||||
defaultIsLocked
|
defaultIsLocked,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
set.params = {
|
set.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
name_label: {
|
name_label: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
name_description: {
|
name_description: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
defaultIsLocked: {
|
defaultIsLocked: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
set.resolve = {
|
set.resolve = {
|
||||||
network: ['id', 'network', 'administrate']
|
network: ['id', 'network', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// =================================================================
|
// =================================================================
|
||||||
@ -112,9 +112,9 @@ export async function delete_ ({ network }) {
|
|||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_.resolve = {
|
delete_.resolve = {
|
||||||
network: ['id', 'network', 'administrate']
|
network: ['id', 'network', 'administrate'],
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ async function delete_ ({PBD}) {
|
|||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_.resolve = {
|
delete_.resolve = {
|
||||||
PBD: ['id', 'PBD', 'administrate']
|
PBD: ['id', 'PBD', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -25,11 +25,11 @@ export async function disconnect ({ pbd }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disconnect.params = {
|
disconnect.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect.resolve = {
|
disconnect.resolve = {
|
||||||
pbd: ['id', 'PBD', 'administrate']
|
pbd: ['id', 'PBD', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -41,9 +41,9 @@ export async function connect ({PBD}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect.params = {
|
connect.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
connect.resolve = {
|
connect.resolve = {
|
||||||
PBD: ['id', 'PBD', 'administrate']
|
PBD: ['id', 'PBD', 'administrate'],
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@ async function delete_ ({pif}) {
|
|||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_.resolve = {
|
delete_.resolve = {
|
||||||
pif: ['id', 'PIF', 'administrate']
|
pif: ['id', 'PIF', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -36,11 +36,11 @@ export async function disconnect ({pif}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disconnect.params = {
|
disconnect.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect.resolve = {
|
disconnect.resolve = {
|
||||||
pif: ['id', 'PIF', 'administrate']
|
pif: ['id', 'PIF', 'administrate'],
|
||||||
}
|
}
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// Connect
|
// Connect
|
||||||
@ -51,11 +51,11 @@ export async function connect ({pif}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect.params = {
|
connect.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
connect.resolve = {
|
connect.resolve = {
|
||||||
pif: ['id', 'PIF', 'administrate']
|
pif: ['id', 'PIF', 'administrate'],
|
||||||
}
|
}
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// Reconfigure IP
|
// Reconfigure IP
|
||||||
@ -70,11 +70,11 @@ reconfigureIp.params = {
|
|||||||
ip: { type: 'string', optional: true },
|
ip: { type: 'string', optional: true },
|
||||||
netmask: { type: 'string', optional: true },
|
netmask: { type: 'string', optional: true },
|
||||||
gateway: { type: 'string', optional: true },
|
gateway: { type: 'string', optional: true },
|
||||||
dns: { type: 'string', optional: true }
|
dns: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
reconfigureIp.resolve = {
|
reconfigureIp.resolve = {
|
||||||
pif: ['id', 'PIF', 'administrate']
|
pif: ['id', 'PIF', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -85,9 +85,9 @@ export async function editPif ({ pif, vlan }) {
|
|||||||
|
|
||||||
editPif.params = {
|
editPif.params = {
|
||||||
id: { type: 'string' },
|
id: { type: 'string' },
|
||||||
vlan: { type: ['integer', 'string'] }
|
vlan: { type: ['integer', 'string'] },
|
||||||
}
|
}
|
||||||
|
|
||||||
editPif.resolve = {
|
editPif.resolve = {
|
||||||
pif: ['id', 'PIF', 'administrate']
|
pif: ['id', 'PIF', 'administrate'],
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,9 @@ configure.description = 'sets the configuration of a plugin'
|
|||||||
|
|
||||||
configure.params = {
|
configure.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
configuration: {}
|
configuration: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
configure.permission = 'admin'
|
configure.permission = 'admin'
|
||||||
@ -33,8 +33,8 @@ disableAutoload.description = ''
|
|||||||
|
|
||||||
disableAutoload.params = {
|
disableAutoload.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
disableAutoload.permission = 'admin'
|
disableAutoload.permission = 'admin'
|
||||||
@ -49,8 +49,8 @@ enableAutoload.description = 'enables a plugin, allowing it to be loaded'
|
|||||||
|
|
||||||
enableAutoload.params = {
|
enableAutoload.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
enableAutoload.permission = 'admin'
|
enableAutoload.permission = 'admin'
|
||||||
@ -65,8 +65,8 @@ load.description = 'loads a plugin'
|
|||||||
|
|
||||||
load.params = {
|
load.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
load.permission = 'admin'
|
load.permission = 'admin'
|
||||||
@ -81,8 +81,8 @@ unload.description = 'unloads a plugin'
|
|||||||
|
|
||||||
unload.params = {
|
unload.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
unload.permission = 'admin'
|
unload.permission = 'admin'
|
||||||
@ -97,8 +97,8 @@ purgeConfiguration.description = 'removes a plugin configuration'
|
|||||||
|
|
||||||
purgeConfiguration.params = {
|
purgeConfiguration.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
purgeConfiguration.permission = 'admin'
|
purgeConfiguration.permission = 'admin'
|
||||||
@ -113,11 +113,11 @@ test.description = 'Test a plugin with its current configuration'
|
|||||||
|
|
||||||
test.params = {
|
test.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
test.permission = 'admin'
|
test.permission = 'admin'
|
||||||
|
@ -9,30 +9,30 @@ export async function set ({
|
|||||||
|
|
||||||
// TODO: use camel case.
|
// TODO: use camel case.
|
||||||
name_description: nameDescription,
|
name_description: nameDescription,
|
||||||
name_label: nameLabel
|
name_label: nameLabel,
|
||||||
}) {
|
}) {
|
||||||
await this.getXapi(pool).setPoolProperties({
|
await this.getXapi(pool).setPoolProperties({
|
||||||
nameDescription,
|
nameDescription,
|
||||||
nameLabel
|
nameLabel,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
set.params = {
|
set.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
name_label: {
|
name_label: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
name_description: {
|
name_description: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
set.resolve = {
|
set.resolve = {
|
||||||
pool: ['id', 'pool', 'administrate']
|
pool: ['id', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -47,12 +47,12 @@ setDefaultSr.permission = '' // signed in
|
|||||||
|
|
||||||
setDefaultSr.params = {
|
setDefaultSr.params = {
|
||||||
sr: {
|
sr: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaultSr.resolve = {
|
setDefaultSr.resolve = {
|
||||||
sr: ['sr', 'SR']
|
sr: ['sr', 'SR'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -65,12 +65,12 @@ export async function setPoolMaster ({ host }) {
|
|||||||
|
|
||||||
setPoolMaster.params = {
|
setPoolMaster.params = {
|
||||||
host: {
|
host: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
setPoolMaster.resolve = {
|
setPoolMaster.resolve = {
|
||||||
host: ['host', 'host']
|
host: ['host', 'host'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -81,15 +81,15 @@ export async function installPatch ({pool, patch: patchUuid}) {
|
|||||||
|
|
||||||
installPatch.params = {
|
installPatch.params = {
|
||||||
pool: {
|
pool: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
patch: {
|
patch: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
installPatch.resolve = {
|
installPatch.resolve = {
|
||||||
pool: ['pool', 'pool', 'administrate']
|
pool: ['pool', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
@ -99,12 +99,12 @@ export async function installAllPatches ({ pool }) {
|
|||||||
|
|
||||||
installAllPatches.params = {
|
installAllPatches.params = {
|
||||||
pool: {
|
pool: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
installAllPatches.resolve = {
|
installAllPatches.resolve = {
|
||||||
pool: ['pool', 'pool', 'administrate']
|
pool: ['pool', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
installAllPatches.description = 'Install automatically all patches for every hosts of a pool'
|
installAllPatches.description = 'Install automatically all patches for every hosts of a pool'
|
||||||
@ -124,16 +124,16 @@ async function handlePatchUpload (req, res, {pool}) {
|
|||||||
|
|
||||||
export async function uploadPatch ({pool}) {
|
export async function uploadPatch ({pool}) {
|
||||||
return {
|
return {
|
||||||
$sendTo: await this.registerHttpRequest(handlePatchUpload, {pool})
|
$sendTo: await this.registerHttpRequest(handlePatchUpload, {pool}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadPatch.params = {
|
uploadPatch.params = {
|
||||||
pool: { type: 'string' }
|
pool: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadPatch.resolve = {
|
uploadPatch.resolve = {
|
||||||
pool: ['pool', 'pool', 'administrate']
|
pool: ['pool', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compatibility
|
// Compatibility
|
||||||
@ -167,12 +167,12 @@ export async function mergeInto ({ source, target, force }) {
|
|||||||
mergeInto.params = {
|
mergeInto.params = {
|
||||||
force: { type: 'boolean', optional: true },
|
force: { type: 'boolean', optional: true },
|
||||||
source: { type: 'string' },
|
source: { type: 'string' },
|
||||||
target: { type: 'string' }
|
target: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeInto.resolve = {
|
mergeInto.resolve = {
|
||||||
source: ['source', 'pool', 'administrate'],
|
source: ['source', 'pool', 'administrate'],
|
||||||
target: ['target', 'pool', 'administrate']
|
target: ['target', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -186,12 +186,12 @@ export async function getLicenseState ({pool}) {
|
|||||||
|
|
||||||
getLicenseState.params = {
|
getLicenseState.params = {
|
||||||
pool: {
|
pool: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
getLicenseState.resolve = {
|
getLicenseState.resolve = {
|
||||||
pool: ['pool', 'pool', 'administrate']
|
pool: ['pool', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -215,16 +215,16 @@ async function handleInstallSupplementalPack (req, res, { poolId }) {
|
|||||||
|
|
||||||
export async function installSupplementalPack ({ pool }) {
|
export async function installSupplementalPack ({ pool }) {
|
||||||
return {
|
return {
|
||||||
$sendTo: await this.registerHttpRequest(handleInstallSupplementalPack, { poolId: pool.id })
|
$sendTo: await this.registerHttpRequest(handleInstallSupplementalPack, { poolId: pool.id }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
installSupplementalPack.description = 'installs supplemental pack from ISO file on all hosts'
|
installSupplementalPack.description = 'installs supplemental pack from ISO file on all hosts'
|
||||||
|
|
||||||
installSupplementalPack.params = {
|
installSupplementalPack.params = {
|
||||||
pool: { type: 'string' }
|
pool: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
installSupplementalPack.resolve = {
|
installSupplementalPack.resolve = {
|
||||||
pool: ['pool', 'pool', 'admin']
|
pool: ['pool', 'pool', 'admin'],
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export async function get ({id}) {
|
|||||||
get.permission = 'admin'
|
get.permission = 'admin'
|
||||||
get.description = 'Gets an existing fs remote point'
|
get.description = 'Gets an existing fs remote point'
|
||||||
get.params = {
|
get.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function test ({id}) {
|
export async function test ({id}) {
|
||||||
@ -22,7 +22,7 @@ export async function test ({id}) {
|
|||||||
test.permission = 'admin'
|
test.permission = 'admin'
|
||||||
test.description = 'Performs a read/write matching test on a remote point'
|
test.description = 'Performs a read/write matching test on a remote point'
|
||||||
test.params = {
|
test.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function list ({id}) {
|
export async function list ({id}) {
|
||||||
@ -32,7 +32,7 @@ export async function list ({id}) {
|
|||||||
list.permission = 'admin'
|
list.permission = 'admin'
|
||||||
list.description = 'Lists the files found in a remote point'
|
list.description = 'Lists the files found in a remote point'
|
||||||
list.params = {
|
list.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create ({name, url}) {
|
export async function create ({name, url}) {
|
||||||
@ -43,7 +43,7 @@ create.permission = 'admin'
|
|||||||
create.description = 'Creates a new fs remote point'
|
create.description = 'Creates a new fs remote point'
|
||||||
create.params = {
|
create.params = {
|
||||||
name: {type: 'string'},
|
name: {type: 'string'},
|
||||||
url: {type: 'string'}
|
url: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function set ({id, name, url, enabled}) {
|
export async function set ({id, name, url, enabled}) {
|
||||||
@ -56,7 +56,7 @@ set.params = {
|
|||||||
id: {type: 'string'},
|
id: {type: 'string'},
|
||||||
name: {type: 'string', optional: true},
|
name: {type: 'string', optional: true},
|
||||||
url: {type: 'string', optional: true},
|
url: {type: 'string', optional: true},
|
||||||
enabled: {type: 'boolean', optional: true}
|
enabled: {type: 'boolean', optional: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
async function delete_ ({id}) {
|
async function delete_ ({id}) {
|
||||||
@ -66,7 +66,7 @@ async function delete_ ({id}) {
|
|||||||
delete_.permission = 'admin'
|
delete_.permission = 'admin'
|
||||||
delete_.description = 'Deletes an existing fs remote point'
|
delete_.description = 'Deletes an existing fs remote point'
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
unauthorized
|
unauthorized,
|
||||||
} from 'xo-common/api-errors'
|
} from 'xo-common/api-errors'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -12,26 +12,26 @@ create.permission = 'admin'
|
|||||||
|
|
||||||
create.params = {
|
create.params = {
|
||||||
name: {
|
name: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
subjects: {
|
subjects: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
objects: {
|
objects: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
limits: {
|
limits: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -45,8 +45,8 @@ delete_.permission = 'admin'
|
|||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -57,7 +57,7 @@ export function set ({ id, name, subjects, objects, ipPools, limits }) {
|
|||||||
name,
|
name,
|
||||||
objects,
|
objects,
|
||||||
ipPools,
|
ipPools,
|
||||||
subjects
|
subjects,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,37 +65,37 @@ set.permission = 'admin'
|
|||||||
|
|
||||||
set.params = {
|
set.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
subjects: {
|
subjects: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
objects: {
|
objects: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
ipPools: {
|
ipPools: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
limits: {
|
limits: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -108,8 +108,8 @@ get.permission = 'admin'
|
|||||||
|
|
||||||
get.params = {
|
get.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -135,11 +135,11 @@ addObject.permission = 'admin'
|
|||||||
|
|
||||||
addObject.params = {
|
addObject.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
object: {
|
object: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -152,11 +152,11 @@ removeObject.permission = 'admin'
|
|||||||
|
|
||||||
removeObject.params = {
|
removeObject.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
object: {
|
object: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -169,11 +169,11 @@ addSubject.permission = 'admin'
|
|||||||
|
|
||||||
addSubject.params = {
|
addSubject.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
subject: {
|
subject: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -186,11 +186,11 @@ removeSubject.permission = 'admin'
|
|||||||
|
|
||||||
removeSubject.params = {
|
removeSubject.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
subject: {
|
subject: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -203,14 +203,14 @@ addLimit.permission = 'admin'
|
|||||||
|
|
||||||
addLimit.params = {
|
addLimit.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
limitId: {
|
limitId: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
quantity: {
|
quantity: {
|
||||||
type: 'integer'
|
type: 'integer',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -223,11 +223,11 @@ removeLimit.permission = 'admin'
|
|||||||
|
|
||||||
removeLimit.params = {
|
removeLimit.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
limitId: {
|
limitId: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -14,7 +14,7 @@ export async function get (id) {
|
|||||||
get.permission = 'admin'
|
get.permission = 'admin'
|
||||||
get.description = 'Gets an existing schedule'
|
get.description = 'Gets an existing schedule'
|
||||||
get.params = {
|
get.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create ({ jobId, cron, enabled, name, timezone }) {
|
export async function create ({ jobId, cron, enabled, name, timezone }) {
|
||||||
@ -27,7 +27,7 @@ create.params = {
|
|||||||
jobId: {type: 'string'},
|
jobId: {type: 'string'},
|
||||||
cron: {type: 'string'},
|
cron: {type: 'string'},
|
||||||
enabled: {type: 'boolean', optional: true},
|
enabled: {type: 'boolean', optional: true},
|
||||||
name: {type: 'string', optional: true}
|
name: {type: 'string', optional: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function set ({ id, jobId, cron, enabled, name, timezone }) {
|
export async function set ({ id, jobId, cron, enabled, name, timezone }) {
|
||||||
@ -41,7 +41,7 @@ set.params = {
|
|||||||
jobId: {type: 'string', optional: true},
|
jobId: {type: 'string', optional: true},
|
||||||
cron: {type: 'string', optional: true},
|
cron: {type: 'string', optional: true},
|
||||||
enabled: {type: 'boolean', optional: true},
|
enabled: {type: 'boolean', optional: true},
|
||||||
name: {type: 'string', optional: true}
|
name: {type: 'string', optional: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
async function delete_ ({id}) {
|
async function delete_ ({id}) {
|
||||||
@ -51,7 +51,7 @@ async function delete_ ({id}) {
|
|||||||
delete_.permission = 'admin'
|
delete_.permission = 'admin'
|
||||||
delete_.description = 'Deletes an existing schedule'
|
delete_.description = 'Deletes an existing schedule'
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
|
@ -7,7 +7,7 @@ export async function enable ({id}) {
|
|||||||
enable.permission = 'admin'
|
enable.permission = 'admin'
|
||||||
enable.description = 'Enables a schedule to run it\'s job as scheduled'
|
enable.description = 'Enables a schedule to run it\'s job as scheduled'
|
||||||
enable.params = {
|
enable.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function disable ({id}) {
|
export async function disable ({id}) {
|
||||||
@ -19,7 +19,7 @@ export async function disable ({id}) {
|
|||||||
disable.permission = 'admin'
|
disable.permission = 'admin'
|
||||||
disable.description = 'Disables a schedule'
|
disable.description = 'Disables a schedule'
|
||||||
disable.params = {
|
disable.params = {
|
||||||
id: {type: 'string'}
|
id: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getScheduleTable () {
|
export function getScheduleTable () {
|
||||||
|
@ -17,25 +17,25 @@ add.permission = 'admin'
|
|||||||
add.params = {
|
add.params = {
|
||||||
label: {
|
label: {
|
||||||
optional: true,
|
optional: true,
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
host: {
|
host: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
autoConnect: {
|
autoConnect: {
|
||||||
optional: true,
|
optional: true,
|
||||||
type: 'boolean'
|
type: 'boolean',
|
||||||
},
|
},
|
||||||
allowUnauthorized: {
|
allowUnauthorized: {
|
||||||
optional: true,
|
optional: true,
|
||||||
type: 'boolean'
|
type: 'boolean',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -50,8 +50,8 @@ remove.permission = 'admin'
|
|||||||
|
|
||||||
remove.params = {
|
remove.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -78,28 +78,28 @@ set.permission = 'admin'
|
|||||||
|
|
||||||
set.params = {
|
set.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
host: {
|
host: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
allowUnauthorized: {
|
allowUnauthorized: {
|
||||||
optional: true,
|
optional: true,
|
||||||
type: 'boolean'
|
type: 'boolean',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -115,8 +115,8 @@ connect.permission = 'admin'
|
|||||||
|
|
||||||
connect.params = {
|
connect.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -132,6 +132,6 @@ disconnect.permission = 'admin'
|
|||||||
|
|
||||||
disconnect.params = {
|
disconnect.params = {
|
||||||
id: {
|
id: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export const signInWithPassword = deprecate(signIn, 'use session.signIn() instea
|
|||||||
|
|
||||||
signInWithPassword.params = {
|
signInWithPassword.params = {
|
||||||
email: { type: 'string' },
|
email: { type: 'string' },
|
||||||
password: { type: 'string' }
|
password: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -31,7 +31,7 @@ signInWithPassword.params = {
|
|||||||
export const signInWithToken = deprecate(signIn, 'use session.signIn() instead')
|
export const signInWithToken = deprecate(signIn, 'use session.signIn() instead')
|
||||||
|
|
||||||
signInWithToken.params = {
|
signInWithToken.params = {
|
||||||
token: { type: 'string' }
|
token: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
138
src/api/sr.js
138
src/api/sr.js
@ -5,7 +5,7 @@ import {
|
|||||||
asyncMap,
|
asyncMap,
|
||||||
ensureArray,
|
ensureArray,
|
||||||
forEach,
|
forEach,
|
||||||
parseXml
|
parseXml,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -15,11 +15,11 @@ export async function set ({
|
|||||||
|
|
||||||
// TODO: use camel case.
|
// TODO: use camel case.
|
||||||
name_description: nameDescription,
|
name_description: nameDescription,
|
||||||
name_label: nameLabel
|
name_label: nameLabel,
|
||||||
}) {
|
}) {
|
||||||
await this.getXapi(sr).setSrProperties(sr._xapiId, {
|
await this.getXapi(sr).setSrProperties(sr._xapiId, {
|
||||||
nameDescription,
|
nameDescription,
|
||||||
nameLabel
|
nameLabel,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,11 +28,11 @@ set.params = {
|
|||||||
|
|
||||||
name_label: { type: 'string', optional: true },
|
name_label: { type: 'string', optional: true },
|
||||||
|
|
||||||
name_description: { type: 'string', optional: true }
|
name_description: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
set.resolve = {
|
set.resolve = {
|
||||||
sr: ['id', 'SR', 'operate']
|
sr: ['id', 'SR', 'operate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -42,11 +42,11 @@ export async function scan ({ SR }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scan.params = {
|
scan.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
scan.resolve = {
|
scan.resolve = {
|
||||||
SR: ['id', 'SR', 'operate']
|
SR: ['id', 'SR', 'operate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -71,11 +71,11 @@ export async function destroy ({sr}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy.params = {
|
destroy.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy.resolve = {
|
destroy.resolve = {
|
||||||
sr: ['id', 'SR', 'administrate']
|
sr: ['id', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -85,11 +85,11 @@ export async function forget ({ SR }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
forget.params = {
|
forget.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
forget.resolve = {
|
forget.resolve = {
|
||||||
SR: ['id', 'SR', 'administrate']
|
SR: ['id', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -99,11 +99,11 @@ export async function connectAllPbds ({ SR }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connectAllPbds.params = {
|
connectAllPbds.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
connectAllPbds.resolve = {
|
connectAllPbds.resolve = {
|
||||||
SR: ['id', 'SR', 'administrate']
|
SR: ['id', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -113,11 +113,11 @@ export async function disconnectAllPbds ({ SR }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disconnectAllPbds.params = {
|
disconnectAllPbds.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectAllPbds.resolve = {
|
disconnectAllPbds.resolve = {
|
||||||
SR: ['id', 'SR', 'administrate']
|
SR: ['id', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -129,7 +129,7 @@ export async function createIso ({
|
|||||||
path,
|
path,
|
||||||
type,
|
type,
|
||||||
user,
|
user,
|
||||||
password
|
password,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
@ -169,11 +169,11 @@ createIso.params = {
|
|||||||
path: { type: 'string' },
|
path: { type: 'string' },
|
||||||
type: { type: 'string' },
|
type: { type: 'string' },
|
||||||
user: { type: 'string', optional: true },
|
user: { type: 'string', optional: true },
|
||||||
password: { type: 'string', optional: true }
|
password: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
createIso.resolve = {
|
createIso.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -187,13 +187,13 @@ export async function createNfs ({
|
|||||||
nameDescription,
|
nameDescription,
|
||||||
server,
|
server,
|
||||||
serverPath,
|
serverPath,
|
||||||
nfsVersion
|
nfsVersion,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
server,
|
server,
|
||||||
serverpath: serverPath
|
serverpath: serverPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
// if NFS version given
|
// if NFS version given
|
||||||
@ -224,11 +224,11 @@ createNfs.params = {
|
|||||||
nameDescription: { type: 'string' },
|
nameDescription: { type: 'string' },
|
||||||
server: { type: 'string' },
|
server: { type: 'string' },
|
||||||
serverPath: { type: 'string' },
|
serverPath: { type: 'string' },
|
||||||
nfsVersion: { type: 'string', optional: true }
|
nfsVersion: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
createNfs.resolve = {
|
createNfs.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -240,12 +240,12 @@ export async function createHba ({
|
|||||||
host,
|
host,
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription,
|
nameDescription,
|
||||||
scsiId
|
scsiId,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
scsiId
|
scsiId,
|
||||||
}
|
}
|
||||||
|
|
||||||
const srRef = await xapi.call(
|
const srRef = await xapi.call(
|
||||||
@ -269,11 +269,11 @@ createHba.params = {
|
|||||||
host: { type: 'string' },
|
host: { type: 'string' },
|
||||||
nameLabel: { type: 'string' },
|
nameLabel: { type: 'string' },
|
||||||
nameDescription: { type: 'string' },
|
nameDescription: { type: 'string' },
|
||||||
scsiId: { type: 'string' }
|
scsiId: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
createHba.resolve = {
|
createHba.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -285,12 +285,12 @@ export async function createLvm ({
|
|||||||
host,
|
host,
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription,
|
nameDescription,
|
||||||
device
|
device,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
device
|
device,
|
||||||
}
|
}
|
||||||
|
|
||||||
const srRef = await xapi.call(
|
const srRef = await xapi.call(
|
||||||
@ -314,11 +314,11 @@ createLvm.params = {
|
|||||||
host: { type: 'string' },
|
host: { type: 'string' },
|
||||||
nameLabel: { type: 'string' },
|
nameLabel: { type: 'string' },
|
||||||
nameDescription: { type: 'string' },
|
nameDescription: { type: 'string' },
|
||||||
device: { type: 'string' }
|
device: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
createLvm.resolve = {
|
createLvm.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -327,12 +327,12 @@ createLvm.resolve = {
|
|||||||
|
|
||||||
export async function probeNfs ({
|
export async function probeNfs ({
|
||||||
host,
|
host,
|
||||||
server
|
server,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
server
|
server,
|
||||||
}
|
}
|
||||||
|
|
||||||
let xml
|
let xml
|
||||||
@ -359,7 +359,7 @@ export async function probeNfs ({
|
|||||||
forEach(ensureArray(xml['nfs-exports'].Export), nfsExport => {
|
forEach(ensureArray(xml['nfs-exports'].Export), nfsExport => {
|
||||||
nfsExports.push({
|
nfsExports.push({
|
||||||
path: nfsExport.Path.trim(),
|
path: nfsExport.Path.trim(),
|
||||||
acl: nfsExport.Accesslist.trim()
|
acl: nfsExport.Accesslist.trim(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -368,18 +368,18 @@ export async function probeNfs ({
|
|||||||
|
|
||||||
probeNfs.params = {
|
probeNfs.params = {
|
||||||
host: { type: 'string' },
|
host: { type: 'string' },
|
||||||
server: { type: 'string' }
|
server: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
probeNfs.resolve = {
|
probeNfs.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// This function helps to detect all HBA devices on the host
|
// This function helps to detect all HBA devices on the host
|
||||||
|
|
||||||
export async function probeHba ({
|
export async function probeHba ({
|
||||||
host
|
host,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
@ -409,7 +409,7 @@ export async function probeHba ({
|
|||||||
path: hbaDevice.path.trim(),
|
path: hbaDevice.path.trim(),
|
||||||
scsciId: hbaDevice.SCSIid.trim(),
|
scsciId: hbaDevice.SCSIid.trim(),
|
||||||
size: hbaDevice.size.trim(),
|
size: hbaDevice.size.trim(),
|
||||||
vendor: hbaDevice.vendor.trim()
|
vendor: hbaDevice.vendor.trim(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -417,11 +417,11 @@ export async function probeHba ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
probeHba.params = {
|
probeHba.params = {
|
||||||
host: { type: 'string' }
|
host: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
probeHba.resolve = {
|
probeHba.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -439,14 +439,14 @@ export async function createIscsi ({
|
|||||||
targetIqn,
|
targetIqn,
|
||||||
scsiId,
|
scsiId,
|
||||||
chapUser,
|
chapUser,
|
||||||
chapPassword
|
chapPassword,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
target,
|
target,
|
||||||
targetIQN: targetIqn,
|
targetIQN: targetIqn,
|
||||||
SCSIid: scsiId
|
SCSIid: scsiId,
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we give user and password
|
// if we give user and password
|
||||||
@ -486,11 +486,11 @@ createIscsi.params = {
|
|||||||
targetIqn: { type: 'string' },
|
targetIqn: { type: 'string' },
|
||||||
scsiId: { type: 'string' },
|
scsiId: { type: 'string' },
|
||||||
chapUser: { type: 'string', optional: true },
|
chapUser: { type: 'string', optional: true },
|
||||||
chapPassword: { type: 'string', optional: true }
|
chapPassword: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
createIscsi.resolve = {
|
createIscsi.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -502,12 +502,12 @@ export async function probeIscsiIqns ({
|
|||||||
target: targetIp,
|
target: targetIp,
|
||||||
port,
|
port,
|
||||||
chapUser,
|
chapUser,
|
||||||
chapPassword
|
chapPassword,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
target: targetIp
|
target: targetIp,
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we give user and password
|
// if we give user and password
|
||||||
@ -550,7 +550,7 @@ export async function probeIscsiIqns ({
|
|||||||
if (target.IPAddress.trim() === targetIp) {
|
if (target.IPAddress.trim() === targetIp) {
|
||||||
targets.push({
|
targets.push({
|
||||||
iqn: target.TargetIQN.trim(),
|
iqn: target.TargetIQN.trim(),
|
||||||
ip: target.IPAddress.trim()
|
ip: target.IPAddress.trim(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -563,10 +563,10 @@ probeIscsiIqns.params = {
|
|||||||
target: { type: 'string' },
|
target: { type: 'string' },
|
||||||
port: { type: 'integer', optional: true },
|
port: { type: 'integer', optional: true },
|
||||||
chapUser: { type: 'string', optional: true },
|
chapUser: { type: 'string', optional: true },
|
||||||
chapPassword: { type: 'string', optional: true }
|
chapPassword: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
probeIscsiIqns.resolve = {
|
probeIscsiIqns.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -579,13 +579,13 @@ export async function probeIscsiLuns ({
|
|||||||
port,
|
port,
|
||||||
targetIqn,
|
targetIqn,
|
||||||
chapUser,
|
chapUser,
|
||||||
chapPassword
|
chapPassword,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
target: targetIp,
|
target: targetIp,
|
||||||
targetIQN: targetIqn
|
targetIQN: targetIqn,
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we give user and password
|
// if we give user and password
|
||||||
@ -626,7 +626,7 @@ export async function probeIscsiLuns ({
|
|||||||
vendor: lun.vendor.trim(),
|
vendor: lun.vendor.trim(),
|
||||||
serial: lun.serial.trim(),
|
serial: lun.serial.trim(),
|
||||||
size: lun.size.trim(),
|
size: lun.size.trim(),
|
||||||
scsiId: lun.SCSIid.trim()
|
scsiId: lun.SCSIid.trim(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -639,11 +639,11 @@ probeIscsiLuns.params = {
|
|||||||
port: { type: 'integer', optional: true },
|
port: { type: 'integer', optional: true },
|
||||||
targetIqn: { type: 'string' },
|
targetIqn: { type: 'string' },
|
||||||
chapUser: { type: 'string', optional: true },
|
chapUser: { type: 'string', optional: true },
|
||||||
chapPassword: { type: 'string', optional: true }
|
chapPassword: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
probeIscsiLuns.resolve = {
|
probeIscsiLuns.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -657,14 +657,14 @@ export async function probeIscsiExists ({
|
|||||||
targetIqn,
|
targetIqn,
|
||||||
scsiId,
|
scsiId,
|
||||||
chapUser,
|
chapUser,
|
||||||
chapPassword
|
chapPassword,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
target: targetIp,
|
target: targetIp,
|
||||||
targetIQN: targetIqn,
|
targetIQN: targetIqn,
|
||||||
SCSIid: scsiId
|
SCSIid: scsiId,
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we give user and password
|
// if we give user and password
|
||||||
@ -696,11 +696,11 @@ probeIscsiExists.params = {
|
|||||||
targetIqn: { type: 'string' },
|
targetIqn: { type: 'string' },
|
||||||
scsiId: { type: 'string' },
|
scsiId: { type: 'string' },
|
||||||
chapUser: { type: 'string', optional: true },
|
chapUser: { type: 'string', optional: true },
|
||||||
chapPassword: { type: 'string', optional: true }
|
chapPassword: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
probeIscsiExists.resolve = {
|
probeIscsiExists.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -710,13 +710,13 @@ probeIscsiExists.resolve = {
|
|||||||
export async function probeNfsExists ({
|
export async function probeNfsExists ({
|
||||||
host,
|
host,
|
||||||
server,
|
server,
|
||||||
serverPath
|
serverPath,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
const deviceConfig = {
|
const deviceConfig = {
|
||||||
server,
|
server,
|
||||||
serverpath: serverPath
|
serverpath: serverPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
const xml = parseXml(await xapi.call('SR.probe', host._xapiRef, deviceConfig, 'nfs', {}))
|
const xml = parseXml(await xapi.call('SR.probe', host._xapiRef, deviceConfig, 'nfs', {}))
|
||||||
@ -734,11 +734,11 @@ export async function probeNfsExists ({
|
|||||||
probeNfsExists.params = {
|
probeNfsExists.params = {
|
||||||
host: { type: 'string' },
|
host: { type: 'string' },
|
||||||
server: { type: 'string' },
|
server: { type: 'string' },
|
||||||
serverPath: { type: 'string' }
|
serverPath: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
probeNfsExists.resolve = {
|
probeNfsExists.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -749,7 +749,7 @@ export async function reattach ({
|
|||||||
uuid,
|
uuid,
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription,
|
nameDescription,
|
||||||
type
|
type,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
@ -777,11 +777,11 @@ reattach.params = {
|
|||||||
uuid: { type: 'string' },
|
uuid: { type: 'string' },
|
||||||
nameLabel: { type: 'string' },
|
nameLabel: { type: 'string' },
|
||||||
nameDescription: { type: 'string' },
|
nameDescription: { type: 'string' },
|
||||||
type: { type: 'string' }
|
type: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
reattach.resolve = {
|
reattach.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -792,7 +792,7 @@ export async function reattachIso ({
|
|||||||
uuid,
|
uuid,
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription,
|
nameDescription,
|
||||||
type
|
type,
|
||||||
}) {
|
}) {
|
||||||
const xapi = this.getXapi(host)
|
const xapi = this.getXapi(host)
|
||||||
|
|
||||||
@ -820,11 +820,11 @@ reattachIso.params = {
|
|||||||
uuid: { type: 'string' },
|
uuid: { type: 'string' },
|
||||||
nameLabel: { type: 'string' },
|
nameLabel: { type: 'string' },
|
||||||
nameDescription: { type: 'string' },
|
nameDescription: { type: 'string' },
|
||||||
type: { type: 'string' }
|
type: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
reattachIso.resolve = {
|
reattachIso.resolve = {
|
||||||
host: ['host', 'host', 'administrate']
|
host: ['host', 'host', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -834,9 +834,9 @@ export function getUnhealthyVdiChainsLength ({ sr }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUnhealthyVdiChainsLength.params = {
|
getUnhealthyVdiChainsLength.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
getUnhealthyVdiChainsLength.resolve = {
|
getUnhealthyVdiChainsLength.resolve = {
|
||||||
sr: ['id', 'SR', 'operate']
|
sr: ['id', 'SR', 'operate'],
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export function getMethodsInfo () {
|
|||||||
methods[name] = {
|
methods[name] = {
|
||||||
description: method.description,
|
description: method.description,
|
||||||
params: method.params || {},
|
params: method.params || {},
|
||||||
permission: method.permission
|
permission: method.permission,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -60,8 +60,8 @@ export function methodSignature ({method: name}) {
|
|||||||
name,
|
name,
|
||||||
description: method.description,
|
description: method.description,
|
||||||
params: method.params || {},
|
params: method.params || {},
|
||||||
permission: method.permission
|
permission: method.permission,
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
methodSignature.description = 'returns the signature of an API method'
|
methodSignature.description = 'returns the signature of an API method'
|
||||||
|
@ -5,12 +5,12 @@ export async function add ({tag, object}) {
|
|||||||
add.description = 'add a new tag to an object'
|
add.description = 'add a new tag to an object'
|
||||||
|
|
||||||
add.resolve = {
|
add.resolve = {
|
||||||
object: ['id', null, 'administrate']
|
object: ['id', null, 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
add.params = {
|
add.params = {
|
||||||
tag: { type: 'string' },
|
tag: { type: 'string' },
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -22,10 +22,10 @@ export async function remove ({tag, object}) {
|
|||||||
remove.description = 'remove an existing tag from an object'
|
remove.description = 'remove an existing tag from an object'
|
||||||
|
|
||||||
remove.resolve = {
|
remove.resolve = {
|
||||||
object: ['id', null, 'administrate']
|
object: ['id', null, 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
remove.params = {
|
remove.params = {
|
||||||
tag: { type: 'string' },
|
tag: { type: 'string' },
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@ export async function cancel ({task}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cancel.params = {
|
cancel.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel.resolve = {
|
cancel.resolve = {
|
||||||
task: ['id', 'task', 'administrate']
|
task: ['id', 'task', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -17,9 +17,9 @@ export async function destroy ({task}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy.params = {
|
destroy.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy.resolve = {
|
destroy.resolve = {
|
||||||
task: ['id', 'task', 'administrate']
|
task: ['id', 'task', 'administrate'],
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,15 @@ getPermissionsForUser.permission = 'admin'
|
|||||||
|
|
||||||
getPermissionsForUser.params = {
|
getPermissionsForUser.params = {
|
||||||
userId: {
|
userId: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
export function hasPermission ({ userId, objectId, permission }) {
|
export function hasPermission ({ userId, objectId, permission }) {
|
||||||
return this.hasPermissions(userId, [
|
return this.hasPermissions(userId, [
|
||||||
[ objectId, permission ]
|
[ objectId, permission ],
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,14 +22,14 @@ hasPermission.permission = 'admin'
|
|||||||
|
|
||||||
hasPermission.params = {
|
hasPermission.params = {
|
||||||
userId: {
|
userId: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
objectId: {
|
objectId: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -44,8 +44,8 @@ export function wait ({duration, returnValue}) {
|
|||||||
|
|
||||||
wait.params = {
|
wait.params = {
|
||||||
duration: {
|
duration: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -77,10 +77,10 @@ copyVm.permission = 'admin'
|
|||||||
|
|
||||||
copyVm.params = {
|
copyVm.params = {
|
||||||
vm: { type: 'string' },
|
vm: { type: 'string' },
|
||||||
sr: { type: 'string' }
|
sr: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
copyVm.resolve = {
|
copyVm.resolve = {
|
||||||
vm: [ 'vm', 'VM' ],
|
vm: [ 'vm', 'VM' ],
|
||||||
sr: [ 'sr', 'SR' ]
|
sr: [ 'sr', 'SR' ],
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
export async function create ({ expiresIn }) {
|
export async function create ({ expiresIn }) {
|
||||||
return (await this.createAuthenticationToken({
|
return (await this.createAuthenticationToken({
|
||||||
expiresIn,
|
expiresIn,
|
||||||
userId: this.session.get('user_id')
|
userId: this.session.get('user_id'),
|
||||||
})).id
|
})).id
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,8 +12,8 @@ create.description = 'create a new authentication token'
|
|||||||
create.params = {
|
create.params = {
|
||||||
expiresIn: {
|
expiresIn: {
|
||||||
optional: true,
|
optional: true,
|
||||||
type: [ 'number', 'string' ]
|
type: [ 'number', 'string' ],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
create.permission = '' // sign in
|
create.permission = '' // sign in
|
||||||
@ -32,5 +32,5 @@ delete_.description = 'delete an existing authentication token'
|
|||||||
delete_.permission = 'admin'
|
delete_.permission = 'admin'
|
||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
token: { type: 'string' }
|
token: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ create.permission = 'admin'
|
|||||||
create.params = {
|
create.params = {
|
||||||
email: { type: 'string' },
|
email: { type: 'string' },
|
||||||
password: { type: 'string' },
|
password: { type: 'string' },
|
||||||
permission: { type: 'string', optional: true }
|
permission: { type: 'string', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -36,7 +36,7 @@ delete_.description = 'deletes an existing user'
|
|||||||
delete_.permission = 'admin'
|
delete_.permission = 'admin'
|
||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -79,7 +79,7 @@ set.params = {
|
|||||||
email: { type: 'string', optional: true },
|
email: { type: 'string', optional: true },
|
||||||
password: { type: 'string', optional: true },
|
password: { type: 'string', optional: true },
|
||||||
permission: { type: 'string', optional: true },
|
permission: { type: 'string', optional: true },
|
||||||
preferences: { type: 'object', optional: true }
|
preferences: { type: 'object', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -95,5 +95,5 @@ changePassword.permission = ''
|
|||||||
|
|
||||||
changePassword.params = {
|
changePassword.params = {
|
||||||
oldPassword: {type: 'string'},
|
oldPassword: {type: 'string'},
|
||||||
newPassword: {type: 'string'}
|
newPassword: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@ async function delete_ ({vif}) {
|
|||||||
export {delete_ as delete}
|
export {delete_ as delete}
|
||||||
|
|
||||||
delete_.params = {
|
delete_.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_.resolve = {
|
delete_.resolve = {
|
||||||
vif: ['id', 'VIF', 'administrate']
|
vif: ['id', 'VIF', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -33,11 +33,11 @@ export async function disconnect ({vif}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disconnect.params = {
|
disconnect.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect.resolve = {
|
disconnect.resolve = {
|
||||||
vif: ['id', 'VIF', 'operate']
|
vif: ['id', 'VIF', 'operate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -48,11 +48,11 @@ export async function connect ({vif}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect.params = {
|
connect.params = {
|
||||||
id: { type: 'string' }
|
id: { type: 'string' },
|
||||||
}
|
}
|
||||||
|
|
||||||
connect.resolve = {
|
connect.resolve = {
|
||||||
vif: ['id', 'VIF', 'operate']
|
vif: ['id', 'VIF', 'operate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -63,7 +63,7 @@ export async function set ({
|
|||||||
mac,
|
mac,
|
||||||
allowedIpv4Addresses,
|
allowedIpv4Addresses,
|
||||||
allowedIpv6Addresses,
|
allowedIpv6Addresses,
|
||||||
attached
|
attached,
|
||||||
}) {
|
}) {
|
||||||
const oldIpAddresses = vif.allowedIpv4Addresses.concat(vif.allowedIpv6Addresses)
|
const oldIpAddresses = vif.allowedIpv4Addresses.concat(vif.allowedIpv6Addresses)
|
||||||
const newIpAddresses = []
|
const newIpAddresses = []
|
||||||
@ -88,7 +88,7 @@ export async function set ({
|
|||||||
const newVif = await xapi.createVif(vm.$id, network.$id, {
|
const newVif = await xapi.createVif(vm.$id, network.$id, {
|
||||||
mac,
|
mac,
|
||||||
currently_attached: attached,
|
currently_attached: attached,
|
||||||
ipv4_allowed: newIpAddresses
|
ipv4_allowed: newIpAddresses,
|
||||||
})
|
})
|
||||||
|
|
||||||
await this.allocIpAddresses(newVif.$id, newIpAddresses)
|
await this.allocIpAddresses(newVif.$id, newIpAddresses)
|
||||||
@ -108,7 +108,7 @@ export async function set ({
|
|||||||
|
|
||||||
return this.getXapi(vif).editVif(vif._xapiId, {
|
return this.getXapi(vif).editVif(vif._xapiId, {
|
||||||
ipv4Allowed: allowedIpv4Addresses,
|
ipv4Allowed: allowedIpv4Addresses,
|
||||||
ipv6Allowed: allowedIpv6Addresses
|
ipv6Allowed: allowedIpv6Addresses,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,21 +119,21 @@ set.params = {
|
|||||||
allowedIpv4Addresses: {
|
allowedIpv4Addresses: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
allowedIpv6Addresses: {
|
allowedIpv6Addresses: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
attached: { type: 'boolean', optional: true }
|
attached: { type: 'boolean', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
set.resolve = {
|
set.resolve = {
|
||||||
vif: ['id', 'VIF', 'operate'],
|
vif: ['id', 'VIF', 'operate'],
|
||||||
network: ['network', 'network', 'operate']
|
network: ['network', 'network', 'operate'],
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,13 @@ export async function exportConfig () {
|
|||||||
return {
|
return {
|
||||||
$getFrom: await this.registerHttpRequest((req, res) => {
|
$getFrom: await this.registerHttpRequest((req, res) => {
|
||||||
res.writeHead(200, 'OK', {
|
res.writeHead(200, 'OK', {
|
||||||
'content-disposition': 'attachment'
|
'content-disposition': 'attachment',
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.exportConfig()
|
return this.exportConfig()
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
{ suffix: '/config.json' })
|
{ suffix: '/config.json' }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ getAllObjects.description = 'Returns all XO objects'
|
|||||||
|
|
||||||
getAllObjects.params = {
|
getAllObjects.params = {
|
||||||
filter: { type: 'object', optional: true },
|
filter: { type: 'object', optional: true },
|
||||||
limit: { type: 'number', optional: true }
|
limit: { type: 'number', optional: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -48,7 +48,7 @@ export async function importConfig () {
|
|||||||
await this.importConfig(JSON.parse(await streamToBuffer(req)))
|
await this.importConfig(JSON.parse(await streamToBuffer(req)))
|
||||||
|
|
||||||
res.end('config successfully imported')
|
res.end('config successfully imported')
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
132
src/api/xosan.js
132
src/api/xosan.js
@ -12,7 +12,7 @@ import {
|
|||||||
remove,
|
remove,
|
||||||
filter,
|
filter,
|
||||||
find,
|
find,
|
||||||
range
|
range,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import { asInteger } from '../xapi/utils'
|
import { asInteger } from '../xapi/utils'
|
||||||
@ -67,7 +67,7 @@ function _getGlusterEndpoint (sr) {
|
|||||||
xapi,
|
xapi,
|
||||||
data: data,
|
data: data,
|
||||||
hosts: map(data.nodes, node => xapi.getObject(node.host)),
|
hosts: map(data.nodes, node => xapi.getObject(node.host)),
|
||||||
addresses: map(data.nodes, node => node.vm.ip)
|
addresses: map(data.nodes, node => node.vm.ip),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ export async function getVolumeInfo ({sr, infoType}) {
|
|||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
commandStatus: true,
|
commandStatus: true,
|
||||||
result: {nodes: brickDictByUuid, tasks: volume['tasks']}
|
result: {nodes: brickDictByUuid, tasks: volume['tasks']},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ export async function getVolumeInfo ({sr, infoType}) {
|
|||||||
return async () => {
|
return async () => {
|
||||||
const cmdShouldRetry = result => !result['commandStatus'] && result.parsed && result.parsed['cliOutput']['opErrno'] === '30802'
|
const cmdShouldRetry = result => !result['commandStatus'] && result.parsed && result.parsed['cliOutput']['opErrno'] === '30802'
|
||||||
const runCmd = async () => glusterCmd(glusterEndpoint, 'volume ' + command, true)
|
const runCmd = async () => glusterCmd(glusterEndpoint, 'volume ' + command, true)
|
||||||
let commandResult = await rateLimitedRetry(runCmd, cmdShouldRetry)
|
const commandResult = await rateLimitedRetry(runCmd, cmdShouldRetry)
|
||||||
return commandResult['commandStatus'] ? handler(commandResult.parsed['cliOutput']) : commandResult
|
return commandResult['commandStatus'] ? handler(commandResult.parsed['cliOutput']) : commandResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ export async function getVolumeInfo ({sr, infoType}) {
|
|||||||
statusDetail: sshInfoType('status xosan detail', parseStatus),
|
statusDetail: sshInfoType('status xosan detail', parseStatus),
|
||||||
statusMem: sshInfoType('status xosan mem', parseStatus),
|
statusMem: sshInfoType('status xosan mem', parseStatus),
|
||||||
info: sshInfoType('info xosan', parseInfo),
|
info: sshInfoType('info xosan', parseInfo),
|
||||||
hosts: this::checkHosts
|
hosts: this::checkHosts,
|
||||||
}
|
}
|
||||||
if (glusterEndpoint == null) {
|
if (glusterEndpoint == null) {
|
||||||
return null
|
return null
|
||||||
@ -157,14 +157,14 @@ getVolumeInfo.permission = 'admin'
|
|||||||
|
|
||||||
getVolumeInfo.params = {
|
getVolumeInfo.params = {
|
||||||
sr: {
|
sr: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
infoType: {
|
infoType: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
getVolumeInfo.resolve = {
|
getVolumeInfo.resolve = {
|
||||||
sr: ['sr', 'SR', 'administrate']
|
sr: ['sr', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
function reconfigurePifIP (xapi, pif, newIP) {
|
function reconfigurePifIP (xapi, pif, newIP) {
|
||||||
@ -190,7 +190,7 @@ export async function fixHostNotInNetwork ({xosanSr, host}) {
|
|||||||
await callPlugin(xapi, host, 'receive_ssh_keys', {
|
await callPlugin(xapi, host, 'receive_ssh_keys', {
|
||||||
private_key: sshKey.private,
|
private_key: sshKey.private,
|
||||||
public_key: sshKey.public,
|
public_key: sshKey.public,
|
||||||
force: true
|
force: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,14 +200,14 @@ fixHostNotInNetwork.permission = 'admin'
|
|||||||
|
|
||||||
fixHostNotInNetwork.params = {
|
fixHostNotInNetwork.params = {
|
||||||
xosanSr: {
|
xosanSr: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
host: {
|
host: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
fixHostNotInNetwork.resolve = {
|
fixHostNotInNetwork.resolve = {
|
||||||
sr: ['sr', 'SR', 'administrate']
|
sr: ['sr', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
function floor2048 (value) {
|
function floor2048 (value) {
|
||||||
@ -315,7 +315,7 @@ const createNetworkAndInsertHosts = defer.onFailure(async function ($onFailure,
|
|||||||
description: 'XOSAN network',
|
description: 'XOSAN network',
|
||||||
pifId: pif._xapiId,
|
pifId: pif._xapiId,
|
||||||
mtu: pif.mtu,
|
mtu: pif.mtu,
|
||||||
vlan: +vlan
|
vlan: +vlan,
|
||||||
})
|
})
|
||||||
$onFailure(() => xapi.deleteNetwork(xosanNetwork))
|
$onFailure(() => xapi.deleteNetwork(xosanNetwork))
|
||||||
const addresses = xosanNetwork.$PIFs.map(pif => ({pif, address: networkPrefix + (hostIpLastNumber++)}))
|
const addresses = xosanNetwork.$PIFs.map(pif => ({pif, address: networkPrefix + (hostIpLastNumber++)}))
|
||||||
@ -338,7 +338,7 @@ async function getOrCreateSshKey (xapi) {
|
|||||||
const readKeys = async () => {
|
const readKeys = async () => {
|
||||||
sshKey = {
|
sshKey = {
|
||||||
private: await fs.readFile(SSH_KEY_FILE, 'ascii'),
|
private: await fs.readFile(SSH_KEY_FILE, 'ascii'),
|
||||||
public: await fs.readFile(SSH_KEY_FILE + '.pub', 'ascii')
|
public: await fs.readFile(SSH_KEY_FILE + '.pub', 'ascii'),
|
||||||
}
|
}
|
||||||
xapi.xo.setData(xapi.pool, 'xosan_ssh_key', sshKey)
|
xapi.xo.setData(xapi.pool, 'xosan_ssh_key', sshKey)
|
||||||
}
|
}
|
||||||
@ -380,18 +380,18 @@ async function configureGluster (redundancy, ipAndHosts, glusterEndpoint, gluste
|
|||||||
const configByType = {
|
const configByType = {
|
||||||
replica_arbiter: {
|
replica_arbiter: {
|
||||||
creation: 'replica 3 arbiter 1',
|
creation: 'replica 3 arbiter 1',
|
||||||
extra: []
|
extra: [],
|
||||||
},
|
},
|
||||||
replica: {
|
replica: {
|
||||||
creation: 'replica ' + redundancy + ' ',
|
creation: 'replica ' + redundancy + ' ',
|
||||||
extra: ['volume set xosan cluster.data-self-heal on']
|
extra: ['volume set xosan cluster.data-self-heal on'],
|
||||||
},
|
},
|
||||||
disperse: {
|
disperse: {
|
||||||
creation: 'disperse ' + ipAndHosts.length + ' redundancy ' + redundancy + ' ',
|
creation: 'disperse ' + ipAndHosts.length + ' redundancy ' + redundancy + ' ',
|
||||||
extra: []
|
extra: [],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
let brickVms = arbiter ? ipAndHosts.concat(arbiter) : ipAndHosts
|
const brickVms = arbiter ? ipAndHosts.concat(arbiter) : ipAndHosts
|
||||||
await _probePoolAndWaitForPresence(glusterEndpoint, map(brickVms.slice(1), bv => bv.address))
|
await _probePoolAndWaitForPresence(glusterEndpoint, map(brickVms.slice(1), bv => bv.address))
|
||||||
const creation = configByType[glusterType].creation
|
const creation = configByType[glusterType].creation
|
||||||
const volumeCreation = 'volume create xosan ' + creation + ' ' +
|
const volumeCreation = 'volume create xosan ' + creation + ' ' +
|
||||||
@ -418,12 +418,12 @@ async function configureGluster (redundancy, ipAndHosts, glusterEndpoint, gluste
|
|||||||
|
|
||||||
export const createSR = defer.onFailure(async function ($onFailure, {
|
export const createSR = defer.onFailure(async function ($onFailure, {
|
||||||
template, pif, vlan, srs, glusterType,
|
template, pif, vlan, srs, glusterType,
|
||||||
redundancy, brickSize = this::computeBrickSize(srs), memorySize = 2 * GIGABYTE, ipRange = DEFAULT_NETWORK_PREFIX + '.0'
|
redundancy, brickSize = this::computeBrickSize(srs), memorySize = 2 * GIGABYTE, ipRange = DEFAULT_NETWORK_PREFIX + '.0',
|
||||||
}) {
|
}) {
|
||||||
const OPERATION_OBJECT = {
|
const OPERATION_OBJECT = {
|
||||||
operation: 'createSr',
|
operation: 'createSr',
|
||||||
states: ['configuringNetwork', 'importingVm', 'copyingVms',
|
states: ['configuringNetwork', 'importingVm', 'copyingVms',
|
||||||
'configuringVms', 'configuringGluster', 'creatingSr', 'scanningSr']
|
'configuringVms', 'configuringGluster', 'creatingSr', 'scanningSr'],
|
||||||
}
|
}
|
||||||
if (!this.requestResource) {
|
if (!this.requestResource) {
|
||||||
throw new Error('requestResource is not a function')
|
throw new Error('requestResource is not a function')
|
||||||
@ -450,7 +450,7 @@ export const createSR = defer.onFailure(async function ($onFailure, {
|
|||||||
await Promise.all(srsObjects.map(sr => callPlugin(xapi, sr.$PBDs[0].$host, 'receive_ssh_keys', {
|
await Promise.all(srsObjects.map(sr => callPlugin(xapi, sr.$PBDs[0].$host, 'receive_ssh_keys', {
|
||||||
private_key: sshKey.private,
|
private_key: sshKey.private,
|
||||||
public_key: sshKey.public,
|
public_key: sshKey.public,
|
||||||
force: 'true'
|
force: 'true',
|
||||||
})))
|
})))
|
||||||
|
|
||||||
const firstSr = srsObjects[0]
|
const firstSr = srsObjects[0]
|
||||||
@ -465,7 +465,7 @@ export const createSR = defer.onFailure(async function ($onFailure, {
|
|||||||
)
|
)
|
||||||
const vmsAndSrs = [{
|
const vmsAndSrs = [{
|
||||||
vm: firstVM,
|
vm: firstVM,
|
||||||
sr: firstSr
|
sr: firstSr,
|
||||||
}].concat(copiedVms)
|
}].concat(copiedVms)
|
||||||
let arbiter = null
|
let arbiter = null
|
||||||
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 3}
|
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 3}
|
||||||
@ -477,7 +477,7 @@ export const createSR = defer.onFailure(async function ($onFailure, {
|
|||||||
arbiter = await _prepareGlusterVm(xapi, sr, arbiterVm, xosanNetwork, arbiterIP, {
|
arbiter = await _prepareGlusterVm(xapi, sr, arbiterVm, xosanNetwork, arbiterIP, {
|
||||||
labelSuffix: '_arbiter',
|
labelSuffix: '_arbiter',
|
||||||
increaseDataDisk: false,
|
increaseDataDisk: false,
|
||||||
memorySize
|
memorySize,
|
||||||
})
|
})
|
||||||
arbiter.arbiter = true
|
arbiter.arbiter = true
|
||||||
}
|
}
|
||||||
@ -507,7 +507,7 @@ export const createSR = defer.onFailure(async function ($onFailure, {
|
|||||||
host: param.host.$id,
|
host: param.host.$id,
|
||||||
vm: {id: param.vm.$id, ip: param.address},
|
vm: {id: param.vm.$id, ip: param.address},
|
||||||
underlyingSr: param.underlyingSr.$id,
|
underlyingSr: param.underlyingSr.$id,
|
||||||
arbiter: !!param['arbiter']
|
arbiter: !!param['arbiter'],
|
||||||
}))
|
}))
|
||||||
await xapi.xo.setData(xosanSrRef, 'xosan_config', {
|
await xapi.xo.setData(xosanSrRef, 'xosan_config', {
|
||||||
version: 'beta2',
|
version: 'beta2',
|
||||||
@ -516,7 +516,7 @@ export const createSR = defer.onFailure(async function ($onFailure, {
|
|||||||
network: xosanNetwork.$id,
|
network: xosanNetwork.$id,
|
||||||
type: glusterType,
|
type: glusterType,
|
||||||
networkPrefix,
|
networkPrefix,
|
||||||
redundancy
|
redundancy,
|
||||||
})
|
})
|
||||||
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 6}
|
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 6}
|
||||||
debug('scanning new SR')
|
debug('scanning new SR')
|
||||||
@ -532,32 +532,32 @@ createSR.params = {
|
|||||||
srs: {
|
srs: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
pif: {
|
pif: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
vlan: {
|
vlan: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
glusterType: {
|
glusterType: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
redundancy: {
|
redundancy: {
|
||||||
type: 'number'
|
type: 'number',
|
||||||
},
|
},
|
||||||
memorySize: {
|
memorySize: {
|
||||||
type: 'number', optional: true
|
type: 'number', optional: true,
|
||||||
},
|
},
|
||||||
ipRange: {
|
ipRange: {
|
||||||
type: 'string', optional: true
|
type: 'string', optional: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
createSR.resolve = {
|
createSR.resolve = {
|
||||||
srs: ['sr', 'SR', 'administrate'],
|
srs: ['sr', 'SR', 'administrate'],
|
||||||
pif: ['pif', 'PIF', 'administrate']
|
pif: ['pif', 'PIF', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
async function umountDisk (localEndpoint, diskMountPoint) {
|
async function umountDisk (localEndpoint, diskMountPoint) {
|
||||||
@ -608,7 +608,7 @@ async function mountNewDisk (localEndpoint, hostname, newDeviceFiledeviceFile) {
|
|||||||
async function replaceBrickOnSameVM (xosansr, previousBrick, newLvmSr, brickSize) {
|
async function replaceBrickOnSameVM (xosansr, previousBrick, newLvmSr, brickSize) {
|
||||||
const OPERATION_OBJECT = {
|
const OPERATION_OBJECT = {
|
||||||
operation: 'replaceBrick',
|
operation: 'replaceBrick',
|
||||||
states: ['creatingNewDisk', 'mountingDisk', 'swappingBrick', 'disconnectingOldDisk', 'scanningSr']
|
states: ['creatingNewDisk', 'mountingDisk', 'swappingBrick', 'disconnectingOldDisk', 'scanningSr'],
|
||||||
}
|
}
|
||||||
const xapi = this.getXapi(xosansr)
|
const xapi = this.getXapi(xosansr)
|
||||||
const poolId = xapi.pool.$id
|
const poolId = xapi.pool.$id
|
||||||
@ -627,7 +627,7 @@ async function replaceBrickOnSameVM (xosansr, previousBrick, newLvmSr, brickSize
|
|||||||
const localEndpoint = {
|
const localEndpoint = {
|
||||||
xapi,
|
xapi,
|
||||||
hosts: map(nodes, node => xapi.getObject(node.host)),
|
hosts: map(nodes, node => xapi.getObject(node.host)),
|
||||||
addresses: [previousIp]
|
addresses: [previousIp],
|
||||||
}
|
}
|
||||||
const previousBrickRoot = previousBrick.split(':')[1].split('/').slice(0, 3).join('/')
|
const previousBrickRoot = previousBrick.split(':')[1].split('/').slice(0, 3).join('/')
|
||||||
const previousBrickDevice = (await remoteSsh(localEndpoint, `grep " ${previousBrickRoot} " /proc/mounts | cut -d ' ' -f 1 | sed 's_/dev/__'`)).stdout.trim()
|
const previousBrickDevice = (await remoteSsh(localEndpoint, `grep " ${previousBrickRoot} " /proc/mounts | cut -d ' ' -f 1 | sed 's_/dev/__'`)).stdout.trim()
|
||||||
@ -653,7 +653,7 @@ async function replaceBrickOnSameVM (xosansr, previousBrick, newLvmSr, brickSize
|
|||||||
export async function replaceBrick ({xosansr, previousBrick, newLvmSr, brickSize, onSameVM = true}) {
|
export async function replaceBrick ({xosansr, previousBrick, newLvmSr, brickSize, onSameVM = true}) {
|
||||||
const OPERATION_OBJECT = {
|
const OPERATION_OBJECT = {
|
||||||
operation: 'replaceBrick',
|
operation: 'replaceBrick',
|
||||||
states: ['insertingNewVm', 'swapingBrick', 'deletingVm', 'scaningSr']
|
states: ['insertingNewVm', 'swapingBrick', 'deletingVm', 'scaningSr'],
|
||||||
}
|
}
|
||||||
if (onSameVM) {
|
if (onSameVM) {
|
||||||
return this::replaceBrickOnSameVM(xosansr, previousBrick, newLvmSr, brickSize)
|
return this::replaceBrickOnSameVM(xosansr, previousBrick, newLvmSr, brickSize)
|
||||||
@ -672,12 +672,12 @@ export async function replaceBrick ({xosansr, previousBrick, newLvmSr, brickSize
|
|||||||
const glusterEndpoint = {
|
const glusterEndpoint = {
|
||||||
xapi,
|
xapi,
|
||||||
hosts: map(stayingNodes, node => xapi.getObject(node.host)),
|
hosts: map(stayingNodes, node => xapi.getObject(node.host)),
|
||||||
addresses: map(stayingNodes, node => node.vm.ip)
|
addresses: map(stayingNodes, node => node.vm.ip),
|
||||||
}
|
}
|
||||||
const previousVMEntry = _getIPToVMDict(xapi, xosansr)[previousBrick]
|
const previousVMEntry = _getIPToVMDict(xapi, xosansr)[previousBrick]
|
||||||
const arbiter = nodes[nodeIndex].arbiter
|
const arbiter = nodes[nodeIndex].arbiter
|
||||||
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 0}
|
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 0}
|
||||||
let {newVM, addressAndHost} = await this::insertNewGlusterVm(xapi, xosansr, newLvmSr,
|
const {newVM, addressAndHost} = await this::insertNewGlusterVm(xapi, xosansr, newLvmSr,
|
||||||
{labelSuffix: arbiter ? '_arbiter' : '', glusterEndpoint, newIpAddress, increaseDataDisk: !arbiter, brickSize})
|
{labelSuffix: arbiter ? '_arbiter' : '', glusterEndpoint, newIpAddress, increaseDataDisk: !arbiter, brickSize})
|
||||||
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 1}
|
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 1}
|
||||||
await glusterCmd(glusterEndpoint, `volume replace-brick xosan ${previousBrick} ${addressAndHost.brickName} commit force`)
|
await glusterCmd(glusterEndpoint, `volume replace-brick xosan ${previousBrick} ${addressAndHost.brickName} commit force`)
|
||||||
@ -687,7 +687,7 @@ export async function replaceBrick ({xosansr, previousBrick, newLvmSr, brickSize
|
|||||||
host: addressAndHost.host.$id,
|
host: addressAndHost.host.$id,
|
||||||
arbiter: arbiter,
|
arbiter: arbiter,
|
||||||
vm: {ip: addressAndHost.address, id: newVM.$id},
|
vm: {ip: addressAndHost.address, id: newVM.$id},
|
||||||
underlyingSr: newLvmSr
|
underlyingSr: newLvmSr,
|
||||||
})
|
})
|
||||||
await xapi.xo.setData(xosansr, 'xosan_config', data)
|
await xapi.xo.setData(xosansr, 'xosan_config', data)
|
||||||
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 2}
|
CURRENT_POOL_OPERATIONS[poolId] = {...OPERATION_OBJECT, state: 2}
|
||||||
@ -707,16 +707,16 @@ replaceBrick.params = {
|
|||||||
xosansr: {type: 'string'},
|
xosansr: {type: 'string'},
|
||||||
previousBrick: {type: 'string'},
|
previousBrick: {type: 'string'},
|
||||||
newLvmSr: {type: 'string'},
|
newLvmSr: {type: 'string'},
|
||||||
brickSize: {type: 'number'}
|
brickSize: {type: 'number'},
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceBrick.resolve = {
|
replaceBrick.resolve = {
|
||||||
xosansr: ['sr', 'SR', 'administrate']
|
xosansr: ['sr', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _prepareGlusterVm (xapi, lvmSr, newVM, xosanNetwork, ipAddress, {
|
async function _prepareGlusterVm (xapi, lvmSr, newVM, xosanNetwork, ipAddress, {
|
||||||
labelSuffix = '', increaseDataDisk = true,
|
labelSuffix = '', increaseDataDisk = true,
|
||||||
maxDiskSize = Infinity, memorySize = 2 * GIGABYTE
|
maxDiskSize = Infinity, memorySize = 2 * GIGABYTE,
|
||||||
}) {
|
}) {
|
||||||
const host = lvmSr.$PBDs[0].$host
|
const host = lvmSr.$PBDs[0].$host
|
||||||
const xenstoreData = {
|
const xenstoreData = {
|
||||||
@ -724,7 +724,7 @@ async function _prepareGlusterVm (xapi, lvmSr, newVM, xosanNetwork, ipAddress, {
|
|||||||
'vm-data/sshkey': (await getOrCreateSshKey(xapi)).public,
|
'vm-data/sshkey': (await getOrCreateSshKey(xapi)).public,
|
||||||
'vm-data/ip': ipAddress,
|
'vm-data/ip': ipAddress,
|
||||||
'vm-data/mtu': String(xosanNetwork.MTU),
|
'vm-data/mtu': String(xosanNetwork.MTU),
|
||||||
'vm-data/vlan': String(xosanNetwork.$PIFs[0].vlan || 0)
|
'vm-data/vlan': String(xosanNetwork.$PIFs[0].vlan || 0),
|
||||||
}
|
}
|
||||||
const ip = ipAddress
|
const ip = ipAddress
|
||||||
const sr = xapi.getObject(lvmSr.$id)
|
const sr = xapi.getObject(lvmSr.$id)
|
||||||
@ -750,7 +750,7 @@ async function _prepareGlusterVm (xapi, lvmSr, newVM, xosanNetwork, ipAddress, {
|
|||||||
memoryMax: memorySize,
|
memoryMax: memorySize,
|
||||||
memoryMin: memorySize,
|
memoryMin: memorySize,
|
||||||
memoryStaticMax: memorySize,
|
memoryStaticMax: memorySize,
|
||||||
memory: memorySize
|
memory: memorySize,
|
||||||
})
|
})
|
||||||
await xapi.call('VM.set_xenstore_data', newVM.$ref, xenstoreData)
|
await xapi.call('VM.set_xenstore_data', newVM.$ref, xenstoreData)
|
||||||
const rootDisk = newVM.$VBDs.map(vbd => vbd && vbd.$VDI).find(vdi => vdi && vdi.name_label === 'xosan_root')
|
const rootDisk = newVM.$VBDs.map(vbd => vbd && vbd.$VDI).find(vdi => vdi && vdi.name_label === 'xosan_root')
|
||||||
@ -778,7 +778,7 @@ async function _importGlusterVM (xapi, template, lvmsrId) {
|
|||||||
await xapi.editVm(newVM, {
|
await xapi.editVm(newVM, {
|
||||||
autoPoweron: true,
|
autoPoweron: true,
|
||||||
name_label: 'XOSAN imported VM',
|
name_label: 'XOSAN imported VM',
|
||||||
name_description: 'freshly imported'
|
name_description: 'freshly imported',
|
||||||
})
|
})
|
||||||
return xapi.barrier(newVM.$ref)
|
return xapi.barrier(newVM.$ref)
|
||||||
}
|
}
|
||||||
@ -804,7 +804,7 @@ const _median = arr => {
|
|||||||
|
|
||||||
const insertNewGlusterVm = defer.onFailure(async function ($onFailure, xapi, xosansr, lvmsrId, {
|
const insertNewGlusterVm = defer.onFailure(async function ($onFailure, xapi, xosansr, lvmsrId, {
|
||||||
labelSuffix = '',
|
labelSuffix = '',
|
||||||
glusterEndpoint = null, ipAddress = null, increaseDataDisk = true, brickSize = Infinity
|
glusterEndpoint = null, ipAddress = null, increaseDataDisk = true, brickSize = Infinity,
|
||||||
}) {
|
}) {
|
||||||
const data = getXosanConfig(xosansr, xapi)
|
const data = getXosanConfig(xosansr, xapi)
|
||||||
if (ipAddress === null) {
|
if (ipAddress === null) {
|
||||||
@ -827,7 +827,7 @@ const insertNewGlusterVm = defer.onFailure(async function ($onFailure, xapi, xos
|
|||||||
labelSuffix,
|
labelSuffix,
|
||||||
increaseDataDisk,
|
increaseDataDisk,
|
||||||
maxDiskSize: brickSize,
|
maxDiskSize: brickSize,
|
||||||
memorySize: vmsMemories.length ? _median(vmsMemories) : 2 * GIGABYTE
|
memorySize: vmsMemories.length ? _median(vmsMemories) : 2 * GIGABYTE,
|
||||||
})
|
})
|
||||||
if (!glusterEndpoint) {
|
if (!glusterEndpoint) {
|
||||||
glusterEndpoint = this::_getGlusterEndpoint(xosansr)
|
glusterEndpoint = this::_getGlusterEndpoint(xosansr)
|
||||||
@ -839,7 +839,7 @@ const insertNewGlusterVm = defer.onFailure(async function ($onFailure, xapi, xos
|
|||||||
export const addBricks = defer.onFailure(async function ($onFailure, {xosansr, lvmsrs, brickSize}) {
|
export const addBricks = defer.onFailure(async function ($onFailure, {xosansr, lvmsrs, brickSize}) {
|
||||||
const OPERATION_OBJECT = {
|
const OPERATION_OBJECT = {
|
||||||
operation: 'addBricks',
|
operation: 'addBricks',
|
||||||
states: ['insertingNewVms', 'addingBricks', 'scaningSr']
|
states: ['insertingNewVms', 'addingBricks', 'scaningSr'],
|
||||||
}
|
}
|
||||||
const xapi = this.getXapi(xosansr)
|
const xapi = this.getXapi(xosansr)
|
||||||
const poolId = xapi.pool.$id
|
const poolId = xapi.pool.$id
|
||||||
@ -890,15 +890,15 @@ addBricks.params = {
|
|||||||
lvmsrs: {
|
lvmsrs: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
brickSize: {type: 'number'}
|
brickSize: {type: 'number'},
|
||||||
}
|
}
|
||||||
|
|
||||||
addBricks.resolve = {
|
addBricks.resolve = {
|
||||||
xosansr: ['sr', 'SR', 'administrate'],
|
xosansr: ['sr', 'SR', 'administrate'],
|
||||||
lvmsrs: ['sr', 'SR', 'administrate']
|
lvmsrs: ['sr', 'SR', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const removeBricks = defer.onFailure(async function ($onFailure, {xosansr, bricks}) {
|
export const removeBricks = defer.onFailure(async function ($onFailure, {xosansr, bricks}) {
|
||||||
@ -933,8 +933,8 @@ removeBricks.params = {
|
|||||||
xosansr: {type: 'string'},
|
xosansr: {type: 'string'},
|
||||||
bricks: {
|
bricks: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {type: 'string'}
|
items: {type: 'string'},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkSrCurrentState ({poolId}) {
|
export function checkSrCurrentState ({poolId}) {
|
||||||
@ -1001,12 +1001,12 @@ computeXosanPossibleOptions.params = {
|
|||||||
lvmSrs: {
|
lvmSrs: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
brickSize: {
|
brickSize: {
|
||||||
type: 'number', optional: true
|
type: 'number', optional: true,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
@ -1021,7 +1021,7 @@ export async function downloadAndInstallXosanPack ({id, version, pool}) {
|
|||||||
|
|
||||||
await xapi.installSupplementalPackOnAllHosts(res)
|
await xapi.installSupplementalPackOnAllHosts(res)
|
||||||
await xapi._updateObjectMapProperty(xapi.pool, 'other_config', {
|
await xapi._updateObjectMapProperty(xapi.pool, 'other_config', {
|
||||||
'xosan_pack_installation_time': String(Math.floor(Date.now() / 1e3))
|
'xosan_pack_installation_time': String(Math.floor(Date.now() / 1e3)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1030,11 +1030,11 @@ downloadAndInstallXosanPack.description = 'Register a resource via cloud plugin'
|
|||||||
downloadAndInstallXosanPack.params = {
|
downloadAndInstallXosanPack.params = {
|
||||||
id: {type: 'string'},
|
id: {type: 'string'},
|
||||||
version: {type: 'string'},
|
version: {type: 'string'},
|
||||||
pool: {type: 'string'}
|
pool: {type: 'string'},
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadAndInstallXosanPack.resolve = {
|
downloadAndInstallXosanPack.resolve = {
|
||||||
pool: ['pool', 'pool', 'administrate']
|
pool: ['pool', 'pool', 'administrate'],
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadAndInstallXosanPack.permission = 'admin'
|
downloadAndInstallXosanPack.permission = 'admin'
|
||||||
|
@ -4,8 +4,8 @@ import {EventEmitter} from 'events'
|
|||||||
import {
|
import {
|
||||||
isArray,
|
isArray,
|
||||||
isObject,
|
isObject,
|
||||||
map
|
map,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ export default class Collection extends EventEmitter {
|
|||||||
configurable: true,
|
configurable: true,
|
||||||
enumerale: true,
|
enumerale: true,
|
||||||
value: Model,
|
value: Model,
|
||||||
writable: true
|
writable: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ export default class Redis extends Collection {
|
|||||||
connection,
|
connection,
|
||||||
indexes = [],
|
indexes = [],
|
||||||
prefix,
|
prefix,
|
||||||
uri
|
uri,
|
||||||
}) {
|
}) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ export default class Redis extends Collection {
|
|||||||
const key = `${prefix}:${id}`
|
const key = `${prefix}:${id}`
|
||||||
const promises = [
|
const promises = [
|
||||||
redis.del(key),
|
redis.del(key),
|
||||||
redis.hmset(key, ...params)
|
redis.hmset(key, ...params),
|
||||||
]
|
]
|
||||||
|
|
||||||
// Update indexes.
|
// Update indexes.
|
||||||
|
@ -2,14 +2,14 @@ import { getBoundPropertyDescriptor } from 'bind-property-descriptor'
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
isArray,
|
isArray,
|
||||||
isFunction
|
isFunction,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
const {
|
const {
|
||||||
defineProperties,
|
defineProperties,
|
||||||
getOwnPropertyDescriptor
|
getOwnPropertyDescriptor,
|
||||||
} = Object
|
} = Object
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -29,7 +29,7 @@ export const debounce = duration => (target, name, descriptor) => {
|
|||||||
function debounced () {
|
function debounced () {
|
||||||
const data = this[s] || (this[s] = {
|
const data = this[s] || (this[s] = {
|
||||||
lastCall: 0,
|
lastCall: 0,
|
||||||
wrapper: null
|
wrapper: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
@ -56,7 +56,7 @@ const _ownKeys = (
|
|||||||
(typeof Reflect !== 'undefined' && Reflect.ownKeys) ||
|
(typeof Reflect !== 'undefined' && Reflect.ownKeys) ||
|
||||||
(({
|
(({
|
||||||
getOwnPropertyNames: names,
|
getOwnPropertyNames: names,
|
||||||
getOwnPropertySymbols: symbols
|
getOwnPropertySymbols: symbols,
|
||||||
}) => symbols
|
}) => symbols
|
||||||
? obj => names(obj).concat(symbols(obj))
|
? obj => names(obj).concat(symbols(obj))
|
||||||
: names
|
: names
|
||||||
@ -75,7 +75,7 @@ const _IGNORED_STATIC_PROPERTIES = {
|
|||||||
caller: true,
|
caller: true,
|
||||||
length: true,
|
length: true,
|
||||||
name: true,
|
name: true,
|
||||||
prototype: true
|
prototype: true,
|
||||||
}
|
}
|
||||||
const _isIgnoredStaticProperty = name => _IGNORED_STATIC_PROPERTIES[name]
|
const _isIgnoredStaticProperty = name => _IGNORED_STATIC_PROPERTIES[name]
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ export function init () {
|
|||||||
BootSig: 41,
|
BootSig: 41,
|
||||||
VolID: 895111106,
|
VolID: 895111106,
|
||||||
VolLab: 'NO NAME ',
|
VolLab: 'NO NAME ',
|
||||||
FilSysType: 'FAT16 '
|
FilSysType: 'FAT16 ',
|
||||||
}, buf)
|
}, buf)
|
||||||
|
|
||||||
// End of sector.
|
// End of sector.
|
||||||
@ -80,6 +80,6 @@ export default buffer => {
|
|||||||
writeSectors: (i, source, cb) => {
|
writeSectors: (i, source, cb) => {
|
||||||
source.copy(buffer, i * SECTOR_SIZE, 0)
|
source.copy(buffer, i * SECTOR_SIZE, 0)
|
||||||
cb()
|
cb()
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// See: https://gist.github.com/julien-f/5b9a3537eb82a34b04e2
|
// See: https://gist.github.com/julien-f/5b9a3537eb82a34b04e2
|
||||||
|
|
||||||
var matcher = require('micromatch').matcher
|
const matcher = require('micromatch').matcher
|
||||||
|
|
||||||
module.exports = function globMatcher (patterns, opts) {
|
module.exports = function globMatcher (patterns, opts) {
|
||||||
if (!Array.isArray(patterns)) {
|
if (!Array.isArray(patterns)) {
|
||||||
if (patterns[0] === '!') {
|
if (patterns[0] === '!') {
|
||||||
var m = matcher(patterns.slice(1), opts)
|
const m = matcher(patterns.slice(1), opts)
|
||||||
return function (string) {
|
return function (string) {
|
||||||
return !m(string)
|
return !m(string)
|
||||||
}
|
}
|
||||||
@ -14,12 +14,12 @@ module.exports = function globMatcher (patterns, opts) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var noneMustMatch = []
|
const noneMustMatch = []
|
||||||
var anyMustMatch = []
|
const anyMustMatch = []
|
||||||
|
|
||||||
// TODO: could probably be optimized by combining all positive patterns (and all negative patterns) as a single matcher.
|
// TODO: could probably be optimized by combining all positive patterns (and all negative patterns) as a single matcher.
|
||||||
for (var i = 0, n = patterns.length; i < n; ++i) {
|
for (let i = 0, n = patterns.length; i < n; ++i) {
|
||||||
var pattern = patterns[i]
|
const pattern = patterns[i]
|
||||||
if (pattern[0] === '!') {
|
if (pattern[0] === '!') {
|
||||||
noneMustMatch.push(matcher(pattern.slice(1), opts))
|
noneMustMatch.push(matcher(pattern.slice(1), opts))
|
||||||
} else {
|
} else {
|
||||||
@ -27,11 +27,11 @@ module.exports = function globMatcher (patterns, opts) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var nNone = noneMustMatch.length
|
const nNone = noneMustMatch.length
|
||||||
var nAny = anyMustMatch.length
|
const nAny = anyMustMatch.length
|
||||||
|
|
||||||
return function (string) {
|
return function (string) {
|
||||||
var i
|
let i
|
||||||
|
|
||||||
for (i = 0; i < nNone; ++i) {
|
for (i = 0; i < nNone; ++i) {
|
||||||
if (noneMustMatch[i](string)) {
|
if (noneMustMatch[i](string)) {
|
||||||
|
34
src/index.js
34
src/index.js
@ -20,7 +20,7 @@ import { invalidCredentials } from 'xo-common/api-errors'
|
|||||||
import {
|
import {
|
||||||
ensureDir,
|
ensureDir,
|
||||||
readdir,
|
readdir,
|
||||||
readFile
|
readFile,
|
||||||
} from 'fs-extra'
|
} from 'fs-extra'
|
||||||
|
|
||||||
import WebServer from 'http-server-plus'
|
import WebServer from 'http-server-plus'
|
||||||
@ -31,7 +31,7 @@ import {
|
|||||||
isArray,
|
isArray,
|
||||||
isFunction,
|
isFunction,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
pFromCallback
|
pFromCallback,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
import bodyParser from 'body-parser'
|
import bodyParser from 'body-parser'
|
||||||
@ -54,12 +54,12 @@ const warn = (...args) => {
|
|||||||
|
|
||||||
const DEPRECATED_ENTRIES = [
|
const DEPRECATED_ENTRIES = [
|
||||||
'users',
|
'users',
|
||||||
'servers'
|
'servers',
|
||||||
]
|
]
|
||||||
|
|
||||||
async function loadConfiguration () {
|
async function loadConfiguration () {
|
||||||
const config = await appConf.load('xo-server', {
|
const config = await appConf.load('xo-server', {
|
||||||
ignoreUnknownFormats: true
|
ignoreUnknownFormats: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
debug('Configuration loaded.')
|
debug('Configuration loaded.')
|
||||||
@ -89,7 +89,7 @@ function createExpressApp () {
|
|||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
|
|
||||||
// TODO: should be in the config file.
|
// TODO: should be in the config file.
|
||||||
secret: 'CLWguhRZAZIXZcbrMzHCYmefxgweItKnS'
|
secret: 'CLWguhRZAZIXZcbrMzHCYmefxgweItKnS',
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Registers the connect-flash middleware, necessary for Passport to
|
// Registers the connect-flash middleware, necessary for Passport to
|
||||||
@ -124,7 +124,7 @@ async function setUpPassport (express, xo) {
|
|||||||
express.get('/signin', (req, res, next) => {
|
express.get('/signin', (req, res, next) => {
|
||||||
res.send(signInPage({
|
res.send(signInPage({
|
||||||
error: req.flash('error')[0],
|
error: req.flash('error')[0],
|
||||||
strategies
|
strategies,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -220,7 +220,7 @@ async function registerPlugin (pluginPath, pluginName) {
|
|||||||
default: factory = plugin,
|
default: factory = plugin,
|
||||||
configurationSchema,
|
configurationSchema,
|
||||||
configurationPresets,
|
configurationPresets,
|
||||||
testSchema
|
testSchema,
|
||||||
} = plugin
|
} = plugin
|
||||||
|
|
||||||
// The default export can be either a factory or directly a plugin
|
// The default export can be either a factory or directly a plugin
|
||||||
@ -231,7 +231,7 @@ async function registerPlugin (pluginPath, pluginName) {
|
|||||||
getDataDir: () => {
|
getDataDir: () => {
|
||||||
const dir = `${this._config.datadir}/${pluginName}`
|
const dir = `${this._config.datadir}/${pluginName}`
|
||||||
return ensureDir(dir).then(() => dir)
|
return ensureDir(dir).then(() => dir)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
: factory
|
: factory
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ async function registerPluginsInPath (path) {
|
|||||||
async function registerPlugins (xo) {
|
async function registerPlugins (xo) {
|
||||||
await Promise.all(mapToArray([
|
await Promise.all(mapToArray([
|
||||||
`${__dirname}/../node_modules/`,
|
`${__dirname}/../node_modules/`,
|
||||||
'/usr/local/lib/node_modules/'
|
'/usr/local/lib/node_modules/',
|
||||||
], xo::registerPluginsInPath))
|
], xo::registerPluginsInPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ async function makeWebServerListen (webServer, {
|
|||||||
if (cert && key) {
|
if (cert && key) {
|
||||||
[opts.cert, opts.key] = await Promise.all([
|
[opts.cert, opts.key] = await Promise.all([
|
||||||
readFile(cert),
|
readFile(cert),
|
||||||
readFile(key)
|
readFile(key),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -346,7 +346,7 @@ const setUpProxies = (express, opts, xo) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const proxy = createProxyServer({
|
const proxy = createProxyServer({
|
||||||
ignorePath: true
|
ignorePath: true,
|
||||||
}).on('error', (error) => console.error(error))
|
}).on('error', (error) => console.error(error))
|
||||||
|
|
||||||
// TODO: sort proxies by descending prefix length.
|
// TODO: sort proxies by descending prefix length.
|
||||||
@ -360,7 +360,7 @@ const setUpProxies = (express, opts, xo) => {
|
|||||||
const target = opts[prefix]
|
const target = opts[prefix]
|
||||||
|
|
||||||
proxy.web(req, res, {
|
proxy.web(req, res, {
|
||||||
target: target + url.slice(prefix.length)
|
target: target + url.slice(prefix.length),
|
||||||
})
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -372,7 +372,7 @@ const setUpProxies = (express, opts, xo) => {
|
|||||||
|
|
||||||
// WebSocket proxy.
|
// WebSocket proxy.
|
||||||
const webSocketServer = new WebSocket.Server({
|
const webSocketServer = new WebSocket.Server({
|
||||||
noServer: true
|
noServer: true,
|
||||||
})
|
})
|
||||||
xo.on('stop', () => pFromCallback(cb => webSocketServer.close(cb)))
|
xo.on('stop', () => pFromCallback(cb => webSocketServer.close(cb)))
|
||||||
|
|
||||||
@ -384,7 +384,7 @@ const setUpProxies = (express, opts, xo) => {
|
|||||||
const target = opts[prefix]
|
const target = opts[prefix]
|
||||||
|
|
||||||
proxy.ws(req, socket, head, {
|
proxy.ws(req, socket, head, {
|
||||||
target: target + url.slice(prefix.length)
|
target: target + url.slice(prefix.length),
|
||||||
})
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -413,7 +413,7 @@ const setUpStaticFiles = (express, opts) => {
|
|||||||
|
|
||||||
const setUpApi = (webServer, xo, verboseLogsOnErrors) => {
|
const setUpApi = (webServer, xo, verboseLogsOnErrors) => {
|
||||||
const webSocketServer = new WebSocket.Server({
|
const webSocketServer = new WebSocket.Server({
|
||||||
noServer: true
|
noServer: true,
|
||||||
})
|
})
|
||||||
xo.on('stop', () => pFromCallback(cb => webSocketServer.close(cb)))
|
xo.on('stop', () => pFromCallback(cb => webSocketServer.close(cb)))
|
||||||
|
|
||||||
@ -474,7 +474,7 @@ const CONSOLE_PROXY_PATH_RE = /^\/api\/consoles\/(.*)$/
|
|||||||
|
|
||||||
const setUpConsoleProxy = (webServer, xo) => {
|
const setUpConsoleProxy = (webServer, xo) => {
|
||||||
const webSocketServer = new WebSocket.Server({
|
const webSocketServer = new WebSocket.Server({
|
||||||
noServer: true
|
noServer: true,
|
||||||
})
|
})
|
||||||
xo.on('stop', () => pFromCallback(cb => webSocketServer.close(cb)))
|
xo.on('stop', () => pFromCallback(cb => webSocketServer.close(cb)))
|
||||||
|
|
||||||
@ -519,7 +519,7 @@ const setUpConsoleProxy = (webServer, xo) => {
|
|||||||
|
|
||||||
const USAGE = (({
|
const USAGE = (({
|
||||||
name,
|
name,
|
||||||
version
|
version,
|
||||||
}) => `Usage: ${name} [--safe-mode]
|
}) => `Usage: ${name} [--safe-mode]
|
||||||
|
|
||||||
${name} v${version}`)(require('../package.json'))
|
${name} v${version}`)(require('../package.json'))
|
||||||
|
@ -12,13 +12,13 @@ import {
|
|||||||
map,
|
map,
|
||||||
mapValues,
|
mapValues,
|
||||||
size,
|
size,
|
||||||
some
|
some,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import { crossProduct } from './math'
|
import { crossProduct } from './math'
|
||||||
import {
|
import {
|
||||||
serializeError,
|
serializeError,
|
||||||
thunkToArray
|
thunkToArray,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
export class JobExecutorError extends BaseError {}
|
export class JobExecutorError extends BaseError {}
|
||||||
@ -81,11 +81,11 @@ const paramsVectorActionsMap = {
|
|||||||
return map(resolveParamsVector.call(this, collection), value => {
|
return map(resolveParamsVector.call(this, collection), value => {
|
||||||
return resolveParamsVector.call(this, {
|
return resolveParamsVector.call(this, {
|
||||||
...iteratee,
|
...iteratee,
|
||||||
[paramName]: value
|
[paramName]: value,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
set: ({ values }) => values
|
set: ({ values }) => values,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveParamsVector (paramsVector) {
|
export function resolveParamsVector (paramsVector) {
|
||||||
@ -114,7 +114,7 @@ export default class JobExecutor {
|
|||||||
event: 'job.start',
|
event: 'job.start',
|
||||||
userId: job.userId,
|
userId: job.userId,
|
||||||
jobId: job.id,
|
jobId: job.id,
|
||||||
key: job.key
|
key: job.key,
|
||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -128,13 +128,13 @@ export default class JobExecutor {
|
|||||||
|
|
||||||
this._logger.notice(`Execution terminated for ${job.id}.`, {
|
this._logger.notice(`Execution terminated for ${job.id}.`, {
|
||||||
event: 'job.end',
|
event: 'job.end',
|
||||||
runJobId
|
runJobId,
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._logger.error(`The execution of ${job.id} has failed.`, {
|
this._logger.error(`The execution of ${job.id} has failed.`, {
|
||||||
event: 'job.end',
|
event: 'job.end',
|
||||||
runJobId,
|
runJobId,
|
||||||
error: serializeError(error)
|
error: serializeError(error),
|
||||||
})
|
})
|
||||||
|
|
||||||
throw error
|
throw error
|
||||||
@ -157,7 +157,7 @@ export default class JobExecutor {
|
|||||||
calls: {},
|
calls: {},
|
||||||
runJobId,
|
runJobId,
|
||||||
start: Date.now(),
|
start: Date.now(),
|
||||||
timezone: schedule !== undefined ? schedule.timezone : undefined
|
timezone: schedule !== undefined ? schedule.timezone : undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
await Bluebird.map(paramsFlatVector, params => {
|
await Bluebird.map(paramsFlatVector, params => {
|
||||||
@ -165,13 +165,13 @@ export default class JobExecutor {
|
|||||||
event: 'jobCall.start',
|
event: 'jobCall.start',
|
||||||
runJobId,
|
runJobId,
|
||||||
method: job.method,
|
method: job.method,
|
||||||
params
|
params,
|
||||||
})
|
})
|
||||||
|
|
||||||
const call = execStatus.calls[runCallId] = {
|
const call = execStatus.calls[runCallId] = {
|
||||||
method: job.method,
|
method: job.method,
|
||||||
params,
|
params,
|
||||||
start: Date.now()
|
start: Date.now(),
|
||||||
}
|
}
|
||||||
let promise = this.xo.callApiMethod(connection, job.method, assign({}, params))
|
let promise = this.xo.callApiMethod(connection, job.method, assign({}, params))
|
||||||
if (job.timeout) {
|
if (job.timeout) {
|
||||||
@ -184,7 +184,7 @@ export default class JobExecutor {
|
|||||||
event: 'jobCall.end',
|
event: 'jobCall.end',
|
||||||
runJobId,
|
runJobId,
|
||||||
runCallId,
|
runCallId,
|
||||||
returnedValue: value
|
returnedValue: value,
|
||||||
})
|
})
|
||||||
|
|
||||||
call.returnedValue = value
|
call.returnedValue = value
|
||||||
@ -195,7 +195,7 @@ export default class JobExecutor {
|
|||||||
event: 'jobCall.end',
|
event: 'jobCall.end',
|
||||||
runJobId,
|
runJobId,
|
||||||
runCallId,
|
runCallId,
|
||||||
error: serializeError(reason)
|
error: serializeError(reason),
|
||||||
})
|
})
|
||||||
|
|
||||||
call.error = reason
|
call.error = reason
|
||||||
@ -203,7 +203,7 @@ export default class JobExecutor {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}, {
|
}, {
|
||||||
concurrency: 2
|
concurrency: 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
connection.close()
|
connection.close()
|
||||||
|
@ -18,21 +18,21 @@ describe('resolveParamsVector', function () {
|
|||||||
type: 'crossProduct',
|
type: 'crossProduct',
|
||||||
items: [{
|
items: [{
|
||||||
type: 'set',
|
type: 'set',
|
||||||
values: [ { id: 3 }, { id: 7 }, { id: 10 } ]
|
values: [ { id: 3 }, { id: 7 }, { id: 10 } ],
|
||||||
}, {
|
}, {
|
||||||
type: 'set',
|
type: 'set',
|
||||||
values: [ { value: 'foo' }, { value: 'bar' } ]
|
values: [ { value: 'foo' }, { value: 'bar' } ],
|
||||||
}, {
|
}, {
|
||||||
type: 'set',
|
type: 'set',
|
||||||
values: [ { remote: 'local' } ]
|
values: [ { remote: 'local' } ],
|
||||||
}]
|
}],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
'cross product with `set` and `map`': [
|
'cross product with `set` and `map`': [
|
||||||
// Expected result.
|
// Expected result.
|
||||||
[
|
[
|
||||||
{ remote: 'local', id: 'vm:2' },
|
{ remote: 'local', id: 'vm:2' },
|
||||||
{ remote: 'smb', id: 'vm:2' }
|
{ remote: 'smb', id: 'vm:2' },
|
||||||
],
|
],
|
||||||
|
|
||||||
// Entry.
|
// Entry.
|
||||||
@ -40,7 +40,7 @@ describe('resolveParamsVector', function () {
|
|||||||
type: 'crossProduct',
|
type: 'crossProduct',
|
||||||
items: [{
|
items: [{
|
||||||
type: 'set',
|
type: 'set',
|
||||||
values: [ { remote: 'local' }, { remote: 'smb' } ]
|
values: [ { remote: 'local' }, { remote: 'smb' } ],
|
||||||
}, {
|
}, {
|
||||||
type: 'map',
|
type: 'map',
|
||||||
collection: {
|
collection: {
|
||||||
@ -49,14 +49,14 @@ describe('resolveParamsVector', function () {
|
|||||||
$pool: { __or: [ 'pool:1', 'pool:8', 'pool:12' ] },
|
$pool: { __or: [ 'pool:1', 'pool:8', 'pool:12' ] },
|
||||||
power_state: 'Running',
|
power_state: 'Running',
|
||||||
tags: [ 'foo' ],
|
tags: [ 'foo' ],
|
||||||
type: 'VM'
|
type: 'VM',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
iteratee: {
|
iteratee: {
|
||||||
type: 'extractProperties',
|
type: 'extractProperties',
|
||||||
mapping: { id: 'id' }
|
mapping: { id: 'id' },
|
||||||
}
|
},
|
||||||
}]
|
}],
|
||||||
},
|
},
|
||||||
|
|
||||||
// Context.
|
// Context.
|
||||||
@ -68,28 +68,28 @@ describe('resolveParamsVector', function () {
|
|||||||
$pool: 'pool:1',
|
$pool: 'pool:1',
|
||||||
tags: [],
|
tags: [],
|
||||||
type: 'VM',
|
type: 'VM',
|
||||||
power_state: 'Halted'
|
power_state: 'Halted',
|
||||||
}, {
|
}, {
|
||||||
id: 'vm:2',
|
id: 'vm:2',
|
||||||
$pool: 'pool:1',
|
$pool: 'pool:1',
|
||||||
tags: [ 'foo' ],
|
tags: [ 'foo' ],
|
||||||
type: 'VM',
|
type: 'VM',
|
||||||
power_state: 'Running'
|
power_state: 'Running',
|
||||||
}, {
|
}, {
|
||||||
id: 'host:1',
|
id: 'host:1',
|
||||||
type: 'host',
|
type: 'host',
|
||||||
power_state: 'Running'
|
power_state: 'Running',
|
||||||
}, {
|
}, {
|
||||||
id: 'vm:3',
|
id: 'vm:3',
|
||||||
$pool: 'pool:8',
|
$pool: 'pool:8',
|
||||||
tags: [ 'foo' ],
|
tags: [ 'foo' ],
|
||||||
type: 'VM',
|
type: 'VM',
|
||||||
power_state: 'Halted'
|
power_state: 'Halted',
|
||||||
}]
|
}]
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}, ([ expectedResult, entry, context ], name) => {
|
}, ([ expectedResult, entry, context ], name) => {
|
||||||
describe(`with ${name}`, () => {
|
describe(`with ${name}`, () => {
|
||||||
it('Resolves params vector', () => {
|
it('Resolves params vector', () => {
|
||||||
|
@ -105,12 +105,12 @@ function getArgs () {
|
|||||||
default: {
|
default: {
|
||||||
limit: 100,
|
limit: 100,
|
||||||
json: false,
|
json: false,
|
||||||
help: false
|
help: false,
|
||||||
},
|
},
|
||||||
alias: {
|
alias: {
|
||||||
limit: 'n',
|
limit: 'n',
|
||||||
help: 'h'
|
help: 'h',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const patterns = {}
|
const patterns = {}
|
||||||
@ -176,7 +176,7 @@ export default async function main () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const config = await appConf.load('xo-server', {
|
const config = await appConf.load('xo-server', {
|
||||||
ignoreUnknownFormats: true
|
ignoreUnknownFormats: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (args.repair) {
|
if (args.repair) {
|
||||||
|
@ -6,7 +6,7 @@ import { isArray, map } from 'lodash'
|
|||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
const parse = createParser({
|
const parse = createParser({
|
||||||
keyTransform: key => key.slice(5).toLowerCase()
|
keyTransform: key => key.slice(5).toLowerCase(),
|
||||||
})
|
})
|
||||||
const makeFunction = command => (fields, ...args) =>
|
const makeFunction = command => (fields, ...args) =>
|
||||||
execa.stdout(command, [
|
execa.stdout(command, [
|
||||||
@ -18,7 +18,7 @@ const makeFunction = command => (fields, ...args) =>
|
|||||||
'b',
|
'b',
|
||||||
'-o',
|
'-o',
|
||||||
String(fields),
|
String(fields),
|
||||||
...args
|
...args,
|
||||||
]).then(stdout => map(
|
]).then(stdout => map(
|
||||||
splitLines(stdout),
|
splitLines(stdout),
|
||||||
isArray(fields)
|
isArray(fields)
|
||||||
|
@ -4,32 +4,32 @@ import { forEach } from 'lodash'
|
|||||||
import { thunkToArray } from './utils'
|
import { thunkToArray } from './utils'
|
||||||
import {
|
import {
|
||||||
crossProduct,
|
crossProduct,
|
||||||
mergeObjects
|
mergeObjects,
|
||||||
} from './math'
|
} from './math'
|
||||||
|
|
||||||
describe('mergeObjects', function () {
|
describe('mergeObjects', function () {
|
||||||
forEach({
|
forEach({
|
||||||
'Two sets of one': [
|
'Two sets of one': [
|
||||||
{a: 1, b: 2}, {a: 1}, {b: 2}
|
{a: 1, b: 2}, {a: 1}, {b: 2},
|
||||||
],
|
],
|
||||||
'Two sets of two': [
|
'Two sets of two': [
|
||||||
{a: 1, b: 2, c: 3, d: 4}, {a: 1, b: 2}, {c: 3, d: 4}
|
{a: 1, b: 2, c: 3, d: 4}, {a: 1, b: 2}, {c: 3, d: 4},
|
||||||
],
|
],
|
||||||
'Three sets': [
|
'Three sets': [
|
||||||
{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}, {a: 1}, {b: 2, c: 3}, {d: 4, e: 5, f: 6}
|
{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}, {a: 1}, {b: 2, c: 3}, {d: 4, e: 5, f: 6},
|
||||||
],
|
],
|
||||||
'One set': [
|
'One set': [
|
||||||
{a: 1, b: 2}, {a: 1, b: 2}
|
{a: 1, b: 2}, {a: 1, b: 2},
|
||||||
],
|
],
|
||||||
'Empty set': [
|
'Empty set': [
|
||||||
{a: 1}, {a: 1}, {}
|
{a: 1}, {a: 1}, {},
|
||||||
],
|
],
|
||||||
'All empty': [
|
'All empty': [
|
||||||
{}, {}, {}
|
{}, {}, {},
|
||||||
],
|
],
|
||||||
'No set': [
|
'No set': [
|
||||||
{}
|
{},
|
||||||
]
|
],
|
||||||
}, ([ resultSet, ...sets ], name) => {
|
}, ([ resultSet, ...sets ], name) => {
|
||||||
describe(`with ${name}`, () => {
|
describe(`with ${name}`, () => {
|
||||||
it('Assembles all given param sets in on set', function () {
|
it('Assembles all given param sets in on set', function () {
|
||||||
@ -47,23 +47,23 @@ describe('crossProduct', function () {
|
|||||||
|
|
||||||
forEach({
|
forEach({
|
||||||
'2 sets of 2 items to multiply': [
|
'2 sets of 2 items to multiply': [
|
||||||
[10, 14, 15, 21], [[2, 3], [5, 7]], multiplyTest
|
[10, 14, 15, 21], [[2, 3], [5, 7]], multiplyTest,
|
||||||
],
|
],
|
||||||
'3 sets of 2 items to multiply': [
|
'3 sets of 2 items to multiply': [
|
||||||
[110, 130, 154, 182, 165, 195, 231, 273], [[2, 3], [5, 7], [11, 13]], multiplyTest
|
[110, 130, 154, 182, 165, 195, 231, 273], [[2, 3], [5, 7], [11, 13]], multiplyTest,
|
||||||
],
|
],
|
||||||
'2 sets of 3 items to multiply': [
|
'2 sets of 3 items to multiply': [
|
||||||
[14, 22, 26, 21, 33, 39, 35, 55, 65], [[2, 3, 5], [7, 11, 13]], multiplyTest
|
[14, 22, 26, 21, 33, 39, 35, 55, 65], [[2, 3, 5], [7, 11, 13]], multiplyTest,
|
||||||
],
|
],
|
||||||
'2 sets of 2 items to add': [
|
'2 sets of 2 items to add': [
|
||||||
[7, 9, 8, 10], [[2, 3], [5, 7]], addTest
|
[7, 9, 8, 10], [[2, 3], [5, 7]], addTest,
|
||||||
],
|
],
|
||||||
'3 sets of 2 items to add': [
|
'3 sets of 2 items to add': [
|
||||||
[18, 20, 20, 22, 19, 21, 21, 23], [[2, 3], [5, 7], [11, 13]], addTest
|
[18, 20, 20, 22, 19, 21, 21, 23], [[2, 3], [5, 7], [11, 13]], addTest,
|
||||||
],
|
],
|
||||||
'2 sets of 3 items to add': [
|
'2 sets of 3 items to add': [
|
||||||
[9, 13, 15, 10, 14, 16, 12, 16, 18], [[2, 3, 5], [7, 11, 13]], addTest
|
[9, 13, 15, 10, 14, 16, 12, 16, 18], [[2, 3, 5], [7, 11, 13]], addTest,
|
||||||
]
|
],
|
||||||
}, ([ product, items, cb ], name) => {
|
}, ([ product, items, cb ], name) => {
|
||||||
describe(`with ${name}`, () => {
|
describe(`with ${name}`, () => {
|
||||||
it('Crosses sets of values with a crossProduct callback', function () {
|
it('Crosses sets of values with a crossProduct callback', function () {
|
||||||
|
@ -3,7 +3,7 @@ import {EventEmitter} from 'events'
|
|||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
isEmpty,
|
isEmpty,
|
||||||
isString
|
isString,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
@ -3,7 +3,7 @@ import Model from '../model'
|
|||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
multiKeyHash
|
multiKeyHash,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -21,7 +21,7 @@ Acl.create = (subject, object, action) => {
|
|||||||
id: hash,
|
id: hash,
|
||||||
subject,
|
subject,
|
||||||
object,
|
object,
|
||||||
action
|
action,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ export class PluginsMetadata extends Collection {
|
|||||||
return /* await */ this.update({
|
return /* await */ this.update({
|
||||||
id,
|
id,
|
||||||
autoload: autoload ? 'true' : 'false',
|
autoload: autoload ? 'true' : 'false',
|
||||||
configuration: configuration && JSON.stringify(configuration)
|
configuration: configuration && JSON.stringify(configuration),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ export class PluginsMetadata extends Collection {
|
|||||||
|
|
||||||
return /* await */ this.save({
|
return /* await */ this.save({
|
||||||
...pluginMetadata.properties,
|
...pluginMetadata.properties,
|
||||||
...data
|
...data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Collection from '../collection/redis'
|
import Collection from '../collection/redis'
|
||||||
import Model from '../model'
|
import Model from '../model'
|
||||||
import {
|
import {
|
||||||
forEach
|
forEach,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -18,7 +18,7 @@ export class Remotes extends Collection {
|
|||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
error: ''
|
error: '',
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export class Schedules extends Collection {
|
|||||||
cron,
|
cron,
|
||||||
enabled,
|
enabled,
|
||||||
name,
|
name,
|
||||||
timezone
|
timezone,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import { parseProp } from './utils'
|
|||||||
export default class User extends Model {}
|
export default class User extends Model {}
|
||||||
|
|
||||||
User.prototype.default = {
|
User.prototype.default = {
|
||||||
permission: 'none'
|
permission: 'none',
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -43,8 +43,8 @@ export class Users extends Collection {
|
|||||||
? undefined
|
? undefined
|
||||||
: JSON.stringify(tmp)
|
: JSON.stringify(tmp)
|
||||||
user.preferences = isEmpty(tmp = user.preferences)
|
user.preferences = isEmpty(tmp = user.preferences)
|
||||||
? undefined
|
? undefined
|
||||||
: JSON.stringify(tmp)
|
: JSON.stringify(tmp)
|
||||||
|
|
||||||
return /* await */ this.update(user)
|
return /* await */ this.update(user)
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,14 @@ export default function proxyConsole (ws, vmConsole, sessionId) {
|
|||||||
const socket = connect({
|
const socket = connect({
|
||||||
host: url.host,
|
host: url.host,
|
||||||
port: url.port || 443,
|
port: url.port || 443,
|
||||||
rejectUnauthorized: false
|
rejectUnauthorized: false,
|
||||||
}, () => {
|
}, () => {
|
||||||
// Write headers.
|
// Write headers.
|
||||||
socket.write([
|
socket.write([
|
||||||
`CONNECT ${url.path} HTTP/1.0`,
|
`CONNECT ${url.path} HTTP/1.0`,
|
||||||
`Host: ${url.hostname}`,
|
`Host: ${url.hostname}`,
|
||||||
`Cookie: session_id=${sessionId}`,
|
`Cookie: session_id=${sessionId}`,
|
||||||
'', ''
|
'', '',
|
||||||
].join('\r\n'))
|
].join('\r\n'))
|
||||||
|
|
||||||
const onSend = (error) => {
|
const onSend = (error) => {
|
||||||
|
@ -29,7 +29,7 @@ xo-server-recover-account <user name or email>
|
|||||||
}
|
}
|
||||||
|
|
||||||
const xo = new Xo(await appConf.load('xo-server', {
|
const xo = new Xo(await appConf.load('xo-server', {
|
||||||
ignoreUnknownFormats: true
|
ignoreUnknownFormats: true,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const user = await xo.getUserByName(name, true)
|
const user = await xo.getUserByName(name, true)
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
addChecksumToReadStream,
|
addChecksumToReadStream,
|
||||||
getPseudoRandomBytes,
|
getPseudoRandomBytes,
|
||||||
streamToBuffer,
|
streamToBuffer,
|
||||||
validChecksumOfReadStream
|
validChecksumOfReadStream,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
export default class RemoteHandlerAbstract {
|
export default class RemoteHandlerAbstract {
|
||||||
@ -56,14 +56,14 @@ export default class RemoteHandlerAbstract {
|
|||||||
throw new Error('output and input did not match')
|
throw new Error('output and input did not match')
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
success: true
|
success: true,
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
step,
|
step,
|
||||||
file: testFileName,
|
file: testFileName,
|
||||||
error: error.message || String(error)
|
error: error.message || String(error),
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
this.unlink(testFileName)::ignoreErrors()
|
this.unlink(testFileName)::ignoreErrors()
|
||||||
@ -73,7 +73,7 @@ export default class RemoteHandlerAbstract {
|
|||||||
async outputFile (file, data, options) {
|
async outputFile (file, data, options) {
|
||||||
return this._outputFile(file, data, {
|
return this._outputFile(file, data, {
|
||||||
flags: 'wx',
|
flags: 'wx',
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ export default class RemoteHandlerAbstract {
|
|||||||
promise,
|
promise,
|
||||||
this.getSize(file).then(size => {
|
this.getSize(file).then(size => {
|
||||||
stream.length = size
|
stream.length = size
|
||||||
})::ignoreErrors()
|
})::ignoreErrors(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ export default class RemoteHandlerAbstract {
|
|||||||
} = {}) {
|
} = {}) {
|
||||||
const streamP = this._createOutputStream(file, {
|
const streamP = this._createOutputStream(file, {
|
||||||
flags: 'wx',
|
flags: 'wx',
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!checksum) {
|
if (!checksum) {
|
||||||
@ -202,7 +202,7 @@ export default class RemoteHandlerAbstract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async unlink (file, {
|
async unlink (file, {
|
||||||
checksum = true
|
checksum = true,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
if (checksum) {
|
if (checksum) {
|
||||||
this._unlink(`${file}.checksum`)::ignoreErrors()
|
this._unlink(`${file}.checksum`)::ignoreErrors()
|
||||||
|
@ -24,7 +24,7 @@ export default class NfsHandler extends LocalHandler {
|
|||||||
const match = regex.exec(m)
|
const match = regex.exec(m)
|
||||||
mounted[match[3]] = {
|
mounted[match[3]] = {
|
||||||
host: match[1],
|
host: match[1],
|
||||||
share: match[2]
|
share: match[2],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -3,7 +3,7 @@ import Smb2 from '@marsaud/smb2-promise'
|
|||||||
import RemoteHandlerAbstract from './abstract'
|
import RemoteHandlerAbstract from './abstract'
|
||||||
import {
|
import {
|
||||||
noop,
|
noop,
|
||||||
pFinally
|
pFinally,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// Normalize the error code for file not found.
|
// Normalize the error code for file not found.
|
||||||
@ -19,8 +19,8 @@ const normalizeError = error => {
|
|||||||
configurable: true,
|
configurable: true,
|
||||||
readable: true,
|
readable: true,
|
||||||
value: 'ENOENT',
|
value: 'ENOENT',
|
||||||
writable: true
|
writable: true,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
: error
|
: error
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ export default class SmbHandler extends RemoteHandlerAbstract {
|
|||||||
domain: remote.domain,
|
domain: remote.domain,
|
||||||
username: remote.username,
|
username: remote.username,
|
||||||
password: remote.password,
|
password: remote.password,
|
||||||
autoCloseTimeout: 0
|
autoCloseTimeout: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,25 +4,25 @@ export default {
|
|||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'unique identifier for this ACL'
|
description: 'unique identifier for this ACL',
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'permission (or role)'
|
description: 'permission (or role)',
|
||||||
},
|
},
|
||||||
object: {
|
object: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'item (or set)'
|
description: 'item (or set)',
|
||||||
},
|
},
|
||||||
subject: {
|
subject: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'user (or group)'
|
description: 'user (or group)',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'id',
|
'id',
|
||||||
'action',
|
'action',
|
||||||
'object',
|
'object',
|
||||||
'subject'
|
'subject',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -3,41 +3,41 @@ export default {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
type: {
|
type: {
|
||||||
enum: ['call']
|
enum: ['call'],
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'job identifier'
|
description: 'job identifier',
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'human readable name'
|
description: 'human readable name',
|
||||||
},
|
},
|
||||||
userId: {
|
userId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'identifier of the user who have created the job (the permissions of the user are used by the job)'
|
description: 'identifier of the user who have created the job (the permissions of the user are used by the job)',
|
||||||
},
|
},
|
||||||
key: {
|
key: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
// TODO description
|
// TODO description
|
||||||
},
|
},
|
||||||
method: {
|
method: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'called method'
|
description: 'called method',
|
||||||
},
|
},
|
||||||
paramsVector: {
|
paramsVector: {
|
||||||
type: 'object'
|
type: 'object',
|
||||||
},
|
},
|
||||||
timeout: {
|
timeout: {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'number of milliseconds after which the job is considered failed'
|
description: 'number of milliseconds after which the job is considered failed',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'type',
|
'type',
|
||||||
'id',
|
'id',
|
||||||
'userId',
|
'userId',
|
||||||
'key',
|
'key',
|
||||||
'method'
|
'method',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -4,26 +4,26 @@ export default {
|
|||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'unique identifier for this log'
|
description: 'unique identifier for this log',
|
||||||
},
|
},
|
||||||
time: {
|
time: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'timestamp (in milliseconds) of this log'
|
description: 'timestamp (in milliseconds) of this log',
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'human readable (short) description of this log'
|
description: 'human readable (short) description of this log',
|
||||||
},
|
},
|
||||||
namespace: {
|
namespace: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'space to store logs'
|
description: 'space to store logs',
|
||||||
},
|
},
|
||||||
data: {}
|
data: {},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'id',
|
'id',
|
||||||
'time',
|
'time',
|
||||||
'message',
|
'message',
|
||||||
'namespace'
|
'namespace',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -3,31 +3,31 @@ export default {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
event: {
|
event: {
|
||||||
enum: ['jobCall.end']
|
enum: ['jobCall.end'],
|
||||||
},
|
},
|
||||||
runJobId: {
|
runJobId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'instance id of this job'
|
description: 'instance id of this job',
|
||||||
},
|
},
|
||||||
runCallId: {
|
runCallId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'instance id of this call'
|
description: 'instance id of this call',
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'describe one failure, exists if the call has failed'
|
description: 'describe one failure, exists if the call has failed',
|
||||||
},
|
},
|
||||||
returnedValue: {
|
returnedValue: {
|
||||||
description: 'call\'s result, exists if the call is a success'
|
description: 'call\'s result, exists if the call is a success',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'event',
|
'event',
|
||||||
'runJobId',
|
'runJobId',
|
||||||
'runCallId'
|
'runCallId',
|
||||||
],
|
],
|
||||||
oneOf: [
|
oneOf: [
|
||||||
{ required: ['error'] },
|
{ required: ['error'] },
|
||||||
{ required: ['returnedValue'] }
|
{ required: ['returnedValue'] },
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -3,25 +3,25 @@ export default {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
event: {
|
event: {
|
||||||
enum: ['jobCall.start']
|
enum: ['jobCall.start'],
|
||||||
},
|
},
|
||||||
runJobId: {
|
runJobId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'instance id of this job'
|
description: 'instance id of this job',
|
||||||
},
|
},
|
||||||
method: {
|
method: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'method linked to this call'
|
description: 'method linked to this call',
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'params of the called method'
|
description: 'params of the called method',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'event',
|
'event',
|
||||||
'runJobId',
|
'runJobId',
|
||||||
'method',
|
'method',
|
||||||
'params'
|
'params',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,19 @@ export default {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
event: {
|
event: {
|
||||||
enum: ['job.end']
|
enum: ['job.end'],
|
||||||
},
|
},
|
||||||
runJobId: {
|
runJobId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'instance id of this job'
|
description: 'instance id of this job',
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'describe one failure, exists if no call has been made'
|
description: 'describe one failure, exists if no call has been made',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'event',
|
'event',
|
||||||
'runJobId'
|
'runJobId',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -3,24 +3,24 @@ export default {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
event: {
|
event: {
|
||||||
enum: ['job.start']
|
enum: ['job.start'],
|
||||||
},
|
},
|
||||||
userId: {
|
userId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'user who executes this job'
|
description: 'user who executes this job',
|
||||||
},
|
},
|
||||||
jobId: {
|
jobId: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'identifier of this job'
|
description: 'identifier of this job',
|
||||||
},
|
},
|
||||||
key: {
|
key: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'event',
|
'event',
|
||||||
'userId',
|
'userId',
|
||||||
'jobId',
|
'jobId',
|
||||||
'key'
|
'key',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -4,46 +4,46 @@ export default {
|
|||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'unique identifier for this plugin'
|
description: 'unique identifier for this plugin',
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'unique human readable name for this plugin'
|
description: 'unique human readable name for this plugin',
|
||||||
},
|
},
|
||||||
autoload: {
|
autoload: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description: 'whether this plugin is loaded on startup'
|
description: 'whether this plugin is loaded on startup',
|
||||||
},
|
},
|
||||||
loaded: {
|
loaded: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description: 'whether or not this plugin is currently loaded'
|
description: 'whether or not this plugin is currently loaded',
|
||||||
},
|
},
|
||||||
unloadable: {
|
unloadable: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: true,
|
default: true,
|
||||||
description: 'whether or not this plugin can be unloaded'
|
description: 'whether or not this plugin can be unloaded',
|
||||||
},
|
},
|
||||||
configuration: {
|
configuration: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'current configuration of this plugin (not present if none)'
|
description: 'current configuration of this plugin (not present if none)',
|
||||||
},
|
},
|
||||||
configurationSchema: {
|
configurationSchema: {
|
||||||
$ref: 'http://json-schema.org/draft-04/schema#',
|
$ref: 'http://json-schema.org/draft-04/schema#',
|
||||||
description: 'configuration schema for this plugin (not present if not configurable)'
|
description: 'configuration schema for this plugin (not present if not configurable)',
|
||||||
},
|
},
|
||||||
testable: {
|
testable: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description: 'whether or not this plugin can be tested'
|
description: 'whether or not this plugin can be tested',
|
||||||
},
|
},
|
||||||
testSchema: {
|
testSchema: {
|
||||||
$ref: 'http://json-schema.org/draft-04/schema#',
|
$ref: 'http://json-schema.org/draft-04/schema#',
|
||||||
description: 'test schema for this plugin'
|
description: 'test schema for this plugin',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
'autoload',
|
'autoload',
|
||||||
'loaded'
|
'loaded',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
@ -4,22 +4,22 @@ export default {
|
|||||||
properties: {
|
properties: {
|
||||||
id: {
|
id: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'unique identifier for this user'
|
description: 'unique identifier for this user',
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'email address of this user'
|
description: 'email address of this user',
|
||||||
},
|
},
|
||||||
groups: {
|
groups: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: {
|
items: {
|
||||||
type: 'string'
|
type: 'string',
|
||||||
},
|
},
|
||||||
description: 'identifier of groups this user belong to'
|
description: 'identifier of groups this user belong to',
|
||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
enum: ['none', 'read', 'write', 'admin'],
|
enum: ['none', 'read', 'write', 'admin'],
|
||||||
description: 'root permission for this user, none and admin are the only significant ones'
|
description: 'root permission for this user, none and admin are the only significant ones',
|
||||||
},
|
},
|
||||||
preferences: {
|
preferences: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@ -31,20 +31,20 @@ export default {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
key: { type: 'string' },
|
key: { type: 'string' },
|
||||||
title: { type: 'string' }
|
title: { type: 'string' },
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'key',
|
'key',
|
||||||
'title'
|
'title',
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
description: 'various user preferences'
|
description: 'various user preferences',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: [
|
||||||
'id',
|
'id',
|
||||||
'email'
|
'email',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
22
src/utils.js
22
src/utils.js
@ -30,11 +30,11 @@ import {
|
|||||||
fromCallback,
|
fromCallback,
|
||||||
isPromise,
|
isPromise,
|
||||||
promisify,
|
promisify,
|
||||||
reflect as pReflect
|
reflect as pReflect,
|
||||||
} from 'promise-toolbox'
|
} from 'promise-toolbox'
|
||||||
import {
|
import {
|
||||||
createHash,
|
createHash,
|
||||||
randomBytes
|
randomBytes,
|
||||||
} from 'crypto'
|
} from 'crypto'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -111,7 +111,7 @@ export const diffItems = (coll1, coll2) => {
|
|||||||
const ALGORITHM_TO_ID = {
|
const ALGORITHM_TO_ID = {
|
||||||
md5: '1',
|
md5: '1',
|
||||||
sha256: '5',
|
sha256: '5',
|
||||||
sha512: '6'
|
sha512: '6',
|
||||||
}
|
}
|
||||||
|
|
||||||
const ID_TO_ALGORITHM = invert(ALGORITHM_TO_ID)
|
const ID_TO_ALGORITHM = invert(ALGORITHM_TO_ID)
|
||||||
@ -258,7 +258,7 @@ export const generateToken = (randomBytes => {
|
|||||||
|
|
||||||
export const formatXml = (function () {
|
export const formatXml = (function () {
|
||||||
const builder = new xml2js.Builder({
|
const builder = new xml2js.Builder({
|
||||||
headless: true
|
headless: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
return (...args) => builder.buildObject(...args)
|
return (...args) => builder.buildObject(...args)
|
||||||
@ -267,7 +267,7 @@ export const formatXml = (function () {
|
|||||||
export const parseXml = (function () {
|
export const parseXml = (function () {
|
||||||
const opts = {
|
const opts = {
|
||||||
mergeAttrs: true,
|
mergeAttrs: true,
|
||||||
explicitArray: false
|
explicitArray: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
return (xml) => {
|
return (xml) => {
|
||||||
@ -315,7 +315,7 @@ export const lightSet = collection => {
|
|||||||
return set
|
return set
|
||||||
},
|
},
|
||||||
has: value => data[value],
|
has: value => data[value],
|
||||||
toArray: () => keys(data)
|
toArray: () => keys(data),
|
||||||
}
|
}
|
||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ export {
|
|||||||
lastly as pFinally,
|
lastly as pFinally,
|
||||||
promisify,
|
promisify,
|
||||||
promisifyAll,
|
promisifyAll,
|
||||||
reflect as pReflect
|
reflect as pReflect,
|
||||||
} from 'promise-toolbox'
|
} from 'promise-toolbox'
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -489,7 +489,7 @@ export const resolveSubpath = (root, path) =>
|
|||||||
|
|
||||||
export const streamToArray = (stream, {
|
export const streamToArray = (stream, {
|
||||||
filter,
|
filter,
|
||||||
mapper
|
mapper,
|
||||||
} = {}) => new Promise((resolve, reject) => {
|
} = {}) => new Promise((resolve, reject) => {
|
||||||
stream = highland(stream).stopOnError(reject)
|
stream = highland(stream).stopOnError(reject)
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@ -526,7 +526,7 @@ export const scheduleFn = (cronTime, fn, timeZone) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
start: true,
|
start: true,
|
||||||
timeZone
|
timeZone,
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -540,7 +540,7 @@ export const scheduleFn = (cronTime, fn, timeZone) => {
|
|||||||
export const serializeError = error => ({
|
export const serializeError = error => ({
|
||||||
message: error.message,
|
message: error.message,
|
||||||
stack: error.stack,
|
stack: error.stack,
|
||||||
...error // Copy enumerable properties.
|
...error, // Copy enumerable properties.
|
||||||
})
|
})
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -598,7 +598,7 @@ export const splitFirst = (string, separator) => {
|
|||||||
const i = string.indexOf(separator)
|
const i = string.indexOf(separator)
|
||||||
return i === -1 ? null : [
|
return i === -1 ? null : [
|
||||||
string.slice(0, i),
|
string.slice(0, i),
|
||||||
string.slice(i + separator.length)
|
string.slice(i + separator.length),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
formatXml,
|
formatXml,
|
||||||
generateToken,
|
generateToken,
|
||||||
parseSize,
|
parseSize,
|
||||||
pSettle
|
pSettle,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -57,7 +57,7 @@ describe('diffItems', () => {
|
|||||||
['baz', 'foo']
|
['baz', 'foo']
|
||||||
)).toEqual([
|
)).toEqual([
|
||||||
['bar'],
|
['bar'],
|
||||||
['baz']
|
['baz'],
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -109,9 +109,9 @@ describe('formatXml()', function () {
|
|||||||
foo: {
|
foo: {
|
||||||
bar: [
|
bar: [
|
||||||
{$: {baz: 'plop'}},
|
{$: {baz: 'plop'}},
|
||||||
{$: {baz: 'plip'}}
|
{$: {baz: 'plip'}},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})).toBe(`<foo>
|
})).toBe(`<foo>
|
||||||
<bar baz="plop"/>
|
<bar baz="plop"/>
|
||||||
<bar baz="plip"/>
|
<bar baz="plip"/>
|
||||||
@ -157,11 +157,11 @@ describe('pSettle()', () => {
|
|||||||
const [
|
const [
|
||||||
status1,
|
status1,
|
||||||
status2,
|
status2,
|
||||||
status3
|
status3,
|
||||||
] = await pSettle([
|
] = await pSettle([
|
||||||
Promise.resolve(42),
|
Promise.resolve(42),
|
||||||
Math.PI,
|
Math.PI,
|
||||||
Promise.reject(rejection)
|
Promise.reject(rejection),
|
||||||
])
|
])
|
||||||
|
|
||||||
expect(status1.isRejected()).toBe(false)
|
expect(status1.isRejected()).toBe(false)
|
||||||
@ -187,11 +187,11 @@ describe('pSettle()', () => {
|
|||||||
const {
|
const {
|
||||||
a: status1,
|
a: status1,
|
||||||
b: status2,
|
b: status2,
|
||||||
c: status3
|
c: status3,
|
||||||
} = await pSettle({
|
} = await pSettle({
|
||||||
a: Promise.resolve(42),
|
a: Promise.resolve(42),
|
||||||
b: Math.PI,
|
b: Math.PI,
|
||||||
c: Promise.reject(rejection)
|
c: Promise.reject(rejection),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(status1.isRejected()).toBe(false)
|
expect(status1.isRejected()).toBe(false)
|
||||||
|
@ -8,7 +8,7 @@ import isEqual from 'lodash/isEqual'
|
|||||||
import constantStream from './constant-stream'
|
import constantStream from './constant-stream'
|
||||||
import {
|
import {
|
||||||
noop,
|
noop,
|
||||||
streamToBuffer
|
streamToBuffer,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
const VHD_UTIL_DEBUG = 0
|
const VHD_UTIL_DEBUG = 0
|
||||||
@ -57,7 +57,7 @@ const fuFooter = fu.struct([
|
|||||||
fu.uint32('fileFormatVersion'), // 12
|
fu.uint32('fileFormatVersion'), // 12
|
||||||
fu.struct('dataOffset', [
|
fu.struct('dataOffset', [
|
||||||
fu.uint32('high'), // 16
|
fu.uint32('high'), // 16
|
||||||
fu.uint32('low') // 20
|
fu.uint32('low'), // 20
|
||||||
]),
|
]),
|
||||||
fu.uint32('timestamp'), // 24
|
fu.uint32('timestamp'), // 24
|
||||||
fu.char('creatorApplication', 4), // 28
|
fu.char('creatorApplication', 4), // 28
|
||||||
@ -65,34 +65,34 @@ const fuFooter = fu.struct([
|
|||||||
fu.uint32('creatorHostOs'), // 36
|
fu.uint32('creatorHostOs'), // 36
|
||||||
fu.struct('originalSize', [ // At the creation, current size of the hard disk.
|
fu.struct('originalSize', [ // At the creation, current size of the hard disk.
|
||||||
fu.uint32('high'), // 40
|
fu.uint32('high'), // 40
|
||||||
fu.uint32('low') // 44
|
fu.uint32('low'), // 44
|
||||||
]),
|
]),
|
||||||
fu.struct('currentSize', [ // Current size of the virtual disk. At the creation: currentSize = originalSize.
|
fu.struct('currentSize', [ // Current size of the virtual disk. At the creation: currentSize = originalSize.
|
||||||
fu.uint32('high'), // 48
|
fu.uint32('high'), // 48
|
||||||
fu.uint32('low') // 52
|
fu.uint32('low'), // 52
|
||||||
]),
|
]),
|
||||||
fu.struct('diskGeometry', [
|
fu.struct('diskGeometry', [
|
||||||
fu.uint16('cylinders'), // 56
|
fu.uint16('cylinders'), // 56
|
||||||
fu.uint8('heads'), // 58
|
fu.uint8('heads'), // 58
|
||||||
fu.uint8('sectorsPerTrackCylinder') // 59
|
fu.uint8('sectorsPerTrackCylinder'), // 59
|
||||||
]),
|
]),
|
||||||
fu.uint32('diskType'), // 60 Disk type, must be equal to HARD_DISK_TYPE_DYNAMIC/HARD_DISK_TYPE_DIFFERENCING.
|
fu.uint32('diskType'), // 60 Disk type, must be equal to HARD_DISK_TYPE_DYNAMIC/HARD_DISK_TYPE_DIFFERENCING.
|
||||||
fu.uint32('checksum'), // 64
|
fu.uint32('checksum'), // 64
|
||||||
fu.uint8('uuid', 16), // 68
|
fu.uint8('uuid', 16), // 68
|
||||||
fu.char('saved'), // 84
|
fu.char('saved'), // 84
|
||||||
fu.char('hidden'), // 85
|
fu.char('hidden'), // 85
|
||||||
fu.char('reserved', 426) // 86
|
fu.char('reserved', 426), // 86
|
||||||
])
|
])
|
||||||
|
|
||||||
const fuHeader = fu.struct([
|
const fuHeader = fu.struct([
|
||||||
fu.char('cookie', 8),
|
fu.char('cookie', 8),
|
||||||
fu.struct('dataOffset', [
|
fu.struct('dataOffset', [
|
||||||
fu.uint32('high'),
|
fu.uint32('high'),
|
||||||
fu.uint32('low')
|
fu.uint32('low'),
|
||||||
]),
|
]),
|
||||||
fu.struct('tableOffset', [ // Absolute byte offset of the Block Allocation Table.
|
fu.struct('tableOffset', [ // Absolute byte offset of the Block Allocation Table.
|
||||||
fu.uint32('high'),
|
fu.uint32('high'),
|
||||||
fu.uint32('low')
|
fu.uint32('low'),
|
||||||
]),
|
]),
|
||||||
fu.uint32('headerVersion'),
|
fu.uint32('headerVersion'),
|
||||||
fu.uint32('maxTableEntries'), // Max entries in the Block Allocation Table.
|
fu.uint32('maxTableEntries'), // Max entries in the Block Allocation Table.
|
||||||
@ -109,10 +109,10 @@ const fuHeader = fu.struct([
|
|||||||
fu.uint32('reserved'),
|
fu.uint32('reserved'),
|
||||||
fu.struct('platformDataOffset', [ // Absolute byte offset of the locator data.
|
fu.struct('platformDataOffset', [ // Absolute byte offset of the locator data.
|
||||||
fu.uint32('high'),
|
fu.uint32('high'),
|
||||||
fu.uint32('low')
|
fu.uint32('low'),
|
||||||
])
|
]),
|
||||||
], VHD_PARENT_LOCATOR_ENTRIES),
|
], VHD_PARENT_LOCATOR_ENTRIES),
|
||||||
fu.char('reserved2', 256)
|
fu.char('reserved2', 256),
|
||||||
])
|
])
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -191,7 +191,7 @@ class Vhd {
|
|||||||
_readStream (start, n) {
|
_readStream (start, n) {
|
||||||
return this._handler.createReadStream(this._path, {
|
return this._handler.createReadStream(this._path, {
|
||||||
start,
|
start,
|
||||||
end: start + n - 1 // end is inclusive
|
end: start + n - 1, // end is inclusive
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +313,7 @@ class Vhd {
|
|||||||
? { bitmap: buf }
|
? { bitmap: buf }
|
||||||
: {
|
: {
|
||||||
bitmap: buf.slice(0, this.bitmapSize),
|
bitmap: buf.slice(0, this.bitmapSize),
|
||||||
data: buf.slice(this.bitmapSize)
|
data: buf.slice(this.bitmapSize),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -370,7 +370,7 @@ class Vhd {
|
|||||||
// TODO: could probably be merged in remote handlers.
|
// TODO: could probably be merged in remote handlers.
|
||||||
return this._handler.createOutputStream(this._path, {
|
return this._handler.createOutputStream(this._path, {
|
||||||
flags: 'r+',
|
flags: 'r+',
|
||||||
start: offset
|
start: offset,
|
||||||
}).then(
|
}).then(
|
||||||
Buffer.isBuffer(data)
|
Buffer.isBuffer(data)
|
||||||
? stream => new Promise((resolve, reject) => {
|
? stream => new Promise((resolve, reject) => {
|
||||||
@ -413,7 +413,7 @@ class Vhd {
|
|||||||
if (tableOffset + batSize < sectorsToBytes(firstSector)) {
|
if (tableOffset + batSize < sectorsToBytes(firstSector)) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
extendBat(),
|
extendBat(),
|
||||||
this.writeHeader()
|
this.writeHeader(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +429,7 @@ class Vhd {
|
|||||||
|
|
||||||
this._setBatEntry(first, newFirstSector),
|
this._setBatEntry(first, newFirstSector),
|
||||||
this.writeHeader(),
|
this.writeHeader(),
|
||||||
this.writeFooter()
|
this.writeFooter(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,7 +460,7 @@ class Vhd {
|
|||||||
sectorsToBytes(blockAddr)
|
sectorsToBytes(blockAddr)
|
||||||
),
|
),
|
||||||
|
|
||||||
this._setBatEntry(blockId, blockAddr)
|
this._setBatEntry(blockId, blockAddr),
|
||||||
])
|
])
|
||||||
|
|
||||||
return blockAddr
|
return blockAddr
|
||||||
@ -585,7 +585,7 @@ export default async function vhdMerge (
|
|||||||
// Reading footer and header.
|
// Reading footer and header.
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
parentVhd.readHeaderAndFooter(),
|
parentVhd.readHeaderAndFooter(),
|
||||||
childVhd.readHeaderAndFooter()
|
childVhd.readHeaderAndFooter(),
|
||||||
])
|
])
|
||||||
|
|
||||||
assert(childVhd.header.blockSize === parentVhd.header.blockSize)
|
assert(childVhd.header.blockSize === parentVhd.header.blockSize)
|
||||||
@ -611,7 +611,7 @@ export default async function vhdMerge (
|
|||||||
// Read allocation table of child/parent.
|
// Read allocation table of child/parent.
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
parentVhd.readBlockTable(),
|
parentVhd.readBlockTable(),
|
||||||
childVhd.readBlockTable()
|
childVhd.readBlockTable(),
|
||||||
])
|
])
|
||||||
|
|
||||||
await parentVhd.ensureBatSize(childVhd.header.maxTableEntries)
|
await parentVhd.ensureBatSize(childVhd.header.maxTableEntries)
|
||||||
@ -648,7 +648,7 @@ export async function chainVhd (
|
|||||||
const childVhd = new Vhd(childHandler, childPath)
|
const childVhd = new Vhd(childHandler, childPath)
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
parentVhd.readHeaderAndFooter(),
|
parentVhd.readHeaderAndFooter(),
|
||||||
childVhd.readHeaderAndFooter()
|
childVhd.readHeaderAndFooter(),
|
||||||
])
|
])
|
||||||
|
|
||||||
const { header } = childVhd
|
const { header } = childVhd
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
startsWith
|
startsWith,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -10,23 +10,23 @@ import {
|
|||||||
isEmpty,
|
isEmpty,
|
||||||
mapFilter,
|
mapFilter,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
parseXml
|
parseXml,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import {
|
import {
|
||||||
isHostRunning,
|
isHostRunning,
|
||||||
isVmHvm,
|
isVmHvm,
|
||||||
isVmRunning,
|
isVmRunning,
|
||||||
parseDateTime
|
parseDateTime,
|
||||||
} from './xapi'
|
} from './xapi'
|
||||||
import {
|
import {
|
||||||
useUpdateSystem
|
useUpdateSystem,
|
||||||
} from './xapi/utils'
|
} from './xapi/utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
const {
|
const {
|
||||||
defineProperties,
|
defineProperties,
|
||||||
freeze
|
freeze,
|
||||||
} = Object
|
} = Object
|
||||||
|
|
||||||
function link (obj, prop, idField = '$id') {
|
function link (obj, prop, idField = '$id') {
|
||||||
@ -83,8 +83,8 @@ const TRANSFORMS = {
|
|||||||
xosanPackInstallationTime: toTimestamp(obj.other_config.xosan_pack_installation_time),
|
xosanPackInstallationTime: toTimestamp(obj.other_config.xosan_pack_installation_time),
|
||||||
cpus: {
|
cpus: {
|
||||||
cores: cpuInfo && +cpuInfo.cpu_count,
|
cores: cpuInfo && +cpuInfo.cpu_count,
|
||||||
sockets: cpuInfo && +cpuInfo.socket_count
|
sockets: cpuInfo && +cpuInfo.socket_count,
|
||||||
}
|
},
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// - ? networks = networksByPool.items[pool.id] (network.$pool.id)
|
// - ? networks = networksByPool.items[pool.id] (network.$pool.id)
|
||||||
@ -104,11 +104,11 @@ const TRANSFORMS = {
|
|||||||
host (obj) {
|
host (obj) {
|
||||||
const {
|
const {
|
||||||
$metrics: metrics,
|
$metrics: metrics,
|
||||||
other_config: otherConfig
|
other_config: otherConfig,
|
||||||
|
software_version: softwareVersion,
|
||||||
} = obj
|
} = obj
|
||||||
|
|
||||||
const isRunning = isHostRunning(obj)
|
const isRunning = isHostRunning(obj)
|
||||||
const { software_version } = obj
|
|
||||||
let supplementalPacks, patches
|
let supplementalPacks, patches
|
||||||
|
|
||||||
if (useUpdateSystem(obj)) {
|
if (useUpdateSystem(obj)) {
|
||||||
@ -124,7 +124,7 @@ const TRANSFORMS = {
|
|||||||
guidance: update.after_apply_guidance,
|
guidance: update.after_apply_guidance,
|
||||||
hosts: link(update, 'hosts'),
|
hosts: link(update, 'hosts'),
|
||||||
vdi: link(update, 'vdi'),
|
vdi: link(update, 'vdi'),
|
||||||
size: update.installation_size
|
size: update.installation_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startsWith(update.name_label, 'XS')) {
|
if (startsWith(update.name_label, 'XS')) {
|
||||||
@ -143,11 +143,11 @@ const TRANSFORMS = {
|
|||||||
|
|
||||||
address: obj.address,
|
address: obj.address,
|
||||||
bios_strings: obj.bios_strings,
|
bios_strings: obj.bios_strings,
|
||||||
build: obj.software_version.build_number,
|
build: softwareVersion.build_number,
|
||||||
enabled: Boolean(obj.enabled),
|
enabled: Boolean(obj.enabled),
|
||||||
cpus: {
|
cpus: {
|
||||||
cores: cpuInfo && +cpuInfo.cpu_count,
|
cores: cpuInfo && +cpuInfo.cpu_count,
|
||||||
sockets: cpuInfo && +cpuInfo.socket_count
|
sockets: cpuInfo && +cpuInfo.socket_count,
|
||||||
},
|
},
|
||||||
current_operations: obj.current_operations,
|
current_operations: obj.current_operations,
|
||||||
hostname: obj.hostname,
|
hostname: obj.hostname,
|
||||||
@ -164,7 +164,7 @@ const TRANSFORMS = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
usage: total - free,
|
usage: total - free,
|
||||||
size: total
|
size: total,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ const TRANSFORMS = {
|
|||||||
size: 0,
|
size: 0,
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
total: 0
|
total: 0,
|
||||||
}
|
}
|
||||||
})(),
|
})(),
|
||||||
patches: patches || link(obj, 'patches'),
|
patches: patches || link(obj, 'patches'),
|
||||||
@ -183,7 +183,7 @@ const TRANSFORMS = {
|
|||||||
: 'Unknown',
|
: 'Unknown',
|
||||||
startTime: toTimestamp(otherConfig.boot_time),
|
startTime: toTimestamp(otherConfig.boot_time),
|
||||||
supplementalPacks: supplementalPacks ||
|
supplementalPacks: supplementalPacks ||
|
||||||
mapFilter(software_version, (value, key) => {
|
mapFilter(softwareVersion, (value, key) => {
|
||||||
let author, name
|
let author, name
|
||||||
if (([ author, name ] = key.split(':')).length === 2) {
|
if (([ author, name ] = key.split(':')).length === 2) {
|
||||||
const [ description, version ] = value.split(', ')
|
const [ description, version ] = value.split(', ')
|
||||||
@ -191,14 +191,14 @@ const TRANSFORMS = {
|
|||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
author,
|
author,
|
||||||
version: version.split(' ')[1]
|
version: version.split(' ')[1],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
agentStartTime: toTimestamp(otherConfig.agent_start_time),
|
agentStartTime: toTimestamp(otherConfig.agent_start_time),
|
||||||
rebootRequired: !isEmpty(obj.updates_requiring_reboot),
|
rebootRequired: !isEmpty(obj.updates_requiring_reboot),
|
||||||
tags: obj.tags,
|
tags: obj.tags,
|
||||||
version: obj.software_version.product_version,
|
version: softwareVersion.product_version,
|
||||||
|
|
||||||
// TODO: dedupe.
|
// TODO: dedupe.
|
||||||
PIFs: link(obj, 'PIFs'),
|
PIFs: link(obj, 'PIFs'),
|
||||||
@ -208,7 +208,7 @@ const TRANSFORMS = {
|
|||||||
PGPUs: link(obj, 'PGPUs'),
|
PGPUs: link(obj, 'PGPUs'),
|
||||||
$PGPUs: link(obj, 'PGPUs'),
|
$PGPUs: link(obj, 'PGPUs'),
|
||||||
|
|
||||||
$PBDs: link(obj, 'PBDs')
|
$PBDs: link(obj, 'PBDs'),
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - controller = vmControllersByContainer.items[host.id]
|
// - controller = vmControllersByContainer.items[host.id]
|
||||||
@ -226,7 +226,7 @@ const TRANSFORMS = {
|
|||||||
const {
|
const {
|
||||||
$guest_metrics: guestMetrics,
|
$guest_metrics: guestMetrics,
|
||||||
$metrics: metrics,
|
$metrics: metrics,
|
||||||
other_config: otherConfig
|
other_config: otherConfig,
|
||||||
} = obj
|
} = obj
|
||||||
|
|
||||||
const isHvm = isVmHvm(obj)
|
const isHvm = isVmHvm(obj)
|
||||||
@ -276,7 +276,7 @@ const TRANSFORMS = {
|
|||||||
isRunning && metrics && xenTools
|
isRunning && metrics && xenTools
|
||||||
? +metrics.VCPUs_number
|
? +metrics.VCPUs_number
|
||||||
: +obj.VCPUs_at_startup
|
: +obj.VCPUs_at_startup
|
||||||
)
|
),
|
||||||
},
|
},
|
||||||
current_operations: obj.current_operations,
|
current_operations: obj.current_operations,
|
||||||
docker: (function () {
|
docker: (function () {
|
||||||
@ -287,14 +287,14 @@ const TRANSFORMS = {
|
|||||||
|
|
||||||
if (monitor === 'False') {
|
if (monitor === 'False') {
|
||||||
return {
|
return {
|
||||||
enabled: false
|
enabled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
docker_ps: process,
|
docker_ps: process,
|
||||||
docker_info: info,
|
docker_info: info,
|
||||||
docker_version: version
|
docker_version: version,
|
||||||
} = otherConfig
|
} = otherConfig
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -302,7 +302,7 @@ const TRANSFORMS = {
|
|||||||
info: info && parseXml(info).docker_info,
|
info: info && parseXml(info).docker_info,
|
||||||
containers: ensureArray(process && parseXml(process).docker_ps.item),
|
containers: ensureArray(process && parseXml(process).docker_ps.item),
|
||||||
process: process && parseXml(process).docker_ps, // deprecated (only used in v4)
|
process: process && parseXml(process).docker_ps, // deprecated (only used in v4)
|
||||||
version: version && parseXml(version).docker_version
|
version: version && parseXml(version).docker_version,
|
||||||
}
|
}
|
||||||
})(),
|
})(),
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ const TRANSFORMS = {
|
|||||||
|
|
||||||
const memory = {
|
const memory = {
|
||||||
dynamic: [ dynamicMin, dynamicMax ],
|
dynamic: [ dynamicMin, dynamicMax ],
|
||||||
static: [ staticMin, staticMax ]
|
static: [ staticMin, staticMax ],
|
||||||
}
|
}
|
||||||
|
|
||||||
const gmMemory = guestMetrics && guestMetrics.memory
|
const gmMemory = guestMetrics && guestMetrics.memory
|
||||||
@ -365,13 +365,13 @@ const TRANSFORMS = {
|
|||||||
|
|
||||||
// TODO: dedupe
|
// TODO: dedupe
|
||||||
VGPUs: link(obj, 'VGPUs'),
|
VGPUs: link(obj, 'VGPUs'),
|
||||||
$VGPUs: link(obj, 'VGPUs')
|
$VGPUs: link(obj, 'VGPUs'),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHvm) {
|
if (isHvm) {
|
||||||
({
|
({
|
||||||
vga: vm.vga = 'cirrus',
|
vga: vm.vga = 'cirrus',
|
||||||
videoram: vm.videoram = 4
|
videoram: vm.videoram = 4,
|
||||||
} = obj.platform)
|
} = obj.platform)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,7 +418,7 @@ const TRANSFORMS = {
|
|||||||
|
|
||||||
return methods ? methods.split(',') : []
|
return methods ? methods.split(',') : []
|
||||||
})(),
|
})(),
|
||||||
install_repository: otherConfig['install-repository']
|
install_repository: otherConfig['install-repository'],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +462,7 @@ const TRANSFORMS = {
|
|||||||
? link(obj, 'pool')
|
? link(obj, 'pool')
|
||||||
: link(obj.$PBDs[0], 'host')
|
: link(obj.$PBDs[0], 'host')
|
||||||
),
|
),
|
||||||
$PBDs: link(obj, 'PBDs')
|
$PBDs: link(obj, 'PBDs'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -475,7 +475,7 @@ const TRANSFORMS = {
|
|||||||
attached: Boolean(obj.currently_attached),
|
attached: Boolean(obj.currently_attached),
|
||||||
host: link(obj, 'host'),
|
host: link(obj, 'host'),
|
||||||
SR: link(obj, 'SR'),
|
SR: link(obj, 'SR'),
|
||||||
device_config: obj.device_config
|
device_config: obj.device_config,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -506,7 +506,7 @@ const TRANSFORMS = {
|
|||||||
physical: Boolean(obj.physical),
|
physical: Boolean(obj.physical),
|
||||||
vlan: +obj.VLAN,
|
vlan: +obj.VLAN,
|
||||||
$host: link(obj, 'host'),
|
$host: link(obj, 'host'),
|
||||||
$network: link(obj, 'network')
|
$network: link(obj, 'network'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ const TRANSFORMS = {
|
|||||||
usage: +obj.physical_utilisation,
|
usage: +obj.physical_utilisation,
|
||||||
|
|
||||||
$SR: link(obj, 'SR'),
|
$SR: link(obj, 'SR'),
|
||||||
$VBDs: link(obj, 'VBDs')
|
$VBDs: link(obj, 'VBDs'),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj.is_a_snapshot) {
|
if (obj.is_a_snapshot) {
|
||||||
@ -553,7 +553,7 @@ const TRANSFORMS = {
|
|||||||
position: obj.userdevice,
|
position: obj.userdevice,
|
||||||
read_only: obj.mode === 'RO',
|
read_only: obj.mode === 'RO',
|
||||||
VDI: link(obj, 'VDI'),
|
VDI: link(obj, 'VDI'),
|
||||||
VM: link(obj, 'VM')
|
VM: link(obj, 'VM'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -571,7 +571,7 @@ const TRANSFORMS = {
|
|||||||
MTU: +obj.MTU,
|
MTU: +obj.MTU,
|
||||||
|
|
||||||
$network: link(obj, 'network'),
|
$network: link(obj, 'network'),
|
||||||
$VM: link(obj, 'VM')
|
$VM: link(obj, 'VM'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -587,7 +587,7 @@ const TRANSFORMS = {
|
|||||||
other_config: obj.other_config,
|
other_config: obj.other_config,
|
||||||
tags: obj.tags,
|
tags: obj.tags,
|
||||||
PIFs: link(obj, 'PIFs'),
|
PIFs: link(obj, 'PIFs'),
|
||||||
VIFs: link(obj, 'VIFs')
|
VIFs: link(obj, 'VIFs'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -599,7 +599,7 @@ const TRANSFORMS = {
|
|||||||
name: obj.name,
|
name: obj.name,
|
||||||
time: toTimestamp(obj.timestamp),
|
time: toTimestamp(obj.timestamp),
|
||||||
|
|
||||||
$object: obj.obj_uuid // Special link as it is already an UUID.
|
$object: obj.obj_uuid, // Special link as it is already an UUID.
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -616,7 +616,7 @@ const TRANSFORMS = {
|
|||||||
result: obj.result,
|
result: obj.result,
|
||||||
status: obj.status,
|
status: obj.status,
|
||||||
|
|
||||||
$host: link(obj, 'resident_on')
|
$host: link(obj, 'resident_on'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -628,7 +628,7 @@ const TRANSFORMS = {
|
|||||||
time: toTimestamp(obj.timestamp_applied),
|
time: toTimestamp(obj.timestamp_applied),
|
||||||
pool_patch: link(obj, 'pool_patch', '$ref'),
|
pool_patch: link(obj, 'pool_patch', '$ref'),
|
||||||
|
|
||||||
$host: link(obj, 'host')
|
$host: link(obj, 'host'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -649,7 +649,7 @@ const TRANSFORMS = {
|
|||||||
// version: obj.version,
|
// version: obj.version,
|
||||||
|
|
||||||
// TODO: host.[$]pool_patches ←→ pool.[$]host_patches
|
// TODO: host.[$]pool_patches ←→ pool.[$]host_patches
|
||||||
$host_patches: link(obj, 'host_patches')
|
$host_patches: link(obj, 'host_patches'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -663,7 +663,7 @@ const TRANSFORMS = {
|
|||||||
device_name: obj.device_name,
|
device_name: obj.device_name,
|
||||||
pci_id: obj.pci_id,
|
pci_id: obj.pci_id,
|
||||||
|
|
||||||
$host: link(obj, 'host')
|
$host: link(obj, 'host'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -685,7 +685,7 @@ const TRANSFORMS = {
|
|||||||
host: link(obj, 'host'),
|
host: link(obj, 'host'),
|
||||||
$host: link(obj, 'host'),
|
$host: link(obj, 'host'),
|
||||||
vgpus: link(obj, 'resident_VGPUs'),
|
vgpus: link(obj, 'resident_VGPUs'),
|
||||||
$vgpus: link(obj, 'resident_VGPUs')
|
$vgpus: link(obj, 'resident_VGPUs'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -701,7 +701,7 @@ const TRANSFORMS = {
|
|||||||
otherConfig: obj.other_config,
|
otherConfig: obj.other_config,
|
||||||
resident_on: link(obj, 'resident_on'),
|
resident_on: link(obj, 'resident_on'),
|
||||||
vgpuType: link(obj, '$type'),
|
vgpuType: link(obj, '$type'),
|
||||||
vm: link(obj, 'VM')
|
vm: link(obj, 'VM'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -719,7 +719,7 @@ const TRANSFORMS = {
|
|||||||
otherConfig: obj.other_config,
|
otherConfig: obj.other_config,
|
||||||
pgpus: link(obj, 'PGPUs'),
|
pgpus: link(obj, 'PGPUs'),
|
||||||
supportedVgpuTypes: link(obj, 'supported_VGPU_types'),
|
supportedVgpuTypes: link(obj, 'supported_VGPU_types'),
|
||||||
vgpus: link(obj, 'VGPUs')
|
vgpus: link(obj, 'VGPUs'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -738,9 +738,9 @@ const TRANSFORMS = {
|
|||||||
modelName: obj.model_name,
|
modelName: obj.model_name,
|
||||||
pgpus: link(obj, 'enabled_on_PGPUs'),
|
pgpus: link(obj, 'enabled_on_PGPUs'),
|
||||||
vendorName: obj.vendor_name,
|
vendorName: obj.vendor_name,
|
||||||
vgpus: link(obj, 'VGPUs')
|
vgpus: link(obj, 'VGPUs'),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -774,11 +774,11 @@ export default xapiObj => {
|
|||||||
// Internal properties.
|
// Internal properties.
|
||||||
defineProperties(xoObj, {
|
defineProperties(xoObj, {
|
||||||
_xapiId: {
|
_xapiId: {
|
||||||
value: xapiObj.$id
|
value: xapiObj.$id,
|
||||||
},
|
},
|
||||||
_xapiRef: {
|
_xapiRef: {
|
||||||
value: xapiObj.$ref
|
value: xapiObj.$ref,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Freezes and returns the new object.
|
// Freezes and returns the new object.
|
||||||
|
@ -14,14 +14,14 @@ const RRD_STEP_FROM_STRING = {
|
|||||||
'seconds': RRD_STEP_SECONDS,
|
'seconds': RRD_STEP_SECONDS,
|
||||||
'minutes': RRD_STEP_MINUTES,
|
'minutes': RRD_STEP_MINUTES,
|
||||||
'hours': RRD_STEP_HOURS,
|
'hours': RRD_STEP_HOURS,
|
||||||
'days': RRD_STEP_DAYS
|
'days': RRD_STEP_DAYS,
|
||||||
}
|
}
|
||||||
|
|
||||||
const RRD_POINTS_PER_STEP = {
|
const RRD_POINTS_PER_STEP = {
|
||||||
[RRD_STEP_SECONDS]: 120,
|
[RRD_STEP_SECONDS]: 120,
|
||||||
[RRD_STEP_MINUTES]: 120,
|
[RRD_STEP_MINUTES]: 120,
|
||||||
[RRD_STEP_HOURS]: 168,
|
[RRD_STEP_HOURS]: 168,
|
||||||
[RRD_STEP_DAYS]: 366
|
[RRD_STEP_DAYS]: 366,
|
||||||
}
|
}
|
||||||
|
|
||||||
export class XapiStatsError extends BaseError {}
|
export class XapiStatsError extends BaseError {}
|
||||||
@ -61,12 +61,12 @@ function getNewHostStats () {
|
|||||||
cpus: [],
|
cpus: [],
|
||||||
pifs: {
|
pifs: {
|
||||||
rx: [],
|
rx: [],
|
||||||
tx: []
|
tx: [],
|
||||||
},
|
},
|
||||||
load: [],
|
load: [],
|
||||||
memory: [],
|
memory: [],
|
||||||
memoryFree: [],
|
memoryFree: [],
|
||||||
memoryUsed: []
|
memoryUsed: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,15 +75,15 @@ function getNewVmStats () {
|
|||||||
cpus: [],
|
cpus: [],
|
||||||
vifs: {
|
vifs: {
|
||||||
rx: [],
|
rx: [],
|
||||||
tx: []
|
tx: [],
|
||||||
},
|
},
|
||||||
xvds: {
|
xvds: {
|
||||||
r: {},
|
r: {},
|
||||||
w: {}
|
w: {},
|
||||||
},
|
},
|
||||||
memory: [],
|
memory: [],
|
||||||
memoryFree: [],
|
memoryFree: [],
|
||||||
memoryUsed: []
|
memoryUsed: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,11 +96,11 @@ function getNewHostLegends () {
|
|||||||
cpus: [],
|
cpus: [],
|
||||||
pifs: {
|
pifs: {
|
||||||
rx: [],
|
rx: [],
|
||||||
tx: []
|
tx: [],
|
||||||
},
|
},
|
||||||
load: null,
|
load: null,
|
||||||
memoryFree: null,
|
memoryFree: null,
|
||||||
memory: null
|
memory: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,14 +109,14 @@ function getNewVmLegends () {
|
|||||||
cpus: [],
|
cpus: [],
|
||||||
vifs: {
|
vifs: {
|
||||||
rx: [],
|
rx: [],
|
||||||
tx: []
|
tx: [],
|
||||||
},
|
},
|
||||||
xvds: {
|
xvds: {
|
||||||
r: [],
|
r: [],
|
||||||
w: []
|
w: [],
|
||||||
},
|
},
|
||||||
memoryFree: null,
|
memoryFree: null,
|
||||||
memory: null
|
memory: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,8 +391,8 @@ export default class XapiStats {
|
|||||||
cf: 'AVERAGE',
|
cf: 'AVERAGE',
|
||||||
host: 'true',
|
host: 'true',
|
||||||
json: 'true',
|
json: 'true',
|
||||||
start: timestamp
|
start: timestamp,
|
||||||
}
|
},
|
||||||
}).then(response => response.readAll().then(JSON5.parse))
|
}).then(response => response.readAll().then(JSON5.parse))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +412,7 @@ export default class XapiStats {
|
|||||||
if (vmId === undefined) {
|
if (vmId === undefined) {
|
||||||
return {
|
return {
|
||||||
interval: step,
|
interval: step,
|
||||||
...hostStats
|
...hostStats,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,14 +422,14 @@ export default class XapiStats {
|
|||||||
return {
|
return {
|
||||||
interval: step,
|
interval: step,
|
||||||
endTimestamp: hostStats.endTimestamp,
|
endTimestamp: hostStats.endTimestamp,
|
||||||
stats: (vmsStats && vmsStats[vmId]) || getNewVmStats()
|
stats: (vmsStats && vmsStats[vmId]) || getNewVmStats(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getAndUpdatePoints (xapi, host, vmId, granularity) {
|
async _getAndUpdatePoints (xapi, host, vmId, granularity) {
|
||||||
// Get granularity to use
|
// Get granularity to use
|
||||||
const step = (granularity === undefined || granularity === 0)
|
const step = (granularity === undefined || granularity === 0)
|
||||||
? RRD_STEP_SECONDS : RRD_STEP_FROM_STRING[granularity]
|
? RRD_STEP_SECONDS : RRD_STEP_FROM_STRING[granularity]
|
||||||
|
|
||||||
if (step === undefined) {
|
if (step === undefined) {
|
||||||
throw new FaultyGranularity(`Unknown granularity: '${granularity}'. Use 'seconds', 'minutes', 'hours', or 'days'.`)
|
throw new FaultyGranularity(`Unknown granularity: '${granularity}'. Use 'seconds', 'minutes', 'hours', or 'days'.`)
|
||||||
@ -475,7 +475,7 @@ export default class XapiStats {
|
|||||||
if (this._hosts[hostname][step] === undefined) {
|
if (this._hosts[hostname][step] === undefined) {
|
||||||
this._hosts[hostname][step] = {
|
this._hosts[hostname][step] = {
|
||||||
endTimestamp: 0,
|
endTimestamp: 0,
|
||||||
localTimestamp: 0
|
localTimestamp: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,13 +17,13 @@ import {
|
|||||||
isEmpty,
|
isEmpty,
|
||||||
omit,
|
omit,
|
||||||
startsWith,
|
startsWith,
|
||||||
uniq
|
uniq,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
import {
|
import {
|
||||||
Xapi as XapiBase
|
Xapi as XapiBase,
|
||||||
} from 'xen-api'
|
} from 'xen-api'
|
||||||
import {
|
import {
|
||||||
satisfies as versionSatisfies
|
satisfies as versionSatisfies,
|
||||||
} from 'semver'
|
} from 'semver'
|
||||||
|
|
||||||
import createSizeStream from '../size-stream'
|
import createSizeStream from '../size-stream'
|
||||||
@ -42,10 +42,10 @@ import {
|
|||||||
pDelay,
|
pDelay,
|
||||||
pFinally,
|
pFinally,
|
||||||
promisifyAll,
|
promisifyAll,
|
||||||
pSettle
|
pSettle,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
import mixins from './mixins'
|
import mixins from './mixins' // eslint-disable-line node/no-missing-import
|
||||||
import OTHER_CONFIG_TEMPLATE from './other-config-template'
|
import OTHER_CONFIG_TEMPLATE from './other-config-template'
|
||||||
import {
|
import {
|
||||||
asBoolean,
|
asBoolean,
|
||||||
@ -60,7 +60,7 @@ import {
|
|||||||
isVmRunning,
|
isVmRunning,
|
||||||
NULL_REF,
|
NULL_REF,
|
||||||
optional,
|
optional,
|
||||||
prepareXapiParam
|
prepareXapiParam,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -104,7 +104,7 @@ export default class Xapi extends XapiBase {
|
|||||||
forEach(objects, object => {
|
forEach(objects, object => {
|
||||||
const {
|
const {
|
||||||
$id: id,
|
$id: id,
|
||||||
$ref: ref
|
$ref: ref,
|
||||||
} = object
|
} = object
|
||||||
|
|
||||||
// Run generic watchers.
|
// Run generic watchers.
|
||||||
@ -131,7 +131,7 @@ export default class Xapi extends XapiBase {
|
|||||||
const fn = super.call
|
const fn = super.call
|
||||||
|
|
||||||
const loop = () => fn.apply(this, args)::pCatch({
|
const loop = () => fn.apply(this, args)::pCatch({
|
||||||
code: 'TOO_MANY_PENDING_TASKS'
|
code: 'TOO_MANY_PENDING_TASKS',
|
||||||
}, () => pDelay(5e3).then(loop))
|
}, () => pDelay(5e3).then(loop))
|
||||||
|
|
||||||
return loop()
|
return loop()
|
||||||
@ -182,7 +182,7 @@ export default class Xapi extends XapiBase {
|
|||||||
// Register the watcher.
|
// Register the watcher.
|
||||||
watcher = this._objectWatchers[predicate] = {
|
watcher = this._objectWatchers[predicate] = {
|
||||||
promise,
|
promise,
|
||||||
resolve
|
resolve,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ export default class Xapi extends XapiBase {
|
|||||||
_setObjectProperties (object, props) {
|
_setObjectProperties (object, props) {
|
||||||
const {
|
const {
|
||||||
$ref: ref,
|
$ref: ref,
|
||||||
$type: type
|
$type: type,
|
||||||
} = object
|
} = object
|
||||||
|
|
||||||
const namespace = getNamespaceForType(type)
|
const namespace = getNamespaceForType(type)
|
||||||
@ -243,7 +243,7 @@ export default class Xapi extends XapiBase {
|
|||||||
async _updateObjectMapProperty (object, prop, values) {
|
async _updateObjectMapProperty (object, prop, values) {
|
||||||
const {
|
const {
|
||||||
$ref: ref,
|
$ref: ref,
|
||||||
$type: type
|
$type: type,
|
||||||
} = object
|
} = object
|
||||||
|
|
||||||
prop = camelToSnakeCase(prop)
|
prop = camelToSnakeCase(prop)
|
||||||
@ -266,46 +266,46 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
async setHostProperties (id, {
|
async setHostProperties (id, {
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription
|
nameDescription,
|
||||||
}) {
|
}) {
|
||||||
await this._setObjectProperties(this.getObject(id), {
|
await this._setObjectProperties(this.getObject(id), {
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription
|
nameDescription,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async setPoolProperties ({
|
async setPoolProperties ({
|
||||||
autoPoweron,
|
autoPoweron,
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription
|
nameDescription,
|
||||||
}) {
|
}) {
|
||||||
const { pool } = this
|
const { pool } = this
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._setObjectProperties(pool, {
|
this._setObjectProperties(pool, {
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription
|
nameDescription,
|
||||||
}),
|
}),
|
||||||
autoPoweron != null && this._updateObjectMapProperty(pool, 'other_config', {
|
autoPoweron != null && this._updateObjectMapProperty(pool, 'other_config', {
|
||||||
autoPoweron: autoPoweron ? 'true' : null
|
autoPoweron: autoPoweron ? 'true' : null,
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSrProperties (id, {
|
async setSrProperties (id, {
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription
|
nameDescription,
|
||||||
}) {
|
}) {
|
||||||
await this._setObjectProperties(this.getObject(id), {
|
await this._setObjectProperties(this.getObject(id), {
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription
|
nameDescription,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async setNetworkProperties (id, {
|
async setNetworkProperties (id, {
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription,
|
nameDescription,
|
||||||
defaultIsLocked
|
defaultIsLocked,
|
||||||
}) {
|
}) {
|
||||||
let defaultLockingMode
|
let defaultLockingMode
|
||||||
if (defaultIsLocked != null) {
|
if (defaultIsLocked != null) {
|
||||||
@ -314,7 +314,7 @@ export default class Xapi extends XapiBase {
|
|||||||
await this._setObjectProperties(this.getObject(id), {
|
await this._setObjectProperties(this.getObject(id), {
|
||||||
nameLabel,
|
nameLabel,
|
||||||
nameDescription,
|
nameDescription,
|
||||||
defaultLockingMode
|
defaultLockingMode,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ export default class Xapi extends XapiBase {
|
|||||||
async addTag (id, tag) {
|
async addTag (id, tag) {
|
||||||
const {
|
const {
|
||||||
$ref: ref,
|
$ref: ref,
|
||||||
$type: type
|
$type: type,
|
||||||
} = this.getObject(id)
|
} = this.getObject(id)
|
||||||
|
|
||||||
const namespace = getNamespaceForType(type)
|
const namespace = getNamespaceForType(type)
|
||||||
@ -333,7 +333,7 @@ export default class Xapi extends XapiBase {
|
|||||||
async removeTag (id, tag) {
|
async removeTag (id, tag) {
|
||||||
const {
|
const {
|
||||||
$ref: ref,
|
$ref: ref,
|
||||||
$type: type
|
$type: type,
|
||||||
} = this.getObject(id)
|
} = this.getObject(id)
|
||||||
|
|
||||||
const namespace = getNamespaceForType(type)
|
const namespace = getNamespaceForType(type)
|
||||||
@ -344,7 +344,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
async setDefaultSr (srId) {
|
async setDefaultSr (srId) {
|
||||||
this._setObjectProperties(this.pool, {
|
this._setObjectProperties(this.pool, {
|
||||||
default_SR: this.getObject(srId).$ref
|
default_SR: this.getObject(srId).$ref,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +490,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
async cloneVm (vmId, {
|
async cloneVm (vmId, {
|
||||||
nameLabel = undefined,
|
nameLabel = undefined,
|
||||||
fast = true
|
fast = true,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const vm = this.getObject(vmId)
|
const vm = this.getObject(vmId)
|
||||||
|
|
||||||
@ -504,7 +504,7 @@ export default class Xapi extends XapiBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async copyVm (vmId, srId, {
|
async copyVm (vmId, srId, {
|
||||||
nameLabel = undefined
|
nameLabel = undefined,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
return /* await */ this._getOrWaitObject(
|
return /* await */ this._getOrWaitObject(
|
||||||
await this._copyVm(
|
await this._copyVm(
|
||||||
@ -517,19 +517,19 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
async remoteCopyVm (vmId, targetXapi, targetSrId, {
|
async remoteCopyVm (vmId, targetXapi, targetSrId, {
|
||||||
compress = true,
|
compress = true,
|
||||||
nameLabel = undefined
|
nameLabel = undefined,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
// Fall back on local copy if possible.
|
// Fall back on local copy if possible.
|
||||||
if (targetXapi === this) {
|
if (targetXapi === this) {
|
||||||
return {
|
return {
|
||||||
vm: await this.copyVm(vmId, targetSrId, { nameLabel })
|
vm: await this.copyVm(vmId, targetSrId, { nameLabel }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sr = targetXapi.getObject(targetSrId)
|
const sr = targetXapi.getObject(targetSrId)
|
||||||
let stream = await this.exportVm(vmId, {
|
let stream = await this.exportVm(vmId, {
|
||||||
compress,
|
compress,
|
||||||
onlyMetadata: false
|
onlyMetadata: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const sizeStream = createSizeStream()
|
const sizeStream = createSizeStream()
|
||||||
@ -537,7 +537,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
const onVmCreation = nameLabel !== undefined
|
const onVmCreation = nameLabel !== undefined
|
||||||
? vm => targetXapi._setObjectProperties(vm, {
|
? vm => targetXapi._setObjectProperties(vm, {
|
||||||
nameLabel
|
nameLabel,
|
||||||
})
|
})
|
||||||
: null
|
: null
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
size: sizeStream.size,
|
size: sizeStream.size,
|
||||||
vm
|
vm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,7 +600,7 @@ export default class Xapi extends XapiBase {
|
|||||||
VCPUs_max,
|
VCPUs_max,
|
||||||
VCPUs_params,
|
VCPUs_params,
|
||||||
version,
|
version,
|
||||||
xenstore_data
|
xenstore_data,
|
||||||
}) {
|
}) {
|
||||||
debug(`Creating VM ${name_label}`)
|
debug(`Creating VM ${name_label}`)
|
||||||
|
|
||||||
@ -647,7 +647,7 @@ export default class Xapi extends XapiBase {
|
|||||||
start_delay: asInteger(start_delay),
|
start_delay: asInteger(start_delay),
|
||||||
tags,
|
tags,
|
||||||
version: asInteger(version),
|
version: asInteger(version),
|
||||||
xenstore_data
|
xenstore_data,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,7 +699,7 @@ export default class Xapi extends XapiBase {
|
|||||||
: onFailure(vdi)
|
: onFailure(vdi)
|
||||||
}
|
}
|
||||||
return test()
|
return test()
|
||||||
})::ignoreErrors()
|
})::ignoreErrors(),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,7 +724,7 @@ export default class Xapi extends XapiBase {
|
|||||||
// Returns a stream to the exported VM.
|
// Returns a stream to the exported VM.
|
||||||
async exportVm (vmId, {
|
async exportVm (vmId, {
|
||||||
compress = true,
|
compress = true,
|
||||||
onlyMetadata = false
|
onlyMetadata = false,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const vm = this.getObject(vmId)
|
const vm = this.getObject(vmId)
|
||||||
|
|
||||||
@ -740,9 +740,9 @@ export default class Xapi extends XapiBase {
|
|||||||
host,
|
host,
|
||||||
query: {
|
query: {
|
||||||
ref: snapshotRef || vm.$ref,
|
ref: snapshotRef || vm.$ref,
|
||||||
use_compression: compress ? 'true' : 'false'
|
use_compression: compress ? 'true' : 'false',
|
||||||
},
|
},
|
||||||
task: this.createTask('VM export', vm.name_label)
|
task: this.createTask('VM export', vm.name_label),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (snapshotRef !== undefined) {
|
if (snapshotRef !== undefined) {
|
||||||
@ -800,7 +800,7 @@ export default class Xapi extends XapiBase {
|
|||||||
fullVdisRequired = [],
|
fullVdisRequired = [],
|
||||||
|
|
||||||
disableBaseTags = false,
|
disableBaseTags = false,
|
||||||
snapshotNameLabel = undefined
|
snapshotNameLabel = undefined,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
if (!bypassVdiChainsCheck) {
|
if (!bypassVdiChainsCheck) {
|
||||||
this._assertHealthyVdiChains(this.getObject(vmId))
|
this._assertHealthyVdiChains(this.getObject(vmId))
|
||||||
@ -810,7 +810,7 @@ export default class Xapi extends XapiBase {
|
|||||||
$onFailure(() => this._deleteVm(vm))
|
$onFailure(() => this._deleteVm(vm))
|
||||||
if (snapshotNameLabel) {
|
if (snapshotNameLabel) {
|
||||||
this._setObjectProperties(vm, {
|
this._setObjectProperties(vm, {
|
||||||
nameLabel: snapshotNameLabel
|
nameLabel: snapshotNameLabel,
|
||||||
})::ignoreErrors()
|
})::ignoreErrors()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,13 +869,13 @@ export default class Xapi extends XapiBase {
|
|||||||
...vdi,
|
...vdi,
|
||||||
other_config: {
|
other_config: {
|
||||||
...vdi.other_config,
|
...vdi.other_config,
|
||||||
[TAG_BASE_DELTA]: baseVdi.uuid
|
[TAG_BASE_DELTA]: baseVdi.uuid,
|
||||||
},
|
},
|
||||||
$SR$uuid: vdi.$SR.uuid
|
$SR$uuid: vdi.$SR.uuid,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
...vdi,
|
...vdi,
|
||||||
$SR$uuid: vdi.$SR.uuid
|
$SR$uuid: vdi.$SR.uuid,
|
||||||
}
|
}
|
||||||
const stream = streams[`${vdiRef}.vhd`] = this._exportVdi($cancelToken, vdi, baseVdi, VDI_FORMAT_VHD)
|
const stream = streams[`${vdiRef}.vhd`] = this._exportVdi($cancelToken, vdi, baseVdi, VDI_FORMAT_VHD)
|
||||||
$onFailure(stream.cancel)
|
$onFailure(stream.cancel)
|
||||||
@ -885,7 +885,7 @@ export default class Xapi extends XapiBase {
|
|||||||
forEach(vm.$VIFs, vif => {
|
forEach(vm.$VIFs, vif => {
|
||||||
vifs[vif.$ref] = {
|
vifs[vif.$ref] = {
|
||||||
...vif,
|
...vif,
|
||||||
$network$uuid: vif.$network.uuid
|
$network$uuid: vif.$network.uuid,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -899,12 +899,12 @@ export default class Xapi extends XapiBase {
|
|||||||
other_config: baseVm && !disableBaseTags
|
other_config: baseVm && !disableBaseTags
|
||||||
? {
|
? {
|
||||||
...vm.other_config,
|
...vm.other_config,
|
||||||
[TAG_BASE_DELTA]: baseVm.uuid
|
[TAG_BASE_DELTA]: baseVm.uuid,
|
||||||
}
|
}
|
||||||
: omit(vm.other_config, TAG_BASE_DELTA)
|
: omit(vm.other_config, TAG_BASE_DELTA),
|
||||||
}
|
},
|
||||||
}, 'streams', {
|
}, 'streams', {
|
||||||
value: await streams::pAll()
|
value: await streams::pAll(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,7 +914,7 @@ export default class Xapi extends XapiBase {
|
|||||||
disableStartAfterImport = true,
|
disableStartAfterImport = true,
|
||||||
mapVdisSrs = {},
|
mapVdisSrs = {},
|
||||||
name_label = delta.vm.name_label,
|
name_label = delta.vm.name_label,
|
||||||
srId = this.pool.default_SR
|
srId = this.pool.default_SR,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const { version } = delta
|
const { version } = delta
|
||||||
|
|
||||||
@ -947,21 +947,21 @@ export default class Xapi extends XapiBase {
|
|||||||
await this._createVmRecord({
|
await this._createVmRecord({
|
||||||
...delta.vm,
|
...delta.vm,
|
||||||
affinity: null,
|
affinity: null,
|
||||||
is_a_template: false
|
is_a_template: false,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
$onFailure(() => this._deleteVm(vm))
|
$onFailure(() => this._deleteVm(vm))
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._setObjectProperties(vm, {
|
this._setObjectProperties(vm, {
|
||||||
name_label: `[Importing…] ${name_label}`
|
name_label: `[Importing…] ${name_label}`,
|
||||||
}),
|
}),
|
||||||
this._updateObjectMapProperty(vm, 'blocked_operations', {
|
this._updateObjectMapProperty(vm, 'blocked_operations', {
|
||||||
start: 'Importing…'
|
start: 'Importing…',
|
||||||
}),
|
}),
|
||||||
this._updateObjectMapProperty(vm, 'other_config', {
|
this._updateObjectMapProperty(vm, 'other_config', {
|
||||||
[TAG_COPY_SRC]: delta.vm.uuid
|
[TAG_COPY_SRC]: delta.vm.uuid,
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
// 2. Delete all VBDs which may have been created by the import.
|
// 2. Delete all VBDs which may have been created by the import.
|
||||||
@ -979,9 +979,9 @@ export default class Xapi extends XapiBase {
|
|||||||
other_config: {
|
other_config: {
|
||||||
...vdi.other_config,
|
...vdi.other_config,
|
||||||
[TAG_BASE_DELTA]: undefined,
|
[TAG_BASE_DELTA]: undefined,
|
||||||
[TAG_COPY_SRC]: vdi.uuid
|
[TAG_COPY_SRC]: vdi.uuid,
|
||||||
},
|
},
|
||||||
sr: mapVdisSrs[vdi.uuid] || srId
|
sr: mapVdisSrs[vdi.uuid] || srId,
|
||||||
})
|
})
|
||||||
$onFailure(() => this._deleteVdi(newVdi))
|
$onFailure(() => this._deleteVdi(newVdi))
|
||||||
|
|
||||||
@ -1002,7 +1002,7 @@ export default class Xapi extends XapiBase {
|
|||||||
$onFailure(() => this._deleteVdi(newVdi))
|
$onFailure(() => this._deleteVdi(newVdi))
|
||||||
|
|
||||||
await this._updateObjectMapProperty(newVdi, 'other_config', {
|
await this._updateObjectMapProperty(newVdi, 'other_config', {
|
||||||
[TAG_COPY_SRC]: vdi.uuid
|
[TAG_COPY_SRC]: vdi.uuid,
|
||||||
})
|
})
|
||||||
|
|
||||||
return newVdi
|
return newVdi
|
||||||
@ -1051,7 +1051,7 @@ export default class Xapi extends XapiBase {
|
|||||||
vif
|
vif
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
if (deleteBase && baseVm) {
|
if (deleteBase && baseVm) {
|
||||||
@ -1060,14 +1060,14 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._setObjectProperties(vm, {
|
this._setObjectProperties(vm, {
|
||||||
name_label
|
name_label,
|
||||||
}),
|
}),
|
||||||
// FIXME: move
|
// FIXME: move
|
||||||
this._updateObjectMapProperty(vm, 'blocked_operations', {
|
this._updateObjectMapProperty(vm, 'blocked_operations', {
|
||||||
start: disableStartAfterImport
|
start: disableStartAfterImport
|
||||||
? 'Do not start this VM, clone it if you want to use it.'
|
? 'Do not start this VM, clone it if you want to use it.'
|
||||||
: null
|
: null,
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
return vm
|
return vm
|
||||||
@ -1077,7 +1077,7 @@ export default class Xapi extends XapiBase {
|
|||||||
migrationNetwork = find(host.$PIFs, pif => pif.management).$network, // TODO: handle not found
|
migrationNetwork = find(host.$PIFs, pif => pif.management).$network, // TODO: handle not found
|
||||||
sr,
|
sr,
|
||||||
mapVdisSrs,
|
mapVdisSrs,
|
||||||
mapVifsNetworks
|
mapVifsNetworks,
|
||||||
}) {
|
}) {
|
||||||
// VDIs/SRs mapping
|
// VDIs/SRs mapping
|
||||||
const vdis = {}
|
const vdis = {}
|
||||||
@ -1094,7 +1094,7 @@ export default class Xapi extends XapiBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VIFs/Networks mapping
|
// VIFs/Networks mapping
|
||||||
let vifsMap = {}
|
const vifsMap = {}
|
||||||
if (vm.$pool !== host.$pool) {
|
if (vm.$pool !== host.$pool) {
|
||||||
const defaultNetworkRef = find(host.$PIFs, pif => pif.management).$network.$ref
|
const defaultNetworkRef = find(host.$PIFs, pif => pif.management).$network.$ref
|
||||||
for (const vif of vm.$VIFs) {
|
for (const vif of vm.$VIFs) {
|
||||||
@ -1119,7 +1119,7 @@ export default class Xapi extends XapiBase {
|
|||||||
vdis,
|
vdis,
|
||||||
vifsMap,
|
vifsMap,
|
||||||
{
|
{
|
||||||
force: 'true'
|
force: 'true',
|
||||||
}
|
}
|
||||||
)::pCatch(
|
)::pCatch(
|
||||||
{ code: 'TOO_MANY_STORAGE_MIGRATES' },
|
{ code: 'TOO_MANY_STORAGE_MIGRATES' },
|
||||||
@ -1202,7 +1202,7 @@ export default class Xapi extends XapiBase {
|
|||||||
async _importVm (stream, sr, onlyMetadata = false, onVmCreation = undefined) {
|
async _importVm (stream, sr, onlyMetadata = false, onVmCreation = undefined) {
|
||||||
const taskRef = await this.createTask('VM import')
|
const taskRef = await this.createTask('VM import')
|
||||||
const query = {
|
const query = {
|
||||||
force: onlyMetadata
|
force: onlyMetadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
let host
|
let host
|
||||||
@ -1223,7 +1223,7 @@ export default class Xapi extends XapiBase {
|
|||||||
{
|
{
|
||||||
host,
|
host,
|
||||||
query,
|
query,
|
||||||
task: taskRef
|
task: taskRef,
|
||||||
}
|
}
|
||||||
).then(extractOpaqueRef)
|
).then(extractOpaqueRef)
|
||||||
|
|
||||||
@ -1245,7 +1245,7 @@ export default class Xapi extends XapiBase {
|
|||||||
memory,
|
memory,
|
||||||
nameLabel,
|
nameLabel,
|
||||||
networks,
|
networks,
|
||||||
nCpus
|
nCpus,
|
||||||
}, sr) {
|
}, sr) {
|
||||||
// 1. Create VM.
|
// 1. Create VM.
|
||||||
const vm = await this._getOrWaitObject(
|
const vm = await this._getOrWaitObject(
|
||||||
@ -1257,14 +1257,14 @@ export default class Xapi extends XapiBase {
|
|||||||
name_description: descriptionLabel,
|
name_description: descriptionLabel,
|
||||||
name_label: nameLabel,
|
name_label: nameLabel,
|
||||||
VCPUs_at_startup: nCpus,
|
VCPUs_at_startup: nCpus,
|
||||||
VCPUs_max: nCpus
|
VCPUs_max: nCpus,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
$onFailure(() => this._deleteVm(vm))
|
$onFailure(() => this._deleteVm(vm))
|
||||||
// Disable start and change the VM name label during import.
|
// Disable start and change the VM name label during import.
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.addForbiddenOperationToVm(vm.$id, 'start', 'OVA import in progress...'),
|
this.addForbiddenOperationToVm(vm.$id, 'start', 'OVA import in progress...'),
|
||||||
this._setObjectProperties(vm, { name_label: `[Importing...] ${nameLabel}` })
|
this._setObjectProperties(vm, { name_label: `[Importing...] ${nameLabel}` }),
|
||||||
])
|
])
|
||||||
|
|
||||||
// 2. Create VDIs & Vifs.
|
// 2. Create VDIs & Vifs.
|
||||||
@ -1275,14 +1275,14 @@ export default class Xapi extends XapiBase {
|
|||||||
const vdi = vdis[disk.path] = await this.createVdi(disk.capacity, {
|
const vdi = vdis[disk.path] = await this.createVdi(disk.capacity, {
|
||||||
name_description: disk.descriptionLabel,
|
name_description: disk.descriptionLabel,
|
||||||
name_label: disk.nameLabel,
|
name_label: disk.nameLabel,
|
||||||
sr: sr.$ref
|
sr: sr.$ref,
|
||||||
})
|
})
|
||||||
$onFailure(() => this._deleteVdi(vdi))
|
$onFailure(() => this._deleteVdi(vdi))
|
||||||
|
|
||||||
return this._createVbd(vm, vdi, { position: disk.position })
|
return this._createVbd(vm, vdi, { position: disk.position })
|
||||||
}).concat(map(networks, (networkId, i) => (
|
}).concat(map(networks, (networkId, i) => (
|
||||||
this._createVif(vm, this.getObject(networkId), {
|
this._createVif(vm, this.getObject(networkId), {
|
||||||
device: vifDevices[i]
|
device: vifDevices[i],
|
||||||
})
|
})
|
||||||
)))
|
)))
|
||||||
)
|
)
|
||||||
@ -1317,7 +1317,7 @@ export default class Xapi extends XapiBase {
|
|||||||
// Enable start and restore the VM name label after import.
|
// Enable start and restore the VM name label after import.
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.removeForbiddenOperationFromVm(vm.$id, 'start'),
|
this.removeForbiddenOperationFromVm(vm.$id, 'start'),
|
||||||
this._setObjectProperties(vm, { name_label: nameLabel })
|
this._setObjectProperties(vm, { name_label: nameLabel }),
|
||||||
])
|
])
|
||||||
return vm
|
return vm
|
||||||
}
|
}
|
||||||
@ -1327,7 +1327,7 @@ export default class Xapi extends XapiBase {
|
|||||||
data,
|
data,
|
||||||
onlyMetadata = false,
|
onlyMetadata = false,
|
||||||
srId,
|
srId,
|
||||||
type = 'xva'
|
type = 'xva',
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const sr = srId && this.getObject(srId)
|
const sr = srId && this.getObject(srId)
|
||||||
|
|
||||||
@ -1350,7 +1350,7 @@ export default class Xapi extends XapiBase {
|
|||||||
sr,
|
sr,
|
||||||
migrationNetworkId,
|
migrationNetworkId,
|
||||||
mapVifsNetworks,
|
mapVifsNetworks,
|
||||||
mapVdisSrs
|
mapVdisSrs,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const vm = this.getObject(vmId)
|
const vm = this.getObject(vmId)
|
||||||
const host = hostXapi.getObject(hostId)
|
const host = hostXapi.getObject(hostId)
|
||||||
@ -1369,7 +1369,7 @@ export default class Xapi extends XapiBase {
|
|||||||
migrationNetwork: migrationNetworkId && hostXapi.getObject(migrationNetworkId),
|
migrationNetwork: migrationNetworkId && hostXapi.getObject(migrationNetworkId),
|
||||||
sr,
|
sr,
|
||||||
mapVdisSrs,
|
mapVdisSrs,
|
||||||
mapVifsNetworks
|
mapVifsNetworks,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -1418,7 +1418,7 @@ export default class Xapi extends XapiBase {
|
|||||||
// to-date object.
|
// to-date object.
|
||||||
const [ , snapshot ] = await Promise.all([
|
const [ , snapshot ] = await Promise.all([
|
||||||
this.call('VM.set_is_a_template', ref, false),
|
this.call('VM.set_is_a_template', ref, false),
|
||||||
this._waitObjectState(ref, snapshot => !snapshot.is_a_template)
|
this._waitObjectState(ref, snapshot => !snapshot.is_a_template),
|
||||||
])
|
])
|
||||||
|
|
||||||
return snapshot
|
return snapshot
|
||||||
@ -1442,7 +1442,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
await this._updateObjectMapProperty(vm, 'blocked_operations', {
|
await this._updateObjectMapProperty(vm, 'blocked_operations', {
|
||||||
start: null
|
start: null,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1473,14 +1473,14 @@ export default class Xapi extends XapiBase {
|
|||||||
const { order } = vm.HVM_boot_params
|
const { order } = vm.HVM_boot_params
|
||||||
|
|
||||||
await this._updateObjectMapProperty(vm, 'HVM_boot_params', {
|
await this._updateObjectMapProperty(vm, 'HVM_boot_params', {
|
||||||
order: 'd'
|
order: 'd',
|
||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this._startVm(vm)
|
await this._startVm(vm)
|
||||||
} finally {
|
} finally {
|
||||||
await this._updateObjectMapProperty(vm, 'HVM_boot_params', {
|
await this._updateObjectMapProperty(vm, 'HVM_boot_params', {
|
||||||
order
|
order,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1502,7 +1502,7 @@ export default class Xapi extends XapiBase {
|
|||||||
forEach(vm.$VBDs, vbd => {
|
forEach(vm.$VBDs, vbd => {
|
||||||
promises.push(
|
promises.push(
|
||||||
this._setObjectProperties(vbd, {
|
this._setObjectProperties(vbd, {
|
||||||
bootable: vbd === cdDrive
|
bootable: vbd === cdDrive,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1511,11 +1511,11 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
promises.push(
|
promises.push(
|
||||||
this._setObjectProperties(vm, {
|
this._setObjectProperties(vm, {
|
||||||
PV_bootloader: 'eliloader'
|
PV_bootloader: 'eliloader',
|
||||||
}),
|
}),
|
||||||
this._updateObjectMapProperty(vm, 'other_config', {
|
this._updateObjectMapProperty(vm, 'other_config', {
|
||||||
'install-distro': template && template.other_config['install-distro'],
|
'install-distro': template && template.other_config['install-distro'],
|
||||||
'install-repository': 'cdrom'
|
'install-repository': 'cdrom',
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1524,7 +1524,7 @@ export default class Xapi extends XapiBase {
|
|||||||
await this._startVm(vm)
|
await this._startVm(vm)
|
||||||
} finally {
|
} finally {
|
||||||
this._setObjectProperties(vm, {
|
this._setObjectProperties(vm, {
|
||||||
PV_bootloader: bootloader
|
PV_bootloader: bootloader,
|
||||||
})::ignoreErrors()
|
})::ignoreErrors()
|
||||||
|
|
||||||
forEach(bootables, ([ vbd, bootable ]) => {
|
forEach(bootables, ([ vbd, bootable ]) => {
|
||||||
@ -1555,7 +1555,7 @@ export default class Xapi extends XapiBase {
|
|||||||
mode = (type === 'Disk') ? 'RW' : 'RO',
|
mode = (type === 'Disk') ? 'RW' : 'RO',
|
||||||
position = userdevice,
|
position = userdevice,
|
||||||
|
|
||||||
readOnly = (mode === 'RO')
|
readOnly = (mode === 'RO'),
|
||||||
} = {}) {
|
} = {}) {
|
||||||
debug(`Creating VBD for VDI ${vdi.name_label} on VM ${vm.name_label}`)
|
debug(`Creating VBD for VDI ${vdi.name_label} on VM ${vm.name_label}`)
|
||||||
|
|
||||||
@ -1593,7 +1593,7 @@ export default class Xapi extends XapiBase {
|
|||||||
unpluggable: Boolean(unpluggable),
|
unpluggable: Boolean(unpluggable),
|
||||||
userdevice: String(position),
|
userdevice: String(position),
|
||||||
VDI: vdi.$ref,
|
VDI: vdi.$ref,
|
||||||
VM: vm.$ref
|
VM: vm.$ref,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isVmRunning(vm)) {
|
if (isVmRunning(vm)) {
|
||||||
@ -1621,7 +1621,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
tags = [],
|
tags = [],
|
||||||
type = 'user',
|
type = 'user',
|
||||||
xenstore_data = undefined
|
xenstore_data = undefined,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
if (sr === NULL_REF) {
|
if (sr === NULL_REF) {
|
||||||
throw new Error('SR required to create VDI')
|
throw new Error('SR required to create VDI')
|
||||||
@ -1642,7 +1642,7 @@ export default class Xapi extends XapiBase {
|
|||||||
tags,
|
tags,
|
||||||
type,
|
type,
|
||||||
virtual_size: String(size),
|
virtual_size: String(size),
|
||||||
SR: sr.$ref
|
SR: sr.$ref,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xenstore_data) {
|
if (xenstore_data) {
|
||||||
@ -1677,7 +1677,7 @@ export default class Xapi extends XapiBase {
|
|||||||
bootable: vbd.bootable,
|
bootable: vbd.bootable,
|
||||||
position: vbd.userdevice,
|
position: vbd.userdevice,
|
||||||
type: vbd.type,
|
type: vbd.type,
|
||||||
readOnly: vbd.mode === 'RO'
|
readOnly: vbd.mode === 'RO',
|
||||||
})
|
})
|
||||||
// Remove the old VDI
|
// Remove the old VDI
|
||||||
await this._deleteVdi(vdi)
|
await this._deleteVdi(vdi)
|
||||||
@ -1722,7 +1722,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
async _insertCdIntoVm (cd, vm, {
|
async _insertCdIntoVm (cd, vm, {
|
||||||
bootable = false,
|
bootable = false,
|
||||||
force = false
|
force = false,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const cdDrive = await this._getVmCdDrive(vm)
|
const cdDrive = await this._getVmCdDrive(vm)
|
||||||
if (cdDrive) {
|
if (cdDrive) {
|
||||||
@ -1745,7 +1745,7 @@ export default class Xapi extends XapiBase {
|
|||||||
} else {
|
} else {
|
||||||
await this._createVbd(vm, cd, {
|
await this._createVbd(vm, cd, {
|
||||||
bootable,
|
bootable,
|
||||||
type: 'CD'
|
type: 'CD',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1845,7 +1845,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
format,
|
format,
|
||||||
vdi: vdi.$ref
|
vdi: vdi.$ref,
|
||||||
}
|
}
|
||||||
if (base) {
|
if (base) {
|
||||||
query.base = base.$ref
|
query.base = base.$ref
|
||||||
@ -1859,14 +1859,14 @@ export default class Xapi extends XapiBase {
|
|||||||
return this.getResource($cancelToken, '/export_raw_vdi/', {
|
return this.getResource($cancelToken, '/export_raw_vdi/', {
|
||||||
host,
|
host,
|
||||||
query,
|
query,
|
||||||
task: this.createTask('VDI Export', vdi.name_label)
|
task: this.createTask('VDI Export', vdi.name_label),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a stream to the exported VDI.
|
// Returns a stream to the exported VDI.
|
||||||
exportVdi (vdiId, {
|
exportVdi (vdiId, {
|
||||||
baseId,
|
baseId,
|
||||||
format
|
format,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
return this._exportVdi(
|
return this._exportVdi(
|
||||||
this.getObject(vdiId),
|
this.getObject(vdiId),
|
||||||
@ -1890,15 +1890,15 @@ export default class Xapi extends XapiBase {
|
|||||||
host: pbd.host,
|
host: pbd.host,
|
||||||
query: {
|
query: {
|
||||||
format,
|
format,
|
||||||
vdi: vdi.$ref
|
vdi: vdi.$ref,
|
||||||
},
|
},
|
||||||
task: this.createTask('VDI Content Import', vdi.name_label)
|
task: this.createTask('VDI Content Import', vdi.name_label),
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
importVdiContent (vdiId, body, {
|
importVdiContent (vdiId, body, {
|
||||||
format
|
format,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
return this._importVdiContent(
|
return this._importVdiContent(
|
||||||
this.getObject(vdiId),
|
this.getObject(vdiId),
|
||||||
@ -1921,7 +1921,7 @@ export default class Xapi extends XapiBase {
|
|||||||
MAC = mac,
|
MAC = mac,
|
||||||
other_config = {},
|
other_config = {},
|
||||||
qos_algorithm_params = {},
|
qos_algorithm_params = {},
|
||||||
qos_algorithm_type = ''
|
qos_algorithm_type = '',
|
||||||
} = {}) {
|
} = {}) {
|
||||||
debug(`Creating VIF for VM ${vm.name_label} on network ${network.name_label}`)
|
debug(`Creating VIF for VM ${vm.name_label} on network ${network.name_label}`)
|
||||||
|
|
||||||
@ -1940,7 +1940,7 @@ export default class Xapi extends XapiBase {
|
|||||||
other_config,
|
other_config,
|
||||||
qos_algorithm_params,
|
qos_algorithm_params,
|
||||||
qos_algorithm_type,
|
qos_algorithm_type,
|
||||||
VM: vm.$ref
|
VM: vm.$ref,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (currently_attached && isVmRunning(vm)) {
|
if (currently_attached && isVmRunning(vm)) {
|
||||||
@ -1965,13 +1965,13 @@ export default class Xapi extends XapiBase {
|
|||||||
description = 'Created with Xen Orchestra',
|
description = 'Created with Xen Orchestra',
|
||||||
pifId,
|
pifId,
|
||||||
mtu,
|
mtu,
|
||||||
vlan
|
vlan,
|
||||||
}) {
|
}) {
|
||||||
const networkRef = await this.call('network.create', {
|
const networkRef = await this.call('network.create', {
|
||||||
name_label: name,
|
name_label: name,
|
||||||
name_description: description,
|
name_description: description,
|
||||||
MTU: asInteger(mtu),
|
MTU: asInteger(mtu),
|
||||||
other_config: {}
|
other_config: {},
|
||||||
})
|
})
|
||||||
$onFailure(() => this.call('network.destroy', networkRef))
|
$onFailure(() => this.call('network.destroy', networkRef))
|
||||||
if (pifId) {
|
if (pifId) {
|
||||||
@ -2059,7 +2059,7 @@ export default class Xapi extends XapiBase {
|
|||||||
|
|
||||||
return /* await */ this.call('host.call_plugin', host.$ref, 'xscontainer', action, {
|
return /* await */ this.call('host.call_plugin', host.$ref, 'xscontainer', action, {
|
||||||
vmuuid: vm.uuid,
|
vmuuid: vm.uuid,
|
||||||
container: containerId
|
container: containerId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2095,8 +2095,8 @@ export default class Xapi extends XapiBase {
|
|||||||
const template = this.getObject(templateId)
|
const template = this.getObject(templateId)
|
||||||
const host = this.pool.$master
|
const host = this.pool.$master
|
||||||
|
|
||||||
let config = await this.call('host.call_plugin', host.$ref, 'xscontainer', 'get_config_drive_default', {
|
const config = await this.call('host.call_plugin', host.$ref, 'xscontainer', 'get_config_drive_default', {
|
||||||
templateuuid: template.uuid
|
templateuuid: template.uuid,
|
||||||
})
|
})
|
||||||
return config.slice(4) // FIXME remove the "True" string on the begining
|
return config.slice(4) // FIXME remove the "True" string on the begining
|
||||||
}
|
}
|
||||||
@ -2110,7 +2110,7 @@ export default class Xapi extends XapiBase {
|
|||||||
await this.call('host.call_plugin', host.$ref, 'xscontainer', 'create_config_drive', {
|
await this.call('host.call_plugin', host.$ref, 'xscontainer', 'create_config_drive', {
|
||||||
vmuuid: vm.uuid,
|
vmuuid: vm.uuid,
|
||||||
sruuid: sr.uuid,
|
sruuid: sr.uuid,
|
||||||
configuration: config
|
configuration: config,
|
||||||
})
|
})
|
||||||
await this.registerDockerContainer(vmId)
|
await this.registerDockerContainer(vmId)
|
||||||
}
|
}
|
||||||
@ -2136,7 +2136,7 @@ export default class Xapi extends XapiBase {
|
|||||||
'openstack/latest/meta_data.json',
|
'openstack/latest/meta_data.json',
|
||||||
'{\n "uuid": "' + vm.uuid + '"\n}\n'
|
'{\n "uuid": "' + vm.uuid + '"\n}\n'
|
||||||
),
|
),
|
||||||
fs.writeFile('openstack/latest/user_data', config)
|
fs.writeFile('openstack/latest/user_data', config),
|
||||||
])
|
])
|
||||||
|
|
||||||
// ignore errors, I (JFT) don't understand why they are emitted
|
// ignore errors, I (JFT) don't understand why they are emitted
|
||||||
@ -2151,7 +2151,7 @@ export default class Xapi extends XapiBase {
|
|||||||
const vdi = await this.createVdi(stream.length, {
|
const vdi = await this.createVdi(stream.length, {
|
||||||
sr: sr.$ref,
|
sr: sr.$ref,
|
||||||
name_label,
|
name_label,
|
||||||
name_description
|
name_description,
|
||||||
})
|
})
|
||||||
$onFailure(() => this._deleteVdi(vdi))
|
$onFailure(() => this._deleteVdi(vdi))
|
||||||
|
|
||||||
|
@ -5,5 +5,5 @@ export default {
|
|||||||
},
|
},
|
||||||
deleteVgpu (vgpu) {
|
deleteVgpu (vgpu) {
|
||||||
return this.call('VGPU.destroy', this.getObject(vgpu).$ref)
|
return this.call('VGPU.destroy', this.getObject(vgpu).$ref)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ export default {
|
|||||||
if (lockingMode !== vif.locking_mode) {
|
if (lockingMode !== vif.locking_mode) {
|
||||||
return this._set('locking_mode', lockingMode)
|
return this._set('locking_mode', lockingMode)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
ipv6Allowed: {
|
ipv6Allowed: {
|
||||||
get: true,
|
get: true,
|
||||||
@ -53,8 +53,8 @@ export default {
|
|||||||
if (lockingMode !== vif.locking_mode) {
|
if (lockingMode !== vif.locking_mode) {
|
||||||
return this._set('locking_mode', lockingMode)
|
return this._set('locking_mode', lockingMode)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@ import {
|
|||||||
forEach,
|
forEach,
|
||||||
mapFilter,
|
mapFilter,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
parseXml
|
parseXml,
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
debug,
|
debug,
|
||||||
extractOpaqueRef,
|
extractOpaqueRef,
|
||||||
useUpdateSystem
|
useUpdateSystem,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -55,7 +55,7 @@ export default {
|
|||||||
requirements: mapToArray(ensureArray(patch.requiredpatches), patch => {
|
requirements: mapToArray(ensureArray(patch.requiredpatches), patch => {
|
||||||
return patch.requiredpatch.uuid
|
return patch.requiredpatch.uuid
|
||||||
}),
|
}),
|
||||||
paid: patch['update-stream'] === 'premium'
|
paid: patch['update-stream'] === 'premium',
|
||||||
// TODO: what does it mean, should we handle it?
|
// TODO: what does it mean, should we handle it?
|
||||||
// version: patch.version,
|
// version: patch.version,
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ export default {
|
|||||||
name: version.name,
|
name: version.name,
|
||||||
id: version.value,
|
id: version.value,
|
||||||
documentationUrl: version.url,
|
documentationUrl: version.url,
|
||||||
patches: resolveVersionPatches(version.patch)
|
patches: resolveVersionPatches(version.patch),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version.latest) {
|
if (version.latest) {
|
||||||
@ -96,7 +96,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
patches,
|
patches,
|
||||||
latestVersion,
|
latestVersion,
|
||||||
versions
|
versions,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ export default {
|
|||||||
stream,
|
stream,
|
||||||
'/pool_patch_upload',
|
'/pool_patch_upload',
|
||||||
{
|
{
|
||||||
task: this.createTask('Patch upload', patchName)
|
task: this.createTask('Patch upload', patchName),
|
||||||
}
|
}
|
||||||
).then(extractOpaqueRef)
|
).then(extractOpaqueRef)
|
||||||
|
|
||||||
@ -303,7 +303,7 @@ export default {
|
|||||||
_installPatchUpdateOnHost: deferrable(async function ($defer, patchUuid, host) {
|
_installPatchUpdateOnHost: deferrable(async function ($defer, patchUuid, host) {
|
||||||
const [ vdi ] = await Promise.all([
|
const [ vdi ] = await Promise.all([
|
||||||
this._getUpdateVdi($defer, patchUuid, host.$id),
|
this._getUpdateVdi($defer, patchUuid, host.$id),
|
||||||
this._ejectToolsIsos(host.$ref)
|
this._ejectToolsIsos(host.$ref),
|
||||||
])
|
])
|
||||||
|
|
||||||
const updateRef = await this.call('pool_update.introduce', vdi.$ref)
|
const updateRef = await this.call('pool_update.introduce', vdi.$ref)
|
||||||
@ -334,7 +334,7 @@ export default {
|
|||||||
async _installPoolPatchOnAllHosts (patchUuid) {
|
async _installPoolPatchOnAllHosts (patchUuid) {
|
||||||
const [ patch ] = await Promise.all([
|
const [ patch ] = await Promise.all([
|
||||||
this._getOrUploadPoolPatch(patchUuid),
|
this._getOrUploadPoolPatch(patchUuid),
|
||||||
this._ejectToolsIsos()
|
this._ejectToolsIsos(),
|
||||||
])
|
])
|
||||||
|
|
||||||
await this.call('pool_patch.pool_apply', patch.$ref)
|
await this.call('pool_patch.pool_apply', patch.$ref)
|
||||||
@ -344,7 +344,7 @@ export default {
|
|||||||
_installPatchUpdateOnAllHosts: deferrable(async function ($defer, patchUuid) {
|
_installPatchUpdateOnAllHosts: deferrable(async function ($defer, patchUuid) {
|
||||||
let [ vdi ] = await Promise.all([
|
let [ vdi ] = await Promise.all([
|
||||||
this._getUpdateVdi($defer, patchUuid),
|
this._getUpdateVdi($defer, patchUuid),
|
||||||
this._ejectToolsIsos()
|
this._ejectToolsIsos(),
|
||||||
])
|
])
|
||||||
if (vdi == null) {
|
if (vdi == null) {
|
||||||
vdi = await this._getUpdateVdi($defer, patchUuid, this.pool.master)
|
vdi = await this._getUpdateVdi($defer, patchUuid, this.pool.master)
|
||||||
@ -473,5 +473,5 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
groupBy
|
groupBy,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createRawObject,
|
createRawObject,
|
||||||
mapToArray
|
mapToArray,
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -92,5 +92,5 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
return unhealthyVdis
|
return unhealthyVdis
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,20 @@ import {
|
|||||||
gte,
|
gte,
|
||||||
includes,
|
includes,
|
||||||
isEmpty,
|
isEmpty,
|
||||||
lte
|
lte,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
parseSize
|
parseSize,
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
isVmHvm,
|
isVmHvm,
|
||||||
isVmRunning,
|
isVmRunning,
|
||||||
makeEditObject,
|
makeEditObject,
|
||||||
NULL_REF
|
NULL_REF,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// According to: https://xenserver.org/blog/entry/vga-over-cirrus-in-xenserver-6-2.html.
|
// According to: https://xenserver.org/blog/entry/vga-over-cirrus-in-xenserver-6-2.html.
|
||||||
@ -29,7 +29,7 @@ export default {
|
|||||||
// TODO: clean up on error.
|
// TODO: clean up on error.
|
||||||
@deferrable.onFailure
|
@deferrable.onFailure
|
||||||
async createVm ($onFailure, templateId, {
|
async createVm ($onFailure, templateId, {
|
||||||
name_label, // deprecated
|
name_label, // eslint-disable-line camelcase
|
||||||
nameLabel = name_label, // eslint-disable-line camelcase
|
nameLabel = name_label, // eslint-disable-line camelcase
|
||||||
|
|
||||||
clone = true,
|
clone = true,
|
||||||
@ -94,7 +94,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._setObjectProperties(vm, {
|
this._setObjectProperties(vm, {
|
||||||
HVM_boot_params: { ...bootParams, order }
|
HVM_boot_params: { ...bootParams, order },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else { // PV
|
} else { // PV
|
||||||
@ -103,11 +103,11 @@ export default {
|
|||||||
// TODO: normalize RHEL URL?
|
// TODO: normalize RHEL URL?
|
||||||
|
|
||||||
await this._updateObjectMapProperty(vm, 'other_config', {
|
await this._updateObjectMapProperty(vm, 'other_config', {
|
||||||
'install-repository': installRepository
|
'install-repository': installRepository,
|
||||||
})
|
})
|
||||||
} else if (installMethod === 'cd') {
|
} else if (installMethod === 'cd') {
|
||||||
await this._updateObjectMapProperty(vm, 'other_config', {
|
await this._updateObjectMapProperty(vm, 'other_config', {
|
||||||
'install-repository': 'cdrom'
|
'install-repository': 'cdrom',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ export default {
|
|||||||
// When the VM is started, if PV, the CD drive will become not
|
// When the VM is started, if PV, the CD drive will become not
|
||||||
// bootable and the first disk bootable.
|
// bootable and the first disk bootable.
|
||||||
await this._insertCdIntoVm(installRepository, vm, {
|
await this._insertCdIntoVm(installRepository, vm, {
|
||||||
bootable: true
|
bootable: true,
|
||||||
})
|
})
|
||||||
hasBootableDisk = true
|
hasBootableDisk = true
|
||||||
}
|
}
|
||||||
@ -158,14 +158,14 @@ export default {
|
|||||||
{
|
{
|
||||||
name_label: vdiDescription.name_label,
|
name_label: vdiDescription.name_label,
|
||||||
name_description: vdiDescription.name_description,
|
name_description: vdiDescription.name_description,
|
||||||
sr: vdiDescription.sr || vdiDescription.SR
|
sr: vdiDescription.sr || vdiDescription.SR,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(ref => this._getOrWaitObject(ref))
|
.then(ref => this._getOrWaitObject(ref))
|
||||||
.then(vdi => this._createVbd(vm, vdi, {
|
.then(vdi => this._createVbd(vm, vdi, {
|
||||||
// Either the CD or the 1st disk is bootable (only useful for PV VMs)
|
// Either the CD or the 1st disk is bootable (only useful for PV VMs)
|
||||||
bootable: !(hasBootableDisk || i),
|
bootable: !(hasBootableDisk || i),
|
||||||
userdevice: devices[i]
|
userdevice: devices[i],
|
||||||
}))
|
}))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ export default {
|
|||||||
device: devices[index],
|
device: devices[index],
|
||||||
locking_mode: isEmpty(vif.ipv4_allowed) && isEmpty(vif.ipv6_allowed) ? 'network_default' : 'locked',
|
locking_mode: isEmpty(vif.ipv4_allowed) && isEmpty(vif.ipv6_allowed) ? 'network_default' : 'locked',
|
||||||
mac: vif.mac,
|
mac: vif.mac,
|
||||||
mtu: vif.mtu
|
mtu: vif.mtu,
|
||||||
}
|
}
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
@ -234,26 +234,26 @@ export default {
|
|||||||
'affinity',
|
'affinity',
|
||||||
value ? this.getObject(value).$ref : NULL_REF
|
value ? this.getObject(value).$ref : NULL_REF
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
autoPoweron: {
|
autoPoweron: {
|
||||||
set (value, vm) {
|
set (value, vm) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
this._updateObjectMapProperty(vm, 'other_config', {
|
this._updateObjectMapProperty(vm, 'other_config', {
|
||||||
autoPoweron: value ? 'true' : null
|
autoPoweron: value ? 'true' : null,
|
||||||
}),
|
}),
|
||||||
value && this.setPoolProperties({
|
value && this.setPoolProperties({
|
||||||
autoPoweron: true
|
autoPoweron: true,
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
coresPerSocket: {
|
coresPerSocket: {
|
||||||
set (coresPerSocket, vm) {
|
set (coresPerSocket, vm) {
|
||||||
return this._updateObjectMapProperty(vm, 'platform', {'cores-per-socket': coresPerSocket})
|
return this._updateObjectMapProperty(vm, 'platform', {'cores-per-socket': coresPerSocket})
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
CPUs: 'cpus',
|
CPUs: 'cpus',
|
||||||
@ -265,7 +265,7 @@ export default {
|
|||||||
// If the other value is not set and the constraint is not
|
// If the other value is not set and the constraint is not
|
||||||
// respected, the other value is changed first.
|
// respected, the other value is changed first.
|
||||||
constraints: {
|
constraints: {
|
||||||
cpusStaticMax: gte
|
cpusStaticMax: gte,
|
||||||
},
|
},
|
||||||
|
|
||||||
get: vm => +vm.VCPUs_at_startup,
|
get: vm => +vm.VCPUs_at_startup,
|
||||||
@ -273,46 +273,46 @@ export default {
|
|||||||
'VCPUs_at_startup',
|
'VCPUs_at_startup',
|
||||||
function (value, vm) {
|
function (value, vm) {
|
||||||
return isVmRunning(vm) && this._set('VCPUs_number_live', value)
|
return isVmRunning(vm) && this._set('VCPUs_number_live', value)
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
cpuCap: {
|
cpuCap: {
|
||||||
get: vm => vm.VCPUs_params.cap && +vm.VCPUs_params.cap,
|
get: vm => vm.VCPUs_params.cap && +vm.VCPUs_params.cap,
|
||||||
set (cap, vm) {
|
set (cap, vm) {
|
||||||
return this._updateObjectMapProperty(vm, 'VCPUs_params', { cap })
|
return this._updateObjectMapProperty(vm, 'VCPUs_params', { cap })
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
cpusMax: 'cpusStaticMax',
|
cpusMax: 'cpusStaticMax',
|
||||||
cpusStaticMax: {
|
cpusStaticMax: {
|
||||||
constraints: {
|
constraints: {
|
||||||
cpus: lte
|
cpus: lte,
|
||||||
},
|
},
|
||||||
get: vm => +vm.VCPUs_max,
|
get: vm => +vm.VCPUs_max,
|
||||||
set: 'VCPUs_max'
|
set: 'VCPUs_max',
|
||||||
},
|
},
|
||||||
|
|
||||||
cpuWeight: {
|
cpuWeight: {
|
||||||
get: vm => vm.VCPUs_params.weight && +vm.VCPUs_params.weight,
|
get: vm => vm.VCPUs_params.weight && +vm.VCPUs_params.weight,
|
||||||
set (weight, vm) {
|
set (weight, vm) {
|
||||||
return this._updateObjectMapProperty(vm, 'VCPUs_params', { weight })
|
return this._updateObjectMapProperty(vm, 'VCPUs_params', { weight })
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
highAvailability: {
|
highAvailability: {
|
||||||
set (ha, vm) {
|
set (ha, vm) {
|
||||||
return this.call('VM.set_ha_restart_priority', vm.$ref, ha ? 'restart' : '')
|
return this.call('VM.set_ha_restart_priority', vm.$ref, ha ? 'restart' : '')
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
memoryMin: {
|
memoryMin: {
|
||||||
constraints: {
|
constraints: {
|
||||||
memoryMax: gte
|
memoryMax: gte,
|
||||||
},
|
},
|
||||||
get: vm => +vm.memory_dynamic_min,
|
get: vm => +vm.memory_dynamic_min,
|
||||||
preprocess: parseSize,
|
preprocess: parseSize,
|
||||||
set: 'memory_dynamic_min'
|
set: 'memory_dynamic_min',
|
||||||
},
|
},
|
||||||
|
|
||||||
memory: 'memoryMax',
|
memory: 'memoryMax',
|
||||||
@ -321,20 +321,20 @@ export default {
|
|||||||
limitName: 'memory',
|
limitName: 'memory',
|
||||||
constraints: {
|
constraints: {
|
||||||
memoryMin: lte,
|
memoryMin: lte,
|
||||||
memoryStaticMax: gte
|
memoryStaticMax: gte,
|
||||||
},
|
},
|
||||||
get: vm => +vm.memory_dynamic_max,
|
get: vm => +vm.memory_dynamic_max,
|
||||||
preprocess: parseSize,
|
preprocess: parseSize,
|
||||||
set: 'memory_dynamic_max'
|
set: 'memory_dynamic_max',
|
||||||
},
|
},
|
||||||
|
|
||||||
memoryStaticMax: {
|
memoryStaticMax: {
|
||||||
constraints: {
|
constraints: {
|
||||||
memoryMax: lte
|
memoryMax: lte,
|
||||||
},
|
},
|
||||||
get: vm => +vm.memory_static_max,
|
get: vm => +vm.memory_static_max,
|
||||||
preprocess: parseSize,
|
preprocess: parseSize,
|
||||||
set: 'memory_static_max'
|
set: 'memory_static_max',
|
||||||
},
|
},
|
||||||
|
|
||||||
nameDescription: true,
|
nameDescription: true,
|
||||||
@ -351,7 +351,7 @@ export default {
|
|||||||
throw new Error(`The different values that the VGA can take are: ${XEN_VGA_VALUES}`)
|
throw new Error(`The different values that the VGA can take are: ${XEN_VGA_VALUES}`)
|
||||||
}
|
}
|
||||||
return this._updateObjectMapProperty(vm, 'platform', { vga })
|
return this._updateObjectMapProperty(vm, 'platform', { vga })
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
videoram: {
|
videoram: {
|
||||||
@ -360,8 +360,8 @@ export default {
|
|||||||
throw new Error(`The different values that the video RAM can take are: ${XEN_VIDEORAM_VALUES}`)
|
throw new Error(`The different values that the video RAM can take are: ${XEN_VIDEORAM_VALUES}`)
|
||||||
}
|
}
|
||||||
return this._updateObjectMapProperty(vm, 'platform', { videoram })
|
return this._updateObjectMapProperty(vm, 'platform', { videoram })
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
async editVm (id, props, checkLimits) {
|
async editVm (id, props, checkLimits) {
|
||||||
@ -387,5 +387,5 @@ export default {
|
|||||||
async resumeVm (vmId) {
|
async resumeVm (vmId) {
|
||||||
// the force parameter is always true
|
// the force parameter is always true
|
||||||
return this.call('VM.resume', this.getObject(vmId).$ref, false, true)
|
return this.call('VM.resume', this.getObject(vmId).$ref, false, true)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ const OTHER_CONFIG_TEMPLATE = {
|
|||||||
blocked_operations: {},
|
blocked_operations: {},
|
||||||
ha_always_run: false,
|
ha_always_run: false,
|
||||||
HVM_boot_params: {
|
HVM_boot_params: {
|
||||||
order: 'cdn'
|
order: 'cdn',
|
||||||
},
|
},
|
||||||
HVM_boot_policy: 'BIOS order',
|
HVM_boot_policy: 'BIOS order',
|
||||||
HVM_shadow_multiplier: 1,
|
HVM_shadow_multiplier: 1,
|
||||||
@ -22,7 +22,7 @@ const OTHER_CONFIG_TEMPLATE = {
|
|||||||
vgpu_pci: '',
|
vgpu_pci: '',
|
||||||
base_template_name: 'Other install media',
|
base_template_name: 'Other install media',
|
||||||
mac_seed: '5e88eb6a-d680-c47f-a94a-028886971ba4',
|
mac_seed: '5e88eb6a-d680-c47f-a94a-028886971ba4',
|
||||||
'install-methods': 'cdrom'
|
'install-methods': 'cdrom',
|
||||||
},
|
},
|
||||||
PCI_bus: '',
|
PCI_bus: '',
|
||||||
platform: {
|
platform: {
|
||||||
@ -32,7 +32,7 @@ const OTHER_CONFIG_TEMPLATE = {
|
|||||||
apic: 'true',
|
apic: 'true',
|
||||||
pae: 'true',
|
pae: 'true',
|
||||||
hpet: 'true',
|
hpet: 'true',
|
||||||
viridian: 'true'
|
viridian: 'true',
|
||||||
},
|
},
|
||||||
protection_policy: NULL_REF,
|
protection_policy: NULL_REF,
|
||||||
PV_args: '',
|
PV_args: '',
|
||||||
@ -48,6 +48,6 @@ const OTHER_CONFIG_TEMPLATE = {
|
|||||||
VCPUs_at_startup: 1,
|
VCPUs_at_startup: 1,
|
||||||
VCPUs_max: 1,
|
VCPUs_max: 1,
|
||||||
VCPUs_params: {},
|
VCPUs_params: {},
|
||||||
version: 0
|
version: 0,
|
||||||
}
|
}
|
||||||
export { OTHER_CONFIG_TEMPLATE as default }
|
export { OTHER_CONFIG_TEMPLATE as default }
|
||||||
|
@ -19,7 +19,7 @@ import {
|
|||||||
map,
|
map,
|
||||||
mapFilter,
|
mapFilter,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
noop
|
noop,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -102,7 +102,7 @@ forEach([
|
|||||||
'VM_guest_metrics',
|
'VM_guest_metrics',
|
||||||
'VM_metrics',
|
'VM_metrics',
|
||||||
'VMPP',
|
'VMPP',
|
||||||
'VTPM'
|
'VTPM',
|
||||||
], namespace => {
|
], namespace => {
|
||||||
TYPE_TO_NAMESPACE[namespace.toLowerCase()] = namespace
|
TYPE_TO_NAMESPACE[namespace.toLowerCase()] = namespace
|
||||||
})
|
})
|
||||||
@ -152,7 +152,7 @@ export const isVmHvm = vm => Boolean(vm.HVM_boot_policy)
|
|||||||
|
|
||||||
const VM_RUNNING_POWER_STATES = {
|
const VM_RUNNING_POWER_STATES = {
|
||||||
Running: true,
|
Running: true,
|
||||||
Paused: true
|
Paused: true,
|
||||||
}
|
}
|
||||||
export const isVmRunning = vm => VM_RUNNING_POWER_STATES[vm.power_state]
|
export const isVmRunning = vm => VM_RUNNING_POWER_STATES[vm.power_state]
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ export const makeEditObject = specs => {
|
|||||||
if (spec === true) {
|
if (spec === true) {
|
||||||
spec = {
|
spec = {
|
||||||
get: true,
|
get: true,
|
||||||
set: true
|
set: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ export const makeEditObject = specs => {
|
|||||||
// Context used to execute functions.
|
// Context used to execute functions.
|
||||||
const context = {
|
const context = {
|
||||||
__proto__: this,
|
__proto__: this,
|
||||||
_set: (prop, value) => this.call(_setMethodPrefix + prop, _objectRef, prepareXapiParam(value))
|
_set: (prop, value) => this.call(_setMethodPrefix + prop, _objectRef, prepareXapiParam(value)),
|
||||||
}
|
}
|
||||||
|
|
||||||
const set = (value, name) => {
|
const set = (value, name) => {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import checkAuthorization from 'xo-acl-resolver'
|
import checkAuthorization from 'xo-acl-resolver'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ModelAlreadyExists
|
ModelAlreadyExists,
|
||||||
} from '../collection'
|
} from '../collection'
|
||||||
import {
|
import {
|
||||||
Acls
|
Acls,
|
||||||
} from '../models/acl'
|
} from '../models/acl'
|
||||||
import {
|
import {
|
||||||
createRawObject,
|
createRawObject,
|
||||||
forEach,
|
forEach,
|
||||||
includes,
|
includes,
|
||||||
mapToArray
|
mapToArray,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -22,7 +22,7 @@ export default class {
|
|||||||
const aclsDb = this._acls = new Acls({
|
const aclsDb = this._acls = new Acls({
|
||||||
connection: xo._redis,
|
connection: xo._redis,
|
||||||
prefix: 'xo:acl',
|
prefix: 'xo:acl',
|
||||||
indexes: ['subject', 'object']
|
indexes: ['subject', 'object'],
|
||||||
})
|
})
|
||||||
|
|
||||||
xo.on('start', () => {
|
xo.on('start', () => {
|
||||||
@ -93,10 +93,10 @@ export default class {
|
|||||||
async getPermissionsForUser (userId) {
|
async getPermissionsForUser (userId) {
|
||||||
const [
|
const [
|
||||||
acls,
|
acls,
|
||||||
permissionsByRole
|
permissionsByRole,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
this._getAclsForUser(userId),
|
this._getAclsForUser(userId),
|
||||||
this._getPermissionsByRole()
|
this._getPermissionsByRole(),
|
||||||
])
|
])
|
||||||
|
|
||||||
const permissions = createRawObject()
|
const permissions = createRawObject()
|
||||||
@ -152,16 +152,16 @@ export default class {
|
|||||||
id: 'viewer',
|
id: 'viewer',
|
||||||
name: 'Viewer',
|
name: 'Viewer',
|
||||||
permissions: [
|
permissions: [
|
||||||
'view'
|
'view',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'operator',
|
id: 'operator',
|
||||||
name: 'Operator',
|
name: 'Operator',
|
||||||
permissions: [
|
permissions: [
|
||||||
'view',
|
'view',
|
||||||
'operate'
|
'operate',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'admin',
|
id: 'admin',
|
||||||
@ -169,9 +169,9 @@ export default class {
|
|||||||
permissions: [
|
permissions: [
|
||||||
'view',
|
'view',
|
||||||
'operate',
|
'operate',
|
||||||
'administrate'
|
'administrate',
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,17 +7,17 @@ import {
|
|||||||
isArray,
|
isArray,
|
||||||
isFunction,
|
isFunction,
|
||||||
map,
|
map,
|
||||||
mapValues
|
mapValues,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import * as methods from '../api'
|
import * as methods from '../api' // eslint-disable-line node/no-missing-import
|
||||||
import {
|
import {
|
||||||
MethodNotFound
|
MethodNotFound,
|
||||||
} from 'json-rpc-peer'
|
} from 'json-rpc-peer'
|
||||||
import {
|
import {
|
||||||
createRawObject,
|
createRawObject,
|
||||||
noop,
|
noop,
|
||||||
serializeError
|
serializeError,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
import * as errors from 'xo-common/api-errors'
|
import * as errors from 'xo-common/api-errors'
|
||||||
@ -30,7 +30,7 @@ const PERMISSIONS = {
|
|||||||
none: 0,
|
none: 0,
|
||||||
read: 1,
|
read: 1,
|
||||||
write: 2,
|
write: 2,
|
||||||
admin: 3
|
admin: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
@ -50,7 +50,7 @@ const XAPI_ERROR_TO_XO_ERROR = {
|
|||||||
VM_IS_TEMPLATE: errors.vmIsTemplate,
|
VM_IS_TEMPLATE: errors.vmIsTemplate,
|
||||||
VM_LACKS_FEATURE: ([ vm ], getId) => errors.vmLacksFeature({ vm: getId(vm) }),
|
VM_LACKS_FEATURE: ([ vm ], getId) => errors.vmLacksFeature({ vm: getId(vm) }),
|
||||||
VM_LACKS_FEATURE_SHUTDOWN: ([ vm ], getId) => errors.vmLacksFeature({ vm: getId(vm), feature: 'shutdown' }),
|
VM_LACKS_FEATURE_SHUTDOWN: ([ vm ], getId) => errors.vmLacksFeature({ vm: getId(vm), feature: 'shutdown' }),
|
||||||
VM_MISSING_PV_DRIVERS: ([ vm ], getId) => errors.vmMissingPvDrivers({ vm: getId(vm) })
|
VM_MISSING_PV_DRIVERS: ([ vm ], getId) => errors.vmMissingPvDrivers({ vm: getId(vm) }),
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasPermission = (user, permission) => (
|
const hasPermission = (user, permission) => (
|
||||||
@ -65,7 +65,7 @@ function checkParams (method, params) {
|
|||||||
|
|
||||||
const result = schemaInspector.validate({
|
const result = schemaInspector.validate({
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: schema
|
properties: schema,
|
||||||
}, params)
|
}, params)
|
||||||
|
|
||||||
if (!result.valid) {
|
if (!result.valid) {
|
||||||
@ -243,11 +243,11 @@ export default class Api {
|
|||||||
// XO methods called from the API.
|
// XO methods called from the API.
|
||||||
const context = Object.create(this._xo, {
|
const context = Object.create(this._xo, {
|
||||||
api: { // Used by system.*().
|
api: { // Used by system.*().
|
||||||
value: this
|
value: this,
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
value: session
|
value: session,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Fetch and inject the current user.
|
// Fetch and inject the current user.
|
||||||
@ -303,7 +303,7 @@ export default class Api {
|
|||||||
method: name,
|
method: name,
|
||||||
params: removeSensitiveParams(params),
|
params: removeSensitiveParams(params),
|
||||||
duration: Date.now() - startTime,
|
duration: Date.now() - startTime,
|
||||||
error: serializeError(error)
|
error: serializeError(error),
|
||||||
}
|
}
|
||||||
const message = `${userName} | ${name}(${JSON.stringify(params)}) [${ms(Date.now() - startTime)}] =!> ${error}`
|
const message = `${userName} | ${name}(${JSON.stringify(params)}) [${ms(Date.now() - startTime)}] =!> ${error}`
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import Token, { Tokens } from '../models/token'
|
|||||||
import {
|
import {
|
||||||
createRawObject,
|
createRawObject,
|
||||||
forEach,
|
forEach,
|
||||||
generateToken
|
generateToken,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -30,13 +30,13 @@ export default class {
|
|||||||
const tokensDb = this._tokens = new Tokens({
|
const tokensDb = this._tokens = new Tokens({
|
||||||
connection: xo._redis,
|
connection: xo._redis,
|
||||||
prefix: 'xo:token',
|
prefix: 'xo:token',
|
||||||
indexes: ['user_id']
|
indexes: ['user_id'],
|
||||||
})
|
})
|
||||||
|
|
||||||
// Password authentication provider.
|
// Password authentication provider.
|
||||||
this.registerAuthenticationProvider(async ({
|
this.registerAuthenticationProvider(async ({
|
||||||
username,
|
username,
|
||||||
password
|
password,
|
||||||
}) => {
|
}) => {
|
||||||
if (username === undefined || password === undefined) {
|
if (username === undefined || password === undefined) {
|
||||||
return
|
return
|
||||||
@ -50,7 +50,7 @@ export default class {
|
|||||||
|
|
||||||
// Token authentication provider.
|
// Token authentication provider.
|
||||||
this.registerAuthenticationProvider(async ({
|
this.registerAuthenticationProvider(async ({
|
||||||
token: tokenId
|
token: tokenId,
|
||||||
}) => {
|
}) => {
|
||||||
if (!tokenId) {
|
if (!tokenId) {
|
||||||
return
|
return
|
||||||
@ -154,7 +154,7 @@ export default class {
|
|||||||
|
|
||||||
async createAuthenticationToken ({
|
async createAuthenticationToken ({
|
||||||
expiresIn = ONE_MONTH,
|
expiresIn = ONE_MONTH,
|
||||||
userId
|
userId,
|
||||||
}) {
|
}) {
|
||||||
const token = new Token({
|
const token = new Token({
|
||||||
id: await generateToken(),
|
id: await generateToken(),
|
||||||
@ -163,7 +163,7 @@ export default class {
|
|||||||
typeof expiresIn === 'string'
|
typeof expiresIn === 'string'
|
||||||
? ms(expiresIn)
|
? ms(expiresIn)
|
||||||
: expiresIn
|
: expiresIn
|
||||||
)
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
await this._tokens.add(token)
|
await this._tokens.add(token)
|
||||||
|
@ -10,7 +10,7 @@ import { satisfies as versionSatisfies } from 'semver'
|
|||||||
import { utcFormat } from 'd3-time-format'
|
import { utcFormat } from 'd3-time-format'
|
||||||
import {
|
import {
|
||||||
basename,
|
basename,
|
||||||
dirname
|
dirname,
|
||||||
} from 'path'
|
} from 'path'
|
||||||
import {
|
import {
|
||||||
endsWith,
|
endsWith,
|
||||||
@ -22,7 +22,7 @@ import {
|
|||||||
range,
|
range,
|
||||||
sortBy,
|
sortBy,
|
||||||
startsWith,
|
startsWith,
|
||||||
trim
|
trim,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import createSizeStream from '../size-stream'
|
import createSizeStream from '../size-stream'
|
||||||
@ -41,10 +41,10 @@ import {
|
|||||||
resolveSubpath,
|
resolveSubpath,
|
||||||
safeDateFormat,
|
safeDateFormat,
|
||||||
safeDateParse,
|
safeDateParse,
|
||||||
tmpDir
|
tmpDir,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import {
|
import {
|
||||||
VDI_FORMAT_VHD
|
VDI_FORMAT_VHD,
|
||||||
} from '../xapi'
|
} from '../xapi'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -76,7 +76,7 @@ const parseVmBackupPath = name => {
|
|||||||
id: name,
|
id: name,
|
||||||
name: baseMatches[3],
|
name: baseMatches[3],
|
||||||
tag: baseMatches[2],
|
tag: baseMatches[2],
|
||||||
type: 'xva'
|
type: 'xva',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ const parseVmBackupPath = name => {
|
|||||||
name: baseMatches[2],
|
name: baseMatches[2],
|
||||||
tag: dirMatches[1],
|
tag: dirMatches[1],
|
||||||
type: 'delta',
|
type: 'delta',
|
||||||
uuid: dirMatches[2]
|
uuid: dirMatches[2],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ const listPartitions = (() => {
|
|||||||
// https://github.com/jhermsmeier/node-mbr/blob/master/lib/partition.js#L38
|
// https://github.com/jhermsmeier/node-mbr/blob/master/lib/partition.js#L38
|
||||||
0x05, 0x0F, 0x85, 0x15, 0x91, 0x9B, 0x5E, 0x5F, 0xCF, 0xD5, 0xC5,
|
0x05, 0x0F, 0x85, 0x15, 0x91, 0x9B, 0x5E, 0x5F, 0xCF, 0xD5, 0xC5,
|
||||||
|
|
||||||
0x82 // swap
|
0x82, // swap
|
||||||
], type => {
|
], type => {
|
||||||
IGNORED[type] = true
|
IGNORED[type] = true
|
||||||
})
|
})
|
||||||
@ -147,7 +147,7 @@ const listPartitions = (() => {
|
|||||||
const TYPES = {
|
const TYPES = {
|
||||||
0x7: 'NTFS',
|
0x7: 'NTFS',
|
||||||
0x83: 'linux',
|
0x83: 'linux',
|
||||||
0xc: 'FAT'
|
0xc: 'FAT',
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseLine = createPairsParser({
|
const parseLine = createPairsParser({
|
||||||
@ -158,14 +158,14 @@ const listPartitions = (() => {
|
|||||||
? +value
|
? +value
|
||||||
: key === 'type'
|
: key === 'type'
|
||||||
? TYPES[+value] || value
|
? TYPES[+value] || value
|
||||||
: value
|
: value,
|
||||||
})
|
})
|
||||||
|
|
||||||
return device => execa.stdout('partx', [
|
return device => execa.stdout('partx', [
|
||||||
'--bytes',
|
'--bytes',
|
||||||
'--output=NR,START,SIZE,NAME,UUID,TYPE',
|
'--output=NR,START,SIZE,NAME,UUID,TYPE',
|
||||||
'--pairs',
|
'--pairs',
|
||||||
device.path
|
device.path,
|
||||||
]).then(stdout => mapFilter(splitLines(stdout), line => {
|
]).then(stdout => mapFilter(splitLines(stdout), line => {
|
||||||
const partition = parseLine(line)
|
const partition = parseLine(line)
|
||||||
const { type } = partition
|
const { type } = partition
|
||||||
@ -187,7 +187,7 @@ const listPartitions2 = device => listPartitions(device).then(partitions => {
|
|||||||
partitions2.push({
|
partitions2.push({
|
||||||
name: lv.lv_name,
|
name: lv.lv_name,
|
||||||
size: +lv.lv_size,
|
size: +lv.lv_size,
|
||||||
id: `${partition.id}/${lv.vg_name}/${lv.lv_name}`
|
id: `${partition.id}/${lv.vg_name}/${lv.lv_name}`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -203,11 +203,11 @@ const listPartitions2 = device => listPartitions(device).then(partitions => {
|
|||||||
|
|
||||||
const mountPartition = (device, partitionId) => Promise.all([
|
const mountPartition = (device, partitionId) => Promise.all([
|
||||||
partitionId != null && listPartitions(device),
|
partitionId != null && listPartitions(device),
|
||||||
tmpDir()
|
tmpDir(),
|
||||||
]).then(([ partitions, path ]) => {
|
]).then(([ partitions, path ]) => {
|
||||||
const options = [
|
const options = [
|
||||||
'loop',
|
'loop',
|
||||||
'ro'
|
'ro',
|
||||||
]
|
]
|
||||||
|
|
||||||
if (partitions) {
|
if (partitions) {
|
||||||
@ -222,7 +222,7 @@ const mountPartition = (device, partitionId) => Promise.all([
|
|||||||
const mount = options => execa('mount', [
|
const mount = options => execa('mount', [
|
||||||
`--options=${options.join(',')}`,
|
`--options=${options.join(',')}`,
|
||||||
`--source=${device.path}`,
|
`--source=${device.path}`,
|
||||||
`--target=${path}`
|
`--target=${path}`,
|
||||||
])
|
])
|
||||||
|
|
||||||
// `norecovery` option is used for ext3/ext4/xfs, if it fails it
|
// `norecovery` option is used for ext3/ext4/xfs, if it fails it
|
||||||
@ -231,7 +231,7 @@ const mountPartition = (device, partitionId) => Promise.all([
|
|||||||
mount(options)
|
mount(options)
|
||||||
).then(() => ({
|
).then(() => ({
|
||||||
path,
|
path,
|
||||||
unmount: once(() => execa('umount', [ '--lazy', path ]))
|
unmount: once(() => execa('umount', [ '--lazy', path ])),
|
||||||
}), error => {
|
}), error => {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ const mountPartition2 = (device, partitionId) => {
|
|||||||
).then(path =>
|
).then(path =>
|
||||||
mountPartition({ path }).then(device2 => ({
|
mountPartition({ path }).then(device2 => ({
|
||||||
...device2,
|
...device2,
|
||||||
unmount: () => device2.unmount().then(device1.unmount)
|
unmount: () => device2.unmount().then(device1.unmount),
|
||||||
}))
|
}))
|
||||||
).catch(error => device1.unmount().then(() => {
|
).catch(error => device1.unmount().then(() => {
|
||||||
throw error
|
throw error
|
||||||
@ -274,7 +274,7 @@ const listLvmLvs = device => pvs([
|
|||||||
'lv_name',
|
'lv_name',
|
||||||
'lv_path',
|
'lv_path',
|
||||||
'lv_size',
|
'lv_size',
|
||||||
'vg_name'
|
'vg_name',
|
||||||
], device.path).then(pvs => filter(pvs, 'lv_name'))
|
], device.path).then(pvs => filter(pvs, 'lv_name'))
|
||||||
|
|
||||||
const mountLvmPv = (device, partition) => {
|
const mountLvmPv = (device, partition) => {
|
||||||
@ -296,9 +296,9 @@ const mountLvmPv = (device, partition) => {
|
|||||||
execa('losetup', [ '-d', path ]),
|
execa('losetup', [ '-d', path ]),
|
||||||
pvs('vg_name', path).then(vgNames => execa('vgchange', [
|
pvs('vg_name', path).then(vgNames => execa('vgchange', [
|
||||||
'-an',
|
'-an',
|
||||||
...vgNames
|
...vgNames,
|
||||||
]))
|
])),
|
||||||
]))
|
])),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ export default class {
|
|||||||
// unmounted
|
// unmounted
|
||||||
xo.on('start', () => Promise.all([
|
xo.on('start', () => Promise.all([
|
||||||
execa('losetup', [ '-D' ]),
|
execa('losetup', [ '-D' ]),
|
||||||
execa('vgchange', [ '-an' ])
|
execa('vgchange', [ '-an' ]),
|
||||||
]).then(() =>
|
]).then(() =>
|
||||||
execa('pvscan', [ '--cache' ])
|
execa('pvscan', [ '--cache' ])
|
||||||
))
|
))
|
||||||
@ -367,7 +367,7 @@ export default class {
|
|||||||
record.disks = mapToArray(JSON.parse(data).vdis, vdi => ({
|
record.disks = mapToArray(JSON.parse(data).vdis, vdi => ({
|
||||||
id: `${entry}/${vdi.xoPath}`,
|
id: `${entry}/${vdi.xoPath}`,
|
||||||
name: vdi.name_label,
|
name: vdi.name_label,
|
||||||
uuid: vdi.uuid
|
uuid: vdi.uuid,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -390,8 +390,8 @@ export default class {
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
xapi.addTag(vm.$id, 'restored from backup'),
|
xapi.addTag(vm.$id, 'restored from backup'),
|
||||||
xapi.editVm(vm.$id, {
|
xapi.editVm(vm.$id, {
|
||||||
name_label: `${vm.name_label} (${shortDate(datetime * 1e3)})`
|
name_label: `${vm.name_label} (${shortDate(datetime * 1e3)})`,
|
||||||
})
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
return xapiObjectToXo(vm).id
|
return xapiObjectToXo(vm).id
|
||||||
@ -424,7 +424,7 @@ export default class {
|
|||||||
const { cancel, token } = CancelToken.source()
|
const { cancel, token } = CancelToken.source()
|
||||||
const delta = await srcXapi.exportDeltaVm(token, srcVm.$id, localBaseUuid, {
|
const delta = await srcXapi.exportDeltaVm(token, srcVm.$id, localBaseUuid, {
|
||||||
bypassVdiChainsCheck: force,
|
bypassVdiChainsCheck: force,
|
||||||
snapshotNameLabel: `XO_DELTA_EXPORT: ${targetSr.name_label} (${targetSr.uuid})`
|
snapshotNameLabel: `XO_DELTA_EXPORT: ${targetSr.name_label} (${targetSr.uuid})`,
|
||||||
})
|
})
|
||||||
$onFailure(() => srcXapi.deleteVm(delta.vm.uuid))
|
$onFailure(() => srcXapi.deleteVm(delta.vm.uuid))
|
||||||
$onFailure(cancel)
|
$onFailure(cancel)
|
||||||
@ -461,7 +461,7 @@ export default class {
|
|||||||
delta,
|
delta,
|
||||||
{
|
{
|
||||||
deleteBase,
|
deleteBase,
|
||||||
srId: targetSr.$id
|
srId: targetSr.$id,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -480,7 +480,7 @@ export default class {
|
|||||||
// (Asynchronously) Identify snapshot as future base.
|
// (Asynchronously) Identify snapshot as future base.
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
return srcXapi._updateObjectMapProperty(srcVm, 'other_config', {
|
return srcXapi._updateObjectMapProperty(srcVm, 'other_config', {
|
||||||
[TAG_LAST_BASE_DELTA]: delta.vm.uuid
|
[TAG_LAST_BASE_DELTA]: delta.vm.uuid,
|
||||||
})
|
})
|
||||||
})::ignoreErrors()
|
})::ignoreErrors()
|
||||||
|
|
||||||
@ -491,7 +491,7 @@ export default class {
|
|||||||
// 5. Return the identifier of the new XO VM object.
|
// 5. Return the identifier of the new XO VM object.
|
||||||
id: xapiObjectToXo(dstVm).id,
|
id: xapiObjectToXo(dstVm).id,
|
||||||
transferDuration: Date.now() - transferStart,
|
transferDuration: Date.now() - transferStart,
|
||||||
transferSize: size
|
transferSize: size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ export default class {
|
|||||||
const stream = await handler.createReadStream(`${dir}/${vdiDir}/${backup}`)
|
const stream = await handler.createReadStream(`${dir}/${vdiDir}/${backup}`)
|
||||||
|
|
||||||
await xapi.importVdiContent(vdiId, stream, {
|
await xapi.importVdiContent(vdiId, stream, {
|
||||||
format: VDI_FORMAT_VHD
|
format: VDI_FORMAT_VHD,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +550,7 @@ export default class {
|
|||||||
// Disable start and change the VM name label during import.
|
// Disable start and change the VM name label during import.
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
xapi.addForbiddenOperationToVm(vm.$id, 'start', 'Delta backup import...'),
|
xapi.addForbiddenOperationToVm(vm.$id, 'start', 'Delta backup import...'),
|
||||||
xapi._setObjectProperties(vm, { name_label: `[Importing...] ${vmName}` })
|
xapi._setObjectProperties(vm, { name_label: `[Importing...] ${vmName}` }),
|
||||||
])
|
])
|
||||||
|
|
||||||
// Destroy vbds if necessary. Why ?
|
// Destroy vbds if necessary. Why ?
|
||||||
@ -583,7 +583,7 @@ export default class {
|
|||||||
// Import done, reenable start and set real vm name.
|
// Import done, reenable start and set real vm name.
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
xapi.removeForbiddenOperationFromVm(vm.$id, 'start'),
|
xapi.removeForbiddenOperationFromVm(vm.$id, 'start'),
|
||||||
xapi._setObjectProperties(vm, { name_label: vmName })
|
xapi._setObjectProperties(vm, { name_label: vmName }),
|
||||||
])
|
])
|
||||||
|
|
||||||
return vm
|
return vm
|
||||||
@ -628,7 +628,7 @@ export default class {
|
|||||||
|
|
||||||
async _mergeDeltaVdiBackups ({handler, dir, retention}) {
|
async _mergeDeltaVdiBackups ({handler, dir, retention}) {
|
||||||
const backups = await this._listVdiBackups(handler, dir)
|
const backups = await this._listVdiBackups(handler, dir)
|
||||||
let i = backups.length - retention
|
const i = backups.length - retention
|
||||||
|
|
||||||
// No merge.
|
// No merge.
|
||||||
if (i <= 0) {
|
if (i <= 0) {
|
||||||
@ -730,7 +730,7 @@ export default class {
|
|||||||
// The problem is in the merge case, a delta merged in a full vdi
|
// The problem is in the merge case, a delta merged in a full vdi
|
||||||
// backup forces us to browse the resulting file =>
|
// backup forces us to browse the resulting file =>
|
||||||
// Significant transfer time on the network !
|
// Significant transfer time on the network !
|
||||||
checksum: !isFull
|
checksum: !isFull,
|
||||||
})
|
})
|
||||||
|
|
||||||
stream.on('error', error => targetStream.emit('error', error))
|
stream.on('error', error => targetStream.emit('error', error))
|
||||||
@ -742,7 +742,7 @@ export default class {
|
|||||||
.pipe(targetStream),
|
.pipe(targetStream),
|
||||||
'finish'
|
'finish'
|
||||||
),
|
),
|
||||||
stream.task
|
stream.task,
|
||||||
])
|
])
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Remove new backup. (corrupt).
|
// Remove new backup. (corrupt).
|
||||||
@ -754,7 +754,7 @@ export default class {
|
|||||||
return {
|
return {
|
||||||
// Returns relative path.
|
// Returns relative path.
|
||||||
path: `${backupDirectory}/${vdiFilename}`,
|
path: `${backupDirectory}/${vdiFilename}`,
|
||||||
size: sizeStream.size
|
size: sizeStream.size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,7 +769,7 @@ export default class {
|
|||||||
|
|
||||||
// Remove xva file.
|
// Remove xva file.
|
||||||
// Version 0.0.0 (Legacy) Delta Backup.
|
// Version 0.0.0 (Legacy) Delta Backup.
|
||||||
handler.unlink(`${dir}/${getDeltaBackupNameWithoutExt(backup)}.xva`)::ignoreErrors()
|
handler.unlink(`${dir}/${getDeltaBackupNameWithoutExt(backup)}.xva`)::ignoreErrors(),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -815,7 +815,7 @@ export default class {
|
|||||||
const delta = await xapi.exportDeltaVm(token, vm.$id, baseVm && baseVm.$id, {
|
const delta = await xapi.exportDeltaVm(token, vm.$id, baseVm && baseVm.$id, {
|
||||||
snapshotNameLabel: `XO_DELTA_BASE_VM_SNAPSHOT_${tag}`,
|
snapshotNameLabel: `XO_DELTA_BASE_VM_SNAPSHOT_${tag}`,
|
||||||
fullVdisRequired,
|
fullVdisRequired,
|
||||||
disableBaseTags: true
|
disableBaseTags: true,
|
||||||
})
|
})
|
||||||
$onFailure(() => xapi.deleteVm(delta.vm.uuid))
|
$onFailure(() => xapi.deleteVm(delta.vm.uuid))
|
||||||
$onFailure(cancel)
|
$onFailure(cancel)
|
||||||
@ -831,12 +831,12 @@ export default class {
|
|||||||
handler,
|
handler,
|
||||||
stream: delta.streams[`${key}.vhd`],
|
stream: delta.streams[`${key}.vhd`],
|
||||||
dir,
|
dir,
|
||||||
retention
|
retention,
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
delta.vdis[key] = {
|
delta.vdis[key] = {
|
||||||
...delta.vdis[key],
|
...delta.vdis[key],
|
||||||
xoPath: data.path
|
xoPath: data.path,
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
@ -912,7 +912,7 @@ export default class {
|
|||||||
mergeDuration: mergedDataSize !== 0 ? mergeDuration : undefined,
|
mergeDuration: mergedDataSize !== 0 ? mergeDuration : undefined,
|
||||||
mergeSize: mergedDataSize !== 0 ? mergedDataSize : undefined,
|
mergeSize: mergedDataSize !== 0 ? mergedDataSize : undefined,
|
||||||
transferDuration: Date.now() - transferStart - mergeDuration,
|
transferDuration: Date.now() - transferStart - mergeDuration,
|
||||||
transferSize: dataSize
|
transferSize: dataSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,7 +930,7 @@ export default class {
|
|||||||
if (!version) {
|
if (!version) {
|
||||||
// Legacy import. (Version 0.0.0)
|
// Legacy import. (Version 0.0.0)
|
||||||
vm = await this._legacyImportDeltaVmBackup(xapi, {
|
vm = await this._legacyImportDeltaVmBackup(xapi, {
|
||||||
remoteId, handler, filePath, info: delta, sr, mapVdisSrs
|
remoteId, handler, filePath, info: delta, sr, mapVdisSrs,
|
||||||
})
|
})
|
||||||
} else if (versionSatisfies(delta.version, '^1')) {
|
} else if (versionSatisfies(delta.version, '^1')) {
|
||||||
const basePath = dirname(filePath)
|
const basePath = dirname(filePath)
|
||||||
@ -956,7 +956,7 @@ export default class {
|
|||||||
vm = await xapi.importDeltaVm(delta, {
|
vm = await xapi.importDeltaVm(delta, {
|
||||||
disableStartAfterImport: false,
|
disableStartAfterImport: false,
|
||||||
srId: sr !== undefined && sr._xapiId,
|
srId: sr !== undefined && sr._xapiId,
|
||||||
mapVdisSrs
|
mapVdisSrs,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unsupported delta backup version: ${version}`)
|
throw new Error(`Unsupported delta backup version: ${version}`)
|
||||||
@ -982,7 +982,7 @@ export default class {
|
|||||||
|
|
||||||
const sourceStream = await this._xo.getXapi(vm).exportVm(vm._xapiId, {
|
const sourceStream = await this._xo.getXapi(vm).exportVm(vm._xapiId, {
|
||||||
compress,
|
compress,
|
||||||
onlyMetadata: onlyMetadata || false
|
onlyMetadata: onlyMetadata || false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const sizeStream = createSizeStream()
|
const sizeStream = createSizeStream()
|
||||||
@ -994,7 +994,7 @@ export default class {
|
|||||||
await promise
|
await promise
|
||||||
|
|
||||||
return {
|
return {
|
||||||
transferSize: sizeStream.size
|
transferSize: sizeStream.size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,11 +1073,11 @@ export default class {
|
|||||||
|
|
||||||
const copyName = `${vm.name_label}_${tag}_${safeDateFormat(new Date())}`
|
const copyName = `${vm.name_label}_${tag}_${safeDateFormat(new Date())}`
|
||||||
const data = await sourceXapi.remoteCopyVm(vm.$id, targetXapi, sr.$id, {
|
const data = await sourceXapi.remoteCopyVm(vm.$id, targetXapi, sr.$id, {
|
||||||
nameLabel: copyName
|
nameLabel: copyName,
|
||||||
})
|
})
|
||||||
|
|
||||||
targetXapi._updateObjectMapProperty(data.vm, 'blocked_operations', {
|
targetXapi._updateObjectMapProperty(data.vm, 'blocked_operations', {
|
||||||
start: 'Start operation for this vm is blocked, clone it if you want to use it.'
|
start: 'Start operation for this vm is blocked, clone it if you want to use it.',
|
||||||
})
|
})
|
||||||
|
|
||||||
await targetXapi.addTag(data.vm.$id, 'Disaster Recovery')
|
await targetXapi.addTag(data.vm.$id, 'Disaster Recovery')
|
||||||
@ -1088,7 +1088,7 @@ export default class {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
transferDuration: Date.now() - transferStart,
|
transferDuration: Date.now() - transferStart,
|
||||||
transferSize: data.size
|
transferSize: data.size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1097,7 +1097,7 @@ export default class {
|
|||||||
_mountVhd (remoteId, vhdPath) {
|
_mountVhd (remoteId, vhdPath) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
this._xo.getRemoteHandler(remoteId),
|
this._xo.getRemoteHandler(remoteId),
|
||||||
tmpDir()
|
tmpDir(),
|
||||||
]).then(([ handler, mountDir ]) => {
|
]).then(([ handler, mountDir ]) => {
|
||||||
if (!handler._getRealPath) {
|
if (!handler._getRealPath) {
|
||||||
throw new Error(`this remote is not supported`)
|
throw new Error(`this remote is not supported`)
|
||||||
@ -1141,7 +1141,7 @@ export default class {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
path: `${mountDir}/vhdi${max}`,
|
path: `${mountDir}/vhdi${max}`,
|
||||||
unmount: once(() => execa('fusermount', [ '-uz', mountDir ]))
|
unmount: once(() => execa('fusermount', [ '-uz', mountDir ])),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -1152,7 +1152,7 @@ export default class {
|
|||||||
return this._mountVhd(remoteId, vhdPath).then(device =>
|
return this._mountVhd(remoteId, vhdPath).then(device =>
|
||||||
mountPartition2(device, partitionId).then(partition => ({
|
mountPartition2(device, partitionId).then(partition => ({
|
||||||
...partition,
|
...partition,
|
||||||
unmount: () => partition.unmount().then(device.unmount)
|
unmount: () => partition.unmount().then(device.unmount),
|
||||||
})).catch(error => device.unmount().then(() => {
|
})).catch(error => device.unmount().then(() => {
|
||||||
throw error
|
throw error
|
||||||
}))
|
}))
|
||||||
@ -1165,7 +1165,7 @@ export default class {
|
|||||||
$defer(device.unmount)
|
$defer(device.unmount)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
partitions: await listPartitions2(device)
|
partitions: await listPartitions2(device),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ const runHook = (app, hook) => {
|
|||||||
onError: error => console.error(
|
onError: error => console.error(
|
||||||
`[WARN] hook ${hook} failure:`,
|
`[WARN] hook ${hook} failure:`,
|
||||||
(error != null && error.stack) || error
|
(error != null && error.stack) || error
|
||||||
)
|
),
|
||||||
}, hook)
|
}, hook)
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
debug(`${hook} finished`)
|
debug(`${hook} finished`)
|
||||||
@ -72,5 +72,5 @@ export default {
|
|||||||
// Run *stop* async listeners.
|
// Run *stop* async listeners.
|
||||||
//
|
//
|
||||||
// They close connections, unmount file systems, save states, etc.
|
// They close connections, unmount file systems, save states, etc.
|
||||||
stop: makeSingletonHook('stop', 'stopped')
|
stop: makeSingletonHook('stop', 'stopped'),
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import hrp from 'http-request-plus'
|
|||||||
import ProxyAgent from 'proxy-agent'
|
import ProxyAgent from 'proxy-agent'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
firstDefined
|
firstDefined,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
export default class Http {
|
export default class Http {
|
||||||
@ -10,14 +10,14 @@ export default class Http {
|
|||||||
httpProxy = firstDefined(
|
httpProxy = firstDefined(
|
||||||
process.env.http_proxy,
|
process.env.http_proxy,
|
||||||
process.env.HTTP_PROXY
|
process.env.HTTP_PROXY
|
||||||
)
|
),
|
||||||
}) {
|
}) {
|
||||||
this._proxy = httpProxy && new ProxyAgent(httpProxy)
|
this._proxy = httpProxy && new ProxyAgent(httpProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpRequest (...args) {
|
httpRequest (...args) {
|
||||||
return hrp({
|
return hrp({
|
||||||
agent: this._proxy
|
agent: this._proxy,
|
||||||
}, ...args)
|
}, ...args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
lightSet,
|
lightSet,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
streamToArray,
|
streamToArray,
|
||||||
throwFn
|
throwFn,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -31,13 +31,13 @@ const normalize = ({
|
|||||||
id = throwFn('id is a required field'),
|
id = throwFn('id is a required field'),
|
||||||
name = '',
|
name = '',
|
||||||
networks,
|
networks,
|
||||||
resourceSets
|
resourceSets,
|
||||||
}) => ({
|
}) => ({
|
||||||
addresses,
|
addresses,
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
networks,
|
networks,
|
||||||
resourceSets
|
resourceSets,
|
||||||
})
|
})
|
||||||
|
|
||||||
const _isAddressInIpPool = (address, network, ipPool) => (
|
const _isAddressInIpPool = (address, network, ipPool) => (
|
||||||
@ -71,7 +71,7 @@ export default class IpPools {
|
|||||||
addresses,
|
addresses,
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
networks
|
networks,
|
||||||
})
|
})
|
||||||
|
|
||||||
return id
|
return id
|
||||||
@ -98,7 +98,7 @@ export default class IpPools {
|
|||||||
_getAllIpPools (filter) {
|
_getAllIpPools (filter) {
|
||||||
return streamToArray(this._store.createValueStream(), {
|
return streamToArray(this._store.createValueStream(), {
|
||||||
filter,
|
filter,
|
||||||
mapper: normalize
|
mapper: normalize,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +161,8 @@ export default class IpPools {
|
|||||||
const saveIpPools = () => Promise.all(mapToArray(updatedIpPools, ipPool => this._save(ipPool)))
|
const saveIpPools = () => Promise.all(mapToArray(updatedIpPools, ipPool => this._save(ipPool)))
|
||||||
return resourseSetId
|
return resourseSetId
|
||||||
? this._xo.allocateLimitsInResourceSet(limits, resourseSetId).then(
|
? this._xo.allocateLimitsInResourceSet(limits, resourseSetId).then(
|
||||||
saveIpPools
|
saveIpPools
|
||||||
)
|
)
|
||||||
: saveIpPools()
|
: saveIpPools()
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
@ -243,7 +243,7 @@ export default class IpPools {
|
|||||||
|
|
||||||
return getXapi(vif).editVif(vif._xapiId, {
|
return getXapi(vif).editVif(vif._xapiId, {
|
||||||
ipv4Allowed: allowedIpv4Addresses,
|
ipv4Allowed: allowedIpv4Addresses,
|
||||||
ipv6Allowed: allowedIpv6Addresses
|
ipv6Allowed: allowedIpv6Addresses,
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -252,7 +252,7 @@ export default class IpPools {
|
|||||||
addresses,
|
addresses,
|
||||||
name,
|
name,
|
||||||
networks,
|
networks,
|
||||||
resourceSets
|
resourceSets,
|
||||||
}) {
|
}) {
|
||||||
const ipPool = await this.getIpPool(id)
|
const ipPool = await this.getIpPool(id)
|
||||||
const previousAddresses = { ...ipPool.addresses }
|
const previousAddresses = { ...ipPool.addresses }
|
||||||
|
@ -14,7 +14,7 @@ export default class Jobs {
|
|||||||
const jobsDb = this._jobs = new JobsDb({
|
const jobsDb = this._jobs = new JobsDb({
|
||||||
connection: xo._redis,
|
connection: xo._redis,
|
||||||
prefix: 'xo:job',
|
prefix: 'xo:job',
|
||||||
indexes: ['user_id', 'key']
|
indexes: ['user_id', 'key'],
|
||||||
})
|
})
|
||||||
this._runningJobs = Object.create(null)
|
this._runningJobs = Object.create(null)
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ export default class Logs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const stream = db.createKeyStream({
|
const stream = db.createKeyStream({
|
||||||
reverse: true
|
reverse: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const deleteEntry = key => {
|
const deleteEntry = key => {
|
||||||
|
@ -9,7 +9,7 @@ const LEVELS = [
|
|||||||
'warning',
|
'warning',
|
||||||
'notice',
|
'notice',
|
||||||
'informational',
|
'informational',
|
||||||
'debug'
|
'debug',
|
||||||
]
|
]
|
||||||
|
|
||||||
// Create high level log methods.
|
// Create high level log methods.
|
||||||
@ -17,6 +17,6 @@ for (const level of LEVELS) {
|
|||||||
Object.defineProperty(AbstractLogger.prototype, level, {
|
Object.defineProperty(AbstractLogger.prototype, level, {
|
||||||
value (message, data) {
|
value (message, data) {
|
||||||
return this._add(level, message, data)
|
return this._add(level, message, data)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ export default class LevelDbLogger extends AbstractLogger {
|
|||||||
message,
|
message,
|
||||||
data,
|
data,
|
||||||
namespace: this._namespace,
|
namespace: this._namespace,
|
||||||
time
|
time,
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = generateUniqueKey(time)
|
const key = generateUniqueKey(time)
|
||||||
|
@ -3,12 +3,12 @@ import Ajv from 'ajv'
|
|||||||
import { PluginsMetadata } from '../models/plugin-metadata'
|
import { PluginsMetadata } from '../models/plugin-metadata'
|
||||||
import {
|
import {
|
||||||
invalidParameters,
|
invalidParameters,
|
||||||
noSuchObject
|
noSuchObject,
|
||||||
} from 'xo-common/api-errors'
|
} from 'xo-common/api-errors'
|
||||||
import {
|
import {
|
||||||
createRawObject,
|
createRawObject,
|
||||||
isFunction,
|
isFunction,
|
||||||
mapToArray
|
mapToArray,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -16,13 +16,13 @@ import {
|
|||||||
export default class {
|
export default class {
|
||||||
constructor (xo) {
|
constructor (xo) {
|
||||||
this._ajv = new Ajv({
|
this._ajv = new Ajv({
|
||||||
useDefaults: true
|
useDefaults: true,
|
||||||
})
|
})
|
||||||
this._plugins = createRawObject()
|
this._plugins = createRawObject()
|
||||||
|
|
||||||
this._pluginsMetadata = new PluginsMetadata({
|
this._pluginsMetadata = new PluginsMetadata({
|
||||||
connection: xo._redis,
|
connection: xo._redis,
|
||||||
prefix: 'xo:plugin-metadata'
|
prefix: 'xo:plugin-metadata',
|
||||||
})
|
})
|
||||||
|
|
||||||
xo.on('start', () => {
|
xo.on('start', () => {
|
||||||
@ -71,7 +71,7 @@ export default class {
|
|||||||
testable: isFunction(instance.test),
|
testable: isFunction(instance.test),
|
||||||
testSchema,
|
testSchema,
|
||||||
unloadable: isFunction(instance.unload),
|
unloadable: isFunction(instance.unload),
|
||||||
version
|
version,
|
||||||
}
|
}
|
||||||
|
|
||||||
const metadata = await this._getPluginMetadata(id)
|
const metadata = await this._getPluginMetadata(id)
|
||||||
@ -80,13 +80,13 @@ export default class {
|
|||||||
if (metadata) {
|
if (metadata) {
|
||||||
({
|
({
|
||||||
autoload,
|
autoload,
|
||||||
configuration
|
configuration,
|
||||||
} = metadata)
|
} = metadata)
|
||||||
} else {
|
} else {
|
||||||
console.log(`[NOTICE] register plugin ${name} for the first time`)
|
console.log(`[NOTICE] register plugin ${name} for the first time`)
|
||||||
await this._pluginsMetadata.save({
|
await this._pluginsMetadata.save({
|
||||||
id,
|
id,
|
||||||
autoload
|
autoload,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,11 +113,11 @@ export default class {
|
|||||||
testable,
|
testable,
|
||||||
testSchema,
|
testSchema,
|
||||||
unloadable,
|
unloadable,
|
||||||
version
|
version,
|
||||||
} = this._getRawPlugin(id)
|
} = this._getRawPlugin(id)
|
||||||
const {
|
const {
|
||||||
autoload,
|
autoload,
|
||||||
configuration
|
configuration,
|
||||||
} = (await this._getPluginMetadata(id)) || {}
|
} = (await this._getPluginMetadata(id)) || {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -132,7 +132,7 @@ export default class {
|
|||||||
configurationPresets,
|
configurationPresets,
|
||||||
configurationSchema,
|
configurationSchema,
|
||||||
testable,
|
testable,
|
||||||
testSchema
|
testSchema,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ export default class {
|
|||||||
// Shallow copy of the configuration object to avoid most of the
|
// Shallow copy of the configuration object to avoid most of the
|
||||||
// errors when the plugin is altering the configuration object
|
// errors when the plugin is altering the configuration object
|
||||||
// which is handed over to it.
|
// which is handed over to it.
|
||||||
...configuration
|
...configuration,
|
||||||
})
|
})
|
||||||
plugin.configured = true
|
plugin.configured = true
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ export default class {
|
|||||||
if (data == null) {
|
if (data == null) {
|
||||||
throw invalidParameters([{
|
throw invalidParameters([{
|
||||||
field: 'data',
|
field: 'data',
|
||||||
message: 'is the wrong type'
|
message: 'is the wrong type',
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,10 @@ import RemoteHandlerNfs from '../remote-handlers/nfs'
|
|||||||
import RemoteHandlerSmb from '../remote-handlers/smb'
|
import RemoteHandlerSmb from '../remote-handlers/smb'
|
||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
mapToArray
|
mapToArray,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import {
|
import {
|
||||||
Remotes
|
Remotes,
|
||||||
} from '../models/remote'
|
} from '../models/remote'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -18,7 +18,7 @@ export default class {
|
|||||||
this._remotes = new Remotes({
|
this._remotes = new Remotes({
|
||||||
connection: xo._redis,
|
connection: xo._redis,
|
||||||
prefix: 'xo:remote',
|
prefix: 'xo:remote',
|
||||||
indexes: ['enabled']
|
indexes: ['enabled'],
|
||||||
})
|
})
|
||||||
|
|
||||||
xo.on('clean', () => this._remotes.rebuildIndexes())
|
xo.on('clean', () => this._remotes.rebuildIndexes())
|
||||||
@ -48,7 +48,7 @@ export default class {
|
|||||||
const HANDLERS = {
|
const HANDLERS = {
|
||||||
file: RemoteHandlerLocal,
|
file: RemoteHandlerLocal,
|
||||||
smb: RemoteHandlerSmb,
|
smb: RemoteHandlerSmb,
|
||||||
nfs: RemoteHandlerNfs
|
nfs: RemoteHandlerNfs,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: should be done in xo-remote-parser.
|
// FIXME: should be done in xo-remote-parser.
|
||||||
@ -84,7 +84,7 @@ export default class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createRemote ({name, url}) {
|
async createRemote ({name, url}) {
|
||||||
let remote = await this._remotes.create(name, url)
|
const remote = await this._remotes.create(name, url)
|
||||||
return /* await */ this.updateRemote(remote.get('id'), {enabled: true})
|
return /* await */ this.updateRemote(remote.get('id'), {enabled: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ export default class {
|
|||||||
// TODO: Should it be private?
|
// TODO: Should it be private?
|
||||||
async forgetAllRemotes () {
|
async forgetAllRemotes () {
|
||||||
const remotes = await this.getAllRemotes()
|
const remotes = await this.getAllRemotes()
|
||||||
for (let remote of remotes) {
|
for (const remote of remotes) {
|
||||||
try {
|
try {
|
||||||
(await this.getRemoteHandler(remote, true)).forget()
|
(await this.getRemoteHandler(remote, true)).forget()
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
@ -5,7 +5,7 @@ import some from 'lodash/some'
|
|||||||
import synchronized from 'decorator-synchronized'
|
import synchronized from 'decorator-synchronized'
|
||||||
import {
|
import {
|
||||||
noSuchObject,
|
noSuchObject,
|
||||||
unauthorized
|
unauthorized,
|
||||||
} from 'xo-common/api-errors'
|
} from 'xo-common/api-errors'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -15,7 +15,7 @@ import {
|
|||||||
lightSet,
|
lightSet,
|
||||||
map,
|
map,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
streamToArray
|
streamToArray,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -25,7 +25,7 @@ const VM_RESOURCES = {
|
|||||||
disk: true,
|
disk: true,
|
||||||
disks: true,
|
disks: true,
|
||||||
memory: true,
|
memory: true,
|
||||||
vms: true
|
vms: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
const computeVmResourcesUsage = vm => {
|
const computeVmResourcesUsage = vm => {
|
||||||
@ -51,7 +51,7 @@ const computeVmResourcesUsage = vm => {
|
|||||||
disk,
|
disk,
|
||||||
disks,
|
disks,
|
||||||
memory: vm.memory_dynamic_max,
|
memory: vm.memory_dynamic_max,
|
||||||
vms: 1
|
vms: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,13 +63,13 @@ const normalize = set => ({
|
|||||||
? limit
|
? limit
|
||||||
: {
|
: {
|
||||||
available: limit,
|
available: limit,
|
||||||
total: limit
|
total: limit,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
: {},
|
: {},
|
||||||
name: set.name || '',
|
name: set.name || '',
|
||||||
objects: set.objects || [],
|
objects: set.objects || [],
|
||||||
subjects: set.subjects || []
|
subjects: set.subjects || [],
|
||||||
})
|
})
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -115,11 +115,11 @@ export default class {
|
|||||||
// (itself or its groups).
|
// (itself or its groups).
|
||||||
!some(set.subjects, lightSet(user.groups).add(user.id).has)
|
!some(set.subjects, lightSet(user.groups).add(user.id).has)
|
||||||
) || (
|
) || (
|
||||||
objectIds &&
|
objectIds &&
|
||||||
|
|
||||||
// The set does not contains ALL objects.
|
// The set does not contains ALL objects.
|
||||||
!every(objectIds, lightSet(set.objects).has)
|
!every(objectIds, lightSet(set.objects).has)
|
||||||
)) {
|
)) {
|
||||||
throw unauthorized()
|
throw unauthorized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ export default class {
|
|||||||
name,
|
name,
|
||||||
objects,
|
objects,
|
||||||
subjects,
|
subjects,
|
||||||
limits
|
limits,
|
||||||
})
|
})
|
||||||
|
|
||||||
await this._store.put(id, set)
|
await this._store.put(id, set)
|
||||||
@ -160,7 +160,7 @@ export default class {
|
|||||||
subjects = undefined,
|
subjects = undefined,
|
||||||
objects = undefined,
|
objects = undefined,
|
||||||
limits = undefined,
|
limits = undefined,
|
||||||
ipPools = undefined
|
ipPools = undefined,
|
||||||
}) {
|
}) {
|
||||||
const set = await this.getResourceSet(id)
|
const set = await this.getResourceSet(id)
|
||||||
if (name) {
|
if (name) {
|
||||||
@ -179,7 +179,7 @@ export default class {
|
|||||||
if (!previous) {
|
if (!previous) {
|
||||||
return {
|
return {
|
||||||
available: quantity,
|
available: quantity,
|
||||||
total: quantity
|
total: quantity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ export default class {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
available: available - total + quantity,
|
available: available - total + quantity,
|
||||||
total: quantity
|
total: quantity,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ export default class {
|
|||||||
|
|
||||||
return streamToArray(this._store.createValueStream(), {
|
return streamToArray(this._store.createValueStream(), {
|
||||||
filter,
|
filter,
|
||||||
mapper: normalize
|
mapper: normalize,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { Schedules } from '../models/schedule'
|
|||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
mapToArray,
|
mapToArray,
|
||||||
scheduleFn
|
scheduleFn,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -40,7 +40,7 @@ export default class {
|
|||||||
const schedules = this._redisSchedules = new Schedules({
|
const schedules = this._redisSchedules = new Schedules({
|
||||||
connection: xo._redis,
|
connection: xo._redis,
|
||||||
prefix: 'xo:schedule',
|
prefix: 'xo:schedule',
|
||||||
indexes: ['user_id', 'job']
|
indexes: ['user_id', 'job'],
|
||||||
})
|
})
|
||||||
this._scheduleTable = undefined
|
this._scheduleTable = undefined
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import { ensureDir } from 'fs-extra'
|
|||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
isFunction,
|
isFunction,
|
||||||
promisify
|
promisify,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -19,7 +19,7 @@ const _levelHas = function has (key, cb) {
|
|||||||
error.notFound
|
error.notFound
|
||||||
? cb(null, false)
|
? cb(null, false)
|
||||||
: cb(error)
|
: cb(error)
|
||||||
)
|
)
|
||||||
: cb(null, true)
|
: cb(null, true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ export default class {
|
|||||||
const dir = `${xo._config.datadir}/leveldb`
|
const dir = `${xo._config.datadir}/leveldb`
|
||||||
this._db = ensureDir(dir).then(() => {
|
this._db = ensureDir(dir).then(() => {
|
||||||
return sublevel(levelup(dir, {
|
return sublevel(levelup(dir, {
|
||||||
valueEncoding: 'json'
|
valueEncoding: 'json',
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,24 +3,24 @@ import { ignoreErrors } from 'promise-toolbox'
|
|||||||
import {
|
import {
|
||||||
hash,
|
hash,
|
||||||
needsRehash,
|
needsRehash,
|
||||||
verify
|
verify,
|
||||||
} from 'hashy'
|
} from 'hashy'
|
||||||
import {
|
import {
|
||||||
invalidCredentials,
|
invalidCredentials,
|
||||||
noSuchObject
|
noSuchObject,
|
||||||
} from 'xo-common/api-errors'
|
} from 'xo-common/api-errors'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Groups
|
Groups,
|
||||||
} from '../models/group'
|
} from '../models/group'
|
||||||
import {
|
import {
|
||||||
Users
|
Users,
|
||||||
} from '../models/user'
|
} from '../models/user'
|
||||||
import {
|
import {
|
||||||
forEach,
|
forEach,
|
||||||
isEmpty,
|
isEmpty,
|
||||||
lightSet,
|
lightSet,
|
||||||
mapToArray
|
mapToArray,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -40,17 +40,17 @@ export default class {
|
|||||||
|
|
||||||
const groupsDb = this._groups = new Groups({
|
const groupsDb = this._groups = new Groups({
|
||||||
connection: redis,
|
connection: redis,
|
||||||
prefix: 'xo:group'
|
prefix: 'xo:group',
|
||||||
})
|
})
|
||||||
const usersDb = this._users = new Users({
|
const usersDb = this._users = new Users({
|
||||||
connection: redis,
|
connection: redis,
|
||||||
prefix: 'xo:user',
|
prefix: 'xo:user',
|
||||||
indexes: ['email']
|
indexes: ['email'],
|
||||||
})
|
})
|
||||||
|
|
||||||
xo.on('clean', () => Promise.all([
|
xo.on('clean', () => Promise.all([
|
||||||
groupsDb.rebuildIndexes(),
|
groupsDb.rebuildIndexes(),
|
||||||
usersDb.rebuildIndexes()
|
usersDb.rebuildIndexes(),
|
||||||
]))
|
]))
|
||||||
xo.on('start', async () => {
|
xo.on('start', async () => {
|
||||||
xo.addConfigManager('groups',
|
xo.addConfigManager('groups',
|
||||||
@ -135,7 +135,7 @@ export default class {
|
|||||||
name = email,
|
name = email,
|
||||||
password,
|
password,
|
||||||
permission,
|
permission,
|
||||||
preferences
|
preferences,
|
||||||
}) {
|
}) {
|
||||||
const user = await this.getUser(id)
|
const user = await this.getUser(id)
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ export default class {
|
|||||||
|
|
||||||
// Get or create a user associated with an auth provider.
|
// Get or create a user associated with an auth provider.
|
||||||
async registerUser (provider, name) {
|
async registerUser (provider, name) {
|
||||||
let user = await this.getUserByName(name, true)
|
const user = await this.getUserByName(name, true)
|
||||||
if (user) {
|
if (user) {
|
||||||
if (user._provider !== provider) {
|
if (user._provider !== provider) {
|
||||||
throw new Error(`the name ${name} is already taken`)
|
throw new Error(`the name ${name} is already taken`)
|
||||||
@ -225,7 +225,7 @@ export default class {
|
|||||||
|
|
||||||
return /* await */ this.createUser({
|
return /* await */ this.createUser({
|
||||||
name,
|
name,
|
||||||
_provider: provider
|
_provider: provider,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ export default class {
|
|||||||
async addUserToGroup (userId, groupId) {
|
async addUserToGroup (userId, groupId) {
|
||||||
const [user, group] = await Promise.all([
|
const [user, group] = await Promise.all([
|
||||||
this.getUser(userId),
|
this.getUser(userId),
|
||||||
this.getGroup(groupId)
|
this.getGroup(groupId),
|
||||||
])
|
])
|
||||||
|
|
||||||
user.groups = addToArraySet(user.groups, groupId)
|
user.groups = addToArraySet(user.groups, groupId)
|
||||||
@ -314,7 +314,7 @@ export default class {
|
|||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._users.save(user),
|
this._users.save(user),
|
||||||
this._groups.save(group)
|
this._groups.save(group),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,12 +331,12 @@ export default class {
|
|||||||
async removeUserFromGroup (userId, groupId) {
|
async removeUserFromGroup (userId, groupId) {
|
||||||
const [user, group] = await Promise.all([
|
const [user, group] = await Promise.all([
|
||||||
this.getUser(userId),
|
this.getUser(userId),
|
||||||
this.getGroup(groupId)
|
this.getGroup(groupId),
|
||||||
])
|
])
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._removeUserFromGroup(userId, group),
|
this._removeUserFromGroup(userId, group),
|
||||||
this._removeGroupFromUser(groupId, user)
|
this._removeGroupFromUser(groupId, user),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,7 +357,7 @@ export default class {
|
|||||||
const getUser = ::this.getUser
|
const getUser = ::this.getUser
|
||||||
const [newUsers, oldUsers] = await Promise.all([
|
const [newUsers, oldUsers] = await Promise.all([
|
||||||
Promise.all(newUsersIds.map(getUser)),
|
Promise.all(newUsersIds.map(getUser)),
|
||||||
Promise.all(oldUsersIds.map(getUser))
|
Promise.all(oldUsersIds.map(getUser)),
|
||||||
])
|
])
|
||||||
|
|
||||||
forEach(newUsers, user => {
|
forEach(newUsers, user => {
|
||||||
@ -373,7 +373,7 @@ export default class {
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
Promise.all(mapToArray(newUsers, saveUser)),
|
Promise.all(mapToArray(newUsers, saveUser)),
|
||||||
Promise.all(mapToArray(oldUsers, saveUser)),
|
Promise.all(mapToArray(oldUsers, saveUser)),
|
||||||
this._groups.save(group)
|
this._groups.save(group),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@ import {
|
|||||||
isEmpty,
|
isEmpty,
|
||||||
isString,
|
isString,
|
||||||
popProperty,
|
popProperty,
|
||||||
serializeError
|
serializeError,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import {
|
import {
|
||||||
Servers
|
Servers,
|
||||||
} from '../models/server'
|
} from '../models/server'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -25,7 +25,7 @@ export default class {
|
|||||||
const serversDb = this._servers = new Servers({
|
const serversDb = this._servers = new Servers({
|
||||||
connection: xo._redis,
|
connection: xo._redis,
|
||||||
prefix: 'xo:server',
|
prefix: 'xo:server',
|
||||||
indexes: ['host']
|
indexes: ['host'],
|
||||||
})
|
})
|
||||||
this._stats = new XapiStats()
|
this._stats = new XapiStats()
|
||||||
this._xapis = createRawObject()
|
this._xapis = createRawObject()
|
||||||
@ -41,7 +41,7 @@ export default class {
|
|||||||
|
|
||||||
// Connects to existing servers.
|
// Connects to existing servers.
|
||||||
const servers = await serversDb.get()
|
const servers = await serversDb.get()
|
||||||
for (let server of servers) {
|
for (const server of servers) {
|
||||||
if (server.enabled) {
|
if (server.enabled) {
|
||||||
this.connectXenServer(server.id).catch(error => {
|
this.connectXenServer(server.id).catch(error => {
|
||||||
console.error(
|
console.error(
|
||||||
@ -62,7 +62,7 @@ export default class {
|
|||||||
label,
|
label,
|
||||||
password,
|
password,
|
||||||
readOnly,
|
readOnly,
|
||||||
username
|
username,
|
||||||
}) {
|
}) {
|
||||||
// FIXME: We are storing passwords which is bad!
|
// FIXME: We are storing passwords which is bad!
|
||||||
// Could we use tokens instead?
|
// Could we use tokens instead?
|
||||||
@ -74,7 +74,7 @@ export default class {
|
|||||||
label: label || undefined,
|
label: label || undefined,
|
||||||
password,
|
password,
|
||||||
readOnly: readOnly ? 'true' : undefined,
|
readOnly: readOnly ? 'true' : undefined,
|
||||||
username
|
username,
|
||||||
})
|
})
|
||||||
|
|
||||||
return server.properties
|
return server.properties
|
||||||
@ -96,7 +96,7 @@ export default class {
|
|||||||
label,
|
label,
|
||||||
password,
|
password,
|
||||||
readOnly,
|
readOnly,
|
||||||
username
|
username,
|
||||||
}) {
|
}) {
|
||||||
const server = await this._getXenServer(id)
|
const server = await this._getXenServer(id)
|
||||||
const xapi = this._xapis[id]
|
const xapi = this._xapis[id]
|
||||||
@ -225,10 +225,10 @@ export default class {
|
|||||||
allowUnauthorized: Boolean(server.allowUnauthorized),
|
allowUnauthorized: Boolean(server.allowUnauthorized),
|
||||||
auth: {
|
auth: {
|
||||||
user: server.username,
|
user: server.username,
|
||||||
password: server.password
|
password: server.password,
|
||||||
},
|
},
|
||||||
readOnly: Boolean(server.readOnly),
|
readOnly: Boolean(server.readOnly),
|
||||||
url: server.host
|
url: server.host,
|
||||||
})
|
})
|
||||||
|
|
||||||
xapi.xo = (() => {
|
xapi.xo = (() => {
|
||||||
@ -316,7 +316,7 @@ export default class {
|
|||||||
|
|
||||||
// Register the updated object.
|
// Register the updated object.
|
||||||
addObject(await xapi._waitObject(id))
|
addObject(await xapi._waitObject(id))
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
|
||||||
@ -410,7 +410,7 @@ export default class {
|
|||||||
const sourceXapi = this.getXapi(sourceId)
|
const sourceXapi = this.getXapi(sourceId)
|
||||||
const {
|
const {
|
||||||
_auth: { user, password },
|
_auth: { user, password },
|
||||||
_url: { hostname }
|
_url: { hostname },
|
||||||
} = this.getXapi(targetId)
|
} = this.getXapi(targetId)
|
||||||
|
|
||||||
// We don't want the events of the source XAPI to interfere with
|
// We don't want the events of the source XAPI to interfere with
|
||||||
|
32
src/xo.js
32
src/xo.js
@ -11,18 +11,18 @@ import {
|
|||||||
isString,
|
isString,
|
||||||
iteratee,
|
iteratee,
|
||||||
map as mapToArray,
|
map as mapToArray,
|
||||||
stubTrue
|
stubTrue,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
|
|
||||||
import mixins from './xo-mixins'
|
import mixins from './xo-mixins' // eslint-disable-line node/no-missing-import
|
||||||
import Connection from './connection'
|
import Connection from './connection'
|
||||||
import {
|
import {
|
||||||
mixin
|
mixin,
|
||||||
} from './decorators'
|
} from './decorators'
|
||||||
import {
|
import {
|
||||||
createRawObject,
|
createRawObject,
|
||||||
generateToken,
|
generateToken,
|
||||||
noop
|
noop,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
@ -49,12 +49,12 @@ export default class Xo extends EventEmitter {
|
|||||||
// Connects to Redis.
|
// Connects to Redis.
|
||||||
{
|
{
|
||||||
const {
|
const {
|
||||||
renameCommands: rename_commands,
|
renameCommands,
|
||||||
socket: path,
|
socket: path,
|
||||||
uri: url
|
uri: url,
|
||||||
} = config.redis || {}
|
} = config.redis || {}
|
||||||
|
|
||||||
this._redis = createRedisClient({ path, rename_commands, url })
|
this._redis = createRedisClient({ path, rename_commands: renameCommands, url })
|
||||||
}
|
}
|
||||||
|
|
||||||
this.on('start', () => this._watchObjects())
|
this.on('start', () => this._watchObjects())
|
||||||
@ -67,8 +67,8 @@ export default class Xo extends EventEmitter {
|
|||||||
const {
|
const {
|
||||||
all,
|
all,
|
||||||
indexes: {
|
indexes: {
|
||||||
byRef
|
byRef,
|
||||||
}
|
},
|
||||||
} = this._objects
|
} = this._objects
|
||||||
|
|
||||||
const obj = all[key] || byRef[key]
|
const obj = all[key] || byRef[key]
|
||||||
@ -180,7 +180,7 @@ export default class Xo extends EventEmitter {
|
|||||||
|
|
||||||
watchers[url] = {
|
watchers[url] = {
|
||||||
data,
|
data,
|
||||||
fn
|
fn,
|
||||||
}
|
}
|
||||||
|
|
||||||
return url
|
return url
|
||||||
@ -188,7 +188,7 @@ export default class Xo extends EventEmitter {
|
|||||||
|
|
||||||
async registerHttpRequestHandler (url, fn, {
|
async registerHttpRequestHandler (url, fn, {
|
||||||
data = undefined,
|
data = undefined,
|
||||||
persistent = true
|
persistent = true,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const {_httpRequestWatchers: watchers} = this
|
const {_httpRequestWatchers: watchers} = this
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ export default class Xo extends EventEmitter {
|
|||||||
watchers[url] = {
|
watchers[url] = {
|
||||||
data,
|
data,
|
||||||
fn,
|
fn,
|
||||||
persistent
|
persistent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ export default class Xo extends EventEmitter {
|
|||||||
|
|
||||||
Object.defineProperty(this, name, {
|
Object.defineProperty(this, name, {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
value
|
value,
|
||||||
})
|
})
|
||||||
|
|
||||||
let unset = () => {
|
let unset = () => {
|
||||||
@ -260,7 +260,7 @@ export default class Xo extends EventEmitter {
|
|||||||
_watchObjects () {
|
_watchObjects () {
|
||||||
const {
|
const {
|
||||||
_connections: connections,
|
_connections: connections,
|
||||||
_objects: objects
|
_objects: objects,
|
||||||
} = this
|
} = this
|
||||||
|
|
||||||
let entered, exited
|
let entered, exited
|
||||||
@ -289,11 +289,11 @@ export default class Xo extends EventEmitter {
|
|||||||
objects.on('finish', () => {
|
objects.on('finish', () => {
|
||||||
const enteredMessage = !isEmpty(entered) && {
|
const enteredMessage = !isEmpty(entered) && {
|
||||||
type: 'enter',
|
type: 'enter',
|
||||||
items: entered
|
items: entered,
|
||||||
}
|
}
|
||||||
const exitedMessage = !isEmpty(exited) && {
|
const exitedMessage = !isEmpty(exited) && {
|
||||||
type: 'exit',
|
type: 'exit',
|
||||||
items: exited
|
items: exited,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enteredMessage && !exitedMessage) {
|
if (!enteredMessage && !exitedMessage) {
|
||||||
|
553
yarn.lock
553
yarn.lock
@ -168,11 +168,11 @@ agent-base@^4.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
es6-promisify "^5.0.0"
|
es6-promisify "^5.0.0"
|
||||||
|
|
||||||
ajv-keywords@^1.0.0:
|
ajv-keywords@^2.1.0:
|
||||||
version "1.5.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
|
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
|
||||||
|
|
||||||
ajv@^4.7.0, ajv@^4.9.1:
|
ajv@^4.9.1:
|
||||||
version "4.11.8"
|
version "4.11.8"
|
||||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -188,6 +188,15 @@ ajv@^5.1.0, ajv@^5.3.0:
|
|||||||
fast-json-stable-stringify "^2.0.0"
|
fast-json-stable-stringify "^2.0.0"
|
||||||
json-schema-traverse "^0.3.0"
|
json-schema-traverse "^0.3.0"
|
||||||
|
|
||||||
|
ajv@^5.2.3:
|
||||||
|
version "5.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.1.tgz#b38bb8876d9e86bee994956a04e721e88b248eb2"
|
||||||
|
dependencies:
|
||||||
|
co "^4.6.0"
|
||||||
|
fast-deep-equal "^1.0.0"
|
||||||
|
fast-json-stable-stringify "^2.0.0"
|
||||||
|
json-schema-traverse "^0.3.0"
|
||||||
|
|
||||||
align-text@^0.1.1, align-text@^0.1.3:
|
align-text@^0.1.1, align-text@^0.1.3:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
|
resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
|
||||||
@ -200,10 +209,6 @@ amdefine@>=0.0.4:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||||
|
|
||||||
ansi-escapes@^1.1.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
|
|
||||||
|
|
||||||
ansi-escapes@^3.0.0:
|
ansi-escapes@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
|
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
|
||||||
@ -388,13 +393,6 @@ array-unique@^0.3.2:
|
|||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
||||||
|
|
||||||
array.prototype.find@^2.0.1:
|
|
||||||
version "2.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.4.tgz#556a5c5362c08648323ddaeb9de9d14bc1864c90"
|
|
||||||
dependencies:
|
|
||||||
define-properties "^1.1.2"
|
|
||||||
es-abstract "^1.7.0"
|
|
||||||
|
|
||||||
arrify@^1.0.0, arrify@^1.0.1:
|
arrify@^1.0.0, arrify@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
|
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
|
||||||
@ -480,7 +478,7 @@ aws4@^1.2.1, aws4@^1.6.0:
|
|||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
|
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
|
||||||
|
|
||||||
babel-code-frame@^6.16.0, babel-code-frame@^6.26.0:
|
babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
|
||||||
version "6.26.0"
|
version "6.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1495,7 +1493,7 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
|
|||||||
strip-ansi "^3.0.0"
|
strip-ansi "^3.0.0"
|
||||||
supports-color "^2.0.0"
|
supports-color "^2.0.0"
|
||||||
|
|
||||||
chalk@^2.0.0, chalk@^2.0.1:
|
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1509,6 +1507,10 @@ character-parser@^2.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-regex "^1.0.3"
|
is-regex "^1.0.3"
|
||||||
|
|
||||||
|
chardet@^0.4.0:
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
|
||||||
|
|
||||||
child-process-promise@^2.0.3:
|
child-process-promise@^2.0.3:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-2.2.1.tgz#4730a11ef610fad450b8f223c79d31d7bdad8074"
|
resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-2.2.1.tgz#4730a11ef610fad450b8f223c79d31d7bdad8074"
|
||||||
@ -1561,11 +1563,11 @@ clean-css@^3.3.0:
|
|||||||
commander "2.8.x"
|
commander "2.8.x"
|
||||||
source-map "0.4.x"
|
source-map "0.4.x"
|
||||||
|
|
||||||
cli-cursor@^1.0.1:
|
cli-cursor@^2.1.0:
|
||||||
version "1.0.2"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
|
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
|
||||||
dependencies:
|
dependencies:
|
||||||
restore-cursor "^1.0.1"
|
restore-cursor "^2.0.0"
|
||||||
|
|
||||||
cli-width@^2.0.0:
|
cli-width@^2.0.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
@ -1661,7 +1663,7 @@ concat-map@0.0.1:
|
|||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
|
|
||||||
concat-stream@^1.5.2, concat-stream@~1.6.0:
|
concat-stream@^1.6.0, concat-stream@~1.6.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
|
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1776,7 +1778,7 @@ cross-spawn@^4.0.2:
|
|||||||
lru-cache "^4.0.1"
|
lru-cache "^4.0.1"
|
||||||
which "^1.2.9"
|
which "^1.2.9"
|
||||||
|
|
||||||
cross-spawn@^5.0.1:
|
cross-spawn@^5.0.1, cross-spawn@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1861,11 +1863,7 @@ debug-fabulous@>=0.1.1:
|
|||||||
memoizee "0.4.X"
|
memoizee "0.4.X"
|
||||||
object-assign "4.X"
|
object-assign "4.X"
|
||||||
|
|
||||||
debug-log@^1.0.0:
|
debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8:
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f"
|
|
||||||
|
|
||||||
debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8:
|
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1925,13 +1923,6 @@ deferred-leveldown@~2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
abstract-leveldown "~3.0.0"
|
abstract-leveldown "~3.0.0"
|
||||||
|
|
||||||
define-properties@^1.1.2:
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
|
|
||||||
dependencies:
|
|
||||||
foreach "^2.0.5"
|
|
||||||
object-keys "^1.0.8"
|
|
||||||
|
|
||||||
define-property@^0.2.5:
|
define-property@^0.2.5:
|
||||||
version "0.2.5"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
|
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
|
||||||
@ -1956,17 +1947,6 @@ degenerator@^1.0.4:
|
|||||||
escodegen "1.x.x"
|
escodegen "1.x.x"
|
||||||
esprima "3.x.x"
|
esprima "3.x.x"
|
||||||
|
|
||||||
deglob@^2.1.0:
|
|
||||||
version "2.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/deglob/-/deglob-2.1.0.tgz#4d44abe16ef32c779b4972bd141a80325029a14a"
|
|
||||||
dependencies:
|
|
||||||
find-root "^1.0.0"
|
|
||||||
glob "^7.0.5"
|
|
||||||
ignore "^3.0.9"
|
|
||||||
pkg-config "^1.1.0"
|
|
||||||
run-parallel "^1.1.2"
|
|
||||||
uniq "^1.0.1"
|
|
||||||
|
|
||||||
del@^2.0.2:
|
del@^2.0.2:
|
||||||
version "2.2.2"
|
version "2.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
|
resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
|
||||||
@ -2027,19 +2007,18 @@ dns-prefetch-control@0.1.0:
|
|||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz#60ddb457774e178f1f9415f0cabb0e85b0b300b2"
|
resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz#60ddb457774e178f1f9415f0cabb0e85b0b300b2"
|
||||||
|
|
||||||
doctrine@1.5.0, doctrine@^1.2.2:
|
doctrine@1.5.0:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
|
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
|
||||||
dependencies:
|
dependencies:
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
isarray "^1.0.0"
|
isarray "^1.0.0"
|
||||||
|
|
||||||
doctrine@^2.0.0:
|
doctrine@^2.0.2:
|
||||||
version "2.0.0"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63"
|
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.2.tgz#68f96ce8efc56cc42651f1faadb4f175273b0075"
|
||||||
dependencies:
|
dependencies:
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
isarray "^1.0.0"
|
|
||||||
|
|
||||||
doctypes@^1.1.0:
|
doctypes@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
@ -2119,24 +2098,6 @@ error-ex@^1.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
es-abstract@^1.7.0:
|
|
||||||
version "1.9.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.9.0.tgz#690829a07cae36b222e7fd9b75c0d0573eb25227"
|
|
||||||
dependencies:
|
|
||||||
es-to-primitive "^1.1.1"
|
|
||||||
function-bind "^1.1.1"
|
|
||||||
has "^1.0.1"
|
|
||||||
is-callable "^1.1.3"
|
|
||||||
is-regex "^1.0.4"
|
|
||||||
|
|
||||||
es-to-primitive@^1.1.1:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
|
|
||||||
dependencies:
|
|
||||||
is-callable "^1.1.1"
|
|
||||||
is-date-object "^1.0.1"
|
|
||||||
is-symbol "^1.0.1"
|
|
||||||
|
|
||||||
es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2:
|
es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2:
|
||||||
version "0.10.35"
|
version "0.10.35"
|
||||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.35.tgz#18ee858ce6a3c45c7d79e91c15fcca9ec568494f"
|
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.35.tgz#18ee858ce6a3c45c7d79e91c15fcca9ec568494f"
|
||||||
@ -2152,17 +2113,6 @@ es6-iterator@^2.0.1, es6-iterator@~2.0.1:
|
|||||||
es5-ext "^0.10.35"
|
es5-ext "^0.10.35"
|
||||||
es6-symbol "^3.1.1"
|
es6-symbol "^3.1.1"
|
||||||
|
|
||||||
es6-map@^0.1.3:
|
|
||||||
version "0.1.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
|
|
||||||
dependencies:
|
|
||||||
d "1"
|
|
||||||
es5-ext "~0.10.14"
|
|
||||||
es6-iterator "~2.0.1"
|
|
||||||
es6-set "~0.1.5"
|
|
||||||
es6-symbol "~3.1.1"
|
|
||||||
event-emitter "~0.3.5"
|
|
||||||
|
|
||||||
es6-promise@^4.0.3:
|
es6-promise@^4.0.3:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a"
|
||||||
@ -2173,17 +2123,7 @@ es6-promisify@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
es6-promise "^4.0.3"
|
es6-promise "^4.0.3"
|
||||||
|
|
||||||
es6-set@~0.1.5:
|
es6-symbol@^3.1.1, es6-symbol@~3.1.1:
|
||||||
version "0.1.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
|
|
||||||
dependencies:
|
|
||||||
d "1"
|
|
||||||
es5-ext "~0.10.14"
|
|
||||||
es6-iterator "~2.0.1"
|
|
||||||
es6-symbol "3.1.1"
|
|
||||||
event-emitter "~0.3.5"
|
|
||||||
|
|
||||||
es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1:
|
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
|
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -2237,122 +2177,106 @@ escodegen@~1.3.2:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
source-map "~0.1.33"
|
source-map "~0.1.33"
|
||||||
|
|
||||||
escope@^3.6.0:
|
eslint-config-standard@^11.0.0-beta.0:
|
||||||
version "3.6.0"
|
version "11.0.0-beta.0"
|
||||||
resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
|
resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0-beta.0.tgz#f8afe69803d95c685a4b8392b8793188eb03cbb3"
|
||||||
|
|
||||||
|
eslint-import-resolver-node@^0.3.1:
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc"
|
||||||
dependencies:
|
dependencies:
|
||||||
es6-map "^0.1.3"
|
debug "^2.6.8"
|
||||||
es6-weak-map "^2.0.1"
|
resolve "^1.2.0"
|
||||||
esrecurse "^4.1.0"
|
|
||||||
estraverse "^4.1.1"
|
|
||||||
|
|
||||||
eslint-config-standard-jsx@4.0.2:
|
eslint-module-utils@^2.1.1:
|
||||||
version "4.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.2.tgz#009e53c4ddb1e9ee70b4650ffe63a7f39f8836e1"
|
|
||||||
|
|
||||||
eslint-config-standard@10.2.1:
|
|
||||||
version "10.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591"
|
|
||||||
|
|
||||||
eslint-import-resolver-node@^0.2.0:
|
|
||||||
version "0.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c"
|
|
||||||
dependencies:
|
|
||||||
debug "^2.2.0"
|
|
||||||
object-assign "^4.0.1"
|
|
||||||
resolve "^1.1.6"
|
|
||||||
|
|
||||||
eslint-module-utils@^2.0.0:
|
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449"
|
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449"
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^2.6.8"
|
debug "^2.6.8"
|
||||||
pkg-dir "^1.0.0"
|
pkg-dir "^1.0.0"
|
||||||
|
|
||||||
eslint-plugin-import@~2.2.0:
|
eslint-plugin-import@^2.8.0:
|
||||||
version "2.2.0"
|
version "2.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz#fa1b6ef31fcb3c501c09859c1b86f1fc5b986894"
|
||||||
dependencies:
|
dependencies:
|
||||||
builtin-modules "^1.1.1"
|
builtin-modules "^1.1.1"
|
||||||
contains-path "^0.1.0"
|
contains-path "^0.1.0"
|
||||||
debug "^2.2.0"
|
debug "^2.6.8"
|
||||||
doctrine "1.5.0"
|
doctrine "1.5.0"
|
||||||
eslint-import-resolver-node "^0.2.0"
|
eslint-import-resolver-node "^0.3.1"
|
||||||
eslint-module-utils "^2.0.0"
|
eslint-module-utils "^2.1.1"
|
||||||
has "^1.0.1"
|
has "^1.0.1"
|
||||||
lodash.cond "^4.3.0"
|
lodash.cond "^4.3.0"
|
||||||
minimatch "^3.0.3"
|
minimatch "^3.0.3"
|
||||||
pkg-up "^1.0.0"
|
read-pkg-up "^2.0.0"
|
||||||
|
|
||||||
eslint-plugin-node@~4.2.2:
|
eslint-plugin-node@^5.2.1:
|
||||||
version "4.2.3"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz#c04390ab8dbcbb6887174023d6f3a72769e63b97"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz#80df3253c4d7901045ec87fa660a284e32bdca29"
|
||||||
dependencies:
|
dependencies:
|
||||||
ignore "^3.0.11"
|
ignore "^3.3.6"
|
||||||
minimatch "^3.0.2"
|
minimatch "^3.0.4"
|
||||||
object-assign "^4.0.1"
|
resolve "^1.3.3"
|
||||||
resolve "^1.1.7"
|
|
||||||
semver "5.3.0"
|
semver "5.3.0"
|
||||||
|
|
||||||
eslint-plugin-promise@~3.5.0:
|
eslint-plugin-promise@^3.6.0:
|
||||||
version "3.5.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz#54b7658c8f454813dc2a870aff8152ec4969ba75"
|
||||||
|
|
||||||
eslint-plugin-react@~6.10.0:
|
eslint-plugin-standard@^3.0.1:
|
||||||
version "6.10.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz#c5435beb06774e12c7db2f6abaddcbf900cd3f78"
|
|
||||||
dependencies:
|
|
||||||
array.prototype.find "^2.0.1"
|
|
||||||
doctrine "^1.2.2"
|
|
||||||
has "^1.0.1"
|
|
||||||
jsx-ast-utils "^1.3.4"
|
|
||||||
object.assign "^4.0.4"
|
|
||||||
|
|
||||||
eslint-plugin-standard@~3.0.1:
|
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2"
|
||||||
|
|
||||||
eslint@~3.19.0:
|
eslint-scope@^3.7.1:
|
||||||
version "3.19.0"
|
version "3.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
|
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-code-frame "^6.16.0"
|
esrecurse "^4.1.0"
|
||||||
chalk "^1.1.3"
|
estraverse "^4.1.1"
|
||||||
concat-stream "^1.5.2"
|
|
||||||
debug "^2.1.1"
|
eslint@^4.13.1:
|
||||||
doctrine "^2.0.0"
|
version "4.13.1"
|
||||||
escope "^3.6.0"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.13.1.tgz#0055e0014464c7eb7878caf549ef2941992b444f"
|
||||||
espree "^3.4.0"
|
dependencies:
|
||||||
|
ajv "^5.3.0"
|
||||||
|
babel-code-frame "^6.22.0"
|
||||||
|
chalk "^2.1.0"
|
||||||
|
concat-stream "^1.6.0"
|
||||||
|
cross-spawn "^5.1.0"
|
||||||
|
debug "^3.0.1"
|
||||||
|
doctrine "^2.0.2"
|
||||||
|
eslint-scope "^3.7.1"
|
||||||
|
espree "^3.5.2"
|
||||||
esquery "^1.0.0"
|
esquery "^1.0.0"
|
||||||
estraverse "^4.2.0"
|
estraverse "^4.2.0"
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
file-entry-cache "^2.0.0"
|
file-entry-cache "^2.0.0"
|
||||||
glob "^7.0.3"
|
functional-red-black-tree "^1.0.1"
|
||||||
globals "^9.14.0"
|
glob "^7.1.2"
|
||||||
ignore "^3.2.0"
|
globals "^11.0.1"
|
||||||
|
ignore "^3.3.3"
|
||||||
imurmurhash "^0.1.4"
|
imurmurhash "^0.1.4"
|
||||||
inquirer "^0.12.0"
|
inquirer "^3.0.6"
|
||||||
is-my-json-valid "^2.10.0"
|
|
||||||
is-resolvable "^1.0.0"
|
is-resolvable "^1.0.0"
|
||||||
js-yaml "^3.5.1"
|
js-yaml "^3.9.1"
|
||||||
json-stable-stringify "^1.0.0"
|
json-stable-stringify-without-jsonify "^1.0.1"
|
||||||
levn "^0.3.0"
|
levn "^0.3.0"
|
||||||
lodash "^4.0.0"
|
lodash "^4.17.4"
|
||||||
mkdirp "^0.5.0"
|
minimatch "^3.0.2"
|
||||||
|
mkdirp "^0.5.1"
|
||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
optionator "^0.8.2"
|
optionator "^0.8.2"
|
||||||
path-is-inside "^1.0.1"
|
path-is-inside "^1.0.2"
|
||||||
pluralize "^1.2.1"
|
pluralize "^7.0.0"
|
||||||
progress "^1.1.8"
|
progress "^2.0.0"
|
||||||
require-uncached "^1.0.2"
|
require-uncached "^1.0.3"
|
||||||
shelljs "^0.7.5"
|
semver "^5.3.0"
|
||||||
strip-bom "^3.0.0"
|
strip-ansi "^4.0.0"
|
||||||
strip-json-comments "~2.0.1"
|
strip-json-comments "~2.0.1"
|
||||||
table "^3.7.8"
|
table "^4.0.1"
|
||||||
text-table "~0.2.0"
|
text-table "~0.2.0"
|
||||||
user-home "^2.0.0"
|
|
||||||
|
|
||||||
espree@^3.4.0:
|
espree@^3.5.2:
|
||||||
version "3.5.2"
|
version "3.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca"
|
resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -2412,7 +2336,7 @@ etag@~1.8.1:
|
|||||||
version "1.8.1"
|
version "1.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||||
|
|
||||||
event-emitter@^0.3.5, event-emitter@~0.3.5:
|
event-emitter@^0.3.5:
|
||||||
version "0.3.5"
|
version "0.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
|
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -2473,10 +2397,6 @@ execa@^0.8.0:
|
|||||||
signal-exit "^3.0.0"
|
signal-exit "^3.0.0"
|
||||||
strip-eof "^1.0.0"
|
strip-eof "^1.0.0"
|
||||||
|
|
||||||
exit-hook@^1.0.0:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
|
|
||||||
|
|
||||||
expand-brackets@^0.1.4:
|
expand-brackets@^0.1.4:
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
|
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
|
||||||
@ -2591,6 +2511,14 @@ extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
|
|||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
|
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
|
||||||
|
|
||||||
|
external-editor@^2.0.4:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48"
|
||||||
|
dependencies:
|
||||||
|
chardet "^0.4.0"
|
||||||
|
iconv-lite "^0.4.17"
|
||||||
|
tmp "^0.0.33"
|
||||||
|
|
||||||
extglob@^0.3.1:
|
extglob@^0.3.1:
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
|
resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
|
||||||
@ -2664,12 +2592,11 @@ fifolock@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fifolock/-/fifolock-1.0.0.tgz#a37e54f3ebe69d13480d95a82abc42b7a5c1792d"
|
resolved "https://registry.yarnpkg.com/fifolock/-/fifolock-1.0.0.tgz#a37e54f3ebe69d13480d95a82abc42b7a5c1792d"
|
||||||
|
|
||||||
figures@^1.3.5:
|
figures@^2.0.0:
|
||||||
version "1.7.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
|
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
|
||||||
dependencies:
|
dependencies:
|
||||||
escape-string-regexp "^1.0.5"
|
escape-string-regexp "^1.0.5"
|
||||||
object-assign "^4.1.0"
|
|
||||||
|
|
||||||
file-entry-cache@^2.0.0:
|
file-entry-cache@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -2724,10 +2651,6 @@ finalhandler@1.1.0:
|
|||||||
statuses "~1.3.1"
|
statuses "~1.3.1"
|
||||||
unpipe "~1.0.0"
|
unpipe "~1.0.0"
|
||||||
|
|
||||||
find-root@^1.0.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
|
|
||||||
|
|
||||||
find-up@^1.0.0:
|
find-up@^1.0.0:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
|
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
|
||||||
@ -2916,10 +2839,14 @@ ftp@~0.3.10:
|
|||||||
readable-stream "1.1.x"
|
readable-stream "1.1.x"
|
||||||
xregexp "2.0.0"
|
xregexp "2.0.0"
|
||||||
|
|
||||||
function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1:
|
function-bind@^1.0.2:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
|
|
||||||
|
functional-red-black-tree@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||||
|
|
||||||
gauge@~2.7.3:
|
gauge@~2.7.3:
|
||||||
version "2.7.4"
|
version "2.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||||
@ -2937,7 +2864,7 @@ generate-function@^2.0.0:
|
|||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
|
resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
|
||||||
|
|
||||||
generate-object-property@^1.1.0, generate-object-property@^1.2.0:
|
generate-object-property@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
|
resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -2947,10 +2874,6 @@ get-caller-file@^1.0.1:
|
|||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
|
||||||
|
|
||||||
get-stdin@^5.0.1:
|
|
||||||
version "5.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
|
|
||||||
|
|
||||||
get-stream@^3.0.0:
|
get-stream@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||||
@ -3063,7 +2986,11 @@ globals@^10.0.0:
|
|||||||
version "10.3.0"
|
version "10.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-10.3.0.tgz#716aba93657b56630b5a0e77de5ea8ac6215afaa"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-10.3.0.tgz#716aba93657b56630b5a0e77de5ea8ac6215afaa"
|
||||||
|
|
||||||
globals@^9.14.0, globals@^9.18.0:
|
globals@^11.0.1:
|
||||||
|
version "11.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/globals/-/globals-11.1.0.tgz#632644457f5f0e3ae711807183700ebf2e4633e4"
|
||||||
|
|
||||||
|
globals@^9.18.0:
|
||||||
version "9.18.0"
|
version "9.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||||
|
|
||||||
@ -3505,7 +3432,7 @@ husky@^0.14.3:
|
|||||||
normalize-path "^1.0.0"
|
normalize-path "^1.0.0"
|
||||||
strip-indent "^2.0.0"
|
strip-indent "^2.0.0"
|
||||||
|
|
||||||
iconv-lite@0.4.19:
|
iconv-lite@0.4.19, iconv-lite@^0.4.17:
|
||||||
version "0.4.19"
|
version "0.4.19"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
||||||
|
|
||||||
@ -3513,7 +3440,7 @@ ienoopen@1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.0.0.tgz#346a428f474aac8f50cf3784ea2d0f16f62bda6b"
|
resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.0.0.tgz#346a428f474aac8f50cf3784ea2d0f16f62bda6b"
|
||||||
|
|
||||||
ignore@^3.0.11, ignore@^3.0.9, ignore@^3.2.0:
|
ignore@^3.3.3, ignore@^3.3.6:
|
||||||
version "3.3.7"
|
version "3.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
|
||||||
|
|
||||||
@ -3543,22 +3470,23 @@ ini@^1.3.4, ini@~1.3.0:
|
|||||||
version "1.3.4"
|
version "1.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
|
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
|
||||||
|
|
||||||
inquirer@^0.12.0:
|
inquirer@^3.0.6:
|
||||||
version "0.12.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
|
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-escapes "^1.1.0"
|
ansi-escapes "^3.0.0"
|
||||||
ansi-regex "^2.0.0"
|
chalk "^2.0.0"
|
||||||
chalk "^1.0.0"
|
cli-cursor "^2.1.0"
|
||||||
cli-cursor "^1.0.1"
|
|
||||||
cli-width "^2.0.0"
|
cli-width "^2.0.0"
|
||||||
figures "^1.3.5"
|
external-editor "^2.0.4"
|
||||||
|
figures "^2.0.0"
|
||||||
lodash "^4.3.0"
|
lodash "^4.3.0"
|
||||||
readline2 "^1.0.1"
|
mute-stream "0.0.7"
|
||||||
run-async "^0.1.0"
|
run-async "^2.2.0"
|
||||||
rx-lite "^3.1.2"
|
rx-lite "^4.0.8"
|
||||||
string-width "^1.0.1"
|
rx-lite-aggregates "^4.0.8"
|
||||||
strip-ansi "^3.0.0"
|
string-width "^2.1.0"
|
||||||
|
strip-ansi "^4.0.0"
|
||||||
through "^2.3.6"
|
through "^2.3.6"
|
||||||
|
|
||||||
interpret@^1.0.0:
|
interpret@^1.0.0:
|
||||||
@ -3616,10 +3544,6 @@ is-builtin-module@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
builtin-modules "^1.0.0"
|
builtin-modules "^1.0.0"
|
||||||
|
|
||||||
is-callable@^1.1.1, is-callable@^1.1.3:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
|
|
||||||
|
|
||||||
is-ci@^1.0.10:
|
is-ci@^1.0.10:
|
||||||
version "1.0.10"
|
version "1.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e"
|
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e"
|
||||||
@ -3632,10 +3556,6 @@ is-data-descriptor@^0.1.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
kind-of "^3.0.2"
|
kind-of "^3.0.2"
|
||||||
|
|
||||||
is-date-object@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
|
|
||||||
|
|
||||||
is-descriptor@^0.1.0:
|
is-descriptor@^0.1.0:
|
||||||
version "0.1.6"
|
version "0.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
|
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
|
||||||
@ -3716,15 +3636,6 @@ is-glob@^3.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob "^2.1.0"
|
is-extglob "^2.1.0"
|
||||||
|
|
||||||
is-my-json-valid@^2.10.0:
|
|
||||||
version "2.16.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11"
|
|
||||||
dependencies:
|
|
||||||
generate-function "^2.0.0"
|
|
||||||
generate-object-property "^1.1.0"
|
|
||||||
jsonpointer "^4.0.0"
|
|
||||||
xtend "^4.0.0"
|
|
||||||
|
|
||||||
is-number@^2.1.0:
|
is-number@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
|
resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
|
||||||
@ -3773,7 +3684,7 @@ is-primitive@^2.0.0:
|
|||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
|
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
|
||||||
|
|
||||||
is-promise@^2.0.0, is-promise@^2.1:
|
is-promise@^2.0.0, is-promise@^2.1, is-promise@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
|
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
|
||||||
|
|
||||||
@ -3785,7 +3696,7 @@ is-redirect@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
|
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
|
||||||
|
|
||||||
is-regex@^1.0.3, is-regex@^1.0.4:
|
is-regex@^1.0.3:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
|
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3807,10 +3718,6 @@ is-stream@^1.0.1, is-stream@^1.1.0:
|
|||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||||
|
|
||||||
is-symbol@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
|
|
||||||
|
|
||||||
is-typedarray@~1.0.0:
|
is-typedarray@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||||
@ -4159,7 +4066,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
|
|||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||||
|
|
||||||
js-yaml@^3.10.0, js-yaml@^3.5.1, js-yaml@^3.7.0:
|
js-yaml@^3.10.0, js-yaml@^3.7.0, js-yaml@^3.9.1:
|
||||||
version "3.10.0"
|
version "3.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
|
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4225,6 +4132,10 @@ json-schema@0.2.3:
|
|||||||
version "0.2.3"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||||
|
|
||||||
|
json-stable-stringify-without-jsonify@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
||||||
|
|
||||||
json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
|
json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
|
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
|
||||||
@ -4249,10 +4160,6 @@ jsonify@~0.0.0:
|
|||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||||
|
|
||||||
jsonpointer@^4.0.0:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
|
|
||||||
|
|
||||||
jsprim@^1.2.2:
|
jsprim@^1.2.2:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||||
@ -4269,10 +4176,6 @@ jstransformer@1.0.0:
|
|||||||
is-promise "^2.0.0"
|
is-promise "^2.0.0"
|
||||||
promise "^7.0.1"
|
promise "^7.0.1"
|
||||||
|
|
||||||
jsx-ast-utils@^1.3.4:
|
|
||||||
version "1.4.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1"
|
|
||||||
|
|
||||||
julien-f-source-map-support@0.1.0:
|
julien-f-source-map-support@0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/julien-f-source-map-support/-/julien-f-source-map-support-0.1.0.tgz#174152c8509538cf666d813eff77cb261711f0af"
|
resolved "https://registry.yarnpkg.com/julien-f-source-map-support/-/julien-f-source-map-support-0.1.0.tgz#174152c8509538cf666d813eff77cb261711f0af"
|
||||||
@ -4696,7 +4599,7 @@ lodash@^3.10.1:
|
|||||||
version "3.10.1"
|
version "3.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
|
||||||
|
|
||||||
lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.16.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.0:
|
lodash@^4.13.1, lodash@^4.14.0, lodash@^4.16.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.0:
|
||||||
version "4.17.4"
|
version "4.17.4"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||||
|
|
||||||
@ -4965,9 +4868,9 @@ mute-stdout@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.0.tgz#5b32ea07eb43c9ded6130434cf926f46b2a7fd4d"
|
resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.0.tgz#5b32ea07eb43c9ded6130434cf926f46b2a7fd4d"
|
||||||
|
|
||||||
mute-stream@0.0.5:
|
mute-stream@0.0.7:
|
||||||
version "0.0.5"
|
version "0.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
|
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||||
|
|
||||||
nan@2.6.2, nan@~2.6.1:
|
nan@2.6.2, nan@~2.6.1:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
@ -5170,7 +5073,7 @@ object-inspect@~0.4.0:
|
|||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-0.4.0.tgz#f5157c116c1455b243b06ee97703392c5ad89fec"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-0.4.0.tgz#f5157c116c1455b243b06ee97703392c5ad89fec"
|
||||||
|
|
||||||
object-keys@^1.0.10, object-keys@^1.0.6, object-keys@^1.0.8:
|
object-keys@^1.0.6:
|
||||||
version "1.0.11"
|
version "1.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
|
||||||
|
|
||||||
@ -5184,14 +5087,6 @@ object-visit@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
|
|
||||||
object.assign@^4.0.4:
|
|
||||||
version "4.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.0.4.tgz#b1c9cc044ef1b9fe63606fc141abbb32e14730cc"
|
|
||||||
dependencies:
|
|
||||||
define-properties "^1.1.2"
|
|
||||||
function-bind "^1.1.0"
|
|
||||||
object-keys "^1.0.10"
|
|
||||||
|
|
||||||
object.defaults@^1.0.0, object.defaults@^1.1.0:
|
object.defaults@^1.0.0, object.defaults@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
|
resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
|
||||||
@ -5237,9 +5132,11 @@ once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
onetime@^1.0.0:
|
onetime@^2.0.0:
|
||||||
version "1.1.0"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
|
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
|
||||||
|
dependencies:
|
||||||
|
mimic-fn "^1.0.0"
|
||||||
|
|
||||||
optimist@^0.6.1:
|
optimist@^0.6.1:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
@ -5425,7 +5322,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
|
|
||||||
path-is-inside@^1.0.1:
|
path-is-inside@^1.0.1, path-is-inside@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
|
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
|
||||||
|
|
||||||
@ -5501,40 +5398,19 @@ pipette@^0.9.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
typ "~0.6.1"
|
typ "~0.6.1"
|
||||||
|
|
||||||
pkg-conf@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.0.0.tgz#071c87650403bccfb9c627f58751bfe47c067279"
|
|
||||||
dependencies:
|
|
||||||
find-up "^2.0.0"
|
|
||||||
load-json-file "^2.0.0"
|
|
||||||
|
|
||||||
pkg-config@^1.1.0:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/pkg-config/-/pkg-config-1.1.1.tgz#557ef22d73da3c8837107766c52eadabde298fe4"
|
|
||||||
dependencies:
|
|
||||||
debug-log "^1.0.0"
|
|
||||||
find-root "^1.0.0"
|
|
||||||
xtend "^4.0.1"
|
|
||||||
|
|
||||||
pkg-dir@^1.0.0:
|
pkg-dir@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
|
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
|
||||||
dependencies:
|
dependencies:
|
||||||
find-up "^1.0.0"
|
find-up "^1.0.0"
|
||||||
|
|
||||||
pkg-up@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26"
|
|
||||||
dependencies:
|
|
||||||
find-up "^1.0.0"
|
|
||||||
|
|
||||||
platform@1.3.4:
|
platform@1.3.4:
|
||||||
version "1.3.4"
|
version "1.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.4.tgz#6f0fb17edaaa48f21442b3a975c063130f1c3ebd"
|
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.4.tgz#6f0fb17edaaa48f21442b3a975c063130f1c3ebd"
|
||||||
|
|
||||||
pluralize@^1.2.1:
|
pluralize@^7.0.0:
|
||||||
version "1.2.1"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
|
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
|
||||||
|
|
||||||
posix-character-classes@^0.1.0:
|
posix-character-classes@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
@ -5586,9 +5462,9 @@ process-nextick-args@^1.0.7, process-nextick-args@~1.0.6:
|
|||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
||||||
|
|
||||||
progress@^1.1.8:
|
progress@^2.0.0:
|
||||||
version "1.1.8"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
|
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
|
||||||
|
|
||||||
promise-polyfill@^6.0.1:
|
promise-polyfill@^6.0.1:
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
@ -5938,14 +5814,6 @@ readdirp@^2.0.0:
|
|||||||
readable-stream "^2.0.2"
|
readable-stream "^2.0.2"
|
||||||
set-immediate-shim "^1.0.1"
|
set-immediate-shim "^1.0.1"
|
||||||
|
|
||||||
readline2@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
|
|
||||||
dependencies:
|
|
||||||
code-point-at "^1.0.0"
|
|
||||||
is-fullwidth-code-point "^1.0.0"
|
|
||||||
mute-stream "0.0.5"
|
|
||||||
|
|
||||||
rechoir@^0.6.2:
|
rechoir@^0.6.2:
|
||||||
version "0.6.2"
|
version "0.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||||
@ -6110,7 +5978,7 @@ require-package-name@^2.0.1:
|
|||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
|
resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
|
||||||
|
|
||||||
require-uncached@^1.0.2:
|
require-uncached@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
|
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6140,18 +6008,18 @@ resolve@1.1.7, resolve@~1.1.6:
|
|||||||
version "1.1.7"
|
version "1.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||||
|
|
||||||
resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7:
|
resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.3:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
|
||||||
dependencies:
|
dependencies:
|
||||||
path-parse "^1.0.5"
|
path-parse "^1.0.5"
|
||||||
|
|
||||||
restore-cursor@^1.0.1:
|
restore-cursor@^2.0.0:
|
||||||
version "1.0.1"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
|
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
|
||||||
dependencies:
|
dependencies:
|
||||||
exit-hook "^1.0.0"
|
onetime "^2.0.0"
|
||||||
onetime "^1.0.0"
|
signal-exit "^3.0.2"
|
||||||
|
|
||||||
right-align@^0.1.1:
|
right-align@^0.1.1:
|
||||||
version "0.1.3"
|
version "0.1.3"
|
||||||
@ -6165,19 +6033,21 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1, rimraf@^2.6.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.0.5"
|
glob "^7.0.5"
|
||||||
|
|
||||||
run-async@^0.1.0:
|
run-async@^2.2.0:
|
||||||
version "0.1.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
|
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
|
||||||
dependencies:
|
dependencies:
|
||||||
once "^1.3.0"
|
is-promise "^2.1.0"
|
||||||
|
|
||||||
run-parallel@^1.1.2:
|
rx-lite-aggregates@^4.0.8:
|
||||||
version "1.1.6"
|
version "4.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.6.tgz#29003c9a2163e01e2d2dfc90575f2c6c1d61a039"
|
resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
|
||||||
|
dependencies:
|
||||||
|
rx-lite "*"
|
||||||
|
|
||||||
rx-lite@^3.1.2:
|
rx-lite@*, rx-lite@^4.0.8:
|
||||||
version "3.1.2"
|
version "4.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
|
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
|
||||||
|
|
||||||
safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
@ -6314,14 +6184,6 @@ shebang-regex@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
|
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
|
||||||
|
|
||||||
shelljs@^0.7.5:
|
|
||||||
version "0.7.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
|
|
||||||
dependencies:
|
|
||||||
glob "^7.0.0"
|
|
||||||
interpret "^1.0.0"
|
|
||||||
rechoir "^0.6.2"
|
|
||||||
|
|
||||||
shellwords@^0.1.0:
|
shellwords@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
||||||
@ -6352,9 +6214,11 @@ slash@^1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||||
|
|
||||||
slice-ansi@0.0.4:
|
slice-ansi@1.0.0:
|
||||||
version "0.0.4"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
|
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
|
||||||
|
dependencies:
|
||||||
|
is-fullwidth-code-point "^2.0.0"
|
||||||
|
|
||||||
"slice-stream@>= 1.0.0 < 2":
|
"slice-stream@>= 1.0.0 < 2":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
@ -6540,29 +6404,6 @@ stack-trace@0.0.9:
|
|||||||
version "0.0.9"
|
version "0.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695"
|
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695"
|
||||||
|
|
||||||
standard-engine@~7.0.0:
|
|
||||||
version "7.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-7.0.0.tgz#ebb77b9c8fc2c8165ffa353bd91ba0dff41af690"
|
|
||||||
dependencies:
|
|
||||||
deglob "^2.1.0"
|
|
||||||
get-stdin "^5.0.1"
|
|
||||||
minimist "^1.1.0"
|
|
||||||
pkg-conf "^2.0.0"
|
|
||||||
|
|
||||||
standard@^10.0.3:
|
|
||||||
version "10.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/standard/-/standard-10.0.3.tgz#7869bcbf422bdeeaab689a1ffb1fea9677dd50ea"
|
|
||||||
dependencies:
|
|
||||||
eslint "~3.19.0"
|
|
||||||
eslint-config-standard "10.2.1"
|
|
||||||
eslint-config-standard-jsx "4.0.2"
|
|
||||||
eslint-plugin-import "~2.2.0"
|
|
||||||
eslint-plugin-node "~4.2.2"
|
|
||||||
eslint-plugin-promise "~3.5.0"
|
|
||||||
eslint-plugin-react "~6.10.0"
|
|
||||||
eslint-plugin-standard "~3.0.1"
|
|
||||||
standard-engine "~7.0.0"
|
|
||||||
|
|
||||||
static-eval@~0.2.0:
|
static-eval@~0.2.0:
|
||||||
version "0.2.4"
|
version "0.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-0.2.4.tgz#b7d34d838937b969f9641ca07d48f8ede263ea7b"
|
resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-0.2.4.tgz#b7d34d838937b969f9641ca07d48f8ede263ea7b"
|
||||||
@ -6630,7 +6471,7 @@ string-width@^1.0.1, string-width@^1.0.2:
|
|||||||
is-fullwidth-code-point "^1.0.0"
|
is-fullwidth-code-point "^1.0.0"
|
||||||
strip-ansi "^3.0.0"
|
strip-ansi "^3.0.0"
|
||||||
|
|
||||||
string-width@^2.0.0:
|
string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -6734,16 +6575,16 @@ symbol-tree@^3.2.1:
|
|||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
|
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
|
||||||
|
|
||||||
table@^3.7.8:
|
table@^4.0.1:
|
||||||
version "3.8.3"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
|
resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36"
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^4.7.0"
|
ajv "^5.2.3"
|
||||||
ajv-keywords "^1.0.0"
|
ajv-keywords "^2.1.0"
|
||||||
chalk "^1.1.1"
|
chalk "^2.1.0"
|
||||||
lodash "^4.0.0"
|
lodash "^4.17.4"
|
||||||
slice-ansi "0.0.4"
|
slice-ansi "1.0.0"
|
||||||
string-width "^2.0.0"
|
string-width "^2.1.1"
|
||||||
|
|
||||||
tar-fs@^1.13.0:
|
tar-fs@^1.13.0:
|
||||||
version "1.16.0"
|
version "1.16.0"
|
||||||
@ -7029,10 +6870,6 @@ union-value@^1.0.0:
|
|||||||
is-extendable "^0.1.1"
|
is-extendable "^0.1.1"
|
||||||
set-value "^0.4.3"
|
set-value "^0.4.3"
|
||||||
|
|
||||||
uniq@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
|
|
||||||
|
|
||||||
unique-stream@^2.0.2:
|
unique-stream@^2.0.2:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369"
|
resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369"
|
||||||
@ -7075,12 +6912,6 @@ user-home@^1.1.1:
|
|||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
|
resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
|
||||||
|
|
||||||
user-home@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
|
|
||||||
dependencies:
|
|
||||||
os-homedir "^1.0.0"
|
|
||||||
|
|
||||||
util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
Loading…
Reference in New Issue
Block a user