Compare commits

..

33 Commits

Author SHA1 Message Date
Julien Fontanet
abb65325b5 tmp 2019-05-15 14:07:08 +02:00
Julien Fontanet
5757afa1d8 fix(xo-server/proxies): use Host of the config
Use the hostname of the URL in the config instead of the one from the incoming request.
2019-05-14 14:08:04 +02:00
Julien Fontanet
86e9b9c1b8 fix(xo-server/api/*): wrap with JsonRpcError 2019-05-14 10:21:43 +02:00
Danp2
1cdd1fa00e Switch forum link to new XCP subforum (#4203)
* Fix usage of "backuping"

* Switch to XCP sub-forum
2019-05-10 17:49:26 +02:00
Julien Fontanet
9d12759c68 fix(xo-server/VM import): forward error message 2019-05-10 17:32:23 +02:00
Julien Fontanet
594341fab6 fix(xo-server/remotes): dont fail is benchmarks JSON is broken 2019-05-09 14:06:50 +02:00
Julien Fontanet
4e88125cbe fix(xo-server/remotes): always JSON encode benchmarks (#4197)
See xoa-support#1464

Fix an issue when restoring from config.
2019-05-09 13:58:36 +02:00
badrAZ
13237180a2 fix(Backup-ng): report sent even though "Never" is selected (#4178)
Fixes #4092
2019-05-09 09:58:35 +02:00
Olivier Lambert
f64d7e0b6e fix README title and also update installation doc (#4198) 2019-05-09 09:34:36 +02:00
Olivier Lambert
040a6930a4 improving support page (#4196)
* improving support page
2019-05-09 09:27:26 +02:00
Julien Fontanet
c54b9189a6 feat(scripts/normalize-package): add version if missing 2019-05-09 09:23:49 +02:00
Julien Fontanet
8882f1b019 chore(bump-pkg): stop on errors 2019-05-07 14:39:17 +02:00
Julien Fontanet
ae6416c4d2 feat(xo-server): add XenServers from XenStore (#4194)
XenStore can be used to pass XenServers to connect to to xo-server:

`vm-data/xen-servers` entry:

```json
[
  {
    "allowUnauthorized": true,
    "host": "xs1.company.tld",
    "label": "My XenServer",
    "password": "super%secret+password",
    "readOnly": false,
    "username": "root"
  }
]
```
2019-05-07 10:25:00 +02:00
Dustin B
8faed87656 Documentation typo
Typo "on" to "one" in support page
2019-05-06 22:41:37 +02:00
Dustin B
0983f05969 Update support documentation 2019-05-06 22:27:57 +02:00
Julien Fontanet
d43e2544a1 feat(xo-server): admin account from XenStore (#4184)
XenStore can be used to pass the credentials of the default admin account to xo-server:

`vm-data/admin-account` entry:

```json
{ "email": "admin@admin.net", "password": "admin" }
```
2019-05-06 17:40:02 +02:00
Pierre Donias
ca83d11ac8 fix(xo-server/xapi-object-to-xo): cast patch size to number (#4193)
Fixes #4192
2019-05-06 16:55:54 +02:00
badrAZ
1cdcdd9b5f chore(reaclette): v0.8.0 (#4188) 2019-05-06 15:03:08 +02:00
Julien Fontanet
cc7806e35b chore(xo-server plugins): are not published as well 2019-05-06 11:45:00 +02:00
Julien Fontanet
0ee48b6623 chore(xo-{server,web}): mark as private
Explicit that these packages are not published on the npm registry.
2019-05-06 11:32:55 +02:00
Julien Fontanet
8c02e0efbd chore(scripts): publish on version bumping 2019-05-06 11:32:55 +02:00
marcpezin
34d3ca82bc adding free limited support section (#4186) 2019-05-06 10:21:18 +02:00
HamadaBrest
43822d3667 chore(vhd-lib): use write instead of createOutputStream (#4179)
See #4156
2019-05-03 14:07:10 +02:00
Pierre Donias
f4ac73b3b4 fix(xo-web/new-vm): cloud init should only be available in Premium (#4174) 2019-05-02 17:01:06 +02:00
HamadaBrest
f084b6def9 feat(fs#write): write buffer at specific position (#4169)
Fixes #4156
2019-05-02 16:20:57 +02:00
Julien Fontanet
a00d101ff7 chore: update dependencies 2019-05-02 10:58:38 +02:00
badrAZ
9d5900d9b6 chore(CHANGELOG): 5.34.0 2019-04-30 11:39:03 +02:00
badrAZ
28fb4e8216 feat(xo-web): 5.40.1 2019-04-30 11:21:14 +02:00
Julien Fontanet
bec4dbe652 feat(xo-web): unlock basic stats for all editions (#4172)
Fixes #4166
2019-04-30 10:17:31 +02:00
Pierre Donias
72cc14f508 feat(xo-web): add banner to clarify support conditions (#4167)
Fixes #4165
2019-04-30 09:54:40 +02:00
Julien Fontanet
d20941cc2c chore(CHANGELOG): Highlights sections 2019-04-29 14:10:27 +02:00
Julien Fontanet
9cb8a05316 chore(CHANGELOG): update next 2019-04-26 16:31:26 +02:00
Julien Fontanet
dccd799f6d feat(xo-web): 5.40.0 2019-04-26 16:27:25 +02:00
85 changed files with 1215 additions and 844 deletions

View File

@@ -46,6 +46,7 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepare": "yarn run build",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -17,5 +17,8 @@
"dependencies": {
"golike-defer": "^0.4.1",
"xen-api": "^0.25.1"
},
"scripts": {
"postversion": "npm publish"
}
}

View File

@@ -55,6 +55,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run clean",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -43,6 +43,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -42,6 +42,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -55,6 +55,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run clean",
"prepare": "yarn run build"
"prepare": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -410,6 +410,18 @@ export default class RemoteHandlerAbstract {
await this._unlink(file).catch(ignoreEnoent)
}
async write(
file: File,
buffer: Buffer,
position: number
): Promise<{| bytesWritten: number, buffer: Buffer |}> {
await this._write(
typeof file === 'string' ? normalizePath(file) : file,
buffer,
position
)
}
async writeFile(
file: string,
data: Data,
@@ -546,6 +558,28 @@ export default class RemoteHandlerAbstract {
throw new Error('Not implemented')
}
async _write(file: File, buffer: Buffer, position: number): Promise<void> {
const isPath = typeof file === 'string'
if (isPath) {
file = await this.openFile(file, 'r+')
}
try {
return await this._writeFd(file, buffer, position)
} finally {
if (isPath) {
await this.closeFile(file)
}
}
}
async _writeFd(
fd: FileDescriptor,
buffer: Buffer,
position: number
): Promise<void> {
throw new Error('Not implemented')
}
async _writeFile(
file: string,
data: Data,

View File

@@ -3,9 +3,9 @@
import 'dotenv/config'
import asyncIteratorToStream from 'async-iterator-to-stream'
import getStream from 'get-stream'
import { forOwn, random } from 'lodash'
import { fromCallback } from 'promise-toolbox'
import { pipeline } from 'readable-stream'
import { random } from 'lodash'
import { tmpdir } from 'os'
import { getHandler } from '.'
@@ -310,5 +310,45 @@ handlers.forEach(url => {
await handler.unlink('file')
})
})
describe('#write()', () => {
beforeEach(() => handler.outputFile('file', TEST_DATA))
const PATCH_DATA_LEN = Math.ceil(TEST_DATA_LEN / 2)
const PATCH_DATA = unsecureRandomBytes(PATCH_DATA_LEN)
forOwn(
{
'dont increase file size': (() => {
const offset = random(0, TEST_DATA_LEN - PATCH_DATA_LEN)
const expected = Buffer.from(TEST_DATA)
PATCH_DATA.copy(expected, offset)
return { offset, expected }
})(),
'increase file size': (() => {
const offset = random(
TEST_DATA_LEN - PATCH_DATA_LEN + 1,
TEST_DATA_LEN
)
const expected = Buffer.alloc(offset + PATCH_DATA_LEN)
TEST_DATA.copy(expected)
PATCH_DATA.copy(expected, offset)
return { offset, expected }
})(),
},
({ offset, expected }, title) => {
describe(title, () => {
testWithFileDescriptor('file', 'r+', async ({ file }) => {
await handler.write(file, PATCH_DATA, offset)
await expect(await handler.readFile('file')).toEqual(expected)
})
})
}
)
})
})
})

View File

@@ -110,6 +110,10 @@ export default class LocalHandler extends RemoteHandlerAbstract {
return fs.unlink(this._getFilePath(file))
}
_writeFd(file, buffer, position) {
return fs.write(file.fd, buffer, 0, buffer.length, position)
}
_writeFile(file, data, { flags }) {
return fs.writeFile(this._getFilePath(file), data, { flag: flags })
}

View File

@@ -159,6 +159,10 @@ export default class SmbHandler extends RemoteHandlerAbstract {
return this._client.unlink(this._getFilePath(file)).catch(normalizeError)
}
_writeFd(file, buffer, position) {
return this._client.write(file.fd, buffer, 0, buffer.length, position)
}
_writeFile(file, data, options) {
return this._client
.writeFile(this._getFilePath(file), data, options)

View File

@@ -48,6 +48,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -45,6 +45,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -0,0 +1,8 @@
const handler = {
get(target, property) {
const value = target[property]
return value !== undefined ? value : 0
},
}
export const create = () => new Proxy({ __proto__: null }, handler)

View File

@@ -0,0 +1,14 @@
{
"name": "@xen-orchestra/multi-counter",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/multi-counter",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@xen-orchestra/multi-counter",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"version": "0.0.0",
"scripts": {
"postversion": "npm publish"
}
}

View File

@@ -1,6 +1,14 @@
# ChangeLog
## **next** (2019-04-11)
## **5.34.0** (2019-04-30)
### Highlights
- [Self/New VM] Add network config box to custom cloud-init [#3872](https://github.com/vatesfr/xen-orchestra/issues/3872) (PR [#4150](https://github.com/vatesfr/xen-orchestra/pull/4150))
- [Metadata backup] Detailed logs [#4005](https://github.com/vatesfr/xen-orchestra/issues/4005) (PR [#4014](https://github.com/vatesfr/xen-orchestra/pull/4014))
- [Backup reports] Support metadata backups (PR [#4084](https://github.com/vatesfr/xen-orchestra/pull/4084))
- [VM migration] Auto select default SR and collapse optional actions [#3326](https://github.com/vatesfr/xen-orchestra/issues/3326) (PR [#4121](https://github.com/vatesfr/xen-orchestra/pull/4121))
- Unlock basic stats on all editions [#4166](https://github.com/vatesfr/xen-orchestra/issues/4166) (PR [#4172](https://github.com/vatesfr/xen-orchestra/pull/4172))
### Enhancements
@@ -9,8 +17,11 @@
- [Import] Avoid blocking the UI when dropping a big OVA file on the UI (PR [#4018](https://github.com/vatesfr/xen-orchestra/pull/4018))
- [Backup NG/Overview] Make backup list title clearer [#4111](https://github.com/vatesfr/xen-orchestra/issues/4111) (PR [#4129](https://github.com/vatesfr/xen-orchestra/pull/4129))
- [Dashboard] Hide "Report" section for non-admins [#4123](https://github.com/vatesfr/xen-orchestra/issues/4123) (PR [#4126](https://github.com/vatesfr/xen-orchestra/pull/4126))
- [VM migration] Auto select default SR and collapse optional actions [#3326](https://github.com/vatesfr/xen-orchestra/issues/3326) (PR [#4121](https://github.com/vatesfr/xen-orchestra/pull/4121))
- [Metadata backup] Logs [#4005](https://github.com/vatesfr/xen-orchestra/issues/4005) (PR [#4014](https://github.com/vatesfr/xen-orchestra/pull/4014))
- [Self/New VM] Display confirmation modal when user will use a large amount of resources [#4044](https://github.com/vatesfr/xen-orchestra/issues/4044) (PR [#4127](https://github.com/vatesfr/xen-orchestra/pull/4127))
- [VDI migration, New disk] Warning when SR host is different from the other disks [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#4035](https://github.com/vatesfr/xen-orchestra/pull/4035))
- [Attach disk] Display warning message when VDI SR is on different host from the other disks [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#4117](https://github.com/vatesfr/xen-orchestra/pull/4117))
- [Editable] Notify user when editable undo fails [#3799](https://github.com/vatesfr/xen-orchestra/issues/3799) (PR [#4150](https://github.com/vatesfr/xen-orchestra/pull/4157))
- [XO] Add banner for sources users to clarify support conditions [#4165](https://github.com/vatesfr/xen-orchestra/issues/4165) (PR [#4167](https://github.com/vatesfr/xen-orchestra/pull/4167))
### Bug fixes
@@ -18,13 +29,17 @@
- [Backup NG] Only display full backup interval in case of a delta backup (PR [#4125](https://github.com/vatesfr/xen-orchestra/pull/4107))
- [Dashboard/Health] fix 'an error has occurred' on the storage state table [#4128](https://github.com/vatesfr/xen-orchestra/issues/4128) (PR [#4132](https://github.com/vatesfr/xen-orchestra/pull/4132))
- [Menu] XOA: Fixed empty slot when menu is collapsed [#4012](https://github.com/vatesfr/xen-orchestra/issues/4012) (PR [#4068](https://github.com/vatesfr/xen-orchestra/pull/4068)
- [Self/New VM] Fix missing templates when refreshing page [#3265](https://github.com/vatesfr/xen-orchestra/issues/3265) (PR [#3565](https://github.com/vatesfr/xen-orchestra/pull/3565))
- [Home] No more false positives when select Tag on Home page [#4087](https://github.com/vatesfr/xen-orchestra/issues/4087) (PR [#4112](https://github.com/vatesfr/xen-orchestra/pull/4112))
### Released packages
- xo-server-backup-reports v0.16.0
- complex-matcher v0.6.0
- xo-vmdk-to-vhd v0.1.7
- vhd-lib v0.6.1
- xo-server v5.39.0
- xo-web v5.39.1
- xo-server v5.40.0
- xo-web v5.40.1
## **5.33.1** (2019-04-04)

View File

@@ -2,21 +2,16 @@
### Enhancements
- [Self/New VM] Display confirmation modal when user will use a large amount of resources [#4044](https://github.com/vatesfr/xen-orchestra/issues/4044) (PR [#4127](https://github.com/vatesfr/xen-orchestra/pull/4127))
- [Home] No more false positives when select Tag on Home page [#4087](https://github.com/vatesfr/xen-orchestra/issues/4087) (PR [#4112](https://github.com/vatesfr/xen-orchestra/pull/4112))
- [VDI migration, New disk] Warning when SR host is different from the other disks [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#4035](https://github.com/vatesfr/xen-orchestra/pull/4035))
- [Backup reports] Support metadata backups (PR [#4084](https://github.com/vatesfr/xen-orchestra/pull/4084))
- [Attach disk] Display warning message when VDI SR is on different host from the other disks [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#4117](https://github.com/vatesfr/xen-orchestra/pull/4117))
- [Self/New VM] Add network config box to custom cloud-init [#3872](https://github.com/vatesfr/xen-orchestra/issues/3872) (PR [#4150](https://github.com/vatesfr/xen-orchestra/pull/4150))
- [Editable] Notify user when editable undo fails [#3799](https://github.com/vatesfr/xen-orchestra/issues/3799) (PR [#4150](https://github.com/vatesfr/xen-orchestra/pull/4157))
### Bug fixes
- [Self/New VM] Fix missing templates when refreshing page [#3265](https://github.com/vatesfr/xen-orchestra/issues/3265) (PR [#3565](https://github.com/vatesfr/xen-orchestra/pull/3565))
- [Pool/Patches] Fix "an error has occurred" in "Applied patches" [#4192](https://github.com/vatesfr/xen-orchestra/issues/4192) (PR [#4193](https://github.com/vatesfr/xen-orchestra/pull/4193))
- [Backup NG] Fix report sent even though "Never" is selected [#4092](https://github.com/vatesfr/xen-orchestra/issues/4092) (PR [#4178](https://github.com/vatesfr/xen-orchestra/pull/4178))
- [Remotes] Fix issues after a config import (PR [#4197](https://github.com/vatesfr/xen-orchestra/pull/4197))
### Released packages
- xo-server-backup-reports v0.16.0
- complex-matcher v0.6.0
- xo-server v5.40.0
- xo-web v5.40.0
- xo-server-backup-reports v0.16.1
- @xen-orchestra/fs v0.9.0
- vhd-lib v0.7.0
- xo-server v5.41.0
- xo-web v5.41.0

View File

@@ -1,4 +1,4 @@
# Xen Orchestra [![Chat with us](https://storage.crisp.im/plugins/images/936925df-f37b-4ba8-bab0-70cd2edcb0be/badge.svg)](https://go.crisp.im/chat/embed/?website_id=-JzqzzwddSV7bKGtEyAQ) [![Build Status](https://travis-ci.org/vatesfr/xen-orchestra.png?branch=master)](https://travis-ci.org/vatesfr/xen-orchestra)
# Xen Orchestra [![Build Status](https://travis-ci.org/vatesfr/xen-orchestra.png?branch=master)](https://travis-ci.org/vatesfr/xen-orchestra)
![](http://i.imgur.com/tRffA5y.png)

View File

@@ -1,13 +1,13 @@
# Installation
SSH to your XenServer and execute the following:
SSH to your XenServer/XCP-ng host and execute the following:
```
bash -c "$(curl -s http://xoa.io/deploy)"
```
This will automatically download/import/start the XOA appliance. Nothing is changed on your XenServer host itself, it's 100% safe.
This will automatically download/import/start the XOA appliance. Nothing is changed on your host itself, it's 100% safe.
## [More on XOA](xoa.md)

View File

@@ -1,24 +1,33 @@
# Support
You can access our pro support if you subscribe to any of these plans:
Xen Orchestra will run in a controlled/tested environment thanks to XOA ([Xen Orchestra virtual Appliance](https://xen-orchestra.com/#!/xoa)). **This is the way to get pro support**. Any account with a registered XOA can access a [dedicated support panel](https://xen-orchestra.com/#!/member/support).
XOA is available in multiple plans:
* Free
* Starter
* Enterprise
* Premium
The better the plan, the faster the support will be with higher priority.
Higher tier support plans include faster ticket response times (and cover more features). Paid support plans and response times are based on the plan you have, plans can be [reviewed here](https://xen-orchestra.com/#!/xo-pricing).
## XOA Free support
With the free version of the Xen Orchestra Appliance (XOA free), you can open support tickets and we will do our best to assist you, however, this support is limited and is not guaranteed in regards to response times or resolutions offered.
## Community support
If you are using Xen Orchestra via the sources, you can ask questions and try to recieve help two different ways:
If you are using Xen Orchestra via the source and not XOA, you can ask questions and try to recieve help through a number of different ways:
* In our [forum](https://xen-orchestra.com/forum/)
* In our [forum](https://xcp-ng.org/forum/category/12/xen-orchestra)
* In our IRC - `#xen-orchestra` on `Freenode`
However, there's no guarantee you will receive an answer and no guaranteed response time. If you are using XO from sources, we encourage you to give back to the community by assisting other users via these two avenues as well.
We encourage you to give back to the community by assisting other users via these two avenues as well.
If you are using Xen Orchestra in production, please subscribe to a plan.
Lastly while Xen Orchestra is free and Open Source software, supporting and developing it takes a lot of effort. If you are considering using Xen Orchestra in production, please subscribe for one of our [professional support plans](https://xen-orchestra.com/#!/xo-pricing).
> Note: support from the sources is harder, because Xen Orchestra can potentially run on any Linux distro (or even FreeBSD and Windows!). Always try to double check that you followed our guide on how to [install it from the sources](https://xen-orchestra.com/docs/from_the_sources.html) before going further.
## Open a ticket
If you have a subscription, you can open a ticket describing your issue directly from your personal account page [here](https://xen-orchestra.com/#!/member/support)
If you have a subscription (or at least a registered free XOA), you can open a ticket describing your issue directly from your personal account page [here](https://xen-orchestra.com/#!/member/support)

View File

@@ -17,9 +17,9 @@
"eslint-plugin-react": "^7.6.1",
"eslint-plugin-standard": "^4.0.0",
"exec-promise": "^0.7.0",
"flow-bin": "^0.97.0",
"flow-bin": "^0.98.0",
"globby": "^9.0.0",
"husky": "^1.2.1",
"husky": "^2.2.0",
"jest": "^24.1.0",
"lodash": "^4.17.4",
"prettier": "^1.10.2",

View File

@@ -44,6 +44,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -43,6 +43,7 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepare": "yarn run build",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -51,6 +51,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "rimraf dist/ && index-modules --cjs-lazy src/commands",
"predev": "yarn run prebuild",
"prepare": "yarn run build"
"prepare": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -52,6 +52,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run clean",
"prepare": "yarn run build"
"prepare": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -1,9 +1,7 @@
import assert from 'assert'
import { fromEvent } from 'promise-toolbox'
import checkFooter from './_checkFooter'
import checkHeader from './_checkHeader'
import constantStream from './_constant-stream'
import getFirstAndLastBlocks from './_getFirstAndLastBlocks'
import { fuFooter, fuHeader, checksumStruct, unpackField } from './_structs'
import { set as mapSetBit, test as mapTestBit } from './_bitmap'
@@ -232,24 +230,11 @@ export default class Vhd {
// Write functions.
// =================================================================
// Write a buffer/stream at a given position in a vhd file.
// Write a buffer at a given position in a vhd file.
async _write(data, offset) {
debug(
`_write offset=${offset} size=${
Buffer.isBuffer(data) ? data.length : '???'
}`
)
// TODO: could probably be merged in remote handlers.
const stream = await this._handler.createOutputStream(this._path, {
flags: 'r+',
start: offset,
})
return Buffer.isBuffer(data)
? new Promise((resolve, reject) => {
stream.on('error', reject)
stream.end(data, resolve)
})
: fromEvent(data.pipe(stream), 'finish')
assert(Buffer.isBuffer(data))
debug(`_write offset=${offset} size=${data.length}`)
return this._handler.write(this._path, data, offset)
}
async _freeFirstBlockSpace(spaceNeededBytes) {
@@ -306,7 +291,7 @@ export default class Vhd {
`ensureBatSize: extend BAT ${prevMaxTableEntries} -> ${maxTableEntries}`
)
await this._write(
constantStream(BUF_BLOCK_UNUSED, maxTableEntries - prevMaxTableEntries),
Buffer.alloc(maxTableEntries - prevMaxTableEntries, BUF_BLOCK_UNUSED),
header.tableOffset + prevBat.length
)
await this.writeHeader()
@@ -331,10 +316,7 @@ export default class Vhd {
await Promise.all([
// Write an empty block and addr in vhd file.
this._write(
constantStream([0], this.fullBlockSize),
sectorsToBytes(blockAddr)
),
this._write(Buffer.alloc(this.fullBlockSize), sectorsToBytes(blockAddr)),
this._setBatEntry(blockId, blockAddr),
])

View File

@@ -56,6 +56,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -69,6 +69,7 @@
"plot": "gnuplot -p memory-test.gnu",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -25,5 +25,8 @@
},
"dependencies": {
"xo-common": "^0.2.0"
},
"scripts": {
"postversion": "npm publish"
}
}

View File

@@ -64,6 +64,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -43,6 +43,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -45,6 +45,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -55,6 +55,7 @@
"lint": "tslint 'src/*.ts'",
"posttest": "yarn run lint",
"prepublishOnly": "yarn run build",
"start": "node dist/index.js"
"start": "node dist/index.js",
"postversion": "npm publish"
}
}

View File

@@ -32,7 +32,7 @@
"node": ">=6"
},
"dependencies": {
"jsonrpc-websocket-client": "^0.4.1",
"jsonrpc-websocket-client": "^0.5.0",
"lodash": "^4.17.2",
"make-error": "^1.0.4"
},
@@ -49,6 +49,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -41,6 +41,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepare": "yarn run build"
"prepare": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -41,5 +41,6 @@
"build": "NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
"dev": "NODE_DEV=development babel --watch --source-maps --out-dir=dist/ src/",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -49,5 +49,6 @@
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -55,5 +55,6 @@
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -50,5 +50,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -58,5 +58,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -245,6 +245,9 @@ class BackupReportsXoPlugin {
if (
!force &&
(reportWhen === 'never' ||
// Handle improper value introduced by:
// https://github.com/vatesfr/xen-orchestra/commit/753ee994f2948bbaca9d3161eaab82329a682773#diff-9c044ab8a42ed6576ea927a64c1ec3ebR105
reportWhen === 'Never' ||
(reportWhen === 'failure' && log.status === 'success'))
) {
return

View File

@@ -33,7 +33,7 @@
},
"dependencies": {
"http-request-plus": "^0.8.0",
"jsonrpc-websocket-client": "^0.4.1"
"jsonrpc-websocket-client": "^0.5.0"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
@@ -49,5 +49,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -44,5 +44,6 @@
"build": "NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
"dev": "NODE_DEV=development babel --watch --source-maps --out-dir=dist/ src/",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -42,5 +42,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -50,5 +50,6 @@
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -49,5 +49,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -50,5 +50,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -50,5 +50,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -59,5 +59,6 @@
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
}
},
"private": true
}

View File

@@ -1,4 +1,5 @@
{
"private": true,
"name": "xo-server",
"version": "5.40.0",
"license": "AGPL-3.0",
@@ -91,6 +92,7 @@
"make-error": "^1",
"micromatch": "^3.1.4",
"minimist": "^1.2.0",
"mnemonist": "^0.27.2",
"moment-timezone": "^0.5.14",
"ms": "^2.1.1",
"multikey-hash": "^1.0.4",
@@ -109,7 +111,7 @@
"readable-stream": "^3.2.0",
"redis": "^2.8.0",
"schema-inspector": "^1.6.8",
"semver": "^5.4.1",
"semver": "^6.0.0",
"serve-static": "^1.13.1",
"split-lines": "^2.0.0",
"stack-chain": "^2.0.0",

View File

@@ -0,0 +1,5 @@
import fromCallback from 'promise-toolbox/fromCallback'
import { execFile } from 'child_process'
export const read = key =>
fromCallback(cb => execFile('xenstore-read', [key], cb))

View File

@@ -1,6 +1,6 @@
import createLogger from '@xen-orchestra/log'
import pump from 'pump'
import { format } from 'json-rpc-peer'
import { format, JsonRpcError } from 'json-rpc-peer'
import { noSuchObject } from 'xo-common/api-errors'
import { parseSize } from '../utils'
@@ -128,7 +128,7 @@ async function handleImportContent(req, res, { xapi, id }) {
res.end(format.response(0, true))
} catch (e) {
res.writeHead(500)
res.end(format.error(0, new Error(e.message)))
res.end(format.error(0, new JsonRpcError(e.message)))
}
}

View File

@@ -1,4 +1,4 @@
import { format } from 'json-rpc-peer'
import { format, JsonRpcError } from 'json-rpc-peer'
// ===================================================================
@@ -248,7 +248,7 @@ async function handleInstallSupplementalPack(req, res, { hostId }) {
res.end(format.response(0))
} catch (e) {
res.writeHead(500)
res.end(format.error(0, new Error(e.message)))
res.end(format.error(0, new JsonRpcError(e.message)))
}
}

View File

@@ -1,4 +1,4 @@
import { format } from 'json-rpc-peer'
import { format, JsonRPcError } from 'json-rpc-peer'
// ===================================================================
@@ -234,7 +234,7 @@ async function handleInstallSupplementalPack(req, res, { poolId }) {
res.end(format.response(0))
} catch (e) {
res.writeHead(500)
res.end(format.error(0, new Error(e.message)))
res.end(format.error(0, new JsonRPcError(e.message)))
}
}

View File

@@ -1,5 +1,5 @@
import defer from 'golike-defer'
import { format } from 'json-rpc-peer'
import { format, JsonRpcError } from 'json-rpc-peer'
import { ignoreErrors } from 'promise-toolbox'
import { assignWith, concat } from 'lodash'
import {
@@ -1203,7 +1203,7 @@ async function handleVmImport(req, res, { data, srId, type, xapi }) {
res.end(format.response(0, vm.$id))
} catch (e) {
res.writeHead(500)
res.end(format.error(0, new Error(e.message)))
res.end(format.error(0, new JsonRpcError(e.message)))
}
}

View File

@@ -417,6 +417,7 @@ const setUpProxies = (express, opts, xo) => {
}
const proxy = createProxyServer({
changeOrigin: true,
ignorePath: true,
}).on('error', error => console.error(error))

View File

@@ -2,6 +2,8 @@ import Collection from '../collection/redis'
import Model from '../model'
import { forEach } from '../utils'
import { parseProp } from './utils'
// ===================================================================
export default class Remote extends Model {}
@@ -14,12 +16,21 @@ export class Remotes extends Collection {
async get(properties) {
const remotes = await super.get(properties)
forEach(remotes, remote => {
remote.benchmarks =
remote.benchmarks !== undefined
? JSON.parse(remote.benchmarks)
: undefined
remote.benchmarks = parseProp('remote', remote, 'benchmarks')
remote.enabled = remote.enabled === 'true'
})
return remotes
}
_update(remotes) {
return super._update(
remotes.map(remote => {
const { benchmarks } = remote
if (benchmarks !== undefined) {
remote.benchmarks = JSON.stringify(benchmarks)
}
return remote
})
)
}
}

View File

@@ -633,7 +633,7 @@ const TRANSFORMS = {
description: poolPatch.name_description,
name: poolPatch.name_label,
pool_patch: poolPatch.$ref,
size: poolPatch.size,
size: +poolPatch.size,
guidance: poolPatch.after_apply_guidance,
time: toTimestamp(obj.timestamp_applied),

View File

@@ -1,3 +1,4 @@
import * as MultiCounter from '@xen-orchestra/multi-counter'
import aclResolver from 'xo-acl-resolver'
import { forEach, includes, map } from 'lodash'
@@ -6,9 +7,11 @@ import { Acls } from '../models/acl'
// ===================================================================
// TODO add cache per user
export default class {
constructor(xo) {
this._xo = xo
this._cacheByObjectByUser = { __proto__: null }
const aclsDb = (this._acls = new Acls({
connection: xo._redis,
@@ -16,6 +19,20 @@ export default class {
indexes: ['subject', 'object'],
}))
const nSessionsByUser = MultiCounter.create()
xo.on('session.open', session => {
const userId = session.get('user_id')
if (nSessionsByUser[userId]++ === 0) {
this._cacheByObjectByUser[userId] = { __proto__: null }
}
})
xo.on('session.close', session => {
const userId = session.get('user_id')
if (--nSessionsByUser[userId] === 0) {
delete this._cacheByObjectByUser[userId]
}
})
xo.on('start', () => {
xo.addConfigManager(
'acls',

View File

@@ -168,7 +168,7 @@ export default class {
}
@synchronized()
async _updateRemote(id, { benchmarks, url, ...props }) {
async _updateRemote(id, { url, ...props }) {
const remote = await this._getRemote(id)
// url is handled separately to take care of obfuscated values
@@ -176,13 +176,6 @@ export default class {
remote.url = format(sensitiveValues.merge(parse(url), parse(remote.url)))
}
if (
benchmarks !== undefined ||
(benchmarks = remote.benchmarks) !== undefined
) {
remote.benchmarks = JSON.stringify(benchmarks)
}
patch(remote, props)
return (await this._remotes.update(remote)).properties

View File

@@ -4,6 +4,7 @@ import { ignoreErrors } from 'promise-toolbox'
import { hash, needsRehash, verify } from 'hashy'
import { invalidCredentials, noSuchObject } from 'xo-common/api-errors'
import * as XenStore from '../_XenStore'
import { Groups } from '../models/group'
import { Users } from '../models/user'
import { forEach, isEmpty, lightSet, mapToArray } from '../utils'
@@ -68,8 +69,12 @@ export default class {
)
if (!(await usersDb.exists())) {
const email = 'admin@admin.net'
const password = 'admin'
const {
email = 'admin@admin.net',
password = 'admin',
} = await XenStore.read('vm-data/admin-account')
.then(JSON.parse)
.catch(() => ({}))
await this.createUser({ email, password, permission: 'admin' })
log.info(`Default user created: ${email} with password ${password}`)

View File

@@ -0,0 +1,75 @@
import BloomFilter from 'mnemonist/bloom-filter'
import forOwn from 'lodash/forOwn'
import iteratee from 'lodash/iteratee'
const BLOOM_FILTER_CAPACITY = 50
export default class Subscriptions {
constructor(app) {
this._app = app
this._permCacheByUser = { __proto__: null }
this._objCacheBySession = { __proto__: null }
this._predicatesBySession = { __proto__: null }
}
async subscribe(sessionId, userId, filter) {
const predicatesBySession = this._predicatesBySession
const predicates =
predicatesBySession[sessionId] ??
(predicatesBySession[sessionId] = { __proto__: null })
const subscriptionId = Math.random()
.toString(36)
.slice(2)
const predicate = iteratee(filter)
predicates[subscriptionId] = predicate
const objCacheBySession = this._objCacheBySession
const objCache =
objCacheBySession[sessionId] ??
(objCacheBySession[sessionId] = { __proto__: null })
const objects = this.getObjects()
const ids = Object.keys(objects)
await Promise.all(
ids.map(async id => {
if (!(await this.hasPermissions(userId, [[id, 'view']]))) {
// user cannot see this object
return
}
const cache =
objCache[id] ??
(objCache[id] = new BloomFilter(BLOOM_FILTER_CAPACITY))
cache.add(subscriptionId)
})
)
return subscriptionId
}
unsubscribe(sessionId, userId, subscriptionId) {
const predicates = this._predicatesBySession[sessionId]
if (predicates === undefined || !(subscriptionId in predicates)) {
return
}
delete predicates[subscriptionId]
const objCache = this._objCacheBySession[sessionId]
forOwn(objCache, (cache, id) => {
if (!cache.test(subscriptionId)) {
// not handled by this subscription
return
}
const object = this.getObject(id)
cache = objCache[id] = new BloomFilter(BLOOM_FILTER_CAPACITY)
forOwn(predicates, (predicate, subscriptionId) => {
if (predicate(object)) {
cache.add(subscriptionId)
}
})
})
}
}

View File

@@ -4,6 +4,7 @@ import { fibonacci } from 'iterable-backoff'
import { noSuchObject } from 'xo-common/api-errors'
import { pDelay, ignoreErrors } from 'promise-toolbox'
import * as XenStore from '../_XenStore'
import Xapi from '../xapi'
import xapiObjectToXo from '../xapi-object-to-xo'
import XapiStats from '../xapi-stats'
@@ -64,8 +65,19 @@ export default class {
servers => serversDb.update(servers)
)
// Connects to existing servers.
const servers = await serversDb.get()
// Add servers in XenStore
if (servers.length === 0) {
const xenStoreServers = await XenStore.read('vm-data/xen-servers')
.then(JSON.parse)
.catch(() => [])
for (const server of xenStoreServers) {
servers.push(await this.registerXenServer(server))
}
}
// Connects to existing servers.
for (const server of servers) {
if (server.enabled) {
this.connectXenServer(server.id).catch(error => {

View File

@@ -50,6 +50,7 @@
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run clean",
"prepare": "yarn run build"
"prepare": "yarn run build",
"postversion": "npm publish"
}
}

View File

@@ -1,7 +1,7 @@
{
"private": false,
"private": true,
"name": "xo-web",
"version": "5.39.1",
"version": "5.40.1",
"license": "AGPL-3.0",
"description": "Web interface client for Xen-Orchestra",
"keywords": [
@@ -100,7 +100,7 @@
"prop-types": "^15.6.0",
"qrcode": "^1.3.2",
"random-password": "^0.1.2",
"reaclette": "^0.7.0",
"reaclette": "^0.8.0",
"react": "^15.4.1",
"react-addons-shallow-compare": "^15.6.2",
"react-addons-test-utils": "^15.6.2",

View File

@@ -87,3 +87,5 @@ export const DEFAULT_NETWORK_CONFIG_TEMPLATE = `#network:
# name: eth0
# subnets:
# - type: dhcp`
export const CAN_CLOUD_INIT = +process.env.XOA_PLAN > 3

View File

@@ -3411,7 +3411,7 @@ export default {
// Original text: "This version is not bundled with any support nor updates. Use it with caution for critical tasks."
disclaimerText3:
'Esta versión no está creada para recibir soporte ni actualizaciones. Úsala con precaución para tareas críticas.',
'Esta versión no está creada para recibir soporte ni actualizaciones. Úsala con precaución.',
// Original text: "Connect PIF"
connectPif: 'Conectar PIF',

View File

@@ -3497,7 +3497,7 @@ export default {
// Original text: "This version is not bundled with any support nor updates. Use it with caution for critical tasks."
disclaimerText3:
"Cette version n'est fournie avec aucun support ni aucune mise à jour. Soyez prudent en cas d'utilisation pour des tâches importantes.",
"Cette version n'est fournie avec aucun support ni aucune mise à jour. Utilisez-la avec précaution.",
// Original text: "Connect PIF"
connectPif: 'Connecter la PIF',

View File

@@ -3248,7 +3248,7 @@ export default {
// Original text: "This version is not bundled with any support nor updates. Use it with caution for critical tasks."
disclaimerText3:
'This Verzió is not bundled with any support nor upDates. Use it with caution for critical tasks.',
'This Verzió is not bundled with any support nor upDates. Use it with caution.',
// Original text: "Connect PIF"
connectPif: 'Csatlakozás PIF',

View File

@@ -2958,7 +2958,7 @@ export default {
// Original text: "This version is not bundled with any support nor updates. Use it with caution for critical tasks."
disclaimerText3:
'This version is not bundled with any support nor updates. Use it with caution for critical tasks.',
'This version is not bundled with any support nor updates. Use it with caution.',
// Original text: "Connect PIF"
connectPif: 'Connect PIF',

View File

@@ -2944,7 +2944,7 @@ export default {
// Original text: "This version is not bundled with any support nor updates. Use it with caution for critical tasks."
disclaimerText3:
'Esta versão não está vinculada a qualquer tipo de suporte nem atualizações. Use-a com cuidado em se tratando de tarefas críticas.',
'Esta versão não está vinculada a qualquer tipo de suporte nem atualizações. Use-a com cuidado.',
// Original text: "Connect PIF"
connectPif: 'Conectar PIF',

View File

@@ -4294,7 +4294,7 @@ export default {
// Original text: "This version is not bundled with any support nor updates. Use it with caution for critical tasks."
disclaimerText3:
'Bu sürüm herhangi bir destek veya güncellemeyle birlikte verilmez. Kritik görevler için dikkatli kullanın.',
'Bu sürüm herhangi bir destek veya güncellemeyle birlikte verilmez. Dikkatli kullanın.',
// Original text: "Connect PIF"
connectPif: "PIF'e bağlan",

View File

@@ -2236,7 +2236,7 @@ export default {
disclaimerText2: '如果你是一个公司,建议使用我们的设备结合专业的支持',
// Original text: "This version is not bundled with any support nor updates. Use it with caution for critical tasks."
disclaimerText3: '这个版本没有绑定任何支持或更新,在紧急任务下,请谨慎使用',
disclaimerText3: '这个版本没有绑定任何支持或更新,请谨慎使用',
// Original text: "Connect PIF"
connectPif: '连接物理网卡',

View File

@@ -1321,6 +1321,7 @@ const messages = {
newVmSshKey: 'SSH key',
noConfigDrive: 'No config drive',
newVmCustomConfig: 'Custom config',
premiumOnly: 'Only available in Premium',
availableTemplateVarsInfo:
'Click here to see the available template variables',
availableTemplateVarsTitle: 'Available template variables',
@@ -1868,7 +1869,7 @@ const messages = {
disclaimerText2:
"If you are a company, it's better to use it with our appliance + pro support included:",
disclaimerText3:
'This version is not bundled with any support nor updates. Use it with caution for critical tasks.',
'This version is not bundled with any support nor updates. Use it with caution.',
notRegisteredDisclaimerInfo:
'You are not registered. Your XOA may not be up to date.',
notRegisteredDisclaimerCreateAccount: 'Click here to create an account.',

View File

@@ -37,7 +37,9 @@ export class TooltipViewer extends Component {
return (
<div
className={classNames(
show ? styles.tooltipEnabled : styles.tooltipDisabled,
show && content !== undefined
? styles.tooltipEnabled
: styles.tooltipDisabled,
className
)}
style={{

View File

@@ -88,7 +88,7 @@ export default class About extends Component {
<p className='text-muted'>{_('bugTrackerText')}</p>
</Col>
<Col mediumSize={6}>
<a href='https://xen-orchestra.com/forum/'>
<a href='https://xcp-ng.org/forum/category/12/xen-orchestra'>
<Icon icon='group' size={4} />
<h4>{_('community')}</h4>
</a>

View File

@@ -126,7 +126,7 @@ const REPORT_WHEN_FILTER_OPTIONS = [
},
{
label: 'reportWhenNever',
value: 'Never',
value: 'never',
},
]

View File

@@ -3,7 +3,6 @@ import Component from 'base-component'
import Icon from 'icon'
import React from 'react'
import Tooltip from 'tooltip'
import Upgrade from 'xoa-upgrade'
import { Container, Row, Col } from 'grid'
import { Toggle } from 'form'
import { fetchHostStats } from 'xo'
@@ -105,7 +104,7 @@ export default class HostStats extends Component {
return !stats ? (
<p>No stats.</p>
) : process.env.XOA_PLAN > 2 ? (
) : (
<Container>
<Row>
<Col mediumSize={5}>
@@ -179,10 +178,6 @@ export default class HostStats extends Component {
</Col>
</Row>
</Container>
) : (
<Container>
<Upgrade place='hostStats' available={3} />
</Container>
)
}
}

View File

@@ -222,6 +222,17 @@ export default class XoApp extends Component {
</Link>
</div>
)}
{+process.env.XOA_PLAN === 5 && (
<div className='alert alert-danger mb-0'>
<a
href='https://xen-orchestra.com/#!/xoa?pk_campaign=xo_source_banner'
rel='noopener noreferrer'
target='_blank'
>
{_('disclaimerText3')}
</a>
</div>
)}
<div style={CONTAINER_STYLE}>
<Shortcuts
name='XoApp'

View File

@@ -16,6 +16,7 @@ import Tooltip from 'tooltip'
import Wizard, { Section } from 'wizard'
import {
AvailableTemplateVars,
CAN_CLOUD_INIT,
DEFAULT_CLOUD_CONFIG_TEMPLATE,
DEFAULT_NETWORK_CONFIG_TEMPLATE,
NetworkConfigInfo,
@@ -1163,13 +1164,18 @@ export default class NewVm extends BaseComponent {
<br />
<LineItem>
<label>
<input
checked={installMethod === 'SSH'}
name='installMethod'
onChange={this._linkState('installMethod')}
type='radio'
value='SSH'
/>
<Tooltip
content={CAN_CLOUD_INIT ? undefined : _('premiumOnly')}
>
<input
checked={installMethod === 'SSH'}
disabled={!CAN_CLOUD_INIT}
name='installMethod'
onChange={this._linkState('installMethod')}
type='radio'
value='SSH'
/>
</Tooltip>
&nbsp;
{_('newVmSshKey')}
</label>
@@ -1201,13 +1207,18 @@ export default class NewVm extends BaseComponent {
<br />
<LineItem>
<label>
<input
checked={installMethod === 'customConfig'}
name='installMethod'
onChange={this._linkState('installMethod')}
type='radio'
value='customConfig'
/>
<Tooltip
content={CAN_CLOUD_INIT ? undefined : _('premiumOnly')}
>
<input
checked={installMethod === 'customConfig'}
disabled={!CAN_CLOUD_INIT}
name='installMethod'
onChange={this._linkState('installMethod')}
type='radio'
value='customConfig'
/>
</Tooltip>
&nbsp;
{_('newVmCustomConfig')}
</label>

View File

@@ -4,7 +4,6 @@ import getEventValue from 'get-event-value'
import Icon from 'icon'
import React from 'react'
import Tooltip from 'tooltip'
import Upgrade from 'xoa-upgrade'
import { Container, Row, Col } from 'grid'
import { Toggle } from 'form'
import { fetchHostStats } from 'xo'
@@ -96,100 +95,91 @@ export default class PoolStats extends Component {
useCombinedValues,
} = this.state
return process.env.XOA_PLAN > 2 ? (
stats ? (
<Container>
<Row>
<Col mediumSize={5}>
<div className='form-group'>
<Tooltip content={_('useStackedValuesOnStats')}>
<Toggle
value={useCombinedValues}
onChange={this.linkState('useCombinedValues')}
/>
</Tooltip>
</div>
</Col>
<Col mediumSize={1}>
{selectStatsLoading && (
<div className='text-xs-right'>
<Icon icon='loading' size={2} />
</div>
)}
</Col>
<Col mediumSize={6}>
<div className='btn-tab'>
<select
className='form-control'
onChange={this._handleSelectStats}
defaultValue={granularity}
>
{_('statLastTenMinutes', message => (
<option value='seconds'>{message}</option>
))}
{_('statLastTwoHours', message => (
<option value='minutes'>{message}</option>
))}
{_('statLastWeek', message => (
<option value='hours'>{message}</option>
))}
{_('statLastYear', message => (
<option value='days'>{message}</option>
))}
</select>
</div>
</Col>
</Row>
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='cpu' /> {_('statsCpu')}
</h5>
<PoolCpuLineChart addSumSeries={useCombinedValues} data={stats} />
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='memory' /> {_('statsMemory')}
</h5>
<PoolMemoryLineChart
addSumSeries={useCombinedValues}
data={stats}
/>
</Col>
</Row>
<br />
<hr />
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='network' /> {_('statsNetwork')}
</h5>
{/* key: workaround that unmounts and re-mounts the chart to make sure the legend updates when toggling "stacked values"
FIXME: remove key prop once this issue is fixed: https://github.com/CodeYellowBV/chartist-plugin-legend/issues/5 */}
<PoolPifLineChart
key={useCombinedValues ? 'stacked' : 'unstacked'}
addSumSeries={useCombinedValues}
data={stats}
/>
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='disk' /> {_('statLoad')}
</h5>
<PoolLoadLineChart
addSumSeries={useCombinedValues}
data={stats}
/>
</Col>
</Row>
</Container>
) : (
<p>{_('poolNoStats')}</p>
)
) : (
return stats ? (
<Container>
<Upgrade place='hostStats' available={3} />
<Row>
<Col mediumSize={5}>
<div className='form-group'>
<Tooltip content={_('useStackedValuesOnStats')}>
<Toggle
value={useCombinedValues}
onChange={this.linkState('useCombinedValues')}
/>
</Tooltip>
</div>
</Col>
<Col mediumSize={1}>
{selectStatsLoading && (
<div className='text-xs-right'>
<Icon icon='loading' size={2} />
</div>
)}
</Col>
<Col mediumSize={6}>
<div className='btn-tab'>
<select
className='form-control'
onChange={this._handleSelectStats}
defaultValue={granularity}
>
{_('statLastTenMinutes', message => (
<option value='seconds'>{message}</option>
))}
{_('statLastTwoHours', message => (
<option value='minutes'>{message}</option>
))}
{_('statLastWeek', message => (
<option value='hours'>{message}</option>
))}
{_('statLastYear', message => (
<option value='days'>{message}</option>
))}
</select>
</div>
</Col>
</Row>
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='cpu' /> {_('statsCpu')}
</h5>
<PoolCpuLineChart addSumSeries={useCombinedValues} data={stats} />
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='memory' /> {_('statsMemory')}
</h5>
<PoolMemoryLineChart
addSumSeries={useCombinedValues}
data={stats}
/>
</Col>
</Row>
<br />
<hr />
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='network' /> {_('statsNetwork')}
</h5>
{/* key: workaround that unmounts and re-mounts the chart to make sure the legend updates when toggling "stacked values"
FIXME: remove key prop once this issue is fixed: https://github.com/CodeYellowBV/chartist-plugin-legend/issues/5 */}
<PoolPifLineChart
key={useCombinedValues ? 'stacked' : 'unstacked'}
addSumSeries={useCombinedValues}
data={stats}
/>
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='disk' /> {_('statLoad')}
</h5>
<PoolLoadLineChart addSumSeries={useCombinedValues} data={stats} />
</Col>
</Row>
</Container>
) : (
<p>{_('poolNoStats')}</p>
)
}
}

