Compare commits

...

173 Commits

Author SHA1 Message Date
Marc-André Pezin
78df47c726 license activation documentation 2020-03-31 10:22:01 +02:00
Julien Fontanet
efffbafa42 feat(xo-server,xo-web): checkpoint backups (#4252)
Fixes #645
2020-03-30 22:02:57 +02:00
Rajaa.BARHTAOUI
899cec8814 feat: technical release (#4888) 2020-03-27 15:59:51 +01:00
Pierre Donias
55beb993e5 feat(xo-web/xoa): handle XOA licenses (#3717) 2020-03-27 15:25:14 +01:00
badrAZ
fba46a1e00 feat(audit): contextualize integrity check error (#4879)
See #4798
2020-03-27 13:20:58 +01:00
Rajaa.BARHTAOUI
68c4d6f295 feat(xo-web/vm/backup): show backup jobs that include the VM (#4860)
Fixes #4623
2020-03-27 12:14:24 +01:00
Pierre Donias
2ad07c018e fix(xo-server/self): remove ACLs when user is removed from resource set (#4874) 2020-03-25 14:26:43 +01:00
badrAZ
c2418559f1 feat(xo-server/audit): add more data about open/close console event (#4867)
See #4798
2020-03-24 16:43:55 +01:00
badrAZ
de0277eb3b feat(xo-server-audit): ability to export records (#4858)
See #4798
2020-03-24 15:49:16 +01:00
Pierre Donias
b58802b495 fix(xo-web/recomputeAllLimits): force refresh the subscription 2020-03-24 13:19:01 +01:00
Pierre Donias
898e20e8b2 fix(xo-server/recomputeAllLimits): properly take IP pools into account 2020-03-24 13:19:01 +01:00
Pierre Donias
75bf10d83d chore(xo-server/self): computeVmResourcesUsage → computeVmXapiResourcesUsage 2020-03-24 13:19:01 +01:00
Pierre Donias
e8e58cc4a2 fix(xo-server/computeVmIpPoolsUsage): bad destructuring 2020-03-24 13:19:01 +01:00
Pierre Donias
342d02c8a8 fix(xo-web/VM resource set): handle unknown resource set (#4872)
In the VM's advanced tab, there was an "an error has occurred" whenever the user
couldn't access the VM's resource set.
2020-03-24 11:29:21 +01:00
badrAZ
ae885eaddc feat(xo-web/proxies): only deploy on HVM-capable SRs (#4849)
See #4825
2020-03-24 10:01:36 +01:00
badrAZ
b75bb4ed9f feat(proxy/deploy): ability to select the destination network (#4855)
See #4825
2020-03-23 19:42:18 +01:00
badrAZ
a171863591 fix(xo-server/xen-servers): pass type to getXenServerIdByObject (#4883) 2020-03-23 15:40:02 +01:00
badrAZ
bcc2286018 fix(xo-server/api): user_ip is not defined for scheduled jobs (#4878)
See https://xcp-ng.org/forum/topic/2752/jobs-not-running-error-no-value-for-user_ip/5

Context: The audit plugin needs to log the User IP to identify which user has executed an action. This IP is got from the client request, unfortunately, there is no client request for scheduled jobs and this case is not handled by the audit. It will be done in #4844.
2020-03-23 14:38:29 +01:00
Julien Fontanet
beb8b9723f feat(xo-server/xapi/utils/parseDateTime): throw on invalid input it no default value passed
See xoa-support#2277

Before it was simply returning `null` which can lead to bugs.
2020-03-23 11:06:53 +01:00
Jon Sands
ab3129b9c3 feat(docs/troubleshooting): clarify RAM allocation to XO (#4881) 2020-03-23 09:36:25 +01:00
badrAZ
c061505bf8 fix(xo-server/backup-ng): log instant failure task in case of missing VM (#4862)
Fixes #4857
2020-03-19 14:58:00 +01:00
Rajaa.BARHTAOUI
171bbedcde feat(xo-web/sr/disks): ability to migrate VDI (#4696)
Fixes #4455
See #4035
2020-03-19 11:40:25 +01:00
Julien Fontanet
ae655727c0 chore(CHANGELOG.unreleased): format with Prettier 2020-03-18 16:22:13 +01:00
Julien Fontanet
288b3783c3 fix(xo-server-auth-ldap): fix reading ca files
Fixes #4873
2020-03-18 16:21:25 +01:00
marcpezin
320612c826 feat(docs/continuous replication): failover process (#4870) 2020-03-17 11:34:52 +01:00
Julien Fontanet
9b0a293d2b chore(xo-server): update dep hashy@0.8.0
Remove unnecessary bcrypt dep, update argon2@0.25 which is compatible with newer Node versions.
2020-03-16 11:58:15 +01:00
W Anders
d5b6f27e97 fix(docs/configuration/custom ca): add note on Linux Capabilities (#4718) 2020-03-13 16:16:52 +01:00
Julien Fontanet
cf8bd759e3 feat(docs/from sources): Node 8 → LTS 2020-03-13 11:35:00 +01:00
Rajaa.BARHTAOUI
c2142c5cd9 fix(xo-web/set boot firmware): experimental warning on 8.0 only (#4780)
Fixes #4749
2020-03-12 11:56:06 +01:00
Nicolas Raynaud
eeef536803 fix(xo-server/importOvaVm): set memory_static_min (#4866) 2020-03-12 09:48:40 +01:00
Julien Fontanet
ec51cf7606 feat(xo-server-auth-{github,google,saml}): reload on configure (#4864)
Fixes #4863

Otherwise, the new configuration is not taken into account.
2020-03-12 09:35:51 +01:00
Pierre Donias
ec83b76e46 fix(xo-server/self): always de-allocate resources in case of failure (#4861)
See support#2240
2020-03-11 17:31:54 +01:00
badrAZ
6bc73f8f43 feat(proxy): ability to re-deploy a proxy (#4725)
See #4825
2020-03-11 17:01:17 +01:00
badrAZ
65127e04aa feat(xo-web/audit): remove useless step in the integrity check (#4846)
See #4798
2020-03-11 15:41:20 +01:00
Nicolas Raynaud
2726045fb0 fix(XOSAN): fix XOSAN installer (#4839) 2020-03-11 10:19:46 +01:00
Rajaa.BARHTAOUI
d4046c3295 feat(xo-web/xoa/support): add a link to create a support ticket (#4833)
Fixes #4234
2020-03-10 11:16:25 +01:00
marcpezin
97d4f5583c feat(docs/supported-version): add CH 8.0, 8.1 and XCP-ng 8.0 (#4786) 2020-03-10 09:49:43 +01:00
badrAZ
96dc36cd16 chore(xo-server/proxies): remove unused defer (#4859) 2020-03-09 16:42:55 +01:00
Julien Fontanet
ab2344ebfc feat(CHANGELOG): add missing release 5.43.3 2020-03-09 15:36:28 +01:00
Rajaa.BARHTAOUI
4dd7d86ea8 feat(xo-web/vm/migrate): choose network even within pool (#4828)
Fixes #2028
2020-03-09 10:29:04 +01:00
Julien Fontanet
6adfa618a3 feat(xo-cli): 0.11.0 2020-03-06 11:38:27 +01:00
Julien Fontanet
855e896a5a fix(CHANGELOG): syntax 2020-03-05 17:38:09 +01:00
Julien Fontanet
2bacb0f073 feat: release 5.44.1 (#4853) 2020-03-05 17:36:21 +01:00
Julien Fontanet
399131a5a9 feat: technical release (patch) (#4851) 2020-03-05 16:45:52 +01:00
Julien Fontanet
4c77be9e83 feat: add description for plugins (#4850) 2020-03-05 16:27:19 +01:00
Julien Fontanet
8ed5463f19 feat: technical release (#4845) 2020-03-05 12:16:39 +01:00
Julien Fontanet
63739df903 Merge branch '5.43' 2020-03-05 11:30:55 +01:00
Julien Fontanet
3d72232bb9 feat(xo-server): 5.56.3 2020-03-05 10:42:13 +01:00
Julien Fontanet
d5ff811de7 feat(xen-api): 0.28.2 2020-03-05 10:42:02 +01:00
Julien Fontanet
f74f47965c fix: revert to http-request-plus@0.8
Fixes #4774

There appears to be an issue with `pump` in `http-request-plus@0.9` which leads backups to never finish.
2020-03-05 10:29:24 +01:00
Pierre Donias
79adb7225e fix(xo-web/select-objects): clearer placeholder for SelectProxy (#4843) 2020-03-05 10:21:08 +01:00
Pierre Donias
11e79914ef feat(xo-web/audit): upgrade panel if insufficient plan (#4836)
See #4798
2020-03-05 10:15:00 +01:00
badrAZ
9b34fc369b fix(@xen-orchestra/fs): fix deadlock between "outputFile" and "mkdir" (#4831) 2020-03-04 16:07:50 +01:00
Rajaa.BARHTAOUI
ae812806a1 feat(xo-web/plugins): show plugin description (#4832)
Fixes #4569
2020-03-04 15:32:36 +01:00
Julien Fontanet
956c7728bf fix(CHANGELOG.unreleased): missing xen-api pkg 2020-03-04 14:26:14 +01:00
Julien Fontanet
6d5a5a46e4 feat(xo-server/createVdi): allow setting sm_config (#4841) 2020-03-04 08:43:28 +01:00
badrAZ
b244126d60 fix(@xen-orchestra/fs#write): dont call limited public methods (#4840) 2020-03-03 18:08:56 +01:00
Julien Fontanet
2a7f8c5229 fix(xen-api): accept TLSv1 which is used by XenServer 6.5 (#4837)
Fixes xoa-support#2216
2020-03-02 17:35:55 +01:00
Julien Fontanet
59fddf7c59 fix(xo-server/proxy.register): only returns the id 2020-03-02 11:59:01 +01:00
Julien Fontanet
d21fd2a1ed fix(xo-server/proxy.checkHealth): dont return server version 2020-03-02 11:59:01 +01:00
badrAZ
6828a5d9a0 fix(xo-server-backup-reports): handle interrupted root task (#4772) 2020-03-02 11:08:53 +01:00
Rajaa.BARHTAOUI
32960332b9 fix(xo-web): fix selectors (#4807) 2020-03-02 10:57:48 +01:00
BenjiReis
9ba77c9498 doc(sdn-controller): use correct XOA version (not xo-server one) (#4830) 2020-03-02 10:48:59 +01:00
Rajaa.BARHTAOUI
65f9a9dcc1 feat: release 5.44.0 (#4829) 2020-02-28 10:38:13 +01:00
Julien Fontanet
13315eec42 feat(xo-server): 5.57.2 2020-02-28 09:51:39 +01:00
Julien Fontanet
e43ccd155b fix(docs/xoa): bad markdown formatting 2020-02-28 09:10:54 +01:00
Julien Fontanet
e92960a413 fix(xo-server-logs): require level from level-party
This is not very clean but I dont want to add a `level` dependency to `xo-server` which might have a different version of the one provided by `level-party`.
2020-02-27 17:13:01 +01:00
Julien Fontanet
e82eec0cd6 feat(xo-server): 5.57.1 2020-02-27 16:14:13 +01:00
Julien Fontanet
23b687c528 feat(xo-server-auth-ldap/cli): default to adding as many items as present in default value 2020-02-27 14:02:21 +01:00
Julien Fontanet
5044a814a1 fix(xo-server-logs): missing JSON value encoding option 2020-02-27 10:58:18 +01:00
Julien Fontanet
3250b95f5e feat(xo-server-audit): 0.1.2 2020-02-27 10:16:11 +01:00
badrAZ
2a0934ec28 fix(xo-server-audit): missing @iarna/toml dep (#4827) 2020-02-27 10:15:36 +01:00
Julien Fontanet
f1752abc5d feat(xo-server-audit): 0.1.1 2020-02-27 09:53:27 +01:00
badrAZ
e931ec74dd fix(xo-server-audit): package config.toml (#4826) 2020-02-27 09:51:50 +01:00
Rajaa.BARHTAOUI
528d823c55 feat: technical release (#4823) 2020-02-26 17:25:53 +01:00
badrAZ
6475b58541 feat(audit-log): version 1 (#4740)
Fixes #4653 #701
2020-02-26 16:25:35 +01:00
badrAZ
59e8b26015 feat(xo-server/backup-ng): list existent backups on proxy remote (#4816)
See #4814
2020-02-26 14:32:26 +01:00
Julien Fontanet
0894c21296 feat(xen-api): setFields method 2020-02-26 14:30:12 +01:00
Julien Fontanet
4223bdd4ad feat(xo-server/deployProxy): dont destroy on error
Fixes #4815
2020-02-26 14:29:28 +01:00
badrAZ
c55ed42b2b feat(xo-server/backups-ng): ability to restore a VM via proxy (#4821)
See #4814
2020-02-26 13:58:17 +01:00
Rajaa.BARHTAOUI
7abc833ebe feat(xo-web/new-vm): ability to copy host bios strings (#4755)
Fixes #4204
2020-02-26 09:52:39 +01:00
Rajaa.BARHTAOUI
6abe399e36 feat(xo-web/sr/general): add a link to disks group (#4754)
Fixes #4747
2020-02-25 16:06:08 +01:00
Julien Fontanet
555b1a16da fix(xo-server-logs): level-sublevel → subleveldown 2020-02-25 10:31:42 +01:00
Julien Fontanet
52b956e677 fix(xo-server-logs): use indirect dep level 2020-02-25 10:31:35 +01:00
Julien Fontanet
0296cbe9e9 chore(xo-server/package.files): better-stacks.js no longer exists 2020-02-24 17:55:58 +01:00
Julien Fontanet
8315d7790a fix(xo-server-logs): better-stacks.js no longer exists 2020-02-24 17:55:58 +01:00
Rajaa.BARHTAOUI
dd60d289ff feat(xo-web/menu): warning in case of missing patches (#4683)
Fixes #4475
2020-02-21 16:14:07 +01:00
Pierre Donias
8c61fd0bf7 fix(xo-web/update): put current version first (#4795) 2020-02-21 14:15:41 +01:00
Pierre Donias
814e08edd4 fix(xo-web/vm/disks): don't pass null to Size component (#4811)
Fixes support#2181

- `vdi.size` should always be defined
- `null` was passed when `vdi.size` was `0`
2020-02-20 15:51:32 +01:00
badrAZ
44956dff85 fix(xo-server/proxies#deployProxy): unregister created proxy on failure (#4812) 2020-02-20 15:06:51 +01:00
badrAZ
18685d061a feat(proxy): ability to set the deployed VM network configuration (#4810) 2020-02-20 12:03:25 +01:00
Julien Fontanet
692d5be166 chore(xo-web/xoa/update): this._lowState.statestate 2020-02-18 16:21:17 +01:00
Julien Fontanet
60bdaef716 fix(xo-web/xoa/update): fix test for register-needed 2020-02-18 16:21:17 +01:00
Julien Fontanet
cb51f44a45 fix(xo-web/xoa-updater): handle all *-upgrade-needed states
Otherwise adding new namespaces in the updater will break state handling.
2020-02-18 16:21:17 +01:00
Julien Fontanet
88f43a8124 fix(xo-web/xoa/update): dont fail if channels is undefined
Which is always the case during loading.
2020-02-18 14:35:39 +01:00
Julien Fontanet
7de7cdba60 fix(xo-web/xoa/update): channels is an object not an array 2020-02-18 14:34:59 +01:00
BenjiReis
ba140c60e3 chore(sdn-controller/ovsdb-client): dont use set when not necessary (#4806) 2020-02-18 12:09:19 +01:00
BenjiReis
95a5c7a001 fix(sdn-controller/_hostUpdated): use splice instead of slice to remove newHost (#4805) 2020-02-17 17:23:58 +01:00
BenjiReis
b399da72d8 fix(sdn-controller): missing namespace for other_config/private-network-uuid (#4804) 2020-02-17 17:23:27 +01:00
BenjiReis
f9a10d8932 chore(xo-server-sdn-controller): various cleaning in the code (#4699) 2020-02-17 13:45:09 +01:00
Julien Fontanet
549ce6fbf9 feat(xo-server-auth-ldap): schedule release 0.7.0 2020-02-13 17:32:48 +01:00
BenjiReis
e63d27a035 feat(xo-server-sdn-controller): dynamically handle (dis)connected servers (fixes #4649) (#4677)
* feat(xo-server-sdn-controller): Dynamically monitor xapis dis/connection to XO (fixes #4649)

* fill changelog.unreleased.md

* adapt ro PR comments

* rename methods

* refactor code

* Update packages/xo-server-sdn-controller/src/index.js

Co-Authored-By: badrAZ <azizbibadr@gmail.com>

* refactor

* Update CHANGELOG.unreleased.md

Co-Authored-By: Julien Fontanet <julien.fontanet@isonoe.net>

* Update CHANGELOG.unreleased.md

Co-Authored-By: Julien Fontanet <julien.fontanet@isonoe.net>

* use native array map

* Better name for setControllerNeeded

* add try/catch block

* use correct check on objects

* fix previous commit

* remove useless emit

Co-authored-by: badrAZ <azizbibadr@gmail.com>
Co-authored-by: Julien Fontanet <julien.fontanet@isonoe.net>
2020-02-13 12:04:22 +01:00
badrAZ
ab3621fe3c fix(xo-server-usage-report): dynamic date (#4799)
Fixes #4779
2020-02-13 11:22:24 +01:00
Pierre Donias
8b99f2ecbc fix(xo-server/disk): remove unused resize method (#4796)
- resizing a VDI can be done with `vdi.set`
- `disk.resize` doesn't check Self Service constraints
2020-02-11 16:02:14 +01:00
Rajaa.BARHTAOUI
433b309907 feat: relase 5.43.2 (#4794) 2020-02-11 11:08:45 +01:00
badrAZ
ac40cec138 feat(xo-web/new-vm): ability to set VM max vCPUS (#4729)
Fixes #4703
2020-02-11 10:43:45 +01:00
Rajaa.BARHTAOUI
93702ece48 feat(xo-server): 5.56.2 (#4793) 2020-02-11 10:29:38 +01:00
Julien Fontanet
1678474830 chore: update yarn.lock 2020-02-11 10:24:38 +01:00
badrAZ
4260099c23 fix(xen-servers#getXenServer): should return raw server (#4791) 2020-02-11 10:05:33 +01:00
Julien Fontanet
6139cb50bc fix(server/backup): fix vms pattern when calling proxy (#4792) 2020-02-11 09:58:09 +01:00
Julien Fontanet
49e334d726 feat(@xen-orchestra/backups): 0.1.1 2020-02-11 09:25:04 +01:00
Julien Fontanet
6beded153b feat(backups/extractIdsFromSimplePattern): throw on invalid pattern 2020-02-11 09:23:26 +01:00
Julien Fontanet
750308a16a fix(backups/extractIdsFromSimplePattern): returns [] for undefined pattern 2020-02-11 09:22:09 +01:00
Julien Fontanet
57fa00b765 feat(bump-pkg): without version, simply update other packages 2020-02-10 15:58:03 +01:00
Julien Fontanet
b57d4fdbec feat(xen-api): 0.28.0 2020-02-10 15:40:39 +01:00
Julien Fontanet
93aca81265 feat(xen-api): way to add methods on record
Example: calling `Vm#foo()` will call `XenApi#VM_foo(vmRef)`.
2020-02-10 15:40:08 +01:00
Julien Fontanet
5c704e142e feat(xen-api): add $call and $callAsync on records 2020-02-10 15:38:20 +01:00
Julien Fontanet
1a4a77066e chore(xen-api/_watchEvents): add FIXME 2020-02-10 15:37:42 +01:00
Julien Fontanet
a690b9d825 feat(xen-api): export isOpaqueRef 2020-02-10 15:37:06 +01:00
Julien Fontanet
b70969fd03 feat(@xen-orchestra/backups): 0.1.0 2020-02-10 15:35:36 +01:00
Julien Fontanet
daf5fff83f feat(backups): add a bunch of utils 2020-02-10 15:34:20 +01:00
Rajaa.BARHTAOUI
aef1f9b857 feat: release 5.43.1 (#4785) 2020-02-06 10:58:42 +01:00
Rajaa.BARHTAOUI
c1c8ea7df0 feat: technical release (#4784) 2020-02-06 10:18:41 +01:00
BenjiReis
b75034b40c fix(xo-server-sdn-controller): match VLAN when selecting PIF on network creation (#4757)
Fixes #4737
2020-02-05 14:49:08 +01:00
Pierre Donias
cb41a79b36 fix(xo-web): use window.open instead of window.location (#4782)
Fixes #4709

Changing the location closes the WebSocket connection.
2020-02-05 10:51:07 +01:00
Pierre Donias
cedc20ce6a fix(doc/self): snapshots don't use the quota (#4781)
Since 75521f8757
2020-02-05 10:21:24 +01:00
Julien Fontanet
43bc1e9116 fix(auth-saml): add missing type for disableRequestedAuthnContext 2020-02-04 16:14:57 +01:00
Julien Fontanet
6fa1379c1e chore(xo-server): julien-f-unzipunzipper (#4717)
`julien-f-unzip` does not work with recent versions of Node.
2020-02-04 15:55:34 +01:00
Pierre Donias
cb16438b1c fix(xo-server/store): store.get returns a promise (#4776)
Fixes xoa-support#2137
2020-02-04 11:14:41 +01:00
badrAZ
e6c8d6cc7d fix(xo-server/proxy.update): only check address/VM duplicates on change (#4723)
See xoa#49
2020-02-03 09:37:54 +01:00
Rajaa.BARHTAOUI
f0e87e71ab chore(CHANGELOG): 5.43.0 (#4771) 2020-01-31 16:43:55 +01:00
Rajaa.BARHTAOUI
cdd28b8e31 feat: technical release (patch) (#4769) 2020-01-31 14:28:59 +01:00
Rajaa.BARHTAOUI
9bff564ace fix(xo-web/common): import Icon component (#4768) 2020-01-31 14:15:18 +01:00
Rajaa.BARHTAOUI
62c616c6af feat: technical release (#4767) 2020-01-31 12:16:55 +01:00
Julien Fontanet
8a35f5d6ca chore(CHANGELOG): format with Prettier 2020-01-31 12:04:03 +01:00
Rajaa.BARHTAOUI
e1b051324d feat(xo-web/migration): dont force migration by default (#4364)
Fixes #2136
2020-01-31 11:14:18 +01:00
badrAZ
a947c3152a fix(xo-server/network): create bond for each host (#4756)
Fixes #4529
2020-01-31 11:00:12 +01:00
badrAZ
cca43040d3 feat(xo-server/proxy): make static values configurable (#4724)
See xoa#49
2020-01-31 10:55:06 +01:00
badrAZ
9b42657ca7 fix(xo-server/proxy): ability to remove proxy VM (#4722)
See xoa#49
2020-01-31 10:43:49 +01:00
Rajaa.BARHTAOUI
bb19c55c3a fix(log): procces.stdout/stderr are undefined in browsers (#4765) 2020-01-31 10:32:39 +01:00
Pierre Donias
1ec6611410 feat(xo-web/proxy) (#4764)
See #4254
2020-01-31 09:48:41 +01:00
Pierre Donias
218bd0ffc1 feat(xo-server/proxy) (#4763)
See #4254
2020-01-30 16:32:26 +01:00
Julien Fontanet
d649a22b80 feat(log/transports/console): add colors 2020-01-30 15:25:54 +01:00
badrAZ
0bffbbfe65 fix(xo-web/backup/overview): disable job cancellation (#4688)
Fixes #4657
2020-01-30 10:48:03 +01:00
Rajaa.BARHTAOUI
04a562372b feat(xo-web/SelectTag): ability to manually add custom tags (#4648)
See #2810
2020-01-29 16:17:45 +01:00
Rajaa.BARHTAOUI
11b08ce53a feat(xo-web/tags): ability to add existing tags (#4530)
See #2810
2020-01-29 09:35:23 +01:00
Rajaa.BARHTAOUI
70f8f9679d feat(xo-web/home): allow to change the number of items per page (#4708)
See #4535
2020-01-27 17:11:58 +01:00
Julien Fontanet
4773f9ebf6 chore(xo-server-auth-ldap): use ldapts instead of unmaintained ldapjs (#4732) 2020-01-24 09:27:48 +01:00
Julien Fontanet
c1b6d1706a chore(vhd-lib): remove unused _constant-stream.js
Since 43822d3667
2020-01-21 15:35:07 +01:00
Jon Sands
9f94b8f915 feat(docs/concurrency): document VM exports limit (#4746) 2020-01-20 22:57:11 +01:00
badrAZ
3abd97d0fb chore(xo-server/xen-servers): delete duplicated logic (#4684) 2020-01-20 17:25:09 +01:00
Rajaa.BARHTAOUI
416a0687ee feat: release 5.42.1 (#4745) 2020-01-17 17:59:10 +01:00
Rajaa.BARHTAOUI
7056e20075 feat: technical release (#4744) 2020-01-17 16:50:06 +01:00
Julien Fontanet
de4b158a44 fix(xo-server): correct isValidXva import
Introduced by a456be9d7
2020-01-17 15:44:09 +01:00
Julien Fontanet
c7f4648d5a feat(xo-server/Xapi): make built-in concurrency limits configurable (#4743)
See xoa-support#2075
2020-01-17 13:44:22 +01:00
Julien Fontanet
a456be9d76 feat(xo-server/backup): check XVA file after creation (#4741)
See xoa-support#2017
2020-01-17 11:49:56 +01:00
badrAZ
3befaac114 feat(xo-web/log): add XOA info to bug report (#4692) 2020-01-14 16:23:29 +01:00
Julien Fontanet
11616ee03b feat(xo-server/snapshotVm): handle removed method (#4736)
Fixes #4735

This is necessary because CH 8.1 removed this method.
2020-01-14 10:09:01 +01:00
Julien Fontanet
2a59feddb6 feat(xen-api/barrier): add ms timestamp in barrier tags
Enable identification of stale entries.
2020-01-13 12:15:16 +01:00
Julien Fontanet
e2fa0aface chore(xo-server-auth-ldap): remove event-to-promise dep 2020-01-09 13:53:53 +01:00
Julien Fontanet
6d4d954713 chore(xo-server-auth-ldap): remove lodash dep 2020-01-09 11:59:42 +01:00
marcpezin
a4592ca425 feat(docs/xosan): remove legacy beta info (#4727) 2020-01-08 23:52:41 +01:00
Julien Fontanet
700eae4cc6 chore(backups-cli): move isValidXva into new backups package 2020-01-08 16:35:21 +01:00
Julien Fontanet
2c9fe6f37d feat(normalize-packages): pkgs are private by default 2020-01-08 16:21:13 +01:00
Julien Fontanet
558ede11cf fix(docs/README): use local XO logo
To avoid being detected as trackers and blocked.
2020-01-07 11:13:28 +01:00
Julien Fontanet
4c0a68ab0b chore(docs): remove unused cover image 2020-01-07 11:02:14 +01:00
Julien Fontanet
d6b4931001 chore(xo-server): julien-f-source-map-supportsource-map-support
`source-map-support` is correctly maintained and support modern Node versions.
2019-12-27 15:36:31 +01:00
Julien Fontanet
79ef01cb25 fix(xo-server/store): missing await 2019-12-26 11:09:28 +01:00
Julien Fontanet
ea8735f390 chore(xo-server): level-sublevelsubleveldown
`level-sublevel` is no longer maintained, `subleveldown` is the official replacement
2019-12-26 00:47:28 +01:00
Julien Fontanet
7b70855e94 chore(xo-server): remove direct level dep
This is an indirect dep via `level-party`.
2019-12-25 11:43:17 +01:00
Julien Fontanet
65f818b631 chore(backups-cli): only package relevant files 2019-12-25 11:12:16 +01:00
Julien Fontanet
0a0baeaeab feat(xo-server/blocked-at): disable by default 2019-12-23 16:12:06 +01:00
Julien Fontanet
e011ed1f64 chore: update dependencies 2019-12-23 14:39:03 +01:00
177 changed files with 7416 additions and 2503 deletions

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/async-map",
"version": "0.0.0",
"license": "ISC",

View File

@@ -0,0 +1,3 @@
module.exports = require('../../@xen-orchestra/babel-config')(
require('./package.json')
)

View File

@@ -0,0 +1,24 @@
/benchmark/
/benchmarks/
*.bench.js
*.bench.js.map
/examples/
example.js
example.js.map
*.example.js
*.example.js.map
/fixture/
/fixtures/
*.fixture.js
*.fixture.js.map
*.fixtures.js
*.fixtures.js.map
/test/
/tests/
*.spec.js
*.spec.js.map
__snapshots__/

View File

@@ -0,0 +1,40 @@
{
"name": "@xen-orchestra/audit-core",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/audit-core",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@xen-orchestra/audit-core",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"version": "0.1.1",
"engines": {
"node": ">=8.10"
},
"main": "dist/",
"scripts": {
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"postversion": "npm publish --access public",
"prebuild": "rimraf dist/",
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
},
"devDependencies": {
"@babel/cli": "^7.7.4",
"@babel/core": "^7.7.4",
"@babel/plugin-proposal-decorators": "^7.8.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.0",
"@babel/preset-env": "^7.7.4",
"@babel/preset-typescript": "^7.7.4",
"cross": "^1.0.0",
"rimraf": "^3.0.0"
},
"dependencies": {
"core-js": "^3.6.4",
"golike-defer": "^0.4.1",
"lodash": "^4.17.15",
"object-hash": "^2.0.1"
},
"private": false
}

View File

@@ -0,0 +1,142 @@
// see https://github.com/babel/babel/issues/8450
import 'core-js/features/symbol/async-iterator'
import assert from 'assert'
import defer from 'golike-defer'
import hash from 'object-hash'
export class Storage {
constructor() {
this._lock = Promise.resolve()
}
async acquireLock() {
const lock = this._lock
let releaseLock
this._lock = new Promise(resolve => {
releaseLock = resolve
})
await lock
return releaseLock
}
}
// Format: $<algorithm>$<salt>$<encrypted>
//
// http://man7.org/linux/man-pages/man3/crypt.3.html#NOTES
const ID_TO_ALGORITHM = {
'5': 'sha256',
}
export class AlteredRecordError extends Error {
constructor(id, nValid, record) {
super('altered record')
this.id = id
this.nValid = nValid
this.record = record
}
}
export class MissingRecordError extends Error {
constructor(id, nValid) {
super('missing record')
this.id = id
this.nValid = nValid
}
}
export const NULL_ID = 'nullId'
const HASH_ALGORITHM_ID = '5'
const createHash = (data, algorithmId = HASH_ALGORITHM_ID) =>
`$${algorithmId}$$${hash(data, {
algorithm: ID_TO_ALGORITHM[algorithmId],
excludeKeys: key => key === 'id',
})}`
export class AuditCore {
constructor(storage) {
assert.notStrictEqual(storage, undefined)
this._storage = storage
}
@defer
async add($defer, subject, event, data) {
const time = Date.now()
const storage = this._storage
$defer(await storage.acquireLock())
// delete "undefined" properties and normalize data with JSON.stringify
const record = JSON.parse(
JSON.stringify({
data,
event,
previousId: (await storage.getLastId()) ?? NULL_ID,
subject,
time,
})
)
record.id = createHash(record)
await storage.put(record)
await storage.setLastId(record.id)
return record
}
async checkIntegrity(oldest, newest) {
const storage = this._storage
// handle separated chains case
if (newest !== (await storage.getLastId())) {
let isNewestAccessible = false
for await (const { id } of this.getFrom()) {
if (id === newest) {
isNewestAccessible = true
break
}
}
if (!isNewestAccessible) {
throw new MissingRecordError(newest, 0)
}
}
let nValid = 0
while (newest !== oldest) {
const record = await storage.get(newest)
if (record === undefined) {
throw new MissingRecordError(newest, nValid)
}
if (
newest !== createHash(record, newest.slice(1, newest.indexOf('$', 1)))
) {
throw new AlteredRecordError(newest, nValid, record)
}
newest = record.previousId
nValid++
}
return nValid
}
async *getFrom(newest) {
const storage = this._storage
let id = newest ?? (await storage.getLastId())
if (id === undefined) {
return
}
let record
while ((record = await storage.get(id)) !== undefined) {
yield record
id = record.previousId
}
}
async deleteFrom(newest) {
assert.notStrictEqual(newest, undefined)
for await (const { id } of this.getFrom(newest)) {
await this._storage.del(id)
}
}
}

View File

@@ -0,0 +1,126 @@
/* eslint-env jest */
import {
AlteredRecordError,
AuditCore,
MissingRecordError,
NULL_ID,
Storage,
} from '.'
const asyncIteratorToArray = async asyncIterator => {
const array = []
for await (const entry of asyncIterator) {
array.push(entry)
}
return array
}
class DB extends Storage {
constructor() {
super()
this._db = new Map()
this._lastId = undefined
}
async put(record) {
this._db.set(record.id, record)
}
async setLastId(id) {
this._lastId = id
}
async getLastId() {
return this._lastId
}
async del(id) {
this._db.delete(id)
}
async get(id) {
return this._db.get(id)
}
_clear() {
return this._db.clear()
}
}
const DATA = [
[
{
name: 'subject0',
},
'event0',
{},
],
[
{
name: 'subject1',
},
'event1',
{},
],
[
{
name: 'subject2',
},
'event2',
{},
],
]
const db = new DB()
const auditCore = new AuditCore(db)
const storeAuditRecords = async () => {
await Promise.all(DATA.map(data => auditCore.add(...data)))
const records = await asyncIteratorToArray(auditCore.getFrom())
expect(records.length).toBe(DATA.length)
return records
}
describe('auditCore', () => {
afterEach(() => db._clear())
it('detects that a record is missing', async () => {
const [newestRecord, deletedRecord] = await storeAuditRecords()
const nValidRecords = await auditCore.checkIntegrity(
NULL_ID,
newestRecord.id
)
expect(nValidRecords).toBe(DATA.length)
await db.del(deletedRecord.id)
await expect(
auditCore.checkIntegrity(NULL_ID, newestRecord.id)
).rejects.toEqual(new MissingRecordError(deletedRecord.id, 1))
})
it('detects that a record has been altered', async () => {
const [newestRecord, alteredRecord] = await storeAuditRecords()
alteredRecord.event = ''
await db.put(alteredRecord)
await expect(
auditCore.checkIntegrity(NULL_ID, newestRecord.id)
).rejects.toEqual(
new AlteredRecordError(alteredRecord.id, 1, alteredRecord)
)
})
it('confirms interval integrity after deletion of records outside of the interval', async () => {
const [thirdRecord, secondRecord, firstRecord] = await storeAuditRecords()
await auditCore.deleteFrom(secondRecord.id)
expect(await db.get(firstRecord.id)).toBe(undefined)
expect(await db.get(secondRecord.id)).toBe(undefined)
await auditCore.checkIntegrity(secondRecord.id, thirdRecord.id)
})
})

View File

@@ -0,0 +1,25 @@
class Storage {
acquire: () => Promise<() => undefined>
del: (id: string) => Promise<void>
get: (id: string) => Promise<Record | void>
getLastId: () => Promise<string | void>
put: (record: Record) => Promise<void>
setLastId: (id: string) => Promise<void>
}
interface Record {
data: object
event: string
id: string
previousId: string
subject: object
time: number
}
export class AuditCore {
constructor(storage: Storage) {}
public add(subject: any, event: string, data: any): Promise<Record> {}
public checkIntegrity(oldest: string, newest: string): Promise<number> {}
public getFrom(newest?: string): AsyncIterator {}
public deleteFrom(newest: string): Promise<void> {}
}

View File

@@ -8,6 +8,7 @@ let force
const assert = require('assert')
const flatten = require('lodash/flatten')
const getopts = require('getopts')
const isValidXva = require('@xen-orchestra/backups/isValidXva')
const lockfile = require('proper-lockfile')
const pipe = require('promise-toolbox/pipe')
const { default: Vhd } = require('vhd-lib')
@@ -21,70 +22,6 @@ const handler = require('@xen-orchestra/fs').getHandler({ url: 'file://' })
// -----------------------------------------------------------------------------
const isGzipFile = async fd => {
// https://tools.ietf.org/html/rfc1952.html#page-5
const magicNumber = Buffer.allocUnsafe(2)
assert.strictEqual(
await fs.read(fd, magicNumber, 0, magicNumber.length, 0),
magicNumber.length
)
return magicNumber[0] === 31 && magicNumber[1] === 139
}
// TODO: better check?
//
// our heuristic is not good enough, there has been some false positives
// (detected as invalid by us but valid by `tar` and imported with success),
// either THOUGH THEY MAY HAVE BEEN COMPRESSED FILES:
// - these files were normal but the check is incorrect
// - these files were invalid but without data loss
// - these files were invalid but with silent data loss
//
// maybe reading the end of the file looking for a file named
// /^Ref:\d+/\d+\.checksum$/ and then validating the tar structure from it
//
// https://github.com/npm/node-tar/issues/234#issuecomment-538190295
const isValidTar = async (size, fd) => {
if (size <= 1024 || size % 512 !== 0) {
return false
}
const buf = Buffer.allocUnsafe(1024)
assert.strictEqual(
await fs.read(fd, buf, 0, buf.length, size - buf.length),
buf.length
)
return buf.every(_ => _ === 0)
}
// TODO: find an heuristic for compressed files
const isValidXva = async path => {
try {
const fd = await fs.open(path, 'r')
try {
const { size } = await fs.fstat(fd)
if (size < 20) {
// neither a valid gzip not tar
return false
}
return (await isGzipFile(fd))
? true // gzip files cannot be validated at this time
: await isValidTar(size, fd)
} finally {
fs.close(fd).catch(noop)
}
} catch (error) {
// never throw, log and report as valid to avoid side effects
console.error('isValidXva', path, error)
return true
}
}
const noop = Function.prototype
// -----------------------------------------------------------------------------
// chain is an array of VHDs from child to parent
//
// the whole chain will be merged into parent, parent will be renamed to child

View File

@@ -1,10 +1,12 @@
{
"private": false,
"bin": {
"xo-backups": "index.js"
},
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"dependencies": {
"@xen-orchestra/fs": "^0.10.2",
"@xen-orchestra/backups": "^0.1.1",
"@xen-orchestra/fs": "^0.10.3",
"filenamify": "^4.1.0",
"getopts": "^2.2.5",
"lodash": "^4.17.15",
@@ -15,6 +17,10 @@
"engines": {
"node": ">=7.10.1"
},
"files": [
"commands",
"*.js"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/backups-cli",
"name": "@xen-orchestra/backups-cli",
"repository": {

View File

@@ -0,0 +1,30 @@
function extractIdsFromSimplePattern(pattern) {
if (pattern === undefined) {
return []
}
if (pattern !== null && typeof pattern === 'object') {
let keys = Object.keys(pattern)
if (keys.length === 1 && keys[0] === 'id') {
pattern = pattern.id
if (typeof pattern === 'string') {
return [pattern]
}
if (pattern !== null && typeof pattern === 'object') {
keys = Object.keys(pattern)
if (
keys.length === 1 &&
keys[0] === '__or' &&
Array.isArray((pattern = pattern.__or)) &&
pattern.every(_ => typeof _ === 'string')
) {
return pattern
}
}
}
}
throw new Error('invalid pattern')
}
exports.extractIdsFromSimplePattern = extractIdsFromSimplePattern

View File

@@ -0,0 +1,6 @@
const { utcFormat, utcParse } = require('d3-time-format')
// Format a date in ISO 8601 in a safe way to be used in filenames
// (even on Windows).
exports.formatFilenameDate = utcFormat('%Y%m%dT%H%M%SZ')
exports.parseFilenameDate = utcParse('%Y%m%dT%H%M%SZ')

View File

@@ -0,0 +1,7 @@
// returns all entries but the last retention-th
exports.getOldEntries = (retention, entries) =>
entries === undefined
? []
: retention > 0
? entries.slice(0, -retention)
: entries

View File

@@ -0,0 +1,65 @@
const assert = require('assert')
const fs = require('fs-extra')
const isGzipFile = async fd => {
// https://tools.ietf.org/html/rfc1952.html#page-5
const magicNumber = Buffer.allocUnsafe(2)
assert.strictEqual(
(await fs.read(fd, magicNumber, 0, magicNumber.length, 0)).bytesRead,
magicNumber.length
)
return magicNumber[0] === 31 && magicNumber[1] === 139
}
// TODO: better check?
//
// our heuristic is not good enough, there has been some false positives
// (detected as invalid by us but valid by `tar` and imported with success),
// either THOUGH THEY MAY HAVE BEEN COMPRESSED FILES:
// - these files were normal but the check is incorrect
// - these files were invalid but without data loss
// - these files were invalid but with silent data loss
//
// maybe reading the end of the file looking for a file named
// /^Ref:\d+/\d+\.checksum$/ and then validating the tar structure from it
//
// https://github.com/npm/node-tar/issues/234#issuecomment-538190295
const isValidTar = async (size, fd) => {
if (size <= 1024 || size % 512 !== 0) {
return false
}
const buf = Buffer.allocUnsafe(1024)
assert.strictEqual(
(await fs.read(fd, buf, 0, buf.length, size - buf.length)).bytesRead,
buf.length
)
return buf.every(_ => _ === 0)
}
// TODO: find an heuristic for compressed files
const isValidXva = async path => {
try {
const fd = await fs.open(path, 'r')
try {
const { size } = await fs.fstat(fd)
if (size < 20) {
// neither a valid gzip not tar
return false
}
return (await isGzipFile(fd))
? true // gzip files cannot be validated at this time
: await isValidTar(size, fd)
} finally {
fs.close(fd).catch(noop)
}
} catch (error) {
// never throw, log and report as valid to avoid side effects
console.error('isValidXva', path, error)
return true
}
}
exports.isValidXva = isValidXva
const noop = Function.prototype

View File

@@ -0,0 +1,22 @@
{
"private": false,
"name": "@xen-orchestra/backups",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/backups",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@xen-orchestra/backups",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"version": "0.1.1",
"engines": {
"node": ">=8.10"
},
"scripts": {
"postversion": "npm publish --access public"
},
"dependencies": {
"d3-time-format": "^2.2.3",
"fs-extra": "^8.1.0"
}
}

View File

@@ -0,0 +1,11 @@
exports.watchStreamSize = stream => {
const container = { size: 0 }
const isPaused = stream.isPaused()
stream.on('data', data => {
container.size += data.length
})
if (isPaused) {
stream.pause()
}
return container
}

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/cr-seed-cli",
"version": "0.2.0",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/cr-seed-cli",
@@ -16,7 +17,7 @@
},
"dependencies": {
"golike-defer": "^0.4.1",
"xen-api": "^0.27.3"
"xen-api": "^0.28.3"
},
"scripts": {
"postversion": "npm publish"

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/cron",
"version": "1.0.6",
"license": "ISC",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/defined",
"version": "0.0.0",
"license": "ISC",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/emit-async",
"version": "0.0.0",
"license": "ISC",

View File

@@ -1,6 +1,7 @@
{
"private": false,
"name": "@xen-orchestra/fs",
"version": "0.10.2",
"version": "0.10.3",
"license": "AGPL-3.0",
"description": "The File System for Xen Orchestra backups.",
"keywords": [],

View File

@@ -118,7 +118,7 @@ export default class RemoteHandlerAbstract {
}
async closeFile(fd: FileDescriptor): Promise<void> {
await timeout.call(this._closeFile(fd.fd), this._timeout)
await this.__closeFile(fd)
}
async createOutputStream(
@@ -283,30 +283,15 @@ export default class RemoteHandlerAbstract {
}
async mkdir(dir: string): Promise<void> {
dir = normalizePath(dir)
try {
await this._mkdir(dir)
} catch (error) {
if (error == null || error.code !== 'EEXIST') {
throw error
}
// this operation will throw if it's not already a directory
await this._list(dir)
}
await this.__mkdir(normalizePath(dir))
}
async mktree(dir: string): Promise<void> {
await this._mktree(normalizePath(dir))
}
async openFile(path: string, flags: string): Promise<FileDescriptor> {
path = normalizePath(path)
return {
fd: await timeout.call(this._openFile(path, flags), this._timeout),
path,
}
openFile(path: string, flags: string): Promise<FileDescriptor> {
return this.__openFile(path, flags)
}
async outputFile(
@@ -455,6 +440,34 @@ export default class RemoteHandlerAbstract {
await this._writeFile(normalizePath(file), data, { flags })
}
// Methods that can be called by private methods to avoid parallel limit on public methods
async __closeFile(fd: FileDescriptor): Promise<void> {
await timeout.call(this._closeFile(fd.fd), this._timeout)
}
async __mkdir(dir: string): Promise<void> {
try {
await this._mkdir(dir)
} catch (error) {
if (error == null || error.code !== 'EEXIST') {
throw error
}
// this operation will throw if it's not already a directory
await this._list(dir)
}
}
async __openFile(path: string, flags: string): Promise<FileDescriptor> {
path = normalizePath(path)
return {
fd: await timeout.call(this._openFile(path, flags), this._timeout),
path,
}
}
// Methods that can be implemented by inheriting classes
async _closeFile(fd: mixed): Promise<void> {
@@ -503,7 +516,7 @@ export default class RemoteHandlerAbstract {
async _mktree(dir: string): Promise<void> {
try {
return await this.mkdir(dir)
return await this.__mkdir(dir)
} catch (error) {
if (error.code !== 'ENOENT') {
throw error
@@ -586,13 +599,13 @@ export default class RemoteHandlerAbstract {
async _write(file: File, buffer: Buffer, position: number): Promise<void> {
const isPath = typeof file === 'string'
if (isPath) {
file = await this.openFile(file, 'r+')
file = await this.__openFile(file, 'r+')
}
try {
return await this._writeFd(file, buffer, position)
} finally {
if (isPath) {
await this.closeFile(file)
await this.__closeFile(file)
}
}
}

View File

@@ -219,6 +219,12 @@ handlers.forEach(url => {
const error = await rejectionOf(handler.outputFile('file', ''))
expect(error.code).toBe('EEXIST')
})
it("shouldn't timeout in case of the respect of the parallel execution restriction", async () => {
const handler = getHandler({ url }, { maxParallelOperations: 1 })
await handler.sync()
await handler.outputFile(`xo-fs-tests-${Date.now()}/test`, '')
}, 40)
})
describe('#read()', () => {

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/log",
"version": "0.2.0",
"license": "ISC",

View File

@@ -1,6 +1,85 @@
import LEVELS, { NAMES } from '../levels'
const { ERROR, INFO, WARN } = LEVELS
const { DEBUG, ERROR, FATAL, INFO, WARN } = LEVELS
let formatLevel, formatNamespace
if (
process.stdout !== undefined &&
process.stdout.isTTY &&
process.stderr !== undefined &&
process.stderr.isTTY
) {
const ansi = (style, str) => `\x1b[${style}m${str}\x1b[0m`
const LEVEL_STYLES = {
[DEBUG]: '2',
[ERROR]: '1;31',
[FATAL]: '1;31',
[INFO]: '1',
[WARN]: '1;33',
}
formatLevel = level => {
const style = LEVEL_STYLES[level]
const name = NAMES[level]
return style === undefined ? name : ansi(style, name)
}
const NAMESPACE_COLORS = [
196,
202,
208,
214,
220,
226,
190,
154,
118,
82,
46,
47,
48,
49,
50,
51,
45,
39,
33,
27,
21,
57,
93,
129,
165,
201,
200,
199,
198,
197,
]
formatNamespace = namespace => {
// https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
let hash = 0
for (let i = 0, n = namespace.length; i < n; ++i) {
hash = ((hash << 5) - hash + namespace.charCodeAt(i)) | 0
}
// // select a hue (HSV)
// const h = (Math.abs(hash) % 20) * 18
// // convert to RGB
// const f = (n, k = (n + h / 60) % 6) =>
// Math.round(255 * (1 - Math.max(Math.min(k, 4 - k, 1), 0)))
// const r = f(5)
// const g = f(3)
// const b = f(1)
// return ansi(`38;2;${r};${g};${b}`, namespace)
return ansi(
`1;38;5;${NAMESPACE_COLORS[Math.abs(hash) % NAMESPACE_COLORS.length]}`,
namespace
)
}
} else {
formatLevel = str => NAMES[str]
formatNamespace = str => str
}
const consoleTransport = ({ data, level, namespace, message, time }) => {
const fn =
@@ -14,7 +93,12 @@ const consoleTransport = ({ data, level, namespace, message, time }) => {
: console.error
/* eslint-enable no-console */
const args = [time.toISOString(), namespace, NAMES[level], message]
const args = [
time.toISOString(),
formatNamespace(namespace),
formatLevel(level),
message,
]
if (data != null) {
args.push(data)
}

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/mixin",
"version": "0.0.0",
"license": "ISC",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "@xen-orchestra/template",
"version": "0.1.0",
"license": "ISC",

View File

@@ -4,19 +4,186 @@
### Enhancements
- [VM migration] Ability to choose network for migration within a pool [#2028](https://github.com/vatesfr/xen-orchestra/issues/2028) (PR [#4828](https://github.com/vatesfr/xen-orchestra/pull/4828))
- [Support] Link to create a new support ticket [#4234](https://github.com/vatesfr/xen-orchestra/issues/4234) (PR [#4833](https://github.com/vatesfr/xen-orchestra/pull/4833))
- [Proxies] Ability to redeploy a proxy VM [#4825](https://github.com/vatesfr/xen-orchestra/issues/4825) (PR [#4725](https://github.com/vatesfr/xen-orchestra/pull/4725))
- [SR / Disks] Ability to migrate VDIs [#4455](https://github.com/vatesfr/xen-orchestra/issues/4455) (PR [#4696](https://github.com/vatesfr/xen-orchestra/pull/4696))
- [Proxy / Deploy] Ability to select the destination network [#4825](https://github.com/vatesfr/xen-orchestra/issues/4825) (PR [#4855](https://github.com/vatesfr/xen-orchestra/pull/4855))
- [Proxies/Deploy] Remove SRs not connected to an HVM-capable host from selection [#4825](https://github.com/vatesfr/xen-orchestra/issues/4825) (PR [#4849](https://github.com/vatesfr/xen-orchestra/pull/4849))
- [Audit] Ability to export records [#4798](https://github.com/vatesfr/xen-orchestra/issues/4798) (PR [#4858](https://github.com/vatesfr/xen-orchestra/pull/4858))
- [VM/backup] Show backup jobs [#4623](https://github.com/vatesfr/xen-orchestra/issues/4623) (PR [#4860](https://github.com/vatesfr/xen-orchestra/pull/4860))
- [Audit] Improve integrity check feedback [#4798](https://github.com/vatesfr/xen-orchestra/issues/4798) (PR [#4879](https://github.com/vatesfr/xen-orchestra/pull/4879))
- [XOA] Manage the XOA licenses from the xoa/licenses page (PR [#3717](https://github.com/vatesfr/xen-orchestra/pull/3717))
### Bug fixes
- [XOSAN] Fix the installer (PR [#4839](https://github.com/vatesfr/xen-orchestra/pull/4839))
- [OVA Import] Fix _no host available_ error when starting for imported VMs with low memory (PR [#4866](https://github.com/vatesfr/xen-orchestra/pull/4866))
- [Self] When a Self Service related operation fails, always revert the quotas to what they were before the operation (PR [#4861](https://github.com/vatesfr/xen-orchestra/pull/4861))
- [auth-{github,google,saml}] Don't require manually reloading the plugin for configuration changes to take effect [#4863](https://github.com/vatesfr/xen-orchestra/issues/4863) (PR [#4864](https://github.com/vatesfr/xen-orchestra/pull/4864))
- [auth-ldap] Fix reading certificate authorities files [#3873](https://github.com/vatesfr/xen-orchestra/issues/3873)
- [Backup NG / logs] Replace successful backup job status by failed status in case of missing VMs [#4857](https://github.com/vatesfr/xen-orchestra/issues/4857) (PR [#4862](https://github.com/vatesfr/xen-orchestra/pull/4862))
- [Jobs] Fix "no value for `user_ip`" error on jobs execution (PR [#4878](https://github.com/vatesfr/xen-orchestra/pull/4878))
- [Self] Properly take IP pools into account when computing quotas (PR [#4871](https://github.com/vatesfr/xen-orchestra/pull/4871))
### Released packages
- @xen-orchestra/audit-core 0.1.1
- xo-server-audit 0.2.0
- xo-server-auth-github 0.2.2
- xo-server-auth-google 0.2.2
- xo-server-auth-ldap 0.7.1
- xo-server-auth-saml 0.7.2
- xo-server 5.58.0
- xo-web 5.58.0
## **5.42.0** (2019-12-20)
## **5.44.1** (2020-03-05)
![Channel: latest](https://badgen.net/badge/channel/latest/yellow)
### Enhancements
- [Plugin] Show plugin description [#4569](https://github.com/vatesfr/xen-orchestra/issues/4569) (PR [#4832](https://github.com/vatesfr/xen-orchestra/pull/4832))
### Bug fixes
- [Backup reports] Fix backup report not sent in case of interrupted backup job (PR [#4772](https://github.com/vatesfr/xen-orchestra/pull/4772))
- Fix TLS error (`unsupported protocol`) with XenServer <= 6.5 and Node >= 12 (PR [#8437](https://github.com/vatesfr/xen-orchestra/pull/8437))
- [Metadata backup] Fix timeout when lots of pools are backed up [#4819](https://github.com/vatesfr/xen-orchestra/issues/4819) (PR [#4831](https://github.com/vatesfr/xen-orchestra/pull/4831))
### Released packages
- @xen-orchestra/fs v0.10.3
- xen-api v0.28.3
- xo-server-backup-reports v0.16.5
- xo-server-perf-alert v0.2.1
- xo-server-sdn-controller v0.4.1
- xo-server-transport-icinga2 v0.1.1
- xo-server-transport-nagios v0.1.1
- xo-server-usage-report v0.7.5
- xo-server-web-hooks v0.1.1
- xo-server v5.57.3
- xo-web v5.57.1
## **5.44.0** (2020-02-28)
### Highlights
- [Audit log] Record side effects triggered by users [#4653](https://github.com/vatesfr/xen-orchestra/issues/4653) [#701](https://github.com/vatesfr/xen-orchestra/issues/701) (PR [#4740](https://github.com/vatesfr/xen-orchestra/pull/4740))
- [SR/general] Clickable SR usage graph: shows the corresponding disks when you click on one of the sections [#4747](https://github.com/vatesfr/xen-orchestra/issues/4747) (PR [#4754](https://github.com/vatesfr/xen-orchestra/pull/4754))
- [New VM] Ability to copy host BIOS strings [#4204](https://github.com/vatesfr/xen-orchestra/issues/4204) (PR [4755](https://github.com/vatesfr/xen-orchestra/pull/4755))
- [New VM] Ability to set VM max vCPUS [#4703](https://github.com/vatesfr/xen-orchestra/issues/4703) (PR [#4729](https://github.com/vatesfr/xen-orchestra/pull/4729))
### Enhancements
- [SDN Controller] Automatically handle new, connected and disconnected servers (PR [#4677](https://github.com/vatesfr/xen-orchestra/pull/4677))
- [Proxy] Support network configuration for the deployed proxy (PR [#4810](https://github.com/vatesfr/xen-orchestra/pull/4810))
- [Menu] Display a warning icon in case of missing patches [#4475](https://github.com/vatesfr/xen-orchestra/issues/4475) (PR [#4683](https://github.com/vatesfr/xen-orchestra/pull/4683))
### Bug fixes
- [Usage Report] Fix wrong report date [#4779](https://github.com/vatesfr/xen-orchestra/issues/4779) (PR [#4799](https://github.com/vatesfr/xen-orchestra/pull/4799))
- [SDN Controller] Fix plugin stuck loading [#4649](https://github.com/vatesfr/xen-orchestra/issues/4649) (PR [#4677](https://github.com/vatesfr/xen-orchestra/pull/4677))
- [xo-server-logs] Fix `Cannot find module '../better-stacks'`
### Released packages
- xo-common v0.4.0
- @xen-orchestra/audit-core v0.1.0
- xo-server-audit v0.1.2
- xo-server-auth-ldap v0.7.0
- xo-server-usage-report v0.7.4
- xo-server-sdn-controller v0.4.0
- xo-server v5.57.2
- xo-web v5.57.0
## **5.43.3** (2020-03-06)
![Channel: stable](https://badgen.net/badge/channel/stable/green)
### Bug fixes
- [Backups] Fix an issue where DR and CR could stay stuck (commit [63739df](https://github.com/vatesfr/xen-orchestra/commit/63739df90369798f16b61bf96d1a89513c7edc77))
### Released packages
- xo-server v5.56.3
## **5.43.2** (2020-02-11)
### Bug fixes
- [Proxy] Correctly call the proxy when running backups (PRs [#4791](https://github.com/vatesfr/xen-orchestra/pull/4791) & [#4792](https://github.com/vatesfr/xen-orchestra/pull/4792))
### Released packages
- xo-server v5.56.2
## **5.43.1** (2020-02-06)
### Bug fixes
- [Self,IP pools] Fixed the creation being stuck and freezing XO (PR [#4776](https://github.com/vatesfr/xen-orchestra/pull/4776))
- [SDN Controller] Ensure the correct PIF is used to create private networks tunnels [#4737](https://github.com/vatesfr/xen-orchestra/issues/4737) (PR [#4757](https://github.com/vatesfr/xen-orchestra/pull/4757))
### Released packages
- xo-server-sdn-controller v0.3.2
- xo-server-auth-saml 0.7.1
- xo-server v5.56.1
- xo-web v5.56.2
## **5.43.0** (2020-01-31)
### Highlights
- [Home] Allow to change the number of items per page [#4535](https://github.com/vatesfr/xen-orchestra/issues/4535) (PR [#4708](https://github.com/vatesfr/xen-orchestra/pull/4708))
- [Tag] Adding a tag: ability to select from existing tags [#2810](https://github.com/vatesfr/xen-orchestra/issues/2810) (PR [#4530](https://github.com/vatesfr/xen-orchestra/pull/4530))
- [Smart backup] Ability to manually add custom tags [#2810](https://github.com/vatesfr/xen-orchestra/issues/2810) (PR [#4648](https://github.com/vatesfr/xen-orchestra/pull/4648))
- [Proxy] Ability to backup VMs via registered proxy [#4254](https://github.com/vatesfr/xen-orchestra/issues/4254) (PR [#4495](https://github.com/vatesfr/xen-orchestra/pull/4495))
### Enhancements
- [VM/Migrate] Ask user before forcing migration [#2136](https://github.com/vatesfr/xen-orchestra/issues/2136) (PR [#4364](https://github.com/vatesfr/xen-orchestra/pull/4364))
### Bug fixes
- [New network] Fix bonded network not linked to the slave hosts [#4529](https://github.com/vatesfr/xen-orchestra/issues/4529) (PR [#4756](https://github.com/vatesfr/xen-orchestra/pull/4756))
### Dropped features
- [Backup / Overview] Job cancellation will be disabled until we find a way to make it work [#4657](https://github.com/vatesfr/xen-orchestra/issues/4657) (PR [#4688](https://github.com/vatesfr/xen-orchestra/pull/4688))
### Released packages
- xo-common v0.3.0
- xo-server v5.56.0
- xo-web v5.56.1
## **5.42.1** (2020-01-17)
### Enhancements
- [Snapshot] Fallback to normal snapshot if quiesce is not available [#4735](https://github.com/vatesfr/xen-orchestra/issues/4735) (PR [#4736](https://github.com/vatesfr/xen-orchestra/pull/4736)) \
Fixes compatibility with **Citrix Hypervisor 8.1**.
- [Uncompressed full backup] Quick healthcheck of downloaded XVAs in case there was an undetected issue (PR [#4741](https://github.com/vatesfr/xen-orchestra/pull/4741))
- [Backup] Make built-in concurrency limits configurable (PR [#4743](https://github.com/vatesfr/xen-orchestra/pull/4743)) \
Via the following entries in `xo-server`'s configuration file:
- `xapiOptions.vdiExportConcurrency`
- `xapiOptions.vmExportConcurrency`
- `xapiOptions.vmSnapshotConcurrency`
### Released packages
- xo-server v5.55.0
- xo-web v5.55.0
## **5.42.0** (2019-12-20)
### Highlights
- [SDN Controller] Allow private network creation on bond and VLAN (PR [#4682](https://github.com/vatesfr/xen-orchestra/pull/4682))
- [Hub/recipes] [Ability to create a kubernetes cluster](https://xen-orchestra.com/blog/devblog-5-kubernetes-clutser-on-xo/) (PR [#4695](https://github.com/vatesfr/xen-orchestra/pull/4695))
- [Hub/recipes][ability to create a kubernetes cluster](https://xen-orchestra.com/blog/devblog-5-kubernetes-clutser-on-xo/) (PR [#4695](https://github.com/vatesfr/xen-orchestra/pull/4695))
### Enhancements
@@ -29,13 +196,11 @@
## **5.41.0** (2019-11-29)
![Channel: stable](https://badgen.net/badge/channel/stable/green)
### Highlights
- [Backup NG] Make report recipients configurable in the backup settings [#4581](https://github.com/vatesfr/xen-orchestra/issues/4581) (PR [#4646](https://github.com/vatesfr/xen-orchestra/pull/4646))
- [Host] Advanced Live Telemetry (PR [#4680](https://github.com/vatesfr/xen-orchestra/pull/4680))
- [Plugin] [Web hooks](https://xen-orchestra.com/docs/web-hooks.html) [#1946](https://github.com/vatesfr/xen-orchestra/issues/1946) (PR [#3155](https://github.com/vatesfr/xen-orchestra/pull/3155))
- [Plugin][web hooks](https://xen-orchestra.com/docs/web-hooks.html) [#1946](https://github.com/vatesfr/xen-orchestra/issues/1946) (PR [#3155](https://github.com/vatesfr/xen-orchestra/pull/3155))
### Enhancements
@@ -131,7 +296,6 @@
- xo-server-cloud : this package was useless for OpenSource installations because it required a complete XOA environment
## **5.39.1** (2019-10-11)
### Enhancements
@@ -147,7 +311,6 @@
- xo-web v5.50.3
## **5.39.0** (2019-09-30)
### Highlights
@@ -189,7 +352,6 @@
- [Backup NG] Properly log and report if job is already running [#4497](https://github.com/vatesfr/xen-orchestra/issues/4497) (PR [4534](https://github.com/vatesfr/xen-orchestra/pull/4534))
- [Host] Fix an issue where host was wrongly reporting time inconsistency (PR [#4540](https://github.com/vatesfr/xen-orchestra/pull/4540))
### Released packages
- xen-api v0.27.2
@@ -200,7 +362,6 @@
- xo-server v5.50.1
- xo-web v5.50.2
## **5.38.0** (2019-08-29)
### Enhancements
@@ -377,9 +538,9 @@
### Bug fixes
- [Continuous Replication] Fix VHD size guess for empty files [#4105](https://github.com/vatesfr/xen-orchestra/issues/4105) (PR [#4107](https://github.com/vatesfr/xen-orchestra/pull/4107))
- [Continuous Replication] Fix VHD size guess for empty files [#4105](https://github.com/vatesfr/xen-orchestra/issues/4105) (PR [#4107](https://github.com/vatesfr/xen-orchestra/pull/4107))
- [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))
- [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))
@@ -415,7 +576,7 @@
- Enable compression for HTTP requests (and initial objects fetch)
- [VDI migration] Display same-pool SRs first in the selector [#3945](https://github.com/vatesfr/xen-orchestra/issues/3945) (PR [#3996](https://github.com/vatesfr/xen-orchestra/pull/3996))
- [Home] Save the current page in url [#3993](https://github.com/vatesfr/xen-orchestra/issues/3993) (PR [#3999](https://github.com/vatesfr/xen-orchestra/pull/3999))
- [VDI] Ensure suspend VDI is destroyed when destroying a VM [#4027](https://github.com/vatesfr/xen-orchestra/issues/4027) (PR [#4038](https://github.com/vatesfr/xen-orchestra/pull/4038))
- [VDI] Ensure suspend VDI is destroyed when destroying a VM [#4027](https://github.com/vatesfr/xen-orchestra/issues/4027) (PR [#4038](https://github.com/vatesfr/xen-orchestra/pull/4038))
- [VM/disk]: Warning when 2 VDIs are on 2 different hosts' local SRs [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#3969](https://github.com/vatesfr/xen-orchestra/pull/3969))
- [Remotes] Benchmarks (read and write rate speed) added when remote is tested [#3991](https://github.com/vatesfr/xen-orchestra/issues/3991) (PR [#4015](https://github.com/vatesfr/xen-orchestra/pull/4015))
- [Cloud Config] Support both NoCloud and Config Drive 2 datasources for maximum compatibility (PR [#4053](https://github.com/vatesfr/xen-orchestra/pull/4053))
@@ -490,7 +651,7 @@
- [Home/VM] Show creation date of the VM on if it available [#3953](https://github.com/vatesfr/xen-orchestra/issues/3953) (PR [#3959](https://github.com/vatesfr/xen-orchestra/pull/3959))
- [Notifications] Fix invalid notifications when not registered (PR [#3966](https://github.com/vatesfr/xen-orchestra/pull/3966))
- [Import] Fix import of some OVA files [#3962](https://github.com/vatesfr/xen-orchestra/issues/3962) (PR [#3974](https://github.com/vatesfr/xen-orchestra/pull/3974))
- [Servers] Fix *already connected error* after a server has been removed during connection [#3976](https://github.com/vatesfr/xen-orchestra/issues/3976) (PR [#3977](https://github.com/vatesfr/xen-orchestra/pull/3977))
- [Servers] Fix _already connected error_ after a server has been removed during connection [#3976](https://github.com/vatesfr/xen-orchestra/issues/3976) (PR [#3977](https://github.com/vatesfr/xen-orchestra/pull/3977))
- [Backup] Fix random _mount_ issues with NFS/SMB remotes [#3973](https://github.com/vatesfr/xen-orchestra/issues/3973) (PR [#4003](https://github.com/vatesfr/xen-orchestra/pull/4003))
### Released packages
@@ -567,7 +728,7 @@
- [Self] Display sorted Resource Sets [#3818](https://github.com/vatesfr/xen-orchestra/issues/3818) (PR [#3823](https://github.com/vatesfr/xen-orchestra/pull/3823))
- [Servers] Correctly report connecting status (PR [#3838](https://github.com/vatesfr/xen-orchestra/pull/3838))
- [Servers] Fix cannot reconnect to a server after connection has been lost [#3839](https://github.com/vatesfr/xen-orchestra/issues/3839) (PR [#3841](https://github.com/vatesfr/xen-orchestra/pull/3841))
- [New VM] Fix `NO_HOSTS_AVAILABLE()` error when creating a VM on a local SR from template on another local SR [#3084](https://github.com/vatesfr/xen-orchestra/issues/3084) (PR [#3827](https://github.com/vatesfr/xen-orchestra/pull/3827))
- [New VM] Fix `NO_HOSTS_AVAILABLE()` error when creating a VM on a local SR from template on another local SR [#3084](https://github.com/vatesfr/xen-orchestra/issues/3084) (PR [#3827](https://github.com/vatesfr/xen-orchestra/pull/3827))
- [Backup NG] Fix typo in the form [#3854](https://github.com/vatesfr/xen-orchestra/issues/3854) (PR [#3855](https://github.com/vatesfr/xen-orchestra/pull/3855))
- [New SR] No warning when creating a NFS SR on a path that is already used as NFS SR [#3844](https://github.com/vatesfr/xen-orchestra/issues/3844) (PR [#3851](https://github.com/vatesfr/xen-orchestra/pull/3851))
- [New SR] No redirection if the SR creation failed or canceled [#3843](https://github.com/vatesfr/xen-orchestra/issues/3843) (PR [#3853](https://github.com/vatesfr/xen-orchestra/pull/3853))
@@ -579,7 +740,7 @@
- [VM creation] Broken CloudInit config drive when VM created on local SR
- [Legacy Backup] Fix error when restoring a backup
- [Home] Fix `user.getAll` error when user is not admin [#3573](https://github.com/vatesfr/xen-orchestra/issues/3573) (PR [#3918](https://github.com/vatesfr/xen-orchestra/pull/3918))
- [Backup NG] Fix restore issue when a disk has grown [#3910](https://github.com/vatesfr/xen-orchestra/issues/3910) (PR [#3920](https://github.com/vatesfr/xen-orchestra/pull/3920))
- [Backup NG] Fix restore issue when a disk has grown [#3910](https://github.com/vatesfr/xen-orchestra/issues/3910) (PR [#3920](https://github.com/vatesfr/xen-orchestra/pull/3920))
- [Backup NG] Delete _importing_ VMs due to interrupted CR/DR (PR [#3923](https://github.com/vatesfr/xen-orchestra/pull/3923))
### Released packages
@@ -807,7 +968,7 @@
### Enhancements
- [Remotes] Test the remote automatically on changes [#3323](https://github.com/vatesfr/xen-orchestra/issues/3323) (PR [#3397](https://github.com/vatesfr/xen-orchestra/pull/3397))
- [Remotes] Use *WORKGROUP* as default domain for new SMB remote (PR [#3398](https://github.com/vatesfr/xen-orchestra/pull/3398))
- [Remotes] Use _WORKGROUP_ as default domain for new SMB remote (PR [#3398](https://github.com/vatesfr/xen-orchestra/pull/3398))
- [Backup NG form] Display a tip to encourage users to create vms on a thin-provisioned storage [#3334](https://github.com/vatesfr/xen-orchestra/issues/3334) (PR [#3402](https://github.com/vatesfr/xen-orchestra/pull/3402))
- [Backup NG form] improve schedule's form [#3138](https://github.com/vatesfr/xen-orchestra/issues/3138) (PR [#3359](https://github.com/vatesfr/xen-orchestra/pull/3359))
- [Backup NG Overview] Display transferred and merged data size for backup jobs [#3340](https://github.com/vatesfr/xen-orchestra/issues/3340) (PR [#3408](https://github.com/vatesfr/xen-orchestra/pull/3408))
@@ -824,7 +985,7 @@
- [Backup NG] Don't fail on VMs with empty VBDs (like CDs or floppy disks) (PR [#3410](https://github.com/vatesfr/xen-orchestra/pull/3410))
- [XOA updater] Fix issue where trial request would fail [#3407](https://github.com/vatesfr/xen-orchestra/issues/3407) (PR [#3412](https://github.com/vatesfr/xen-orchestra/pull/3412))
- [Backup NG logs] Fix log's value not being updated in the copy and report button [#3273](https://github.com/vatesfr/xen-orchestra/issues/3273) (PR [#3360](https://github.com/vatesfr/xen-orchestra/pull/3360))
- [Backup NG] Fix issue when *Delete first* was enabled for some of the remotes [#3424](https://github.com/vatesfr/xen-orchestra/issues/3424) (PR [#3427](https://github.com/vatesfr/xen-orchestra/pull/3427))
- [Backup NG] Fix issue when _Delete first_ was enabled for some of the remotes [#3424](https://github.com/vatesfr/xen-orchestra/issues/3424) (PR [#3427](https://github.com/vatesfr/xen-orchestra/pull/3427))
- [VM/host consoles] Work around a XenServer/XCP-ng issue which lead to some consoles not working [#3432](https://github.com/vatesfr/xen-orchestra/issues/3432) (PR [#3435](https://github.com/vatesfr/xen-orchestra/pull/3435))
- [Backup NG] Remove extraneous snapshots in case of multiple schedules [#3132](https://github.com/vatesfr/xen-orchestra/issues/3132) (PR [#3439](https://github.com/vatesfr/xen-orchestra/pull/3439))
- [Backup NG] Fix page reloaded on creating a schedule [#3461](https://github.com/vatesfr/xen-orchestra/issues/3461) (PR [#3462](https://github.com/vatesfr/xen-orchestra/pull/3462))
@@ -1004,7 +1165,7 @@
- Make cloud config templates available for all users [3147](https://github.com/vatesfr/xen-orchestra/issues/3147) (PR [3148](https://github.com/vatesfr/xen-orchestra/pull/3148))
- [New VM] Only create the cloud config drive when its option is enabled [3161](https://github.com/vatesfr/xen-orchestra/issues/3161) (PR [3162](https://github.com/vatesfr/xen-orchestra/pull/3162))
- Fix error when installing patches from the host or without a default SR (PR [3166](https://github.com/vatesfr/xen-orchestra/pull/3166))
- [Backup NG] Fix SMB *Not implemented* issue [#3149](](https://github.com/vatesfr/xen-orchestra/issues/3149) (PR [3175](https://github.com/vatesfr/xen-orchestra/pull/3175))
- [Backup NG] Fix SMB _Not implemented_ issue [#3149](<](https://github.com/vatesfr/xen-orchestra/issues/3149)> 'PR [3175](https://github.com/vatesfr/xen-orchestra/pull/3175')
### Released packages
@@ -1118,10 +1279,9 @@
- Hook/action if an export stream is cut [#1929](https://github.com/vatesfr/xen-orchestra/issues/1929)
- Backup paths should not contain tags but job ids [#1854](https://github.com/vatesfr/xen-orchestra/issues/1854)
- Add a button to delete a backup [#1751](https://github.com/vatesfr/xen-orchestra/issues/1751)
- Dashboard available for Pool and Host level [#1631](https://github.com/vatesfr/xen-orchestra/issues/1631)
- UI Enhancement - VM list - Allways show the Toolbar [#1581](https://github.com/vatesfr/xen-orchestra/issues/1581)
- xoa-updater --register: unable to define proxy using the CLI [#873](https://github.com/vatesfr/xen-orchestra/issues/873)
- Dashboard available for Pool and Host level [#1631](https://github.com/vatesfr/xen-orchestra/issues/1631)
- UI Enhancement - VM list - Allways show the Toolbar [#1581](https://github.com/vatesfr/xen-orchestra/issues/1581)
- xoa-updater --register: unable to define proxy using the CLI [#873](https://github.com/vatesfr/xen-orchestra/issues/873)
### Bugs
@@ -1162,7 +1322,7 @@
- Set a self-service VM at "share" after creation [#2589](https://github.com/vatesfr/xen-orchestra/issues/2589)
- [Backup logs] Improve Unhealthy VDI Chain message [#2586](https://github.com/vatesfr/xen-orchestra/issues/2586)
- [SortedTable] Put sort criteria in URL like the filter [#2584](https://github.com/vatesfr/xen-orchestra/issues/2584)
- Cant attach XenTools on User side. [#2503](https://github.com/vatesfr/xen-orchestra/issues/2503)
- Cant attach XenTools on User side. [#2503](https://github.com/vatesfr/xen-orchestra/issues/2503)
- Pool filter for health view [#2302](https://github.com/vatesfr/xen-orchestra/issues/2302)
- [Smart Backup] Improve feedback [#2253](https://github.com/vatesfr/xen-orchestra/issues/2253)
- Backup jobs stuck if no space left on NFS remote [#2116](https://github.com/vatesfr/xen-orchestra/issues/2116)
@@ -1193,7 +1353,7 @@
- Move VM In to/Out of Self Service Group [#1913](https://github.com/vatesfr/xen-orchestra/issues/1913)
- Two factor auth [#1897](https://github.com/vatesfr/xen-orchestra/issues/1897)
- token.create should accept an expiration [#1769](https://github.com/vatesfr/xen-orchestra/issues/1769)
- Self Service User - User don't have quota in his dashboard [#1538](https://github.com/vatesfr/xen-orchestra/issues/1538)
- Self Service User - User don't have quota in his dashboard [#1538](https://github.com/vatesfr/xen-orchestra/issues/1538)
- Remove CoffeeScript in xo-server [#189](https://github.com/vatesfr/xen-orchestra/issues/189)
- Better Handling of suspending VMs from the Home screen [#2547](https://github.com/vatesfr/xen-orchestra/issues/2547)
- [xen-api] Stronger reconnection policy [#2410](https://github.com/vatesfr/xen-orchestra/issues/2410)
@@ -1212,7 +1372,6 @@
- TZ selector is not used for backup schedule preview [#2464](https://github.com/vatesfr/xen-orchestra/issues/2464)
- Remove filter in VM/network view [#2548](https://github.com/vatesfr/xen-orchestra/issues/2548)
## **5.15.0** (2017-12-29)
### Enhancements
@@ -1221,7 +1380,7 @@
- Smart replace VDI.pool_migrate removed from XenServer 7.3 Free [#2541](https://github.com/vatesfr/xen-orchestra/issues/2541)
- New memory constraints in XenServer 7.3 [#2540](https://github.com/vatesfr/xen-orchestra/issues/2540)
- Link to Settings/Logs for admins in error notifications [#2516](https://github.com/vatesfr/xen-orchestra/issues/2516)
- [Self Service] Do not use placehodlers to describe inputs [#2509](https://github.com/vatesfr/xen-orchestra/issues/2509)
- [Self Service] Do not use placehodlers to describe inputs [#2509](https://github.com/vatesfr/xen-orchestra/issues/2509)
- Obfuscate password in log in LDAP plugin test [#2506](https://github.com/vatesfr/xen-orchestra/issues/2506)
- Log rotation [#2492](https://github.com/vatesfr/xen-orchestra/issues/2492)
- Continuous Replication TAG [#2473](https://github.com/vatesfr/xen-orchestra/issues/2473)
@@ -1238,7 +1397,6 @@
- Cloud config drive create fail on XenServer < 7 [#2478](https://github.com/vatesfr/xen-orchestra/issues/2478)
- VM create fails due to missing vGPU id [#2466](https://github.com/vatesfr/xen-orchestra/issues/2466)
## **5.14.0** (2017-10-31)
### Enhancements
@@ -1288,9 +1446,9 @@
- Warning on SMB remote creation [#2316](https://github.com/vatesfr/xen-orchestra/issues/2316)
- [Home | SortedTable] Add link to syntax doc in the filter input [#2305](https://github.com/vatesfr/xen-orchestra/issues/2305)
- [SortedTable] Add optional binding of filter to an URL query [#2301](https://github.com/vatesfr/xen-orchestra/issues/2301)
- [Home][Keyboard navigation] Allow selecting the objects [#2214](https://github.com/vatesfr/xen-orchestra/issues/2214)
- [Home][keyboard navigation] Allow selecting the objects [#2214](https://github.com/vatesfr/xen-orchestra/issues/2214)
- SR view / Disks: option to display non managed VDIs [#1724](https://github.com/vatesfr/xen-orchestra/issues/1724)
- Continuous Replication Retention [#1692](https://github.com/vatesfr/xen-orchestra/issues/1692)
- Continuous Replication Retention [#1692](https://github.com/vatesfr/xen-orchestra/issues/1692)
### Bugs
@@ -1298,7 +1456,7 @@
- Errors in VM copy are not properly reported [#2347](https://github.com/vatesfr/xen-orchestra/issues/2347)
- Removing a PIF IP fails [#2346](https://github.com/vatesfr/xen-orchestra/issues/2346)
- Review and fix creating a VM from a snapshot [#2343](https://github.com/vatesfr/xen-orchestra/issues/2343)
- iSCSI LUN Detection fails with authentification [#2339](https://github.com/vatesfr/xen-orchestra/issues/2339)
- iSCSI LUN Detection fails with authentification [#2339](https://github.com/vatesfr/xen-orchestra/issues/2339)
- Fix PoolActionBar to add a new SR [#2307](https://github.com/vatesfr/xen-orchestra/issues/2307)
- [VM migration] Error if default SR not accessible to target host [#2180](https://github.com/vatesfr/xen-orchestra/issues/2180)
- A job shouldn't executable more than once at the same time [#2053](https://github.com/vatesfr/xen-orchestra/issues/2053)
@@ -1316,9 +1474,9 @@
- [SortedTable] Add grouped actions feature [#2276](https://github.com/vatesfr/xen-orchestra/issues/2276)
- Add a filter to the backups' log [#2246](https://github.com/vatesfr/xen-orchestra/issues/2246)
- It should not be possible to migrate a halted VM. [#2233](https://github.com/vatesfr/xen-orchestra/issues/2233)
- [Home][Keyboard navigation] Allow selecting the objects [#2214](https://github.com/vatesfr/xen-orchestra/issues/2214)
- [Home][keyboard navigation] Allow selecting the objects [#2214](https://github.com/vatesfr/xen-orchestra/issues/2214)
- Allow to set pool master [#2213](https://github.com/vatesfr/xen-orchestra/issues/2213)
- Continuous Replication Retention [#1692](https://github.com/vatesfr/xen-orchestra/issues/1692)
- Continuous Replication Retention [#1692](https://github.com/vatesfr/xen-orchestra/issues/1692)
### Bugs
@@ -1399,8 +1557,7 @@
- Select is "moving" [\#2142](https://github.com/vatesfr/xen-orchestra/issues/2142)
- Select issue for affinity host [\#2141](https://github.com/vatesfr/xen-orchestra/issues/2141)
- Dashboard Storage Usage incorrect [\#2123](https://github.com/vatesfr/xen-orchestra/issues/2123)
- Detect unmerged *base copy* and prevent too long chains [\#2047](https://github.com/vatesfr/xen-orchestra/issues/2047)
- Detect unmerged _base copy_ and prevent too long chains [\#2047](https://github.com/vatesfr/xen-orchestra/issues/2047)
## **5.8.0** (2017-04-28)
@@ -1462,7 +1619,7 @@
- Missing objects should be displayed in backup edition [\#2052](https://github.com/vatesfr/xen-orchestra/issues/2052)
- Search bar content changes while typing [\#2035](https://github.com/vatesfr/xen-orchestra/issues/2035)
- VM.$guest_metrics.PV_drivers_up_to_date is deprecated in XS 7.1 [\#2024](https://github.com/vatesfr/xen-orchestra/issues/2024)
- VM.\$guest_metrics.PV_drivers_up_to_date is deprecated in XS 7.1 [\#2024](https://github.com/vatesfr/xen-orchestra/issues/2024)
- Bootable flag selection checkbox for extra disk not fetched [\#1994](https://github.com/vatesfr/xen-orchestra/issues/1994)
- Home view Changing type must reset paging [\#1993](https://github.com/vatesfr/xen-orchestra/issues/1993)
- XOSAN menu item should only be displayed to admins [\#1968](https://github.com/vatesfr/xen-orchestra/issues/1968)
@@ -1548,7 +1705,7 @@ File level restore.
- Use paginated table for backup jobs [\#1726](https://github.com/vatesfr/xen-orchestra/issues/1726)
- SR view / Disks: should display snapshot VDIs [\#1723](https://github.com/vatesfr/xen-orchestra/issues/1723)
- Restored VM should have an identifiable name [\#1719](https://github.com/vatesfr/xen-orchestra/issues/1719)
- If host reboot action returns NO\_HOSTS\_AVAILABLE, ask to force [\#1717](https://github.com/vatesfr/xen-orchestra/issues/1717)
- If host reboot action returns NO_HOSTS_AVAILABLE, ask to force [\#1717](https://github.com/vatesfr/xen-orchestra/issues/1717)
- Hide xo-server timezone in backups [\#1706](https://github.com/vatesfr/xen-orchestra/issues/1706)
- Enable hyperlink for Hostname for Issues [\#1700](https://github.com/vatesfr/xen-orchestra/issues/1700)
- Pool/network - Modify column [\#1696](https://github.com/vatesfr/xen-orchestra/issues/1696)
@@ -1572,15 +1729,15 @@ File level restore.
- Should jobs be accessible to non admins? [\#1759](https://github.com/vatesfr/xen-orchestra/issues/1759)
- Schedules deletion is not working [\#1737](https://github.com/vatesfr/xen-orchestra/issues/1737)
- Editing a job from the jobs overview page does not work [\#1736](https://github.com/vatesfr/xen-orchestra/issues/1736)
- Editing a schedule from jobs overview does not work [\#1728](https://github.com/vatesfr/xen-orchestra/issues/1728)
- Editing a job from the jobs overview page does not work [\#1736](https://github.com/vatesfr/xen-orchestra/issues/1736)
- Editing a schedule from jobs overview does not work [\#1728](https://github.com/vatesfr/xen-orchestra/issues/1728)
- ACLs not correctly imported [\#1722](https://github.com/vatesfr/xen-orchestra/issues/1722)
- Some Bootstrap style broken [\#1721](https://github.com/vatesfr/xen-orchestra/issues/1721)
- Not properly sign out on auth token expiration [\#1711](https://github.com/vatesfr/xen-orchestra/issues/1711)
- Hosts/<UUID>/network status is incorrect [\#1702](https://github.com/vatesfr/xen-orchestra/issues/1702)
- Patches application fails "Found : Moved Temporarily" [\#1701](https://github.com/vatesfr/xen-orchestra/issues/1701)
- Password generation for user creation is not working [\#1678](https://github.com/vatesfr/xen-orchestra/issues/1678)
- \#/dashboard/health Remove All Orphaned VDIs [\#1622](https://github.com/vatesfr/xen-orchestra/issues/1622)
- \#/dashboard/health Remove All Orphaned VDIs [\#1622](https://github.com/vatesfr/xen-orchestra/issues/1622)
- Create a new SR - CIFS/SAMBA Broken [\#1615](https://github.com/vatesfr/xen-orchestra/issues/1615)
- xo-cli --list-objects: truncated output ? 64k buffer limitation ? [\#1356](https://github.com/vatesfr/xen-orchestra/issues/1356)
@@ -1759,7 +1916,7 @@ File level restore.
- Button to recompute resource sets limits [\#1287](https://github.com/vatesfr/xen-orchestra/issues/1287)
- Credit scheduler CAP and weight configuration [\#1283](https://github.com/vatesfr/xen-orchestra/issues/1283)
- Migration form problem on the /v5/vms/\_\_UUID\_\_ page when doing xenmotion inside a pool [\#1254](https://github.com/vatesfr/xen-orchestra/issues/1254)
- /v5/\#/pools/\_\_UUID\_\_: patch table improvement [\#1246](https://github.com/vatesfr/xen-orchestra/issues/1246)
- /v5/\#/pools/\_\_UUID\_\_: patch table improvement [\#1246](https://github.com/vatesfr/xen-orchestra/issues/1246)
- /v5/\#/hosts/\_\_UUID\_\_: patch list improvements ? [\#1245](https://github.com/vatesfr/xen-orchestra/issues/1245)
- F\*cking patches, how do they work? [\#1236](https://github.com/vatesfr/xen-orchestra/issues/1236)
- Change Default Filter [\#1235](https://github.com/vatesfr/xen-orchestra/issues/1235)
@@ -1814,7 +1971,7 @@ File level restore.
- Scheduled jobs seems use GMT since 5.0 [\#1258](https://github.com/vatesfr/xen-orchestra/issues/1258)
- Can't create a VM with disks on 2 different SRs [\#1257](https://github.com/vatesfr/xen-orchestra/issues/1257)
- Graph display bug [\#1247](https://github.com/vatesfr/xen-orchestra/issues/1247)
- /v5/#/hosts/__UUID__: Patch list not limited to the current pool [\#1244](https://github.com/vatesfr/xen-orchestra/issues/1244)
- /v5/#/hosts/**UUID**: Patch list not limited to the current pool [\#1244](https://github.com/vatesfr/xen-orchestra/issues/1244)
- Replication issues [\#1233](https://github.com/vatesfr/xen-orchestra/issues/1233)
- VM creation install method disabled fields [\#1198](https://github.com/vatesfr/xen-orchestra/issues/1198)
- Update icon shouldn't be displayed when menu is collapsed [\#1188](https://github.com/vatesfr/xen-orchestra/issues/1188)
@@ -1852,10 +2009,10 @@ File level restore.
- Show HVM, PVM, PVHVM modes in guest details [\#806](https://github.com/vatesfr/xen-orchestra/issues/806)
- Tree view: display cpu available/total for each host [\#696](https://github.com/vatesfr/xen-orchestra/issues/696)
- Greenkeeper integration [\#667](https://github.com/vatesfr/xen-orchestra/issues/667)
- Clarify vCPUs and RAM editor [\#658](https://github.com/vatesfr/xen-orchestra/issues/658)
- Clarify vCPUs and RAM editor [\#658](https://github.com/vatesfr/xen-orchestra/issues/658)
- Backup LZ4 compression [\#647](https://github.com/vatesfr/xen-orchestra/issues/647)
- Support enum in plugins configuration [\#638](https://github.com/vatesfr/xen-orchestra/issues/638)
- Add configuration option to disable xoa-updater [\#535](https://github.com/vatesfr/xen-orchestra/issues/535)
- Add configuration option to disable xoa-updater [\#535](https://github.com/vatesfr/xen-orchestra/issues/535)
- Use cursors to add more context to actions [\#523](https://github.com/vatesfr/xen-orchestra/issues/523)
- Review UI for flat view [\#354](https://github.com/vatesfr/xen-orchestra/issues/354)
- Review UI for the tree view [\#353](https://github.com/vatesfr/xen-orchestra/issues/353)
@@ -1865,7 +2022,7 @@ File level restore.
- Ability to collapse pools/hosts in main view [\#173](https://github.com/vatesfr/xen-orchestra/issues/173)
- Issue importing .xva VM via xo-web [\#1022](https://github.com/vatesfr/xen-orchestra/issues/1022)
- Enhancement Proposal - Cancel In Progress Backups [\#1003](https://github.com/vatesfr/xen-orchestra/issues/1003)
- Can't create VM with CloudConfigDrive [\#917](https://github.com/vatesfr/xen-orchestra/issues/917)
- Can't create VM with CloudConfigDrive [\#917](https://github.com/vatesfr/xen-orchestra/issues/917)
- Auth: LDAP User causes problems [\#893](https://github.com/vatesfr/xen-orchestra/issues/893)
- No tags in Continuous Replication [\#838](https://github.com/vatesfr/xen-orchestra/issues/838)
- Delta backup Depth not working [\#802](https://github.com/vatesfr/xen-orchestra/issues/802)
@@ -1881,20 +2038,20 @@ File level restore.
- vCPUs number when no tools installed [\#1089](https://github.com/vatesfr/xen-orchestra/issues/1089)
- Config Drive textbox disappears when content is deleted [\#1012](https://github.com/vatesfr/xen-orchestra/issues/1012)
- storage status not changed in host view page after disconnect/connect [\#1009](https://github.com/vatesfr/xen-orchestra/issues/1009)
- storage status not changed in host view page after disconnect/connect [\#1009](https://github.com/vatesfr/xen-orchestra/issues/1009)
- Cannot Delete Logs From Backup Overview [\#1004](https://github.com/vatesfr/xen-orchestra/issues/1004)
- \[v5.x\] Plugins configuration: optional non-used objects are sent [\#1000](https://github.com/vatesfr/xen-orchestra/issues/1000)
- "@" char in remote password break the remote view [\#997](https://github.com/vatesfr/xen-orchestra/issues/997)
- Handle MEMORY\_CONSTRAINT\_VIOLATION correctly [\#970](https://github.com/vatesfr/xen-orchestra/issues/970)
- Handle MEMORY_CONSTRAINT_VIOLATION correctly [\#970](https://github.com/vatesfr/xen-orchestra/issues/970)
- VM creation error on XenServer Dundee [\#964](https://github.com/vatesfr/xen-orchestra/issues/964)
- Copy VMs doesn't display all SRs [\#945](https://github.com/vatesfr/xen-orchestra/issues/945)
- Autopower\_on wrong value [\#937](https://github.com/vatesfr/xen-orchestra/issues/937)
- Autopower_on wrong value [\#937](https://github.com/vatesfr/xen-orchestra/issues/937)
- Correctly handle unknown users in group view [\#900](https://github.com/vatesfr/xen-orchestra/issues/900)
- Importing into Dundee [\#887](https://github.com/vatesfr/xen-orchestra/issues/887)
- update status - gui resize issue [\#803](https://github.com/vatesfr/xen-orchestra/issues/803)
- Backup Remote Stores Problem [\#751](https://github.com/vatesfr/xen-orchestra/issues/751)
- VM view is broken when changing a disk SR twice [\#670](https://github.com/vatesfr/xen-orchestra/issues/670)
- console mouse sync [\#280](https://github.com/vatesfr/xen-orchestra/issues/280)
- console mouse sync [\#280](https://github.com/vatesfr/xen-orchestra/issues/280)
## **4.16.0** (2016-04-29)
@@ -1902,7 +2059,7 @@ Maintenance release
### Enhancements
- TOO\_MANY\_PENDING\_TASKS [\#861](https://github.com/vatesfr/xen-orchestra/issues/861)
- TOO_MANY_PENDING_TASKS [\#861](https://github.com/vatesfr/xen-orchestra/issues/861)
### Bug fixes
@@ -1943,7 +2100,7 @@ Load balancing, SMB delta support, advanced network operations...
### Bug fixes
- Broken link to backup remote [\#821](https://github.com/vatesfr/xen-orchestra/issues/821)
- Broken link to backup remote [\#821](https://github.com/vatesfr/xen-orchestra/issues/821)
- Issue with self-signed cert for email plugin [\#817](https://github.com/vatesfr/xen-orchestra/issues/817)
- Plugins view, reset form and errors [\#815](https://github.com/vatesfr/xen-orchestra/issues/815)
- HVM recovery mode is broken [\#794](https://github.com/vatesfr/xen-orchestra/issues/794)
@@ -2097,7 +2254,7 @@ Delta backup, CloudInit...
- Allow editing PV args even when empty \(but only for PV VMs\) [\#557](https://github.com/vatesfr/xen-orchestra/issues/557)
- Crashes when using legacy event system [\#556](https://github.com/vatesfr/xen-orchestra/issues/556)
- XenServer patches check error for 6.1 [\#555](https://github.com/vatesfr/xen-orchestra/issues/555)
- activation plugin xo-server-transport-email [\#553](https://github.com/vatesfr/xen-orchestra/issues/553)
- activation plugin xo-server-transport-email [\#553](https://github.com/vatesfr/xen-orchestra/issues/553)
- Server error with JSON on 32 bits Dom0 [\#552](https://github.com/vatesfr/xen-orchestra/issues/552)
- Cloud Config drive shouldn't be created on default SR [\#548](https://github.com/vatesfr/xen-orchestra/issues/548)
- Deep properties cannot be edited in plugins configuration form [\#521](https://github.com/vatesfr/xen-orchestra/issues/521)
@@ -2365,7 +2522,7 @@ An issue in `xo-server` with the password of default admin account and also a UI
## **4.0.1** (2015-05-30)
An issue with the updater in HTTPS was left in the *4.0.0*. This patch release fixed
An issue with the updater in HTTPS was left in the _4.0.0_. This patch release fixed
it.
### Bug fixes
@@ -2397,10 +2554,9 @@ it.
- VM stats behavior more robust ([xo-web#250](https://github.com/vatesfr/xen-orchestra/issues/250))
- XO not on the root of domain ([xo-web#254](https://github.com/vatesfr/xen-orchestra/issues/254))
## **3.9.1** (2015-04-21)
A few bugs hve made their way into *3.9.0*, this minor release fixes
A few bugs hve made their way into _3.9.0_, this minor release fixes
them.
### Bug fixes
@@ -2451,13 +2607,13 @@ them.
### Bug fixes
- fix *Invalid parameter(s)* message on the settings page ([xo-server#49](https://github.com/vatesfr/xo-server/issues/49))
- fix _Invalid parameter(s)_ message on the settings page ([xo-server#49](https://github.com/vatesfr/xo-server/issues/49))
- fix mouse clicks in console ([xo-web#205](https://github.com/vatesfr/xen-orchestra/issues/205))
- fix user editing on the settings page ([xo-web#206](https://github.com/vatesfr/xen-orchestra/issues/206))
## **3.7.0** (2015-03-06)
*Highlights in this release are the [initial ACLs implementation](https://xen-orchestra.com/blog/xen-orchestra-3-7-is-out-acls-in-early-access), [live migration for VDIs](https://xen-orchestra.com/blog/moving-vdi-in-live) and the ability to [create a new storage repository](https://xen-orchestra.com/blog/create-a-storage-repository-with-xen-orchestra/).*
_Highlights in this release are the [initial ACLs implementation](https://xen-orchestra.com/blog/xen-orchestra-3-7-is-out-acls-in-early-access), [live migration for VDIs](https://xen-orchestra.com/blog/moving-vdi-in-live) and the ability to [create a new storage repository](https://xen-orchestra.com/blog/create-a-storage-repository-with-xen-orchestra/)._
### Enhancements
@@ -2484,7 +2640,7 @@ them.
- fix console view on IE ([xo-web#184](https://github.com/vatesfr/xen-orchestra/issues/184))
- fix out of sync objects in XO-Web ([xo-web#142](https://github.com/vatesfr/xen-orchestra/issues/142))
- fix incorrect connection status displayed in login view ([xo-web#193](https://github.com/vatesfr/xen-orchestra/issues/193))
- fix *flickering* tree view ([xo-web#194](https://github.com/vatesfr/xen-orchestra/issues/194))
- fix _flickering_ tree view ([xo-web#194](https://github.com/vatesfr/xen-orchestra/issues/194))
- single host pools should not have a dropdown menu in tree view ([xo-web#198](https://github.com/vatesfr/xen-orchestra/issues/198))
## **3.6.0** (2014-11-28)
@@ -2528,7 +2684,7 @@ them.
## **3.5.0** (2014-08-14)
*[XO-Web](https://www.npmjs.org/package/xo-web) and [XO-Server](https://www.npmjs.org/package/xo-server) are now available as npm packages!*
_[XO-Web](https://www.npmjs.org/package/xo-web) and [XO-Server](https://www.npmjs.org/package/xo-server) are now available as npm packages!_
### Enhancements
@@ -2554,9 +2710,9 @@ them.
## **3.4.0** (2014-05-22)
*Highlight in this release is the new events system between XO-Web
_Highlight in this release is the new events system between XO-Web
and XO-Server which results in less bandwidth consumption as well as
better performance and reactivity.*
better performance and reactivity._
### Enhancements
@@ -2590,8 +2746,8 @@ better performance and reactivity.*
### Bug fixes
- *Snapshot* not working in VM view ([#95](https://github.com/vatesfr/xen-orchestra/issues/95))
- Host *Reboot*/*Restart toolstack*/*Shutdown* not working in main view ([#97](https://github.com/vatesfr/xen-orchestra/issues/97))
- _Snapshot_ not working in VM view ([#95](https://github.com/vatesfr/xen-orchestra/issues/95))
- Host _Reboot_/_Restart toolstack_/_Shutdown_ not working in main view ([#97](https://github.com/vatesfr/xen-orchestra/issues/97))
- Bower cannot install `angular` automatically due to a version conflict ([#101](https://github.com/vatesfr/xen-orchestra/issues/101))
- Bower installs an incorrect version of `angular-animate` ([#102](https://github.com/vatesfr/xen-orchestra/issues/102))
@@ -2619,7 +2775,7 @@ better performance and reactivity.*
- in VM view, interfaces' network should be displayed ([#64](https://github.com/vatesfr/xen-orchestra/issues/64))
- middle-click or `Ctrl`+click should open new windows (even on pseudo-links) ([#66](https://github.com/vatesfr/xen-orchestra/issues/66))
- lists should use natural sorting (e.g. *VM 2* before *VM 10*) ([#69](https://github.com/vatesfr/xen-orchestra/issues/69))
- lists should use natural sorting (e.g. _VM 2_ before _VM 10_) ([#69](https://github.com/vatesfr/xen-orchestra/issues/69))
### Bug fixes
@@ -2627,7 +2783,7 @@ better performance and reactivity.*
- it makes no sense to remove a stand-alone host from a pool (58)
- in VM view, the migrate button is not working ([#59](https://github.com/vatesfr/xen-orchestra/issues/59))
- pool and host names overflow their box in the main view ([#63](https://github.com/vatesfr/xen-orchestra/issues/63))
- in host view, interfaces incorrectly named *networks* and VLAN not shown ([#70](https://github.com/vatesfr/xen-orchestra/issues/70))
- in host view, interfaces incorrectly named _networks_ and VLAN not shown ([#70](https://github.com/vatesfr/xen-orchestra/issues/70))
- VM suspended state is not properly handled ([#71](https://github.com/vatesfr/xen-orchestra/issues/71))
- unauthenticated users should not be able to access to consoles ([#73](https://github.com/vatesfr/xen-orchestra/issues/73))
- incorrect scroll (under the navbar) when the view changes ([#74](https://github.com/vatesfr/xen-orchestra/issues/74))

View File

@@ -7,6 +7,8 @@
> Users must be able to say: “Nice enhancement, I'm eager to test it”
- [Backup] **BETA** Ability to backup running VMs with their memory [#645](https://github.com/vatesfr/xen-orchestra/issues/645) (PR [#4252](https://github.com/vatesfr/xen-orchestra/pull/4252))
### Bug fixes
> Users must be able to say: “I had this issue, happy to know it's fixed”
@@ -18,5 +20,5 @@
>
> Rule of thumb: add packages on top.
- xo-server v5.55.0
- xo-web v5.55.0
- xo-server minor
- xo-web minor

View File

@@ -8,7 +8,7 @@ XO is a web interface to visualize and administer your XenServer (or XAPI enable
It aims to be easy to use on any device supporting modern web technologies (HTML 5, CSS 3, JavaScript), such as your desktop computer or your smartphone.
![](https://pbs.twimg.com/profile_images/601775622675898368/xWbbafyO_400x400.png)
![Xen Orchestra logo](./assets/logo.png)
## XOA quick deploy

View File

@@ -10,6 +10,7 @@
- [XOA](xoa.md)
- [Updater](updater.md)
- [Trial activation](trial_activation.md)
- [License activation](license_activation.md)
- [Plugins](plugins.md)
- [Logs](logs.md)
- [Compatibility](supported-version.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/assets/force-start.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@@ -14,7 +14,7 @@ Xen Orchestra will fetch the content of the snapshot made in step 1. This operat
### 3. Snapshot removal
When it's done exporting, we'll remove the snapshot. Note: this operation will trigger a coalesce on your storage in the near future.
When it's done exporting, we'll remove the snapshot. Note: this operation will trigger a coalesce on your storage in the near future (a coalesce is required every time a snapshot is removed).
## Concurrency
@@ -39,6 +39,7 @@ Each step has its own concurrency to fit its requirements:
- **snapshot process** needs to be performed with the lowest concurrency possible. 2 is a good compromise: one snapshot is fast, but a stuck snapshot won't block the whole job. That's why a concurrency of 2 is not too bad on your storage. Basically, at 3 AM, we'll do all the VM snapshots needed, 2 at a time.
- **disk export process** is bottlenecked by XCP-ng/XenServer - so to get the most of it, you can use up to 12 in parallel. As soon a snapshot is done, the export process will start, until reaching 12 at once. Then as soon as one in those 12 is finished, another one will appear until there is nothing more to export.
- **VM export process:** the 12 disk export limit mentioned above applies to VDI exports, which happen during delta exports. For full VM exports (for example, for full backup job types), there is a built in limit of 2. This means if you have a full backup job of 6 VMs, only 2 will be exported at once.
- **snapshot deletion** can't happen all at once because the previous step durations are random - no need to implement concurrency on this one.
This is how it currently works in Xen Orchestra. But sometimes, you also want to have _sequential_ backups combined with the _parallel strategy_. That's why we introduced a sequential option in the advanced section of backup-ng:

View File

@@ -77,6 +77,8 @@ Don't forget to reload `systemd` conf and restart `xo-server`:
# systemctl restart xo-server.service
```
**Note:** The `--use-openssl-ca` option is ignored by Node if Xen-Orchestra is run with Linux capabilities. Capabilities are commonly used to bind applications to privileged ports (<1024) (i.e. `CAP_NET_BIND_SERVICE`). Local NAT rules (`iptables`) or a reverse proxy would be required to use privileged ports and a custom certficate authority.
### Redis server
By default, XO-server will try to contact Redis server on `localhost`, with the port `6379`. But you can define whatever you want:

View File

@@ -96,3 +96,11 @@ xo-cr-seed https://root:password@xen1.company.tld 4a21c1cd-e8bd-4466-910a-f7524e
### Finished
Your backup job should now be working correctly! Manually run the job the first time to check if everything is OK. Then, enable the job. **Now, only the deltas are sent, your initial seed saved you a LOT of time if you have a slow network.**
### Failover process
In the situation where you need to failover to your destination host, you simply need to start all your VMs on the destination host.
> Note: If you want to start a VM on your destination host without breaking the CR jobs on the other side, you will need to make a copy of the VM and start the copy. Otherwise, you will be asked if you would like to force start the VMs.
![](./assets/force-start.jpg)

View File

@@ -14,13 +14,13 @@ As you may have seen in other parts of the documentation, XO is composed of two
### NodeJS
XO needs Node.js. **Please use Node 8**.
XO needs Node.js. **Please use Node LTS**.
We'll consider at this point that you've got a working node on your box. E.g:
```
$ node -v
v8.16.2
v12.16.1
```
If not, see [this page](https://nodejs.org/en/download/package-manager/) for instructions on how to install Node.

View File

@@ -0,0 +1,25 @@
# License activation
Once you purchased a license on the [website](https://xen-orchestra.com/#!/xo-home) you will need to activate it for your appliance.
The procedure is very simple:
1. Log to your Xen Orchestra appliance and go in the Licenses section
![](https://user-images.githubusercontent.com/10992860/77639410-08e1a700-6f59-11ea-9e2b-37eada0d11b1.png)
2. All the licenses you paid for should be visible on this page. Unbinded licenses should have a green activate license button.
![](https://user-images.githubusercontent.com/10992860/77639410-08e1a700-6f59-11ea-9e2b-37eada0d11b1.png)
3. By clicking on the activate license button, you will start the process of binding the license on the **current Xen Orchestra Appliance you are using.**
![](https://user-images.githubusercontent.com/10992860/77639550-3b8b9f80-6f59-11ea-9ab6-9a0a60ca7a39.png)
That's it, you are ready to use your Xen Orchestra Appliance with all the features you unlocked.
## How to unbind and rebind a new Appliance
Sometimes, you might need to change the XO appliance to which you have bind the license you purchase (eg. If you lose the host on which you had your Xen Orchestra appliance).
Do unbind an already registered license, you simply need to open a [support request](https://xen-orchestra.com/#!/member/support) and ask us to release the license.

View File

@@ -1,8 +1,8 @@
# SDN Controller
> SDN Controller is available in XOA 5.44 and higher
> SDN Controller is available in XOA 5.36.0 and higher
The SDN Controller enables a user to **create pool-wide and cross-pool** (since XOA 5.48.1) **private networks**.
The SDN Controller enables a user to **create pool-wide and cross-pool** (since XOA 5.38.0) **private networks**.
![](./assets/sdn-controller.png)

View File

@@ -36,7 +36,7 @@ Then, you can define quotas on this set:
- max RAM
- max disk usage
> Note: Snapshotting a VM within a self-service will use the quota from the resource set. The same rule applies for backups and replication.
> Note: Snapshotting a VM within a self-service will _not_ use the quota from the resource set. The same rule applies for backups and replication.
When you click on create, you can see the resource set and remove or edit it:

View File

@@ -6,6 +6,8 @@ Xen Orchestra is designed to work exclusively on [XCP-ng](https://xcp-ng.org/) a
Backup restore for large VM disks (>1TiB usage) is [broken on all XenServer versions](https://bugs.xenserver.org/browse/XSO-868) until Citrix release a fix.
- Citrix Hypervisor 8.1
- Citrix Hypervisor 8.0
- XenServer 7.6
- XenServer 7.5
- [VDI I/O error](https://bugs.xenserver.org/browse/XSO-873), waiting for Citrix to release our fix
@@ -27,6 +29,7 @@ Backup restore for large VM disks (>1TiB usage) is [broken on all XenServer vers
All the pending fixes are already integrated in the latest XCP-ng version. We strongly suggest people to keep using the latest XCP-ng version as far as possible.
- XCP-ng 8.0
- XCP-ng 7.6
- XCP-ng 7.5
- XCP-ng 7.4.1

View File

@@ -90,14 +90,12 @@ FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memo
1: node::Abort() [node]
```
In that case, you need to increase the memory allocated to the
XOA VM (from 2GB to 4 or 8 GB), and then update the service file
(`/etc/systemd/system/xo-server.service`) to increase the allocated
memory to xo-server itself:
In that case, you need to increase the memory allocated to the XOA VM (from 2GB to 4GB or 8GB). Note that simply increasing the RAM for the VM is not enough. You must also edit the service file (`/etc/systemd/system/xo-server.service`) to increase the memory allocated to the xo-server process itself.
**Note:** you should leave ~512MB for the debian OS itself. Meaning if your VM has 4096MB total RAM, you should use `3584` for the memory value below.
```diff
- ExecStart=/usr/local/bin/xo-server
+ ExecStart=/usr/local/bin/node --max-old-space-size=8192 /usr/local/bin/xo-server
+ ExecStart=/usr/local/bin/node --max-old-space-size=3584 /usr/local/bin/xo-server
```
The last step is to refresh and restart the service:

View File

@@ -43,13 +43,12 @@ curl -sS https://xoa.io/deploy | bash
> ```
> curl: (35) error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
> ```
````
>
> It means that the secure HTTPS protocol is not supported, you can bypass this using the unsecure command instead:
>
> ```
> curl -sS http://xoa.io/deploy | bash
````
> ```
Follow the instructions:

View File

@@ -6,29 +6,20 @@ XOSAN is a virtual SAN that allows you to create a shared SR (Storage Repository
## Introduction
This documentation will give you some advices and assistance in order to create a XOSAN storage on your XenServer infrastructure.
This documentation will give you some advice and assistance in order to create an XOSAN storage on your XenServer or XCP-ng infrastructure.
## Objectives
XOSAN will "gather" all your local disks into a shared SR, that XenServer will just see as any other shared SR, without limitations on it (you can live migrate, snapshot, backup, whatever you need). **It's a fully software defined solution** that doesn't require to buy extra-hardware. It could even run on the disk where your XenServer is already installed!
XOSAN will "gather" all your local disks (across multiple hosts) into a shared SR, that XenServer/XCP-ng will just see as any other shared SR, without limitations (you can live migrate, snapshot, backup, whatever you need). **It's a fully software defined solution** that doesn't require you to buy extra hardware. It can even run on the disk where your Citrix Hypervisor (Xenserver) or XCP-ng is already installed!
![](https://xen-orchestra.com/blog/content/images/2016/12/hyperpool.jpg)
The objectives are to:
- protect your data thanks to replication of data on multiple hosts
- provide XenServer high availability without buying a NAS nor a SAN
- protect your data thanks to replication of data across multiple hosts
- Unlock High Availability without buying a NAS nor a SAN
- give you flexibility to grow your storage by adding new nodes
- work on all kind of hardware, from HDDs to SSDs, with hardware RAID or not
## Beta access - Phase II
XOSAN is currently in beta phase II. Every user can access this beta stage and try the solution in its current version.
To activate you XOSAN beta, just go in the **"XOSAN"** menu in your (up-to-date) XOA. Once on the menu, click on **"Register for Beta"**.
![](https://xen-orchestra.com/blog/content/images/2017/02/xosan-menu.png)
> Even a free version of XOA can access the XOSAN beta.
- work on all kinds of hardware, HDDs or SSDs, with hardware RAID or not
## Deployment

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "complex-matcher",
"version": "0.6.0",
"license": "ISC",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "value-matcher",
"version": "0.2.0",
"license": "ISC",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "vhd-cli",
"version": "0.3.1",
"license": "ISC",
@@ -27,7 +28,7 @@
"node": ">=8.10"
},
"dependencies": {
"@xen-orchestra/fs": "^0.10.2",
"@xen-orchestra/fs": "^0.10.3",
"cli-progress": "^3.1.0",
"exec-promise": "^0.7.0",
"getopts": "^2.2.3",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "vhd-lib",
"version": "0.7.2",
"license": "AGPL-3.0",
@@ -24,7 +25,6 @@
"@xen-orchestra/log": "^0.2.0",
"async-iterator-to-stream": "^1.0.2",
"core-js": "^3.0.0",
"from2": "^2.3.0",
"fs-extra": "^8.0.1",
"limit-concurrency-decorator": "^0.4.0",
"lodash": "^4.17.4",
@@ -37,7 +37,7 @@
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-flow": "^7.0.0",
"@xen-orchestra/fs": "^0.10.2",
"@xen-orchestra/fs": "^0.10.3",
"babel-plugin-lodash": "^3.3.2",
"cross-env": "^6.0.3",
"execa": "^3.2.0",

View File

@@ -1,42 +0,0 @@
import from2 from 'from2'
const constantStream = (data, n = 1) => {
if (!Buffer.isBuffer(data)) {
data = Buffer.from(data)
}
const { length } = data
if (!length) {
throw new Error('data should not be empty')
}
n *= length
let currentLength = length
return from2((size, next) => {
if (n <= 0) {
return next(null, null)
}
if (n < size) {
size = n
}
if (size < currentLength) {
const m = Math.floor(size / length) * length || length
n -= m
return next(null, data.slice(0, m))
}
// if more than twice the data length is requested, repeat the data
if (size > currentLength * 2) {
currentLength = Math.floor(size / length) * length
data = Buffer.alloc(currentLength, data)
}
n -= currentLength
return next(null, data)
})
}
export { constantStream as default }

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "xapi-explore-sr",
"version": "0.2.1",
"license": "ISC",
@@ -41,7 +42,7 @@
"human-format": "^0.10.0",
"lodash": "^4.17.4",
"pw": "^0.0.4",
"xen-api": "^0.27.3"
"xen-api": "^0.28.3"
},
"devDependencies": {
"@babel/cli": "^7.1.5",

View File

@@ -1,6 +1,7 @@
{
"private": false,
"name": "xen-api",
"version": "0.27.3",
"version": "0.28.3",
"license": "ISC",
"description": "Connector to the Xen API",
"keywords": [
@@ -38,7 +39,7 @@
"debug": "^4.0.1",
"event-to-promise": "^0.8.0",
"exec-promise": "^0.7.0",
"http-request-plus": "^0.9.1",
"http-request-plus": "^0.8.0",
"jest-diff": "^24.0.0",
"json-rpc-protocol": "^0.13.1",
"kindof": "^2.0.0",

View File

@@ -39,6 +39,8 @@ const { defineProperties, defineProperty, freeze, keys: getKeys } = Object
export const NULL_REF = 'OpaqueRef:NULL'
export { isOpaqueRef }
// -------------------------------------------------------------------
const RESERVED_FIELDS = {
@@ -281,6 +283,17 @@ export class Xapi extends EventEmitter {
return this.call(`${type}.set_${field}`, ref, value).then(noop)
}
setFields(type, ref, fields) {
return Promise.all(
getKeys(fields).map(field => {
const value = fields[field]
if (value !== undefined) {
return this.call(`${type}.set_${field}`, ref, value)
}
})
).then(noop)
}
setFieldEntries(type, ref, field, entries) {
return Promise.all(
getKeys(entries).map(entry => {
@@ -506,7 +519,13 @@ export class Xapi extends EventEmitter {
const { promise, resolve } = defer()
eventWatchers[key] = resolve
await this._sessionCall('pool.add_to_other_config', [poolRef, key, ''])
await this._sessionCall('pool.add_to_other_config', [
poolRef,
key,
// use ms timestamp as values to enable identification of stale entries
String(Date.now()),
])
await promise
@@ -758,7 +777,10 @@ export class Xapi extends EventEmitter {
_setUrl(url) {
this._humanId = `${this._auth.user}@${url.hostname}`
this._transport = autoTransport({
allowUnauthorized: this._allowUnauthorized,
secureOptions: {
minVersion: 'TLSv1',
rejectUnauthorized: !this._allowUnauthorized,
},
url,
})
this._url = url
@@ -981,6 +1003,8 @@ export class Xapi extends EventEmitter {
this._processEvents(result.events)
// detect and fix disappearing tasks (e.g. when toolstack restarts)
//
// FIXME: only if 'task' in 'types
if (result.valid_ref_counts.task !== this._nTasks) {
await this._refreshCachedRecords(['task'])
}
@@ -1063,7 +1087,32 @@ export class Xapi extends EventEmitter {
)
const getters = { $pool: getPool }
const props = { $type: type }
const props = {
$call: function(method, ...args) {
return xapi.call(`${type}.${method}`, this.$ref, ...args)
},
$callAsync: function(method, ...args) {
return xapi.callAsync(`${type}.${method}`, this.$ref, ...args)
},
$type: type,
}
;(function addMethods(object) {
Object.getOwnPropertyNames(object).forEach(name => {
// dont trigger getters (eg sessionId)
const fn = Object.getOwnPropertyDescriptor(object, name).value
if (typeof fn === 'function' && name.startsWith(type + '_')) {
const key = '$' + name.slice(type.length + 1)
assert.strictEqual(props[key], undefined)
props[key] = function(...args) {
return xapi[name](this.$ref, ...args)
}
}
})
const proto = Object.getPrototypeOf(object)
if (proto !== null) {
addMethods(proto)
}
})(xapi)
fields.forEach(field => {
props[`set_${field}`] = function(value) {
return xapi.setField(this.$type, this.$ref, field, value)

View File

@@ -6,11 +6,11 @@ import XapiError from '../_XapiError'
import UnsupportedTransport from './_UnsupportedTransport'
// https://github.com/xenserver/xenadmin/blob/0df39a9d83cd82713f32d24704852a0fd57b8a64/XenModel/XenAPI/Session.cs#L403-L433
export default ({ allowUnauthorized, url }) => {
export default ({ secureOptions, url }) => {
return (method, args) =>
httpRequestPlus
.post(url, {
rejectUnauthorized: !allowUnauthorized,
...secureOptions,
body: format.request(0, method, args),
headers: {
Accept: 'application/json',

View File

@@ -74,12 +74,13 @@ const parseResult = result => {
throw new UnsupportedTransport()
}
export default ({ allowUnauthorized, url: { hostname, port, protocol } }) => {
const client = (protocol === 'https:' ? createSecureClient : createClient)({
export default ({ secureOptions, url: { hostname, port, protocol } }) => {
const secure = protocol === 'https:'
const client = (secure ? createSecureClient : createClient)({
...(secure ? secureOptions : undefined),
host: hostname,
path: '/json',
port,
rejectUnauthorized: !allowUnauthorized,
})
const call = promisify(client.methodCall, client)

View File

@@ -34,11 +34,12 @@ const parseResult = result => {
return result.Value
}
export default ({ allowUnauthorized, url: { hostname, port, protocol } }) => {
const client = (protocol === 'https:' ? createSecureClient : createClient)({
export default ({ secureOptions, url: { hostname, port, protocol } }) => {
const secure = protocol === 'https:'
const client = (secure ? createSecureClient : createClient)({
...(secure ? secureOptions : undefined),
host: hostname,
port,
rejectUnauthorized: !allowUnauthorized,
})
const call = promisify(client.methodCall, client)

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "xo-acl-resolver",
"version": "0.4.1",
"license": "ISC",
@@ -24,7 +25,7 @@
"node": ">=6"
},
"dependencies": {
"xo-common": "^0.2.0"
"xo-common": "^0.4.0"
},
"scripts": {
"postversion": "npm publish"

View File

@@ -1,6 +1,7 @@
{
"private": false,
"name": "xo-cli",
"version": "0.10.1",
"version": "0.11.0",
"license": "AGPL-3.0",
"description": "Basic CLI for Xen-Orchestra",
"keywords": [

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "xo-collection",
"version": "0.4.1",
"license": "ISC",

View File

@@ -1,6 +1,7 @@
{
"private": false,
"name": "xo-common",
"version": "0.2.0",
"version": "0.4.0",
"license": "AGPL-3.0",
"description": "Code shared between [XO](https://xen-orchestra.com) server and clients",
"keywords": [],

View File

@@ -172,3 +172,28 @@ export const patchPrecheckFailed = create(20, ({ errorType, patch }) => ({
},
message: `patch precheck failed: ${errorType}`,
}))
export const operationFailed = create(21, ({ objectId, code }) => ({
data: {
objectId,
code,
},
message: 'operation failed',
}))
export const missingAuditRecord = create(22, ({ id, nValid }) => ({
data: {
id,
nValid,
},
message: 'missing record',
}))
export const alteredAuditRecord = create(23, ({ id, record, nValid }) => ({
data: {
id,
record,
nValid,
},
message: 'altered record',
}))

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "xo-import-servers-csv",
"version": "1.1.0",
"license": "ISC",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "xo-lib",
"version": "0.9.0",
"license": "ISC",

View File

@@ -1,4 +1,5 @@
{
"private": false,
"name": "xo-remote-parser",
"version": "0.5.0",
"license": "AGPL-3.0",

View File

@@ -0,0 +1,3 @@
module.exports = require('../../@xen-orchestra/babel-config')(
require('./package.json')
)

View File

@@ -0,0 +1,10 @@
/examples/
example.js
example.js.map
*.example.js
*.example.js.map
/test/
/tests/
*.spec.js
*.spec.js.map

View File

@@ -0,0 +1,50 @@
# xo-server-audit [![Build Status](https://api.travis-ci.org/vatesfr/xo-server-audit.png?branch=master)](https://travis-ci.org/vatesfr/xen-orchestra)
> **TODO**
## Install
Installation of the [npm package](https://npmjs.org/package/xo-server-audit):
```
> npm install --global xo-server-audit
```
## Usage
Like all other xo-server plugins, it can be configured directly via
the web interface, see [the plugin documentation](https://xen-orchestra.com/docs/plugins.html).
## Development
```
# Install dependencies
> yarn
# Run the tests
> yarn test
# Continuously compile
> yarn dev
# Continuously run the tests
> yarn dev-test
# Build for production
> yarn build
```
## Contributions
Contributions are _very_ welcomed, either on the documentation or on
the code.
You may:
- report any [issue](https://github.com/vatesfr/xen-orchestra/issues)
you've encountered;
- fork and create a pull request.
## License
AGPL3 © [Vates SAS](http://vates.fr)

View File

@@ -0,0 +1,39 @@
# List of skipped methods
blockedList = [
'acl.get',
'acl.getCurrentPermissions',
'audit.checkIntegrity',
'audit.generateFingerprint',
'audit.getRecords',
'backupNg.getAllJobs',
'backupNg.getAllLogs',
'cloud.getResourceCatalog',
'cloudConfig.getAll',
'group.getAll',
'host.stats',
'ipPool.getAll',
'job.getAll',
'log.get',
'metadataBackup.getAllJobs',
'plugin.get',
'pool.listMissingPatches',
'proxy.getAll',
'remote.getAll',
'remote.getAllInfo',
'resourceSet.getAll',
'role.getAll',
'schedule.getAll',
'server.getAll',
'session.getUser',
'sr.getUnhealthyVdiChainsLength',
'sr.stats',
'system.getMethodsInfo',
'system.getServerTimezone',
'system.getServerVersion',
'user.getAll',
'vm.stats',
'xo.getAllObjects',
'xoa.supportTunnel.getState',
'xosan.checkSrCurrentState',
'xosan.getVolumeInfo',
]

View File

@@ -0,0 +1,62 @@
{
"name": "xo-server-audit",
"version": "0.2.0",
"license": "AGPL-3.0",
"description": "Audit plugin for XO-Server",
"keywords": [
"audit",
"log",
"logs",
"orchestra",
"plugin",
"xen-orchestra",
"xen",
"xo-server"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-audit",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "packages/xo-server-audit",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Julien Fontanet",
"email": "julien.fontanet@isonoe.net"
},
"preferGlobal": false,
"main": "dist/",
"bin": {},
"files": [
"config.toml",
"dist/"
],
"engines": {
"node": ">=6"
},
"devDependencies": {
"@babel/cli": "^7.7.0",
"@babel/core": "^7.7.2",
"@babel/preset-env": "^7.7.1",
"cross-env": "^6.0.3",
"rimraf": "^3.0.0"
},
"scripts": {
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
"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"
},
"dependencies": {
"@iarna/toml": "^2.2.3",
"@xen-orchestra/audit-core": "^0.1.1",
"@xen-orchestra/log": "^0.2.0",
"app-conf": "^0.7.1",
"async-iterator-to-stream": "^1.1.0",
"promise-toolbox": "^0.15.0",
"readable-stream": "^3.5.0",
"xo-common": "^0.4.0"
},
"private": true
}

View File

@@ -0,0 +1,252 @@
import appConf from 'app-conf'
import asyncIteratorToStream from 'async-iterator-to-stream'
import createLogger from '@xen-orchestra/log'
import path from 'path'
import { alteredAuditRecord, missingAuditRecord } from 'xo-common/api-errors'
import { createGzip } from 'zlib'
import { fromCallback } from 'promise-toolbox'
import { pipeline } from 'readable-stream'
import {
AlteredRecordError,
AuditCore,
MissingRecordError,
NULL_ID,
Storage,
} from '@xen-orchestra/audit-core'
const log = createLogger('xo:xo-server-audit')
const LAST_ID = 'lastId'
class Db extends Storage {
constructor(db) {
super()
this._db = db
}
async put(record) {
await this._db.put(record.id, record)
}
async del(id) {
await this._db.del(id)
}
get(id) {
return this._db.get(id).catch(error => {
if (!error.notFound) {
throw error
}
})
}
async setLastId(id) {
await this._db.put(LAST_ID, id)
}
getLastId() {
return this.get(LAST_ID)
}
}
const NAMESPACE = 'audit'
class AuditXoPlugin {
constructor({ xo }) {
this._cleaners = []
this._xo = xo
this._auditCore = undefined
this._blockedList = undefined
this._storage = undefined
}
async load() {
const cleaners = this._cleaners
try {
const storage = (this._storage = new Db(
await this._xo.getStore(NAMESPACE)
))
this._auditCore = new AuditCore(storage)
this._blockedList = (
await appConf.load('xo-server-audit', {
appDir: path.join(__dirname, '..'),
})
).blockedList
cleaners.push(() => {
this._auditCore = undefined
this._blockedList = undefined
this._storage = undefined
})
} catch (error) {
this._auditCore = undefined
this._blockedList = undefined
this._storage = undefined
throw error
}
this._addListener('xo:postCall', this._handleEvent.bind(this, 'apiCall'))
this._addListener('xo:audit', this._handleEvent.bind(this))
const exportRecords = this._exportRecords.bind(this)
exportRecords.permission = 'admin'
const getRecords = this._getRecords.bind(this)
getRecords.description = 'Get records from a passed record ID'
getRecords.permission = 'admin'
getRecords.params = {
id: { type: 'string', optional: true },
ndjson: { type: 'boolean', optional: true },
}
const checkIntegrity = this._checkIntegrity.bind(this)
checkIntegrity.description =
'Check records integrity between oldest and newest'
checkIntegrity.permission = 'admin'
checkIntegrity.params = {
newest: { type: 'string', optional: true },
oldest: { type: 'string', optional: true },
}
const generateFingerprint = this._generateFingerprint.bind(this)
generateFingerprint.description =
'Generate a fingerprint of the chain oldest-newest'
generateFingerprint.permission = 'admin'
generateFingerprint.params = {
newest: { type: 'string', optional: true },
oldest: { type: 'string', optional: true },
}
cleaners.push(
this._xo.addApiMethods({
audit: {
checkIntegrity,
exportRecords,
generateFingerprint,
getRecords,
},
})
)
}
unload() {
this._cleaners.forEach(cleaner => cleaner())
this._cleaners.length = 0
}
_addListener(event, listener_) {
const listener = async (...args) => {
try {
await listener_(...args)
} catch (error) {
log.error(error)
}
}
const xo = this._xo
xo.on(event, listener)
this._cleaners.push(() => xo.removeListener(event, listener))
}
_handleEvent(event, { userId, userIp, userName, ...data }) {
if (event !== 'apiCall' || this._blockedList.indexOf(data.method) === -1) {
return this._auditCore.add(
{
userId,
userIp,
userName,
},
event,
data
)
}
}
async _getRecords({ id, ndjson = false }) {
if (ndjson) {
return this._xo
.registerHttpRequest((req, res) => {
res.set('Content-Type', 'application/json')
return fromCallback(pipeline, this._getRecordsStream(id), res)
})
.then($getFrom => ({
$getFrom,
}))
}
const records = []
for await (const record of this._auditCore.getFrom(id)) {
records.push(record)
}
return records
}
_exportRecords() {
return this._xo
.registerHttpRequest(
(req, res) => {
res.writeHead(200, {
'content-disposition': 'attachment',
'content-type': 'application/json',
})
return fromCallback(
pipeline,
this._getRecordsStream(),
createGzip(),
res
)
},
undefined,
{
suffix: `/audit-records-${new Date()
.toISOString()
.replace(/:/g, '_')}.gz`,
}
)
.then($getFrom => ({
$getFrom,
}))
}
async _checkIntegrity(props) {
const { oldest = NULL_ID, newest = await this._storage.getLastId() } = props
return this._auditCore.checkIntegrity(oldest, newest).catch(error => {
if (error instanceof MissingRecordError) {
throw missingAuditRecord(error)
}
if (error instanceof AlteredRecordError) {
throw alteredAuditRecord(error)
}
throw error
})
}
async _generateFingerprint(props) {
const { oldest = NULL_ID, newest = await this._storage.getLastId() } = props
try {
return {
fingerprint: `${oldest}|${newest}`,
nValid: await this._checkIntegrity({ oldest, newest }),
}
} catch (error) {
if (missingAuditRecord.is(error) || alteredAuditRecord.is(error)) {
return {
fingerprint: `${error.data.id}|${newest}`,
nValid: error.data.nValid,
error,
}
}
throw error
}
}
}
AuditXoPlugin.prototype._getRecordsStream = asyncIteratorToStream(
async function*(id) {
for await (const record of this._auditCore.getFrom(id)) {
yield JSON.stringify(record)
yield '\n'
}
}
)
export default opts => new AuditXoPlugin(opts)

View File

@@ -1,6 +1,6 @@
{
"name": "xo-server-auth-github",
"version": "0.2.1",
"version": "0.2.2",
"license": "AGPL-3.0",
"description": "GitHub authentication plugin for XO-Server",
"keywords": [

View File

@@ -23,8 +23,13 @@ class AuthGitHubXoPlugin {
this._xo = xo
}
configure(conf) {
async configure(conf, { loaded }) {
this._conf = conf
if (loaded) {
await this.unload()
await this.load()
}
}
load() {

View File

@@ -1,6 +1,6 @@
{
"name": "xo-server-auth-google",
"version": "0.2.1",
"version": "0.2.2",
"license": "AGPL-3.0",
"description": "Google authentication plugin for XO-Server",
"keywords": [

View File

@@ -35,8 +35,13 @@ class AuthGoogleXoPlugin {
this._xo = xo
}
configure(conf) {
async configure(conf, { loaded }) {
this._conf = conf
if (loaded) {
await this.unload()
await this.load()
}
}
load() {

View File

@@ -1,6 +1,6 @@
{
"name": "xo-server-auth-ldap",
"version": "0.6.6",
"version": "0.7.1",
"license": "AGPL-3.0",
"description": "LDAP authentication plugin for XO-Server",
"keywords": [
@@ -34,18 +34,15 @@
"node": ">=6"
},
"dependencies": {
"event-to-promise": "^0.8.0",
"exec-promise": "^0.7.0",
"inquirer": "^7.0.0",
"ldapjs": "^1.0.1",
"lodash": "^4.17.4",
"ldapts": "1.10.0",
"promise-toolbox": "^0.15.0"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-plugin-lodash": "^3.3.2",
"cross-env": "^6.0.3",
"rimraf": "^3.0.0"
},

View File

@@ -1,10 +1,8 @@
/* eslint no-throw-literal: 0 */
import eventToPromise from 'event-to-promise'
import noop from 'lodash/noop'
import { createClient } from 'ldapjs'
import { escape } from 'ldapjs/lib/filters/escape'
import { promisify } from 'promise-toolbox'
import fromCallback from 'promise-toolbox/fromCallback'
import { Client } from 'ldapts'
import { Filter } from 'ldapts/filters/Filter'
import { readFile } from 'fs'
// ===================================================================
@@ -14,6 +12,8 @@ const DEFAULTS = {
filter: '(uid={{name}})',
}
const { escape } = Filter.prototype
const VAR_RE = /\{\{([^}]+)\}\}/g
const evalFilter = (filter, vars) =>
filter.replace(VAR_RE, (_, name) => {
@@ -26,6 +26,8 @@ const evalFilter = (filter, vars) =>
return escape(value)
})
const noop = Function.prototype
export const configurationSchema = {
type: 'object',
properties: {
@@ -152,7 +154,7 @@ class AuthLdap {
tlsOptions.rejectUnauthorized = checkCertificate
if (certificateAuthorities) {
tlsOptions.ca = await Promise.all(
certificateAuthorities.map(path => readFile(path))
certificateAuthorities.map(path => fromCallback(readFile, path))
)
}
}
@@ -194,68 +196,48 @@ class AuthLdap {
return null
}
const client = createClient(this._clientOpts)
const client = new Client(this._clientOpts)
try {
// Promisify some methods.
const bind = promisify(client.bind, client)
const search = promisify(client.search, client)
await eventToPromise(client, 'connect')
// Bind if necessary.
{
const { _credentials: credentials } = this
if (credentials) {
logger(`attempting to bind with as ${credentials.dn}...`)
await bind(credentials.dn, credentials.password)
await client.bind(credentials.dn, credentials.password)
logger(`successfully bound as ${credentials.dn}`)
}
}
// Search for the user.
const entries = []
{
logger('searching for entries...')
const response = await search(this._searchBase, {
scope: 'sub',
filter: evalFilter(this._searchFilter, {
name: username,
}),
})
response.on('searchEntry', entry => {
logger('.')
entries.push(entry.json)
})
const { status } = await eventToPromise(response, 'end')
if (status) {
throw new Error('unexpected search response status: ' + status)
}
logger(`${entries.length} entries found`)
}
logger('searching for entries...')
const { searchEntries: entries } = await client.search(this._searchBase, {
scope: 'sub',
filter: evalFilter(this._searchFilter, {
name: username,
}),
})
logger(`${entries.length} entries found`)
// Try to find an entry which can be bind with the given password.
for (const entry of entries) {
try {
logger(`attempting to bind as ${entry.objectName}`)
await bind(entry.objectName, password)
logger(`attempting to bind as ${entry.dn}`)
await client.bind(entry.dn, password)
logger(
`successfully bound as ${entry.objectName} => ${username} authenticated`
`successfully bound as ${entry.dn} => ${username} authenticated`
)
logger(JSON.stringify(entry, null, 2))
return { username }
} catch (error) {
logger(`failed to bind as ${entry.objectName}: ${error.message}`)
logger(`failed to bind as ${entry.dn}: ${error.message}`)
}
}
logger(`could not authenticate ${username}`)
return null
} finally {
client.unbind()
await client.unbind()
}
}
}

View File

@@ -1,4 +1,3 @@
import { forEach, isFinite, isInteger } from 'lodash'
import { pForOwn } from 'promise-toolbox'
import { prompt } from 'inquirer'
@@ -95,11 +94,12 @@ const promptByType = {
}
n = schema.maxItems || Infinity
const m = defaultValue.length
while (
// eslint-disable-next-line no-unmodified-loop-condition
i < n &&
(await confirm('additional item?', {
default: false,
default: i < m,
}))
) {
await promptItem()
@@ -122,7 +122,7 @@ const promptByType = {
input(path, {
default: defaultValue || schema.default,
filter: input => +input,
validate: input => isInteger(+input),
validate: input => Number.isInteger(+input),
}),
number: (schema, defaultValue, path) =>
@@ -137,7 +137,7 @@ const promptByType = {
const required = {}
schema.required &&
forEach(schema.required, name => {
schema.required.forEach(name => {
required[name] = true
})

View File

@@ -1,6 +1,6 @@
{
"name": "xo-server-auth-saml",
"version": "0.7.0",
"version": "0.7.2",
"license": "AGPL-3.0",
"description": "SAML authentication plugin for XO-Server",
"keywords": [

View File

@@ -38,6 +38,7 @@ You should try \`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddr
title: "Don't request an authentication context",
description: 'This is known to help when using Active Directory',
default: DEFAULTS.disableRequestedAuthnContext,
type: 'boolean',
},
},
required: ['cert', 'entryPoint', 'issuer', 'usernameField'],
@@ -53,7 +54,7 @@ class AuthSamlXoPlugin {
this._xo = xo
}
configure({ usernameField, ...conf }) {
async configure({ usernameField, ...conf }, { loaded }) {
this._usernameField = usernameField
this._conf = {
...DEFAULTS,
@@ -62,6 +63,11 @@ class AuthSamlXoPlugin {
// must match the callback URL
path: '/signin/saml/callback',
}
if (loaded) {
await this.unload()
await this.load()
}
}
load() {

View File

@@ -1,6 +1,6 @@
{
"name": "xo-server-backup-reports",
"version": "0.16.4",
"version": "0.16.5",
"license": "AGPL-3.0",
"description": "Backup reports plugin for XO-Server",
"keywords": [

View File

@@ -395,7 +395,13 @@ class BackupReportsXoPlugin {
mailReceivers,
markdown: toMarkdown(markdown),
success: false,
nagiosMarkdown: `[Xen Orchestra] [${log.status}] Backup report for ${jobName} - Error : ${log.result.message}`,
nagiosMarkdown: `[Xen Orchestra] [${
log.status
}] Backup report for ${jobName}${
log.result?.message !== undefined
? ` - Error : ${log.result.message}`
: ''
}`,
})
}

View File

@@ -1,8 +1,8 @@
{
"name": "xo-server-perf-alert",
"version": "0.2.0",
"version": "0.2.1",
"license": "AGPL-3.0",
"description": "",
"description": "Sends alerts based on performance criteria",
"keywords": [],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-perf-alert",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",

View File

@@ -1,5 +1,6 @@
{
"name": "xo-server-sdn-controller",
"description": "Creates pool-wide and cross-pool private networks",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-sdn-controller",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
@@ -15,7 +16,7 @@
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
},
"version": "0.3.1",
"version": "0.4.1",
"engines": {
"node": ">=8.10"
},
@@ -30,7 +31,7 @@
"dependencies": {
"@xen-orchestra/log": "^0.2.0",
"lodash": "^4.17.11",
"node-openssl-cert": "^0.0.116",
"node-openssl-cert": "^0.0.117",
"promise-toolbox": "^0.15.0",
"uuid": "^3.3.2"
},

View File

@@ -214,11 +214,20 @@ async function generateCertificatesAndKey(dataDir) {
// -----------------------------------------------------------------------------
async function createTunnel(host, network, pifDevice) {
const hostPif = find(host.$PIFs, { device: pifDevice })
async function createTunnel(host, network) {
const otherConfig = network.other_config
const pifDevice = otherConfig['xo:sdn-controller:pif-device']
const pifVlan = otherConfig['xo:sdn-controller:vlan']
const hostPif = host.$PIFs.find(
pif =>
pif.device === pifDevice &&
pif.VLAN === +pifVlan &&
pif.ip_configuration_mode !== 'None'
)
if (hostPif === undefined) {
log.error("Can't create tunnel: no available PIF", {
pif: pifDevice,
pifDevice,
pifVlan,
network: network.name_label,
host: host.name_label,
pool: host.$pool.name_label,
@@ -232,7 +241,8 @@ async function createTunnel(host, network, pifDevice) {
} catch (error) {
log.error('Error while creating tunnel', {
error,
pif: pifDevice,
pifDevice,
pifVlan,
network: network.name_label,
host: host.name_label,
pool: host.$pool.name_label,
@@ -241,7 +251,8 @@ async function createTunnel(host, network, pifDevice) {
}
log.debug('New tunnel added', {
pif: pifDevice,
pifDevice,
pifVlan,
network: network.name_label,
host: host.name_label,
pool: host.$pool.name_label,
@@ -249,7 +260,7 @@ async function createTunnel(host, network, pifDevice) {
}
function getHostTunnelForNetwork(host, networkRef) {
const pif = find(host.$PIFs, { network: networkRef })
const pif = host.$PIFs.find(_ => _.network === networkRef)
if (pif === undefined) {
return
}
@@ -264,7 +275,7 @@ function getHostTunnelForNetwork(host, networkRef) {
// -----------------------------------------------------------------------------
function setControllerNeeded(xapi) {
function isControllerNeeded(xapi) {
const controller = find(xapi.objects.all, { $type: 'SDN_controller' })
return !(
controller?.protocol === PROTOCOL &&
@@ -281,8 +292,9 @@ class SDNController extends EventEmitter {
- `other_config`:
- `xo:sdn-controller:encapsulation` : encapsulation protocol used for tunneling (either `gre` or `vxlan`)
- `xo:sdn-controller:encrypted` : `true` if the network is encrypted
- `xo:sdn-controller:pif-device` : PIF device on which the tunnels are created, must be physical and have an IP configuration
- `xo:sdn-controller:pif-device` : PIF device on which the tunnels are created, must be physical or VLAN or bond master and have an IP configuration
- `xo:sdn-controller:private-network-uuid`: UUID of the private network, same across pools
- `xo:sdn-controller:vlan` : VLAN of the PIFs on which the network is created
- `xo:sdn-controller:vni` : VxLAN Network Identifier,
it is used by OpenVSwitch to route traffic of different networks in a single tunnel
See: https://tools.ietf.org/html/rfc7348
@@ -356,7 +368,7 @@ class SDNController extends EventEmitter {
await Promise.all(
map(this._privateNetworks, async privateNetworks => {
await Promise.all(
map(privateNetworks.getPools(), async pool => {
privateNetworks.getPools().map(async pool => {
if (!updatedPools.includes(pool)) {
const xapi = this._xo.getXapi(pool)
await this._installCaCertificateIfNeeded(xapi)
@@ -406,109 +418,21 @@ class SDNController extends EventEmitter {
},
})
// FIXME: we should monitor when xapis are added/removed
this._xapis = this._xo.getAllXapis()
await Promise.all(
map(this._xapis, async xapi => {
await xapi.objectsFetched
forOwn(this._xo.getAllXapis(), xapi => {
if (xapi.status === 'connected') {
this._handleConnectedXapi(xapi)
}
})
if (setControllerNeeded(xapi)) {
return
}
this._cleaners.push(await this._manageXapi(xapi))
const hosts = filter(xapi.objects.all, { $type: 'host' })
for (const host of hosts) {
this._createOvsdbClient(host)
}
// Add already existing private networks
const networks = filter(xapi.objects.all, { $type: 'network' })
const noVniNetworks = []
await Promise.all(
map(networks, async network => {
// 2019-09-03
// Compatibility code, to be removed in 1 year.
await updateNetworkOtherConfig(network)
network = await network.$xapi.barrier(network.$ref)
let otherConfig = network.other_config
// 2019-10-01
// To be removed in a year
if (otherConfig['xo:sdn-controller:private-pool-wide'] === 'true') {
await updateOldPrivateNetwork(network)
}
network = await network.$xapi.barrier(network.$ref)
otherConfig = network.other_config
const uuid = otherConfig['xo:sdn-controller:private-network-uuid']
if (uuid === undefined) {
return
}
let privateNetwork = this._privateNetworks[uuid]
if (privateNetwork === undefined) {
privateNetwork = new PrivateNetwork(this, uuid)
this._privateNetworks[uuid] = privateNetwork
}
const vni = otherConfig['xo:sdn-controller:vni']
if (vni === undefined) {
noVniNetworks.push(network)
} else {
this._prevVni = Math.max(this._prevVni, +vni)
}
await privateNetwork.addNetwork(network)
// Previously created network didn't store `pif_device`
//
// 2019-08-22
// This is used to add the pif_device to networks created before this version. (v0.1.2)
// This will be removed in 1 year.
if (otherConfig['xo:sdn-controller:pif-device'] === undefined) {
const tunnel = getHostTunnelForNetwork(
privateNetwork.center,
network.$ref
)
const pif = xapi.getObjectByRef(tunnel.transport_PIF)
await network.update_other_config(
'xo:sdn-controller:pif-device',
pif.device
)
}
this._networks.set(network.$id, network.$ref)
if (privateNetwork.center !== undefined) {
this._starCenters.set(
privateNetwork.center.$id,
privateNetwork.center.$ref
)
}
})
)
// Add VNI to other config of networks without VNI
//
// 2019-08-22
// This is used to add the VNI to networks created before this version. (v0.1.3)
// This will be removed in 1 year.
await Promise.all(
map(noVniNetworks, async network => {
await network.update_other_config(
'xo:sdn-controller:vni',
String(++this._prevVni)
)
// Re-elect a center to apply the VNI
const privateNetwork = this._privateNetworks[
network.other_config['private-network-uuid']
]
await this._electNewCenter(privateNetwork)
})
)
})
)
const handleConnectedServer = ({ xapi }) => this._handleConnectedXapi(xapi)
const handleDisconnectedServer = ({ xapi }) =>
this._handleDisconnectedXapi(xapi)
this._xo.on('server:connected', handleConnectedServer)
this._xo.on('server:disconnected', handleDisconnectedServer)
this._cleaners.push(() => {
this._xo.removeListener('server:connected', handleConnectedServer)
this._xo.removeListener('server:disconnected', handleDisconnectedServer)
})
}
async unload() {
@@ -528,6 +452,159 @@ class SDNController extends EventEmitter {
// ===========================================================================
async _handleConnectedXapi(xapi) {
log.debug('xapi connected', { id: xapi.pool.uuid })
try {
await xapi.objectsFetched
if (isControllerNeeded(xapi)) {
return
}
this._cleaners.push(await this._manageXapi(xapi))
const hosts = filter(xapi.objects.all, { $type: 'host' })
for (const host of hosts) {
this._createOvsdbClient(host)
}
// Add already existing private networks
const networks = filter(xapi.objects.all, { $type: 'network' })
const noVniNetworks = []
await Promise.all(
networks.map(async network => {
// 2019-09-03
// Compatibility code, to be removed in 1 year.
await updateNetworkOtherConfig(network)
network = await network.$xapi.barrier(network.$ref)
let otherConfig = network.other_config
// 2019-10-01
// To be removed in a year
if (otherConfig['xo:sdn-controller:private-pool-wide'] === 'true') {
await updateOldPrivateNetwork(network)
}
network = await network.$xapi.barrier(network.$ref)
otherConfig = network.other_config
const uuid = otherConfig['xo:sdn-controller:private-network-uuid']
if (uuid === undefined) {
return
}
let privateNetwork = this._privateNetworks[uuid]
if (privateNetwork === undefined) {
privateNetwork = new PrivateNetwork(this, uuid)
this._privateNetworks[uuid] = privateNetwork
}
const vni = otherConfig['xo:sdn-controller:vni']
if (vni === undefined) {
noVniNetworks.push(network)
} else {
this._prevVni = Math.max(this._prevVni, +vni)
}
await privateNetwork.addNetwork(network)
// Previously created network didn't store `pif-device`
//
// 2019-08-22
// This is used to add the pif-device to networks created before this version. (v0.1.2)
// This will be removed in 1 year.
if (otherConfig['xo:sdn-controller:pif-device'] === undefined) {
const tunnel = getHostTunnelForNetwork(
privateNetwork.center,
network.$ref
)
const pif = xapi.getObjectByRef(tunnel.transport_PIF)
await network.update_other_config(
'xo:sdn-controller:pif-device',
pif.device
)
}
// Previously created network didn't store `vlan`
//
// 2020-01-27
// This is used to add the `vlan` to networks created before this version. (v0.4.0)
// This will be removed in 1 year.
if (otherConfig['xo:sdn-controller:vlan'] === undefined) {
const tunnel = getHostTunnelForNetwork(
privateNetwork.center,
network.$ref
)
const pif = xapi.getObjectByRef(tunnel.transport_PIF)
await network.update_other_config(
'xo:sdn-controller:vlan',
String(pif.VLAN)
)
}
this._networks.set(network.$id, network.$ref)
if (privateNetwork.center !== undefined) {
this._starCenters.set(
privateNetwork.center.$id,
privateNetwork.center.$ref
)
}
})
)
// Add VNI to other config of networks without VNI
//
// 2019-08-22
// This is used to add the VNI to networks created before this version. (v0.1.3)
// This will be removed in 1 year.
await Promise.all(
noVniNetworks.map(async network => {
await network.update_other_config(
'xo:sdn-controller:vni',
String(++this._prevVni)
)
// Re-elect a center to apply the VNI
const privateNetwork = this._privateNetworks[
network.other_config['xo:sdn-controller:private-network-uuid']
]
await this._electNewCenter(privateNetwork)
})
)
} catch (error) {
log.error('Error while handling xapi connection', {
id: xapi.pool.uuid,
error,
})
}
}
_handleDisconnectedXapi(xapi) {
log.debug('xapi disconnected', { id: xapi.pool.uuid })
try {
forOwn(this._privateNetworks, privateNetwork => {
privateNetwork.networks = omitBy(
privateNetwork.networks,
network => network.$pool.uuid === xapi.pool.uuid
)
if (privateNetwork.center?.$pool.uuid === xapi.pool.uuid) {
this._electNewCenter(privateNetwork)
}
})
this._privateNetworks = filter(
this._privateNetworks,
privateNetwork => Object.keys(privateNetwork.networks).length !== 0
)
} catch (error) {
log.error('Error while handling xapi disconnection', {
id: xapi.pool.uuid,
error,
})
}
}
// ===========================================================================
async _createPrivateNetwork({
poolIds,
pifIds,
@@ -544,7 +621,7 @@ class SDNController extends EventEmitter {
await this._setPoolControllerIfNeeded(pool)
const pifId = find(pifIds, id => {
const pifId = pifIds.find(id => {
const pif = this._xo.getXapiObject(this._xo.getObject(id, 'PIF'))
return pif.$pool.$ref === pool.$ref
})
@@ -563,6 +640,7 @@ class SDNController extends EventEmitter {
'xo:sdn-controller:encrypted': encrypted ? 'true' : undefined,
'xo:sdn-controller:pif-device': pif.device,
'xo:sdn-controller:private-network-uuid': privateNetwork.uuid,
'xo:sdn-controller:vlan': String(pif.VLAN),
'xo:sdn-controller:vni': String(vni),
},
})
@@ -581,7 +659,7 @@ class SDNController extends EventEmitter {
const hosts = filter(pool.$xapi.objects.all, { $type: 'host' })
await Promise.all(
map(hosts, async host => {
await createTunnel(host, createdNetwork, pif.device)
await createTunnel(host, createdNetwork)
this._createOvsdbClient(host)
})
)
@@ -626,7 +704,7 @@ class SDNController extends EventEmitter {
pool: object.$pool.name_label,
})
if (find(this._newHosts, { $ref: object.$ref }) === undefined) {
if (!this._newHosts.some(_ => _.$ref === object.$ref)) {
this._newHosts.push(object)
}
this._createOvsdbClient(object)
@@ -686,6 +764,11 @@ class SDNController extends EventEmitter {
network => network.$ref === networkRef
)
})
this._privateNetworks = filter(
this._privateNetworks,
privateNetwork => Object.keys(privateNetwork.networks).length !== 0
)
}
} catch (error) {
log.error('Error in _objectsRemoved', {
@@ -748,12 +831,16 @@ class SDNController extends EventEmitter {
}
async _hostUpdated(host) {
const newHost = find(this._newHosts, { $ref: host.$ref })
if (!host.enabled || host.PIFs.length === 0 || newHost === undefined) {
let i
if (
!host.enabled ||
host.PIFs.length === 0 ||
(i = this._newHosts.findIndex(_ => _.$ref === host.$ref)) === -1
) {
return
}
this._newHosts = this._newHosts.slice(this._newHosts.indexOf(newHost), 1)
this._newHosts.splice(i, 1)
log.debug('Sync pool certificates', {
newHost: host.name_label,
@@ -779,9 +866,7 @@ class SDNController extends EventEmitter {
continue
}
const pifDevice =
network.other_config['xo:sdn-controller:pif-device'] ?? 'eth0'
await createTunnel(host, network, pifDevice)
await createTunnel(host, network)
}
await this._addHostToPrivateNetworks(host)
@@ -803,7 +888,7 @@ class SDNController extends EventEmitter {
// ---------------------------------------------------------------------------
async _setPoolControllerIfNeeded(pool) {
if (!setControllerNeeded(pool.$xapi)) {
if (!isControllerNeeded(pool.$xapi)) {
// Nothing to do
return
}
@@ -989,9 +1074,8 @@ class SDNController extends EventEmitter {
// ---------------------------------------------------------------------------
_createOvsdbClient(host) {
const foundClient = this.ovsdbClients[host.$ref]
if (foundClient !== undefined) {
return foundClient
if (this.ovsdbClients[host.$ref] !== undefined) {
return
}
const client = new OvsdbClient(
@@ -1001,7 +1085,6 @@ class SDNController extends EventEmitter {
this._caCert
)
this.ovsdbClients[host.$ref] = client
return client
}
}

View File

@@ -1,5 +1,5 @@
import createLogger from '@xen-orchestra/log'
import { filter, find, forOwn, map, sample } from 'lodash'
import { filter, forOwn, sample } from 'lodash'
// =============================================================================
@@ -111,7 +111,7 @@ export class PrivateNetwork {
const hosts = filter(network.$pool.$xapi.objects.all, { $type: 'host' })
return Promise.all(
map(hosts, async host => {
hosts.map(async host => {
const hostClient = this.controller.ovsdbClients[host.$ref]
const network = this.networks[host.$pool.uuid]
await hostClient.resetForNetwork(network, this.uuid)
@@ -126,9 +126,9 @@ export class PrivateNetwork {
// TODO: make it random
const hosts = this._getHosts()
for (const host of hosts) {
const pif = find(host.$PIFs, {
network: this.networks[host.$pool.uuid].$ref,
})
const pif = host.$PIFs.find(
_ => _.network === this.networks[host.$pool.uuid].$ref
)
if (pif?.currently_attached && host.$metrics.live) {
this.center = host
break
@@ -145,7 +145,7 @@ export class PrivateNetwork {
await this._reset()
// Recreate star topology
await Promise.all(map(hosts, host => this.addHost(host)))
await Promise.all(hosts.map(host => this.addHost(host)))
log.info('New star-center elected', {
center: this.center.name_label,
@@ -167,7 +167,7 @@ export class PrivateNetwork {
_reset() {
return Promise.all(
map(this._getHosts(), async host => {
this._getHosts().map(async host => {
// Clean old ports and interfaces
const hostClient = this.controller.ovsdbClients[host.$ref]
if (hostClient === undefined) {

View File

@@ -131,7 +131,7 @@ export class OvsdbClient {
table: 'Port',
row: {
name: portName,
interfaces: ['set', [['named-uuid', 'new_iface']]],
interfaces: ['named-uuid', 'new_iface'],
other_config: toMap({
'xo:sdn-controller:private-network-uuid': privateNetworkUuid,
}),
@@ -143,7 +143,7 @@ export class OvsdbClient {
op: 'mutate',
table: 'Bridge',
where: [['_uuid', '==', ['uuid', bridge.uuid]]],
mutations: [['ports', 'insert', ['set', [['named-uuid', 'new_port']]]]],
mutations: [['ports', 'insert', ['named-uuid', 'new_port']]],
}
const params = [
'Open_vSwitch',
@@ -487,7 +487,7 @@ export class OvsdbClient {
let resultRequestId
do {
try {
result = await fromEvent(stream, 'data', {})
result = await fromEvent(stream, 'data')
} catch (error) {
log.error('Error while waiting for stream data', {
error,
@@ -518,7 +518,7 @@ export class OvsdbClient {
const socket = connect(options)
try {
await fromEvent(socket, 'secureConnect', {})
await fromEvent(socket, 'secureConnect')
} catch (error) {
log.error('TLS connection failed', {
error,

View File

@@ -38,7 +38,7 @@
"lodash": "^4.17.11",
"promise-toolbox": "^0.15.0",
"xo-collection": "^0.4.1",
"xo-common": "^0.2.0",
"xo-common": "^0.4.0",
"xo-lib": "^0.9.0"
},
"scripts": {

View File

@@ -1,5 +1,6 @@
{
"name": "xo-server-transport-icinga2",
"description": "Sends backup runs statuses to icinga2 server",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-transport-icinga2",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
@@ -15,7 +16,7 @@
"predev": "yarn run prebuild",
"prepublishOnly": "yarn run build"
},
"version": "0.1.0",
"version": "0.1.1",
"engines": {
"node": ">=8.9.4"
},

View File

@@ -1,8 +1,8 @@
{
"name": "xo-server-transport-nagios",
"version": "0.1.0",
"version": "0.1.1",
"license": "ISC",
"description": "",
"description": "Send backup runs statuses to Nagios",
"keywords": [
"nagios",
"orchestra",

View File

@@ -1,8 +1,8 @@
{
"name": "xo-server-usage-report",
"version": "0.7.3",
"version": "0.7.5",
"license": "AGPL-3.0",
"description": "",
"description": "Report resources usage with their evolution",
"keywords": [
"orchestra",
"plugin",

View File

@@ -30,8 +30,6 @@ const GRANULARITY = 'days'
const pReadFile = promisify(readFile)
const pWriteFile = promisify(writeFile)
const currDate = new Date().toISOString().slice(0, 10)
const compareOperators = {
'>': (l, r) => l > r,
}
@@ -615,7 +613,7 @@ async function computeEvolution({ storedStatsPath, ...newStats }) {
}
}
async function dataBuilder({ xo, storedStatsPath, all }) {
async function dataBuilder({ currDate, xo, storedStatsPath, all }) {
const xoObjects = values(xo.getObjects())
const runningVms = filter(xoObjects, { type: 'VM', power_state: 'Running' })
const haltedVms = filter(xoObjects, { type: 'VM', power_state: 'Halted' })
@@ -766,7 +764,9 @@ class UsageReportPlugin {
)
}
const currDate = new Date().toISOString().slice(0, 10)
const data = await dataBuilder({
currDate,
xo,
storedStatsPath: this._storedStatsPath,
all: this._conf.all,

View File

@@ -1,8 +1,8 @@
{
"name": "xo-server-web-hooks",
"version": "0.1.0",
"version": "0.1.1",
"license": "AGPL-3.0",
"description": "",
"description": "Sends HTTP requests on XO-Server API calls",
"keywords": [
"hooks",
"orchestra",

View File

@@ -1,30 +0,0 @@
Error.stackTraceLimit = 100
// Removes internal modules.
try {
const sep = require('path').sep
require('stack-chain').filter.attach(function(_, frames) {
const filtered = frames.filter(function(frame) {
const name = frame && frame.getFileName()
return (
// has a filename
name &&
// contains a separator (no internal modules)
name.indexOf(sep) !== -1 &&
// does not start with `internal`
name.lastIndexOf('internal', 0) !== -1
)
})
// depd (used amongst other by express requires at least 3 frames
// in the stack.
return filtered.length > 2 ? filtered : frames
})
} catch (_) {}
// Source maps.
try {
require('julien-f-source-map-support/register')
} catch (_) {}

View File

@@ -10,7 +10,11 @@ if (process.env.NODE_ENV === undefined) {
}
// Better stack traces if possible.
require('../better-stacks')
try {
require('source-map-support').install({
handleUncaughtExceptions: false
});
} catch (_) {}
// Use Bluebird for all promises as it provides better performance and
// less memory usage.

View File

@@ -5,6 +5,10 @@
// ===================================================================
// Better stack traces if possible.
require('../better-stacks')
try {
require('source-map-support').install({
handleUncaughtExceptions: false,
})
} catch (_) {}
require('exec-promise')(require('../dist/logs-cli').default)

View File

@@ -74,6 +74,7 @@ poolMetadataTimeout = '10 minutes'
# https://github.com/naugtur/blocked-at#params-and-return-value
[blockedAtOptions]
enabled = false
threshold = 1000
# Helmet handles HTTP security via headers
@@ -120,3 +121,25 @@ timeout = 600e3
[xapiOptions]
maxUncoalescedVdis = 1
vdiExportConcurrency = 12
vmExportConcurrency = 2
vmSnapshotConcurrency = 2
["xo-proxy"]
callTimeout = '1 min'
channel = 'xo-proxy-appliance'
namespace = 'xoProxyAppliance'
proxyName = 'Proxy {date}'
vmName = 'XOA Proxy {date}'
# The duration for which we can wait for the VM networks to be defined
vmNetworksTimeout = '5 min'
vmTag = 'XOA Proxy'
# The duration for which we can wait for the XOA to be upgraded
xoaUpgradeTimeout = '5 min'

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "xo-server",
"version": "5.54.0",
"version": "5.58.0",
"license": "AGPL-3.0",
"description": "Server part of Xen-Orchestra",
"keywords": [
@@ -19,7 +19,6 @@
},
"preferGlobal": true,
"files": [
"better-stacks.js",
"bin/",
"dist/",
"config.toml",
@@ -35,12 +34,14 @@
"dependencies": {
"@iarna/toml": "^2.2.1",
"@xen-orchestra/async-map": "^0.0.0",
"@xen-orchestra/backups": "^0.1.1",
"@xen-orchestra/cron": "^1.0.6",
"@xen-orchestra/defined": "^0.0.0",
"@xen-orchestra/emit-async": "^0.0.0",
"@xen-orchestra/fs": "^0.10.2",
"@xen-orchestra/fs": "^0.10.3",
"@xen-orchestra/log": "^0.2.0",
"@xen-orchestra/mixin": "^0.0.0",
"@xen-orchestra/template": "^0.1.0",
"ajv": "^6.1.1",
"app-conf": "^0.7.0",
"archiver": "^3.0.0",
@@ -68,11 +69,11 @@
"fs-extra": "^8.0.1",
"get-stream": "^5.1.0",
"golike-defer": "^0.4.1",
"hashy": "^0.7.1",
"hashy": "^0.8.0",
"helmet": "^3.9.0",
"highland": "^2.11.1",
"http-proxy": "^1.16.2",
"http-request-plus": "^0.9.1",
"http-request-plus": "^0.8.0",
"http-server-plus": "^0.11.0",
"human-format": "^0.10.0",
"is-redirect": "^1.0.0",
@@ -81,12 +82,8 @@
"js-yaml": "^3.10.0",
"json-rpc-peer": "^0.15.3",
"json5": "^2.0.1",
"julien-f-source-map-support": "0.1.0",
"julien-f-unzip": "^0.2.1",
"kindof": "^2.0.0",
"level": "^6.0.0",
"level-party": "^4.0.0",
"level-sublevel": "^6.6.1",
"limit-concurrency-decorator": "^0.4.0",
"lodash": "^4.17.4",
"make-error": "^1",
@@ -106,29 +103,35 @@
"proxy-agent": "^3.0.0",
"pug": "^2.0.0-rc.4",
"pump": "^3.0.0",
"pumpify": "^2.0.0",
"pw": "^0.0.4",
"readable-stream": "^3.2.0",
"redis": "^2.8.0",
"schema-inspector": "^1.6.8",
"semver": "^6.0.0",
"serve-static": "^1.13.1",
"set-cookie-parser": "^2.3.5",
"source-map-support": "^0.5.16",
"split-lines": "^2.0.0",
"split2": "^3.1.1",
"stack-chain": "^2.0.0",
"stoppable": "^1.0.5",
"strict-timeout": "^1.0.0",
"struct-fu": "^1.2.0",
"subleveldown": "^4.1.4",
"tar-stream": "^2.0.1",
"through2": "^3.0.0",
"tmp": "^0.1.0",
"unzipper": "^0.10.5",
"uuid": "^3.0.1",
"value-matcher": "^0.2.0",
"vhd-lib": "^0.7.2",
"ws": "^7.1.2",
"xen-api": "^0.27.3",
"xen-api": "^0.28.3",
"xml2js": "^0.4.19",
"xo-acl-resolver": "^0.4.1",
"xo-collection": "^0.4.1",
"xo-common": "^0.2.0",
"xo-common": "^0.4.0",
"xo-remote-parser": "^0.5.0",
"xo-vmdk-to-vhd": "^0.1.8",
"yazl": "^2.4.3"

View File

@@ -0,0 +1,38 @@
function onEnd() {
this.onError(new Error('unexpected end of stream'))
}
function onError(reject, error) {
reject(error)
removeListeners.call(this)
}
function onReadable(resolve, size) {
const data = this.stream.read(size)
if (data !== null) {
resolve(data)
removeListeners.call(this)
}
}
function removeListeners() {
const { onEnd, onError, onReadable, stream } = this
stream.removeListener('end', onEnd)
stream.removeListener('error', onError)
stream.removeListener('readable', onReadable)
}
function Reader(stream, size, resolve, reject) {
stream.on('end', (this.onEnd = onEnd.bind(this, reject)))
stream.on('error', (this.onError = onError.bind(this, reject)))
stream.on(
'readable',
(this.onReadable = onReadable.bind(this, resolve, size))
)
this.stream = stream
}
export default (stream, size) =>
new Promise((resolve, reject) => {
new Reader(stream, size, resolve, reject).onReadable()
})

View File

@@ -24,6 +24,10 @@ createJob.params = {
type: 'string',
optional: true,
},
proxy: {
type: 'string',
optional: true,
},
remotes: {
type: 'object',
optional: true,
@@ -85,6 +89,10 @@ editJob.params = {
type: 'string',
optional: true,
},
proxy: {
type: ['string', 'null'],
optional: true,
},
remotes: {
type: 'object',
optional: true,

View File

@@ -1,18 +1,21 @@
import createLogger from '@xen-orchestra/log'
import pump from 'pump'
import convertVmdkToVhdStream from 'xo-vmdk-to-vhd'
import createLogger from '@xen-orchestra/log'
import defer from 'golike-defer'
import pump from 'pump'
import { format, JsonRpcError } from 'json-rpc-peer'
import { noSuchObject } from 'xo-common/api-errors'
import { peekFooterFromVhdStream } from 'vhd-lib'
import { parseSize } from '../utils'
import { VDI_FORMAT_VHD } from '../xapi'
const log = createLogger('xo:disk')
// ===================================================================
export async function create({ name, size, sr, vm, bootable, position, mode }) {
export const create = defer(async function(
$defer,
{ name, size, sr, vm, bootable, position, mode }
) {
const attach = vm !== undefined
do {
@@ -23,6 +26,9 @@ export async function create({ name, size, sr, vm, bootable, position, mode }) {
sr.id,
])
await this.allocateLimitsInResourceSet({ disk: size }, resourceSet)
$defer.onFailure(() =>
this.releaseLimitsInResourceSet({ disk: size }, resourceSet)
)
break
} catch (error) {
@@ -43,6 +49,7 @@ export async function create({ name, size, sr, vm, bootable, position, mode }) {
size,
sr: sr._xapiId,
})
$defer.onFailure(() => xapi.deleteVdi(vdi.$id))
if (attach) {
await xapi.createVbd({
@@ -55,7 +62,7 @@ export async function create({ name, size, sr, vm, bootable, position, mode }) {
}
return vdi.$id
}
})
create.description = 'create a new disk on a SR'
@@ -154,21 +161,6 @@ importContent.resolve = {
// -------------------------------------------------------------------
export async function resize({ vdi, size }) {
await this.getXapi(vdi).resizeVdi(vdi._xapiId, parseSize(size))
}
resize.description = 'resize an existing VDI'
resize.params = {
id: { type: 'string' },
size: { type: ['integer', 'string'] },
}
resize.resolve = {
vdi: ['id', ['VDI', 'VDI-snapshot'], 'administrate'],
}
async function handleImport(
req,
res,

View File

@@ -46,7 +46,6 @@ export async function createBonded({
description,
pifs,
mtu = 1500,
mac,
bondMode,
}) {
return this.getXapi(pool).createBondedNetwork({
@@ -54,7 +53,6 @@ export async function createBonded({
description,
pifIds: mapToArray(pifs, pif => this.getObject(pif, 'PIF')._xapiId),
mtu: +mtu,
mac,
bondMode,
})
}
@@ -70,7 +68,6 @@ createBonded.params = {
},
},
mtu: { type: ['integer', 'string'], optional: true },
mac: { type: 'string', optional: true },
// RegExp since schema-inspector does not provide a param check based on an enumeration
bondMode: {
type: 'string',

Some files were not shown because too many files have changed in this diff Show More