Compare commits

...
Author SHA1 Message Date
yannick Achy 5f3960ec03 hosts updates revision 2021-04-08 11:10:07 +02:00
yannick Achy 077f66d6a9 Merge branch 'master' of https://github.com/vatesfr/xen-orchestra 2021-04-08 10:17:40 +02:00
Julien Fontanet de288a008d fix(proxy): upgrade to koa-compress@5
Fix a koa-compress@4 bug which compress the reply when no accept-encoding header has been passed.
2021-04-07 17:21:10 +02:00
Julien Fontanet 3c5d73224a feat(normalize-packages): delete empty dependencies, description and keywords fields 2021-04-07 15:14:48 +02:00
Julien Fontanet 05f9c07836 chore: add descriptions to all pkgs (but mixin) 2021-04-07 15:13:18 +02:00
Julien Fontanet a7ba6add39 feat(read-chunk): ensure function is properly named 2021-04-07 14:02:50 +02:00
Julien Fontanet 479973bf06 fix(xapi): add missing cli.js
Introduced by be9b5332d9
2021-04-07 14:00:40 +02:00
Julien Fontanet 854c9fe794 fix(.gitignore): handle @vates/* pkgs 2021-04-07 13:59:07 +02:00
Julien Fontanet 5a17c75fe4 feat: unified .npmignore for all packages
Ensure sources, tests and USAGE.Md files will not be published.
2021-04-07 13:58:14 +02:00
Julien Fontanet 4dc5eff252 chore(normalize-packages): remove unused require 2021-04-07 13:39:12 +02:00
Julien Fontanet 7fe0d78154 fix(compose/USAGE): typo 2021-04-07 13:36:24 +02:00
Julien Fontanet 2c709dc205 fix(xo-server/proxies): readChunk import
Introduced by 538253cdc
2021-04-07 13:09:29 +02:00
Julien Fontanet 9353349a39 chore(vhd-lib): use @vates/read-chunk 2021-04-07 13:08:44 +02:00
Julien Fontanet d3049b2bfa feat(@vates/read-chunk): 0.1.2 2021-04-07 13:07:57 +02:00
Julien Fontanet 61cb2529bd feat(read-chunk/package.json): only publish index.js 2021-04-07 13:05:49 +02:00
Julien Fontanet e6c6e4395f chore(read-chunk): add tests 2021-04-07 13:03:56 +02:00
Julien Fontanet 959c955616 feat(read-chunk): handle 0 size 2021-04-07 12:51:27 +02:00
Julien Fontanet 538253cdc1 chore(xo-server/proxies): use @vates/read-chunk 2021-04-07 12:31:16 +02:00
Julien Fontanet b4c6594333 chore(xo-server/utils): remove unused wrap 2021-04-07 12:25:47 +02:00
Julien Fontanet a7f5f8889c chore(xo-server/http): use @xen-orchestra/defined 2021-04-07 12:15:33 +02:00
Julien Fontanet 1c9b4cf552 feat(xo-server/Xo): pass appDir, AppName and httpServer
As done in xo-proxy.

This may allow sharing mixins in the future.
2021-04-07 10:41:50 +02:00
Julien Fontanet ce09f487bd feat(xo-server/XenServers): dont auto connect on safe mode 2021-04-07 10:41:50 +02:00
Julien Fontanet a5d1decf40 feat(xo-server/Xo): safeMode param 2021-04-07 10:41:50 +02:00
Julien Fontanet 7024c7d598 chore(xo-server/Xo): pass config as named param
As done in xo-proxy.
2021-04-07 10:41:50 +02:00
Jon Sands 8109253eeb fix(xo-web/en): grammar fixes (#5713) 2021-04-06 10:31:52 +02:00
Julien Fontanet b61f1e3803 fix(xapi/VM_snapshot): VM#refresh_snapshots does not exist
Fixes xoa-support#3587
2021-04-04 22:41:46 +02:00
Julien Fontanet db40f80be7 chore(CHANGELOG.unreleased): formatting 2021-04-04 22:36:35 +02:00
Mathieu 26eaf97032 fix(xo-web/restore): generateNewMACAddresses disabled by default (#5707) 2021-04-04 18:41:37 +02:00
Ronan Abhamon da349374bf feat(load-balancer): add option to disable migration (#5706) 2021-04-02 17:32:26 +02:00
Julien Fontanet 0ffa925fee chore(xo-server-load-balancer): format with Prettier 2021-04-02 15:34:38 +02:00
Julien Fontanet 082787c4cf chore: update dependencies 2021-04-02 15:34:19 +02:00
Julien Fontanet be9b5332d9 feat(xapi): add xo-xapi CLI
Allows to easily test @xen-orchestra/xapi features.
2021-04-01 14:47:04 +02:00
Julien Fontanet 97ae3ba7d3 feat(@xen-orchestra/proxy): 0.12.0 2021-04-01 14:09:09 +02:00
Julien Fontanet d047f401c2 fix(CHANGELOG): move Highlights title under badge
Introduced by 1e9e78223
2021-04-01 14:08:12 +02:00
Julien Fontanet 1e9e78223b fix(CHANGELOG): missing Highlights title 2021-04-01 13:44:21 +02:00
Julien Fontanet 6d5baebd08 feat: release 5.57.0 2021-04-01 13:29:58 +02:00
Pierre Donias 4e758dbb85 feat: technical release (#5705) 2021-04-01 11:28:09 +02:00
Julien Fontanet 40d943c620 feat(backups/CR writer): delete interrupted copies in prepare() 2021-04-01 10:52:06 +02:00
Julien Fontanet e69b6c4dc8 fix(backups/delta writers): compute old entries before run 2021-04-01 10:48:39 +02:00
Julien Fontanet 23444f7083 fix(xo-server): Backup/getConnectedRecord receive XAPI not XO type 2021-03-31 16:48:20 +02:00
Julien Fontanet 8c077b96df chore(xo-server/getXapiObject): clarify that second param is an XO type 2021-03-31 16:31:56 +02:00
Pierre Donias 4b1a055a88 feat: technical release (#5704) 2021-03-31 11:15:41 +02:00
Rajaa.BARHTAOUI b4ddcc1dec feat(xo-server,xo-web/startVm): avoid booting VM if there's an identical MAC address elsewhere (#5655)
Fixes #5601
2021-03-31 10:50:32 +02:00
badrAZ 271d2e3abc feat(fs): expose highWaterMark stream option (#5676) 2021-03-31 10:34:42 +02:00
Julien Fontanet 37b6399398 fix(backups/importDeltaVm): reverse newMacAddresses condition for VIF creation
Introduced by 4df8c9610
2021-03-30 21:26:08 +02:00
Julien Fontanet ebf19b1506 fix(proxy/backup.importVmBackup): settings param is optional
Introduced by b475b265a
2021-03-30 21:26:08 +02:00
Julien Fontanet e4dd773644 fix(proxy/api/ndJsonStream): dont fail if one message cannot be JSONified 2021-03-30 21:26:08 +02:00
Mathieu f9b3a1f293 feat(xo-web/restore): support new mac addresses (#5697) 2021-03-30 17:48:45 +02:00
Rajaa.BARHTAOUI 7c9850ada8 feat(xo-server-perf-alert): ability to choose all hosts, VMs and SRs (#5692)
Fixes #2987
2021-03-30 17:26:48 +02:00
Ronan Abhamon 9ef05b8afe feat(load-balancer): add new anti-affinity mode (#5652)
Fixes #5600
2021-03-30 17:25:41 +02:00
Mathieu efdd196441 feat(xo-web/proxies): move proxy actions to dropdown (#5688) 2021-03-30 16:56:10 +02:00
Julien Fontanet 6e780a3876 fix(xapi/call{,Async}): fix call to retry
Introduced by 3bb7d2c29
2021-03-30 15:42:05 +02:00
Julien Fontanet b475b265ae feat(import VM backup): newMacAddresses setting
Related to #5697
2021-03-30 14:31:08 +02:00
Julien Fontanet 3bb7d2c294 feat(xapi/call{,Async}): retry if too many pending tasks
Logic from xo-server/xapi/call
2021-03-30 14:21:19 +02:00
Julien Fontanet 594a148a39 feat(xo-server): VDI_destroy instead of deleteVdi 2021-03-30 14:08:25 +02:00
Julien Fontanet 779591db36 feat(xapi/VDI_destroy): dont fail if VDI not found
Aligned with xo-server/xapi/deleteVdi.
2021-03-30 13:59:10 +02:00
Julien Fontanet c002eeffb7 chore(proxy): remove unused Node test
The proxy now requires Node >=12
2021-03-30 09:23:15 +02:00
Julien Fontanet 1dac973d70 feat(backups/Task.wrapFn): compatibility with @decorateWith 2021-03-30 09:20:30 +02:00
Julien Fontanet f5024f0e75 feat(backups/delta writers): split run method in prepare/transfer/cleanup
Fixes xoa-support#3523

This avoids starting the transfer before the writers are ready, which caused it to failed with `deleteFirst` when deletion was so long that the transfer stalled.
2021-03-30 09:20:30 +02:00
Pierre Donias cf320c08c5 feat: technical release (#5702) 2021-03-29 16:45:00 +02:00
Rajaa.BARHTAOUI 8973c9550c fix(xo-web/vm/advanced): remove noop (#5700)
See https://github.com/vatesfr/xen-orchestra/pull/3774/files#r602860699
2021-03-29 15:10:48 +02:00
Julien Fontanet bb671f0e93 feat(xapi): update to xo-common@0.7.0 2021-03-29 15:01:12 +02:00
Julien Fontanet a8774b5011 chore(log/transport/console): remove unused code 2021-03-29 14:59:14 +02:00
Julien Fontanet f092cd41bc chore: named import from @xen-orchestra/log 2021-03-29 14:06:29 +02:00
yannick Achy a548c225ff Merge branch 'master' of https://github.com/vatesfr/xen-orchestra 2021-03-29 10:22:20 +02:00
Julien Fontanet b17ec9731a fix(xapi/task_create): dont use super
Introduced by 021810201b

It cannot be used due to our mixin architecture.
2021-03-28 23:29:17 +02:00
Julien Fontanet 021810201b fix(xapi/task_create): remove duplicate [XO] prefix
Found while investigating xoa-support#3553
2021-03-28 14:30:36 +02:00
Julien Fontanet 6038dc9c8a fix(xo-web/vm/advanced): RTL819 → RTL8139
Fixes #5698
2021-03-28 12:23:52 +02:00
Julien Fontanet 4df8c9610a fix(backups/importDeltaVm): new mac_seed when using newMacAddresses 2021-03-26 17:14:37 +01:00
Julien Fontanet 6c12dd4f16 feat(xapi/VM_create): generateMacSeed option 2021-03-26 17:14:37 +01:00
badrAZ ad3b8fa59f feat(xo-server-usage-report): add VM IP addresses to the report (#5696) 2021-03-26 14:39:35 +01:00
Mathieu cb52a8b51b feat(xo-server): VM_destroy instead of deleteVm (#5693)
Continuation of 5f1c127
2021-03-26 14:23:04 +01:00
badrAZ 22ba1302d2 fix(xo-server-backup-reports): support failed targets (#5694)
Introduced by d282d8dd5
2021-03-26 10:27:08 +01:00
Mathieu 7d04559921 fix(xo-web/disk import): an error has occurred (#5683)
Fixes #5663

undefined files in collection due to unhandled disk formats
2021-03-26 09:37:31 +01:00
Julien Fontanet e40e35d30c fix(xo-server): dont provide mac_send when importing OVA VM
Fixes xoa-support#3544
2021-03-25 15:51:02 +01:00
Julien Fontanet d1af9f236c feat(backup/importDeltaVm): restoreMacAddresses option 2021-03-24 16:39:08 +01:00
Julien Fontanet 45a0ff26c5 feat(xapi/VIF_create): MAC must be passed explicitely 2021-03-24 16:38:19 +01:00
Julien Fontanet 1fd330d7a4 fix(CHANGELOG.unreleased): @vates/disposable 2021-03-24 16:03:49 +01:00
Julien Fontanet 09833f31cf fix(xapi/VM_export): correctly destroy snapshot after export 2021-03-24 16:00:45 +01:00
Julien Fontanet 20e7a036cf feat(xapi): no longer use promise-toolbox/cancelable 2021-03-24 15:34:47 +01:00
Julien Fontanet e6667c1782 fix(xapi/VM_destroy): only update blocked operations when bypassBlockedOperation 2021-03-24 15:13:09 +01:00
Julien Fontanet 657935eba5 feat(xapi/VM_destroy): split bypassBlockedOperation out of force 2021-03-24 15:12:25 +01:00
Julien Fontanet 67b905a757 feat(xapi/VM_destroy): forceDeleteDefaultTemplate default to force 2021-03-24 15:11:49 +01:00
Julien Fontanet 55cede0434 fix(xapi/VM_destroy): ignore missing VM.set_is_default_template
Introduced by 5f1c1278e
2021-03-24 15:09:09 +01:00
Julien Fontanet c7677d6d1e fix(xapi/VM_destroy): only update default template when forceDeleteDefaultTemplate 2021-03-24 15:07:30 +01:00
Mathieu d191ca54ad feat(xo-server/xapi-object-to-xo): display full driver version (#5691) 2021-03-24 13:38:49 +01:00
badrAZ 20f4c952fe feat(@xen-orchestra/backups#RemoteAdapter): ability to clean broken backups (#5684) 2021-03-24 10:00:47 +01:00
Julien Fontanet 0bd09896f3 feat(docs/xoa): network config for other interfaces 2021-03-24 09:49:59 +01:00
badrAZ 60ecfbfb8e feat(xo-server, proxy, @xen-orchestra/backups): execute backup jobs on different processes (#5660) 2021-03-24 09:25:52 +01:00
Julien Fontanet 8921d78610 fix(disposable/deduped): call dispose with disposable context 2021-03-24 00:27:25 +01:00
Julien Fontanet b243ff94e9 feat(fs/lock): returns a disposable 2021-03-23 23:04:49 +01:00
Mathieu 5f1c1278e3 fix(xapi/VM_destroy): handle is_default_template (#5644) 2021-03-23 17:28:18 +01:00
badrAZ fa56e594b1 feat(xo-server-transport-email): ability to customize transport settings (#5681)
See xoa-support#3327

This functionnality can help users to get more info about their SMTP issues
2021-03-23 15:47:31 +01:00
badrAZ c9b64927be feat(@xen-orchestra/fs): ability to lock a path (#5689)
Related to #5684
2021-03-23 13:00:15 +01:00
Julien Fontanet 3689cb2a99 chore(fs/outputStream): dont normalize path twice 2021-03-23 12:53:17 +01:00
Julien Fontanet 3bb7541361 fix(fs/local): opts is optional 2021-03-23 12:53:17 +01:00
Julien Fontanet 7b15aa5f83 fix(package.json/jest.moduleNameMapper): dont map sub-modules
For instance `@xen-orchestra/async-map/legacy`.
2021-03-23 12:53:17 +01:00
Julien Fontanet 690d3036db chore(xo-server): use native Promise#finally() (#5687) 2021-03-22 17:25:40 +01:00
Julien Fontanet 416e8d02a1 chore(xo-server): usingDisposable.use (#5686)
`using` is deprecated.
2021-03-22 17:25:28 +01:00
Julien Fontanet a968c2d2b7 chore(xo-server): remove promise-toolbox/all uses (#5685) 2021-03-22 15:58:13 +01:00
Julien Fontanet b4787bf444 fix(xo-server/(re)deployProxy): works whith missing bound VM 2021-03-22 14:44:39 +01:00
Julien Fontanet a4d90e8aff fix(xo-web/proxies): ignore running jobs on force upgrade
See #3527
2021-03-22 14:37:34 +01:00
Julien Fontanet 32d0606ee4 feat(@xen-orchestra/proxy): 0.11.6 2021-03-22 13:41:28 +01:00
Julien Fontanet 4541f7c758 chore(xo-server): remove pSettle (#5682) 2021-03-22 10:37:07 +01:00
Julien Fontanet 65428d629c feat: release 5.56.2 2021-03-22 10:36:24 +01:00
Julien Fontanet bdfd9cc617 feat: technical release 2021-03-22 09:56:31 +01:00
Julien Fontanet 6d324921a0 fix(CHANGELOG.unreleased): add xapi to packages to release
Introduced by dcf0f5c5a
2021-03-19 14:53:29 +01:00
Julien Fontanet dcf0f5c5a3 fix(xapi/VM_create): ignore missing VM.set_bios_strings
Fixes xoa-support#3516
2021-03-19 14:51:51 +01:00
Julien Fontanet d98f851a2c fix(xo-web/restore): dont break if log is missing result
Found when investigating xoa-support#3516
2021-03-19 13:46:22 +01:00
Julien Fontanet a95b102396 fix(backups/ImportVmBackup#run): dont swallow errors
Found when investigating xoa-support#3516
2021-03-19 13:38:17 +01:00
Julien Fontanet 7e2fbbaae6 fix(xo-server/createAuthenticationToken): parse expiresIn param
Introduced by 92cf6bb887
2021-03-19 13:02:19 +01:00
Julien Fontanet 070e8b0b54 fix(docs): restore full_backups.md
Introduced by 078f40281
2021-03-19 11:04:42 +01:00
Yannick Achy 7b49a1296c feat(doc): various changes (#5679) 2021-03-19 11:02:24 +01:00
Julien Fontanet 1e278bde92 feat(xo-common/Error.is): apply predicate only on data
See #5644
2021-03-19 10:30:35 +01:00
Yannick Achy 078f402819 feat(doc): check dead links and duplicate (#5664) 2021-03-18 09:35:07 +01:00
Mathieu 52af565f77 fix(fs/localHandler): resource temporarily unavailable (#5612)
Fixes xoa-support#3414
2021-03-17 15:28:04 +01:00
Julien Fontanet 853905e52f feat(xen-api): automatically retry ro calls on ECONNRESET (#5674)
See xoa-support#3266
2021-03-16 17:31:18 +01:00
Julien Fontanet 2e0e1d2aac fix(xo-server/xen-servers): fix autoconnection
Fixes #5675

Introduced by 2fbfc97cca
2021-03-16 13:59:01 +01:00
Julien Fontanet 7f33a62bb5 fix(async-map/asyncMap): fix typing of first param 2021-03-16 11:32:39 +01:00
Julien Fontanet bdb59ea429 fix(Travis CI): use Node 14 2021-03-15 18:26:22 +01:00
Julien Fontanet 1c0ffe39f7 fix(xapi): merge vdiDestroyRetryWhenInUse after defaults 2021-03-15 13:22:41 +01:00
Julien Fontanet 2fbfc97cca fix(xo-server): connect servers after config import (#5672)
Fixes #5670
2021-03-15 11:49:41 +01:00
Pierre Donias 482299e765 fix(xo-web/pool): disconnectServer → disableServer (#5671)
Fixes #5669
Introduced c7aaeca530
2021-03-15 09:53:34 +01:00
Julien Fontanet 54f4734847 chore: remove babel-plugin-lodash where unnecessary 2021-03-13 20:47:20 +01:00
Julien Fontanet 0fb6cef577 chore(defined): remove Flow 2021-03-13 20:47:20 +01:00
badrAZ 7eec264961 chore(@xen-orchestra/backups): fix logger names (#5666) 2021-03-12 13:53:43 +01:00
Julien Fontanet aff874c68a chore(xo-server,xo-server-load-balancer): phase out mapToArray (#5662)
Use native `Array#map` or `Object.values` where possible and import directly from `lodash`.

Reasons:
- less dependencies
- more idiomatic
- better example for new code
2021-03-11 15:17:28 +01:00
Julien Fontanet 27abee0850 chore(xo-server-load-balancer): typo ressource → resource 2021-03-11 14:17:02 +01:00
Julien Fontanet bcfb19f7c5 feat(normalize-packages): delete empty bin field 2021-03-11 12:15:53 +01:00
Julien Fontanet 306a8ce0df feat(@xen-orchestra/proxy): 0.11.5 2021-03-10 13:48:15 +01:00
Julien Fontanet d9ea8d2c9c feat: release 5.56.1 2021-03-10 13:04:11 +01:00
Julien Fontanet b479956bb2 feat: technical release (#5657) 2021-03-10 11:11:27 +01:00
Julien Fontanet b32dc0e450 fix(xen-api/call): allow *.get_all_records in read only 2021-03-10 09:41:49 +01:00
badrAZ 5cca5d69af fix(@xen-orchestra/backups/Backup.js): fix rolling snapshot not ran if alone (#5656) 2021-03-09 18:24:58 +01:00
badrAZ e0e89213d3 chore(xo-server): delete unused workers mixin (#5654)
Due to 0811da9014
2021-03-09 15:26:21 +01:00
Julien Fontanet e246c19eb3 feat(xen-api/Ref): introduce new utils to manipulate refs (#5650)
Fixes xoa-support#3463

See xapi-project/xen-api#4338
2021-03-09 14:59:32 +01:00
badrAZ d282d8dd52 fix(@xen-orchestra/backups): missing targets no longer prevent runs (#5651)
Fixes #5353
2021-03-09 14:37:52 +01:00
badrAZ 9601ad13ee fix(xo-web/proxies): fix "invalid parameters" error on canceling proxy deploy (#5649)
Issue: fetchProxyUpgrades called with an undefined proxy in the proxies collection.

Solution: Interrupt the deployment process on cancel, in order to not fetch updates in this case.
2021-03-09 10:37:59 +01:00
badrAZ b7603e109d feat(xo-web/backup/new): ability to force full backup per schedule in case of CR (#5648)
Fixes #5541
2021-03-09 09:38:56 +01:00
Julien Fontanet 066f54906b chore: format with Prettier 2021-03-08 17:41:10 +01:00
Julien Fontanet ea0aa9df70 chore(xen-api): disable problematic ESLint rules on specific lines 2021-03-08 14:23:57 +01:00
badrAZ 0811da9014 feat(xo-server): use @xen-orchestra/backups lib to run VM backups (#5642) 2021-03-08 14:05:41 +01:00
Julien Fontanet d601290c46 fix(destroy VM): try harder to destroy VDIs (#5645)
Should fix #4926

Work-around XCP-ng/XenServer unmount from control-domain delay, especially with iSCSI SRs.

This issue impacts a lot XO backups which create snapshots, export them and delete them.
2021-03-08 09:46:51 +01:00
badrAZ 64357aff55 fix(@xen-orchestra/xapi): fix full VM backup imported as a template (#5646) 2021-03-05 17:41:50 +01:00
badrAZ a20a3311b5 fix(xo-server/backup-ng): fix "xapi._assertHealthyVdiChains is not a function" error (#5647)
Introduced by 4c27562650
2021-03-05 17:33:24 +01:00
Julien Fontanet ffce5d4bb5 chore(@xen-orchestra/xapi): make xen-api a peer dep 2021-03-05 16:17:02 +01:00
badrAZ cbfadc019a fix(@xen-orchestra/backups): fix "asyncMapSettled is not a function" error (#5643) 2021-03-05 12:23:25 +01:00
Julien Fontanet bf5427f3e8 feat(@xen-orchestra/proxy): 0.11.4 2021-03-05 11:39:06 +01:00
badrAZ 4c27562650 fix(xo-server/xapi): dont override @xen-orchestra/xapi#_assertHealthyVdiChain (#5641) 2021-03-05 11:38:49 +01:00
badrAZ e8d20532ba feat(xo-server): use @xen-orchestra/backups lib to run metadata backups (#5616) 2021-03-05 10:51:00 +01:00
Mathieu d928157569 fix(xo-web/vm/tab-network): an error has occurred when trying to sort empty network (#5639)
This issue happens when you have an ACL role on one VM, but you don't have an ACL role on the network of this VM.
2021-03-05 09:37:40 +01:00
Mathieu 872b05a7de feat(xo-server/VIF): set MAC address requires Admin ACL on network (#5631)
Fixes #4700
2021-03-05 09:27:22 +01:00
Julien Fontanet 6ea71ec6a2 chore(xapi/VM_destroy): add new lines 2021-03-04 16:11:08 +01:00
Julien Fontanet 139cb72209 chore(xapi/VM_destroy): use VM_getDisks 2021-03-04 16:11:08 +01:00
Julien Fontanet 855a15e696 fix(xapi/VM_getDisks): sync iteration 2021-03-04 16:11:08 +01:00
Mathieu eeebd3fc1b fix(xo-web/DropdownButton): add required id prop (#5628)
See https://react-bootstrap.netlify.app/components/dropdowns/#dropdown-button-props
2021-03-04 15:56:01 +01:00
Julien Fontanet a4b209c654 fix(disposable/deduped): race condition when disposed during acquisition
Introduced in 43aad3d11
2021-03-04 10:46:03 +01:00
Julien Fontanet 43aad3d117 feat(disposable/deduped): works with sync factories 2021-03-03 17:43:39 +01:00
Mathieu f2d4fdd4d2 fix(xo-web/editable/number): throw error if onChange fails (#5634) 2021-03-03 16:33:41 +01:00
Julien Fontanet a630106d80 feat(@xen-orchestra/backups): 0.6.1 2021-03-03 12:05:33 +01:00
Julien Fontanet c7acd455c5 feat(@xen-orchestra/async-map): 0.1.2 2021-03-03 12:05:05 +01:00
Julien Fontanet 555a9d4883 fix(async-map/asyncMapSettled): issue when latest promise rejects 2021-03-03 11:58:51 +01:00
Julien Fontanet ec4ce0c70c fix(async-map/test): missing await 2021-03-03 11:57:51 +01:00
Julien Fontanet edf275badc fix(backups/RemoteAdapter#readDeltaVmBackup): new asyncMapSettled does not support plain objects
Introduced by 20377e9c56
2021-03-03 11:49:21 +01:00
Julien Fontanet 2e91285f02 feat(xo-web/debug): similar display for success and result 2021-03-03 10:06:36 +01:00
Julien Fontanet ec69ba7e0e feat(xo-web/debug): display API call result 2021-03-03 10:06:03 +01:00
Julien Fontanet 3804ca18cb feat(@xen-orchestra/proxy): 0.11.3 2021-03-03 09:19:14 +01:00
Julien Fontanet 9ea3222da8 feat(@xen-orchestra/xapi): 0.4.3 2021-03-03 09:18:58 +01:00
Julien Fontanet df48524ca5 feat(@xen-orchestra/async-map): 0.1.1 2021-03-03 09:17:08 +01:00
Julien Fontanet b3aff1162c feat(@xen-orchestra/proxy): 0.11.2 2021-03-03 08:58:42 +01:00
Julien Fontanet 891ca8a31b feat(@xen-orchestra/xapi): 0.4.2 2021-03-03 08:58:30 +01:00
Julien Fontanet ba99ac8b17 fix(package.json): support non-transpiled @xen-orchestra/* and xo-* 2021-03-02 16:53:02 +01:00
badrAZ 1ff25943dc fix(xo-server): enable async_hooks support in Bluebird (#5635)
Necessary for `@xen-orchestra/backups`.
2021-03-02 13:22:47 +01:00
Julien Fontanet deb58e40d5 chore(xo-server/bin): format with Prettier 2021-03-02 11:39:42 +01:00
Julien Fontanet eab6eb8fab chore(xen-api): event-to-promise → promise-toolbox/fromEvent 2021-03-02 10:20:38 +01:00
Julien Fontanet ff65367851 chore(async-map): add basic tests 2021-03-01 17:25:08 +01:00
Julien Fontanet f16e29c63e fix(async-map/asyncMapSettled): fix hasError condition 2021-03-01 17:22:05 +01:00
Julien Fontanet cdfeb094b3 chore(async-map/package.json): remove unused browserslist 2021-03-01 17:01:48 +01:00
Julien Fontanet b63c5d2987 chore: dont import @xen-orchestra/log/dist 2021-03-01 17:00:42 +01:00
Julien Fontanet 015309c882 chore(backups-cli): use @xen-orchestra/async-map 2021-03-01 16:55:06 +01:00
Julien Fontanet 20377e9c56 feat(async-map): new implementations
These implementations are no longer compatible with plain objects but support iterables.

The previous implementation is still available as `@xen-orchestra/async-map/legacy`.
2021-03-01 16:55:06 +01:00
Mathieu 08857a6198 fix(xo-server): fix asyncMap is not defined (#5632)
Introduced by 57612ee
2021-03-01 16:54:53 +01:00
badrAZ d9ce1b3a97 feat(xo-server#importVmBackupNg): use @xen-orchestra/backups lib (#5630) 2021-03-01 13:36:23 +01:00
Julien Fontanet d166073b16 chore(xo-server/package.json): fix deps sorting
Introduced by 624f32826

Sorting values is different than sorting JSON text.
2021-03-01 09:48:13 +01:00
Julien Fontanet f858c196f4 chore: rename asyncMap → asyncMapSettled
To express more clearly this function's behavior.
2021-03-01 09:45:56 +01:00
Julien Fontanet 57612eeced feat(async-map): remove build step 2021-02-28 23:32:23 +01:00
Julien Fontanet be2257153c feat(proxy-cli): clearer call headers 2021-02-26 17:50:47 +01:00
Julien Fontanet d920a97f4f feat(proxy-cli): supports nested sequences 2021-02-26 17:23:49 +01:00
Julien Fontanet 322f2a1728 chore(xo-server/runJob): group runningJobs logic 2021-02-26 16:52:43 +01:00
Julien Fontanet cfe6b0d9ab fix(xo-server/runJob): emit job:terminated and forward error
Introduced in fd560c351
2021-02-26 16:52:43 +01:00
Pierre Donias e229deb238 feat: release 5.56.0 (#5629) 2021-02-26 16:50:00 +01:00
Julien Fontanet 8cdde947bc feat(@xen-orchestra/proxy): 0.11.1 2021-02-26 16:07:47 +01:00
Julien Fontanet c1b3ddf87a fix(proxy): add missing peerdep xen-api 2021-02-26 16:07:47 +01:00
Pierre Donias 27d97add1e feat: technical release (#5627) 2021-02-26 16:07:15 +01:00
Mathieu 3783724c40 fix(xo-web/task): items-per-page dropdown position (#5584) 2021-02-26 15:21:45 +01:00
Julien Fontanet 67bc4ffe68 feat(@xen-orchestra/proxy): 0.11.0 2021-02-26 15:15:05 +01:00
Julien Fontanet 453bbfbbde feat(@xen-orchestra/backups): 0.6.0 2021-02-26 15:11:35 +01:00
Julien Fontanet ff463c4261 chore(proxy-cli): mutualize request options 2021-02-26 15:10:42 +01:00
Damien Thenot 748b77ae7a fix(docs/advanced): typo telemtry → telemetry (#5625) 2021-02-26 14:57:11 +01:00
Rajaa.BARHTAOUI 58c1005657 fix(xo-web/migrateVms): explicit main SR (#5615)
See #5577

So that when there's no default SR on the pool and the VM's snapshot has orphan
VDI-snapshots, xo-server knows where to migrate them
2021-02-26 14:01:48 +01:00
Rajaa.BARHTAOUI 9271eb61ac fix(xo-web/vm/advanced): fix 'an error has occurred' (#5604)
Fixes #5592
2021-02-26 13:39:34 +01:00
Rajaa.BARHTAOUI c82cee25a5 fix(xo-web): fix 'mapVdisSrs is assigned a value but never used' error (#5617)
Introduced by 90cafa126f
2021-02-26 13:34:33 +01:00
badrAZ 2e5dfa5845 fix(xo-server#deleteVmBackupNg): pass remote record to getBackupsRemoteAdapter instead of ID (#5624)
Introduced by baa5847949
2021-02-26 12:07:04 +01:00
Julien Fontanet 693c07b927 chore: update app-conf to 0.9.0 2021-02-26 12:02:39 +01:00
Julien Fontanet 71a6f70f46 chore: update promise-toolbox to 0.17.0
Allow using `Disposable.use()`.
2021-02-26 12:02:39 +01:00
badrAZ 2952b5a7ec feat(xo-server#deleteVmBackupNg): use @xen-orchestra/backups lib (#5623) 2021-02-26 11:40:28 +01:00
badrAZ baa5847949 feat(xo-server#_listVmBackupsOnRemote): use @xen-orchestra/backups lib (#5622) 2021-02-26 11:17:45 +01:00
Rajaa.BARHTAOUI b9ce0bd99d fix(xo-web): fix 'mapValues is defined but never used' error (#5618)
Introduced by 062fb3ba30
2021-02-26 10:11:04 +01:00
Julien Fontanet aac61d8120 chore: update golike-defer to 0.5.1 2021-02-25 18:41:11 +01:00
Julien Fontanet 1f6edfdbcc fix(xo-server/runJob): upgrade defer to fix import
Introduced by fd560c351
2021-02-25 18:40:55 +01:00
Mathieu 9d1ce7fadf fix(backups/importDeltaVm): restore the bios_strings (#5598)
Aligned with XAPI behavior for XVA exports/imports.
2021-02-25 17:26:43 +01:00
Julien Fontanet fd560c351f fix(xo-server/runJob): register job as soon as job.start (#5620) 2021-02-25 17:00:07 +01:00
badrAZ b45556062d fix(@xen-orchestra/backups): don't double JSON config (#5621)
Config returned by `Xo#exportConfig` is already a string, it must not be JSON encoded again.
2021-02-25 16:49:45 +01:00
badrAZ 5be45599ed fix(xo-server/metadata-backup): XO config not restored (#5619)
Introduced by 61c3057060

`log.taskId` cannot be compared with the `rootTaskId` because it's generated by the Task lib and the `rootTaskId` is generated by the `xo-server` logger.
2021-02-25 16:41:39 +01:00
Julien Fontanet 9b2533dbc9 chore(yarn.lock): update 2021-02-25 14:43:16 +01:00
Julien Fontanet ec1a4b1974 fix(proxy/backup.run): bind getConnectedRecord
Introduced in 4eb9aa9cc
2021-02-25 11:19:20 +01:00
Julien Fontanet bb9fde17c9 chore(xo-server/_backupVm): update todo list 2021-02-25 11:03:54 +01:00
Rajaa.BARHTAOUI 8cb524080c fix(xo-server#_migrateVmWithStorageMotion): don't migrate VM VDIs to default SR (#5577)
See xoa-support#3248
See xoa-support#3355
2021-02-25 10:35:14 +01:00
badrAZ 171ec54781 feat(xo-server#restoreMetadataBackup): use @xen-orchestra/backups lib (#5611) 2021-02-25 09:43:15 +01:00
Julien Fontanet 5d9503b78c feat(backups/Backup): getAdapter accepts ids instead of remotes
This should make it easier to interface with xo-server.
2021-02-24 17:33:26 +01:00
Julien Fontanet f56cb69c2e chore(backups/Backup): remove unused property 2021-02-24 17:30:43 +01:00
Julien Fontanet 4eb9aa9ccb feat(backups/Backup): pass directly getConnectedRecord (#5614)
This should make it easier to interface with xo-server.
2021-02-24 17:25:46 +01:00
Pierre Donias 11801f306c feat: technical release (#5613) 2021-02-24 15:54:37 +01:00
badrAZ 95c2944f30 feat(xo-server#deleteMetadataBackup): use @xen-orchestra/backups lib (#5610) 2021-02-24 11:38:27 +01:00
badrAZ 5bd4c54ab6 feat(xo-server#_listXoMetadataBackups): use @xen-orchestra/backups lib (#5609) 2021-02-24 10:16:27 +01:00
Julien Fontanet 95d6d0a0fe chore(backups/formatVmBackup): ensure function is nammed 2021-02-24 10:08:59 +01:00
Julien Fontanet 7941be083a chore(backups): rename task.js → Task.js
To be in line with other modules in this lib.
2021-02-24 10:07:36 +01:00
badrAZ e36efaec08 feat(xo-server#_listPoolMetadataBackups): use @xen-orchestra/backups lib (#5607) 2021-02-24 10:02:57 +01:00
Julien Fontanet 637afdb540 feat(@vates/toggle-scripts): 1.0.0 2021-02-24 08:55:38 +01:00
Julien Fontanet dafdedef9a feat(toggle-scripts): supports npm < 7 2021-02-24 08:54:29 +01:00
Julien Fontanet ce17ee2ae6 fix(toggle-scripts/package.json): fix files entry 2021-02-24 08:48:33 +01:00
Julien Fontanet e74daa97d2 fix(toggle-scripts): fix usage 2021-02-23 21:54:31 +01:00
Julien Fontanet 44d64d1b80 fix(proxy): dont run systemd-service-installer in dev
See ronivay/XenOrchestraInstallerUpdater#62
2021-02-23 21:37:26 +01:00
Julien Fontanet 1a4731aa83 feat(@vates/toggle-scripts): 0.1.0 2021-02-23 21:32:58 +01:00
Julien Fontanet a75e1c52b7 feat(toggle-scripts): CLI to enable/disable package.json scripts 2021-02-23 21:28:23 +01:00
Julien Fontanet 1b97cb263c feat(proxy/config): resourceDebouce → resourceCacheDelay
Similar to xo-server.
2021-02-23 19:54:20 +01:00
badrAZ 5c9a47b6b7 feat(xo-server#fetchBackupNgPartitionFiles): use @xen-orchestra/backups lib (#5606) 2021-02-23 17:48:11 +01:00
badrAZ 8a5fe86193 feat(xo-server#listBackupNgPartitionFiles): use @xen-orchestra/backups lib (#5605) 2021-02-23 17:40:02 +01:00
badrAZ d9531e24a3 feat(xo-server/listBackupNgDiskPartitions): use @xen-orchestra/backups lib (#5599) 2021-02-23 17:34:55 +01:00
Julien Fontanet 624f328269 chore(xo-server/package.json): sort deps 2021-02-23 16:29:46 +01:00
badrAZ a6f4e6771d fix(xo-server/package.json): missing dependency (#5603)
Introduced by a958fe86d7

Used in https://github.com/vatesfr/xen-orchestra/blob/a506c21b80432542b2a8665e023f8ad8d58a4b0f/%40xen-orchestra/backups/RemoteAdapter.js#L14
2021-02-23 15:34:31 +01:00
Julien Fontanet a506c21b80 feat(docs/installation): XO now requires Node >=14.5 2021-02-23 15:26:21 +01:00
Julien Fontanet 981193ed23 feat(docs/from the sources): XO now requires Node >=14.5 2021-02-23 15:12:42 +01:00
Julien Fontanet 85a6204db2 feat(@xen-orchestra/backups-cli): 0.4.0 2021-02-23 14:41:47 +01:00
Julien Fontanet b82aba1181 chore(backups-cli): add usage to README 2021-02-23 14:40:15 +01:00
Julien Fontanet 0a6dea2c79 feat(backups-cli/clean-vms): better usage 2021-02-23 14:32:16 +01:00
Julien Fontanet 69b6d75927 feat(CHANGELOG.unreleased): release backups 2021-02-23 12:35:04 +01:00
Julien Fontanet eff2d48cc5 feat(backups/RemoteAdapter#outputStream): make path first param
Similar to `fs/Abstract#outputStream()`.
2021-02-23 12:34:26 +01:00
Julien Fontanet ca5af2505c fix(fs/outputStream): always make path first param
Introduced by 7a1377119
2021-02-23 11:47:19 +01:00
a958fe86d7 feat(proxy): version 1 (#4495)
Co-authored-by: badrAZ <azizbibadr@gmail.com>
Co-authored-by: Mathieu <70369997+MathieuRA@users.noreply.github.com>
2021-02-23 08:58:10 +01:00
Julien Fontanet 3ed488e10f chore(compose): regenerate README 2021-02-22 15:09:23 +01:00
Julien Fontanet dcc11f16b1 feat(@vates/compose): 2.0.0 2021-02-22 14:42:45 +01:00
Julien Fontanet 209706b70d feat(compose): forwards this to all functions 2021-02-22 14:42:18 +01:00
badrAZ 1bc80eb485 fix(package.json#moduleNameMapper): fix tests for non-transpiled @vates/ packages (#5593) 2021-02-19 16:34:14 +01:00
badrAZ 9ab9e3fe46 feat(vates/disposable): utilities for disposables (#5590) 2021-02-19 16:22:41 +01:00
Mathieu d654c096ed feat(xo-web/menu): xoa.check sync between menu and support page (#5534) 2021-02-19 10:21:52 +01:00
Olivier Lambert f5d5884988 feat(docs/advanced): add a section about terraform provider (#5589) 2021-02-19 09:22:05 +01:00
Julien Fontanet 2c016204bf feat(@vates/compose): 1.2.0 2021-02-18 17:03:17 +01:00
Julien Fontanet 04fd625bde feat(compose): this and args passed to first function 2021-02-18 17:03:17 +01:00
Mathieu 8455d4a49f fix(xo-web/select): wrapping text if label is too long (#5580)
See https://xcp-ng.org/forum/topic/4072/create-vm-network-names-too-large
2021-02-18 16:51:52 +01:00
Yannick Achyandyannick Achy a3960bb7c5 feat(docs/full backup): document offline backup (#5582)
Co-authored-by: yannick Achy <yannick.achy@vates.fr>
2021-02-18 15:15:21 +01:00
Mathieu 769262d60e fix(changelog): add # to PR reference (#5585) 2021-02-18 14:49:14 +01:00
Julien Fontanet 942567586f feat(@vates/compose): 1.1.1 2021-02-18 11:29:10 +01:00
Julien Fontanet ba6baaec0a fix(compose): update README 2021-02-18 11:27:24 +01:00
Julien Fontanet a8ac6fc738 fix(compose): require Node 7.6 2021-02-18 11:26:00 +01:00
Julien Fontanet b027d3b1d6 feat(@vates/compose): 1.1.0 2021-02-18 11:25:33 +01:00
Julien Fontanet 71f9d268c9 feat(compose): async functions support 2021-02-18 11:25:14 +01:00
Julien Fontanet 2b91d4af99 feat(compose): right to left support 2021-02-18 11:25:14 +01:00
Julien Fontanet 0ec0e286ba feat(compose/README): document functions in an array 2021-02-18 11:25:14 +01:00
Rajaa.BARHTAOUI 258ae64568 fix(xo-web/home/vm): bulk intra pool migration: fix map VDI -> SR (#5578)
See xoa-support#3355
See xoa-support#3248
2021-02-18 11:04:47 +01:00
Rajaa.BARHTAOUI 90cafa126f feat(xo-web/migrateVm): show error when no main SR selected (#5568)
See xoa-support#3355
2021-02-18 10:57:00 +01:00
Julien Fontanet 43d31e285c feat(@vates/compose): 1.0.0 2021-02-18 10:40:27 +01:00
Julien Fontanet 57945e6751 feat(compose): new lib to compose functions 2021-02-18 10:39:57 +01:00
Rajaa.BARHTAOUI fce56cbf4c fix(xo-server/utils/parseXml): keep all values as strings (#5581)
Fixes #5497

All values must be kept as strings because that's what the previous implementation used to do.

Introduced by https://github.com/vatesfr/xen-orchestra/commit/525369e0ceeb6988bd169e4580c450d6b392a31c

See https://github.com/vatesfr/xen-orchestra/issues/5497#issuecomment-780314187

```
{
  'iscsi-target': {
    LUN: {
      vendor: 'TrueNAS',
      serial: '9eaa394581f3003',
      LUNid: 55,
      size: 10995116277760,
      SCSIid: '36589cfc000000581d40d6d5140d9b9da'
    }
  }
}
```
2021-02-18 09:46:17 +01:00
Julien Fontanet 7a13771198 fix(fs/outputStream): make path the first param
From #5373
2021-02-17 17:11:55 +01:00
Julien Fontanet 819c798e99 chore: format mardown files with Prettier 2021-02-17 16:04:22 +01:00
Julien Fontanet 8560ca0661 chore(vhd-lib/Vhd#_getBatEntry): name param blockId
Because it's not a full block but an identifier.
2021-02-17 14:39:02 +01:00
Julien Fontanet 82cdfe7014 chore(vhd-lib): fix a test
From #5481
2021-02-17 14:30:40 +01:00
Julien Fontanet 52642f5854 chore(vhd-lib): move tests into src
From #5481

Fix Jest module mapping.
2021-02-17 14:29:40 +01:00
Julien Fontanet 6c6f9f5a44 feat(backups-cli/clean-vms): rename force flag to remove 2021-02-17 14:01:14 +01:00
Julien Fontanet 039ce15253 chore(xo-server/backups-ng): use invalidParameter.is() 2021-02-17 14:01:14 +01:00
badrAZ 695a4c785c feat(xo-server/backups-ng): handle proxy VM restoration logs (#5576) 2021-02-17 11:03:52 +01:00
Rajaa.BARHTAOUI 7d7f160159 fix(xo-web/migrateVm): don't automatically select migration network (#5564)
See xoa-support#3355
2021-02-17 10:06:03 +01:00
Julien Fontanet b454b4dff1 feat(xo-server/backups): add proxy id to logs 2021-02-17 09:53:00 +01:00
yannick Achy fbc99c1ca9 Add_backup_without_snapshot 2021-02-17 09:21:00 +01:00
Nicolas Raynaud e5d711dd28 fix(fs/S3Handler#_write): work when file doesn't exist (#5561) 2021-02-16 13:45:01 +01:00
badrAZ 10b127ca55 feat(xo-web/backup): ability to force full backup per schedule (#5546)
Fixes #5541
2021-02-16 11:31:17 +01:00
Julien Fontanet fb4dff4fca chore(xo-cli/USAGE): clearer JSON param explanation 2021-02-16 10:52:22 +01:00
badrAZ ef25b364ec fix(xo-server/metadata-backups): fix interrupted status on backup running (#5573)
Introduced by 8a3ae59f77
2021-02-15 14:31:01 +01:00
Nicolas Raynaud 9394db986d fix(import/disk): allow uppercase extensions (#5574)
See https://xcp-ng.org/forum/topic/4216/cannot-import-a-large-vhd-using-import-disk-option
2021-02-15 12:05:49 +01:00
Rajaa.BARHTAOUI 9226c6cac1 fix(xo-server/api): don't log host.stats errors (#5553)
See xoa-support#3323

This avoids flooding the logs with ECONNREFUSED errors when the host's toolstack
is restarted
2021-02-12 11:29:16 +01:00
Julien Fontanet 283193e992 feat(complex-matcher): 0.7.0 2021-02-11 13:54:29 +01:00
Julien Fontanet 72f8a6d220 chore(complex-matcher): add test for non-ASCII raw strings
Related to f5e4fb49c
2021-02-11 13:53:54 +01:00
Albin Hedman f5e4fb49c3 feat(complex-matcher): allow most letters to be unquoted (#5555) 2021-02-11 11:14:44 +01:00
Olivier Lambert 3cd15c783c fix(docs): update the deploy script to fix an issue (#5565) 2021-02-11 10:17:42 +01:00
badrAZ bf51ba860a fix(xo-server, xen-api): clear XO cache on event fetch failure (#5526)
Fixes #5475
2021-02-10 16:17:46 +01:00
Mathieu 6aa8515df4 feat(xo-web/restore): allow all licenses to restore backups (#5547)
See xcp-ng.org/forum/topic/4165/crashed-xoa-can-t-boot-a-clean-xoa-and-use-restore-because-of-registration/7
2021-02-10 15:53:29 +01:00
Julien Fontanet 3bf4ee35a1 fix(xo-server/Xapi#_disconnectVbd): dont swallow unhandled error
Detected while working on #5543
2021-02-09 14:47:55 +01:00
badrAZ e08c600740 fix(xo-server/xapi): handle VM/VDI export stream close (#5538) 2021-02-09 14:24:35 +01:00
badrAZ f823690b44 feat(xo-common,xo-server,xo-web/proxy upgrade): confirm before interrupting backup job (#5533) 2021-02-05 18:11:09 +01:00
Pierre Donias 350b0c1e3c feat: release 5.55.1 (#5551) 2021-02-05 16:13:32 +01:00
Pierre Donias b01a6124a9 feat: technical release (#5550) 2021-02-05 15:46:04 +01:00
Rajaa.BARHTAOUI b00652f9eb fix(xo-server#_migrateVmWithStorageMotion): fix VIF_NOT_IN_MAP error (#5544) 2021-02-04 17:17:24 +01:00
Mathieu 19159a203a feat(xo-web/task): display age and estimated duration (#5530)
See https://xcp-ng.org/forum/topic/4083/task-list-enhancement
2021-02-04 15:07:48 +01:00
Pierre Donias be8c77af5a fix(xo-server-auth-ldap/synchronizeGroups): fix adding users to groups (#5545)
Fixes xoa-support#3333
Introduced by 8cfaabedeb

`synchronizeGroups` (called without a user) tries to find XO users that belong
to LDAP groups and add them to those groups. In order to find those users, it
was using the `userIdAttribute` attribute instead of the
`membersMapping.userAttribute` attribute from the configuration.
2021-02-04 11:45:59 +01:00
MathieuandJon Sands 8bb7803d23 feat(docs): migration to new XOA (#5542)
Co-authored-by: Jon Sands <fohdeesha@gmail.com>
2021-02-04 09:41:17 +01:00
Julien Fontanet 54a85a8dd0 fix(xo-server/utils/parseXml): fix buffer support
Fixes #5539

Introduced by 525369e0c
2021-01-30 10:51:18 +01:00
Julien Fontanet 6fd40c0a7c chore(xo-server/utils/parseXml): add basic test 2021-01-30 10:50:59 +01:00
Rajaa.BARHTAOUI 97dd423486 feat: release 5.55.0 (#5537) 2021-01-29 15:05:21 +01:00
Rajaa.BARHTAOUI 281d60df4f feat: technical release (#5531) 2021-01-27 16:44:25 +01:00
badrAZ 43933f4089 fix(xo-server/metadata-backups): ensure cache reset at the end (#5529)
Introduced by 61c3057060
2021-01-27 14:41:15 +01:00
badrAZ 4f7e140737 feat(xo-web/proxies): better upgrade feedback (#5525)
- display up-to-date message instead of upgrade button
- add "force upgrade" button to the advanced actions
2021-01-27 11:05:33 +01:00
badrAZ 2b6945a382 feat(xo-server/metadata-backups): delete proxy backups (#5520) 2021-01-27 09:54:09 +01:00
badrAZ 8a3ae59f77 feat(xo-server/metadata-backups): restore proxy backup (#5519) 2021-01-27 08:57:02 +01:00
Mathieu db253875cc feat(xo-server,xo-web/vm): expose VM UEFI secure boot option (#5527)
Fixes #5502
2021-01-26 17:08:21 +01:00
Jerome Charaoui a8359dcb75 feat(docs/backups): modifier tags 2021-01-26 16:43:43 +01:00
Julien Fontanet e5dac06d91 feat(xo-server): add x-forwarded headers on proxied requests 2021-01-26 10:34:32 +01:00
Rajaa.BARHTAOUI e9f82558ed feat(xo-web/vm/console): ability to open RDP session (#5523)
Fixes #5495
See xoa-support#3254
2021-01-25 16:14:20 +01:00
badrAZ 26f5ef5e31 feat(xo-server/metadata-backups): list proxy backups (#5517) 2021-01-23 12:42:55 +01:00
Rajaa.BARHTAOUI 874e889b36 fix(xo-web/dashboard/health): filter out snapshots from "duplicated MAC addresses" table (#5524)
See https://github.com/vatesfr/xen-orchestra/commit/fb3f2d46fa136fd68d0d1b362ba98b3edc967fcf#commitcomment-46167022
2021-01-22 16:06:57 +01:00
badrAZ bece5f7083 feat(xo-server, xo-web/metadata-backup): ability to define a proxy for the backup (#4206) 2021-01-21 13:27:33 +01:00
Rajaa.BARHTAOUI 2f535e6db1 fix(xo-web): SR_NOT_ATTACHED when migration network is selected (#5516)
See xoa-support#3248
Introduced by 062fb3ba30 and 4dd7d86ea8

- Issue:  
  When choosing a network for VM migration within a pool: 
    - default SR is shared: the VMs' VDIs will be migrated to this SR
    - if not: `SR_NOT_ATTACHED` error will be thrown.
- Fix: when the migration network is defined, the SR will be required.
2021-01-21 12:07:42 +01:00
badrAZ 61c3057060 feat(xo-server/metadata-backups): run backups through proxy (#5499) 2021-01-21 12:04:30 +01:00
badrAZ 063d7d5cc4 fix(xo-web/backup/overview): fix proxy item not updated on ID change (#5522) 2021-01-21 10:55:35 +01:00
Rajaa.BARHTAOUI 0e0211050b feat(xo-server,xo-web/pool): ability to set default migration network (#5465)
See xoa-support#3118
See https://github.com/vatesfr/xen-orchestra/issues/3788#issuecomment-743207834
2021-01-21 09:44:09 +01:00
Rajaa.BARHTAOUI c8c7245da1 fix(xo-web/home/SR): sort SR usage in % (#5513)
Fixes #5463
2021-01-20 16:53:59 +01:00
Julien Fontanet 3e27e50bab feat(xo-server/utils/parseXml): silent validation
Related to #5497

Error is longed ATM to avoid breaking existing code, but will be thrown in the future.
2021-01-20 12:03:03 +01:00
badrAZ 6b9d3ed60e fix(xo-server/remotes): update remote error on test (#5514)
See xoa-support#3255
2021-01-20 08:37:51 +01:00
Pierre Donias 11a78111de fix(xo-web/home,xo-server): fix ghost missing patch on XCP-ng (#5509)
Fixes #4922
Fixes xoa-support#3216

- xo-server: get error message from updater.py plugin's message and throw it
- xo-web: when counting missing patches, ignore hosts that failed
2021-01-19 10:12:59 +01:00
Mathieu 2655421171 fix(xo-web/host/stats): network throughput legend labels (#5483)
See xoa-support#3211
2021-01-15 10:02:10 +01:00
Pierre Donias c6bc2ea485 fix(xo-server,xo-web/reattach SR): multiple fixes (#5488)
Fixes xoa-support#3227
Fixes #4546

- Fix already attached SRs not being displayed and show their names
- Refresh SR list after SR has been reattached
- Properly reattach SR:
   - Introduce SR (already done)
   - Compute device config from form data
   - Create PBDs for each host
   - Plug in PBDs
- Fix SR list key props to fix loading feedback inconsistencies
- Always show form summary once the SR location has been selected
2021-01-14 23:34:31 +01:00
Nicolas Raynaud 289b7a3dbe fix(fs/s3): TimeoutError: Connection timed out after 120000ms (#5397) 2021-01-14 23:23:40 +01:00
badrAZ 70083c6dca fix(xo-server): check remote is enabled even when bound to proxy (#5501) 2021-01-14 17:37:30 +01:00
Julien Fontanet 3e25b92369 chore: update dependencies 2021-01-14 16:57:44 +01:00
Rajaa.BARHTAOUI 806eaaf14b fix(xo-server/vif#set): changing network set locking mode to 'network_default' (#5500) 2021-01-14 16:53:38 +01:00
Mathieu fb3f2d46fa feat(xo-web/dashboard/health): duplicated MAC addresses (#5468)
Fixes #5448
2021-01-14 15:26:54 +01:00
Julien Fontanet 14d06fe754 fix(xo-server/store): dont fail on serializing circular values
See https://github.com/vatesfr/xen-orchestra/pull/5397#discussion_r555170305
2021-01-14 14:59:08 +01:00
Rajaa.BARHTAOUI 752146028b feat(xo-web): assign custom date-time fields (#5473)
Fixes #4730

On pools, hosts, SRs, and VMs
2021-01-14 14:22:07 +01:00
badrAZ 6c6ae30ce5 fix(xo-web/restore/metadata): ignore disabled remotes (#5504) 2021-01-14 09:10:02 +01:00
Nicolas Raynaud b00750bfa3 chore(xo-vmdk-to-vhd): fix integration tests (#5490) 2021-01-09 19:19:34 +01:00
Pierre Donias 55eac005a0 feat(xo-web/XOA/update): add link to channel's changelog (#5494)
See xoa-support#3257
2021-01-08 16:35:47 +01:00
badrAZ 257524de18 fix(xo-server-backup-reports): fix markdown (#5479)
Observed while investigating #3195

This PR:
  - removes extra indent
  - add a line between sections to handle the case when it was before a nested list
2021-01-08 15:26:18 +01:00
Julien Fontanet d4f78056dd feat(xo-lib): 0.10.1 2021-01-08 14:50:06 +01:00
Julien Fontanet 66c054f24b fix(xo-lib): correctly use . as default URL base
Fixes #5489

Introduced by b25adf7f5
2021-01-08 14:50:06 +01:00
Julien Fontanet 711b722118 fix(xo-server-backup-reports/test): don't swallow errors (#5491)
See #5486
2021-01-08 14:24:13 +01:00
Mathieu 26614b5f40 feat(xo-server-web-books): waiting response from server (#5420)
Fixes #4948
2021-01-08 12:12:52 +01:00
Pierre Donias 9240211f3e fix(xo-server config): change restartHostTimeout from 5min to 20min (#5493)
Fixes #5492
2021-01-08 09:37:56 +01:00
badrAZ 67d84d956e chore(xo-server/docs): fix command (#5487) 2021-01-07 11:11:21 +01:00
Julien Fontanet 97b620f98f fix(xo-server): rm xenStore entries after use (#5482)
This should already be done by the deploy scripts but in case it's not, xo-server should do it.
2021-01-06 11:50:36 +01:00
Julien Fontanet 2f5c91a1e1 feat(docs/CR/manual seed): percent encoding 2021-01-06 11:25:24 +01:00
Rajaa.BARHTAOUI 038dad834d fix(xo-server): set VIF locking mode to 'locked' when adding allowed IPs (#5472)
Introduced by #5357
See xoa-support#2929 (last comment)
2021-01-05 09:54:16 +01:00
Rajaa.BARHTAOUI b3cd265955 fix(CHANGELOG.md): fix packages versions (#5478) 2021-01-04 16:23:56 +01:00
Olivier Lambert 2c670bc838 docs(infra mgmt): add maintenance mode explanation (#5480)
Fixes #5477
2021-01-04 16:04:10 +01:00
Julien Fontanet 30c2b8e192 fix(backups-cli clean-vms): document --merge 2021-01-02 23:29:37 +01:00
Julien Fontanet a00d45522b chore(xo-server/utils): remove unused formatXml 2020-12-31 15:57:48 +01:00
Julien Fontanet 525369e0ce chore(xo-server/utils/parseXml): use fast-xml-parser instead of xml2js
It's faster, the API is simpler and it appears to be better maintained.
2020-12-31 10:51:25 +01:00
Julien Fontanet ba413f3e8f feat: release 5.54.0 2020-12-29 15:56:53 +01:00
Julien Fontanet 4afebca77b feat(@xen-orchestra/backups-cli): 0.3.0 2020-12-23 10:43:44 +01:00
Julien Fontanet d2eb92143d feat(backups-cli/clean-vms): split --merge out of --force 2020-12-23 10:43:32 +01:00
Olivier Lambert e01d3c64fe docs(supported hosts): add XCP-ng 8.2 LTS (#5469) 2020-12-18 13:15:15 +01:00
Pierre Donias 9f497c9c2c docs(users): LDAP groups synchronization (#5459)
See #1884
2020-12-18 10:28:57 +01:00
Julien Fontanet 9aae154c4e fix(xo-web/xoa/update): handle installer2 namespace 2020-12-17 14:23:03 +01:00
Pierre Donias 339f012794 feat: technical release (#5464) 2020-12-16 17:53:43 +01:00
Julien Fontanet af500d7b7b fix(yarn.lock): sync 2020-12-16 17:39:43 +01:00
Pierre Donias 16a71b3917 feat(xo-web): set rolling pool updates plan (#5462) 2020-12-16 17:30:08 +01:00
Pierre Donias 7dfa104f65 feat(xo-server,xo-web/user): prevent setting email/pwd of LDAP users (#5460)
See #1884
2020-12-16 15:28:13 +01:00
Julien Fontanet 44a7b1761f fix(xo-server/vm.export): fail instead of waiting when queue is full
Fixes xoa-support#3035

Otherwise the client request may timeout before the transfer starts.
2020-12-15 21:57:02 +01:00
Julien Fontanet 22c8ea255c feat(xo-cli): 0.11.1 2020-12-15 12:54:53 +01:00
Julien Fontanet a1c10828d8 feat(xo-lib): 0.10.0 2020-12-15 12:52:56 +01:00
Julien Fontanet 25d69d1bd7 fix(xo-lib): handle URLs ending with /
Thanks @rushikeshjadhav
2020-12-15 12:51:20 +01:00
Mathieu a84961f8ba feat(xo-server,xo-web/host): maintenance mode (#5421)
ON: disable & evacuate host
OFF: enable host
2020-12-14 17:15:27 +01:00
Mathieu e17b6790b5 fix(xo-web/dashboard): filter out udev SRs (#5453)
Fixes #5423
2020-12-14 17:01:57 +01:00
badrAZ 815aed52d3 fix(xo-web/file-restore): re-initialize partitions' list on backup/disk change (#5454) 2020-12-14 14:48:36 +01:00
Mathieu a03581ccd3 fix(xo-web/host): component not loaded if controller is undefined (#5417) 2020-12-14 14:29:31 +01:00
Mathieu c10f6e6c6a fix(xo-web/host): dont fetch missing patches when host is halted (#5407)
Fixes #5053
See fe7901ca7f
2020-12-14 11:22:34 +01:00
Pierre Donias 18abd0384f feat: rolling pool updates (#5430)
See #5286
2020-12-14 11:08:19 +01:00
Julien Fontanet 4292bdd7b4 feat(xo-server): 5.72.1 2020-12-11 09:56:12 +01:00
Julien Fontanet 1149648399 feat(xo-server): update hashy to 0.10.0 2020-12-11 09:51:59 +01:00
Rajaa.BARHTAOUI b6846eb21d feat: release 5.53.1 (#5449) 2020-12-10 17:04:29 +01:00
Rajaa.BARHTAOUI d19546fcb4 feat: technical release (#5447) 2020-12-10 16:23:41 +01:00
Julien Fontanet 6a1eb198d1 chore(xo-server/docs): better part listing formatting 2020-12-10 16:12:00 +01:00
badrAZ e4757d4345 chore(xo-server/docs): add "partx" on a raw disk (#5446) 2020-12-10 15:52:45 +01:00
Rajaa.BARHTAOUI 3873a59a37 feat(xo-web/{vm,sr}/disks): improve VDI actions tooltips (#5435) 2020-12-10 15:16:33 +01:00
Pierre Donias cf9f6c10d7 feat(xo-server,xo-web/host): set control domain memory (#5437)
Fixes #2218
2020-12-10 15:05:42 +01:00
badrAZ 8bcd9debc2 Chore(xo-server/docs/file-restoration): add tips (#5438) 2020-12-09 11:27:30 +01:00
Pierre Donias 510a159eee fix(xo-web/modal/form): pass onChange and value to form's body component (#5434)
Fixes #4705
2020-12-08 16:46:55 +01:00
Rajaa.BARHTAOUI 062fb3ba30 feat(xo-web/home/vm): ability to choose network for bulk migration within a pool (#5427)
See xoa-support#3118
2020-12-08 16:45:12 +01:00
badrAZ 3bc477d21b fix(xo-server/docs/file-restoration): use sizelimit options (#5433)
When creating a loop device, the `sizelimit` options is necessary to indicate the end of the data to mount, otherwise the following error is thrown when trying to mount multiple parts of the disk:

```
overlapping loop device exists for /tmp/proxy1/vhdi1.
```

As an example, let's take this disk:

```
[ partition 0 | partition 1 | partition 2 ]
```

Mounting *partition 1* without `sizelimit` will mount the whole space starting from *partition 1* up to the end, which prevents *partition 2* from being mounted.

`man losetup`: https://manpages.ubuntu.com/manpages/precise/en/man8/losetup.8.html
2020-12-08 16:24:03 +01:00
Rajaa.BARHTAOUI 79eb2feb2c feat(xo-web/home): sort VMs by disk physical usage (#5418)
See xoa-support#3059
2020-12-08 14:15:15 +01:00
Julien Fontanet 1fa42a5753 chore(xo-server): update hashy to 0.9.0
BREAKING: requires Node >=10.

See https://xcp-ng.org/forum/topic/3107/python3-support
2020-12-08 11:57:35 +01:00
Mathieu 2eaab408dd fix(xo-server/jobs): bug fix when run job manually (#5426) 2020-12-08 10:34:05 +01:00
Nicolas Raynaud f7fd0d9121 fix(upload-ova): compatibility with latest API (#5432) 2020-12-07 11:11:37 +01:00
badrAZ 3b7b776ac4 feat(xo-server/backups-ng): ability to delete VM backups though proxy (#5428) 2020-12-07 11:05:30 +01:00
Rajaa.BARHTAOUI 43abc8440b feat(xo-server,xo-web/new/sr): show serial and ID in LUN selector (#5422)
See xoa-support#3080
2020-12-04 16:55:25 +01:00
Julien Fontanet 37515b5da9 chore(xo-web/common/xo/index.js): fix formatting 2020-12-04 12:10:09 +01:00
Julien Fontanet 2dec327013 chore: update dependencies 2020-12-04 12:09:32 +01:00
Julien Fontanet 8f4dae3134 chore(multi-key-map/README): sync with USAGE 2020-12-03 14:16:13 +01:00
Julien Fontanet a584daa92d chore(emit-async/README): minor improvements/fixes 2020-12-03 14:16:13 +01:00
Julien Fontanet 43431aa9a0 chore(fs/outputStream): remove duplicate await 2020-12-03 14:16:13 +01:00
Mathieu f196d2abec feat(xo-web/plugins): user feedback on successful test (#5409) 2020-12-03 09:10:57 +01:00
Julien Fontanet 4a6724f664 fea: release 5.53.0 (#5416) 2020-11-30 15:39:32 +01:00
Julien Fontanet a960737207 feat: technical release (#5415) 2020-11-30 15:33:14 +01:00
badrAZ da08bd7fff fix(xo-server/backups-ng): invalidate cache in case of proxy backup (#5414) 2020-11-30 15:19:44 +01:00
Julien Fontanet 517430f23d feat(xo-server/vm.set memory{,Max}): better error when DMC disabled and VM running 2020-11-30 14:39:36 +01:00
Julien Fontanet 48e82ac15b feat(xo-server/vm.set memory{,Max}): handle MEMORY_CONSTRAINT_VIOLATION_MAXPIN
Fixes #4978
Fixes #5326
Fixes xoa-support#1187

This error is used when DMC is disabled.
2020-11-30 14:39:36 +01:00
Julien Fontanet eead64ff71 feat(xo-server/authenticateUser): make throttling delay configurable 2020-11-30 12:53:40 +01:00
Rajaa.BARHTAOUI 9ac6db2f4c fix(xo-web/vm/snapshots): missing color on bulk delete (#5410) 2020-11-30 11:59:14 +01:00
Julien Fontanet 92cf6bb887 chore(xo-server/authentication): parseDuration in constructor 2020-11-30 11:23:49 +01:00
Mathieu 1d3978ce2f fix(xo-web/host): unsubscribe missing patches when the props change (#5370) 2020-11-30 11:20:28 +01:00
badrAZ 16c71da487 feat: technical release (#5406) 2020-11-27 16:22:15 +01:00
badrAZ 214dbafd62 fix(xo-server/jobs): don't throw when the job owner doesn't exist (#5405)
Introduced by 31b19725b7
2020-11-27 16:11:48 +01:00
badrAZ 89b162704c feat: technical release (#5404) 2020-11-27 15:15:00 +01:00
Rajaa.BARHTAOUI fbf906d97c feat(xo-web/SortedTable): allow to change the number of items per page (#5355)
See xoa-support#3020
2020-11-27 14:20:33 +01:00
Rajaa.BARHTAOUI 7961ff0785 feat(xo-server, xo-web): expose and edit custom fields (#5387)
See #4730
2020-11-27 13:39:08 +01:00
Pierre Donias 00e53f455b feat(xo-web/Dashboard): make Overview & Health available on all plans (#5401) 2020-11-27 11:10:32 +01:00
Mathieu d1d4839a09 feat(xo-web/trial): end of trial info banner (#5374)
See company#558
2020-11-27 10:37:51 +01:00
Mathieu 31b19725b7 feat(xo-server/jobs): backup job support for webhooks (#5360)
Fixes #5205
2020-11-27 10:15:51 +01:00
badrAZ a776eaf61a feat(xo-server,xo-web): file restore via proxies (#5359) 2020-11-26 17:14:06 +01:00
badrAZ ae2a92d229 feat(xo-server,fs): stricter perms for backup dirs (#5378)
Fixes xoa-support#3088
2020-11-26 11:02:33 +01:00
badrAZ dedc4aa8b9 feat(xo-server/callProxyMethod): support binary response (#5399) 2020-11-25 18:16:20 +01:00
Julien Fontanet 7a8ca2f068 chore: change print width to 120 chars 2020-11-24 10:51:35 +01:00
Nicolas Raynaud fdf52a3d59 feat(OVA/VMDK import): transmit VMDK tables in multipart POST request (#5372)
See xoa-support#3060

The VMDK block tables could become bigger than the max allowed size of a websocket message. The tables are now sent in a multipart POST in the same transaction as the file.
2020-11-23 10:27:35 +01:00
Pierre Donias e0987059d3 fix(xo-server-auth-ldap): typo defaults → default (#5388)
The "Check certificate" option's default value was incorrectly set in the UI. So if it was left untouched by the user (showing as OFF since `undefined`), it would be saved as `undefined`, and then fallback to the actual default value (`true`) when used in the code. So it would try to check the certificate even though the user didn't want to.
2020-11-20 14:10:58 +01:00
Pierre Donias ee7217c7c9 feat(xo-server,xo-web/VIF): set any allowed IP as an admin (#5367)
Fixes #2535
See #1872
See #5358
2020-11-20 10:35:23 +01:00
Pierre Donias 1027659f34 fix(xo-web/backup/restore): refresh button loading feedback (#5381)
See xoa-support#3093
Introduced by 48eeab974c
2020-11-20 10:05:21 +01:00
Albin Hedman 424a212cc3 feat(xo-web/dashboard/health): add 'missing guest tools' section (#5376) 2020-11-18 09:34:12 +01:00
Nicolas Raynaud 949ddbdcd7 feat(new SR): use zfs type when XCP-ng 8.2+ #5302 (#5330) 2020-11-16 15:04:39 +01:00
Rajaa.BARHTAOUI 7fcfc306f9 fix(xo-server/vif.set): don't change locking mode automatically (#5357)
See xoa-support#2929
2020-11-10 15:15:54 +01:00
Rajaa.BARHTAOUI a691e033eb fix(xo-web/pool/network): remove unnecessary braces (#5366) 2020-11-10 09:19:24 +01:00
Rajaa.BARHTAOUI b76f62d470 fix(xo-web): missing key props (#5365) 2020-11-10 09:16:52 +01:00
Julien Fontanet 01a90a1694 feat(xapi-explore-sr): 0.3.0 2020-11-09 12:33:45 +01:00
badrAZ 97bcc7afb6 feat(@vates): add MultiKeyMap (#5362) 2020-11-09 12:30:35 +01:00
Olivier Lambert 9fa0ec440d fix(xapi-explore-sr): replace XenServer by Host (#5363) 2020-11-09 12:19:44 +01:00
Mathieu 28559cde02 feat(xo-web/copyVm): enable intrapool VM copy for everyone (#5333)
Fixes #4890
2020-11-05 14:20:26 +01:00
Rajaa.BARHTAOUI 6970d48cc3 fix(xo-web/home/pool): add missing memory icon (#5356)
See https://xcp-ng.org/forum/topic/3783/missing-icon-on-the-ui
2020-11-05 10:25:40 +01:00
Julien Fontanet 52801c5afc fix(fs/nfs): only use vers=3 if no other options (#5354)
Fixes #4940
2020-11-02 22:21:27 +01:00
Pierre Donias 7797bce814 feat(xo-server,xo-web/groups): prevent edition of LDAP groups (#5351)
See #1884
2020-11-02 16:18:43 +01:00
Rajaa.BARHTAOUI 18762dc624 feat: release 5.52.0 (#5352) 2020-10-30 14:23:00 +01:00
Julien Fontanet 5a828a6465 fix(CHANGELOG): "Packages to release* → *Released packages* 2020-10-30 11:48:53 +01:00
Julien Fontanet eaa9f36478 feat: technical release (#5350) 2020-10-30 10:09:37 +01:00
Julien Fontanet 2b63134bcf feat(xo-web): add API debug mode
Adding `?debug` in URL (as search param), log all API calls in browser console.
2020-10-30 09:34:17 +01:00
Julien Fontanet 8dcff63aea fix(xo-server/{CR,DR}): add tags at VM creation (#5341)
Fixes https://xcp-ng.org/forum/topic/3285/cr-tag-ignored-kind-of-in-smart-backup

Necessary to avoid smart mode from matching the replicated VMs currently being imported.
2020-10-29 17:27:04 +01:00
Pierre Donias c2777607be feat(xo-server-auth-ldap,xo-web): LDAP group manual sync (#5343)
See #1884

When the auth-ldap plugin is configured to synchronize LDAP groups, a group will
only be created in XO when a user that belongs to that group logs into XO. This
commit adds a button that allows an admin to force the synchronization of all
LDAP groups.
This can be useful if an admin wants to configure ACLs for those groups without
having to wait for a user of each group to log into XO at least once.
2020-10-29 17:13:38 +01:00
Julien Fontanet 9ba2b18fdb feat(xo-server/backup): dont backup migrating VMs
Fixes xoa-support#2953
2020-10-29 16:27:38 +01:00
Mathieu 4ebc10db6a fix(xo-web/formatSize): don't throw if the size is undefined (#5348) 2020-10-29 15:52:23 +01:00
Mathieu 610b6c7bb0 feat(xo-server,xo-web/host): get/set scheduler granularity (#5320)
Fixes #5291
2020-10-29 14:58:09 +01:00
Rajaa.BARHTAOUI 357333c4e4 feat: technical release (#5347) 2020-10-28 16:07:21 +01:00
Rajaa.BARHTAOUI 723334a685 feat(xo-web/pool/network): add tooltip for Automatic column (#5345)
See xoa-support#2978
2020-10-28 11:50:49 +01:00
Mathieu b2c218ff83 fix(xo-web/home): error notification when bulk VM snapshot fails (#5323) 2020-10-28 10:55:42 +01:00
badrAZ adabd6966d feat(xo-server, xo-web/host): ability to install a certificate (#5332)
Fixes #5134
2020-10-27 16:36:26 +01:00
Mathieu b3eb1270dd fix(xo-web/user): use default filter when custom filter is unset (#5321) 2020-10-27 15:25:38 +01:00
Mathieu 7659a195d3 fix(xo-web/vm): show snapshot button for self service user (#5324)
Introduced by a88798cc22
2020-10-27 15:17:33 +01:00
Julien Fontanet 8d2e23f4a8 fix(xo-server): remove TLS config to use native settings
See https://xcp-ng.org/forum/topic/3747/xen-orchestra-tls-minimum-version-requirement-how-to-set
2020-10-26 15:54:29 +01:00
Mathieu 539d7dab5d fix(xo-web/backup): add tooltip on running backup job button (#5325)
See https://xcp-ng.org/forum/topic/3687/xo-interface-and-usability/5
2020-10-26 15:22:35 +01:00
Pierre Donias 06d43cdb24 chore(xo-server-auth-ldap): remove unused dependency (#5344) 2020-10-26 09:32:04 +01:00
badrAZandJon Sands af7bcf19ab docs(users): add audit log documentation (#5342)
* docs: audit log
* docs: grammar edit for audit log info
* Fixes #5340

Co-authored-by: Jon Sands <fohdeesha@gmail.com>
2020-10-24 12:53:38 +02:00
Rajaa.BARHTAOUI 7ebeb37881 fix(xo-web#addSshKey): SSH key must be unique (#5329)
Mostly needed by the SortedTable, which uses the key as the item's ID.
2020-10-23 14:30:15 +02:00
Julien Fontanet 4911bbe3a2 chore: normalize packages 2020-10-23 10:21:52 +02:00
Julien Fontanet e0b6ab3f8a feat(value-matcher/README): document patterns 2020-10-23 10:21:52 +02:00
Rajaa.BARHTAOUI 8736c2cf9a feat(xo-server,xo-web/VIF): require network ACLs to change VIF locking mode (#5283)
See xoa-support#2929
2020-10-23 10:18:29 +02:00
Rajaa.BARHTAOUI d825c33b55 feat(xo-server,xo-web/networks): ability to change a VIF's network for self users (#5203)
Fixes #5020
2020-10-23 10:05:03 +02:00
badrAZ 171ecaaf62 feat(xo-server, xo-web/host): display installed certificates (#5319)
See #5134
2020-10-21 14:36:55 +02:00
Julien Fontanet 5e6d5d4eb0 docs(xo-server): file restoration (#5336) 2020-10-20 15:35:16 +02:00
Rajaa.BARHTAOUI 3733a3c335 fix(xo-web): component names must be in PascalCase (#5322) 2020-10-20 15:19:59 +02:00
badrAZ 7fca6defd6 fix(xo-web, xo-server): fix host power state (#5288)
Fixes #4919
2020-10-20 10:01:48 +02:00
Julien Fontanet 2a270b399e fix(xo-server/getRemoteHandler): synchronize to avoid race conds during sync 2020-10-19 22:35:13 +02:00
Julien Fontanet 64109aee05 chore(vhd-lib/Vhd#_createBlock): assert block not already allocated 2020-10-19 22:33:58 +02:00
Julien Fontanet e1d9395128 feat(vhd-lib/Vhd#_createBlock): dont initialize block
It's unnecessary, the block is written right after creation.
2020-10-19 22:30:57 +02:00
Julien Fontanet 32eec95c26 feat(@xen-orchestra/backups-cli): 0.2.1 2020-10-19 17:15:00 +02:00
badrAZ f41cca45aa feat(audit-core, xo-server-audit): ability to delete a range of records (#5277) 2020-10-19 13:09:08 +02:00
Rajaa.BARHTAOUI 48eeab974c feat(xo-web/backup/restore): load backups in parallel (#5278)
See #5176
2020-10-19 11:47:33 +02:00
Pierre Donias eed44156ae feat: release 5.51.1 (#5328) 2020-10-14 16:12:37 +02:00
Pierre Donias 1177d9bdd8 feat: technical release (#5327) 2020-10-14 15:23:00 +02:00
badrAZ d151a94285 feat(xo-server, xo-web/proxy): ability to update http proxy cfg (#5148) 2020-10-14 14:43:33 +02:00
badrAZ a7fe6453ee feat(xo-server#_migrateVmWithStorageMotion): improve migration error (#5306)
Fixes #5282
2020-10-14 13:17:55 +02:00
Rajaa.BARHTAOUI 313eb136f4 fix(xo-web): some methods call throw 'not enough permissions' (#5303)
See #5285
2020-10-13 15:30:06 +02:00
Mathieu 98591ff83d fix(xo-server/deleteResourceSet): detach VMs from resource set (#5312)
Fixes #4797
2020-10-12 11:33:29 +02:00
Mathieu 0b9d78560b feat(xo-web/home): better sort of bulk VM migrate selector (#5308)
Fixes #4462
2020-10-12 10:22:24 +02:00
Rajaa.BARHTAOUI 32a930e598 feat(xo-web/vm/network): remove unused method (#5316)
Introduced by c4d96fbc49
2020-10-12 10:05:57 +02:00
Rajaa.BARHTAOUI edd8512196 feat(xo-web/vm): hide backup tab for non-admin users (#5317)
Fixes #5309
2020-10-12 10:02:08 +02:00
Mathieu 7a6aec34ae fix(xo-web/ips): fix the range formatting (#5314)
Fixes #3170
2020-10-09 17:15:50 +02:00
badrAZ 009a0c5703 feat(xo-web/backup/overview): add link from backup job/schedule to corresponding logs (#5260)
Fixes #4564
2020-10-09 14:54:23 +02:00
badrAZ a99086b6bd chore(xo-web/log-alert-body): remove unused subscription (#5292)
Introduced By 3370014ddf
2020-10-07 15:17:29 +02:00
badrAZ a186672447 feat(xo-web/sorted-table): ability to collapse actions (#5311)
See #5148
2020-10-07 11:13:10 +02:00
badrAZ 0b8a7c0d09 feat(xo-web/backup/new): enable created schedules by default (#5280)
See xoa-support#2921
2020-10-07 10:36:10 +02:00
BenjiReis 1990bf3d7a fix(sdn-controller): use correct bridge address to create tunnels (#5281)
Fixes xoa-support#2919
2020-10-06 23:54:02 +02:00
Julien Fontanet ea74a7e401 fix(backups-cli clean-vms): fix limit-concurrency-decorator import 2020-10-06 18:35:35 +02:00
Nicolas Raynaud bf12c3ff74 fix(xo-server/backup-ng): use getRemoteWithCredentials (#5315)
Introduced in #4907

Fix #5253

Otherwise the handler will be incorrectly defined due to the obfuscation of credentials.
2020-10-06 18:13:27 +02:00
Rajaa.BARHTAOUI 9d261aae76 fix(xo-web/home): hide backup filter for non-admin users (#5287)
See #5285
2020-10-06 16:47:20 +02:00
badrAZ 3d8c8fd745 feat(xo-web/backup-reports): hide merge task when no merge (#5263) 2020-10-06 16:08:12 +02:00
Rajaa.BARHTAOUI 6ad7db522a fix(xo-web/vm/disks): fix "not enough permissions" error (#5299)
Introduced by 1116530a6b
2020-10-06 15:16:27 +02:00
Rajaa.BARHTAOUI 385984b1d8 fix(xo-web/vm/disks): VDI disappears after migration (#5296)
Related to 1116530a6b
2020-10-06 10:38:33 +02:00
Mathieu 4f3d4b06b5 fix(xo-web/user): fix custom filters in default filter select (#5298) 2020-10-02 14:40:17 +02:00
badrAZ 2291986e2c fix(xo-web/new/network): omit bond slave PIFs from selection (#5262)
See xcp-ng.org/forum/topic/3524/old-networks-not-removed-after-creating-bond/8
2020-10-02 14:12:53 +02:00
Nicolas Raynaud fc81cf4d70 fix(xo-web/remotes): fix S3 secret key edit UI (#5305)
Fixes #5233
2020-10-02 11:38:18 +02:00
Pierre Donias fdeab86a87 fix(xo-web/xoa): don't show expired notifications (#5304) 2020-10-01 16:40:27 +02:00
Julien Fontanet 3616b7a67b feat(xo-server/sensitive-values): make obfuscated value obvious 2020-10-01 15:01:21 +02:00
Julien Fontanet 83ea57d825 feat(xo-server/vm.migrate): ensure original error is logged
Fixes https://github.com/vatesfr/xen-orchestra/pull/4364/files#r488539823
2020-10-01 14:52:42 +02:00
Mathieu 24a69bcade feat(xo-server,xo-web/host/advanced): add IOMMU state (#5294)
Fixes #4936
2020-10-01 10:40:10 +02:00
badrAZ 58dc3244be feat: release 5.51.0 (#5295) 2020-09-30 14:19:35 +02:00
badrAZ 61e580b992 feat: technical release (#5293) 2020-09-29 16:40:26 +02:00
Rajaa.BARHTAOUI 1116530a6b feat(xo-web/vm/disks): ability to migrate VDIs to other SRs within resource set (#5201)
See #5020
2020-09-29 16:07:10 +02:00
Pierre Donias 8cfaabedeb feat(xo-server-auth-ldap): import LDAP groups (#5279)
See #1884

When a user logs into XO using LDAP:

- Create a XO user if it doesn't already exist
- Mark it as being provided by LDAP and bind it to the LDAP user with an ID
- If group synchronization is enabled:
  - Fetch all the LDAP groups based on the Base and Filter (plugin config)
  - Create and delete the corresponding XO groups based on the LDAP groups that
    were found
  - Add and remove the XO users from the XO groups based on the LDAP data
2020-09-29 15:35:30 +02:00
Rajaa.BARHTAOUI 66ba05dcd0 feat(xo-web/tasks): display linked objects (#5267)
Fixes #4275
2020-09-29 15:13:56 +02:00
Julien Fontanet d1db616d1e feat(backups-cli/clean-vms): limit VHD merging concurrency to 1 2020-09-29 10:43:48 +02:00
Nicolas Raynaud aed09b152a fix(import/ova): speedup the import of gziped vmdk disks nested in .ova (#5275)
This the followup to #5085

Avoid unzipping the entire file from the beginning before each read.
The test case when from 10min down to 26 seconds.

When reading a block from the gzipped file, we keep the current state in memory, if the next read happens at an offset greater than the previous read, we just carry one decompressing the file until the desired position.

The previous code would decompress from the start of the file for every read operation.
2020-09-28 15:42:55 +02:00
Nicolas Raynaud f755365e23 fix(xo-web/remotes): fix editing bucket and directory for S3 (#5276) 2020-09-28 15:33:06 +02:00
badrAZ ccd34c1610 fix(CHANGELOG): update advanced filter entry (#5290)
Introduced by 45fe70f0fa
2020-09-28 12:12:15 +02:00
badrAZ f9104e6cc9 fix(xo-web/messages): remove unused messages (#5289)
Introduced by 45fe70f0fa
2020-09-28 12:10:21 +02:00
Nicolas Raynaud 4bb702fe89 fix(fs/S3): support 50GB+ files (#5242) 2020-09-27 20:49:41 +02:00
Julien Fontanet 511a04dad5 feat(xo-server-auth-ldap/configuration): add titles and reorder settings 2020-09-27 20:37:00 +02:00
Nicolas Raynaud f3527a44d7 fix(vm/import): make the UI respond instantly to .ova file drop (#5274)
When dropping a file on the import zone, the UI didn't acknowledge the file until the vmdk table were parsed.

Now the UI parses the XML instantly, displays it on the UI, and start parsing the tables in the background. If the user clicks the "import" button, the system will finish parsing the tables and start the upload in when fell swoop. Hiding the parsing time in the upload time.
2020-09-27 19:45:32 +02:00
Julien Fontanet fdbe84cb1e chore(xo-server-test): format with Prettier 2020-09-27 19:42:35 +02:00
badrAZ 45fe70f0fa feat(xo-web/logs/backup-ng): advanced filter (#5208)
See #4406
2020-09-25 16:58:33 +02:00
badrAZ 2aed2fd534 feat(xo-web/logs/backup-ng): log tasks pagination (#5209)
See #4406
2020-09-24 16:36:18 +02:00
Julien Fontanet a523fa9733 feat(@xen-orchestra/backups-cli): 0.2.0 2020-09-24 15:14:07 +02:00
Julien Fontanet 0f42f032e4 feat(backups-cli/info): compute the used space per job 2020-09-24 15:12:38 +02:00
Dom Del Nano 4575b98fd5 fix(xo-server#removeSubjectToResourceSet): rename to removeSubjectFromResourceSet (#5266) 2020-09-21 17:50:55 +02:00
Pierre Donias 3a0cc0d6f6 fix(xo-server/subjects/addToArraySet): dont erase previous values (#5269)
Prior to this change, adding a value to an existing set that already contains
that value would replace the whole set with a new one containing only that
value.
2020-09-21 12:14:50 +02:00
Pierre Donias 626e2fcb12 fix(xo-server/users): serialize properties on user create as well (#5273)
This didn't break anything because we usually don't assign `groups` and/or
`preferences` (which are the only 2 properties that need serialization) on user
creation.

This also prepares a minimal change to add a `authProviders` object property on
users.
2020-09-18 12:11:20 +02:00
Pierre Donias 592feb54b7 fix(xo-server/_authenticateUser): remove broken/unused provider API (#5270) 2020-09-18 10:54:20 +02:00
badrAZ 9c6b63e7e4 feat: release 5.50.3 (#5272) 2020-09-17 16:19:30 +02:00
badrAZ 4364a74b7a feat: technical release (patch) (#5271) 2020-09-17 16:07:58 +02:00
badrAZ 00f13102f8 feat(xo-server-audit): API method to clean DB (#5150) 2020-09-17 15:03:03 +02:00
badrAZ 3f17389871 fix(xo-server-audit): remove unused variable (#5268) 2020-09-17 10:51:09 +02:00
Julien Fontanet 726ba287b1 chore(xo-server-audit/_uploadLastHash): simplify conditions 2020-09-17 10:07:32 +02:00
Julien Fontanet 42ee29cb3c fix(xo-server-audit/_uploadLastHash): dont hide errors 2020-09-17 10:06:28 +02:00
badrAZ 8a98b6b012 feat(xo-server-audit/_uploadLastHash): check integrity sequentially (#5250)
- implementation is simpler
- stop on first error
2020-09-17 09:35:42 +02:00
Julien Fontanet 14ab694804 fix(xo-cli): mkdirp must not be promisified
Introduced by d622f7a65
2020-09-16 15:56:38 +02:00
Nicolas Raynaud 14b8cda543 fix(xo-vmdk-to-vhd/grabTables): read each entry independently (#5255)
Reading all entries at once cause problems on some VMDKs (those generated by VirtualBox) because they appear to be distributed throughout the VMDK thus making the buffer not fit in memory.

See https://xcp-ng.org/forum/topic/3374/cannot-import-ova-from-virtualbox/14?_=1599689219209
2020-09-16 11:46:10 +02:00
Julien Fontanet 4264e34ffd feat(xo-web/createSubscription): support lazy subscribers (#5158)
These subscribers follow the value of the subscription but do not make the
subscription refresh itself.

A lazy subscriber triggers an initial fetch if no value is available.
2020-09-16 10:49:54 +02:00
Pierre Donias bd9bf55e43 feat(xo-web/groups): bulk deletion (#5264) 2020-09-16 10:46:35 +02:00
Albin Hedman 7c802bbd33 feat(xo-web/dashboard/health): add 'too many snapshots' section (#5238) 2020-09-14 10:45:37 +02:00
Julien Fontanet 9e37f3f586 feat(xo-web/new VM): hide missing VDIs
See #5222

Related to 15bc30a2d
2020-09-11 11:11:25 +02:00
Nicolas Raynaud 1d4f5d068a fix(xo-web/VM import): make description optional (#5258) 2020-09-11 08:45:10 +02:00
badrAZ 5be5eb80e8 feat: release 5.50.2 (#5257) 2020-09-10 17:03:26 +02:00
Julien Fontanet 12c774a34a feat(travis-tests): dont stop on first failure on master 2020-09-10 16:42:56 +02:00
badrAZ 14c3fa4378 feat: technical release (patch) (#5256) 2020-09-10 16:36:25 +02:00
badrAZ 2f17420721 feat(xo-web/backup/overview): add link from log to its job (#5202)
See #4564
2020-09-10 16:05:36 +02:00
badrAZ 8d7f8d156f fix(xo-server,xo-web/orphan VDIs): ignore irrelevant VDI types (#5249)
Fixes #5248
2020-09-10 16:00:20 +02:00
Julien Fontanet 38248d8c35 fix(test): auto map @xen-orchestra/*, @vates/* and xo-* 2020-09-10 15:32:08 +02:00
badrAZ edaae02892 fix(xo-web,xo-server#probeIscsiLuns): handle undefined lun size (#5212)
See xoa-support#2815
See https://xcp-ng.org/forum/topic/3409/getting-error-when-trying-to-mount-iscsi-lun
2020-09-09 12:11:50 +02:00
Rajaa.BARHTAOUI 846eff4984 feat(xo-web/vm/networks): improve tooltip messages (#5227)
See https://github.com/vatesfr/xen-orchestra/issues/4713#issuecomment-667655321
2020-09-09 11:59:54 +02:00
badrAZ 481adf3a1e feat(xo-server-audit): don't save last hash when it doesn't change (#5251) 2020-09-08 14:35:19 +02:00
Julien Fontanet d622f7a65c chore: update dependencies 2020-09-07 10:26:51 +02:00
badrAZ a479501aef feat: release 5.50.1 (#5246) 2020-09-04 12:04:55 +02:00
badrAZ 2456374e5a feat: technical release (patch) (#5247) 2020-09-04 11:55:01 +02:00
badrAZ c77016ea44 feat(xo-server-usage-report): ignore replicated VMs (#5241)
Fixes #4778
2020-09-04 11:42:32 +02:00
badrAZ 6fd45a37e2 feat: technical release (patch) (#5245) 2020-09-04 11:16:45 +02:00
badrAZ 9be56d3ab8 fix(xo-server-audit): handle non-existent XOA plugin (#5239)
See https://github.com/vatesfr/xen-orchestra/commit/38de5048bc2f867944546337d4a464ed19eb51a4#commitcomment-41875481
2020-09-04 10:31:46 +02:00
Julien Fontanet 24b264b6c9 fix(xo-server): TX checksumming is enabled by default
Introduced by fe2de9c1154c5a0b183c6d7897f1d9c376fa4031

Fixes #5234
2020-08-28 16:01:26 +02:00
tonyuh 7f9130470b feat(docs/backup_troubleshooting): SR_OPERATION_NOT_SUPPORTED (#5232)
Add SR_OPERATION_NOT_SUPPORTED error troubleshooting.
2020-08-28 11:49:47 +02:00
Julien Fontanet b82aa1daa5 feat: release 5.50 2020-08-27 15:06:49 +02:00
Julien Fontanet 53cb325974 feat: technical release 2020-08-27 14:46:33 +02:00
Julien Fontanet 1256c320e3 feat(xo-web/host/network): button to scan PIFs
Fixes #5230
2020-08-27 11:42:28 +02:00
Julien Fontanet 15bc30a2d5 feat(xo-web/iso-device): hide missing VDIs
Fixes #5222
2020-08-27 11:13:59 +02:00
Julien Fontanet fc3bc8468f feat(xo-server/backup): add proxyId to job log 2020-08-27 10:54:44 +02:00
Julien Fontanet b4e068f630 chore(xo-server/backup executor): proxyId = job.proxy 2020-08-26 16:50:33 +02:00
Pierre Donias 08eef80673 feat(xo-web/orphan VDIs): show VDI(-snapshot)s that don't have VBDs (#5228)
In the Dashboard > Health > Orphan VDIs table, show non-ISO VDIs and
VDI-snapshot that don't have any VBDs.
2020-08-25 09:32:21 +02:00
Pierre Donias 152f73ebf0 feat: technical release (#5226) 2020-08-20 15:15:34 +02:00
badrAZ 38de5048bc feat(xo-server-audit): backup last hash (#5077) 2020-08-20 12:32:22 +02:00
Rajaa.BARHTAOUI c4d96fbc49 feat(xo-web/vm/network): ability to change VIF locking mode (#5188)
See #4713
2020-08-20 09:48:50 +02:00
BenjiReis ff25d402c1 fix(sdn-controller): host.$PIFs can have undefined element (#5217) 2020-08-20 09:25:41 +02:00
Julien Fontanet f957024605 chore(xo-web): use js-cookie instead of cookies-js (#5224)
See #5223

`cookies-js` is no longer maintained.
2020-08-19 17:18:03 +02:00
badrAZ 006e54e2fd feat(xo-web, xo-server/proxy): improve proxy health check errors (#5191)
Fixes #5161
2020-08-19 16:20:05 +02:00
badrAZ 5f7bc58788 fix(xo-server/sensitive-values): obfuscate params containing "password" (#5220)
Fixes #5219
2020-08-19 10:56:40 +02:00
Fabian Untermoser bdd93603aa fix(docs/backups): fix typo (#5225) 2020-08-18 21:46:30 +02:00
Rajaa.BARHTAOUI 8392a17cb2 fix(xo-server/authentication): add missing 'createPredicate' (#5221)
Fixes #5218
Introduced by 9ded2641a7
2020-08-18 16:15:35 +02:00
Julien Fontanet 5f7f0b777e fix(xo-server): use http.cookies config everywhere 2020-08-17 11:06:45 +02:00
Julien Fontanet 3f574606d9 feat(backups-cli/clean-vms): display merge progress 2020-08-17 11:06:45 +02:00
badrAZ 45f0f93895 feat(xo-server,xo-web/VM): ability to set VIF TX checksumming (#5182)
Fixes #5095
See xoa-support#2619
2020-08-14 17:14:48 +02:00
badrAZ af2710135b fix(xo-web/proxies): remove upgrade button style (#5216)
See https://github.com/vatesfr/xen-orchestra/pull/5167/files?file-filters%5B%5D=.md#r469763760

...when the proxy is already up to date
2020-08-13 16:52:29 +02:00
Rajaa.BARHTAOUI 95ed6094fe fix(xo-web/vm/snapshot): fix redirection when copying a VM (#5213)
Introduced by d9211053ce
2020-08-13 11:12:56 +02:00
BenjiReis 6af8ce9eeb feat(sdn-controller): specify tunnel protocol at its creation (#5210) 2020-08-13 11:11:11 +02:00
badrAZ 3ff37f00fe fix(xo-web/deploy-proxy): throw error on trial start failure (#5196)
Introduced by 902953a1fa
2020-08-12 15:11:49 +02:00
Pierre Donias ed5b066cbe fix(CHANGELOG.unreleased): remove sdn-controller package (#5214)
Introduced by cec5593c70
2020-08-12 12:21:18 +02:00
Mark Martin cec5593c70 feat(xo-web/vm): protect from accidental shutdown (#5107)
Fixes #5090
2020-08-12 12:17:30 +02:00
Julien Fontanet 04924884ad feat(@xen-orchestra/backups-cli): 0.1.0 2020-08-11 09:57:01 +02:00
Julien Fontanet 3ccf64fcd3 feat(backups-cli/clean-vms): merge single children 2020-08-11 09:56:25 +02:00
Julien Fontanet 8eb7f9b91c fix(xo-server-sdn-controller): remove deprecated uuid import 2020-08-10 11:15:40 +02:00
Julien Fontanet f25c50c629 chore: update dev deps 2020-08-10 11:15:40 +02:00
Rajaa.BARHTAOUI e524a1b865 feat: release 5.49.1 (#5207) 2020-08-05 14:46:12 +02:00
Rajaa.BARHTAOUI ac15e3355e feat: technical release (#5206)
* feat(xo-server-sdn-controller): 1.0.2

* feat(xo-web): 5.67.0

* chore(CHANGELOG): update next
2020-08-05 13:39:50 +02:00
Julien Fontanet 0930a37819 fix(CHANGELOG.unreleased): add xo-server patch
Due to 2789ead99
2020-08-05 12:33:30 +02:00
Rajaa.BARHTAOUI d62f91a9e6 feat(xo-web/sr/advanced): show thin/thick provisioning for missing SR types (#5204) 2020-08-05 11:15:55 +02:00
Julien Fontanet 2789ead999 fix(xo-server/pool.listMissingPatches): really dont log errors
Previous fix (e1bf68ab3) was incorrect.
2020-08-05 11:10:35 +02:00
BenjiReis f25fd267dd fix(sdn-controller): only admin can create private networks (#5200) 2020-08-04 14:09:33 +02:00
BenjiReis 47999f1f72 doc(sdn-controller): indicate correct version in OpenFlow requirements (#5199) 2020-08-03 16:47:13 +02:00
Pierre Donias 095bbcd15c feat: release 5.49.0 (#5195) 2020-07-31 14:14:32 +02:00
Pierre Donias 9177bb8451 feat: technical release (patch) (#5194) 2020-07-31 09:41:11 +02:00
Pierre Donias 119bf9b0ff feat(xo-web/VM/network): click on IP address to copy it (#5186)
Fixes #5185
2020-07-31 09:17:37 +02:00
Julien Fontanet 015c6037c4 fix: add prepublishOnly to replace removed prepare scripts
Introduced by 452a7e744
2020-07-30 19:07:36 +02:00
Adam Stankiewicz 452a7e7445 feat(test): remove need for prepare scripts (#5192) 2020-07-30 18:56:13 +02:00
Nicolas Raynaud 407586e2d5 feat(remotes): AWS S3 backup storage (#5037) 2020-07-30 16:47:04 +02:00
badrAZ ffa431a3cd fix(xo-web/vm/tab-network): add default value to plugins (#5190)
Introduced by 2a74a49995

Plugins can be `undefined` on fetching which triggers the error `Cannot read property "some" of undefined`
2020-07-30 14:57:06 +02:00
Julien Fontanet 281a5ff991 chore: remove unused JSHint comments 2020-07-30 14:32:19 +02:00
BenjiReis 92db9bd284 fix(xo-server-sdn-controller): deactive DH for TLS connections (#5187)
Fixes #5074
2020-07-30 13:17:40 +02:00
Julien Fontanet ea8f319f45 feat(self-signed): expose days option 2020-07-30 11:20:57 +02:00
Olivier Lambert a11e9fe04e fix(changelog): caps typo (#5184) 2020-07-29 16:58:10 +02:00
Pierre Donias 27367bd1fc fix(CHANGELOG): wrong xo-server version (#5183) 2020-07-29 16:50:16 +02:00
Pierre Donias c6f48ae054 feat: technical release (#5181) 2020-07-29 16:32:55 +02:00
Rajaa.BARHTAOUI 7d6efe3694 feat(xo-web/vm/network): improve the VIF locking mode feedback (#5170)
See #4713
2020-07-29 15:55:59 +02:00
Rajaa.BARHTAOUI f4aad05edc feat(xo-web/backup): show warning if min(fullBackupInterval, retention)>50 (#5144)
See https://xcp-ng.org/forum/post/27539
2020-07-29 15:30:38 +02:00
Pierre Donias d8f7637ca0 feat(xo-web/self): ability to cancel edition of resource set (#5174)
See xoa-support#2767
2020-07-29 13:59:45 +02:00
badrAZ f9a7bd199e fix(xo-server#createVm): change network boot priority (#5119)
Fixes #4980
2020-07-29 11:34:24 +02:00
Rajaa.BARHTAOUI 68b7ed284a feat(xo-web/backup/health): show detached VM snapshots (#5125)
Fixes #5086
2020-07-29 10:56:31 +02:00
badrAZ e782895cf5 feat(xo-server-audit): add extension to exported records (#5180) 2020-07-29 10:52:06 +02:00
Julien Fontanet a5935b40d5 feat(xo-server/api): user must be signed in by default (#5175)
It's a lot more secure than previous default value.
2020-07-29 10:40:17 +02:00
badrAZ 035d2cb440 fix(xo-server-audit): fix incorrect records content type (#5179) 2020-07-29 10:38:59 +02:00
BenjiReis 2a74a49995 feat(sdn-controller, xo-web): add & remove network rules to a VM's VIFs (#5177) 2020-07-29 09:56:06 +02:00
badrAZ 902953a1fa feat(xo-server, xo-web): display proxy available upgrades (#5167) 2020-07-28 17:13:01 +02:00
Pierre Donias 1ffef91b7a fix(xo-web/copyVm): correctly pass the VM type to copyVms (#5173)
Fixes xoa-support#2773

The modal uses the type to find the objects (either VMs or snapshots) and use
them to generate the names. The missing type caused the VM clones to be named
`undefined_clone`.
2020-07-28 16:29:37 +02:00
Julien Fontanet 3d13d9b0dc feat(xo-server/addApiMethod): check method props 2020-07-28 16:02:32 +02:00
Nicolas Raynaud adcc5d5692 feat(import/ova): allow import of gzipped vmdk disks (#5085) 2020-07-28 11:52:44 +02:00
badrAZ c49d70170e feat(xo-server,xo-web/proxy/deploy): ability to set HTTP proxy (#5145) 2020-07-28 11:51:57 +02:00
badrAZ 349a78a5bd fix(xo-web/file-restore): ignore proxy remotes (#5171)
See xoa-support#2741
2020-07-28 11:43:33 +02:00
badrAZ 48734c6896 fix(xo-web/proxies): don't open proxy VM in new tab (#5172) 2020-07-28 10:23:16 +02:00
Rajaa.BARHTAOUI 0f60a3b24d feat(xo-web/home): ability to filter by power state (#5118) 2020-07-27 16:52:07 +02:00
Pierre Donias d3a88011a6 feat(xo-server/self): can ignore VM snapshots resources usage (#5164)
See xoa-support#2643

With the config option `selfService.ignoreVmSnapshotResources`
2020-07-27 16:08:20 +02:00
Rajaa.BARHTAOUI 9b6e4c605b feat(xo-web/schedules): ability to enable schedule when editing (#5111)
Fixes #5026

This change affects ordinary jobs only, not backup jobs
2020-07-27 15:46:21 +02:00
Nicolas Raynaud 7c91524111 fix(OVA import): allow import of .ova files generated by Red Hat (#5159)
See xoa-support#2713.

 - use <rasd:Address> when <rasd:AddressOnParent> is not available on disks
 - avoid dotfiles and pax headers in tar parser.
2020-07-27 08:24:01 +02:00
Olivier Lambert e1573069e4 fix(docs/license): truly fix the warning tag (#5169) 2020-07-24 10:08:58 +02:00
marcpezin f2459c964b Fixing warning closing tag (#5168)
Fixing warning closing tag
2020-07-24 09:20:36 +02:00
Pierre Donias 43aa0b815d feat(xo-web/VM/disks): sort disks by device by default (#5165)
Fixes #5163
2020-07-23 09:53:07 +02:00
marcpezin 0740630e05 fix(docs): rebind license documentation update (#5166) 2020-07-21 17:16:18 +02:00
Rajaa.BARHTAOUI c9244b2b13 feat(xo-web): log Invalid XML-RPC message error as an unexpected response (#5138)
See xoa-support#2588
2020-07-21 15:11:57 +02:00
Pierre Donias 0d398f867f fix(xo-web/home): link to global filter section (#5157) 2020-07-16 15:32:44 +02:00
Julien Fontanet b74ec2d7d3 fix(xo-web/backup/restore): dont fail if no backups for a VM (#5156)
Fixes xoa-support#2707

The API does not guarantee that each VM UUID will have at least a backup, and when it happens, the code failed because `first` and `last` where not properly defined.
2020-07-16 14:29:10 +02:00
Julien Fontanet 26a295c8ed chore(xo-web/createSubscription/run): add small comment 2020-07-13 16:13:33 +02:00
Julien Fontanet 2a71d3d20c chore(xo-web/createSubscription): rename loop to run 2020-07-13 16:10:48 +02:00
Pierre Donias b79605b692 feat: release 5.48.3 (#5154) 2020-07-10 18:12:03 +02:00
Pierre Donias ea0fc68a53 feat: technical release (patch) (#5153) 2020-07-10 16:38:41 +02:00
badrAZ 1ca5c32de3 feat(xo-web/audit): show warning in case of disabled logs record (#5152) 2020-07-10 15:32:30 +02:00
Julien Fontanet f51bcfa05a feat(xo-server-audit): add active setting (default false) (#5151) 2020-07-10 14:29:30 +02:00
Pierre Donias e1bf68ab38 fix(xo-server/pool.listMissingPatches): don't log errors (#5149)
Work-around to avoid generating too many logs
2020-07-10 12:49:37 +02:00
Pierre Donias 99e03b7ce5 fix(xo-web): broken doc links (#5146)
Introduced by 30d69dadbb
2020-07-10 09:14:55 +02:00
Julien Fontanet cd70d3ea46 fix(Travis CI): use Node 12 (#5147) 2020-07-09 15:51:22 +02:00
Julien Fontanet d387227cef fix(xo-server/backups): dont ignore proxy job result/error 2020-07-09 09:40:02 +02:00
Pierre Donias 2f4530e426 feat: release 5.48.2 (#5143) 2020-07-07 15:49:34 +02:00
badrAZ 4db181d8bf chore(xo-server-audit): document audit DB strucure (#5078) 2020-07-07 15:22:41 +02:00
Pierre Donias 9a7a1cc752 feat: technical release (#5142) 2020-07-07 15:03:04 +02:00
Pierre Donias 59ca6c6708 feat(xo-web): prevent XO from checking time consistency of halted hosts 2020-07-07 14:51:06 +02:00
Pierre Donias fe7901ca7f feat(xo-web): prevent XO from listing missing patches on halted XCP-ng hosts
Otherwise it triggers a lot of errors on XCP-ng
2020-07-07 14:51:06 +02:00
Pierre Donias 9351b4a5bb feat(xo-web/backup/logs): better resolution of last run log (#5141) 2020-07-07 13:47:32 +02:00
badrAZ dfdd0a0496 fix(xo-server-test): extend timeout of deleteTempResources (#5117) 2020-07-07 13:31:13 +02:00
Pierre Donias cda39ec256 fix(xo-web/backup/edit): tags overwritten by default ones (#5136)
Introduced by 1c042778b6
See xoa-support#2663

It was due to a race condition between the fetch of the default excluded tags
and the fetch of the job (and its schedules) which made the component populate
the form with the job's information.

Changes:
- `Edit` waits for the `job` and the `schedules` before rendering its child
- `New`'s wrapper waits for the `remotes` and the `suggestedExcludedTags` before
  rendering `New`
- `New`: `updateParams` is now called in `initialize` because we don't need to
  wait for the job and the schedules any more to be able to populate the form
2020-07-07 09:40:40 +02:00
Olivier Lambert 3720a46ff3 feat(docs/supported_hosts): no pro support for XS < 6.5 (#5137) 2020-07-06 20:03:47 +02:00
Julien Fontanet 7ea50ea41e fix(xo-server/callProxyMethod): dont use HTTP proxy 2020-07-06 17:06:37 +02:00
Pierre Donias 60a696916b feat: release 5.48.1 (#5133) 2020-07-03 15:25:39 +02:00
Pierre Donias b6a255d96f feat: technical release (patch) (#5132) 2020-07-03 14:24:40 +02:00
marcpezin 44a0cce7f2 fix(docs/license_management): replace confusing screenshot about activation (#5131) 2020-07-03 12:03:07 +02:00
Nicolas Raynaud f580e0d26f fix(import/OVA): fix big size parsing in OVA files (#5129) 2020-07-03 11:48:39 +02:00
Rajaa.BARHTAOUI 6beefe86e2 feat(xo-web/backup): don't open edition in new tab (#5130) 2020-07-03 11:45:06 +02:00
Julien Fontanet cbada35788 fix(xo-server/file restore): dont fail on LVM partitions
Fixes xoa-support#2640

Introduced by 48ce7df43

The issue was due to object spreading copying only own properties but `path` is now an inherited property due to `dedupeUnmount`.
2020-07-03 11:05:04 +02:00
Julien Fontanet 44ff2f872d feat(xo-server/getBackupNgLogs): dont fail on undefined/null errors
See xoa-support#2663

This should almost never happen but if it does, it should not prevent logs from being consolidated.
2020-07-03 09:22:28 +02:00
Julien Fontanet 2198853662 feat(xo-server/logs-cli): can match on missing props 2020-07-03 09:22:28 +02:00
badrAZ 4636109081 fix(xo-web/(file-)restore-legacy): ignore proxy remotes (#5124)
Legacy restore doesn't support proxy remotes
2020-07-02 16:23:36 +02:00
Pierre Donias 1c042778b6 feat(xo-server,xo-web/smart backup): exclude XO Proxy VMs by default (#5128) 2020-07-02 15:06:47 +02:00
Rajaa.BARHTAOUI 34b5962eac fix(xo-web/backup/health): missing noop function (#5126)
Introduced by committing a suggestion https://github.com/vatesfr/xen-orchestra/pull/5062#discussion_r446135166 
without taking into account that the `noop` function is not already defined.
2020-07-02 15:05:55 +02:00
Rajaa.BARHTAOUI fc7af59eb7 chore(xo-web/home): remove 'tags' filter from selector (#5121)
See https://github.com/vatesfr/xen-orchestra/pull/5118#discussion_r447586676
2020-07-02 14:52:59 +02:00
Olivier Lambert 7e557ca059 feat(docs/supported hosts): add CH 8.2 LTS in the list of supported hosts (#5127) 2020-07-02 09:30:16 +02:00
Julien Fontanet 1d0cea8ad0 feat(xo-server/logs-cli): add --delete command 2020-07-01 18:04:45 +02:00
Julien Fontanet 5c901d7c1e fix(xo-server/logs-cli): dont fail on non-string value 2020-07-01 18:01:34 +02:00
Julien Fontanet 1dffab0bb8 feat(xen-api): 0.29.0 2020-07-01 17:11:19 +02:00
Julien Fontanet ae89e14ea2 feat(xo-server/getRemoteHandler): throw for proxy remotes 2020-07-01 11:46:28 +02:00
Pierre Donias 908255060c feat: release 5.48.0 (#5123) 2020-06-30 17:25:16 +02:00
Pierre Donias 88278d0041 feat: technical release (patch) (#5122) 2020-06-30 16:51:20 +02:00
Julien Fontanet 86bfd91c9d feat(xo-server/backup): logs proxy support 2020-06-30 15:45:40 +02:00
Julien Fontanet 0ee412ccb9 feat(xo-server/callProxyMethod): allow proxy.address to contain port 2020-06-30 15:20:58 +02:00
Julien Fontanet b8bd6ea820 chore(xo-server/callProxyMethod): use parse.result to handle errors 2020-06-30 12:14:45 +02:00
Julien Fontanet 98a1ab3033 fix(xo-server/callProxyMethod): destroy lines stream in case of error 2020-06-30 12:14:45 +02:00
Julien Fontanet e360f53a40 fix(xo-server/callProxyMethod): all lines should be JSON parsed 2020-06-30 12:14:45 +02:00
Julien Fontanet 237ec38003 fix(xo-server/callProxyMethod): lines is an object stream 2020-06-30 12:14:45 +02:00
Julien Fontanet 30ea1bbf87 feat(xo-server/callProxyMethod): expectStream as named option 2020-06-30 12:14:45 +02:00
Pierre Donias 0d0aef6014 feat: technical release (patch) (#5120) 2020-06-30 11:40:44 +02:00
badrAZ 1b7441715c feat(xo-server-perf-alert): regroup items with missing stats in one email (#4413)
Fixes #5104
2020-06-30 09:30:20 +02:00
badrAZ e3223b6124 fix(xo-web/audit): ref not correctly forwarded (#5106)
Introduced by 9f29a047a7

The high level component (audit UI) need to call a `SortedTable` method. The only way to do it is to have access to its ref.

All components between the high level component and the `SortedTable` should forward this ref. Unfortunately, the commit  9f29a047a7 decorate the `StortedTable` with `withRouter` without forwarding its ref which breaks the audit check integrity feedback.
2020-06-29 15:44:33 +02:00
Julien Fontanet 41fb06187b fix(coalesce-calls/README): fix import 2020-06-29 15:39:14 +02:00
Julien Fontanet adf0e8ae3b feat(@vates/coalesce-calls): 0.1.0 2020-06-29 15:33:53 +02:00
Rajaa.BARHTAOUI 42dd1efb41 feat(xo-web/home): remove unnecessary condition (#5116)
Introduced by f736381933

Backup filter: remove the needless condition to go to the first page.
2020-06-29 15:24:28 +02:00
badrAZ b6a6694abf fix(xo-server-test/job with non-existent VM): logged as failed task (#5112)
Since c061505bf8, missing VMs are logged as a failure tasks
2020-06-29 14:04:23 +02:00
Pierre Donias 04f2f50d6d feat: technical release (#5115) 2020-06-26 15:56:40 +02:00
Rajaa.BARHTAOUI 6d1048e5c5 feat(xo-web/backup/health): show detached backups (#5062)
See #4716
2020-06-26 14:45:01 +02:00
Pierre Donias fe722c8b31 feat(xo-web/licenses): rebind license to this XOA (#5110)
See xoa#55
Requires xoa#58

When an XOA license is bound to another XOA, allow the user to move it to the
current XOA (thus unbinding it from the other one).
2020-06-26 13:12:53 +02:00
badrAZ 0326ce1d85 feat(xo-server-audit): ignore common methods without side effects (#5109)
Ignoring these methods reduce the number of records in the audit which makes it easier to analyze and store.
2020-06-25 16:55:57 +02:00
Rajaa.BARHTAOUI 183ddb68d3 fix(changelog): missing a parenthesis (#5113) 2020-06-25 15:53:30 +02:00
badrAZ d7fe1afc08 fix(xo-server#listVmBackups): provide schedule ID (#5101)
Introduced by b138438036
Schedule ID is used by [xo-server-test](https://github.com/vatesfr/xen-orchestra/blob/c1d588264c2904ff45d49900f011ff7de9a73033/packages/xo-server-test/src/_xoConnection.js#L216)
2020-06-25 10:20:17 +02:00
Rajaa.BARHTAOUI ae9aeaf5fd feat(xo-server,xo-web/SR): expose thin/thick provisioning (#5081)
Fixes #2208
2020-06-24 16:21:23 +02:00
Rajaa.BARHTAOUI ec9476216f feat(xo-web/sr/disks): add tooltip for disabled migration (#4884) 2020-06-24 16:07:48 +02:00
badrAZ 619f2ef119 fix(VM): support old ipv4 protocol (#5098)
See xoa-support#2540
Indroduced by 7f64cd1801
2020-06-24 15:44:52 +02:00
Rajaa.BARHTAOUI 52020abde8 feat(xo-web/home): don't use SortedTable for VMs (not) backed up (#5046)
Introduced by f736381933
2020-06-24 14:12:37 +02:00
badrAZ 1bd504d67e feat: differentiate PV drivers and management agent (#5007)
Fixes #4783
2020-06-24 11:50:45 +02:00
badrAZ edc4414de4 fix(xo-server/remotes): inability to get remotes info (#5093)
Introduced by 218bd0f
2020-06-23 11:12:16 +02:00
Olivier Lambert c1d588264c feat(docs/backups): crop delta images (#5097) 2020-06-19 10:00:25 +02:00
badrAZ 94b84b75ad feat(xo-web/backup): document full backup interval functionality (#5052)
Fixes #4986
2020-06-19 09:43:13 +02:00
Olivier Lambert b72a4c5aa9 feat(docs/proxy): add missing image and store them locally (#5096) 2020-06-18 21:37:19 +02:00
Julien Fontanet 857a9f3efc feat(xen-api): optional sync traces (#5091)
Initial actions call stacks are often missing from the resulting error for the following reasons:

- low level Node functions don't have proper stack traces
- replies handling maybe separate from requests (eg watchers)

This commit adds the option `syncStackTraces` that works around this, it has a performance impact but is useful for debugging.
2020-06-18 17:19:21 +02:00
badrAZ ce53128657 feat(xo-server-audit): ignore xoa.getApplianceInfo (#5083)
`xoa.getApplianceInfo` doesn't have any side effect and is called many times.
2020-06-18 15:16:12 +02:00
Rajaa.BARHTAOUI d9211053ce feat(xo-web/home/template): ability to copy/clone VM templates (#5006)
Fixes #4734
2020-06-18 15:13:12 +02:00
Rajaa.BARHTAOUI e8316178a0 feat(xo-web/plugins): disable "Test plugin" if not loaded (#5038) 2020-06-18 14:33:18 +02:00
badrAZ bf763d2cf4 feat(xo-web/backup): add placeholder to report recipients input (#5051)
Fixes #5035
2020-06-17 16:22:38 +02:00
badrAZ eba5b34982 fix(xo-server#moveVdi): moveVdi should always return a VDI (#5073)
Fixes #5072
2020-06-16 20:56:00 +02:00
Pierre Donias afb8b3dd6b feat(xo-server,xo-web/vm): protect from accidental deletion (#5045)
Fixes #4773
2020-06-16 15:40:49 +02:00
Julien Fontanet c5fa94894b feat(xen-api): require Node >=7.6
Native support of async functions which leads to better stack traces.
2020-06-16 12:54:51 +02:00
Pierre Donias 4137758caa fix(xo-web/tooltip): use pointer events instead of mouse events (#5084) 2020-06-15 17:29:40 +02:00
Nicolas Raynaud 3578d16e9e fix(xo-server): correctly import vmdkToVhd (#5087)
Introduced in 5ee1ceced
2020-06-15 17:00:49 +02:00
BenjiReis 3ef263a5cc fix(xo-server-sdn-controller): correctly find preferred center's pool (#5080) 2020-06-15 11:13:01 +02:00
BenjiReis 510460c966 fix(xo-web): dont pass preferredCenter to sdnController.createPrivateNetwork (#5079) 2020-06-13 10:00:08 +02:00
Julien Fontanet f74ecc53ae chore(xo-server): use @vates/decorate-with 2020-06-12 11:18:47 +02:00
Julien Fontanet c4121073ad feat(@vates/decorate-with): 0.0.1 2020-06-12 11:12:49 +02:00
Julien Fontanet 9ded2641a7 chore(xo-server/authentication): remove unused import 2020-06-12 11:02:42 +02:00
Julien Fontanet 295ca68d02 chore(xo-server): use @vates/parse-duration 2020-06-12 11:02:42 +02:00
Julien Fontanet 27f53f262b feat(@vates/parse-duration): 0.1.0 2020-06-12 11:02:42 +02:00
Olivier Lambert 3fc16cb414 feat(docs/backups): warn of 99 chain limit for file restore (#5070) 2020-06-11 14:29:49 +02:00
Pierre Donias 90db25d732 fix(xo-web/notifications): set cookie expiration date (#5067)
Without an expiration date, the cookie expires at the end of the session and
read notifications are marked as unread the next time the user connects.
2020-06-11 12:34:33 +02:00
Julien Fontanet bbb359470e fix(xo-server/backup): remove enumerable xapi on SR records (#5069)
Fixes xoa-support#2527

This was causing huge logs in case of CR/DR errors because this property was included and pulled in all XAPI records.

Instead of making it non-enumerable, I was able to remove entirely because records now already include a non-enumerable `$xapi` property.
2020-06-10 11:25:32 +02:00
badrAZ 319652c7c7 fix(xo-web/migrate-vdi): remove inter-pool migration possibility (#5050) 2020-06-10 09:16:14 +02:00
Julien Fontanet c9c271fee8 feat(xen-api): $xapi defined on prototype instead of record
This should reduce a bit memory consumption.
2020-06-09 23:17:02 +02:00
marcpezin ca0755e92b fix(docs/delta-backup): schemas should not display XVA (#5032) 2020-06-09 15:50:13 +02:00
Rajaa.BARHTAOUI acd38597f6 fix(xo-web/vm/network): VM addresses can be null (#5049)
Introduced by 7f64cd1801
2020-06-09 15:12:04 +02:00
Pierre Donias f4a5a80f3c fix(xo-web/SR): fix name_label edition from the home view (#5058)
Fixes #5057
Introduced by da468c46ee
2020-06-09 13:38:42 +02:00
Pierre Donias c45d00fee8 fix(xo-web/import): default sub-route should be /vm (#5056)
Fixes #5055
Introduced by a95d7796bc
2020-06-08 16:31:02 +02:00
Ronan Abhamon ffae59fa1c feat(changelog): missing entries for #5054 (#5066) 2020-06-08 11:17:38 +02:00
Pierre Donias b697178f68 feat(xo-web/SortedTable): always show amount of selected items (#5041)
Fixes #4982
2020-06-08 10:57:37 +02:00
Julien Fontanet 83ade5eecb chore(CHANGELOG.unreleased): clarify that packages are not yet released 2020-06-08 10:54:42 +02:00
Ronan Abhamon 6973b92c4a fix(load-balancer): fix memory check condition in the performance plan
We must migrate a VM if the free memory in the destination host is lower than the used VM
memory!
2020-06-08 10:22:34 +02:00
Ronan Abhamon 6261f8a778 feat(load-balancer): add various logs to explicit migration checks and steps 2020-06-08 10:22:34 +02:00
badrAZ 6048493ac6 fix(xo-server#_extractIpFromVmNetworks): support old ipv4 protocol (#5036)
See xoa-support#2540

In case of an old version of guest tools, the VM ipv4 isn't reported.

This issue is due to a non-existant `n/ipv4/m` property in the VM addresses which is a new protocol.
2020-06-08 09:52:33 +02:00
Pierre Donias 1cbd715235 feat(xo-web/new-vm): dont prefill VM description (#5047)
Fixes #4981

Except if the template is a custom template
2020-06-05 14:52:31 +02:00
Julien Fontanet 703fcbccd6 feat(xo-server/xo.exportConfig): entries param
Can be used to export a subset of the config, example:

```
xo.exportConfig entries=["acls"]
```

This will only export `acls` entries and dependencies (`groups` and `users`).
2020-06-05 13:57:54 +02:00
Julien Fontanet 2f9cbec07e feat(xo-cli): support @=- to output to stdout 2020-06-05 13:57:54 +02:00
badrAZ 9f0b22d3e9 fix(xo-server#createVm): move VDIs before resize them (#5044)
See xoa-support#2535

Otherwise resizing might file due to space limitation on the template VDI's SR.
2020-06-05 13:37:18 +02:00
Julien Fontanet ab5907c09c feat(xo-server/logs-cli): implement --gc 2020-06-05 10:58:26 +02:00
Olivier Lambert fae0b168f6 feat(docs/load_balancing): various improvements (#5048) 2020-06-04 10:49:26 +02:00
Julien Fontanet f18e98a63e chore: reformat code with Prettier 2020-06-03 11:03:03 +02:00
Julien Fontanet 3524886d5d chore: update dev dependencies 2020-06-03 11:03:03 +02:00
Julien Fontanet fb44eea06c fix(xo-server): load globally installed plugin
It has been broken by d4526e1ed

Thanks @Danp2 for the report!
2020-06-02 20:44:33 +02:00
Julien Fontanet 3ea4c757e6 feat(backups-cli): clean checksums for missing XVAs 2020-06-02 15:27:36 +02:00
badrAZ cfb8d79049 feat: release 5.47.1 (#5043) 2020-06-02 13:40:36 +02:00
badrAZ 1ea86da7af feat: technical release (patch) (#5042) 2020-06-02 13:02:21 +02:00
Julien Fontanet e289f2dba2 fix(auth-ldap/authenticate): dont use second param as logger (#5039) 2020-06-02 11:11:25 +02:00
Rajaa.BARHTAOUI 7f64cd1801 feat(xo-web/vm/network): show IPs in front of their VIFs (#5003)
Fixes #4882
2020-06-02 09:26:31 +02:00
Julien Fontanet d4526e1ed2 feat(xo-server): load @xen-orchestra/server-* plugins 2020-06-01 21:06:04 +02:00
Julien Fontanet 34f42216c8 feat(*/README.md): better badges 2020-06-01 14:41:52 +02:00
Julien Fontanet a26a24a8ad fix(normalize-packages): dont replace author in READMEs 2020-06-01 14:06:09 +02:00
Julien Fontanet 4530fd4164 chore(*/package.json): normalize author to Vates SAS 2020-06-01 14:06:09 +02:00
Olivier Lambert 9156b8f48c feat(docs): merge and clean old docs into new one (#5025) 2020-06-01 11:32:27 +02:00
Julien Fontanet 6212109fc1 feat(@vates/read-chunk): 0.1.1 2020-05-29 15:10:20 +02:00
Julien Fontanet c22a080e23 fix(read-chunk): not an ES module 2020-05-29 15:10:20 +02:00
Julien Fontanet 834a7109f9 fix: add @vates to list of workspaces 2020-05-29 15:10:20 +02:00
badrAZ 7cbf32202d feat: release 5.47.0 (#5031) 2020-05-29 12:29:41 +02:00
Julien Fontanet d0b9380dca fix(*/README): license link 2020-05-28 21:24:20 +02:00
Julien Fontanet 13fd9be566 feat(*/README.md): re-generate for all packages 2020-05-28 20:56:14 +02:00
Julien Fontanet 53a9aa6ad2 fix(vhd-lib): dont prefer global install 2020-05-28 20:29:10 +02:00
Julien Fontanet c2ce4aca1b feat(async-map/package.json): add description 2020-05-28 20:28:52 +02:00
Julien Fontanet 567f6d7cc0 fix: prefer global install for CLIs 2020-05-28 20:28:28 +02:00
Julien Fontanet 489c0b27f9 fix: use AGPL-3.0-or-later licenses for xo pkgs 2020-05-28 20:27:39 +02:00
Julien Fontanet 343f988584 fix: use AGPL-3.0-or-later license identifier
`AGPL-3.0` identifier has been deprecated by SPDX.org
2020-05-28 20:26:55 +02:00
Julien Fontanet 7f676c56c8 feat(normalize-packages): add license to all packages 2020-05-28 16:05:55 +02:00
Julien Fontanet 3c0ca7026f fix(read-chunk/README): fix pkg name 2020-05-28 16:05:55 +02:00
Rajaa.BARHTAOUI 2ceba11aa7 feat: technical release (#5028) 2020-05-28 16:04:13 +02:00
Julien Fontanet 6db5e0b27c feat(@vates/read-chunk): 0.1.0 2020-05-28 14:49:00 +02:00
Julien Fontanet dfecb801db fix(read-chunk/USAGE): fix pkg name 2020-05-28 14:48:27 +02:00
Julien Fontanet c10bfe3db2 feat(read-chunk): module to read data from stream 2020-05-28 14:45:22 +02:00
Julien Fontanet 20fb2c99bc feat(normalize-packages): generate README.md from USAGE.md 2020-05-28 14:45:21 +02:00
Pierre Donias b4a0b5c58b fix(xo-server/setData): dont wait for update if no changes (#5027)
If an other_config entry is set to the same value as it was before, the object
will not be updated and the _waitObject promise will "never" resolve.
2020-05-28 14:01:54 +02:00
badrAZ faa46c2a21 fix(xo-web/modal#form): defer rendering until all props are set (#5024)
The set default value is not used in the first render due to a race condition between the modal render and the modal value.

To avoid this race condition and multiple renders, the modal should open at the end of the set of its properties.
2020-05-28 11:19:25 +02:00
badrAZ 9691199ae8 feat(xo-web/proxies): start trial if no license available (#5022)
See xoa#54
2020-05-28 10:58:43 +02:00
Rajaa.BARHTAOUI f736381933 feat(xo-web/home): ability to list VMs which are (not) backed up (#4974)
Fixes #4777
2020-05-28 10:10:34 +02:00
Julien Fontanet f44e5b3b7a fix(babel-config): remove auto useBuiltIns
Too magical, caused too much problems.
2020-05-27 10:25:41 +02:00
Julien Fontanet 6e24bf5f8c fix(xo-{cli,upload-ova}): remove deprecated dep @babel/polyfill 2020-05-27 10:13:54 +02:00
Julien Fontanet 8fb43e31c5 fix(babel-config): useBuiltIns only if core-js
Because `@babel/polyfill` is deprecated.

See https://babeljs.io/docs/en/babel-preset-env#usebuiltins
2020-05-27 10:13:30 +02:00
Julien Fontanet 0860c80e51 fix(*/README): legacy project URLs 2020-05-27 10:04:00 +02:00
Julien Fontanet 66fc25756f Revert "feat(xo-server): load plugins from mono-repo"
This reverts commit 3e3ce543a8.

This can cause problems due to duplicate loading.
2020-05-27 09:53:46 +02:00
Olivier Lambert f008e240cd feat(docs/installation): banner explanation (#5023) 2020-05-27 09:44:36 +02:00
BenjiReis 8d7e95d6e9 feat(sdn-controller/new network): choose preferred center (#5000)
Fixes #4991
2020-05-26 16:56:46 +02:00
Julien Fontanet 3e3ce543a8 feat(xo-server): load plugins from mono-repo 2020-05-26 14:01:43 +02:00
Julien Fontanet 6c447a82f1 chore(audit-core): remove unused dev dep 2020-05-26 13:59:06 +02:00
Julien Fontanet 64a0918ff1 chore(yarn.lock): update dependencies 2020-05-26 13:59:06 +02:00
Nicolas Raynaud 9274223701 chore(server): dont handle errors in registerHttpRequest() handlers (#5021)
`registerHttpRequest()` has built in error handling/logging.
2020-05-26 12:19:24 +02:00
Pierre Donias 1368c18844 feat(xo-web): disclaimer banner cooldown (#5008) 2020-05-26 10:59:10 +02:00
Pierre Donias 67a60a7557 feat(xo-web/config): UI for the encrypted config export/import (#4997)
See 1da889e420
2020-05-25 14:58:48 +02:00
badrAZ 3d5fd47748 feat(audit): record failed users' connection attempt (#4900)
See #4844
2020-05-25 12:48:05 +02:00
Julien Fontanet b9a18807ae fix(xo-server/_handleHttpRequest): dont write if something has been sent 2020-05-25 09:58:03 +02:00
marcpezin 088c0b6321 fix(docs): replace the delta backup image with the right file type (#5019)
Replace `.xva` with `.vhd`
2020-05-25 09:23:30 +02:00
Nicolas Raynaud ecee11a24c feat(xo-server/OVA import): comptibility with version 2.0 (#4921) 2020-05-25 08:50:32 +02:00
Olivier Lambert ec8df7ce57 fix(docs): properly add license management to menu (#5018) 2020-05-23 22:16:58 +02:00
Julien Fontanet 4159fd2ffb fix(backups-cli/_fs/readdir2): dont warn on missing dir 2020-05-22 23:48:15 +02:00
Julien Fontanet 1a1d21bbb3 fix(backups-cli/clean-vms): isValidXva is a named import 2020-05-22 23:48:14 +02:00
marcpezin be1045fed9 feat(docs): license management (#5015)
* licensing documentation

How to bind license in XOA

* Update license-management.md

* Add files via upload

license activation image

* fix links

* fix wording

* adding license management in menu

* Update license-management.md
2020-05-22 16:47:14 +02:00
Olivier Lambert e43773c712 feat(docs/delta_backups): manual initial seed (#5011) 2020-05-22 14:03:07 +02:00
Olivier Lambert 30d69dadbb feat(docs): major rewrite using vue-press (#4957) 2020-05-21 11:46:24 +02:00
badrAZ b138438036 feat(xo-server#_listVmBackupsOnRemote): remove unused properties (#4985)
This reduce by 10/100 times the quantity of data sent to the clients, which should improve performance.
2020-05-19 14:25:33 +02:00
badrAZ d649211330 fix(xo-server-backup-reports): fix No recipients defined error (#4998)
Correctly fall back to plugin recipients if `mailRecipients` is empty.
2020-05-19 14:22:24 +02:00
Nicolas Raynaud 6cf211a9ad fix(xo-server-perf-alert): make message compatible with XenCenter (#5004) 2020-05-18 14:56:11 +02:00
badrAZ 3388e5e8a4 fix(xen-api#_sessionOpen): don't log credentials on error (#4995) 2020-05-18 09:47:52 +02:00
Julien Fontanet 5d497a1908 fix(xo-server-auth-ldap): use this._tlsOptions in bind
Introduced by 5870f6f73
2020-05-17 16:48:57 +02:00
Julien Fontanet c820646fb6 fix(xo-server-auth-ldap): upgrade ldapts dep
Necessary for 5870f6f73

Also, only pass `tlsOptions` when creating client when using `ldaps`.
2020-05-17 16:11:24 +02:00
Julien Fontanet 5870f6f734 feat(xo-server-auth-ldap): support startTLS
Fixes #4999
2020-05-17 15:24:01 +02:00
Julien Fontanet 6732150121 fix(xo-server-auth-ldap): dont pass bindDN and `bindCredentials to LDAP client
It was left from an older version of the code which was working differently.
2020-05-17 12:47:08 +02:00
Pierre Donias 1dead8b080 feat(xo-web/modal/form): don't close on click or escape (#5002)
See xoa-support#2469

When the user clicks outside of a form modal or presses escape, don't close the
modal as all the information they entered so far will be lost.
2020-05-15 16:24:16 +02:00
BenjiReis d547aa8ebd fix(sdn-controller): recreate both sides of tunnels when host updated (#4996)
To keep password synchronized.
2020-05-15 16:05:21 +02:00
Julien Fontanet 1da889e420 feat(xo-server/xo.{export,import}Config}): support passphrase (#4935) 2020-05-14 15:23:45 +02:00
Pierre Donias 5d0a308d1d fix(xo-web/SortedTable): don't inject empty filter if there isn't a URL param (#4994) 2020-05-14 11:11:05 +02:00
badrAZ f9886d52da feat(usage-report): include CSV raw data files to sent email (#4979)
Fixes #4970
2020-05-13 14:42:46 +02:00
badrAZ 4f8e48b7d4 fix(CHANGELOG.unreleased): add missing entry (#4992) 2020-05-12 12:26:22 +02:00
Rajaa.BARHTAOUI 258e07c2ca feat(xo-web/render-xo-item): add pool name to networks (#4990)
Fixes #4885
2020-05-12 11:24:24 +02:00
badrAZ cc32c50665 feat(xo-web/xoa): display proxy licenses (#4944)
There are three license states:
- license bound to an `XOA` which **is** linked to a proxy: display proxy link
- license bound to an `XOA` which **isn't** linked to a proxy: display `License attached to an unknown proxy` 
- license not bound to any `XOA`: display `No proxy attached`
2020-05-12 09:17:19 +02:00
Ben ec1d91f73e fix(@xen-orchestra/fs): fix mount for FreeBSD (#4988) (#4989) 2020-05-12 00:08:34 +02:00
badrAZ eb2f429964 fix(xo-server#getAllRemotesInfo): ignore disabled remotes 2020-05-11 17:49:58 +02:00
Julien Fontanet 1ad067309d fix(xo-cli/README): link to xo-upload-ova 2020-05-11 17:30:12 +02:00
Julien Fontanet 48ce7df43a feat(xo-server/file restore): dedupe mount/unmount (#4961) 2020-05-07 17:36:37 +02:00
Pierre Donias 6555e2c440 chore(xo-web/VM): move boot order setting from Disks to Advanced (#4975)
See #1523
2020-05-07 09:37:00 +02:00
badrAZ a05191e112 fix(xo-server/proxies): remove duplicated license unbind (#4977)
On destroying a proxy, the license will be unbound twice: on the proxy destruction and on the proxy unregistration.

These unbinds will lead to an error which will be displayed in the console and will have no side effects on the process. This error will not be visible by users.
2020-05-06 14:23:04 +02:00
Julien Fontanet b8eeee1d5d feat(xo-server/listVmBackups): use backup.listingDebounce setting (#4972) 2020-05-05 14:23:22 +02:00
Pierre Donias 4aa87f3fa5 chore(xo-web/xoa/update): hide XOA build number when unknown (#4973) 2020-05-05 14:15:44 +02:00
badrAZ 40c37d923b fix(xo-web/Number): fix inability to set advanced expressions (#4690)
Fixes #4566
2020-05-05 11:20:17 +02:00
Rajaa.BARHTAOUI 5a5837b8ed feat: release 5.46.0 (#4963) 2020-04-30 16:20:04 +02:00
Julien Fontanet 1e0b521070 fix(xo-server/backup): pass correct path to isValidXva (2)
Fix incorrect change in c4a157919.
2020-04-30 15:16:30 +02:00
Julien Fontanet 35ed58cc5e feat(xo-server): auto-generate express-session secret on first run
Also, use this secret to sign all cookies.
2020-04-30 14:57:05 +02:00
Julien Fontanet c4a1579197 fix(xo-server/backup): pass correct path to isValidXva
The path was incorrect which means there was a warning in xo-server logs and the check was not properly working.
2020-04-30 14:45:53 +02:00
badrAZ e471706422 fix(xo-web/proxies): only fetch licenses when (re)deploy (#4962) 2020-04-30 13:49:47 +02:00
Julien Fontanet d78b7350b5 feat(xo-server): use memorystore as express-session store
This removes a warning and potential memory leaks.
2020-04-30 09:32:42 +02:00
Rajaa.BARHTAOUI 47b29d5a49 feat: technical release (#4958) 2020-04-29 10:51:35 +02:00
Rajaa.BARHTAOUI e5946a51d1 feat(xo-web/backup/run): show # of VMs that will be backed up (#4875) 2020-04-28 17:40:05 +02:00
Pierre Donias a88798cc22 feat(xo-server/vm/snapshot): handle Self Service (#3693)
See #3304
2020-04-28 16:14:43 +02:00
badrAZ 6fbd32523a fix(xo-server/callProxyMethod): support IPv6 address (#4955) 2020-04-28 14:17:46 +02:00
Pierre Donias 94b1cc2bdd chore(xo-web/xosan): prevent installing XOSAN on XCP-ng pools (#4953) 2020-04-28 14:17:02 +02:00
badrAZ 0ed5c8f0ae fix(xo-server/proxies): use configured address only when no associated VM (#4950) 2020-04-28 09:49:49 +02:00
Pierre Donias 5f883f552b feat(xo-common/api-errors): notEnoughResources error (#4952) 2020-04-27 16:55:44 +02:00
Julien Fontanet 9db99ab4a5 feat(xo-server): auto self signed cert generation (#4954) 2020-04-27 15:40:15 +02:00
Julien Fontanet 287214c2b2 fix(xo-server): debounceWithKey.decorate(decorateWith(debounceWithKey
Introduced by 317a02084
2020-04-27 13:21:53 +02:00
Julien Fontanet 317a020841 chore(xo-server/decorateWith): use fn wrappers as method decorator 2020-04-27 09:35:05 +02:00
Julien Fontanet b50e3aec5f chore(xo-server/decorators/debounce): replace with debounceWithKey 2020-04-24 17:18:15 +02:00
badrAZ 21a9e0e2a7 chore(xo-web/proxies): remove proxy address column (#4951) 2020-04-24 17:16:58 +02:00
badrAZ 7775df8ef1 fix(xo-web/proxies): proxy VM should be in RO (#4947) 2020-04-24 11:16:07 +02:00
badrAZ 53f9b5d131 fix(xo-server,xo-web): add mainIpAddress to VM objects (#4943)
Fixes #4927
2020-04-24 10:16:13 +02:00
badrAZ bf4d4a4742 fix(xo-web/backup-ng): only show delta info if delta is enabled (#4946)
Fixes #4945
2020-04-23 10:12:51 +02:00
Nicolas Raynaud 0dbbe7104d fix(xo-server/OVA import): fix memory issue (#4920)
Affects both VDMK and OVA import because an OVA file contains VMDK disks.

The input VMDK stream was put in memory instead of braking the upload speed when the VHD stream was slower than the input stream.

The reason is that pipette/slicer makes no attempts at pausing the input stream, so it will store everything in memory if the writing of the VHD stream is slower than the reading of the VMDK stream (https://github.com/Medium/pipette#layering-philosophy "They do not make upstream calls to the flow-control methods pause() and resume()")

The proposed solution is to remove pipette and handle the case ourselves.
2020-04-22 17:25:17 +02:00
badrAZ 561ef00680 fix(xo-server/backup-ng): throw error if remote's proxy is different than backup's proxy (#4907)
See #4905
2020-04-22 14:39:28 +02:00
Pierre Donias 85428fa72e fix(xo-web/xoa): always allow users to manage the XOA (#4941) 2020-04-22 14:18:59 +02:00
badrAZ 29d0593b86 fix(xo-server/proxies): incorrect extract of network IP (#4928)
See #4927
2020-04-22 13:04:33 +02:00
badrAZ ac524dd799 feat(xo-server/proxies): unbind license on forgetting a proxy
See xoa#52
2020-04-22 09:14:53 +02:00
badrAZ aba8b764b6 feat(xo-server/proxies): unbind license on destroying a proxy
See xoa#52
2020-04-22 09:14:53 +02:00
badrAZ a9050e0f41 fix(xo-server/proxies): fix inability to destroy proxy on missing VM
See xoa#52
2020-04-22 09:14:53 +02:00
badrAZ 15ef84e238 feat(xo-web/proxy): bind license to a (re)deployed proxy (#4916)
See xoa#52
2020-04-22 09:14:53 +02:00
badrAZ 09096fef5b feat(xo-server/proxy): bind license on (re)deploying (#4913)
See xoa#52
2020-04-22 09:14:53 +02:00
badrAZ 19b08e1019 feat(proxy): CHANGELOG (#4930)
See xoa#52
2020-04-22 09:14:53 +02:00
Pierre Donias 06d67642dd fix(xo-server/patching): filter out CH8x patches (#4942)
We already filter out XSxx patches from normal patches (XSxxExxx) since they're special patches that are meant to upgrade the host to the next version.

Since XenServer has been renamed Citrix Hypervisor, patches names now start with the letters "CH" so we also need to filter out CHxx patches.
2020-04-21 12:01:47 +02:00
Pierre Donias ceb6c450c0 feat(xo-web): Italian locale (#4932)
Fixes #2888
2020-04-20 10:48:23 +02:00
Julien Fontanet a745e42cf5 feat(xo-server/_handleHttpRequest): send directly string/Buffer results 2020-04-17 17:09:40 +02:00
Julien Fontanet 462d6a4450 chore(xo-server/{export,import}Config): handle JSON instead of raw objects 2020-04-17 17:08:38 +02:00
Julien Fontanet a2e39c5e2e fix(xo-server-audit/_exportRecords): dont return 200 on failure
See ec899be3b
2020-04-17 16:14:34 +02:00
Julien Fontanet ec899be3b5 fix(xo-server/xo.exportConfig): dont return 200 on failure
`writeHead` sends immediatly the response header, which has a number of undesirable side-effects.

For instance, in this case, it prevented returning a 500 code in case of error.

It's almost always preferable to use `statusCode`, `writeHead()` or Express methods like `set()`.
2020-04-17 16:12:55 +02:00
Julien Fontanet c79ebfdd0a fix(CHANGELOG.unreleased): better syntax for variables 2020-04-16 15:09:11 +02:00
Julien Fontanet cd95e6c552 chore(CHANGELOG.unreleased): doc for package version 2020-04-16 15:08:06 +02:00
Julien Fontanet f676145302 fix(xen-api/putResource): compat with XS 6.5 and Node 12 2020-04-16 15:04:17 +02:00
Pierre Donias 0847267069 feat(xo-web/snapshot with memory): add confirm modal (#4917)
Fixes #4914
2020-04-09 16:51:09 +02:00
Julien Fontanet 6fe1da1587 fix(CHANGELOG): add missing released packages 2020-04-08 16:43:55 +02:00
Julien Fontanet 7ab555d869 feat: release 5.45.1 2020-04-08 15:37:09 +02:00
Julien Fontanet 4a35e9e60d feat(xo-web): 5.58.2 2020-04-08 13:59:20 +02:00
Julien Fontanet 5e8dfdfd9b feat(xo-server): 5.58.2 2020-04-08 13:59:14 +02:00
Julien Fontanet 278a1b8ab3 feat(xo-server-audit): 0.3.0 2020-04-08 13:58:30 +02:00
Julien Fontanet 6cb03dded1 feat(xo-server-auth-saml): 0.8.0 2020-04-08 13:58:25 +02:00
Julien Fontanet 4752ec1b67 fix(CHANGELOG.unreleased): xo-server-saml → xo-server-auth-saml 2020-04-08 13:58:18 +02:00
Pierre Donias e641371544 feat(xo-server/patches): debounce listMissingPatches for XS (#4911) 2020-04-07 11:18:58 +02:00
Nicolas Raynaud 8d9a7e9af1 fix(xo-server/xosan): fix SR size limit (#4910) 2020-04-07 09:54:14 +02:00
Julien Fontanet 2b8e9bf887 feat(auth-ldap): support strategyOptions from static config 2020-04-06 15:17:14 +02:00
Julien Fontanet a16c55c679 fix(xo-web/utils/format*): never throw (#4909)
These functions previously thew if the param was not a number.

This can breaks the UI, as a work-around, this change logs the error and returns a default value.
2020-04-06 14:09:55 +02:00
badrAZ 9a72c40149 feat(audit,xo-server): blockedList can be configure via xo-server (#4897)
Fixes #4854
See #4844
2020-04-06 11:47:09 +02:00
Julien Fontanet 8424fc4c19 fix(xen-api,xo-server): fix compatibility with XS 6.5 and Node 12
Fixes #4906
2020-04-02 16:07:54 +02:00
badrAZ 9f29a047a7 feat(xo-web/sorted-table): make url state dynamic (#4641)
See #4564
2020-04-02 09:17:37 +02:00
Pierre Donias af4904ce8d chore(xo-web,xo-server): move "snapshot before" feature to the client (#4893)
From xo-server's API's point of view, it makes more sense for the "snapshot before" feature to be implemented in xo-web since snapshotting a VM is a whole independent process on its own that requires its own API permissions.

Making this change will be especially useful to not over-complicate the permissions checks for the incoming "Self Service snapshots" feature.

See #3693
2020-04-01 14:10:35 +02:00
Rajaa.BARHTAOUI 6f2a323063 feat(xo-web/vm/disks): add bulk migration (#4877)
See #4455
2020-04-01 11:46:01 +02:00
Rajaa.BARHTAOUI 1da8ecfaac feat(xo-web): VDI migration: remove 'Migrate all VDIs' checkbox (#4876)
See #4455
2020-04-01 09:51:17 +02:00
Rajaa.BARHTAOUI 1ba386bbd2 feat: release 5.45.0 (#4902) 2020-03-31 18:11:33 +02:00
Julien Fontanet d00d791cda feat(@xen-orchestra/upload-ova): 0.1.3 2020-03-31 17:49:25 +02:00
Julien Fontanet 51aabd7b21 feat(xo-vmdk-to-vhd): 1.1.1
Re-release of 1.0.1 because an erroneous 1.1.0 has been published which prevents it from being matched by `^1.0.1`.
2020-03-31 17:48:06 +02:00
Julien Fontanet 7840c3bdc8 feat(@xen-orchestra/upload-ova): 0.1.2 2020-03-31 17:34:30 +02:00
Julien Fontanet 07d13002b0 feat(xo-vmdk-to-vhd): 1.0.1 2020-03-31 17:33:28 +02:00
Julien Fontanet 23abe2ba06 fix(xo-vmdk-to-vhd): tmp is a dev dep 2020-03-31 17:32:43 +02:00
Julien Fontanet 4d73821d21 fix(xo-vmdk-to-vhd): add missing dep lodash 2020-03-31 17:31:40 +02:00
Julien Fontanet f2687cf807 fix(xo-vmdk-to-vhd): add missing dep xml2js 2020-03-31 17:30:31 +02:00
Julien Fontanet 8abce0d4cf feat(@xen-orchestra/upload-ova): 0.1.1 2020-03-31 17:21:56 +02:00
Julien Fontanet 62ad3848c4 fix(upload-ova): add shebang to bin
Also set executable permission even if not necessary when installed via npm.
2020-03-31 17:21:20 +02:00
Rajaa.BARHTAOUI 521e9969f1 feat: technical release (patch) (#4901) 2020-03-31 16:04:21 +02:00
Nicolas Raynaud 5ee1ceced3 feat(upload-ova): new CLI to import OVA VMs (#3630) 2020-03-31 14:44:10 +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
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
Julien Fontanet 5142bf4338 chore: update dependencies 2019-12-21 13:36:55 +01:00
Rajaa.BARHTAOUI e3532612ff feat: release 5.42.0 (#4714) 2019-12-20 12:33:02 +01:00
Pierre Donias d25e403233 fix(xo-web/remotes): refresh remote subscription right after an edition
And keep the subscription refresh after the `remote.test` call as well
2019-12-19 10:01:10 +01:00
Pierre Donias 8a5580eae5 fix(xo-web/remotes): SMB domain default value 2019-12-19 10:01:10 +01:00
Pierre Donias cf1251ad7b fix(xo-web/remotes/edit): reset form before populating it with remote
Otherwise, the inputs that have already been edited by the user aren't properly
overwritten by the remote's values
2019-12-19 10:01:10 +01:00
Pierre Donias 4b1d0e8786 chore(xo-web/remotes): remove *s in placeholders since they can be confusing
See support#1974
2019-12-19 10:01:10 +01:00
Pierre Donias b6e99ce4a6 fix(xo-web/remotes): simplify SMB host inputs patterns 2019-12-19 10:01:10 +01:00
Rajaa.BARHTAOUI 920def30d7 feat: technical release (#4711) 2019-12-18 14:23:04 +01:00
GHEMID Mohamed 3839aa7419 feat(xo-web/recipes): hub recipes (#4695)
See xoa#43

Kubernetes cluster recipe
2019-12-16 16:39:17 +01:00
Rajaa.BARHTAOUI 8fde720f02 feat(xo-web/xoa): display XOA build number (#4694)
Fixes #4693
2019-12-12 16:12:26 +01:00
Julien Fontanet c6dfaa30b5 feat(xo-server/blocked-at): increase threshold to 1s
Should be enough to detect problems without flooding the logs.
2019-12-11 10:20:59 +01:00
Julien Fontanet 0d4975ba0f feat(xo-server/blocked-at): expose settings in config 2019-12-11 10:20:32 +01:00
Julien Fontanet 77325c98a6 feat(xo-server): use blocked-at instead of blocked
It provides more info regarding why the event loop was blocked.

It could not be used before because it requires Node >= 8.
2019-12-11 10:13:39 +01:00
Julien Fontanet 01dc088a6f feat(xo-server/blocked): use ms to format the time 2019-12-11 10:10:35 +01:00
Julien Fontanet c20e9820fe feat(xo-server/workers): expose options in config 2019-12-10 12:03:18 +01:00
Julien Fontanet d255c116dd feat(backups-cli): create-symlink-index command
```
> xo-backups create-symlink-indexes ./xo-vm-backups vm.name_label
> ls ./xo-vm-backups/indexes/vm.name_label
Debian\ 9.5\ 64bit\ web9 -> ../../c60dc26a-49e8-be58-6ae4-175cf03b19d5/
Prod\ VM -> ../../1498796a-3d23-d0cc-74be-b25d6e598c03/
```
2019-12-09 16:36:21 +01:00
Julien Fontanet 2c1da3458a chore(backups-cli): move utils in their own module 2019-12-09 16:36:19 +01:00
Julien Fontanet 8017e42797 feat(xo-server): passport strategies can be unregistered (#4702)
Now all authentication plugins can be unloaded.
2019-12-09 10:51:35 +01:00
Julien Fontanet c162a7d3b1 feat(xo-server): configurable passport strategies name/label 2019-12-06 12:27:22 +01:00
Julien Fontanet d759d3dfee chore(xo-server/setUpPassport): handle unchecked paths first 2019-12-05 17:06:36 +01:00
Julien Fontanet daecf4db14 chore(xo-server/setUpPassport): remove unnecessary returns 2019-12-05 17:06:26 +01:00
Julien Fontanet 1e8318598a chore: update dependencies 2019-12-05 11:37:24 +01:00
Julien Fontanet 53450d1160 feat: autoformat TypeScript and Markdown files 2019-12-04 17:44:56 +01:00
Julien Fontanet c0049b3223 chore: format Markdown files with Prettier 2019-12-04 17:18:47 +01:00
Julien Fontanet 3ea9ce0270 feat(vhd-cli): 0.3.1 2019-12-04 12:23:15 +01:00
BenjiReis bb18ffd9e7 feat(xo-web/new/network): private network on bond and VLAN (#4682) 2019-12-03 16:54:19 +01:00
Julien Fontanet 1064c04ab8 feat(docs/xoa): add unsecure deploy variant 2019-12-03 13:09:18 +01:00
Julien Fontanet 2d84027a59 feat(docs/xoa): simpler deploy command 2019-12-03 12:58:06 +01:00
Julien Fontanet 98680508d3 feat(docs/xoa): ensure curl display errors 2019-12-03 12:57:06 +01:00
Julien Fontanet 74cbec468f feat(docs/xoa): use HTTPS for deploy 2019-12-03 12:55:38 +01:00
Rajaa.BARHTAOUI 31e89b0868 fix(xo-web): don't show a spinner on empty selectors (#4639)
Fixes #4525
2019-12-03 10:01:25 +01:00
Julien Fontanet c12a7a6319 feat(PULL_REQUEST_TEMPLATE): remove strikethrough
This was cumbersome to use, items should simply stay unchecked if not intended to be implemented.
2019-12-02 16:21:04 +01:00
Jon Sands 82b0df6058 feat(docs/delta): add note about snapshots (#4691) 2019-12-02 10:35:04 +01:00
Rajaa.BARHTAOUI b6bd67b62f feat: release 5.41.0 (#4689) 2019-11-29 16:55:44 +01:00
Julien Fontanet 877226014d feat(xo-web): 5.53.3 2019-11-29 15:58:04 +01:00
Julien Fontanet 7572d306a0 fix(xo-web/host/advanced): encode hostname in telemetry URL 2019-11-29 15:57:50 +01:00
Julien Fontanet f2f4573064 fix(xo-web/host/advanced): add trailing slash to telemetry URL 2019-11-29 15:57:01 +01:00
Julien Fontanet b1641edff6 feat(xo-web): 5.53.2 2019-11-29 14:55:32 +01:00
Julien Fontanet b5147256e9 fix(xo-web/host/advanced): fix telemetry URL 2019-11-29 14:44:13 +01:00
Julien Fontanet 06f596adc6 feat(xo-web): 5.53.1 2019-11-29 13:53:42 +01:00
HamadaBrest 1f3b54e0c4 fix(xo-web/host): recheck telemetry state after install (#4686) 2019-11-29 13:52:27 +01:00
Rajaa.BARHTAOUI 2ddfbe8566 feat: technical release (#4685) 2019-11-28 16:58:30 +01:00
HamadaBrest c61a118e4f feat(xo-web/host): advanced live telemetry (#4680) 2019-11-28 14:52:01 +01:00
Nicolas Raynaud d69e61a634 feat(xo-web,xo-server): ability to import a VHD/VMDK disk (#4138) 2019-11-28 11:35:31 +01:00
Julien Fontanet 14f0cbaec6 fix(docs/from sources): no need to configure / mount point 2019-11-27 20:25:00 +01:00
Bill Gertz b313eb14ee fix(docs/configuration): hosthostname (#4681)
The attribute `hostname` is incorrectly documented as `host`. Updated all occurrences of attribute `host` to `hostname`.
2019-11-26 14:38:33 +01:00
Julien Fontanet 7b47e40244 fix(docs/from sources): dont use .xo-server.toml 2019-11-26 14:12:10 +01:00
Julien Fontanet b52204817d feat(xo-server): configurable sign in page (#4678)
See xoa-support#1940
2019-11-26 13:27:13 +01:00
Julien Fontanet 377552103e fix(xo-server/config): maxMergedDeltasPerRun position
Introduced by 688b65ccd
2019-11-26 11:55:25 +01:00
Julien Fontanet 688b65ccde feat(xo-server/backups-ng): limit number of gc-ed deltas (#4674)
Merging multiple VHDs is currently a slow process which could be optimized by doing a single merge of a synthetic delta.

Until this is implement, the number of garbage collected deltas should be limited to avoid taking too much time (and possibly interrupted jobs) in case of an important retention change.
2019-11-26 11:29:55 +01:00
badrAZ 6cb4faf33d feat(xo-web/log): add log schedule to bug report (#4676) 2019-11-26 11:23:24 +01:00
badrAZ 78b83bb901 feat(xo-server/metadata-backups): clear backup listing cache on change (#4672)
See 471f39741
2019-11-26 10:34:26 +01:00
badrAZ 9ff6f60b66 fix(xo-server/metadata-backups): add 10m timeout to avoid stuck jobs (#4666)
See #4657
2019-11-25 16:26:11 +01:00
Julien Fontanet 624e10ed15 feat(xo-server-auth-saml): disableRequestedAuthnContext (#4675)
Fixes xoa-support#1940
2019-11-25 15:05:48 +01:00
badrAZ 19e10bbb53 feat(backup): report recipients configurable in backup settings (#4646)
Fixes #4581
2019-11-25 14:49:17 +01:00
Julien Fontanet cca945e05b fix(xo-server): remove overzealous changes
Bug introduced in 21901f2a7

As usual, thanks @Danp2 for your report :-)
2019-11-25 14:10:12 +01:00
Julien Fontanet 21901f2a75 chore: dont wrap unnecessary with fromCallback 2019-11-25 12:34:21 +01:00
Julien Fontanet ef7f943eee chore(xo-server/index): use Array#forEach lodash.forOwn and ensureArray 2019-11-25 12:10:52 +01:00
Julien Fontanet ec1062f9f2 chore(xo-server-auth-ldap): centralize default settings 2019-11-25 09:25:05 +01:00
Pierre Donias 2f67ed3138 fix(fs/Local#getInfo): remove NaN values (#4671)
Introduced by e34a0a6e33

NaNs were turned into nulls when sent to the client which was making
human-format throw a value must be a number error.
2019-11-22 17:16:23 +01:00
Rajaa.BARHTAOUI ce912db30e feat(CHANGELOG): 5.40.2 (#4669) 2019-11-22 11:40:40 +01:00
Julien Fontanet 41d790f346 feat(xo-server): 5.52.1 2019-11-22 11:33:38 +01:00
Julien Fontanet bf426e15ec fix(xo-server/proxies): fix WS error handling
Fixes #4670

Introduced by 56d63b10e4
2019-11-22 11:22:12 +01:00
badrAZ e4403baeb9 fix(xo-server/backup-ng): fix pool metadata backups not debounced (#4668) 2019-11-22 10:04:13 +01:00
Julien Fontanet 61101b00a1 feat(xo-server-auth-ldap): add group filter example for AD 2019-11-20 21:37:22 +01:00
Julien Fontanet 69f8ffcfeb feat(xen-api/examples/import-vdi): guess VHD size if necessary 2019-11-20 12:12:12 +01:00
Rajaa.BARHTAOUI 6b8042291c feat: technical release (#4667) 2019-11-20 12:04:53 +01:00
Julien Fontanet ffc0c83b50 fix: revert http-request-plus to 0.8
The new version breaks some features like VDI import.

This will be fixed this directly in `http-request-plus` but in the meantime 0.8 will be used.

Fixes #4640
2019-11-19 18:15:23 +01:00
badrAZ 8ccd4c269a feat(xo-web/logs): open bug even if support panel doesnt respond (#4654) 2019-11-19 16:10:29 +01:00
Julien Fontanet 934ec86f93 feat(vhd-lib/_readChunk): explicit error when read too much 2019-11-19 15:51:21 +01:00
Julien Fontanet 23be38b5fa chore(vhd-lib/_readChunk): dont clean twice on end 2019-11-19 15:49:56 +01:00
Rajaa.BARHTAOUI fe7f74e46b feat(xo-web): store SortedTable param in URL (#4637)
Fixes #4542
2019-11-19 15:25:57 +01:00
Pierre Donias a3fd78f8e2 fix(doc): web hooks menu link (#4665) 2019-11-19 10:30:44 +01:00
Pierre Donias 137bad6f7b feat(xo-server-web-hooks): web hooks on XO API calls (#3155)
Fixes #1946
2019-11-15 16:17:17 +01:00
Julien Fontanet 17df6fc764 fix(xen-api): Node warning promise rejected with non-error (#4659)
Not a real problems but triggered a lot of warnings which could be very verbose in application logs.
2019-11-15 15:42:03 +01:00
badrAZ 2e51c8a124 fix(xo-server/backup-ng): handle timeouts larger than 596h (#4663)
Fixes #4662
2019-11-15 15:06:57 +01:00
Julien Fontanet 5588a46366 feat(xo-server/proxies): use proxy config (#4655) 2019-11-15 14:44:03 +01:00
Julien Fontanet a8122f9add feat(normalize-packages): replace vars in READMEs 2019-11-15 11:25:51 +01:00
Julien Fontanet 5568be91d2 chore: format with Prettier
Related to 2ec964178
2019-11-15 11:05:30 +01:00
Julien Fontanet a04bd6f93c fix(docs/configuration): convert redirectToHttps to TOML 2019-11-14 15:32:24 +01:00
Julien Fontanet 56d63b10e4 fix(xo-server/proxies): correctly handle errors 2019-11-14 15:31:55 +01:00
Julien Fontanet 2c97643b10 feat(xo-server/Xapi#_assertHealthyVdiChains): configurable tolerance (#4651)
Fixes #4124

Related to xoa-support#1921

Only configurable globally (not per backup job) for the moment with the `xapiOptions.maxUncoalescedVdis` setting.
2019-11-14 14:34:32 +01:00
marcpezin 679f403648 feat(docs/xoa): UI support page (#4650) 2019-11-14 13:10:00 +01:00
Julien Fontanet d482c707f6 chore(docs/xoa): various improvements 2019-11-14 12:30:47 +01:00
Julien Fontanet 2ec9641783 chore: update dependencies 2019-11-13 17:15:42 +01:00
badrAZ dab1788a3b feat(logs/backup-ng): support ticket with attached log (#4201)
Related to support-panel#24
2019-11-13 15:57:52 +01:00
Julien Fontanet 47bb79cce1 feat(server/Xo): remove #httpProxy in favor of `#hasOwnHttpProxy 2019-11-12 16:51:50 +01:00
badrAZ 41dbc20be9 fix(xo-server/plugins): try empty config if none provided (#4647)
Required by #4581

Plugins with optional configuration should be loadable without explicit user configuration.
2019-11-08 15:27:22 +01:00
Julien Fontanet 10a631ec96 fix(log/README): catchGlobalErrors expect a logger 2019-11-08 11:07:42 +01:00
Julien Fontanet 830e5aed96 feat(log/README): { createLogger }
Related to 0b90befda
2019-11-08 09:58:15 +01:00
Julien Fontanet 7db573885b fix(cron/tests): mock Date.now() (#4628)
Related to changes in #4623 (and 07526efe6).
2019-11-07 11:37:53 +01:00
Julien Fontanet a74d56ebc6 feat: always specify required Node version 2019-11-07 10:18:05 +01:00
Julien Fontanet ff7d84297e fix(server/plugins): prevent duplicate loading (#4645)
Related to xoa-support#1905
2019-11-06 15:15:13 +01:00
Julien Fontanet 3a76509fe9 chore(xo-server/xapi): use promise-toolbox/retry (#4635)
Instead of custom implementation.
2019-11-06 10:23:06 +01:00
Julien Fontanet ac4de9ab0f chore(backups-cli): move clean-vms in dedicated module 2019-11-05 15:29:49 +01:00
badrAZ 471f397418 feat(xo-server/backup-ng): clear "_listVmBackupsOnRemote" cache on change (#4580)
See #4539

This PR gives the possibility to clear the backup list cache using the API and it makes sure that the cache is cleaned after a backup or its deletion on a remote.
2019-11-05 09:44:50 +01:00
badrAZ 73bbdf6d4e fix(xo-web): missing "noopener noreferrer" (#4643)
Anchors with `target='_blank'` need `rel='noopener noreferrer'`
2019-11-04 15:24:01 +01:00
Julien Fontanet 7f26aea585 feat(backups-cli): dont report compressed XVAs as broken (#4642)
Detect compressed XVAs and don't try to validate them with tar heuristic.
2019-11-04 14:33:50 +01:00
Julien Fontanet 1c767b709f chore(xo-server/setUpApi): fix void lint 2019-10-31 16:45:17 +01:00
badrAZ 0ced82c885 fix(xo-web/sorted-table): missing "noopener noreferrer" (#4636) 2019-10-31 11:05:50 +01:00
BenjiReis 21dd195b0d fix(xo-web): prevent private network creation on bond slave PIFs (#4633)
Fixes xcp-ng/xcp#300
2019-10-30 17:17:18 +01:00
badrAZ 6aa6cfba8e fix(xo-server): failed metadata backup reported as successful (#4598)
Fixes #4596
2019-10-30 17:08:56 +01:00
Julien Fontanet fd7d52d38b chore: update dependencies 2019-10-30 14:06:50 +01:00
Julien Fontanet a47bb14364 chore(vhd-lib): prefix private methods with _ (#4621)
So they are clearly identified, which will help us with a future refactorization.
2019-10-30 10:18:29 +01:00
Julien Fontanet d6e6fa5735 chore: use Function#bind instead of lodash/bind (#4602) (#4614)
Support is good enough: https://kangax.github.io/compat-table/es5/#test-Function.prototype.bind
2019-10-30 09:50:15 +01:00
Rajaa.BARHTAOUI 46da11a52e chore(CHANGELOG): 5.40.1 (#4632) 2019-10-29 15:24:05 +01:00
Pierre Donias 68e3dc21e4 fix(xo-web): update checks for Cloud plugin (#4631)
See #4615
Introduced by fd06374365

- Every time we checked if the Cloud plugin was installed, we now need to check
  if the XOA plugin is installed
- Update the warning messages mentioning the Cloud plugin
2019-10-29 14:25:49 +01:00
Julien Fontanet 7232cc45b4 feat(scripts/bump-pkg): dont create version tags 2019-10-29 13:59:27 +01:00
Julien Fontanet be5a297248 feat(xo-server/Xo#httpProxy): expose 2019-10-29 12:01:16 +01:00
Rajaa.BARHTAOUI 257031b1bc chore(CHANGELOG): 5.40.0 (#4630) 2019-10-29 10:36:25 +01:00
Julien Fontanet c9db9fa17a fix(vhd-lib/Vhd#readHeaderAndFooter): always throw AssertionErrors 2019-10-28 15:58:22 +01:00
Julien Fontanet 13f961a422 feat(server): new setHttpProxy internal method
Related to xoa#38
2019-10-28 14:20:07 +01:00
Rajaa.BARHTAOUI 3b38e0c4e1 chore: patch release (#4629) 2019-10-25 16:40:36 +02:00
Julien Fontanet 07526efe61 fix(cron): dont forget to compute next date
Introduced by #4626
2019-10-25 15:49:05 +02:00
badrAZ 8753c02adb chore: technical release (#4627) 2019-10-25 15:47:40 +02:00
Julien Fontanet 6a0bbfa447 chore(log): always build on install
Necessary because used by other modules during their tests.
2019-10-25 13:29:21 +02:00
Julien Fontanet 21faaeb33d fix(server/scheduling): start/stop schedules after import (#4624) 2019-10-25 10:44:36 +02:00
Julien Fontanet 0525fc5909 fix(cron): prevent early runs (#4626)
Fixes #4625
2019-10-25 10:22:24 +02:00
badrAZ a1a53bb285 feat(backup-ng): offline snapshotless backup (#4470)
Fixes #3449
2019-10-25 09:45:45 +02:00
Rajaa.BARHTAOUI 0c453c4415 feat(xo-web/backup): hide legacy backup menu entry (#4476)
Fixes #4467
2019-10-24 17:19:16 +02:00
HamadaBrest d0406f9736 feat(xo-web/hub): update existing template (#4613)
See xoa#35
2019-10-24 15:11:22 +02:00
BenjiReis ba74b8603d feat(xo-server-transport-icinga2): Icinga2 support (#4573)
Fixes #4563
2019-10-24 14:35:02 +02:00
Julien Fontanet c675a4d61d chore(yarn.lock): remove unnecessary entry 2019-10-24 14:16:40 +02:00
Julien Fontanet 965c45bc70 chore(vhd-lib): use @xen-orchestra/log 2019-10-24 12:18:01 +02:00
Rajaa.BARHTAOUI 139a22602a feat(xo-web/xoa/support): expose support tunnel (#4616)
Fixes #4513
2019-10-24 09:51:22 +02:00
Julien Fontanet e0e4969198 fix(backups-cli): should be compatible with Node 7.10 2019-10-23 17:53:07 +02:00
Julien Fontanet 08d69d95b3 chore(server/backup): explicit use of SR UUID (#4622) 2019-10-23 15:38:51 +02:00
HamadaBrest 4e6c507ba9 feat(xo-web/hub): extra hub template info (#4593)
See xoa#35
2019-10-23 12:09:11 +02:00
HamadaBrest fd06374365 feat(xo-server-cloud): remove (#4615)
All its features were irrelevant for the open source version and have been merged into `xo-server-xoa`.

See xoa#39
2019-10-22 16:03:51 +02:00
Julien Fontanet a07ebc636a fix(docs/from sources): show Node 8.16.2 2019-10-20 12:43:06 +02:00
BenjiReis 4c151ac9aa chore(xo-server-sdn-controller): complete refactor (#4570) 2019-10-18 17:04:26 +02:00
HamadaBrest 05c425698f feat(xo-web/hub): ability to select SR in hub VM installation (#4571) 2019-10-16 15:34:43 +02:00
Julien Fontanet 2a961979e6 chore: use String#trim instead of lodash/trim (#4602)
Support is good enough: https://kangax.github.io/compat-table/es5/#test-String_properties_and_methods
2019-10-15 09:43:20 +02:00
Pierre Donias 211ede92cc fix(xo-web/new/sr): reattach SR (#4550)
See #4546
2019-10-14 14:57:24 +02:00
Julien Fontanet 256af03772 chore: use typeof instead of lodash/isString (#4603) 2019-10-14 13:58:58 +02:00
Julien Fontanet 654fd5a4f9 chore: use typeof instead of lodash/isBoolean (#4604) 2019-10-14 13:51:45 +02:00
Julien Fontanet 541d90e49f fix(xo-server-recover-account): explicit appDir 2019-10-12 17:07:14 +02:00
Julien Fontanet 974e7038e7 chore(backups-cli): dont fail on missing dirs 2019-10-12 00:49:16 +02:00
Pierre Donias e2f5b30aa9 fix(xo-server/patching): install XCP-ng patches host by host (#4532)
Fixes #4468

To prevent issues where 2 hosts try to modify the XAPI DB at the same time
2019-10-12 00:39:17 +02:00
Julien Fontanet 3483e7d9e0 chore: update dependencies 2019-10-11 17:15:25 +02:00
Julien Fontanet 56cb20a1af chore: use typeof instead of lodash/isFunction (#4587) 2019-10-11 15:16:37 +02:00
Rajaa.BARHTAOUI 64929653dd feat(xo-server): upgrade to execa@2.0.5 (#4584) 2019-10-11 15:01:56 +02:00
Julien Fontanet c955da9bc6 feat(backups-cli): lowlevel tool to help with backups (#4556) 2019-10-11 14:48:37 +02:00
Julien Fontanet 291354fa8e chore: use Object.assign instead of lodash/assign (#4585)
Support is good enough:
- https://node.green/#ES2015-built-in-extensions-Object-static-methods-Object-assign
- https://kangax.github.io/compat-table/es6/#test-Object_static_methods
2019-10-11 14:43:38 +02:00
Julien Fontanet 905d736512 chore: use Array.isArray instead of lodash/isArray (#4586)
Support is good enough:
- https://node.green/#ES2015-built-ins-Proxy-Array-isArray-support
- https://kangax.github.io/compat-table/es5/#test-Array_methods
2019-10-11 14:29:01 +02:00
Rajaa.BARHTAOUI 3406d6e2a9 chore(CHANGELOG): 5.39.1 (#4597) 2019-10-11 10:33:18 +02:00
BARHTAOUI fc10b5ffb9 chore(CHANGELOG): update next 2019-10-10 16:03:20 +02:00
BARHTAOUI f89c313166 feat(xo-web): 5.50.3 2019-10-10 16:03:20 +02:00
Rajaa.BARHTAOUI 7c734168d0 feat(xo-web/xoa): expose 'xoa check' on the UI (#4574)
See #4513
2019-10-10 13:49:17 +02:00
HamadaBrest 1e7bfec2ce feat(xo-web/hub): delete template by namespace instead of ID (#4594) 2019-10-10 10:36:07 +02:00
badrAZ 1eb0603b4e chore(xo-server-test/backup-ng): consolidate default values (#4544)
Required for #4470
2019-10-08 14:34:11 +02:00
badrAZ 4b32730ce8 feat(xo-web/vm): improve invalid cores per socket feedback (#4187)
Fixes #4120
2019-10-08 11:05:11 +02:00
BenjiReis ad083c1d9b chore(xo-server-sdn-controller): better cert creation code (#4582) 2019-10-07 12:12:01 +02:00
BenjiReis b4f84c2de2 chore(xo-server-sdn-controller): arrow functions when possible (#4583) 2019-10-07 11:29:30 +02:00
badrAZ fc17443ce4 fix(xo-web/vm/advanced): error on displaying ACL users (#4578) 2019-10-07 11:08:11 +02:00
Julien Fontanet 342ae06b21 chore(xo-sdn-controller): minor formatting fix 2019-10-07 10:19:34 +02:00
Julien Fontanet 093fb7f959 fix(xo-server-logs): explicit appDir
May fix #4576
2019-10-03 16:02:10 +02:00
Julien Fontanet f6472424ad fix(eslint): disable lines-between-class-members rule 2019-10-02 15:52:51 +02:00
Julien Fontanet 31ed3767c6 chore: fix some lint
Mainly: `obj['prop']` → `obj.prop`
2019-10-02 15:45:32 +02:00
marcpezin 366acb65ea doc(updater): release channels (#4572) 2019-10-02 15:24:45 +02:00
Pierre Donias 7c6946931b chore(xo-web): PascalCase NotFound component (#4567)
https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md
2019-10-01 17:21:00 +02:00
HamadaBrest 5d971433a5 fix(xo-web/new-vm/self): template selection (#4568)
Fixes #4565
Introduced by 9efc3dd1fb
2019-10-01 16:59:59 +02:00
Rajaa.BARHTAOUI 05264b326b chore(CHANGELOG): 5.39.0 (#4561) 2019-09-30 16:08:56 +02:00
BARHTAOUI fdd5c6bfd8 chore(CHANGELOG): update next 2019-09-30 15:13:05 +02:00
BARHTAOUI 42c3528c2f feat(xo-web): 5.50.2 2019-09-30 15:13:05 +02:00
HamadaBrest 18640714f1 fix(xo-web/hub/resource): "remove" button icon (#4559) 2019-09-30 14:43:31 +02:00
HamadaBrest cda4d3399b fix(xo-web/hub): responsive hub VM templates (#4558)
Fixes #4557
2019-09-30 14:42:01 +02:00
Julien Fontanet 4da8af6e69 fix(log/configure): process nested transport 2019-09-27 14:55:26 +02:00
Julien Fontanet b535565612 feat(@xen-orchestra/log): 0.2.0 2019-09-27 14:29:34 +02:00
Julien Fontanet bef39b8a96 fix(log): support DEBUG and NODE_DEBUG when both defined 2019-09-27 14:26:19 +02:00
Julien Fontanet fb2502a031 feat(log): support env var LOG_LEVEL 2019-09-27 14:23:27 +02:00
Julien Fontanet 0b90befda1 feat(log): also export createLogger symbol 2019-09-27 13:59:44 +02:00
Julien Fontanet f9800f104a feat(log/console): display data inline 2019-09-27 13:59:03 +02:00
Julien Fontanet 99134cc381 Merge pull request #4554 from vatesfr/release
Technical release
2019-09-27 10:22:49 +02:00
BARHTAOUI 66ca08da6d chore(CHANGELOG): update next 2019-09-27 10:15:46 +02:00
BARHTAOUI 5eb7ece6ba feat(xo-web): 5.50.1 2019-09-27 09:59:05 +02:00
1073 changed files with 62528 additions and 35776 deletions
+9 -14
View File
@@ -1,13 +1,5 @@
module.exports = {
extends: [
'plugin:eslint-comments/recommended',
'standard',
'standard-jsx',
'prettier',
'prettier/standard',
'prettier/react',
],
extends: ['plugin:eslint-comments/recommended', 'standard', 'standard-jsx', 'prettier'],
globals: {
__DEV__: true,
$Dict: true,
@@ -21,7 +13,7 @@ module.exports = {
overrides: [
{
files: ['cli.js', '*-cli.js', 'packages/*cli*/**/*.js'],
files: ['cli.js', '*-cli.js', '**/*cli*/**/*.js'],
rules: {
'no-console': 'off',
},
@@ -40,10 +32,13 @@ module.exports = {
'react/jsx-handler-names': 'off',
// disabled because not always relevant, we might reconsider in the future
//
// enabled by https://github.com/standard/eslint-config-standard/commit/319b177750899d4525eb1210686f6aca96190b2f
//
// example: https://github.com/vatesfr/xen-orchestra/blob/31ed3767c67044ca445658eb6b560718972402f2/packages/xen-api/src/index.js#L156-L157
'lines-between-class-members': 'off',
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-var': 'error',
'node/no-extraneous-import': 'error',
'node/no-extraneous-require': 'error',
'prefer-const': 'error',
},
}
+4
View File
@@ -4,11 +4,15 @@
/lerna-debug.log
/lerna-debug.log.*
/@vates/*/dist/
/@vates/*/node_modules/
/@xen-orchestra/*/dist/
/@xen-orchestra/*/node_modules/
/packages/*/dist/
/packages/*/node_modules/
/@xen-orchestra/proxy/src/app/mixins/index.js
/packages/vhd-cli/src/commands/index.js
/packages/xen-api/examples/node_modules/
+6 -1
View File
@@ -1,6 +1,11 @@
module.exports = {
arrowParens: 'avoid',
jsxSingleQuote: true,
semi: false,
singleQuote: true,
trailingComma: 'es5',
// 2020-11-24: Requested by nraynaud and approved by the rest of the team
//
// https://team.vates.fr/vates/pl/a1i8af1b9id7pgzm3jcg4toacy
printWidth: 120,
}
+1 -2
View File
@@ -1,7 +1,6 @@
language: node_js
node_js:
#- stable # disable for now due to an issue of indirect dep upath with Node 9
- 8
- 14
# Use containers.
# http://docs.travis-ci.com/user/workers/container-based-infrastructure/
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+46
View File
@@ -0,0 +1,46 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/coalesce-calls
[![Package Version](https://badgen.net/npm/v/@vates/coalesce-calls)](https://npmjs.org/package/@vates/coalesce-calls) ![License](https://badgen.net/npm/license/@vates/coalesce-calls) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/coalesce-calls)](https://bundlephobia.com/result?p=@vates/coalesce-calls) [![Node compatibility](https://badgen.net/npm/node/@vates/coalesce-calls)](https://npmjs.org/package/@vates/coalesce-calls)
> Wraps an async function so that concurrent calls will be coalesced
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/coalesce-calls):
```
> npm install --save @vates/coalesce-calls
```
## Usage
```js
import { coalesceCalls } from '@vates/coalesce-calls'
const connect = coalesceCalls(async function () {
// async operation
})
connect()
// the previous promise result will be returned if the operation is not
// complete yet
connect()
```
## 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
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+13
View File
@@ -0,0 +1,13 @@
```js
import { coalesceCalls } from '@vates/coalesce-calls'
const connect = coalesceCalls(async function () {
// async operation
})
connect()
// the previous promise result will be returned if the operation is not
// complete yet
connect()
```
+14
View File
@@ -0,0 +1,14 @@
exports.coalesceCalls = function (fn) {
let promise
const clean = () => {
promise = undefined
}
return function () {
if (promise !== undefined) {
return promise
}
promise = fn.apply(this, arguments)
promise.then(clean, clean)
return promise
}
}
+33
View File
@@ -0,0 +1,33 @@
/* eslint-env jest */
const { coalesceCalls } = require('./')
const pDefer = () => {
const r = {}
r.promise = new Promise((resolve, reject) => {
r.reject = reject
r.resolve = resolve
})
return r
}
describe('coalesceCalls', () => {
it('decorates an async function', async () => {
const fn = coalesceCalls(promise => promise)
const defer1 = pDefer()
const promise1 = fn(defer1.promise)
const defer2 = pDefer()
const promise2 = fn(defer2.promise)
defer1.resolve('foo')
expect(await promise1).toBe('foo')
expect(await promise2).toBe('foo')
const defer3 = pDefer()
const promise3 = fn(defer3.promise)
defer3.resolve('bar')
expect(await promise3).toBe('bar')
})
})
+38
View File
@@ -0,0 +1,38 @@
{
"private": false,
"name": "@vates/coalesce-calls",
"description": "Wraps an async function so that concurrent calls will be coalesced",
"keywords": [
"async",
"calls",
"coalesce",
"decorate",
"decorator",
"merge",
"promise",
"wrap",
"wrapper"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/coalesce-calls",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/coalesce-calls",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"files": [
"index.js"
],
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
},
"license": "ISC",
"version": "0.1.0",
"engines": {
"node": ">=8.10"
},
"scripts": {
"postversion": "npm publish --access public"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+81
View File
@@ -0,0 +1,81 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/compose
[![Package Version](https://badgen.net/npm/v/@vates/compose)](https://npmjs.org/package/@vates/compose) ![License](https://badgen.net/npm/license/@vates/compose) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/compose)](https://bundlephobia.com/result?p=@vates/compose) [![Node compatibility](https://badgen.net/npm/node/@vates/compose)](https://npmjs.org/package/@vates/compose)
> Compose functions from left to right
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/compose):
```
> npm install --save @vates/compose
```
## Usage
```js
import { compose } from '@vates/compose'
const add2 = x => x + 2
const mul3 = x => x * 3
// const f = x => mul3(add2(x))
const f = compose(add2, mul3)
console.log(f(5))
// → 21
```
> The call context (`this`) of the composed function is forwarded to all functions.
The first function is called with all arguments of the composed function:
```js
const add = (x, y) => x + y
const mul3 = x => x * 3
// const f = (x, y) => mul3(add(x, y))
const f = compose(add, mul3)
console.log(f(4, 5))
// → 27
```
Functions may also be passed in an array:
```js
const f = compose([add2, mul3])
```
Options can be passed as first parameter:
```js
const f = compose(
{
// compose async functions
async: true,
// compose from right to left
right: true,
},
[add2, mul3]
)
```
## 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
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+48
View File
@@ -0,0 +1,48 @@
```js
import { compose } from '@vates/compose'
const add2 = x => x + 2
const mul3 = x => x * 3
// const f = x => mul3(add2(x))
const f = compose(add2, mul3)
console.log(f(5))
// → 21
```
> The call context (`this`) of the composed function is forwarded to all functions.
The first function is called with all arguments of the composed function:
```js
const add = (x, y) => x + y
const mul3 = x => x * 3
// const f = (x, y) => mul3(add(x, y))
const f = compose(add, mul3)
console.log(f(4, 5))
// → 27
```
Functions may also be passed in an array:
```js
const f = compose([add2, mul3])
```
Options can be passed as first parameter:
```js
const f = compose(
{
// compose async functions
async: true,
// compose from right to left
right: true,
},
[add2, mul3]
)
```
+46
View File
@@ -0,0 +1,46 @@
'use strict'
const defaultOpts = { async: false, right: false }
exports.compose = function compose(opts, fns) {
if (Array.isArray(opts)) {
fns = opts
opts = defaultOpts
} else if (typeof opts === 'object') {
opts = Object.assign({}, defaultOpts, opts)
if (!Array.isArray(fns)) {
fns = Array.prototype.slice.call(arguments, 1)
}
} else {
fns = Array.from(arguments)
opts = defaultOpts
}
const n = fns.length
if (n === 0) {
throw new TypeError('at least one function must be passed')
}
if (n === 1) {
return fns[0]
}
if (opts.right) {
fns.reverse()
}
return opts.async
? async function () {
let value = await fns[0].apply(this, arguments)
for (let i = 1; i < n; ++i) {
value = await fns[i].call(this, value)
}
return value
}
: function () {
let value = fns[0].apply(this, arguments)
for (let i = 1; i < n; ++i) {
value = fns[i].call(this, value)
}
return value
}
}
+66
View File
@@ -0,0 +1,66 @@
/* eslint-env jest */
const { compose } = require('./')
const add2 = x => x + 2
const mul3 = x => x * 3
describe('compose()', () => {
it('throws when no functions is passed', () => {
expect(() => compose()).toThrow(TypeError)
expect(() => compose([])).toThrow(TypeError)
})
it('applies from left to right', () => {
expect(compose(add2, mul3)(5)).toBe(21)
})
it('accepts functions in an array', () => {
expect(compose([add2, mul3])(5)).toBe(21)
})
it('can apply from right to left', () => {
expect(compose({ right: true }, add2, mul3)(5)).toBe(17)
})
it('accepts options with functions in an array', () => {
expect(compose({ right: true }, [add2, mul3])(5)).toBe(17)
})
it('can compose async functions', async () => {
expect(
await compose(
{ async: true },
async x => x + 2,
async x => x * 3
)(5)
).toBe(21)
})
it('forwards all args to first function', () => {
expect.assertions(1)
const expectedArgs = [Math.random(), Math.random()]
compose(
(...args) => {
expect(args).toEqual(expectedArgs)
},
// add a second function to avoid the one function special case
Function.prototype
)(...expectedArgs)
})
it('forwards context to all functions', () => {
expect.assertions(2)
const expectedThis = {}
compose(
function () {
expect(this).toBe(expectedThis)
},
function () {
expect(this).toBe(expectedThis)
}
).call(expectedThis)
})
})
+24
View File
@@ -0,0 +1,24 @@
{
"private": false,
"name": "@vates/compose",
"description": "Compose functions from left to right",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/compose",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/compose",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
},
"license": "ISC",
"version": "2.0.0",
"engines": {
"node": ">=7.6"
},
"scripts": {
"postversion": "npm publish --access public"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+45
View File
@@ -0,0 +1,45 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/decorate-with
[![Package Version](https://badgen.net/npm/v/@vates/decorate-with)](https://npmjs.org/package/@vates/decorate-with) ![License](https://badgen.net/npm/license/@vates/decorate-with) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/decorate-with)](https://bundlephobia.com/result?p=@vates/decorate-with) [![Node compatibility](https://badgen.net/npm/node/@vates/decorate-with)](https://npmjs.org/package/@vates/decorate-with)
> Creates a decorator from a function wrapper
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/decorate-with):
```
> npm install --save @vates/decorate-with
```
## Usage
For instance, allows using Lodash's functions as decorators:
```js
import { decorateWith } from '@vates/decorate-with'
class Foo {
@decorateWith(lodash.debounce, 150)
bar() {
// body
}
}
```
## 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
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+12
View File
@@ -0,0 +1,12 @@
For instance, allows using Lodash's functions as decorators:
```js
import { decorateWith } from '@vates/decorate-with'
class Foo {
@decorateWith(lodash.debounce, 150)
bar() {
// body
}
}
```
+4
View File
@@ -0,0 +1,4 @@
exports.decorateWith = (fn, ...args) => (target, name, descriptor) => ({
...descriptor,
value: fn(descriptor.value, ...args),
})
+30
View File
@@ -0,0 +1,30 @@
{
"private": false,
"name": "@vates/decorate-with",
"description": "Creates a decorator from a function wrapper",
"keywords": [
"apply",
"decorator",
"factory",
"wrapper"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/decorate-with",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/decorate-with",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
},
"license": "ISC",
"version": "0.0.1",
"engines": {
"node": ">=8.10"
},
"scripts": {
"postversion": "npm publish --access public"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+89
View File
@@ -0,0 +1,89 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/disposable
[![Package Version](https://badgen.net/npm/v/@vates/disposable)](https://npmjs.org/package/@vates/disposable) ![License](https://badgen.net/npm/license/@vates/disposable) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/disposable)](https://bundlephobia.com/result?p=@vates/disposable) [![Node compatibility](https://badgen.net/npm/node/@vates/disposable)](https://npmjs.org/package/@vates/disposable)
> Utilities for disposables
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/disposable):
```
> npm install --save @vates/disposable
```
## Usage
This library contains utilities for disposables as defined by the [`promise-toolbox` library](https://github.com/JsCommunity/promise-toolbox#resource-management).
### `deduped(fn, keyFn)`
Creates a new function that wraps `fn` and instead of creating a new disposables at each call, returns copies of the same one when `keyFn` returns the same keys.
Those copies contains the same value and can be disposed independently, the source disposable will only be disposed when all copies are disposed.
`keyFn` is called with the same context and arguments as the wrapping function and must returns an array of keys which will be used to identify which disposables should be grouped together.
```js
import { deduped } from '@vates/disposable/deduped'
// the connection with the passed host will be established once at the first call, then, it will be shared with the next calls
const getConnection = deduped(async function (host)) {
const connection = new Connection(host)
return new Disposabe(connection, () => connection.close())
}, host => [host])
```
### `debounceResource(disposable, delay)`
Creates a new disposable with the same value and with a delayed disposer.
On calling this disposer, the source disposable will be disposed when the `delay` is passed.
```js
import { createDebounceResource } from '@vates/disposable/debounceResource'
const debounceResource = createDebounceResource()
// it will wait for 10 seconds before calling the disposer
using(debounceResource(getConnection(host), 10e3), connection => {})
```
### `debounceResource.flushAll()`
Disposes all delayed disposers and cancels the delaying of the disposables that are in usage.
```js
import { createDebounceResource } from '@vates/disposable/debounceResource'
const debounceResource = createDebounceResource()
const res1 = await debounceResource(res, 10e3)
const res2 = await debounceResource(res, 10e3)
const res3 = await debounceResource(res, 10e3)
rest1.dispose()
rest2.dispose()
// res3 is in usage
debounceResource.flushAll()
// res1 and res2 are immediately disposed
// res3 will be disposed immediately when its disposer will be called
```
## 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
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+56
View File
@@ -0,0 +1,56 @@
This library contains utilities for disposables as defined by the [`promise-toolbox` library](https://github.com/JsCommunity/promise-toolbox#resource-management).
### `deduped(fn, keyFn)`
Creates a new function that wraps `fn` and instead of creating a new disposables at each call, returns copies of the same one when `keyFn` returns the same keys.
Those copies contains the same value and can be disposed independently, the source disposable will only be disposed when all copies are disposed.
`keyFn` is called with the same context and arguments as the wrapping function and must returns an array of keys which will be used to identify which disposables should be grouped together.
```js
import { deduped } from '@vates/disposable/deduped'
// the connection with the passed host will be established once at the first call, then, it will be shared with the next calls
const getConnection = deduped(async function (host)) {
const connection = new Connection(host)
return new Disposabe(connection, () => connection.close())
}, host => [host])
```
### `debounceResource(disposable, delay)`
Creates a new disposable with the same value and with a delayed disposer.
On calling this disposer, the source disposable will be disposed when the `delay` is passed.
```js
import { createDebounceResource } from '@vates/disposable/debounceResource'
const debounceResource = createDebounceResource()
// it will wait for 10 seconds before calling the disposer
using(debounceResource(getConnection(host), 10e3), connection => {})
```
### `debounceResource.flushAll()`
Disposes all delayed disposers and cancels the delaying of the disposables that are in usage.
```js
import { createDebounceResource } from '@vates/disposable/debounceResource'
const debounceResource = createDebounceResource()
const res1 = await debounceResource(res, 10e3)
const res2 = await debounceResource(res, 10e3)
const res3 = await debounceResource(res, 10e3)
rest1.dispose()
rest2.dispose()
// res3 is in usage
debounceResource.flushAll()
// res1 and res2 are immediately disposed
// res3 will be disposed immediately when its disposer will be called
```
+56
View File
@@ -0,0 +1,56 @@
const { asyncMap } = require('@xen-orchestra/async-map')
const { createLogger } = require('@xen-orchestra/log')
const { warn } = createLogger('vates:disposable:debounceResource')
exports.createDebounceResource = () => {
const flushers = new Set()
async function debounceResource(pDisposable, delay = debounceResource.defaultDelay) {
if (delay === 0) {
return pDisposable
}
const disposable = await pDisposable
let timeoutId
const disposeWrapper = async () => {
if (timeoutId !== undefined) {
clearTimeout(timeoutId)
timeoutId = undefined
flushers.delete(flusher)
try {
await disposable.dispose()
} catch (error) {
warn(error)
}
}
}
const flusher = () => {
const shouldDisposeNow = timeoutId !== undefined
if (shouldDisposeNow) {
return disposeWrapper()
} else {
// will dispose ASAP
delay = 0
}
}
flushers.add(flusher)
return {
dispose() {
timeoutId = setTimeout(disposeWrapper, delay)
},
value: disposable.value,
}
}
debounceResource.flushAll = () => {
// iterate on a sync way in order to not remove a flusher added on processing flushers
const promise = asyncMap(flushers, flush => flush())
flushers.clear()
return promise
}
return debounceResource
}
@@ -0,0 +1,29 @@
/* eslint-env jest */
const { createDebounceResource } = require('./debounceResource')
jest.useFakeTimers()
describe('debounceResource()', () => {
it('calls the resource disposer after 10 seconds', async () => {
const debounceResource = createDebounceResource()
const delay = 10e3
const dispose = jest.fn()
const resource = await debounceResource(
Promise.resolve({
value: '',
dispose,
}),
delay
)
resource.dispose()
expect(dispose).not.toBeCalled()
jest.advanceTimersByTime(delay)
expect(dispose).toBeCalled()
})
})
+52
View File
@@ -0,0 +1,52 @@
const ensureArray = require('ensure-array')
const { MultiKeyMap } = require('@vates/multi-key-map')
function State(factory) {
this.factory = factory
this.users = 0
}
const call = fn => fn()
exports.deduped = (factory, keyFn = (...args) => args) =>
(function () {
const states = new MultiKeyMap()
return function () {
const keys = ensureArray(keyFn.apply(this, arguments))
let state = states.get(keys)
if (state === undefined) {
const result = factory.apply(this, arguments)
const createFactory = disposable => {
const wrapper = {
dispose() {
if (--state.users === 0) {
states.delete(keys)
return disposable.dispose()
}
},
value: disposable.value,
}
return () => {
return wrapper
}
}
if (typeof result.then !== 'function') {
state = new State(createFactory(result))
} else {
result.catch(() => {
states.delete(keys)
})
const pFactory = result.then(createFactory)
state = new State(() => pFactory.then(call))
}
states.set(keys, state)
}
++state.users
return state.factory()
}
})()
+76
View File
@@ -0,0 +1,76 @@
/* eslint-env jest */
const { deduped } = require('./deduped')
describe('deduped()', () => {
it('calls the resource function only once', async () => {
const value = {}
const getResource = jest.fn(async () => ({
value,
dispose: Function.prototype,
}))
const dedupedGetResource = deduped(getResource)
const { value: v1 } = await dedupedGetResource()
const { value: v2 } = await dedupedGetResource()
expect(getResource).toHaveBeenCalledTimes(1)
expect(v1).toBe(value)
expect(v2).toBe(value)
})
it('only disposes the source disposable when its all copies dispose', async () => {
const dispose = jest.fn()
const getResource = async () => ({
value: '',
dispose,
})
const dedupedGetResource = deduped(getResource)
const { dispose: d1 } = await dedupedGetResource()
const { dispose: d2 } = await dedupedGetResource()
d1()
expect(dispose).not.toHaveBeenCalled()
d2()
expect(dispose).toHaveBeenCalledTimes(1)
})
it('works with sync factory', () => {
const value = {}
const dispose = jest.fn()
const dedupedGetResource = deduped(() => ({ value, dispose }))
const d1 = dedupedGetResource()
expect(d1.value).toBe(value)
const d2 = dedupedGetResource()
expect(d2.value).toBe(value)
d1.dispose()
expect(dispose).not.toHaveBeenCalled()
d2.dispose()
expect(dispose).toHaveBeenCalledTimes(1)
})
it('no race condition on dispose before async acquisition', async () => {
const dispose = jest.fn()
const dedupedGetResource = deduped(async () => ({ value: 42, dispose }))
const d1 = await dedupedGetResource()
dedupedGetResource()
d1.dispose()
expect(dispose).not.toHaveBeenCalled()
})
})
+29
View File
@@ -0,0 +1,29 @@
{
"private": false,
"name": "@vates/disposable",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/disposable",
"description": "Utilities for disposables",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/disposable",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
},
"license": "ISC",
"version": "0.1.1",
"engines": {
"node": ">=8.10"
},
"scripts": {
"postversion": "npm publish --access public"
},
"dependencies": {
"@vates/multi-key-map": "^0.1.0",
"@xen-orchestra/log": "^0.2.0",
"ensure-array": "^1.0.0"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+53
View File
@@ -0,0 +1,53 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/multi-key-map
[![Package Version](https://badgen.net/npm/v/@vates/multi-key-map)](https://npmjs.org/package/@vates/multi-key-map) ![License](https://badgen.net/npm/license/@vates/multi-key-map) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/multi-key-map)](https://bundlephobia.com/result?p=@vates/multi-key-map) [![Node compatibility](https://badgen.net/npm/node/@vates/multi-key-map)](https://npmjs.org/package/@vates/multi-key-map)
> Create map with values affected to multiple keys
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/multi-key-map):
```
> npm install --save @vates/multi-key-map
```
## Usage
```js
import { MultiKeyMap } from '@vates/multi-key-map'
const map = new MultiKeyMap()
const OBJ = {}
map.set([], 0)
map.set(['foo'], 1)
map.set(['foo', 'bar'], 2)
map.set(['bar', 'foo'], 3)
map.set([OBJ], 4)
map.set([{}], 5)
map.get([]) // 0
map.get(['foo']) // 1
map.get(['foo', 'bar']) // 2
map.get(['bar', 'foo']) // 3
map.get([OBJ]) // 4
map.get([{}]) // undefined
```
## 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
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+20
View File
@@ -0,0 +1,20 @@
```js
import { MultiKeyMap } from '@vates/multi-key-map'
const map = new MultiKeyMap()
const OBJ = {}
map.set([], 0)
map.set(['foo'], 1)
map.set(['foo', 'bar'], 2)
map.set(['bar', 'foo'], 3)
map.set([OBJ], 4)
map.set([{}], 5)
map.get([]) // 0
map.get(['foo']) // 1
map.get(['foo', 'bar']) // 2
map.get(['bar', 'foo']) // 3
map.get([OBJ]) // 4
map.get([{}]) // undefined
```
@@ -67,7 +67,7 @@ function set(node, i, keys, value) {
return node
}
export default class MultiKeyMap {
exports.MultiKeyMap = class MultiKeyMap {
constructor() {
// each node is either a value or a Node if it contains children
this._root = undefined
@@ -1,6 +1,6 @@
/* eslint-env jest */
import MultiKeyMap from './_MultiKeyMap'
const { MultiKeyMap } = require('./')
describe('MultiKeyMap', () => {
it('works', () => {
+28
View File
@@ -0,0 +1,28 @@
{
"private": false,
"name": "@vates/multi-key-map",
"description": "Create map with values affected to multiple keys",
"keywords": [
"cache",
"map"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/multi-key-map",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/multi-key-map",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
},
"license": "ISC",
"version": "0.1.0",
"engines": {
"node": ">=8.10"
},
"scripts": {
"postversion": "npm publish --access public"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+47
View File
@@ -0,0 +1,47 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/parse-duration
[![Package Version](https://badgen.net/npm/v/@vates/parse-duration)](https://npmjs.org/package/@vates/parse-duration) ![License](https://badgen.net/npm/license/@vates/parse-duration) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/parse-duration)](https://bundlephobia.com/result?p=@vates/parse-duration) [![Node compatibility](https://badgen.net/npm/node/@vates/parse-duration)](https://npmjs.org/package/@vates/parse-duration)
> Small wrapper around ms to parse a duration
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/parse-duration):
```
> npm install --save @vates/parse-duration
```
## Usage
`ms` without magic: always parse a duration and throws if invalid.
```js
import { parseDuration } from '@vates/parse-duration'
parseDuration('2 days')
// 172800000
parseDuration(172800000)
// 172800000
parseDuration(undefined)
// throws TypeError('not a valid duration: undefined')
```
## 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
[AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later) © [Vates SAS](https://vates.fr)
+14
View File
@@ -0,0 +1,14 @@
`ms` without magic: always parse a duration and throws if invalid.
```js
import { parseDuration } from '@vates/parse-duration'
parseDuration('2 days')
// 172800000
parseDuration(172800000)
// 172800000
parseDuration(undefined)
// throws TypeError('not a valid duration: undefined')
```
@@ -1,6 +1,6 @@
import ms from 'ms'
const ms = require('ms')
export default value => {
exports.parseDuration = value => {
if (typeof value === 'number') {
return value
}
+32
View File
@@ -0,0 +1,32 @@
{
"private": false,
"name": "@vates/parse-duration",
"description": "Small wrapper around ms to parse a duration",
"keywords": [
"duration",
"ms",
"parse"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/parse-duration",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/parse-duration",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
},
"license": "AGPL-3.0-or-later",
"version": "0.1.0",
"engines": {
"node": ">=8.10"
},
"dependencies": {
"ms": "^2.1.2"
},
"scripts": {
"postversion": "npm publish --access public"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+46
View File
@@ -0,0 +1,46 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/read-chunk
[![Package Version](https://badgen.net/npm/v/@vates/read-chunk)](https://npmjs.org/package/@vates/read-chunk) ![License](https://badgen.net/npm/license/@vates/read-chunk) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/read-chunk)](https://bundlephobia.com/result?p=@vates/read-chunk) [![Node compatibility](https://badgen.net/npm/node/@vates/read-chunk)](https://npmjs.org/package/@vates/read-chunk)
> Read a chunk of a Node stream
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/read-chunk):
```
> npm install --save @vates/read-chunk
```
## Usage
- returns the next available chunk of data
- like `stream.read()`, a number of bytes can be specified
- returns `null` if the stream has ended
```js
import { readChunk } from '@vates/read-chunk'
;(async () => {
let chunk
while ((chunk = await readChunk(stream, 1024)) !== null) {
// do something with chunk
}
})()
```
## 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
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+13
View File
@@ -0,0 +1,13 @@
- returns the next available chunk of data
- like `stream.read()`, a number of bytes can be specified
- returns `null` if the stream has ended
```js
import { readChunk } from '@vates/read-chunk'
;(async () => {
let chunk
while ((chunk = await readChunk(stream, 1024)) !== null) {
// do something with chunk
}
})()
```
+30
View File
@@ -0,0 +1,30 @@
const readChunk = (stream, size) =>
size === 0
? Promise.resolve(Buffer.alloc(0))
: new Promise((resolve, reject) => {
function onEnd() {
resolve(null)
removeListeners()
}
function onError(error) {
reject(error)
removeListeners()
}
function onReadable() {
const data = stream.read(size)
if (data !== null) {
resolve(data)
removeListeners()
}
}
function removeListeners() {
stream.removeListener('end', onEnd)
stream.removeListener('error', onError)
stream.removeListener('readable', onReadable)
}
stream.on('end', onEnd)
stream.on('error', onError)
stream.on('readable', onReadable)
onReadable()
})
exports.readChunk = readChunk
+43
View File
@@ -0,0 +1,43 @@
/* eslint-env jest */
const { Readable } = require('stream')
const { readChunk } = require('./')
const makeStream = it => Readable.from(it, { objectMode: false })
makeStream.obj = Readable.from
describe('readChunk', () => {
it('returns null if stream is empty', async () => {
expect(await readChunk(makeStream([]))).toBe(null)
})
describe('with binary stream', () => {
it('returns the first chunk of data', async () => {
expect(await readChunk(makeStream(['foo', 'bar']))).toEqual(Buffer.from('foo'))
})
it('returns a chunk of the specified size (smaller than first)', async () => {
expect(await readChunk(makeStream(['foo', 'bar']), 2)).toEqual(Buffer.from('fo'))
})
it('returns a chunk of the specified size (larger than first)', async () => {
expect(await readChunk(makeStream(['foo', 'bar']), 4)).toEqual(Buffer.from('foob'))
})
it('returns less data if stream ends', async () => {
expect(await readChunk(makeStream(['foo', 'bar']), 10)).toEqual(Buffer.from('foobar'))
})
it('returns an empty buffer if the specified size is 0', async () => {
expect(await readChunk(makeStream(['foo', 'bar']), 0)).toEqual(Buffer.alloc(0))
})
})
describe('with object stream', () => {
it('returns the first chunk of data verbatim', async () => {
const chunks = [{}, {}]
expect(await readChunk(makeStream.obj(chunks))).toBe(chunks[0])
})
})
})
+36
View File
@@ -0,0 +1,36 @@
{
"private": false,
"name": "@vates/read-chunk",
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/read-chunk",
"description": "Read a chunk of a Node stream",
"license": "ISC",
"keywords": [
"async",
"chunk",
"data",
"node",
"promise",
"read",
"stream"
],
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/read-chunk",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"version": "0.1.2",
"engines": {
"node": ">=8.10"
},
"files": [
"index.js"
],
"scripts": {
"postversion": "npm publish --access public"
},
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+59
View File
@@ -0,0 +1,59 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @vates/toggle-scripts
[![Package Version](https://badgen.net/npm/v/@vates/toggle-scripts)](https://npmjs.org/package/@vates/toggle-scripts) ![License](https://badgen.net/npm/license/@vates/toggle-scripts) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/toggle-scripts)](https://bundlephobia.com/result?p=@vates/toggle-scripts) [![Node compatibility](https://badgen.net/npm/node/@vates/toggle-scripts)](https://npmjs.org/package/@vates/toggle-scripts)
> Easily enable/disable scripts in package.json
## Install
Installation of the [npm package](https://npmjs.org/package/@vates/toggle-scripts):
```
> npm install --save @vates/toggle-scripts
```
## Usage
```
Usage: toggle-scripts options...
Easily enable/disable scripts in package.json
Options
+<script> Enable the script <script>, ie remove the prefix `_`
-<script> Disable the script <script>, ie prefix it with `_`
Examples
toggle-scripts +postinstall +preuninstall
toggle-scripts -postinstall -preuninstall
```
For example, if you want `postinstall` hook only in dev:
```json
// package.json
{
"scripts": {
"postinstall": "<some dev only command>",
"prepublishOnly": "toggle-scripts -postinstall",
"postpublish": "toggle-scripts +postinstall"
}
}
```
## 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
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+26
View File
@@ -0,0 +1,26 @@
```
Usage: toggle-scripts options...
Easily enable/disable scripts in package.json
Options
+<script> Enable the script <script>, ie remove the prefix `_`
-<script> Disable the script <script>, ie prefix it with `_`
Examples
toggle-scripts +postinstall +preuninstall
toggle-scripts -postinstall -preuninstall
```
For example, if you want `postinstall` hook only in dev:
```json
// package.json
{
"scripts": {
"postinstall": "<some dev only command>",
"prepublishOnly": "toggle-scripts -postinstall",
"postpublish": "toggle-scripts +postinstall"
}
}
```
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env node
const fs = require('fs')
const mapKeys = (object, iteratee) => {
const result = {}
for (const key of Object.keys(object)) {
result[iteratee(key, object)] = object[key]
}
return result
}
const args = process.argv.slice(2)
if (args.length === 0) {
const { description, name, version } = require('./package.json')
const bin = 'toggle-scripts'
process.stdout.write(`Usage: ${bin} options...
${description}
Options
+<script> Enable the script <script>, ie remove the prefix \`_\`
-<script> Disable the script <script>, ie prefix it with \`_\`
Examples
${bin} +postinstall +preuninstall
${bin} -postinstall -preuninstall
${name} v${version}
`)
process.exit()
}
const plan = { __proto__: null }
for (const arg of args) {
const action = arg[0]
const script = arg.slice(1)
if (action === '+') {
plan['_' + script] = script
} else if (action === '-') {
plan[script] = '_' + script
} else {
throw new Error('invalid param: ' + arg)
}
}
const pkgPath = process.env.npm_package_json || './package.json'
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
pkg.scripts = mapKeys(pkg.scripts, (name, scripts) => {
const newName = plan[name]
if (newName === undefined) {
return name
}
if (newName in scripts) {
throw new Error('script already defined: ' + name)
}
return newName
})
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
+41
View File
@@ -0,0 +1,41 @@
{
"private": false,
"name": "@vates/toggle-scripts",
"description": "Easily enable/disable scripts in package.json",
"keywords": [
"dev",
"disable",
"enable",
"lifecycle",
"npm",
"package.json",
"pinst",
"postinstall",
"script",
"scripts",
"toggle"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/toggle-scripts",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
"directory": "@vates/toggle-scripts",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
},
"license": "ISC",
"version": "1.0.0",
"engines": {
"node": ">=6"
},
"files": [
"index.js"
],
"bin": "./index.js",
"scripts": {
"postversion": "npm publish --access public"
}
}
-3
View File
@@ -1,3 +0,0 @@
module.exports = require('../../@xen-orchestra/babel-config')(
require('./package.json')
)
-24
View File
@@ -1,24 +0,0 @@
/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__/
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+56 -16
View File
@@ -1,6 +1,10 @@
# @xen-orchestra/async-map [![Build Status](https://travis-ci.org/vatesfr/xen-orchestra.png?branch=master)](https://travis-ci.org/vatesfr/xen-orchestra)
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
> ${pkg.description}
# @xen-orchestra/async-map
[![Package Version](https://badgen.net/npm/v/@xen-orchestra/async-map)](https://npmjs.org/package/@xen-orchestra/async-map) ![License](https://badgen.net/npm/license/@xen-orchestra/async-map) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@xen-orchestra/async-map)](https://bundlephobia.com/result?p=@xen-orchestra/async-map) [![Node compatibility](https://badgen.net/npm/node/@xen-orchestra/async-map)](https://npmjs.org/package/@xen-orchestra/async-map)
> Promise.all + map for all iterables
## Install
@@ -12,30 +16,66 @@ Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/async
## Usage
**TODO**
### `asyncMap(iterable, iteratee, thisArg = iterable)`
## Development
Similar to `Promise.all + Array#map` for all iterables: calls `iteratee` for each item in `iterable`, and returns a promise of an array containing the awaited result of each calls to `iteratee`.
It rejects as soon as te first call to `iteratee` rejects.
```js
import { asyncMap } from '@xen-orchestra/async-map'
const array = await asyncMap(iterable, iteratee, thisArg)
```
# Install dependencies
> yarn
# Run the tests
> yarn test
It can be used with any iterables (`Array`, `Map`, etc.):
# Continuously compile
> yarn dev
```js
const map = new Map()
map.set('foo', 42)
map.set('bar', 3.14)
# Continuously run the tests
> yarn dev-test
const array = await asyncMap(map, async function ([key, value]) {
// TODO: do async computation
//
// the map can be accessed via `this`
})
```
# Build for production (automatically called by npm install)
> yarn build
#### Use with plain objects
Plain objects are not iterable, but you can use `Object.keys`, `Object.values` or `Object.entries` to help:
```js
const object = {
foo: 42,
bar: 3.14,
}
const array = await asyncMap(
Object.entries(object),
async function ([key, value]) {
// TODO: do async computation
//
// the object can be accessed via `this` because it's been passed as third arg
},
object
)
```
### `asyncMapSettled(iterable, iteratee, thisArg = iterable)`
Similar to `asyncMap` but waits for all promises to settle before rejecting.
```js
import { asyncMapSettled } from '@xen-orchestra/async-map'
const array = await asyncMapSettled(iterable, iteratee, thisArg)
```
## Contributions
Contributions are *very* welcomed, either on the documentation or on
Contributions are _very_ welcomed, either on the documentation or on
the code.
You may:
@@ -46,4 +86,4 @@ You may:
## License
ISC © [Vates SAS](https://vates.fr)
[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr)
+56
View File
@@ -0,0 +1,56 @@
### `asyncMap(iterable, iteratee, thisArg = iterable)`
Similar to `Promise.all + Array#map` for all iterables: calls `iteratee` for each item in `iterable`, and returns a promise of an array containing the awaited result of each calls to `iteratee`.
It rejects as soon as te first call to `iteratee` rejects.
```js
import { asyncMap } from '@xen-orchestra/async-map'
const array = await asyncMap(iterable, iteratee, thisArg)
```
It can be used with any iterables (`Array`, `Map`, etc.):
```js
const map = new Map()
map.set('foo', 42)
map.set('bar', 3.14)
const array = await asyncMap(map, async function ([key, value]) {
// TODO: do async computation
//
// the map can be accessed via `this`
})
```
#### Use with plain objects
Plain objects are not iterable, but you can use `Object.keys`, `Object.values` or `Object.entries` to help:
```js
const object = {
foo: 42,
bar: 3.14,
}
const array = await asyncMap(
Object.entries(object),
async function ([key, value]) {
// TODO: do async computation
//
// the object can be accessed via `this` because it's been passed as third arg
},
object
)
```
### `asyncMapSettled(iterable, iteratee, thisArg = iterable)`
Similar to `asyncMap` but waits for all promises to settle before rejecting.
```js
import { asyncMapSettled } from '@xen-orchestra/async-map'
const array = await asyncMapSettled(iterable, iteratee, thisArg)
```
+71
View File
@@ -0,0 +1,71 @@
const wrapCall = (fn, arg, thisArg) => {
try {
return Promise.resolve(fn.call(thisArg, arg))
} catch (error) {
return Promise.reject(error)
}
}
/**
* Similar to Promise.all + Array#map but supports all iterables and does not trigger ESLint array-callback-return
*
* WARNING: Does not handle plain objects
*
* @template Item,This
* @param {Iterable<Item>} iterable
* @param {(this: This, item: Item) => (Item | PromiseLike<Item>)} mapFn
* @param {This} [thisArg]
* @returns {Promise<Item[]>}
*/
exports.asyncMap = function asyncMap(iterable, mapFn, thisArg = iterable) {
return Promise.all(Array.from(iterable, mapFn, thisArg))
}
/**
* Like `asyncMap` but wait for all promises to settle before rejecting
*
* @template Item,This
* @param {Iterable<Item>} iterable
* @param {(this: This, item: Item) => (Item | PromiseLike<Item>)} mapFn
* @param {This} [thisArg]
* @returns {Promise<Item[]>}
*/
exports.asyncMapSettled = function asyncMapSettled(iterable, mapFn, thisArg = iterable) {
return new Promise((resolve, reject) => {
const onError = e => {
if (result !== undefined) {
error = e
result = undefined
}
if (--n === 0) {
reject(error)
}
}
const onValue = (i, value) => {
const hasError = result === undefined
if (!hasError) {
result[i] = value
}
if (--n === 0) {
if (hasError) {
reject(error)
} else {
resolve(result)
}
}
}
let n = 0
for (const item of iterable) {
const i = n++
wrapCall(mapFn, item, thisArg).then(value => onValue(i, value), onError)
}
if (n === 0) {
return resolve([])
}
let error
let result = new Array(n)
})
}
+71
View File
@@ -0,0 +1,71 @@
/* eslint-env jest */
const { asyncMapSettled } = require('./')
const noop = Function.prototype
describe('asyncMapSettled', () => {
it('works', async () => {
const values = [Math.random(), Math.random()]
const spy = jest.fn(async v => v * 2)
const iterable = new Set(values)
// returns an array containing the result of each calls
expect(await asyncMapSettled(iterable, spy)).toEqual(values.map(value => value * 2))
for (let i = 0, n = values.length; i < n; ++i) {
// each call receive the current item as sole argument
expect(spy.mock.calls[i]).toEqual([values[i]])
// each call as this bind to the iterable
expect(spy.mock.instances[i]).toBe(iterable)
}
})
it('can use a specified thisArg', () => {
const thisArg = {}
const spy = jest.fn()
asyncMapSettled(['foo'], spy, thisArg)
expect(spy.mock.instances[0]).toBe(thisArg)
})
it('rejects only when all calls as resolved', async () => {
const defers = []
const promise = asyncMapSettled([1, 2], () => {
let resolve, reject
// eslint-disable-next-line promise/param-names
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve
reject = _reject
})
defers.push({ promise, resolve, reject })
return promise
})
let hasSettled = false
promise.catch(noop).then(() => {
hasSettled = true
})
const error = new Error()
defers[0].reject(error)
// wait for all microtasks to settle
await new Promise(resolve => setImmediate(resolve))
expect(hasSettled).toBe(false)
defers[1].resolve()
// wait for all microtasks to settle
await new Promise(resolve => setImmediate(resolve))
expect(hasSettled).toBe(true)
await expect(promise).rejects.toBe(error)
})
it('issues when latest promise rejects', async () => {
const error = new Error()
await expect(asyncMapSettled([1], () => Promise.reject(error))).rejects.toBe(error)
})
})
@@ -9,14 +9,18 @@
// (V1, K) => MaybePromise<V2>
// ): Promise<V2[]>
import map from 'lodash/map'
const map = require('lodash/map')
// Similar to map() + Promise.all() but wait for all promises to
// settle before rejecting (with the first error)
const asyncMap = (collection, iteratee) => {
/**
* Similar to map() + Promise.all() but wait for all promises to settle before
* rejecting (with the first error)
*
* @deprecated Don't support iterables, please use new implementations
*/
module.exports = function asyncMapLegacy(collection, iteratee) {
let then
if (collection != null && typeof (then = collection.then) === 'function') {
return then.call(collection, collection => asyncMap(collection, iteratee))
return then.call(collection, collection => asyncMapLegacy(collection, iteratee))
}
let errorContainer
@@ -39,5 +43,3 @@ const asyncMap = (collection, iteratee) => {
return values
})
}
export { asyncMap as default }
+15 -27
View File
@@ -1,9 +1,17 @@
{
"private": false,
"name": "@xen-orchestra/async-map",
"version": "0.0.0",
"version": "0.1.2",
"license": "ISC",
"description": "",
"keywords": [],
"description": "Promise.all + map for all iterables",
"keywords": [
"array",
"async",
"iterable",
"map",
"settled",
"typescript"
],
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/async-map",
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"repository": {
@@ -12,17 +20,13 @@
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"author": {
"name": "Julien Fontanet",
"email": "julien.fontanet@isonoe.net"
"name": "Vates SAS",
"url": "https://vates.fr"
},
"preferGlobal": false,
"main": "dist/",
"bin": {},
"files": [
"dist/"
],
"browserslist": [
">2%"
"index.js",
"legacy.js"
],
"engines": {
"node": ">=6"
@@ -30,23 +34,7 @@
"dependencies": {
"lodash": "^4.17.4"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-flow": "^7.0.0",
"babel-plugin-lodash": "^3.3.2",
"cross-env": "^5.1.3",
"rimraf": "^3.0.0"
},
"scripts": {
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
"clean": "rimraf dist/",
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
"prebuild": "yarn run clean",
"predev": "yarn run prebuild",
"prepare": "yarn run build",
"prepublishOnly": "yarn run build",
"postversion": "npm publish"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = require('../../@xen-orchestra/babel-config')(require('./package.json'))
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+28
View File
@@ -0,0 +1,28 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @xen-orchestra/audit-core
[![Package Version](https://badgen.net/npm/v/@xen-orchestra/audit-core)](https://npmjs.org/package/@xen-orchestra/audit-core) ![License](https://badgen.net/npm/license/@xen-orchestra/audit-core) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@xen-orchestra/audit-core)](https://bundlephobia.com/result?p=@xen-orchestra/audit-core) [![Node compatibility](https://badgen.net/npm/node/@xen-orchestra/audit-core)](https://npmjs.org/package/@xen-orchestra/audit-core)
## Install
Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/audit-core):
```
> npm install --save @xen-orchestra/audit-core
```
## 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
[AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later) © [Vates SAS](https://vates.fr)
View File
+45
View File
@@ -0,0 +1,45 @@
{
"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.2.0",
"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",
"cross": "^1.0.0",
"rimraf": "^3.0.0"
},
"dependencies": {
"@xen-orchestra/log": "^0.2.0",
"core-js": "^3.6.4",
"golike-defer": "^0.5.1",
"lodash": "^4.17.15",
"object-hash": "^2.0.1"
},
"private": false,
"license": "AGPL-3.0-or-later",
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
}
}
+193
View File
@@ -0,0 +1,193 @@
// 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'
import { createLogger } from '@xen-orchestra/log'
const log = createLogger('xo:audit-core')
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()
$defer(await this._storage.acquireLock())
return this._addUnsafe({
data,
event,
subject,
time,
})
}
async _addUnsafe({ data, event, subject, time }) {
const storage = this._storage
// 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)
}
}
@defer
async deleteRangeAndRewrite($defer, newest, oldest) {
assert.notStrictEqual(newest, undefined)
assert.notStrictEqual(oldest, undefined)
const storage = this._storage
$defer(await storage.acquireLock())
assert.notStrictEqual(await storage.get(newest), undefined)
const oldestRecord = await storage.get(oldest)
assert.notStrictEqual(oldestRecord, undefined)
const lastId = await storage.getLastId()
const recentRecords = []
for await (const record of this.getFrom(lastId)) {
if (record.id === newest) {
break
}
recentRecords.push(record)
}
for await (const record of this.getFrom(newest)) {
await storage.del(record.id)
if (record.id === oldest) {
break
}
}
await storage.setLastId(oldestRecord.previousId)
for (const record of recentRecords) {
try {
await this._addUnsafe(record)
await storage.del(record.id)
} catch (error) {
log.error(error)
}
}
}
}
+115
View File
@@ -0,0 +1,115 @@
/* 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)
})
})
@@ -0,0 +1,26 @@
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> { }
public deleteRangeAndRewrite(newest: string, oldest: string): Promise<void> { }
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+18
View File
@@ -0,0 +1,18 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @xen-orchestra/babel-config
## 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
[AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later) © [Vates SAS](https://vates.fr)
+3 -11
View File
@@ -32,27 +32,19 @@ const configs = {
}
return { browsers: pkg.browserslist, node }
})(),
useBuiltIns: '@babel/polyfill' in (pkg.dependencies || {}) && 'usage',
}
},
}
const getConfig = (key, ...args) => {
const config = configs[key]
return config === undefined
? {}
: typeof config === 'function'
? config(...args)
: config
return config === undefined ? {} : typeof config === 'function' ? config(...args) : config
}
// some plugins must be used in a specific order
const pluginsOrder = [
'@babel/plugin-proposal-decorators',
'@babel/plugin-proposal-class-properties',
]
const pluginsOrder = ['@babel/plugin-proposal-decorators', '@babel/plugin-proposal-class-properties']
module.exports = function(pkg, plugins, presets) {
module.exports = function (pkg, plugins, presets) {
plugins === undefined && (plugins = {})
presets === undefined && (presets = {})
+8
View File
@@ -8,5 +8,13 @@
"directory": "@xen-orchestra/babel-config",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"engines": {
"node": ">=6"
},
"license": "AGPL-3.0-or-later",
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+48
View File
@@ -0,0 +1,48 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @xen-orchestra/backups-cli
[![Package Version](https://badgen.net/npm/v/@xen-orchestra/backups-cli)](https://npmjs.org/package/@xen-orchestra/backups-cli) ![License](https://badgen.net/npm/license/@xen-orchestra/backups-cli) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@xen-orchestra/backups-cli)](https://bundlephobia.com/result?p=@xen-orchestra/backups-cli) [![Node compatibility](https://badgen.net/npm/node/@xen-orchestra/backups-cli)](https://npmjs.org/package/@xen-orchestra/backups-cli)
## Install
Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/backups-cli):
```
> npm install --global @xen-orchestra/backups-cli
```
## Usage
```
> xo-backups --help
Usage:
xo-backups clean-vms [--merge] [--remove] xo-vm-backups/*
Detects and repair issues with VM backups.
Options:
-m, --merge Merge (or continue merging) VHD files that are unused
-r, --remove Remove unused, incomplete, orphan, or corrupted files
xo-backups create-symlink-index xo-vm-backups <field path>
xo-backups info xo-vm-backups/*
```
## 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
[AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later) © [Vates SAS](https://vates.fr)
+17
View File
@@ -0,0 +1,17 @@
```
> xo-backups --help
Usage:
xo-backups clean-vms [--merge] [--remove] xo-vm-backups/*
Detects and repair issues with VM backups.
Options:
-m, --merge Merge (or continue merging) VHD files that are unused
-r, --remove Remove unused, incomplete, orphan, or corrupted files
xo-backups create-symlink-index xo-vm-backups <field path>
xo-backups info xo-vm-backups/*
```
@@ -0,0 +1,32 @@
const getopts = require('getopts')
const { version } = require('./package.json')
module.exports = commands =>
async function (args, prefix) {
const opts = getopts(args, {
alias: {
help: 'h',
},
boolean: ['help'],
stopEarly: true,
})
const commandName = opts.help || args.length === 0 ? 'help' : args[0]
const command = commands[commandName]
if (command === undefined) {
process.stdout.write(`Usage:
${Object.keys(commands)
.filter(command => command !== 'help')
.map(command => ` ${prefix} ${command} ${commands[command].usage || ''}`)
.join('\n\n')}
xo-backups v${version}
`)
process.exitCode = commandName === 'help' ? 0 : 1
return
}
return command.main(args.slice(1), prefix + ' ' + commandName)
}
+69
View File
@@ -0,0 +1,69 @@
const { dirname } = require('path')
const fs = require('promise-toolbox/promisifyAll')(require('fs'))
module.exports = fs
fs.getSize = path =>
fs.stat(path).then(
_ => _.size,
error => {
if (error.code === 'ENOENT') {
return 0
}
throw error
}
)
fs.mktree = async function mkdirp(path) {
try {
await fs.mkdir(path)
} catch (error) {
const { code } = error
if (code === 'EEXIST') {
await fs.readdir(path)
return
}
if (code === 'ENOENT') {
await mkdirp(dirname(path))
return mkdirp(path)
}
throw error
}
}
// - easier:
// - single param for direct use in `Array#map`
// - files are prefixed with directory path
// - safer: returns empty array if path is missing or not a directory
fs.readdir2 = path =>
fs.readdir(path).then(
entries => {
entries.forEach((entry, i) => {
entries[i] = `${path}/${entry}`
})
return entries
},
error => {
const { code } = error
if (code === 'ENOENT') {
// do nothing
} else if (code === 'ENOTDIR') {
console.warn('WARN: readdir(%s)', path, error)
} else {
throw error
}
return []
}
)
fs.symlink2 = async (target, path) => {
try {
await fs.symlink(target, path)
} catch (error) {
if (error.code === 'EEXIST' && (await fs.readlink(path)) === target) {
return
}
throw error
}
}
@@ -0,0 +1,33 @@
#!/usr/bin/env node
// -----------------------------------------------------------------------------
const asyncMap = require('lodash/curryRight')(require('@xen-orchestra/async-map').asyncMap)
const getopts = require('getopts')
const { RemoteAdapter } = require('@xen-orchestra/backups/RemoteAdapter')
const { resolve } = require('path')
const adapter = new RemoteAdapter(require('@xen-orchestra/fs').getHandler({ url: 'file://' }))
module.exports = async function main(args) {
const { _, remove, merge } = getopts(args, {
alias: {
remove: 'r',
merge: 'm',
},
boolean: ['merge', 'remove'],
default: {
merge: false,
remove: false,
},
})
await asyncMap(_, async vmDir => {
vmDir = resolve(vmDir)
try {
await adapter.cleanVm(vmDir, { remove, merge, onLog: log => console.warn(log) })
} catch (error) {
console.error('adapter.cleanVm', vmDir, error)
}
})
}
@@ -0,0 +1,28 @@
const filenamify = require('filenamify')
const get = require('lodash/get')
const { asyncMap } = require('@xen-orchestra/async-map')
const { dirname, join, relative } = require('path')
const { mktree, readdir2, readFile, symlink2 } = require('../_fs')
module.exports = async function createSymlinkIndex([backupDir, fieldPath]) {
const indexDir = join(backupDir, 'indexes', filenamify(fieldPath))
await mktree(indexDir)
await asyncMap(await readdir2(backupDir), async vmDir =>
asyncMap(
(await readdir2(vmDir)).filter(_ => _.endsWith('.json')),
async json => {
const metadata = JSON.parse(await readFile(json))
const value = get(metadata, fieldPath)
if (value !== undefined) {
const target = relative(indexDir, dirname(json))
const path = join(indexDir, filenamify(String(value)))
await symlink2(target, path).catch(error => {
console.warn('symlink(%s, %s)', target, path, error)
})
}
}
)
)
}
@@ -0,0 +1,54 @@
const groupBy = require('lodash/groupBy')
const { asyncMap } = require('@xen-orchestra/async-map')
const { createHash } = require('crypto')
const { dirname, resolve } = require('path')
const { readdir2, readFile, getSize } = require('../_fs')
const sha512 = str => createHash('sha512').update(str).digest('hex')
const sum = values => values.reduce((a, b) => a + b)
module.exports = async function info(vmDirs) {
const jsonFiles = (
await asyncMap(vmDirs, async vmDir => (await readdir2(vmDir)).filter(_ => _.endsWith('.json')))
).flat()
const hashes = { __proto__: null }
const info = (
await asyncMap(jsonFiles, async jsonFile => {
try {
const jsonDir = dirname(jsonFile)
const json = await readFile(jsonFile)
const hash = sha512(json)
if (hash in hashes) {
console.log(jsonFile, 'duplicate of', hashes[hash])
return
}
hashes[hash] = jsonFile
const metadata = JSON.parse(json)
return {
jsonDir,
jsonFile,
metadata,
size:
json.length +
(await (metadata.mode === 'delta'
? asyncMap(Object.values(metadata.vhds), _ => getSize(resolve(jsonDir, _))).then(sum)
: getSize(resolve(jsonDir, metadata.xva)))),
}
} catch (error) {
console.error(jsonFile, error)
}
})
).filter(_ => _ !== undefined)
const byJobs = groupBy(info, 'metadata.jobId')
Object.keys(byJobs)
.sort()
.forEach(jobId => {
console.log(jobId, sum(byJobs[jobId].map(_ => _.size)))
})
}
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env node
require('./_composeCommands')({
'clean-vms': {
get main() {
return require('./commands/clean-vms')
},
usage: `[--merge] [--remove] xo-vm-backups/*
Detects and repair issues with VM backups.
Options:
-m, --merge Merge (or continue merging) VHD files that are unused
-r, --remove Remove unused, incomplete, orphan, or corrupted files
`,
},
'create-symlink-index': {
get main() {
return require('./commands/create-symlink-index')
},
usage: 'xo-vm-backups <field path>',
},
info: {
get main() {
return require('./commands/info')
},
usage: 'xo-vm-backups/*',
},
})(process.argv.slice(2), 'xo-backups').catch(error => {
console.error('main', error)
process.exitCode = 1
})
+41
View File
@@ -0,0 +1,41 @@
{
"private": false,
"bin": {
"xo-backups": "index.js"
},
"preferGlobal": true,
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
"dependencies": {
"@xen-orchestra/async-map": "^0.1.2",
"@xen-orchestra/backups": "^0.9.1",
"@xen-orchestra/fs": "^0.14.0",
"filenamify": "^4.1.0",
"getopts": "^2.2.5",
"lodash": "^4.17.15",
"promise-toolbox": "^0.18.0",
"vhd-lib": "^1.0.0"
},
"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": {
"directory": "@xen-orchestra/backups-cli",
"type": "git",
"url": "https://github.com/vatesfr/xen-orchestra.git"
},
"scripts": {
"postversion": "npm publish --access public"
},
"version": "0.5.0",
"license": "AGPL-3.0-or-later",
"author": {
"name": "Vates SAS",
"url": "https://vates.fr"
}
}
+1
View File
@@ -0,0 +1 @@
../../scripts/npmignore
+263
View File
@@ -0,0 +1,263 @@
const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map')
const Disposable = require('promise-toolbox/Disposable')
const ignoreErrors = require('promise-toolbox/ignoreErrors')
const limitConcurrency = require('limit-concurrency-decorator').default
const { compileTemplate } = require('@xen-orchestra/template')
const { extractIdsFromSimplePattern } = require('./_extractIdsFromSimplePattern')
const { PoolMetadataBackup } = require('./_PoolMetadataBackup')
const { Task } = require('./Task')
const { VmBackup } = require('./_VmBackup')
const { XoMetadataBackup } = require('./_XoMetadataBackup')
const noop = Function.prototype
const getAdaptersByRemote = adapters => {
const adaptersByRemote = {}
adapters.forEach(({ adapter, remoteId }) => {
adaptersByRemote[remoteId] = adapter
})
return adaptersByRemote
}
const runTask = (...args) => Task.run(...args).catch(noop) // errors are handled by logs
exports.Backup = class Backup {
constructor({ config, getAdapter, getConnectedRecord, job, schedule }) {
this._config = config
this._getRecord = getConnectedRecord
this._job = job
this._schedule = schedule
this._getAdapter = Disposable.factory(function* (remoteId) {
return {
adapter: yield getAdapter(remoteId),
remoteId,
}
})
this._getSnapshotNameLabel = compileTemplate(config.snapshotNameLabelTpl, {
'{job.name}': job.name,
'{vm.name_label}': vm => vm.name_label,
})
}
run() {
const type = this._job.type
if (type === 'backup') {
return this._runVmBackup()
} else if (type === 'metadataBackup') {
return this._runMetadataBackup()
} else {
throw new Error(`No runner for the backup type ${type}`)
}
}
async _runMetadataBackup() {
const schedule = this._schedule
const job = this._job
const remoteIds = extractIdsFromSimplePattern(job.remotes)
if (remoteIds.length === 0) {
throw new Error('metadata backup job cannot run without remotes')
}
const config = this._config
const settings = {
...config.defaultSettings,
...config.metadata.defaultSettings,
...job.settings[''],
...job.settings[schedule.id],
}
const poolIds = extractIdsFromSimplePattern(job.pools)
const isEmptyPools = poolIds.length === 0
const isXoMetadata = job.xoMetadata !== undefined
if (!isXoMetadata && isEmptyPools) {
throw new Error('no metadata mode found')
}
const { retentionPoolMetadata, retentionXoMetadata } = settings
if (
(retentionPoolMetadata === 0 && retentionXoMetadata === 0) ||
(!isXoMetadata && retentionPoolMetadata === 0) ||
(isEmptyPools && retentionXoMetadata === 0)
) {
throw new Error('no retentions corresponding to the metadata modes found')
}
await Disposable.use(
Disposable.all(
poolIds.map(id =>
this._getRecord('pool', id).catch(error => {
// See https://github.com/vatesfr/xen-orchestra/commit/6aa6cfba8ec939c0288f0fa740f6dfad98c43cbb
runTask(
{
name: 'get pool record',
data: { type: 'pool', id },
},
() => Promise.reject(error)
)
})
)
),
Disposable.all(
remoteIds.map(id =>
this._getAdapter(id).catch(error => {
// See https://github.com/vatesfr/xen-orchestra/commit/6aa6cfba8ec939c0288f0fa740f6dfad98c43cbb
runTask(
{
name: 'get remote adapter',
data: { type: 'remote', id },
},
() => Promise.reject(error)
)
})
)
),
async (pools, remoteAdapters) => {
// remove adapters that failed (already handled)
remoteAdapters = remoteAdapters.filter(_ => _ !== undefined)
if (remoteAdapters.length === 0) {
return
}
remoteAdapters = getAdaptersByRemote(remoteAdapters)
// remove pools that failed (already handled)
pools = pools.filter(_ => _ !== undefined)
const promises = []
if (pools.length !== 0 && settings.retentionPoolMetadata !== 0) {
promises.push(
asyncMap(pools, async pool =>
runTask(
{
name: `Starting metadata backup for the pool (${pool.$id}). (${job.id})`,
data: {
id: pool.$id,
pool,
poolMaster: await ignoreErrors.call(pool.$xapi.getRecord('host', pool.master)),
type: 'pool',
},
},
() =>
new PoolMetadataBackup({
config,
job,
pool,
remoteAdapters,
schedule,
settings,
}).run()
)
)
)
}
if (job.xoMetadata !== undefined && settings.retentionXoMetadata !== 0) {
promises.push(
runTask(
{
name: `Starting XO metadata backup. (${job.id})`,
data: {
type: 'xo',
},
},
() =>
new XoMetadataBackup({
config,
job,
remoteAdapters,
schedule,
settings,
}).run()
)
)
}
await Promise.all(promises)
}
)
}
async _runVmBackup() {
const job = this._job
// FIXME: proper SimpleIdPattern handling
const getSnapshotNameLabel = this._getSnapshotNameLabel
const schedule = this._schedule
const config = this._config
const { settings } = job
const scheduleSettings = {
...config.defaultSettings,
...config.vm.defaultSettings,
...settings[''],
...settings[schedule.id],
}
await Disposable.use(
Disposable.all(
extractIdsFromSimplePattern(job.srs).map(id =>
this._getRecord('SR', id).catch(error => {
runTask(
{
name: 'get SR record',
data: { type: 'SR', id },
},
() => Promise.reject(error)
)
})
)
),
Disposable.all(
extractIdsFromSimplePattern(job.remotes).map(id =>
this._getAdapter(id).catch(error => {
runTask(
{
name: 'get remote adapter',
data: { type: 'remote', id },
},
() => Promise.reject(error)
)
})
)
),
async (srs, remoteAdapters) => {
// remove adapters that failed (already handled)
remoteAdapters = remoteAdapters.filter(_ => _ !== undefined)
// remove srs that failed (already handled)
srs = srs.filter(_ => _ !== undefined)
if (remoteAdapters.length === 0 && srs.length === 0 && scheduleSettings.snapshotRetention === 0) {
return
}
const vmIds = extractIdsFromSimplePattern(job.vms)
Task.info('vms', { vms: vmIds })
remoteAdapters = getAdaptersByRemote(remoteAdapters)
const handleVm = vmUuid =>
runTask({ name: 'backup VM', data: { type: 'VM', id: vmUuid } }, () =>
Disposable.use(this._getRecord('VM', vmUuid), vm =>
new VmBackup({
config,
getSnapshotNameLabel,
job,
// remotes,
remoteAdapters,
schedule,
settings: { ...scheduleSettings, ...settings[vmUuid] },
srs,
vm,
}).run()
)
)
const { concurrency } = scheduleSettings
await asyncMapSettled(vmIds, concurrency === 0 ? handleVm : limitConcurrency(concurrency)(handleVm))
}
)
}
}
@@ -0,0 +1,40 @@
const { asyncMap } = require('@xen-orchestra/async-map')
exports.DurablePartition = class DurablePartition {
// private resource API is used exceptionally to be able to separate resource creation and release
#partitionDisposers = {}
flushAll() {
const partitionDisposers = this.#partitionDisposers
return asyncMap(Object.keys(partitionDisposers), path => {
const disposers = partitionDisposers[path]
delete partitionDisposers[path]
return asyncMap(disposers, d => d(path).catch(noop => {}))
})
}
async mount(adapter, diskId, partitionId) {
const { value: path, dispose } = await adapter.getPartition(diskId, partitionId)
const partitionDisposers = this.#partitionDisposers
if (partitionDisposers[path] === undefined) {
partitionDisposers[path] = []
}
partitionDisposers[path].push(dispose)
return path
}
async unmount(path) {
const partitionDisposers = this.#partitionDisposers
const disposers = partitionDisposers[path]
if (disposers === undefined) {
throw new Error(`No partition corresponding to the path ${path} found`)
}
await disposers.pop()()
if (disposers.length === 0) {
delete partitionDisposers[path]
}
}
}
+61
View File
@@ -0,0 +1,61 @@
const assert = require('assert')
const { formatFilenameDate } = require('./_filenameDate')
const { importDeltaVm } = require('./_deltaVm')
const { Task } = require('./Task')
exports.ImportVmBackup = class ImportVmBackup {
constructor({ adapter, metadata, srUuid, xapi, settings: { newMacAddresses } = {} }) {
this._adapter = adapter
this._importDeltaVmSettings = { newMacAddresses }
this._metadata = metadata
this._srUuid = srUuid
this._xapi = xapi
}
async run() {
const adapter = this._adapter
const metadata = this._metadata
const isFull = metadata.mode === 'full'
let backup
if (isFull) {
backup = await adapter.readFullVmBackup(metadata)
} else {
assert.strictEqual(metadata.mode, 'delta')
backup = await adapter.readDeltaVmBackup(metadata)
}
return Task.run(
{
name: 'transfer',
},
async () => {
const xapi = this._xapi
const srRef = await xapi.call('SR.get_by_uuid', this._srUuid)
const vmRef = isFull
? await xapi.VM_import(backup, srRef)
: await importDeltaVm(backup, await xapi.getRecord('SR', srRef), {
...this._importDeltaVmSettings,
detectBase: false,
})
await Promise.all([
xapi.call('VM.add_tags', vmRef, 'restored from backup'),
xapi.call(
'VM.set_name_label',
vmRef,
`${metadata.vm.name_label} (${formatFilenameDate(metadata.timestamp)})`
),
])
return {
size: metadata.size,
id: await xapi.getField('VM', vmRef, 'uuid'),
}
}
)
}
}
+28
View File
@@ -0,0 +1,28 @@
<!-- DO NOT EDIT MANUALLY, THIS FILE HAS BEEN GENERATED -->
# @xen-orchestra/backups
[![Package Version](https://badgen.net/npm/v/@xen-orchestra/backups)](https://npmjs.org/package/@xen-orchestra/backups) ![License](https://badgen.net/npm/license/@xen-orchestra/backups) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@xen-orchestra/backups)](https://bundlephobia.com/result?p=@xen-orchestra/backups) [![Node compatibility](https://badgen.net/npm/node/@xen-orchestra/backups)](https://npmjs.org/package/@xen-orchestra/backups)
## Install
Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/backups):
```
> npm install --save @xen-orchestra/backups
```
## 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
[AGPL-3.0-or-later](https://spdx.org/licenses/AGPL-3.0-or-later) © [Vates SAS](https://vates.fr)
+558
View File
@@ -0,0 +1,558 @@
const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map')
const Disposable = require('promise-toolbox/Disposable')
const fromCallback = require('promise-toolbox/fromCallback')
const fromEvent = require('promise-toolbox/fromEvent')
const pDefer = require('promise-toolbox/defer')
const pump = require('pump')
const { basename, dirname, join, normalize, resolve } = require('path')
const { createLogger } = require('@xen-orchestra/log')
const { createSyntheticStream, mergeVhd, default: Vhd } = require('vhd-lib')
const { deduped } = require('@vates/disposable/deduped')
const { execFile } = require('child_process')
const { readdir, stat } = require('fs-extra')
const { ZipFile } = require('yazl')
const { BACKUP_DIR } = require('./_getVmBackupDir')
const { cleanVm } = require('./_cleanVm')
const { getTmpDir } = require('./_getTmpDir')
const { isMetadataFile, isVhdFile } = require('./_backupType')
const { listPartitions, LVM_PARTITION_TYPE } = require('./_listPartitions')
const { lvs, pvs } = require('./_lvm')
const DIR_XO_CONFIG_BACKUPS = 'xo-config-backups'
exports.DIR_XO_CONFIG_BACKUPS = DIR_XO_CONFIG_BACKUPS
const DIR_XO_POOL_METADATA_BACKUPS = 'xo-pool-metadata-backups'
exports.DIR_XO_POOL_METADATA_BACKUPS = DIR_XO_POOL_METADATA_BACKUPS
const { warn } = createLogger('xo:backups:RemoteAdapter')
const compareTimestamp = (a, b) => a.timestamp - b.timestamp
const noop = Function.prototype
const resolveRelativeFromFile = (file, path) => resolve('/', dirname(file), path).slice(1)
const resolveSubpath = (root, path) => resolve(root, `.${resolve('/', path)}`)
const RE_VHDI = /^vhdi(\d+)$/
async function addDirectory(files, realPath, metadataPath) {
try {
const subFiles = await readdir(realPath)
await asyncMap(subFiles, file => addDirectory(files, realPath + '/' + file, metadataPath + '/' + file))
} catch (error) {
if (error == null || error.code !== 'ENOTDIR') {
throw error
}
files.push({
realPath,
metadataPath,
})
}
}
const createSafeReaddir = (handler, methodName) => (path, options) =>
handler.list(path, options).catch(error => {
if (error?.code !== 'ENOENT') {
warn(`${methodName} ${path}`, { error })
}
return []
})
const debounceResourceFactory = factory =>
function () {
return this._debounceResource(factory.apply(this, arguments))
}
class RemoteAdapter {
constructor(handler, { debounceResource = res => res, dirMode } = {}) {
this._debounceResource = debounceResource
this._dirMode = dirMode
this._handler = handler
}
get handler() {
return this._handler
}
async _deleteVhd(path) {
const handler = this._handler
const vhds = await asyncMapSettled(
await handler.list(dirname(path), {
filter: isVhdFile,
prependDir: true,
}),
async path => {
try {
const vhd = new Vhd(handler, path)
await vhd.readHeaderAndFooter()
return {
footer: vhd.footer,
header: vhd.header,
path,
}
} catch (error) {
// Do not fail on corrupted VHDs (usually uncleaned temporary files),
// they are probably inconsequent to the backup process and should not
// fail it.
warn(`BackupNg#_deleteVhd ${path}`, { error })
}
}
)
const base = basename(path)
const child = vhds.find(_ => _ !== undefined && _.header.parentUnicodeName === base)
if (child === undefined) {
await handler.unlink(path)
return 0
}
try {
const childPath = child.path
const mergedDataSize = await mergeVhd(handler, path, handler, childPath)
await handler.rename(path, childPath)
return mergedDataSize
} catch (error) {
handler.unlink(path).catch(warn)
throw error
}
}
async _findPartition(devicePath, partitionId) {
const partitions = await listPartitions(devicePath)
const partition = partitions.find(_ => _.id === partitionId)
if (partition === undefined) {
throw new Error(`partition ${partitionId} not found`)
}
return partition
}
_getLvmLogicalVolumes = Disposable.factory(this._getLvmLogicalVolumes)
_getLvmLogicalVolumes = deduped(this._getLvmLogicalVolumes, (devicePath, pvId, vgName) => [devicePath, pvId, vgName])
_getLvmLogicalVolumes = debounceResourceFactory(this._getLvmLogicalVolumes)
async *_getLvmLogicalVolumes(devicePath, pvId, vgName) {
yield this._getLvmPhysicalVolume(devicePath, pvId && (await this._findPartition(devicePath, pvId)))
await fromCallback(execFile, 'vgchange', ['-ay', vgName])
try {
yield lvs(['lv_name', 'lv_path'], vgName)
} finally {
await fromCallback(execFile, 'vgchange', ['-an', vgName])
}
}
_getLvmPhysicalVolume = Disposable.factory(this._getLvmPhysicalVolume)
_getLvmPhysicalVolume = deduped(this._getLvmPhysicalVolume, (devicePath, partition) => [devicePath, partition?.id])
_getLvmPhysicalVolume = debounceResourceFactory(this._getLvmPhysicalVolume)
async *_getLvmPhysicalVolume(devicePath, partition) {
const args = []
if (partition !== undefined) {
args.push('-o', partition.start * 512, '--sizelimit', partition.size)
}
args.push('--show', '-f', devicePath)
const path = (await fromCallback(execFile, 'losetup', args)).trim()
try {
await fromCallback(execFile, 'pvscan', ['--cache', path])
yield path
} finally {
try {
const vgNames = await pvs('vg_name', path)
await fromCallback(execFile, 'vgchange', ['-an', ...vgNames])
} finally {
await fromCallback(execFile, 'losetup', ['-d', path])
}
}
}
_getPartition = Disposable.factory(this._getPartition)
_getPartition = deduped(this._getPartition, (devicePath, partition) => [devicePath, partition?.id])
_getPartition = debounceResourceFactory(this._getPartition)
async *_getPartition(devicePath, partition) {
const options = ['loop', 'ro']
if (partition !== undefined) {
const { size, start } = partition
options.push(`sizelimit=${size}`)
if (start !== undefined) {
options.push(`offset=${start * 512}`)
}
}
const path = yield getTmpDir()
const mount = options => {
return fromCallback(execFile, 'mount', [
`--options=${options.join(',')}`,
`--source=${devicePath}`,
`--target=${path}`,
])
}
// `norecovery` option is used for ext3/ext4/xfs, if it fails it might be
// another fs, try without
try {
await mount([...options, 'norecovery'])
} catch (error) {
await mount(options)
}
try {
yield path
} finally {
await fromCallback(execFile, 'umount', ['--lazy', path])
}
}
_listLvmLogicalVolumes(devicePath, partition, results = []) {
return Disposable.use(this._getLvmPhysicalVolume(devicePath, partition), async path => {
const lvs = await pvs(['lv_name', 'lv_path', 'lv_size', 'vg_name'], path)
const partitionId = partition !== undefined ? partition.id : ''
lvs.forEach((lv, i) => {
const name = lv.lv_name
if (name !== '') {
results.push({
id: `${partitionId}/${lv.vg_name}/${name}`,
name,
size: lv.lv_size,
})
}
})
return results
})
}
_usePartitionFiles = Disposable.factory(this._usePartitionFiles)
async *_usePartitionFiles(diskId, partitionId, paths) {
const path = yield this.getPartition(diskId, partitionId)
const files = []
await asyncMap(paths, file =>
addDirectory(files, resolveSubpath(path, file), normalize('./' + file).replace(/\/+$/, ''))
)
return files
}
fetchPartitionFiles(diskId, partitionId, paths) {
const { promise, reject, resolve } = pDefer()
Disposable.use(
async function* () {
const files = yield this._usePartitionFiles(diskId, partitionId, paths)
const zip = new ZipFile()
files.forEach(({ realPath, metadataPath }) => zip.addFile(realPath, metadataPath))
zip.end()
const { outputStream } = zip
resolve(outputStream)
await fromEvent(outputStream, 'end')
}.bind(this)
).catch(error => {
warn(error)
reject(error)
})
return promise
}
async deleteDeltaVmBackups(backups) {
const handler = this._handler
let mergedDataSize = 0
await asyncMapSettled(backups, ({ _filename, vhds }) =>
Promise.all([
handler.unlink(_filename),
asyncMap(Object.values(vhds), async _ => {
mergedDataSize += await this._deleteVhd(resolveRelativeFromFile(_filename, _))
}),
])
)
return mergedDataSize
}
async deleteMetadataBackup(backupId) {
const uuidReg = '\\w{8}(-\\w{4}){3}-\\w{12}'
const metadataDirReg = 'xo-(config|pool-metadata)-backups'
const timestampReg = '\\d{8}T\\d{6}Z'
const regexp = new RegExp(`^${metadataDirReg}/${uuidReg}(/${uuidReg})?/${timestampReg}`)
if (!regexp.test(backupId)) {
throw new Error(`The id (${backupId}) not correspond to a metadata folder`)
}
await this._handler.rmtree(backupId)
}
async deleteOldMetadataBackups(dir, retention) {
const handler = this.handler
let list = await handler.list(dir)
list.sort()
list = list.filter(timestamp => /^\d{8}T\d{6}Z$/.test(timestamp)).slice(0, -retention)
await asyncMapSettled(list, timestamp => handler.rmtree(`${dir}/${timestamp}`))
}
async deleteFullVmBackups(backups) {
const handler = this._handler
await asyncMapSettled(backups, ({ _filename, xva }) =>
Promise.all([handler.unlink(_filename), handler.unlink(resolveRelativeFromFile(_filename, xva))])
)
}
async deleteVmBackup(filename) {
const metadata = JSON.parse(String(await this._handler.readFile(filename)))
metadata._filename = filename
if (metadata.mode === 'delta') {
await this.deleteDeltaVmBackups([metadata])
} else if (metadata.mode === 'full') {
await this.deleteFullVmBackups([metadata])
} else {
throw new Error(`no deleter for backup mode ${metadata.mode}`)
}
}
getDisk = Disposable.factory(this.getDisk)
getDisk = deduped(this.getDisk, diskId => [diskId])
getDisk = debounceResourceFactory(this.getDisk)
async *getDisk(diskId) {
const handler = this._handler
const diskPath = handler._getFilePath('/' + diskId)
const mountDir = yield getTmpDir()
await fromCallback(execFile, 'vhdimount', [diskPath, mountDir])
try {
let max = 0
let maxEntry
const entries = await readdir(mountDir)
entries.forEach(entry => {
const matches = RE_VHDI.exec(entry)
if (matches !== null) {
const value = +matches[1]
if (value > max) {
max = value
maxEntry = entry
}
}
})
if (max === 0) {
throw new Error('no disks found')
}
yield `${mountDir}/${maxEntry}`
} finally {
await fromCallback(execFile, 'fusermount', ['-uz', mountDir])
}
}
// partitionId values:
//
// - undefined: raw disk
// - `<partitionId>`: partitioned disk
// - `<pvId>/<vgName>/<lvName>`: LVM on a partitioned disk
// - `/<vgName>/lvName>`: LVM on a raw disk
getPartition = Disposable.factory(this.getPartition)
async *getPartition(diskId, partitionId) {
const devicePath = yield this.getDisk(diskId)
if (partitionId === undefined) {
return yield this._getPartition(devicePath)
}
const isLvmPartition = partitionId.includes('/')
if (isLvmPartition) {
const [pvId, vgName, lvName] = partitionId.split('/')
const lvs = yield this._getLvmLogicalVolumes(devicePath, pvId !== '' ? pvId : undefined, vgName)
return yield this._getPartition(lvs.find(_ => _.lv_name === lvName).lv_path)
}
return yield this._getPartition(devicePath, await this._findPartition(devicePath, partitionId))
}
async listAllVmBackups() {
const handler = this._handler
const backups = { __proto__: null }
await asyncMap(await handler.list(BACKUP_DIR), async vmUuid => {
const vmBackups = await this.listVmBackups(vmUuid)
backups[vmUuid] = vmBackups
})
return backups
}
listPartitionFiles(diskId, partitionId, path) {
return Disposable.use(this.getPartition(diskId, partitionId), async rootPath => {
path = resolveSubpath(rootPath, path)
const entriesMap = {}
await asyncMap(await readdir(path), async name => {
try {
const stats = await stat(`${path}/${name}`)
entriesMap[stats.isDirectory() ? `${name}/` : name] = {}
} catch (error) {
if (error == null || error.code !== 'ENOENT') {
throw error
}
}
})
return entriesMap
})
}
listPartitions(diskId) {
return Disposable.use(this.getDisk(diskId), async devicePath => {
const partitions = await listPartitions(devicePath)
if (partitions.length === 0) {
try {
// handle potential raw LVM physical volume
return await this._listLvmLogicalVolumes(devicePath, undefined, partitions)
} catch (error) {
return []
}
}
const results = []
await asyncMapSettled(partitions, partition =>
partition.type === LVM_PARTITION_TYPE
? this._listLvmLogicalVolumes(devicePath, partition, results)
: results.push(partition)
)
return results
})
}
async listPoolMetadataBackups() {
const handler = this._handler
const safeReaddir = createSafeReaddir(handler, 'listPoolMetadataBackups')
const backupsByPool = {}
await asyncMap(await safeReaddir(DIR_XO_POOL_METADATA_BACKUPS, { prependDir: true }), async scheduleDir =>
asyncMap(await safeReaddir(scheduleDir), async poolId => {
const backups = backupsByPool[poolId] ?? (backupsByPool[poolId] = [])
return asyncMap(await safeReaddir(`${scheduleDir}/${poolId}`, { prependDir: true }), async backupDir => {
try {
backups.push({
id: backupDir,
...JSON.parse(String(await handler.readFile(`${backupDir}/metadata.json`))),
})
} catch (error) {
warn(`listPoolMetadataBackups ${backupDir}`, {
error,
})
}
})
})
)
// delete empty entries and sort backups
Object.keys(backupsByPool).forEach(poolId => {
const backups = backupsByPool[poolId]
if (backups.length === 0) {
delete backupsByPool[poolId]
} else {
backups.sort(compareTimestamp)
}
})
return backupsByPool
}
async listVmBackups(vmUuid, predicate) {
const handler = this._handler
const backups = []
try {
const files = await handler.list(`${BACKUP_DIR}/${vmUuid}`, {
filter: isMetadataFile,
prependDir: true,
})
await asyncMap(files, async file => {
try {
const metadata = await this.readVmBackupMetadata(file)
if (predicate === undefined || predicate(metadata)) {
// inject an id usable by importVmBackupNg()
metadata.id = metadata._filename
backups.push(metadata)
}
} catch (error) {
warn(`listVmBackups ${file}`, { error })
}
})
} catch (error) {
let code
if (error == null || ((code = error.code) !== 'ENOENT' && code !== 'ENOTDIR')) {
throw error
}
}
return backups.sort(compareTimestamp)
}
async listXoMetadataBackups() {
const handler = this._handler
const safeReaddir = createSafeReaddir(handler, 'listXoMetadataBackups')
const backups = []
await asyncMap(await safeReaddir(DIR_XO_CONFIG_BACKUPS, { prependDir: true }), async scheduleDir =>
asyncMap(await safeReaddir(scheduleDir, { prependDir: true }), async backupDir => {
try {
backups.push({
id: backupDir,
...JSON.parse(String(await handler.readFile(`${backupDir}/metadata.json`))),
})
} catch (error) {
warn(`listXoMetadataBackups ${backupDir}`, { error })
}
})
)
return backups.sort(compareTimestamp)
}
async outputStream(path, input, { checksum = true, validator = noop } = {}) {
const handler = this._handler
input = await input
const tmpPath = `${dirname(path)}/.${basename(path)}`
const output = await handler.createOutputStream(tmpPath, {
checksum,
dirMode: this._dirMode,
})
try {
await Promise.all([fromCallback(pump, input, output), output.checksumWritten, input.task])
await validator(tmpPath)
await handler.rename(tmpPath, path, { checksum })
} catch (error) {
await handler.unlink(tmpPath, { checksum })
throw error
}
}
async readDeltaVmBackup(metadata) {
const handler = this._handler
const { vbds, vdis, vhds, vifs, vm } = metadata
const dir = dirname(metadata._filename)
const streams = {}
await asyncMapSettled(Object.entries(vdis), async ([id, vdi]) => {
streams[`${id}.vhd`] = await createSyntheticStream(handler, join(dir, vhds[id]))
})
return {
streams,
vbds,
vdis,
version: '1.0.0',
vifs,
vm,
}
}
readFullVmBackup(metadata) {
return this._handler.createReadStream(resolve('/', dirname(metadata._filename), metadata.xva))
}
async readVmBackupMetadata(path) {
return Object.defineProperty(JSON.parse(await this._handler.readFile(path)), '_filename', { value: path })
}
}
RemoteAdapter.prototype.cleanVm = function (vmDir) {
return Disposable.use(this._handler.lock(vmDir), () => cleanVm.apply(this, arguments))
}
exports.RemoteAdapter = RemoteAdapter
@@ -0,0 +1,24 @@
const { DIR_XO_POOL_METADATA_BACKUPS } = require('./RemoteAdapter')
const { PATH_DB_DUMP } = require('./_PoolMetadataBackup')
exports.RestoreMetadataBackup = class RestoreMetadataBackup {
constructor({ backupId, handler, xapi }) {
this._backupId = backupId
this._handler = handler
this._xapi = xapi
}
async run() {
const backupId = this._backupId
const handler = this._handler
const xapi = this._xapi
if (backupId.split('/')[0] === DIR_XO_POOL_METADATA_BACKUPS) {
return xapi.putResource(await handler.createReadStream(`${backupId}/data`), PATH_DB_DUMP, {
task: xapi.task_create('Import pool metadata'),
})
} else {
return String(await handler.readFile(`${backupId}/data.json`))
}
}
}
+181
View File
@@ -0,0 +1,181 @@
const Zone = require('node-zone')
const { SyncThenable } = require('./_syncThenable')
const logAfterEnd = () => {
throw new Error('task has already ended')
}
// Create a serializable object from an error.
//
// Otherwise some fields might be non-enumerable and missing from logs.
const serializeError = error =>
error instanceof Error
? {
...error, // Copy enumerable properties.
code: error.code,
message: error.message,
name: error.name,
stack: error.stack,
}
: error
exports.serializeError = serializeError
class TaskLogger {
constructor(logFn, parentId) {
this._log = logFn
this._parentId = parentId
this._taskId = undefined
}
get taskId() {
const taskId = this._taskId
if (taskId === undefined) {
throw new Error('start the task first')
}
return taskId
}
// create a subtask
fork() {
return new TaskLogger(this._log, this.taskId)
}
info(message, data) {
return this._log({
data,
event: 'info',
message,
taskId: this.taskId,
timestamp: Date.now(),
})
}
run(message, data, fn) {
if (arguments.length === 2) {
fn = data
data = undefined
}
return SyncThenable.tryUnwrap(
SyncThenable.fromFunction(() => {
if (this._taskId !== undefined) {
throw new Error('task has already started')
}
this._taskId = Math.random().toString(36).slice(2)
return this._log({
data,
event: 'start',
message,
parentId: this._parentId,
taskId: this.taskId,
timestamp: Date.now(),
})
})
.then(fn)
.then(
result => {
const log = this._log
this._log = logAfterEnd
return SyncThenable.resolve(
log({
event: 'end',
result,
status: 'success',
taskId: this.taskId,
timestamp: Date.now(),
})
).then(() => result)
},
error => {
const log = this._log
this._log = logAfterEnd
return SyncThenable.resolve(
log({
event: 'end',
result: serializeError(error),
status: 'failure',
taskId: this.taskId,
timestamp: Date.now(),
})
).then(() => {
throw error
})
}
)
)
}
warning(message, data) {
return this._log({
data,
event: 'warning',
message,
taskId: this.taskId,
timestamp: Date.now(),
})
}
wrapFn(fn, message, data) {
const logger = this
return function () {
const evaluate = v => (typeof v === 'function' ? v.apply(this, arguments) : v)
return logger.run(evaluate(message), evaluate(data), () => fn.apply(this, arguments))
}
}
}
const $$task = Symbol('current task logger')
const getCurrent = () => Zone.current.data[$$task]
const Task = {
info(message, data) {
const task = getCurrent()
if (task !== undefined) {
return task.info(message, data)
}
},
run({ name, data, onLog }, fn) {
let parentId
if (onLog === undefined) {
const parent = getCurrent()
if (parent === undefined) {
return fn()
}
onLog = parent._log
parentId = parent.taskId
}
const task = new TaskLogger(onLog, parentId)
const zone = Zone.current.fork('task')
zone.data[$$task] = task
return task.run(name, data, zone.wrap(fn))
},
warning(message, data) {
const task = getCurrent()
if (task !== undefined) {
return task.warning(message, data)
}
},
wrapFn(opts, fn) {
// compatibility with @decorateWith
if (typeof fn !== 'function') {
;[fn, opts] = [opts, fn]
}
const { name, data, onLog } = opts
return function () {
const evaluate = v => (typeof v === 'function' ? v.apply(this, arguments) : v)
return Task.run({ name: evaluate(name), data: evaluate(data), onLog }, () => fn.apply(this, arguments))
}
},
}
exports.Task = Task
View File
@@ -0,0 +1,119 @@
const { asyncMap, asyncMapSettled } = require('@xen-orchestra/async-map')
const ignoreErrors = require('promise-toolbox/ignoreErrors')
const { formatDateTime } = require('@xen-orchestra/xapi')
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { importDeltaVm, TAG_COPY_SRC } = require('./_deltaVm')
const { listReplicatedVms } = require('./_listReplicatedVms')
const { Task } = require('./Task')
exports.ContinuousReplicationWriter = class ContinuousReplicationWriter {
constructor(backup, sr, settings) {
this._backup = backup
this._settings = settings
this._sr = sr
this.transfer = Task.wrapFn(
{
name: 'export',
data: ({ deltaExport }) => ({
id: sr.uuid,
isFull: Object.values(deltaExport.vdis).some(vdi => vdi.other_config['xo:base_delta'] === undefined),
type: 'SR',
}),
},
this.transfer
)
}
async checkBaseVdis(baseUuidToSrcVdi, baseVm) {
const sr = this._sr
const replicatedVm = listReplicatedVms(sr.$xapi, this._backup.job.id, sr.uuid, this._backup.vm.uuid).find(
vm => vm.other_config[TAG_COPY_SRC] === baseVm.uuid
)
if (replicatedVm === undefined) {
return baseUuidToSrcVdi.clear()
}
const xapi = replicatedVm.$xapi
const replicatedVdis = new Set(
await asyncMap(await replicatedVm.$getDisks(), async vdiRef => {
const otherConfig = await xapi.getField('VDI', vdiRef, 'other_config')
return otherConfig[TAG_COPY_SRC]
})
)
for (const uuid of baseUuidToSrcVdi.keys()) {
if (!replicatedVdis.has(uuid)) {
baseUuidToSrcVdi.delete(uuid)
}
}
}
async prepare() {
const settings = this._settings
const { uuid: srUuid, $xapi: xapi } = this._sr
const { scheduleId, vm } = this._backup
// delete previous interrupted copies
ignoreErrors.call(asyncMapSettled(listReplicatedVms(xapi, scheduleId, undefined, vm.uuid), vm => vm.$destroy))
this._oldEntries = getOldEntries(settings.copyRetention - 1, listReplicatedVms(xapi, scheduleId, srUuid, vm.uuid))
if (settings.deleteFirst) {
await this._deleteOldEntries()
} else {
this.cleanup = this._deleteOldEntries
}
}
async _deleteOldEntries() {
return asyncMapSettled(this._oldEntries, vm => vm.$destroy())
}
async transfer({ timestamp, deltaExport, sizeContainers }) {
const sr = this._sr
const { job, scheduleId, vm } = this._backup
const { uuid: srUuid, $xapi: xapi } = sr
let targetVmRef
await Task.run({ name: 'transfer' }, async () => {
targetVmRef = await importDeltaVm(
{
__proto__: deltaExport,
vm: {
...deltaExport.vm,
tags: [...deltaExport.vm.tags, 'Continuous Replication'],
},
},
sr
)
return {
size: Object.values(sizeContainers).reduce((sum, { size }) => sum + size, 0),
}
})
const targetVm = await xapi.getRecord('VM', targetVmRef)
await Promise.all([
targetVm.ha_restart_priority !== '' &&
Promise.all([targetVm.set_ha_restart_priority(''), targetVm.add_tags('HA disabled')]),
targetVm.set_name_label(`${vm.name_label} - ${job.name} - (${formatFilenameDate(timestamp)})`),
targetVm.update_blocked_operations(
'start',
'Start operation for this vm is blocked, clone it if you want to use it.'
),
targetVm.update_other_config({
'xo:backup:sr': srUuid,
// these entries need to be added in case of offline backup
'xo:backup:datetime': formatDateTime(timestamp),
'xo:backup:job': job.id,
'xo:backup:schedule': scheduleId,
'xo:backup:vm': vm.uuid,
}),
])
}
}
@@ -0,0 +1,219 @@
const assert = require('assert')
const map = require('lodash/map')
const mapValues = require('lodash/mapValues')
const ignoreErrors = require('promise-toolbox/ignoreErrors')
const { asyncMap } = require('@xen-orchestra/async-map')
const { chainVhd, checkVhdChain, default: Vhd } = require('vhd-lib')
const { createLogger } = require('@xen-orchestra/log')
const { dirname } = require('path')
const { checkVhd } = require('./_checkVhd')
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { getVmBackupDir } = require('./_getVmBackupDir')
const { packUuid } = require('./_packUuid')
const { Task } = require('./Task')
const { warn } = createLogger('xo:backups:DeltaBackupWriter')
exports.DeltaBackupWriter = class DeltaBackupWriter {
constructor(backup, remoteId, settings) {
this._adapter = backup.remoteAdapters[remoteId]
this._backup = backup
this._settings = settings
this.transfer = Task.wrapFn(
{
name: 'export',
data: ({ deltaExport }) => ({
id: remoteId,
isFull: Object.values(deltaExport.vdis).some(vdi => vdi.other_config['xo:base_delta'] === undefined),
type: 'remote',
}),
},
this.transfer
)
this[settings.deleteFirst ? 'prepare' : 'cleanup'] = this._deleteOldEntries
}
async checkBaseVdis(baseUuidToSrcVdi) {
const { handler } = this._adapter
const backup = this._backup
const backupDir = getVmBackupDir(backup.vm.uuid)
const vdisDir = `${backupDir}/vdis/${backup.job.id}`
await asyncMap(baseUuidToSrcVdi, async ([baseUuid, srcVdi]) => {
let found = false
try {
const vhds = await handler.list(`${vdisDir}/${srcVdi.uuid}`, {
filter: _ => _[0] !== '.' && _.endsWith('.vhd'),
prependDir: true,
})
await asyncMap(vhds, async path => {
try {
await checkVhdChain(handler, path)
const vhd = new Vhd(handler, path)
await vhd.readHeaderAndFooter()
found = found || vhd.footer.uuid.equals(packUuid(baseUuid))
} catch (error) {
warn('checkBaseVdis', { error })
await ignoreErrors.call(handler.unlink(path))
}
})
} catch (error) {
warn('checkBaseVdis', { error })
}
if (!found) {
baseUuidToSrcVdi.delete(baseUuid)
}
})
}
async prepare() {
const adapter = this._adapter
const settings = this._settings
const { scheduleId, vm } = this._backup
const oldEntries = getOldEntries(
settings.exportRetention - 1,
await adapter.listVmBackups(vm.uuid, _ => _.mode === 'delta' && _.scheduleId === scheduleId)
)
this._oldEntries = oldEntries
// FIXME: implement optimized multiple VHDs merging with synthetic
// delta
//
// For the time being, limit the number of deleted backups by run
// because it can take a very long time and can lead to
// interrupted backup with broken VHD chain.
//
// The old backups will be eventually merged in future runs of the
// job.
const { maxMergedDeltasPerRun } = this._settings
if (oldEntries.length > maxMergedDeltasPerRun) {
oldEntries.length = maxMergedDeltasPerRun
}
if (settings.deleteFirst) {
await this._deleteOldEntries()
} else {
this.cleanup = this._deleteOldEntries
}
}
async _deleteOldEntries() {
return Task.run({ name: 'merge' }, async () => {
const adapter = this._adapter
const oldEntries = this._oldEntries
let size = 0
// delete sequentially from newest to oldest to avoid unnecessary merges
for (let i = oldEntries.length; i-- > 0; ) {
size += await adapter.deleteDeltaVmBackups([oldEntries[i]])
}
return {
size,
}
})
}
async transfer({ timestamp, deltaExport, sizeContainers }) {
const adapter = this._adapter
const backup = this._backup
const { job, scheduleId, vm } = backup
const jobId = job.id
const handler = adapter.handler
const backupDir = getVmBackupDir(vm.uuid)
// TODO: clean VM backup directory
const basename = formatFilenameDate(timestamp)
const vhds = mapValues(
deltaExport.vdis,
vdi =>
`vdis/${jobId}/${
vdi.type === 'suspend'
? // doesn't make sense to group by parent for memory because we
// don't do delta for it
vdi.uuid
: vdi.$snapshot_of$uuid
}/${basename}.vhd`
)
const metadataFilename = `${backupDir}/${basename}.json`
const metadataContent = {
jobId,
mode: job.mode,
scheduleId,
timestamp,
vbds: deltaExport.vbds,
vdis: deltaExport.vdis,
version: '2.0.0',
vifs: deltaExport.vifs,
vhds,
vm,
vmSnapshot: this._backup.exportedVm,
}
const { size } = await Task.run({ name: 'transfer' }, async () => {
await Promise.all(
map(deltaExport.vdis, async (vdi, id) => {
const path = `${backupDir}/${vhds[id]}`
const isDelta = vdi.other_config['xo:base_delta'] !== undefined
let parentPath
if (isDelta) {
const vdiDir = dirname(path)
parentPath = (
await handler.list(vdiDir, {
filter: filename => filename[0] !== '.' && filename.endsWith('.vhd'),
prependDir: true,
})
)
.sort()
.pop()
assert.notStrictEqual(parentPath, undefined, `missing parent of ${id}`)
parentPath = parentPath.slice(1) // remove leading slash
// TODO remove when this has been done before the export
await checkVhd(handler, parentPath)
}
await adapter.outputStream(path, deltaExport.streams[`${id}.vhd`], {
// no checksum for VHDs, because they will be invalidated by
// merges and chainings
checksum: false,
validator: tmpPath => checkVhd(handler, tmpPath),
})
if (isDelta) {
await chainVhd(handler, parentPath, handler, path)
}
// set the correct UUID in the VHD
const vhd = new Vhd(handler, path)
await vhd.readHeaderAndFooter()
vhd.footer.uuid = packUuid(vdi.uuid)
await vhd.readBlockAllocationTable() // required by writeFooter()
await vhd.writeFooter()
})
)
return {
size: Object.values(sizeContainers).reduce((sum, { size }) => sum + size, 0),
}
})
metadataContent.size = size
await handler.outputFile(metadataFilename, JSON.stringify(metadataContent), {
dirMode: backup.config.dirMode,
})
// TODO: run cleanup?
}
}
@@ -0,0 +1,85 @@
const ignoreErrors = require('promise-toolbox/ignoreErrors')
const { asyncMapSettled } = require('@xen-orchestra/async-map')
const { formatDateTime } = require('@xen-orchestra/xapi')
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { listReplicatedVms } = require('./_listReplicatedVms')
const { Task } = require('./Task')
exports.DisasterRecoveryWriter = class DisasterRecoveryWriter {
constructor(backup, sr, settings) {
this._backup = backup
this._settings = settings
this._sr = sr
this.run = Task.wrapFn(
{
name: 'export',
data: {
id: sr.uuid,
type: 'SR',
// necessary?
isFull: true,
},
},
this.run
)
}
async run({ timestamp, sizeContainer, stream }) {
const sr = this._sr
const settings = this._settings
const { job, scheduleId, vm } = this._backup
const { uuid: srUuid, $xapi: xapi } = sr
// delete previous interrupted copies
ignoreErrors.call(
asyncMapSettled(listReplicatedVms(xapi, scheduleId, undefined, vm.uuid), vm => xapi.VM_destroy(vm.$ref))
)
const oldVms = getOldEntries(settings.copyRetention - 1, listReplicatedVms(xapi, scheduleId, srUuid, vm.uuid))
const deleteOldBackups = () => asyncMapSettled(oldVms, vm => xapi.VM_destroy(vm.$ref))
const { deleteFirst } = settings
if (deleteFirst) {
await deleteOldBackups()
}
let targetVmRef
await Task.run({ name: 'transfer' }, async () => {
targetVmRef = await xapi.VM_import(stream, sr.$ref, vm =>
Promise.all([
vm.add_tags('Disaster Recovery'),
vm.ha_restart_priority !== '' && Promise.all([vm.set_ha_restart_priority(''), vm.add_tags('HA disabled')]),
vm.set_name_label(`${vm.name_label} - ${job.name} - (${formatFilenameDate(timestamp)})`),
])
)
return { size: sizeContainer.size }
})
const targetVm = await xapi.getRecord('VM', targetVmRef)
await Promise.all([
targetVm.update_blocked_operations(
'start',
'Start operation for this vm is blocked, clone it if you want to use it.'
),
targetVm.update_other_config({
'xo:backup:sr': srUuid,
// these entries need to be added in case of offline backup
'xo:backup:datetime': formatDateTime(timestamp),
'xo:backup:job': job.id,
'xo:backup:schedule': scheduleId,
'xo:backup:vm': vm.uuid,
}),
])
if (!deleteFirst) {
await deleteOldBackups()
}
}
}
@@ -0,0 +1,90 @@
const { formatFilenameDate } = require('./_filenameDate')
const { getOldEntries } = require('./_getOldEntries')
const { getVmBackupDir } = require('./_getVmBackupDir')
const { isValidXva } = require('./isValidXva')
const { Task } = require('./Task')
exports.FullBackupWriter = class FullBackupWriter {
constructor(backup, remoteId, settings) {
this._backup = backup
this._remoteId = remoteId
this._settings = settings
this.run = Task.wrapFn(
{
name: 'export',
data: {
id: remoteId,
type: 'remote',
// necessary?
isFull: true,
},
},
this.run
)
}
async run({ timestamp, sizeContainer, stream }) {
const backup = this._backup
const remoteId = this._remoteId
const settings = this._settings
const { job, scheduleId, vm } = backup
const adapter = backup.remoteAdapters[remoteId]
const handler = adapter.handler
const backupDir = getVmBackupDir(vm.uuid)
// TODO: clean VM backup directory
const oldBackups = getOldEntries(
settings.exportRetention - 1,
await adapter.listVmBackups(vm.uuid, _ => _.mode === 'full' && _.scheduleId === scheduleId)
)
const deleteOldBackups = () => adapter.deleteFullVmBackups(oldBackups)
const basename = formatFilenameDate(timestamp)
const dataBasename = basename + '.xva'
const dataFilename = backupDir + '/' + dataBasename
const metadataFilename = `${backupDir}/${basename}.json`
const metadata = {
jobId: job.id,
mode: job.mode,
scheduleId,
timestamp,
version: '2.0.0',
vm,
vmSnapshot: this._backup.exportedVm,
xva: './' + dataBasename,
}
const { deleteFirst } = settings
if (deleteFirst) {
await deleteOldBackups()
}
await Task.run({ name: 'transfer' }, async () => {
await adapter.outputStream(dataFilename, stream, {
validator: tmpPath => {
if (handler._getFilePath !== undefined) {
return isValidXva(handler._getFilePath('/' + tmpPath))
}
},
})
return { size: sizeContainer.size }
})
metadata.size = sizeContainer.size
await handler.outputFile(metadataFilename, JSON.stringify(metadata), {
dirMode: backup.config.dirMode,
})
if (!deleteFirst) {
await deleteOldBackups()
}
// TODO: run cleanup?
}
}
@@ -0,0 +1,75 @@
const { asyncMap } = require('@xen-orchestra/async-map')
const { DIR_XO_POOL_METADATA_BACKUPS } = require('./RemoteAdapter')
const { forkStreamUnpipe } = require('./_forkStreamUnpipe')
const { formatFilenameDate } = require('./_filenameDate')
const { Task } = require('./Task')
const PATH_DB_DUMP = '/pool/xmldbdump'
exports.PATH_DB_DUMP = PATH_DB_DUMP
exports.PoolMetadataBackup = class PoolMetadataBackup {
constructor({ config, job, pool, remoteAdapters, schedule, settings }) {
this._config = config
this._job = job
this._pool = pool
this._remoteAdapters = remoteAdapters
this._schedule = schedule
this._settings = settings
}
_exportPoolMetadata() {
const xapi = this._pool.$xapi
return xapi.getResource(PATH_DB_DUMP, {
task: xapi.task_create('Export pool metadata'),
})
}
async run() {
const timestamp = Date.now()
const { _job: job, _schedule: schedule, _pool: pool } = this
const poolDir = `${DIR_XO_POOL_METADATA_BACKUPS}/${schedule.id}/${pool.$id}`
const dir = `${poolDir}/${formatFilenameDate(timestamp)}`
const stream = await this._exportPoolMetadata()
const fileName = `${dir}/data`
const metadata = JSON.stringify(
{
jobId: job.id,
jobName: job.name,
pool,
poolMaster: pool.$master,
scheduleId: schedule.id,
scheduleName: schedule.name,
timestamp,
},
null,
2
)
const metaDataFileName = `${dir}/metadata.json`
await asyncMap(
Object.entries(this._remoteAdapters),
([remoteId, adapter]) =>
Task.run(
{
name: `Starting metadata backup for the pool (${pool.$id}) for the remote (${remoteId}). (${job.id})`,
data: {
id: remoteId,
type: 'remote',
},
},
async () => {
// forkStreamUnpipe should be used in a sync way, do not wait for a promise before using it
await adapter.outputStream(fileName, forkStreamUnpipe(stream), { checksum: false })
await adapter.handler.outputFile(metaDataFileName, metadata, {
dirMode: this._config.dirMode,
})
await adapter.deleteOldMetadataBackups(poolDir, this._settings.retentionPoolMetadata)
}
).catch(() => {}) // errors are handled by logs
)
}
}
+354
View File
@@ -0,0 +1,354 @@
const findLast = require('lodash/findLast')
const ignoreErrors = require('promise-toolbox/ignoreErrors')
const keyBy = require('lodash/keyBy')
const mapValues = require('lodash/mapValues')
const { asyncMap } = require('@xen-orchestra/async-map')
const { createLogger } = require('@xen-orchestra/log')
const { formatDateTime } = require('@xen-orchestra/xapi')
const { ContinuousReplicationWriter } = require('./_ContinuousReplicationWriter')
const { DeltaBackupWriter } = require('./_DeltaBackupWriter')
const { DisasterRecoveryWriter } = require('./_DisasterRecoveryWriter')
const { exportDeltaVm } = require('./_deltaVm')
const { forkStreamUnpipe } = require('./_forkStreamUnpipe')
const { FullBackupWriter } = require('./_FullBackupWriter')
const { getOldEntries } = require('./_getOldEntries')
const { Task } = require('./Task')
const { watchStreamSize } = require('./_watchStreamSize')
const { debug, warn } = createLogger('xo:backups:VmBackup')
const forkDeltaExport = deltaExport =>
Object.create(deltaExport, {
streams: {
value: mapValues(deltaExport.streams, forkStreamUnpipe),
},
})
exports.VmBackup = class VmBackup {
constructor({ config, getSnapshotNameLabel, job, remoteAdapters, remotes, schedule, settings, srs, vm }) {
this.config = config
this.job = job
this.remoteAdapters = remoteAdapters
this.remotes = remotes
this.scheduleId = schedule.id
this.timestamp = undefined
// VM currently backed up
this.vm = vm
const { tags } = this.vm
// VM (snapshot) that is really exported
this.exportedVm = undefined
this._fullVdisRequired = undefined
this._getSnapshotNameLabel = getSnapshotNameLabel
this._isDelta = job.mode === 'delta'
this._jobId = job.id
this._jobSnapshots = undefined
this._xapi = vm.$xapi
// Base VM for the export
this._baseVm = undefined
// Settings for this specific run (job, schedule, VM)
if (tags.includes('xo-memory-backup')) {
settings.checkpointSnapshot = true
}
if (tags.includes('xo-offline-backup')) {
settings.offlineSnapshot = true
}
this._settings = settings
// Create writers
{
const writers = []
this._writers = writers
const [BackupWriter, ReplicationWriter] = this._isDelta
? [DeltaBackupWriter, ContinuousReplicationWriter]
: [FullBackupWriter, DisasterRecoveryWriter]
const allSettings = job.settings
Object.keys(remoteAdapters).forEach(remoteId => {
const targetSettings = {
...settings,
...allSettings[remoteId],
}
if (targetSettings.exportRetention !== 0) {
writers.push(new BackupWriter(this, remoteId, targetSettings))
}
})
srs.forEach(sr => {
const targetSettings = {
...settings,
...allSettings[sr.uuid],
}
if (targetSettings.copyRetention !== 0) {
writers.push(new ReplicationWriter(this, sr, targetSettings))
}
})
}
}
// ensure the VM itself does not have any backup metadata which would be
// copied on manual snapshots and interfere with the backup jobs
async _cleanMetadata() {
const { vm } = this
if ('xo:backup:job' in vm.other_config) {
await vm.update_other_config({
'xo:backup:datetime': null,
'xo:backup:deltaChainLength': null,
'xo:backup:exported': null,
'xo:backup:job': null,
'xo:backup:schedule': null,
'xo:backup:vm': null,
})
}
}
async _snapshot() {
const { vm } = this
const xapi = this._xapi
const settings = this._settings
const doSnapshot = this._isDelta || vm.power_state === 'Running' || settings.snapshotRetention !== 0
if (doSnapshot) {
await Task.run({ name: 'snapshot' }, async () => {
if (!settings.bypassVdiChainsCheck) {
await vm.$assertHealthyVdiChains()
}
const snapshotRef = await vm[settings.checkpointSnapshot ? '$checkpoint' : '$snapshot']({
name_label: this._getSnapshotNameLabel(vm),
})
this.timestamp = Date.now()
await xapi.setFieldEntries('VM', snapshotRef, 'other_config', {
'xo:backup:datetime': formatDateTime(this.timestamp),
'xo:backup:job': this._jobId,
'xo:backup:schedule': this.scheduleId,
'xo:backup:vm': vm.uuid,
})
this.exportedVm = await xapi.getRecord('VM', snapshotRef)
return this.exportedVm.uuid
})
} else {
this.exportedVm = vm
this.timestamp = Date.now()
}
}
async _copyDelta() {
const { exportedVm } = this
const baseVm = this._baseVm
await asyncMap(this._writers, writer => writer.prepare && writer.prepare())
const deltaExport = await exportDeltaVm(exportedVm, baseVm, {
fullVdisRequired: this._fullVdisRequired,
})
const sizeContainers = mapValues(deltaExport.streams, watchStreamSize)
const timestamp = Date.now()
await asyncMap(this._writers, async writer => {
try {
await writer.transfer({
deltaExport: forkDeltaExport(deltaExport),
sizeContainers,
timestamp,
})
} catch (error) {
warn('copy failure', {
error,
target: writer.target,
vm: this.vm,
})
}
})
this._baseVm = exportedVm
if (baseVm !== undefined) {
await exportedVm.update_other_config(
'xo:backup:deltaChainLength',
String(+(baseVm.other_config['xo:backup:deltaChainLength'] ?? 0) + 1)
)
}
// not the case if offlineBackup
if (exportedVm.is_a_snapshot) {
await exportedVm.update_other_config('xo:backup:exported', 'true')
}
const size = Object.values(sizeContainers).reduce((sum, { size }) => sum + size, 0)
const end = Date.now()
const duration = end - timestamp
debug('transfer complete', {
duration,
speed: duration !== 0 ? (size * 1e3) / 1024 / 1024 / duration : 0,
size,
})
await asyncMap(this._writers, writer => writer.cleanup && writer.cleanup())
}
async _copyFull() {
const { compression } = this.job
const stream = await this._xapi.VM_export(this.exportedVm.$ref, {
compress: Boolean(compression) && (compression === 'native' ? 'gzip' : 'zstd'),
useSnapshot: false,
})
const sizeContainer = watchStreamSize(stream)
const timestamp = Date.now()
await asyncMap(this._writers, async writer => {
try {
await writer.run({
sizeContainer,
stream: forkStreamUnpipe(stream),
timestamp,
})
} catch (error) {
warn('copy failure', {
error,
target: writer.target,
vm: this.vm,
})
}
})
const { size } = sizeContainer
const end = Date.now()
const duration = end - timestamp
debug('transfer complete', {
duration,
speed: duration !== 0 ? (size * 1e3) / 1024 / 1024 / duration : 0,
size,
})
}
async _fetchJobSnapshots() {
const jobId = this._jobId
const vmRef = this.vm.$ref
const xapi = this._xapi
const snapshotsRef = await xapi.getField('VM', vmRef, 'snapshots')
const snapshotsOtherConfig = await asyncMap(snapshotsRef, ref => xapi.getField('VM', ref, 'other_config'))
const snapshots = []
snapshotsOtherConfig.forEach((other_config, i) => {
if (other_config['xo:backup:job'] === jobId) {
snapshots.push({ other_config, $ref: snapshotsRef[i] })
}
})
snapshots.sort((a, b) => (a.other_config['xo:backup:datetime'] < b.other_config['xo:backup:datetime'] ? -1 : 1))
this._jobSnapshots = snapshots
}
async _removeUnusedSnapshots() {
// TODO: handle all schedules (no longer existing schedules default to 0 retention)
const { scheduleId } = this
const scheduleSnapshots = this._jobSnapshots.filter(_ => _.other_config['xo:backup:schedule'] === scheduleId)
const baseVmRef = this._baseVm?.$ref
const xapi = this._xapi
await asyncMap(getOldEntries(this._settings.snapshotRetention, scheduleSnapshots), ({ $ref }) => {
if ($ref !== baseVmRef) {
return xapi.VM_destroy($ref)
}
})
}
async _selectBaseVm() {
const xapi = this._xapi
let baseVm = findLast(this._jobSnapshots, _ => 'xo:backup:exported' in _.other_config)
if (baseVm === undefined) {
return
}
const fullInterval = this._settings.fullInterval
const deltaChainLength = +(baseVm.other_config['xo:backup:deltaChainLength'] ?? 0) + 1
if (!(fullInterval === 0 || fullInterval > deltaChainLength)) {
return
}
const srcVdis = keyBy(await xapi.getRecords('VDI', await this.vm.$getDisks()), '$ref')
// resolve full record
baseVm = await xapi.getRecord('VM', baseVm.$ref)
const baseUuidToSrcVdi = new Map()
await asyncMap(await baseVm.$getDisks(), async baseRef => {
const snapshotOf = await xapi.getField('VDI', baseRef, 'snapshot_of')
const srcVdi = srcVdis[snapshotOf]
if (srcVdi !== undefined) {
baseUuidToSrcVdi.set(await xapi.getField('VDI', baseRef, 'uuid'), srcVdi)
}
})
const presentBaseVdis = new Map(baseUuidToSrcVdi)
const writers = this._writers
for (let i = 0, n = writers.length; presentBaseVdis.size !== 0 && i < n; ++i) {
await writers[i].checkBaseVdis(presentBaseVdis, baseVm)
}
if (presentBaseVdis.size === 0) {
return
}
const fullVdisRequired = new Set()
baseUuidToSrcVdi.forEach((srcVdi, baseUuid) => {
if (!presentBaseVdis.has(baseUuid)) {
fullVdisRequired.add(srcVdi.uuid)
}
})
this._baseVm = baseVm
this._fullVdisRequired = fullVdisRequired
}
async run() {
await this._fetchJobSnapshots()
if (this._isDelta) {
await this._selectBaseVm()
}
await this._cleanMetadata()
await this._removeUnusedSnapshots()
const { _settings: settings, vm } = this
const isRunning = vm.power_state === 'Running'
const startAfter = isRunning && (settings.offlineBackup ? 'backup' : settings.offlineSnapshot && 'snapshot')
if (startAfter) {
await vm.$callAsync('clean_shutdown')
}
try {
await this._snapshot()
if (startAfter === 'snapshot') {
ignoreErrors.call(vm.$callAsync('start', false, false))
}
if (this._writers.length !== 0) {
await (this._isDelta ? this._copyDelta() : this._copyFull())
}
} finally {
if (startAfter) {
ignoreErrors.call(vm.$callAsync('start', false, false))
}
await this._fetchJobSnapshots()
await this._removeUnusedSnapshots()
}
}
}
@@ -0,0 +1,62 @@
const { asyncMap } = require('@xen-orchestra/async-map')
const { DIR_XO_CONFIG_BACKUPS } = require('./RemoteAdapter')
const { formatFilenameDate } = require('./_filenameDate')
const { Task } = require('./Task')
exports.XoMetadataBackup = class XoMetadataBackup {
constructor({ config, job, remoteAdapters, schedule, settings }) {
this._config = config
this._job = job
this._remoteAdapters = remoteAdapters
this._schedule = schedule
this._settings = settings
}
async run() {
const timestamp = Date.now()
const { _job: job, _schedule: schedule } = this
const scheduleDir = `${DIR_XO_CONFIG_BACKUPS}/${schedule.id}`
const dir = `${scheduleDir}/${formatFilenameDate(timestamp)}`
const data = job.xoMetadata
const fileName = `${dir}/data.json`
const metadata = JSON.stringify(
{
jobId: job.id,
jobName: job.name,
scheduleId: schedule.id,
scheduleName: schedule.name,
timestamp,
},
null,
2
)
const metaDataFileName = `${dir}/metadata.json`
await asyncMap(
Object.entries(this._remoteAdapters),
([remoteId, adapter]) =>
Task.run(
{
name: `Starting XO metadata backup for the remote (${remoteId}). (${job.id})`,
data: {
id: remoteId,
type: 'remote',
},
},
async () => {
const handler = adapter.handler
const dirMode = this._config.dirMode
await handler.outputFile(fileName, data, { dirMode })
await handler.outputFile(metaDataFileName, metadata, {
dirMode,
})
await adapter.deleteOldMetadataBackups(scheduleDir, this._settings.retentionXoMetadata)
}
).catch(() => {}) // errors are handled by logs
)
}
}
+4
View File
@@ -0,0 +1,4 @@
exports.isMetadataFile = filename => filename.endsWith('.json')
exports.isVhdFile = filename => filename.endsWith('.vhd')
exports.isXvaFile = filename => filename.endsWith('.xva')
exports.isXvaSumFile = filename => filename.endsWith('.xva.cheksum')

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