View File

@@ -3,7 +3,6 @@ import Component from 'base-component'
import Icon from 'icon'
import React from 'react'
import Tooltip from 'tooltip'
import Upgrade from 'xoa-upgrade'
import { Container, Row, Col } from 'grid'
import { fetchSrStats } from 'xo'
import { get } from 'lodash'
@@ -85,81 +84,79 @@ export default class SrStats extends Component {
return data === undefined ? (
<span>{_('srNoStats')}</span>
) : (
<Upgrade place='srStats' available={3}>
<Container>
<Row>
<Col mediumSize={5}>
<div className='form-group'>
<Tooltip content={_('useStackedValuesOnStats')}>
<Toggle
value={useCombinedValues}
onChange={this.linkState('useCombinedValues')}
/>
</Tooltip>
<Container>
<Row>
<Col mediumSize={5}>
<div className='form-group'>
<Tooltip content={_('useStackedValuesOnStats')}>
<Toggle
value={useCombinedValues}
onChange={this.linkState('useCombinedValues')}
/>
</Tooltip>
</div>
</Col>
<Col mediumSize={1}>
{selectStatsLoading && (
<div className='text-xs-right'>
<Icon icon='loading' size={2} />
</div>
</Col>
<Col mediumSize={1}>
{selectStatsLoading && (
<div className='text-xs-right'>
<Icon icon='loading' size={2} />
</div>
)}
</Col>
<Col mediumSize={6}>
<div className='btn-tab'>
<select
className='form-control'
onChange={this._onGranularityChange}
defaultValue={granularity}
>
{_('statLastTenMinutes', message => (
<option value='seconds'>{message}</option>
))}
{_('statLastTwoHours', message => (
<option value='minutes'>{message}</option>
))}
{_('statLastWeek', message => (
<option value='hours'>{message}</option>
))}
{_('statLastYear', message => (
<option value='days'>{message}</option>
))}
</select>
</div>
</Col>
</Row>
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='iops' size={1} /> {_('statsIops')}
</h5>
<IopsLineChart addSumSeries={useCombinedValues} data={data} />
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='disk' size={1} /> {_('statsIoThroughput')}
</h5>
<IoThroughputChart addSumSeries={useCombinedValues} data={data} />
</Col>
</Row>
<br />
<hr />
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='latency' size={1} /> {_('statsLatency')}
</h5>
<LatencyChart addSumSeries={useCombinedValues} data={data} />
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='iowait' size={1} /> {_('statsIowait')}
</h5>
<IowaitChart addSumSeries={useCombinedValues} data={data} />
</Col>
</Row>
</Container>
</Upgrade>
)}
</Col>
<Col mediumSize={6}>
<div className='btn-tab'>
<select
className='form-control'
onChange={this._onGranularityChange}
defaultValue={granularity}
>
{_('statLastTenMinutes', message => (
<option value='seconds'>{message}</option>
))}
{_('statLastTwoHours', message => (
<option value='minutes'>{message}</option>
))}
{_('statLastWeek', message => (
<option value='hours'>{message}</option>
))}
{_('statLastYear', message => (
<option value='days'>{message}</option>
))}
</select>
</div>
</Col>
</Row>
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='iops' size={1} /> {_('statsIops')}
</h5>
<IopsLineChart addSumSeries={useCombinedValues} data={data} />
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='disk' size={1} /> {_('statsIoThroughput')}
</h5>
<IoThroughputChart addSumSeries={useCombinedValues} data={data} />
</Col>
</Row>
<br />
<hr />
<Row>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='latency' size={1} /> {_('statsLatency')}
</h5>
<LatencyChart addSumSeries={useCombinedValues} data={data} />
</Col>
<Col mediumSize={6}>
<h5 className='text-xs-center'>
<Icon icon='iowait' size={1} /> {_('statsIowait')}
</h5>
<IowaitChart addSumSeries={useCombinedValues} data={data} />
</Col>
</Row>
</Container>
)
}
}

View File

@@ -3,7 +3,6 @@ import Component from 'base-component'
import Icon from 'icon'
import React from 'react'
import Tooltip from 'tooltip'
import Upgrade from 'xoa-upgrade'
import { fetchVmStats } from 'xo'
import { Toggle } from 'form'
import { injectIntl } from 'react-intl'
@@ -105,7 +104,7 @@ export default injectIntl(
return !stats ? (
<p>No stats.</p>
) : process.env.XOA_PLAN > 2 ? (
) : (
<Container>
<Row>
<Col mediumSize={6}>
@@ -177,10 +176,6 @@ export default injectIntl(
</Col>
</Row>
</Container>
) : (
<Container>
<Upgrade place='vmStats' available={3} />
</Container>
)
}
}

View File

@@ -1,5 +1,7 @@
#!/bin/sh
set -eu
if [ $# -eq 0 ] || [ "$1" = "-h" ]
then
echo "Usage: $0 <package> <version>"

View File

@@ -28,6 +28,10 @@ require('exec-promise')(() =>
url: 'https://github.com/vatesfr/xen-orchestra.git',
}
if (!('version' in pkg)) {
pkg.version = '0.0.0'
}
delete pkg.standard
deleteProperties(pkg, 'config', ['commitizen'])
@@ -54,16 +58,26 @@ require('exec-promise')(() =>
])
deleteProperties(pkg, 'scripts', ['commitmsg', 'cz'])
const { scripts } = pkg
if (scripts !== undefined) {
const prepublish = scripts.prepublish
if (prepublish !== undefined && !('prepublishOnly' in scripts)) {
delete scripts.prepublish
scripts.prepublishOnly = prepublish
pkg.scripts = sortedObject(scripts)
let { scripts = {} } = pkg
const originalScripts = scripts
if (!pkg.private && !('postversion' in scripts)) {
scripts = { ...scripts, postversion: 'npm publish' }
}
const prepublish = scripts.prepublish
if (prepublish !== undefined && !('prepublishOnly' in scripts)) {
scripts = {
...scripts,
prepublishOnly: prepublish,
prepublish: undefined,
}
}
if (scripts !== originalScripts) {
pkg.scripts = sortedObject(scripts)
}
return Promise.all([
writeFile(`${dir}/package.json`, JSON.stringify(pkg, null, 2) + '\n'),
unlink(`${dir}/.editorconfig`),

1111
yarn.lock

File diff suppressed because it is too large Load Diff