Compare commits
801 Commits
xo-web-v5.
...
server-bas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6162ecff04 | ||
|
|
19d859e047 | ||
|
|
049d62873e | ||
|
|
c162a7d3b1 | ||
|
|
d759d3dfee | ||
|
|
daecf4db14 | ||
|
|
1e8318598a | ||
|
|
53450d1160 | ||
|
|
c0049b3223 | ||
|
|
3ea9ce0270 | ||
|
|
bb18ffd9e7 | ||
|
|
1064c04ab8 | ||
|
|
2d84027a59 | ||
|
|
98680508d3 | ||
|
|
74cbec468f | ||
|
|
31e89b0868 | ||
|
|
c12a7a6319 | ||
|
|
82b0df6058 | ||
|
|
b6bd67b62f | ||
|
|
877226014d | ||
|
|
7572d306a0 | ||
|
|
f2f4573064 | ||
|
|
b1641edff6 | ||
|
|
b5147256e9 | ||
|
|
06f596adc6 | ||
|
|
1f3b54e0c4 | ||
|
|
2ddfbe8566 | ||
|
|
c61a118e4f | ||
|
|
d69e61a634 | ||
|
|
14f0cbaec6 | ||
|
|
b313eb14ee | ||
|
|
7b47e40244 | ||
|
|
b52204817d | ||
|
|
377552103e | ||
|
|
688b65ccde | ||
|
|
6cb4faf33d | ||
|
|
78b83bb901 | ||
|
|
9ff6f60b66 | ||
|
|
624e10ed15 | ||
|
|
19e10bbb53 | ||
|
|
cca945e05b | ||
|
|
21901f2a75 | ||
|
|
ef7f943eee | ||
|
|
ec1062f9f2 | ||
|
|
2f67ed3138 | ||
|
|
ce912db30e | ||
|
|
41d790f346 | ||
|
|
bf426e15ec | ||
|
|
e4403baeb9 | ||
|
|
61101b00a1 | ||
|
|
69f8ffcfeb | ||
|
|
6b8042291c | ||
|
|
ffc0c83b50 | ||
|
|
8ccd4c269a | ||
|
|
934ec86f93 | ||
|
|
23be38b5fa | ||
|
|
fe7f74e46b | ||
|
|
a3fd78f8e2 | ||
|
|
137bad6f7b | ||
|
|
17df6fc764 | ||
|
|
2e51c8a124 | ||
|
|
5588a46366 | ||
|
|
a8122f9add | ||
|
|
5568be91d2 | ||
|
|
a04bd6f93c | ||
|
|
56d63b10e4 | ||
|
|
2c97643b10 | ||
|
|
679f403648 | ||
|
|
d482c707f6 | ||
|
|
2ec9641783 | ||
|
|
dab1788a3b | ||
|
|
47bb79cce1 | ||
|
|
41dbc20be9 | ||
|
|
10a631ec96 | ||
|
|
830e5aed96 | ||
|
|
7db573885b | ||
|
|
a74d56ebc6 | ||
|
|
ff7d84297e | ||
|
|
3a76509fe9 | ||
|
|
ac4de9ab0f | ||
|
|
471f397418 | ||
|
|
73bbdf6d4e | ||
|
|
7f26aea585 | ||
|
|
1c767b709f | ||
|
|
0ced82c885 | ||
|
|
21dd195b0d | ||
|
|
6aa6cfba8e | ||
|
|
fd7d52d38b | ||
|
|
a47bb14364 | ||
|
|
d6e6fa5735 | ||
|
|
46da11a52e | ||
|
|
68e3dc21e4 | ||
|
|
7232cc45b4 | ||
|
|
be5a297248 | ||
|
|
257031b1bc | ||
|
|
c9db9fa17a | ||
|
|
13f961a422 | ||
|
|
3b38e0c4e1 | ||
|
|
07526efe61 | ||
|
|
8753c02adb | ||
|
|
6a0bbfa447 | ||
|
|
21faaeb33d | ||
|
|
0525fc5909 | ||
|
|
a1a53bb285 | ||
|
|
0c453c4415 | ||
|
|
d0406f9736 | ||
|
|
ba74b8603d | ||
|
|
c675a4d61d | ||
|
|
965c45bc70 | ||
|
|
139a22602a | ||
|
|
e0e4969198 | ||
|
|
08d69d95b3 | ||
|
|
4e6c507ba9 | ||
|
|
fd06374365 | ||
|
|
a07ebc636a | ||
|
|
4c151ac9aa | ||
|
|
05c425698f | ||
|
|
2a961979e6 | ||
|
|
211ede92cc | ||
|
|
256af03772 | ||
|
|
654fd5a4f9 | ||
|
|
541d90e49f | ||
|
|
974e7038e7 | ||
|
|
e2f5b30aa9 | ||
|
|
3483e7d9e0 | ||
|
|
56cb20a1af | ||
|
|
64929653dd | ||
|
|
c955da9bc6 | ||
|
|
291354fa8e | ||
|
|
905d736512 | ||
|
|
3406d6e2a9 | ||
|
|
fc10b5ffb9 | ||
|
|
f89c313166 | ||
|
|
7c734168d0 | ||
|
|
1e7bfec2ce | ||
|
|
1eb0603b4e | ||
|
|
4b32730ce8 | ||
|
|
ad083c1d9b | ||
|
|
b4f84c2de2 | ||
|
|
fc17443ce4 | ||
|
|
342ae06b21 | ||
|
|
093fb7f959 | ||
|
|
f6472424ad | ||
|
|
31ed3767c6 | ||
|
|
366acb65ea | ||
|
|
7c6946931b | ||
|
|
5d971433a5 | ||
|
|
05264b326b | ||
|
|
fdd5c6bfd8 | ||
|
|
42c3528c2f | ||
|
|
18640714f1 | ||
|
|
cda4d3399b | ||
|
|
4da8af6e69 | ||
|
|
b535565612 | ||
|
|
bef39b8a96 | ||
|
|
fb2502a031 | ||
|
|
0b90befda1 | ||
|
|
f9800f104a | ||
|
|
99134cc381 | ||
|
|
66ca08da6d | ||
|
|
5eb7ece6ba | ||
|
|
6b3d334e76 | ||
|
|
14f5fd8f73 | ||
|
|
5f73aee0df | ||
|
|
f8666ba367 | ||
|
|
9e80f76dd8 | ||
|
|
c76a5eaf67 | ||
|
|
cd378f0168 | ||
|
|
7d51ff0cf5 | ||
|
|
47819ea956 | ||
|
|
c7e3560c98 | ||
|
|
b24400b21d | ||
|
|
6c1d651687 | ||
|
|
e7757b53e7 | ||
|
|
a6d182e92d | ||
|
|
925eca1463 | ||
|
|
8b454f0d39 | ||
|
|
7c4d110353 | ||
|
|
6df55523b6 | ||
|
|
3ec6a24634 | ||
|
|
164b4218c4 | ||
|
|
56df8a6477 | ||
|
|
47a83b312d | ||
|
|
41a28ae088 | ||
|
|
436a8755ae | ||
|
|
960b179d95 | ||
|
|
0f0d0e1076 | ||
|
|
a8bd0d8075 | ||
|
|
986d3af685 | ||
|
|
1833f9ffdf | ||
|
|
30a6877f8a | ||
|
|
aaae2583c7 | ||
|
|
7f24afc2e7 | ||
|
|
0040923e12 | ||
|
|
844efb88d8 | ||
|
|
9efc3dd1fb | ||
|
|
67853bad8e | ||
|
|
faa8e1441a | ||
|
|
5c54611d1b | ||
|
|
dcf55e4385 | ||
|
|
2b0f1b6aab | ||
|
|
ae6cc8eea3 | ||
|
|
5279fa49a7 | ||
|
|
dcd8a62784 | ||
|
|
8c197b0e1a | ||
|
|
aed824b200 | ||
|
|
036b30212e | ||
|
|
3451ab3f50 | ||
|
|
0d0a92c2b1 | ||
|
|
aa19bc7bf5 | ||
|
|
347759b2e7 | ||
|
|
352230446c | ||
|
|
3eff8102e1 | ||
|
|
6693d845d9 | ||
|
|
4d79c462db | ||
|
|
c44ef6a1dc | ||
|
|
f0996fcfa7 | ||
|
|
54bc384d37 | ||
|
|
504fc1efe8 | ||
|
|
f4179b93fb | ||
|
|
564252c198 | ||
|
|
802a7a4463 | ||
|
|
3b3d6ba13c | ||
|
|
7350bf58e2 | ||
|
|
d37e29afc6 | ||
|
|
40de8c9e23 | ||
|
|
c81eac13c8 | ||
|
|
a6e1860f0d | ||
|
|
03eb2d81f0 | ||
|
|
171710b5e8 | ||
|
|
bed76429c2 | ||
|
|
d19f9b5062 | ||
|
|
38081d9822 | ||
|
|
54e278d3f7 | ||
|
|
181ed1b1a5 | ||
|
|
fb2d325ccb | ||
|
|
5f94a52537 | ||
|
|
c69b50c5d2 | ||
|
|
1c72f89178 | ||
|
|
14bd16da14 | ||
|
|
11a57f4618 | ||
|
|
57f35aff90 | ||
|
|
60e63a307f | ||
|
|
175e878ea6 | ||
|
|
5c960a3213 | ||
|
|
5dfb299e37 | ||
|
|
3890d4d9d1 | ||
|
|
77c62d6e7d | ||
|
|
ba54b53194 | ||
|
|
b4ef7352f2 | ||
|
|
1ce3368530 | ||
|
|
a4b32f3cb7 | ||
|
|
ee9cc05ae0 | ||
|
|
b8ccf2b0d6 | ||
|
|
886b499b94 | ||
|
|
07924d5621 | ||
|
|
43f3367ae4 | ||
|
|
454c73f42f | ||
|
|
041df698d5 | ||
|
|
97081f1219 | ||
|
|
f6792bf080 | ||
|
|
88635f31d6 | ||
|
|
abd0f115fc | ||
|
|
e9766c76c1 | ||
|
|
570506b324 | ||
|
|
11889880eb | ||
|
|
a86abde893 | ||
|
|
2cfe3360d8 | ||
|
|
60d75cb8ee | ||
|
|
68838e310a | ||
|
|
161de6cb7c | ||
|
|
af5a9b644b | ||
|
|
785426eab5 | ||
|
|
9267aef498 | ||
|
|
ae27a07578 | ||
|
|
131b2a35aa | ||
|
|
5a89601b24 | ||
|
|
2528bbc552 | ||
|
|
7c3a480003 | ||
|
|
80eac8443d | ||
|
|
a97234c48d | ||
|
|
53ea58c2f6 | ||
|
|
d867524c6b | ||
|
|
5edf9bde78 | ||
|
|
770ea55872 | ||
|
|
4eb0101c5b | ||
|
|
5d7af94abf | ||
|
|
b729b8f7c8 | ||
|
|
064e69d943 | ||
|
|
d880931951 | ||
|
|
f24741cd32 | ||
|
|
45c7017e83 | ||
|
|
7cfb891e6b | ||
|
|
fc8604e896 | ||
|
|
6b5e94103d | ||
|
|
aee4679ae5 | ||
|
|
2c2c930fce | ||
|
|
3f309e4db5 | ||
|
|
d26be402db | ||
|
|
a571e83005 | ||
|
|
10d5228eb2 | ||
|
|
7ed49b476f | ||
|
|
5396b90695 | ||
|
|
a6983d4e7b | ||
|
|
a3d1c76f67 | ||
|
|
15fab226b7 | ||
|
|
5a065d5a05 | ||
|
|
de81f3ffbb | ||
|
|
9103369cf6 | ||
|
|
7be36e6d0d | ||
|
|
a00e3e6f41 | ||
|
|
82ba02b4f3 | ||
|
|
d70ae6ebe3 | ||
|
|
f6c411a261 | ||
|
|
b606eaf9ee | ||
|
|
516edd1b09 | ||
|
|
e31c3b1f27 | ||
|
|
619818f968 | ||
|
|
79a80a1adf | ||
|
|
7cef48b995 | ||
|
|
7d3d1b1544 | ||
|
|
3f935f271d | ||
|
|
89935a1517 | ||
|
|
c67af4fb2f | ||
|
|
0b4adc36a0 | ||
|
|
44776b795f | ||
|
|
bec73a1c43 | ||
|
|
6ce35fdfa8 | ||
|
|
dabc2d0442 | ||
|
|
0527d3bc2b | ||
|
|
a7cfb71070 | ||
|
|
52003bedb4 | ||
|
|
a02fb8e739 | ||
|
|
60fad187a2 | ||
|
|
e8cd1e070f | ||
|
|
de6620be12 | ||
|
|
72dee73faa | ||
|
|
d8ce27907d | ||
|
|
3d8891d518 | ||
|
|
97742ccdc2 | ||
|
|
82fec86179 | ||
|
|
be83b53875 | ||
|
|
85fda0c18b | ||
|
|
a89f8fbd9c | ||
|
|
efdfa1f2f7 | ||
|
|
5bd61e3fb0 | ||
|
|
a45f83b646 | ||
|
|
16135b8e37 | ||
|
|
b011e8656f | ||
|
|
215432be6c | ||
|
|
d373760412 | ||
|
|
a1de04e285 | ||
|
|
23e16732fd | ||
|
|
5efac84b8b | ||
|
|
2cbc7b7d7d | ||
|
|
b1acbaecc2 | ||
|
|
6d61e8efff | ||
|
|
482e6b3cb3 | ||
|
|
445b13ec29 | ||
|
|
116af372dc | ||
|
|
970952783c | ||
|
|
e59cf13456 | ||
|
|
d0cfddce19 | ||
|
|
30b2a8dd8d | ||
|
|
b811ee7e7e | ||
|
|
ebe7f6784a | ||
|
|
e40792378f | ||
|
|
cc9c8fb891 | ||
|
|
ca06c4d403 | ||
|
|
c8aa058ede | ||
|
|
34169d685e | ||
|
|
d5a9d36815 | ||
|
|
c7aaeca530 | ||
|
|
863e4f0c19 | ||
|
|
0226e0553d | ||
|
|
02995d278f | ||
|
|
78a2104bcc | ||
|
|
4e9d143996 | ||
|
|
0811e5c765 | ||
|
|
b2cf2edd43 | ||
|
|
db493f6887 | ||
|
|
2cd0dec480 | ||
|
|
29024888fb | ||
|
|
dbcaab2bc1 | ||
|
|
28d445ae1c | ||
|
|
530360f859 | ||
|
|
738c55bad0 | ||
|
|
4b09bc85f5 | ||
|
|
5bc67d3570 | ||
|
|
f7ae6222b7 | ||
|
|
1e50dab093 | ||
|
|
d1935bf778 | ||
|
|
70a346d11e | ||
|
|
fd39a2063d | ||
|
|
682512fffe | ||
|
|
b13f91ec8d | ||
|
|
a140fc09ac | ||
|
|
f403a7e753 | ||
|
|
dfe5f412eb | ||
|
|
033d784c52 | ||
|
|
62c3fa13ca | ||
|
|
ce338cb6ca | ||
|
|
003eadc8fd | ||
|
|
8782151c5d | ||
|
|
b22c74c5a8 | ||
|
|
254fa36c01 | ||
|
|
a3e4253005 | ||
|
|
2388593b8a | ||
|
|
cdced63c1b | ||
|
|
45e1d1ecef | ||
|
|
f44447ce71 | ||
|
|
238e9cd8cc | ||
|
|
e171d8ed0e | ||
|
|
bd3399e04b | ||
|
|
2b4443f333 | ||
|
|
ab6548122f | ||
|
|
f81573d999 | ||
|
|
84ccebb858 | ||
|
|
530bc50e7c | ||
|
|
57e490fc23 | ||
|
|
61e902c094 | ||
|
|
8378ba77d6 | ||
|
|
c9e30b74e2 | ||
|
|
af944fd2e3 | ||
|
|
bcc0e76f1d | ||
|
|
95078d250a | ||
|
|
4b16a2c0c5 | ||
|
|
b8524732ce | ||
|
|
814fee4f47 | ||
|
|
d641d35d5c | ||
|
|
7464d95b57 | ||
|
|
8924a64622 | ||
|
|
3d6aa667fe | ||
|
|
147c3d2e7b | ||
|
|
ac298c3be3 | ||
|
|
e88848c44a | ||
|
|
cd518e3e4c | ||
|
|
114d521636 | ||
|
|
24d4fad394 | ||
|
|
6d8785e689 | ||
|
|
508cbf0a82 | ||
|
|
c83f56166d | ||
|
|
7199e1a214 | ||
|
|
85d55e97e7 | ||
|
|
cc2c71c076 | ||
|
|
9ca273b2c4 | ||
|
|
b85c2f35b6 | ||
|
|
fdd79885f9 | ||
|
|
b2eb970796 | ||
|
|
3ee9c1b550 | ||
|
|
2566c24753 | ||
|
|
49e1b0ba7e | ||
|
|
453c329f14 | ||
|
|
abad2944fb | ||
|
|
27193f38f3 | ||
|
|
d3dc94e210 | ||
|
|
6dad860635 | ||
|
|
0362ac8909 | ||
|
|
e7b79f83d1 | ||
|
|
62379c1e41 | ||
|
|
23b422e3df | ||
|
|
f8e6dee635 | ||
|
|
c8e9b287f4 | ||
|
|
c9412dbcd0 | ||
|
|
77222e9e6b | ||
|
|
2827544409 | ||
|
|
9d0f24eae1 | ||
|
|
db0a399da1 | ||
|
|
6e527947be | ||
|
|
e7051c1129 | ||
|
|
3196c7ca09 | ||
|
|
0e1e32d241 | ||
|
|
a34912fb0d | ||
|
|
c7c6e0e2ff | ||
|
|
1e529c995a | ||
|
|
7be1c7a47b | ||
|
|
b17380443b | ||
|
|
59e68682bd | ||
|
|
b7a92cfe92 | ||
|
|
5ebe27da49 | ||
|
|
42df6ba6fa | ||
|
|
8210fddfab | ||
|
|
f55ed273c5 | ||
|
|
d67e95af7b | ||
|
|
0b0f235252 | ||
|
|
36a5f52068 | ||
|
|
31266728f7 | ||
|
|
87d2096ed7 | ||
|
|
8c79ea4ce3 | ||
|
|
c73a4204cb | ||
|
|
0b3c2cc252 | ||
|
|
2bd3ca1d0b | ||
|
|
ce8649d991 | ||
|
|
9bd563b111 | ||
|
|
6ceb924a85 | ||
|
|
c2ef0ded43 | ||
|
|
6081a6f6db | ||
|
|
a0d92a0b1d | ||
|
|
3cf1f7ede2 | ||
|
|
5757afa1d8 | ||
|
|
86e9b9c1b8 | ||
|
|
1cdd1fa00e | ||
|
|
9d12759c68 | ||
|
|
d47f66548d | ||
|
|
594341fab6 | ||
|
|
4e88125cbe | ||
|
|
13237180a2 | ||
|
|
f64d7e0b6e | ||
|
|
040a6930a4 | ||
|
|
c54b9189a6 | ||
|
|
8882f1b019 | ||
|
|
ae6416c4d2 | ||
|
|
8faed87656 | ||
|
|
0983f05969 | ||
|
|
d43e2544a1 | ||
|
|
ca83d11ac8 | ||
|
|
1cdcdd9b5f | ||
|
|
cc7806e35b | ||
|
|
0ee48b6623 | ||
|
|
8c02e0efbd | ||
|
|
34d3ca82bc | ||
|
|
43822d3667 | ||
|
|
f4ac73b3b4 | ||
|
|
f084b6def9 | ||
|
|
a00d101ff7 | ||
|
|
9d5900d9b6 | ||
|
|
28fb4e8216 | ||
|
|
bec4dbe652 | ||
|
|
72cc14f508 | ||
|
|
d20941cc2c | ||
|
|
9cb8a05316 | ||
|
|
dccd799f6d | ||
|
|
b42b3d1b01 | ||
|
|
a40d6f772a | ||
|
|
6e9bfd18d9 | ||
|
|
3b92dd0139 | ||
|
|
564d53610a | ||
|
|
b4c7b8ac7f | ||
|
|
7acd90307b | ||
|
|
d3ec76c19f | ||
|
|
fb9425e503 | ||
|
|
688cb20674 | ||
|
|
c63be20bea | ||
|
|
df36633223 | ||
|
|
3597621d88 | ||
|
|
8387684839 | ||
|
|
f261f395f1 | ||
|
|
f27170ff0e | ||
|
|
d82c951db6 | ||
|
|
41ca853e03 | ||
|
|
d75580e11d | ||
|
|
a08d098265 | ||
|
|
a64960ddd0 | ||
|
|
875681b8ce | ||
|
|
a03dcbbf55 | ||
|
|
97cabbbc69 | ||
|
|
13725a9e21 | ||
|
|
f47df961f7 | ||
|
|
2f644d5eeb | ||
|
|
4b292bb78c | ||
|
|
804891cc81 | ||
|
|
d335e06371 | ||
|
|
477058ad23 | ||
|
|
eb3b68401d | ||
|
|
865d2df124 | ||
|
|
88160bae1d | ||
|
|
f581e93b88 | ||
|
|
876850a7a7 | ||
|
|
21a7cf7158 | ||
|
|
5edee4bae0 | ||
|
|
916ca5576a | ||
|
|
6c861bfd1f | ||
|
|
56961b55bd | ||
|
|
cdcd7154ba | ||
|
|
654a2ee870 | ||
|
|
903634073a | ||
|
|
0d4818feb6 | ||
|
|
d6aa40679b | ||
|
|
b7cc31c94d | ||
|
|
6860156b6f | ||
|
|
29486c9ce2 | ||
|
|
7cfa6a5da4 | ||
|
|
2563be472b | ||
|
|
7289e856d9 | ||
|
|
975de1954e | ||
|
|
95bcf0c080 | ||
|
|
f900a5ef4f | ||
|
|
7f1ab529ae | ||
|
|
49fc86e4b1 | ||
|
|
924aef84f1 | ||
|
|
96e6e2b72a | ||
|
|
71997d4e65 | ||
|
|
447f2f9506 | ||
|
|
79aef9024b | ||
|
|
fdf6f4fdf3 | ||
|
|
4d1eaaaade | ||
|
|
bdad6c0f6d | ||
|
|
ff1ca5d933 | ||
|
|
2cf4c494a4 | ||
|
|
95ac0a861a | ||
|
|
746c301f39 | ||
|
|
6455b12b58 | ||
|
|
485b8fe993 | ||
|
|
d7527f280c | ||
|
|
d57fa4375d | ||
|
|
d9e42c6625 | ||
|
|
28293d3fce | ||
|
|
d505401446 | ||
|
|
fafc24aeae | ||
|
|
f78ef0d208 | ||
|
|
8384cc3652 | ||
|
|
60aa18a229 | ||
|
|
3d64b42a89 | ||
|
|
b301997d4b | ||
|
|
ab34743250 | ||
|
|
bc14a1d167 | ||
|
|
2886ec116f | ||
|
|
c2beb2a5fa | ||
|
|
d6ac10f527 | ||
|
|
9dcd8a707a | ||
|
|
e1e97ef158 | ||
|
|
5d6b37f81a | ||
|
|
e1da08ba38 | ||
|
|
1dfb50fefd | ||
|
|
5c06ebc9c8 | ||
|
|
52a9270fb0 | ||
|
|
82247d7422 | ||
|
|
b34688043f | ||
|
|
ce4bcbd19d | ||
|
|
cde9a02c32 | ||
|
|
fe1da4ea12 | ||
|
|
a73306817b | ||
|
|
54e683d3d4 | ||
|
|
f49910ca82 | ||
|
|
4052f7f736 | ||
|
|
b47e097983 | ||
|
|
e44dbfb2a4 | ||
|
|
7d69dd9400 | ||
|
|
e6aae8fcfa | ||
|
|
da800b3391 | ||
|
|
3a574bcecc | ||
|
|
1bb0e234e7 | ||
|
|
b7e14ebf2a | ||
|
|
2af1207702 | ||
|
|
ecfed30e6e | ||
|
|
d06c3e3dd8 | ||
|
|
16b3fbeb16 | ||
|
|
0938804947 | ||
|
|
851bcf9816 | ||
|
|
9f6fc785bc | ||
|
|
56636bf5d4 | ||
|
|
3899a65167 | ||
|
|
628e53c1c3 | ||
|
|
0b689d99fa | ||
|
|
9fa424dd8d | ||
|
|
3e6f2eecfa | ||
|
|
cc655c8ba8 | ||
|
|
78aa0474ee | ||
|
|
9caefa2f49 | ||
|
|
478726fa3b | ||
|
|
f64917ec52 | ||
|
|
2bc25f91c4 | ||
|
|
623d7ffe2f | ||
|
|
07510b5099 | ||
|
|
9f21f9a7bc | ||
|
|
93da70709e | ||
|
|
00436e744a | ||
|
|
1e642fc512 | ||
|
|
6baef2450c | ||
|
|
600f34f85a | ||
|
|
6c0c6bc5c4 | ||
|
|
fcd62ed3cd | ||
|
|
cd0064d19c | ||
|
|
785f2e3a6d | ||
|
|
c2925f7c1e | ||
|
|
60814d8b58 | ||
|
|
2dec448f2c | ||
|
|
b71f4f6800 | ||
|
|
558083a916 | ||
|
|
b4baa6cd7b | ||
|
|
1ab2cdeed3 | ||
|
|
83c0281a33 | ||
|
|
437b0b0240 | ||
|
|
5c48697eda | ||
|
|
0feea5b7a6 | ||
|
|
9eb27fdd5e | ||
|
|
6e4a64232a | ||
|
|
4bbedeeea9 | ||
|
|
b5c004e870 | ||
|
|
a0ef1ab4f4 | ||
|
|
c9172a11a8 | ||
|
|
a0feee912e | ||
|
|
8e42b7b891 | ||
|
|
147d7e773f | ||
|
|
759ab1c5ee | ||
|
|
4c1581d845 | ||
|
|
e1c6e4347a | ||
|
|
256f117bbf | ||
|
|
3b0acf82c7 | ||
|
|
3a12f3d6c7 | ||
|
|
335ac5a595 | ||
|
|
d0e2e97007 | ||
|
|
85e1baa2dc | ||
|
|
0c66c39211 | ||
|
|
250afa38ca | ||
|
|
b7e58eeb3f | ||
|
|
6f024d78a6 | ||
|
|
1e48096f36 | ||
|
|
ccf6a1bedb | ||
|
|
3639edb4db | ||
|
|
d3bbe0b3b6 | ||
|
|
e8ab101993 | ||
|
|
ef98b10063 | ||
|
|
84943e7fe6 | ||
|
|
d0fa5ff385 | ||
|
|
3609559ced | ||
|
|
950c780122 | ||
|
|
32b510ef40 | ||
|
|
4cc33ed29b | ||
|
|
d72906a6ba | ||
|
|
d577b51a86 | ||
|
|
63d4865427 | ||
|
|
1355477e37 | ||
|
|
d50e1b4e02 | ||
|
|
606ae41698 | ||
|
|
b6ee5ae779 | ||
|
|
aeb1b2c30f | ||
|
|
35ace281cc | ||
|
|
6cd056eee5 | ||
|
|
6c664bfaa7 | ||
|
|
8890d445dc | ||
|
|
7a7db1ea08 | ||
|
|
e585a3e5c4 | ||
|
|
7336032009 | ||
|
|
d29bc63b24 | ||
|
|
2a9bd1d4cb | ||
|
|
6578c14292 | ||
|
|
ceee93883f | ||
|
|
dae8fd2370 | ||
|
|
48f8322390 | ||
|
|
7df833bd9f | ||
|
|
2d639e191a | ||
|
|
db758c6806 | ||
|
|
6822e4ac0c | ||
|
|
14b1b07ecd | ||
|
|
3c71a20bb2 | ||
|
|
8f73619ba1 | ||
|
|
0ee6e5a35f | ||
|
|
22692757e6 | ||
|
|
ed9584270d | ||
|
|
5a5c35a1c9 | ||
|
|
1f842e4fe4 | ||
|
|
9275c4a6d6 | ||
|
|
9c7e61cbf3 | ||
|
|
69a6066fd8 | ||
|
|
47d2d09e50 | ||
|
|
da648e0a78 | ||
|
|
9e1c526d51 | ||
|
|
d81998f91c | ||
|
|
a717d9b8f3 | ||
|
|
31d1243a14 | ||
|
|
2424222964 | ||
|
|
370b245d65 | ||
|
|
c4dfcc27e3 | ||
|
|
dfa870a777 | ||
|
|
572375fff4 | ||
|
|
ed1caee9f8 | ||
|
|
6f7757c81b | ||
|
|
4c92965313 | ||
|
|
bbce96eb67 | ||
|
|
e3cb7bd4c7 | ||
|
|
79599bf831 | ||
|
|
1ab67bc225 | ||
|
|
37df213771 | ||
|
|
d48ffdb14f | ||
|
|
766cdc9f59 | ||
|
|
21a40c9d14 | ||
|
|
9275e9d006 | ||
|
|
ef9fe025e0 | ||
|
|
05694a8cda | ||
|
|
e6304cb028 | ||
|
|
b2d00784a4 | ||
|
|
ae31ebdc33 | ||
|
|
a2d50b380f | ||
|
|
654e8fd13f | ||
|
|
bcd44e4b2d | ||
|
|
5200793744 | ||
|
|
abcb29391c | ||
|
|
6a682dc143 | ||
|
|
d93d30537f | ||
|
|
377e88ff36 | ||
|
|
1733290c02 | ||
|
|
e702ccc48a | ||
|
|
ba729c493b | ||
|
|
1c55950b7e | ||
|
|
18c8282bac | ||
|
|
1d20456853 | ||
|
|
7e32d0ae10 | ||
|
|
5d33e45eae | ||
|
|
1590930ef9 | ||
|
|
8186d34f4e |
25
.eslintrc.js
@@ -1,5 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: [
|
||||||
|
'plugin:eslint-comments/recommended',
|
||||||
|
|
||||||
'standard',
|
'standard',
|
||||||
'standard-jsx',
|
'standard-jsx',
|
||||||
'prettier',
|
'prettier',
|
||||||
@@ -16,6 +18,16 @@ module.exports = {
|
|||||||
$PropertyType: true,
|
$PropertyType: true,
|
||||||
$Shape: true,
|
$Shape: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['cli.js', '*-cli.js', '**/*cli*/**/*.js'],
|
||||||
|
rules: {
|
||||||
|
'no-console': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
parser: 'babel-eslint',
|
parser: 'babel-eslint',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaFeatures: {
|
ecmaFeatures: {
|
||||||
@@ -23,6 +35,19 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
|
// disabled because XAPI objects are using camel case
|
||||||
|
camelcase: ['off'],
|
||||||
|
|
||||||
|
'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',
|
'no-var': 'error',
|
||||||
'node/no-extraneous-import': 'error',
|
'node/no-extraneous-import': 'error',
|
||||||
'node/no-extraneous-require': 'error',
|
'node/no-extraneous-require': 'error',
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/async
|
|||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are *very* welcomed, either on the documentation or on
|
Contributions are _very_ welcomed, either on the documentation or on
|
||||||
the code.
|
the code.
|
||||||
|
|
||||||
You may:
|
You may:
|
||||||
|
|||||||
@@ -36,8 +36,8 @@
|
|||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"@babel/preset-flow": "^7.0.0",
|
"@babel/preset-flow": "^7.0.0",
|
||||||
"babel-plugin-lodash": "^3.3.2",
|
"babel-plugin-lodash": "^3.3.2",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run prebuild",
|
"predev": "yarn run prebuild",
|
||||||
"prepare": "yarn run build",
|
"prepare": "yarn run build",
|
||||||
"prepublishOnly": "yarn run build"
|
"prepublishOnly": "yarn run build",
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,12 @@ const getConfig = (key, ...args) => {
|
|||||||
: config
|
: config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// some plugins must be used in a specific order
|
||||||
|
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 = {})
|
plugins === undefined && (plugins = {})
|
||||||
presets === undefined && (presets = {})
|
presets === undefined && (presets = {})
|
||||||
@@ -61,7 +67,13 @@ module.exports = function(pkg, plugins, presets) {
|
|||||||
return {
|
return {
|
||||||
comments: !__PROD__,
|
comments: !__PROD__,
|
||||||
ignore: __TEST__ ? undefined : [/\.spec\.js$/],
|
ignore: __TEST__ ? undefined : [/\.spec\.js$/],
|
||||||
plugins: Object.keys(plugins).map(plugin => [plugin, plugins[plugin]]),
|
plugins: Object.keys(plugins)
|
||||||
|
.map(plugin => [plugin, plugins[plugin]])
|
||||||
|
.sort(([a], [b]) => {
|
||||||
|
const oA = pluginsOrder.indexOf(a)
|
||||||
|
const oB = pluginsOrder.indexOf(b)
|
||||||
|
return oA !== -1 && oB !== -1 ? oA - oB : a < b ? -1 : 1
|
||||||
|
}),
|
||||||
presets: Object.keys(presets).map(preset => [preset, presets[preset]]),
|
presets: Object.keys(presets).map(preset => [preset, presets[preset]]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,8 @@
|
|||||||
"directory": "@xen-orchestra/babel-config",
|
"directory": "@xen-orchestra/babel-config",
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
@xen-orchestra/backups-cli/_composeCommands.js
Normal file
@@ -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)
|
||||||
|
}
|
||||||
393
@xen-orchestra/backups-cli/commands/clean-vms.js
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
// assigned when options are parsed by the main function
|
||||||
|
let force
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const assert = require('assert')
|
||||||
|
const getopts = require('getopts')
|
||||||
|
const lockfile = require('proper-lockfile')
|
||||||
|
const { default: Vhd } = require('vhd-lib')
|
||||||
|
const { curryRight, flatten } = require('lodash')
|
||||||
|
const { dirname, resolve } = require('path')
|
||||||
|
const { DISK_TYPE_DIFFERENCING } = require('vhd-lib/dist/_constants')
|
||||||
|
const { pipe, promisifyAll } = require('promise-toolbox')
|
||||||
|
|
||||||
|
const fs = promisifyAll(require('fs'))
|
||||||
|
const handler = require('@xen-orchestra/fs').getHandler({ url: 'file://' })
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const asyncMap = curryRight((iterable, fn) =>
|
||||||
|
Promise.all(
|
||||||
|
Array.isArray(iterable) ? iterable.map(fn) : Array.from(iterable, fn)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const filter = (...args) => thisArg => thisArg.filter(...args)
|
||||||
|
|
||||||
|
const isGzipFile = async fd => {
|
||||||
|
// https://tools.ietf.org/html/rfc1952.html#page-5
|
||||||
|
const magicNumber = Buffer.allocUnsafe(2)
|
||||||
|
assert.strictEqual(
|
||||||
|
await fs.read(fd, magicNumber, 0, magicNumber.length, 0),
|
||||||
|
magicNumber.length
|
||||||
|
)
|
||||||
|
return magicNumber[0] === 31 && magicNumber[1] === 139
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: better check?
|
||||||
|
//
|
||||||
|
// our heuristic is not good enough, there has been some false positives
|
||||||
|
// (detected as invalid by us but valid by `tar` and imported with success),
|
||||||
|
// either THOUGH THEY MAY HAVE BEEN COMPRESSED FILES:
|
||||||
|
// - these files were normal but the check is incorrect
|
||||||
|
// - these files were invalid but without data loss
|
||||||
|
// - these files were invalid but with silent data loss
|
||||||
|
//
|
||||||
|
// maybe reading the end of the file looking for a file named
|
||||||
|
// /^Ref:\d+/\d+\.checksum$/ and then validating the tar structure from it
|
||||||
|
//
|
||||||
|
// https://github.com/npm/node-tar/issues/234#issuecomment-538190295
|
||||||
|
const isValidTar = async (size, fd) => {
|
||||||
|
if (size <= 1024 || size % 512 !== 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const buf = Buffer.allocUnsafe(1024)
|
||||||
|
assert.strictEqual(
|
||||||
|
await fs.read(fd, buf, 0, buf.length, size - buf.length),
|
||||||
|
buf.length
|
||||||
|
)
|
||||||
|
return buf.every(_ => _ === 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: find an heuristic for compressed files
|
||||||
|
const isValidXva = async path => {
|
||||||
|
try {
|
||||||
|
const fd = await fs.open(path, 'r')
|
||||||
|
try {
|
||||||
|
const { size } = await fs.fstat(fd)
|
||||||
|
if (size < 20) {
|
||||||
|
// neither a valid gzip not tar
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return (await isGzipFile(fd))
|
||||||
|
? true // gzip files cannot be validated at this time
|
||||||
|
: await isValidTar(size, fd)
|
||||||
|
} finally {
|
||||||
|
fs.close(fd).catch(noop)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// never throw, log and report as valid to avoid side effects
|
||||||
|
console.error('isValidXva', path, error)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const noop = Function.prototype
|
||||||
|
|
||||||
|
const readDir = path =>
|
||||||
|
fs.readdir(path).then(
|
||||||
|
entries => {
|
||||||
|
entries.forEach((entry, i) => {
|
||||||
|
entries[i] = `${path}/${entry}`
|
||||||
|
})
|
||||||
|
|
||||||
|
return entries
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
// a missing dir is by definition empty
|
||||||
|
if (error != null && error.code === 'ENOENT') {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// chain is an array of VHDs from child to parent
|
||||||
|
//
|
||||||
|
// the whole chain will be merged into parent, parent will be renamed to child
|
||||||
|
// and all the others will deleted
|
||||||
|
async function mergeVhdChain(chain) {
|
||||||
|
assert(chain.length >= 2)
|
||||||
|
|
||||||
|
const child = chain[0]
|
||||||
|
const parent = chain[chain.length - 1]
|
||||||
|
const children = chain.slice(0, -1).reverse()
|
||||||
|
|
||||||
|
console.warn('Unused parents of VHD', child)
|
||||||
|
chain
|
||||||
|
.slice(1)
|
||||||
|
.reverse()
|
||||||
|
.forEach(parent => {
|
||||||
|
console.warn(' ', parent)
|
||||||
|
})
|
||||||
|
force && console.warn(' merging…')
|
||||||
|
console.warn('')
|
||||||
|
if (force) {
|
||||||
|
// `mergeVhd` does not work with a stream, either
|
||||||
|
// - make it accept a stream
|
||||||
|
// - or create synthetic VHD which is not a stream
|
||||||
|
return console.warn('TODO: implement merge')
|
||||||
|
// await mergeVhd(
|
||||||
|
// handler,
|
||||||
|
// parent,
|
||||||
|
// handler,
|
||||||
|
// children.length === 1
|
||||||
|
// ? child
|
||||||
|
// : await createSyntheticStream(handler, children)
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
force && fs.rename(parent, child),
|
||||||
|
asyncMap(children.slice(0, -1), child => {
|
||||||
|
console.warn('Unused VHD', child)
|
||||||
|
force && console.warn(' deleting…')
|
||||||
|
console.warn('')
|
||||||
|
return force && handler.unlink(child)
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
const listVhds = pipe([
|
||||||
|
vmDir => vmDir + '/vdis',
|
||||||
|
readDir,
|
||||||
|
asyncMap(readDir),
|
||||||
|
flatten,
|
||||||
|
asyncMap(readDir),
|
||||||
|
flatten,
|
||||||
|
filter(_ => _.endsWith('.vhd')),
|
||||||
|
])
|
||||||
|
|
||||||
|
async function handleVm(vmDir) {
|
||||||
|
const vhds = new Set()
|
||||||
|
const vhdParents = { __proto__: null }
|
||||||
|
const vhdChildren = { __proto__: null }
|
||||||
|
|
||||||
|
// remove broken VHDs
|
||||||
|
await asyncMap(await listVhds(vmDir), async path => {
|
||||||
|
try {
|
||||||
|
const vhd = new Vhd(handler, path)
|
||||||
|
await vhd.readHeaderAndFooter()
|
||||||
|
vhds.add(path)
|
||||||
|
if (vhd.footer.diskType === DISK_TYPE_DIFFERENCING) {
|
||||||
|
const parent = resolve(dirname(path), vhd.header.parentUnicodeName)
|
||||||
|
vhdParents[path] = parent
|
||||||
|
if (parent in vhdChildren) {
|
||||||
|
const error = new Error(
|
||||||
|
'this script does not support multiple VHD children'
|
||||||
|
)
|
||||||
|
error.parent = parent
|
||||||
|
error.child1 = vhdChildren[parent]
|
||||||
|
error.child2 = path
|
||||||
|
throw error // should we throw?
|
||||||
|
}
|
||||||
|
vhdChildren[parent] = path
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Error while checking VHD', path)
|
||||||
|
console.warn(' ', error)
|
||||||
|
if (error != null && error.code === 'ERR_ASSERTION') {
|
||||||
|
force && console.warn(' deleting…')
|
||||||
|
console.warn('')
|
||||||
|
force && (await handler.unlink(path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// remove VHDs with missing ancestors
|
||||||
|
{
|
||||||
|
const deletions = []
|
||||||
|
|
||||||
|
// return true if the VHD has been deleted or is missing
|
||||||
|
const deleteIfOrphan = vhd => {
|
||||||
|
const parent = vhdParents[vhd]
|
||||||
|
if (parent === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// no longer needs to be checked
|
||||||
|
delete vhdParents[vhd]
|
||||||
|
|
||||||
|
deleteIfOrphan(parent)
|
||||||
|
|
||||||
|
if (!vhds.has(parent)) {
|
||||||
|
vhds.delete(vhd)
|
||||||
|
|
||||||
|
console.warn('Error while checking VHD', vhd)
|
||||||
|
console.warn(' missing parent', parent)
|
||||||
|
force && console.warn(' deleting…')
|
||||||
|
console.warn('')
|
||||||
|
force && deletions.push(handler.unlink(vhd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// > A property that is deleted before it has been visited will not be
|
||||||
|
// > visited later.
|
||||||
|
// >
|
||||||
|
// > -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in#Deleted_added_or_modified_properties
|
||||||
|
for (const child in vhdParents) {
|
||||||
|
deleteIfOrphan(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(deletions)
|
||||||
|
}
|
||||||
|
|
||||||
|
const [jsons, xvas] = await readDir(vmDir).then(entries => [
|
||||||
|
entries.filter(_ => _.endsWith('.json')),
|
||||||
|
new Set(entries.filter(_ => _.endsWith('.xva'))),
|
||||||
|
])
|
||||||
|
|
||||||
|
await asyncMap(xvas, async path => {
|
||||||
|
// check is not good enough to delete the file, the best we can do is report
|
||||||
|
// it
|
||||||
|
if (!(await isValidXva(path))) {
|
||||||
|
console.warn('Potential broken XVA', path)
|
||||||
|
console.warn('')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const unusedVhds = new Set(vhds)
|
||||||
|
const unusedXvas = new Set(xvas)
|
||||||
|
|
||||||
|
// compile the list of unused XVAs and VHDs, and remove backup metadata which
|
||||||
|
// reference a missing XVA/VHD
|
||||||
|
await asyncMap(jsons, async json => {
|
||||||
|
const metadata = JSON.parse(await fs.readFile(json))
|
||||||
|
const { mode } = metadata
|
||||||
|
if (mode === 'full') {
|
||||||
|
const linkedXva = resolve(vmDir, metadata.xva)
|
||||||
|
|
||||||
|
if (xvas.has(linkedXva)) {
|
||||||
|
unusedXvas.delete(linkedXva)
|
||||||
|
} else {
|
||||||
|
console.warn('Error while checking backup', json)
|
||||||
|
console.warn(' missing file', linkedXva)
|
||||||
|
force && console.warn(' deleting…')
|
||||||
|
console.warn('')
|
||||||
|
force && (await handler.unlink(json))
|
||||||
|
}
|
||||||
|
} else if (mode === 'delta') {
|
||||||
|
const linkedVhds = (() => {
|
||||||
|
const { vhds } = metadata
|
||||||
|
return Object.keys(vhds).map(key => resolve(vmDir, vhds[key]))
|
||||||
|
})()
|
||||||
|
|
||||||
|
// FIXME: find better approach by keeping as much of the backup as
|
||||||
|
// possible (existing disks) even if one disk is missing
|
||||||
|
if (linkedVhds.every(_ => vhds.has(_))) {
|
||||||
|
linkedVhds.forEach(_ => unusedVhds.delete(_))
|
||||||
|
} else {
|
||||||
|
console.warn('Error while checking backup', json)
|
||||||
|
const missingVhds = linkedVhds.filter(_ => !vhds.has(_))
|
||||||
|
console.warn(
|
||||||
|
' %i/%i missing VHDs',
|
||||||
|
missingVhds.length,
|
||||||
|
linkedVhds.length
|
||||||
|
)
|
||||||
|
missingVhds.forEach(vhd => {
|
||||||
|
console.warn(' ', vhd)
|
||||||
|
})
|
||||||
|
force && console.warn(' deleting…')
|
||||||
|
console.warn('')
|
||||||
|
force && (await handler.unlink(json))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: parallelize by vm/job/vdi
|
||||||
|
const unusedVhdsDeletion = []
|
||||||
|
{
|
||||||
|
// VHD chains (as list from child to ancestor) to merge indexed by last
|
||||||
|
// ancestor
|
||||||
|
const vhdChainsToMerge = { __proto__: null }
|
||||||
|
|
||||||
|
const toCheck = new Set(unusedVhds)
|
||||||
|
|
||||||
|
const getUsedChildChainOrDelete = vhd => {
|
||||||
|
if (vhd in vhdChainsToMerge) {
|
||||||
|
const chain = vhdChainsToMerge[vhd]
|
||||||
|
delete vhdChainsToMerge[vhd]
|
||||||
|
return chain
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!unusedVhds.has(vhd)) {
|
||||||
|
return [vhd]
|
||||||
|
}
|
||||||
|
|
||||||
|
// no longer needs to be checked
|
||||||
|
toCheck.delete(vhd)
|
||||||
|
|
||||||
|
const child = vhdChildren[vhd]
|
||||||
|
if (child !== undefined) {
|
||||||
|
const chain = getUsedChildChainOrDelete(child)
|
||||||
|
if (chain !== undefined) {
|
||||||
|
chain.push(vhd)
|
||||||
|
return chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn('Unused VHD', vhd)
|
||||||
|
force && console.warn(' deleting…')
|
||||||
|
console.warn('')
|
||||||
|
force && unusedVhdsDeletion.push(handler.unlink(vhd))
|
||||||
|
}
|
||||||
|
|
||||||
|
toCheck.forEach(vhd => {
|
||||||
|
vhdChainsToMerge[vhd] = getUsedChildChainOrDelete(vhd)
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.keys(vhdChainsToMerge).forEach(key => {
|
||||||
|
const chain = vhdChainsToMerge[key]
|
||||||
|
if (chain !== undefined) {
|
||||||
|
unusedVhdsDeletion.push(mergeVhdChain(chain))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
unusedVhdsDeletion,
|
||||||
|
asyncMap(unusedXvas, path => {
|
||||||
|
console.warn('Unused XVA', path)
|
||||||
|
force && console.warn(' deleting…')
|
||||||
|
console.warn('')
|
||||||
|
return force && handler.unlink(path)
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
module.exports = async function main(args) {
|
||||||
|
const opts = getopts(args, {
|
||||||
|
alias: {
|
||||||
|
force: 'f',
|
||||||
|
},
|
||||||
|
boolean: ['force'],
|
||||||
|
default: {
|
||||||
|
force: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
;({ force } = opts)
|
||||||
|
await asyncMap(opts._, async vmDir => {
|
||||||
|
vmDir = resolve(vmDir)
|
||||||
|
|
||||||
|
// TODO: implement this in `xo-server`, not easy because not compatible with
|
||||||
|
// `@xen-orchestra/fs`.
|
||||||
|
const release = await lockfile.lock(vmDir)
|
||||||
|
try {
|
||||||
|
await handleVm(vmDir)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('handleVm', vmDir, error)
|
||||||
|
} finally {
|
||||||
|
await release()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
13
@xen-orchestra/backups-cli/index.js
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
require('./_composeCommands')({
|
||||||
|
'clean-vms': {
|
||||||
|
get main() {
|
||||||
|
return require('./commands/clean-vms')
|
||||||
|
},
|
||||||
|
usage: '[--force] xo-vm-backups/*',
|
||||||
|
},
|
||||||
|
})(process.argv.slice(2), 'xo-backups').catch(error => {
|
||||||
|
console.error('main', error)
|
||||||
|
process.exitCode = 1
|
||||||
|
})
|
||||||
28
@xen-orchestra/backups-cli/package.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"bin": {
|
||||||
|
"xo-backups": "index.js"
|
||||||
|
},
|
||||||
|
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
|
||||||
|
"dependencies": {
|
||||||
|
"@xen-orchestra/fs": "^0.10.2",
|
||||||
|
"getopts": "^2.2.5",
|
||||||
|
"lodash": "^4.17.15",
|
||||||
|
"promise-toolbox": "^0.14.0",
|
||||||
|
"proper-lockfile": "^4.1.1",
|
||||||
|
"vhd-lib": "^0.7.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=7.10.1"
|
||||||
|
},
|
||||||
|
"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.0.0"
|
||||||
|
}
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"golike-defer": "^0.4.1",
|
"golike-defer": "^0.4.1",
|
||||||
"xen-api": "^0.24.5"
|
"xen-api": "^0.27.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/cron)
|
|||||||
<minute> <hour> <day of month> <month> <day of week>
|
<minute> <hour> <day of month> <month> <day of week>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Each entry can be:
|
Each entry can be:
|
||||||
|
|
||||||
- a single value
|
- a single value
|
||||||
@@ -29,12 +28,12 @@ A wildcard (`*`) can be used as a shortcut for the whole range
|
|||||||
Step values can be used in conjunctions with ranges. For instance,
|
Step values can be used in conjunctions with ranges. For instance,
|
||||||
`1-7/2` is the same as `1,3,5,7`.
|
`1-7/2` is the same as `1,3,5,7`.
|
||||||
|
|
||||||
| Field | Allowed values |
|
| Field | Allowed values |
|
||||||
|------------------|----------------|
|
| ---------------- | ------------------------------------------------------------------ |
|
||||||
| minute | 0-59 |
|
| minute | 0-59 |
|
||||||
| hour | 0-23 |
|
| hour | 0-23 |
|
||||||
| day of the month | 1-31 or 3-letter names (`jan`, `feb`, …) |
|
| day of the month | 1-31 or 3-letter names (`jan`, `feb`, …) |
|
||||||
| month | 0-11 |
|
| month | 0-11 |
|
||||||
| day of week | 0-7 (0 and 7 both mean Sunday) or 3-letter names (`mon`, `tue`, …) |
|
| day of week | 0-7 (0 and 7 both mean Sunday) or 3-letter names (`mon`, `tue`, …) |
|
||||||
|
|
||||||
> Note: the month range is 0-11 to be compatible with
|
> Note: the month range is 0-11 to be compatible with
|
||||||
@@ -131,7 +130,7 @@ job.stop()
|
|||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are *very* welcomed, either on the documentation or on
|
Contributions are _very_ welcomed, either on the documentation or on
|
||||||
the code.
|
the code.
|
||||||
|
|
||||||
You may:
|
You may:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xen-orchestra/cron",
|
"name": "@xen-orchestra/cron",
|
||||||
"version": "1.0.3",
|
"version": "1.0.6",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "Focused, well maintained, cron parser/scheduler",
|
"description": "Focused, well maintained, cron parser/scheduler",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -46,8 +46,8 @@
|
|||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.0.0",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"@babel/preset-flow": "^7.0.0",
|
"@babel/preset-flow": "^7.0.0",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run clean",
|
"predev": "yarn run clean",
|
||||||
"prepublishOnly": "yarn run build"
|
"prepublishOnly": "yarn run build",
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,21 @@ const MAX_DELAY = 2 ** 31 - 1
|
|||||||
|
|
||||||
class Job {
|
class Job {
|
||||||
constructor(schedule, fn) {
|
constructor(schedule, fn) {
|
||||||
|
let scheduledDate
|
||||||
const wrapper = () => {
|
const wrapper = () => {
|
||||||
|
const now = Date.now()
|
||||||
|
if (scheduledDate > now) {
|
||||||
|
// we're early, delay
|
||||||
|
//
|
||||||
|
// no need to check _isEnabled, we're just delaying the existing timeout
|
||||||
|
//
|
||||||
|
// see https://github.com/vatesfr/xen-orchestra/issues/4625
|
||||||
|
this._timeout = setTimeout(wrapper, scheduledDate - now)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this._isRunning = true
|
||||||
|
|
||||||
let result
|
let result
|
||||||
try {
|
try {
|
||||||
result = fn()
|
result = fn()
|
||||||
@@ -22,23 +36,36 @@ class Job {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const scheduleNext = () => {
|
const scheduleNext = () => {
|
||||||
const delay = schedule._nextDelay()
|
this._isRunning = false
|
||||||
this._timeout =
|
|
||||||
delay < MAX_DELAY
|
if (this._isEnabled) {
|
||||||
? setTimeout(wrapper, delay)
|
const now = schedule._createDate()
|
||||||
: setTimeout(scheduleNext, MAX_DELAY)
|
scheduledDate = +next(schedule._schedule, now)
|
||||||
|
const delay = scheduledDate - now
|
||||||
|
this._timeout =
|
||||||
|
delay < MAX_DELAY
|
||||||
|
? setTimeout(wrapper, delay)
|
||||||
|
: setTimeout(scheduleNext, MAX_DELAY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._isEnabled = false
|
||||||
|
this._isRunning = false
|
||||||
this._scheduleNext = scheduleNext
|
this._scheduleNext = scheduleNext
|
||||||
this._timeout = undefined
|
this._timeout = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this.stop()
|
this.stop()
|
||||||
this._scheduleNext()
|
|
||||||
|
this._isEnabled = true
|
||||||
|
if (!this._isRunning) {
|
||||||
|
this._scheduleNext()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
|
this._isEnabled = false
|
||||||
clearTimeout(this._timeout)
|
clearTimeout(this._timeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,11 +95,6 @@ class Schedule {
|
|||||||
return dates
|
return dates
|
||||||
}
|
}
|
||||||
|
|
||||||
_nextDelay() {
|
|
||||||
const now = this._createDate()
|
|
||||||
return next(this._schedule, now) - now
|
|
||||||
}
|
|
||||||
|
|
||||||
startJob(fn) {
|
startJob(fn) {
|
||||||
const job = this.createJob(fn)
|
const job = this.createJob(fn)
|
||||||
job.start()
|
job.start()
|
||||||
|
|||||||
78
@xen-orchestra/cron/src/index.spec.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* eslint-env jest */
|
||||||
|
|
||||||
|
import { createSchedule } from './'
|
||||||
|
|
||||||
|
const wrap = value => () => value
|
||||||
|
|
||||||
|
describe('issues', () => {
|
||||||
|
let originalDateNow
|
||||||
|
beforeAll(() => {
|
||||||
|
originalDateNow = Date.now
|
||||||
|
})
|
||||||
|
afterAll(() => {
|
||||||
|
Date.now = originalDateNow
|
||||||
|
originalDateNow = undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
test('stop during async execution', async () => {
|
||||||
|
let nCalls = 0
|
||||||
|
let resolve, promise
|
||||||
|
|
||||||
|
const schedule = createSchedule('* * * * *')
|
||||||
|
const job = schedule.createJob(() => {
|
||||||
|
++nCalls
|
||||||
|
|
||||||
|
// eslint-disable-next-line promise/param-names
|
||||||
|
promise = new Promise(r => {
|
||||||
|
resolve = r
|
||||||
|
})
|
||||||
|
return promise
|
||||||
|
})
|
||||||
|
|
||||||
|
job.start()
|
||||||
|
Date.now = wrap(+schedule.next(1)[0])
|
||||||
|
jest.runAllTimers()
|
||||||
|
|
||||||
|
expect(nCalls).toBe(1)
|
||||||
|
|
||||||
|
job.stop()
|
||||||
|
|
||||||
|
resolve()
|
||||||
|
await promise
|
||||||
|
|
||||||
|
jest.runAllTimers()
|
||||||
|
expect(nCalls).toBe(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('stop then start during async job execution', async () => {
|
||||||
|
let nCalls = 0
|
||||||
|
let resolve, promise
|
||||||
|
|
||||||
|
const schedule = createSchedule('* * * * *')
|
||||||
|
const job = schedule.createJob(() => {
|
||||||
|
++nCalls
|
||||||
|
|
||||||
|
// eslint-disable-next-line promise/param-names
|
||||||
|
promise = new Promise(r => {
|
||||||
|
resolve = r
|
||||||
|
})
|
||||||
|
return promise
|
||||||
|
})
|
||||||
|
|
||||||
|
job.start()
|
||||||
|
Date.now = wrap(+schedule.next(1)[0])
|
||||||
|
jest.runAllTimers()
|
||||||
|
|
||||||
|
expect(nCalls).toBe(1)
|
||||||
|
|
||||||
|
job.stop()
|
||||||
|
job.start()
|
||||||
|
|
||||||
|
resolve()
|
||||||
|
await promise
|
||||||
|
|
||||||
|
Date.now = wrap(+schedule.next(1)[0])
|
||||||
|
jest.runAllTimers()
|
||||||
|
expect(nCalls).toBe(2)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
# ${pkg.name} [](https://travis-ci.org/${pkg.shortGitHubPath})
|
# @xen-orchestra/defined [](https://travis-ci.org/${pkg.shortGitHubPath})
|
||||||
|
|
||||||
> ${pkg.description}
|
> ${pkg.description}
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Installation of the [npm package](https://npmjs.org/package/${pkg.name}):
|
Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/defined):
|
||||||
|
|
||||||
```
|
```
|
||||||
> npm install --save ${pkg.name}
|
> npm install --save @xen-orchestra/defined
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -35,15 +35,15 @@ Installation of the [npm package](https://npmjs.org/package/${pkg.name}):
|
|||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are *very* welcomed, either on the documentation or on
|
Contributions are _very_ welcomed, either on the documentation or on
|
||||||
the code.
|
the code.
|
||||||
|
|
||||||
You may:
|
You may:
|
||||||
|
|
||||||
- report any [issue](${pkg.bugs})
|
- report any [issue](https://github.com/vatesfr/xen-orchestra/issues)
|
||||||
you've encountered;
|
you've encountered;
|
||||||
- fork and create a pull request.
|
- fork and create a pull request.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
${pkg.license} © [${pkg.author.name}](${pkg.author.url})
|
ISC © [Vates SAS](https://vates.fr)
|
||||||
|
|||||||
@@ -34,8 +34,8 @@
|
|||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"@babel/preset-flow": "^7.0.0",
|
"@babel/preset-flow": "^7.0.0",
|
||||||
"babel-plugin-lodash": "^3.3.2",
|
"babel-plugin-lodash": "^3.3.2",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run prebuild",
|
"predev": "yarn run prebuild",
|
||||||
"prepublishOnly": "yarn run build"
|
"prepublishOnly": "yarn run build",
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import emitAsync from '@xen-orchestra/emit-async'
|
|||||||
const ee = new EE()
|
const ee = new EE()
|
||||||
ee.emitAsync = emitAsync
|
ee.emitAsync = emitAsync
|
||||||
|
|
||||||
ee.on('start', async function () {
|
ee.on('start', async function() {
|
||||||
// whatever
|
// whatever
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -29,11 +29,14 @@ await ee.emitAsync('start')
|
|||||||
|
|
||||||
// by default, it will rejects as soon as one listener reject, you can customise
|
// by default, it will rejects as soon as one listener reject, you can customise
|
||||||
// error handling though:
|
// error handling though:
|
||||||
await ee.emitAsync({
|
await ee.emitAsync(
|
||||||
onError (error) {
|
{
|
||||||
console.warn(error)
|
onError(error) {
|
||||||
}
|
console.warn(error)
|
||||||
}, 'start')
|
},
|
||||||
|
},
|
||||||
|
'start'
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
@@ -57,15 +60,15 @@ await ee.emitAsync({
|
|||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are *very* welcomed, either on the documentation or on
|
Contributions are _very_ welcomed, either on the documentation or on
|
||||||
the code.
|
the code.
|
||||||
|
|
||||||
You may:
|
You may:
|
||||||
|
|
||||||
- report any [issue](${pkg.bugs})
|
- report any [issue](https://github.com/vatesfr/xen-orchestra/issues)
|
||||||
you've encountered;
|
you've encountered;
|
||||||
- fork and create a pull request.
|
- fork and create a pull request.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
${pkg.license} © [${pkg.author.name}](${pkg.author.url})
|
ISC © [Vates SAS](https://vates.fr)
|
||||||
|
|||||||
@@ -33,8 +33,8 @@
|
|||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.0.0",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"babel-plugin-lodash": "^3.3.2",
|
"babel-plugin-lodash": "^3.3.2",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run prebuild",
|
"predev": "yarn run prebuild",
|
||||||
"prepublishOnly": "yarn run build"
|
"prepublishOnly": "yarn run build",
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xen-orchestra/fs",
|
"name": "@xen-orchestra/fs",
|
||||||
"version": "0.7.1",
|
"version": "0.10.2",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"description": "The File System for Xen Orchestra backups.",
|
"description": "The File System for Xen Orchestra backups.",
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
@@ -18,21 +18,22 @@
|
|||||||
"dist/"
|
"dist/"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=8.10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@marsaud/smb2": "^0.13.0",
|
"@marsaud/smb2": "^0.14.0",
|
||||||
"@sindresorhus/df": "^2.1.0",
|
"@sindresorhus/df": "^3.1.1",
|
||||||
"@xen-orchestra/async-map": "^0.0.0",
|
"@xen-orchestra/async-map": "^0.0.0",
|
||||||
"decorator-synchronized": "^0.3.0",
|
"decorator-synchronized": "^0.5.0",
|
||||||
"execa": "^1.0.0",
|
"execa": "^3.2.0",
|
||||||
"fs-extra": "^7.0.0",
|
"fs-extra": "^8.0.1",
|
||||||
"get-stream": "^4.0.0",
|
"get-stream": "^5.1.0",
|
||||||
|
"limit-concurrency-decorator": "^0.4.0",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"promise-toolbox": "^0.11.0",
|
"promise-toolbox": "^0.14.0",
|
||||||
"readable-stream": "^3.0.6",
|
"readable-stream": "^3.0.6",
|
||||||
"through2": "^3.0.0",
|
"through2": "^3.0.0",
|
||||||
"tmp": "^0.0.33",
|
"tmp": "^0.1.0",
|
||||||
"xo-remote-parser": "^0.5.0"
|
"xo-remote-parser": "^0.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -40,14 +41,15 @@
|
|||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.0.0",
|
||||||
"@babel/plugin-proposal-decorators": "^7.1.6",
|
"@babel/plugin-proposal-decorators": "^7.1.6",
|
||||||
"@babel/plugin-proposal-function-bind": "^7.0.0",
|
"@babel/plugin-proposal-function-bind": "^7.0.0",
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"@babel/preset-flow": "^7.0.0",
|
"@babel/preset-flow": "^7.0.0",
|
||||||
"async-iterator-to-stream": "^1.1.0",
|
"async-iterator-to-stream": "^1.1.0",
|
||||||
"babel-plugin-lodash": "^3.3.2",
|
"babel-plugin-lodash": "^3.3.2",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"dotenv": "^6.1.0",
|
"dotenv": "^8.0.0",
|
||||||
"index-modules": "^0.3.0",
|
"index-modules": "^0.3.0",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -55,6 +57,7 @@
|
|||||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run clean",
|
"predev": "yarn run clean",
|
||||||
"prepare": "yarn run build"
|
"prepare": "yarn run build",
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import getStream from 'get-stream'
|
import getStream from 'get-stream'
|
||||||
|
|
||||||
import asyncMap from '@xen-orchestra/async-map'
|
import asyncMap from '@xen-orchestra/async-map'
|
||||||
|
import limit from 'limit-concurrency-decorator'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import synchronized from 'decorator-synchronized'
|
import synchronized from 'decorator-synchronized'
|
||||||
import { fromCallback, fromEvent, ignoreErrors, timeout } from 'promise-toolbox'
|
import { fromCallback, fromEvent, ignoreErrors, timeout } from 'promise-toolbox'
|
||||||
@@ -25,8 +26,13 @@ type RemoteInfo = { used?: number, size?: number }
|
|||||||
type File = FileDescriptor | string
|
type File = FileDescriptor | string
|
||||||
|
|
||||||
const checksumFile = file => file + '.checksum'
|
const checksumFile = file => file + '.checksum'
|
||||||
|
const computeRate = (hrtime: number[], size: number) => {
|
||||||
|
const seconds = hrtime[0] + hrtime[1] / 1e9
|
||||||
|
return size / seconds
|
||||||
|
}
|
||||||
|
|
||||||
const DEFAULT_TIMEOUT = 6e5 // 10 min
|
const DEFAULT_TIMEOUT = 6e5 // 10 min
|
||||||
|
const DEFAULT_MAX_PARALLEL_OPERATIONS = 10
|
||||||
|
|
||||||
const ignoreEnoent = error => {
|
const ignoreEnoent = error => {
|
||||||
if (error == null || error.code !== 'ENOENT') {
|
if (error == null || error.code !== 'ENOENT') {
|
||||||
@@ -79,6 +85,25 @@ export default class RemoteHandlerAbstract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
;({ timeout: this._timeout = DEFAULT_TIMEOUT } = options)
|
;({ timeout: this._timeout = DEFAULT_TIMEOUT } = options)
|
||||||
|
|
||||||
|
const sharedLimit = limit(
|
||||||
|
options.maxParallelOperations ?? DEFAULT_MAX_PARALLEL_OPERATIONS
|
||||||
|
)
|
||||||
|
this.closeFile = sharedLimit(this.closeFile)
|
||||||
|
this.getInfo = sharedLimit(this.getInfo)
|
||||||
|
this.getSize = sharedLimit(this.getSize)
|
||||||
|
this.list = sharedLimit(this.list)
|
||||||
|
this.mkdir = sharedLimit(this.mkdir)
|
||||||
|
this.openFile = sharedLimit(this.openFile)
|
||||||
|
this.outputFile = sharedLimit(this.outputFile)
|
||||||
|
this.read = sharedLimit(this.read)
|
||||||
|
this.readFile = sharedLimit(this.readFile)
|
||||||
|
this.rename = sharedLimit(this.rename)
|
||||||
|
this.rmdir = sharedLimit(this.rmdir)
|
||||||
|
this.truncate = sharedLimit(this.truncate)
|
||||||
|
this.unlink = sharedLimit(this.unlink)
|
||||||
|
this.write = sharedLimit(this.write)
|
||||||
|
this.writeFile = sharedLimit(this.writeFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public members
|
// Public members
|
||||||
@@ -362,18 +387,27 @@ export default class RemoteHandlerAbstract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async test(): Promise<Object> {
|
async test(): Promise<Object> {
|
||||||
|
const SIZE = 1024 * 1024 * 10
|
||||||
const testFileName = normalizePath(`${Date.now()}.test`)
|
const testFileName = normalizePath(`${Date.now()}.test`)
|
||||||
const data = await fromCallback(cb => randomBytes(1024 * 1024, cb))
|
const data = await fromCallback(randomBytes, SIZE)
|
||||||
let step = 'write'
|
let step = 'write'
|
||||||
try {
|
try {
|
||||||
|
const writeStart = process.hrtime()
|
||||||
await this._outputFile(testFileName, data, { flags: 'wx' })
|
await this._outputFile(testFileName, data, { flags: 'wx' })
|
||||||
|
const writeDuration = process.hrtime(writeStart)
|
||||||
|
|
||||||
step = 'read'
|
step = 'read'
|
||||||
|
const readStart = process.hrtime()
|
||||||
const read = await this._readFile(testFileName, { flags: 'r' })
|
const read = await this._readFile(testFileName, { flags: 'r' })
|
||||||
|
const readDuration = process.hrtime(readStart)
|
||||||
|
|
||||||
if (!data.equals(read)) {
|
if (!data.equals(read)) {
|
||||||
throw new Error('output and input did not match')
|
throw new Error('output and input did not match')
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
writeRate: computeRate(writeDuration, SIZE),
|
||||||
|
readRate: computeRate(readDuration, SIZE),
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
@@ -387,6 +421,10 @@ export default class RemoteHandlerAbstract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async truncate(file: string, len: number): Promise<void> {
|
||||||
|
await this._truncate(file, len)
|
||||||
|
}
|
||||||
|
|
||||||
async unlink(file: string, { checksum = true }: Object = {}): Promise<void> {
|
async unlink(file: string, { checksum = true }: Object = {}): Promise<void> {
|
||||||
file = normalizePath(file)
|
file = normalizePath(file)
|
||||||
|
|
||||||
@@ -397,6 +435,18 @@ export default class RemoteHandlerAbstract {
|
|||||||
await this._unlink(file).catch(ignoreEnoent)
|
await this._unlink(file).catch(ignoreEnoent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async write(
|
||||||
|
file: File,
|
||||||
|
buffer: Buffer,
|
||||||
|
position: number
|
||||||
|
): Promise<{| bytesWritten: number, buffer: Buffer |}> {
|
||||||
|
await this._write(
|
||||||
|
typeof file === 'string' ? normalizePath(file) : file,
|
||||||
|
buffer,
|
||||||
|
position
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async writeFile(
|
async writeFile(
|
||||||
file: string,
|
file: string,
|
||||||
data: Data,
|
data: Data,
|
||||||
@@ -533,6 +583,28 @@ export default class RemoteHandlerAbstract {
|
|||||||
throw new Error('Not implemented')
|
throw new Error('Not implemented')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _write(file: File, buffer: Buffer, position: number): Promise<void> {
|
||||||
|
const isPath = typeof file === 'string'
|
||||||
|
if (isPath) {
|
||||||
|
file = await this.openFile(file, 'r+')
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return await this._writeFd(file, buffer, position)
|
||||||
|
} finally {
|
||||||
|
if (isPath) {
|
||||||
|
await this.closeFile(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _writeFd(
|
||||||
|
fd: FileDescriptor,
|
||||||
|
buffer: Buffer,
|
||||||
|
position: number
|
||||||
|
): Promise<void> {
|
||||||
|
throw new Error('Not implemented')
|
||||||
|
}
|
||||||
|
|
||||||
async _writeFile(
|
async _writeFile(
|
||||||
file: string,
|
file: string,
|
||||||
data: Data,
|
data: Data,
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
import 'dotenv/config'
|
import 'dotenv/config'
|
||||||
import asyncIteratorToStream from 'async-iterator-to-stream'
|
import asyncIteratorToStream from 'async-iterator-to-stream'
|
||||||
import getStream from 'get-stream'
|
import getStream from 'get-stream'
|
||||||
|
import { forOwn, random } from 'lodash'
|
||||||
import { fromCallback } from 'promise-toolbox'
|
import { fromCallback } from 'promise-toolbox'
|
||||||
import { pipeline } from 'readable-stream'
|
import { pipeline } from 'readable-stream'
|
||||||
import { random } from 'lodash'
|
|
||||||
import { tmpdir } from 'os'
|
import { tmpdir } from 'os'
|
||||||
|
|
||||||
import { getHandler } from '.'
|
import { getHandler } from '.'
|
||||||
@@ -86,7 +86,7 @@ handlers.forEach(url => {
|
|||||||
describe('#createOutputStream()', () => {
|
describe('#createOutputStream()', () => {
|
||||||
it('creates parent dir if missing', async () => {
|
it('creates parent dir if missing', async () => {
|
||||||
const stream = await handler.createOutputStream('dir/file')
|
const stream = await handler.createOutputStream('dir/file')
|
||||||
await fromCallback(cb => pipeline(createTestDataStream(), stream, cb))
|
await fromCallback(pipeline, createTestDataStream(), stream)
|
||||||
await expect(await handler.readFile('dir/file')).toEqual(TEST_DATA)
|
await expect(await handler.readFile('dir/file')).toEqual(TEST_DATA)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -106,7 +106,7 @@ handlers.forEach(url => {
|
|||||||
describe('#createWriteStream()', () => {
|
describe('#createWriteStream()', () => {
|
||||||
testWithFileDescriptor('file', 'wx', async ({ file, flags }) => {
|
testWithFileDescriptor('file', 'wx', async ({ file, flags }) => {
|
||||||
const stream = await handler.createWriteStream(file, { flags })
|
const stream = await handler.createWriteStream(file, { flags })
|
||||||
await fromCallback(cb => pipeline(createTestDataStream(), stream, cb))
|
await fromCallback(pipeline, createTestDataStream(), stream)
|
||||||
await expect(await handler.readFile('file')).toEqual(TEST_DATA)
|
await expect(await handler.readFile('file')).toEqual(TEST_DATA)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -290,9 +290,11 @@ handlers.forEach(url => {
|
|||||||
|
|
||||||
describe('#test()', () => {
|
describe('#test()', () => {
|
||||||
it('tests the remote appears to be working', async () => {
|
it('tests the remote appears to be working', async () => {
|
||||||
expect(await handler.test()).toEqual({
|
const answer = await handler.test()
|
||||||
success: true,
|
|
||||||
})
|
expect(answer.success).toBe(true)
|
||||||
|
expect(typeof answer.writeRate).toBe('number')
|
||||||
|
expect(typeof answer.readRate).toBe('number')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -308,5 +310,70 @@ handlers.forEach(url => {
|
|||||||
await handler.unlink('file')
|
await handler.unlink('file')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#write()', () => {
|
||||||
|
beforeEach(() => handler.outputFile('file', TEST_DATA))
|
||||||
|
|
||||||
|
const PATCH_DATA_LEN = Math.ceil(TEST_DATA_LEN / 2)
|
||||||
|
const PATCH_DATA = unsecureRandomBytes(PATCH_DATA_LEN)
|
||||||
|
|
||||||
|
forOwn(
|
||||||
|
{
|
||||||
|
'dont increase file size': (() => {
|
||||||
|
const offset = random(0, TEST_DATA_LEN - PATCH_DATA_LEN)
|
||||||
|
|
||||||
|
const expected = Buffer.from(TEST_DATA)
|
||||||
|
PATCH_DATA.copy(expected, offset)
|
||||||
|
|
||||||
|
return { offset, expected }
|
||||||
|
})(),
|
||||||
|
'increase file size': (() => {
|
||||||
|
const offset = random(
|
||||||
|
TEST_DATA_LEN - PATCH_DATA_LEN + 1,
|
||||||
|
TEST_DATA_LEN
|
||||||
|
)
|
||||||
|
|
||||||
|
const expected = Buffer.alloc(offset + PATCH_DATA_LEN)
|
||||||
|
TEST_DATA.copy(expected)
|
||||||
|
PATCH_DATA.copy(expected, offset)
|
||||||
|
|
||||||
|
return { offset, expected }
|
||||||
|
})(),
|
||||||
|
},
|
||||||
|
({ offset, expected }, title) => {
|
||||||
|
describe(title, () => {
|
||||||
|
testWithFileDescriptor('file', 'r+', async ({ file }) => {
|
||||||
|
await handler.write(file, PATCH_DATA, offset)
|
||||||
|
await expect(await handler.readFile('file')).toEqual(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#truncate()', () => {
|
||||||
|
forOwn(
|
||||||
|
{
|
||||||
|
'shrinks file': (() => {
|
||||||
|
const length = random(0, TEST_DATA_LEN)
|
||||||
|
const expected = TEST_DATA.slice(0, length)
|
||||||
|
return { length, expected }
|
||||||
|
})(),
|
||||||
|
'grows file': (() => {
|
||||||
|
const length = random(TEST_DATA_LEN, TEST_DATA_LEN * 2)
|
||||||
|
const expected = Buffer.alloc(length)
|
||||||
|
TEST_DATA.copy(expected)
|
||||||
|
return { length, expected }
|
||||||
|
})(),
|
||||||
|
},
|
||||||
|
({ length, expected }, title) => {
|
||||||
|
it(title, async () => {
|
||||||
|
await handler.outputFile('file', TEST_DATA)
|
||||||
|
await handler.truncate('file', length)
|
||||||
|
await expect(await handler.readFile('file')).toEqual(expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -47,8 +47,19 @@ export default class LocalHandler extends RemoteHandlerAbstract {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_getInfo() {
|
async _getInfo() {
|
||||||
return df.file(this._getFilePath('/'))
|
// df.file() resolves with an object with the following properties:
|
||||||
|
// filesystem, type, size, used, available, capacity and mountpoint.
|
||||||
|
// size, used, available and capacity may be `NaN` so we remove any `NaN`
|
||||||
|
// value from the object.
|
||||||
|
const info = await df.file(this._getFilePath('/'))
|
||||||
|
Object.keys(info).forEach(key => {
|
||||||
|
if (Number.isNaN(info[key])) {
|
||||||
|
delete info[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getSize(file) {
|
async _getSize(file) {
|
||||||
@@ -106,10 +117,18 @@ export default class LocalHandler extends RemoteHandlerAbstract {
|
|||||||
await fs.access(path, fs.R_OK | fs.W_OK)
|
await fs.access(path, fs.R_OK | fs.W_OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_truncate(file, len) {
|
||||||
|
return fs.truncate(this._getFilePath(file), len)
|
||||||
|
}
|
||||||
|
|
||||||
async _unlink(file) {
|
async _unlink(file) {
|
||||||
return fs.unlink(this._getFilePath(file))
|
return fs.unlink(this._getFilePath(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_writeFd(file, buffer, position) {
|
||||||
|
return fs.write(file.fd, buffer, 0, buffer.length, position)
|
||||||
|
}
|
||||||
|
|
||||||
_writeFile(file, data, { flags }) {
|
_writeFile(file, data, { flags }) {
|
||||||
return fs.writeFile(this._getFilePath(file), data, { flag: flags })
|
return fs.writeFile(this._getFilePath(file), data, { flag: flags })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,10 +155,20 @@ export default class SmbHandler extends RemoteHandlerAbstract {
|
|||||||
return this.list('.')
|
return this.list('.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_truncate(file, len) {
|
||||||
|
return this._client
|
||||||
|
.truncate(this._getFilePath(file), len)
|
||||||
|
.catch(normalizeError)
|
||||||
|
}
|
||||||
|
|
||||||
_unlink(file) {
|
_unlink(file) {
|
||||||
return this._client.unlink(this._getFilePath(file)).catch(normalizeError)
|
return this._client.unlink(this._getFilePath(file)).catch(normalizeError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_writeFd(file, buffer, position) {
|
||||||
|
return this._client.write(file.fd, buffer, 0, buffer.length, position)
|
||||||
|
}
|
||||||
|
|
||||||
_writeFile(file, data, options) {
|
_writeFile(file, data, options) {
|
||||||
return this._client
|
return this._client
|
||||||
.writeFile(this._getFilePath(file), data, options)
|
.writeFile(this._getFilePath(file), data, options)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/log):
|
|||||||
Everywhere something should be logged:
|
Everywhere something should be logged:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import createLogger from '@xen-orchestra/log'
|
import { createLogger } from '@xen-orchestra/log'
|
||||||
|
|
||||||
const log = createLogger('my-module')
|
const log = createLogger('my-module')
|
||||||
|
|
||||||
@@ -24,11 +24,25 @@ log.info('this information is relevant to the user')
|
|||||||
log.warn('something went wrong but did not prevent current action')
|
log.warn('something went wrong but did not prevent current action')
|
||||||
log.error('something went wrong')
|
log.error('something went wrong')
|
||||||
log.fatal('service/app is going down')
|
log.fatal('service/app is going down')
|
||||||
|
|
||||||
|
// you can add contextual info
|
||||||
|
log.debug('new API request', {
|
||||||
|
method: 'foo',
|
||||||
|
params: [ 'bar', 'baz' ]
|
||||||
|
user: 'qux'
|
||||||
|
})
|
||||||
|
|
||||||
|
// by convention, errors go into the `error` field
|
||||||
|
log.error('could not join server', {
|
||||||
|
error,
|
||||||
|
server: 'example.org',
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, at application level, configure the logs are handled:
|
Then, at application level, configure the logs are handled:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
import { createLogger } from '@xen-orchestra/log'
|
||||||
import { configure, catchGlobalErrors } from '@xen-orchestra/log/configure'
|
import { configure, catchGlobalErrors } from '@xen-orchestra/log/configure'
|
||||||
import transportConsole from '@xen-orchestra/log/transports/console'
|
import transportConsole from '@xen-orchestra/log/transports/console'
|
||||||
import transportEmail from '@xen-orchestra/log/transports/email'
|
import transportEmail from '@xen-orchestra/log/transports/email'
|
||||||
@@ -37,13 +51,10 @@ const transport = transportEmail({
|
|||||||
service: 'gmail',
|
service: 'gmail',
|
||||||
auth: {
|
auth: {
|
||||||
user: 'jane.smith@gmail.com',
|
user: 'jane.smith@gmail.com',
|
||||||
pass: 'H&NbECcpXF|pyXe#%ZEb'
|
pass: 'H&NbECcpXF|pyXe#%ZEb',
|
||||||
},
|
},
|
||||||
from: 'jane.smith@gmail.com',
|
from: 'jane.smith@gmail.com',
|
||||||
to: [
|
to: ['jane.smith@gmail.com', 'sam.doe@yahoo.com'],
|
||||||
'jane.smith@gmail.com',
|
|
||||||
'sam.doe@yahoo.com'
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
configure([
|
configure([
|
||||||
@@ -53,19 +64,19 @@ configure([
|
|||||||
// matched against the namespace of the logs
|
// matched against the namespace of the logs
|
||||||
filter: process.env.DEBUG,
|
filter: process.env.DEBUG,
|
||||||
|
|
||||||
transport: transportConsole()
|
transport: transportConsole(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// only levels >= warn
|
// only levels >= warn
|
||||||
level: 'warn',
|
level: 'warn',
|
||||||
|
|
||||||
transport
|
transport,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
// send all global errors (uncaught exceptions, warnings, unhandled rejections)
|
// send all global errors (uncaught exceptions, warnings, unhandled rejections)
|
||||||
// to this transport
|
// to this logger
|
||||||
catchGlobalErrors(transport)
|
catchGlobalErrors(createLogger('app'))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Transports
|
### Transports
|
||||||
@@ -91,18 +102,17 @@ Configuration:
|
|||||||
```js
|
```js
|
||||||
import transportEmail from '@xen-orchestra/log/transports/email'
|
import transportEmail from '@xen-orchestra/log/transports/email'
|
||||||
|
|
||||||
configure(transportEmail({
|
configure(
|
||||||
service: 'gmail',
|
transportEmail({
|
||||||
auth: {
|
service: 'gmail',
|
||||||
user: 'jane.smith@gmail.com',
|
auth: {
|
||||||
pass: 'H&NbECcpXF|pyXe#%ZEb'
|
user: 'jane.smith@gmail.com',
|
||||||
},
|
pass: 'H&NbECcpXF|pyXe#%ZEb',
|
||||||
from: 'jane.smith@gmail.com',
|
},
|
||||||
to: [
|
from: 'jane.smith@gmail.com',
|
||||||
'jane.smith@gmail.com',
|
to: ['jane.smith@gmail.com', 'sam.doe@yahoo.com'],
|
||||||
'sam.doe@yahoo.com'
|
})
|
||||||
]
|
)
|
||||||
}))
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Syslog
|
#### Syslog
|
||||||
@@ -146,7 +156,7 @@ configure(transportSyslog('tcp://syslog.company.lan'))
|
|||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are *very* welcomed, either on the documentation or on
|
Contributions are _very_ welcomed, either on the documentation or on
|
||||||
the code.
|
the code.
|
||||||
|
|
||||||
You may:
|
You may:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xen-orchestra/log",
|
"name": "@xen-orchestra/log",
|
||||||
"version": "0.1.4",
|
"version": "0.2.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "",
|
"description": "",
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
@@ -27,20 +27,20 @@
|
|||||||
">2%"
|
">2%"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4"
|
"node": ">=6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"promise-toolbox": "^0.11.0"
|
"promise-toolbox": "^0.14.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.0.0",
|
"@babel/cli": "^7.0.0",
|
||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.0.0",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"babel-plugin-lodash": "^3.3.2",
|
"babel-plugin-lodash": "^3.3.2",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"index-modules": "^0.3.0",
|
"index-modules": "^0.3.0",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -48,6 +48,7 @@
|
|||||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run prebuild",
|
"predev": "yarn run prebuild",
|
||||||
"prepublishOnly": "yarn run build"
|
"prepare": "yarn run build",
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ const createTransport = config => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let { filter, transport } = config
|
let { filter } = config
|
||||||
|
let transport = createTransport(config.transport)
|
||||||
const level = resolve(config.level)
|
const level = resolve(config.level)
|
||||||
|
|
||||||
if (filter !== undefined) {
|
if (filter !== undefined) {
|
||||||
@@ -51,11 +52,12 @@ const symbol =
|
|||||||
? Symbol.for('@xen-orchestra/log')
|
? Symbol.for('@xen-orchestra/log')
|
||||||
: '@@@xen-orchestra/log'
|
: '@@@xen-orchestra/log'
|
||||||
|
|
||||||
|
const { env } = process
|
||||||
global[symbol] = createTransport({
|
global[symbol] = createTransport({
|
||||||
// display warnings or above, and all that are enabled via DEBUG or
|
// display warnings or above, and all that are enabled via DEBUG or
|
||||||
// NODE_DEBUG env
|
// NODE_DEBUG env
|
||||||
filter: process.env.DEBUG || process.env.NODE_DEBUG,
|
filter: [env.DEBUG, env.NODE_DEBUG].filter(Boolean).join(','),
|
||||||
level: LEVELS.INFO,
|
level: resolve(env.LOG_LEVEL, LEVELS.INFO),
|
||||||
|
|
||||||
transport: createConsoleTransport(),
|
transport: createConsoleTransport(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import createTransport from './transports/console'
|
import createTransport from './transports/console'
|
||||||
import LEVELS from './levels'
|
import LEVELS, { resolve } from './levels'
|
||||||
|
|
||||||
const symbol =
|
const symbol =
|
||||||
typeof Symbol !== 'undefined'
|
typeof Symbol !== 'undefined'
|
||||||
@@ -9,7 +9,8 @@ if (!(symbol in global)) {
|
|||||||
// the default behavior, without requiring `configure` is to avoid
|
// the default behavior, without requiring `configure` is to avoid
|
||||||
// logging anything unless it's a real error
|
// logging anything unless it's a real error
|
||||||
const transport = createTransport()
|
const transport = createTransport()
|
||||||
global[symbol] = log => log.level > LEVELS.WARN && transport(log)
|
const level = resolve(process.env.LOG_LEVEL, LEVELS.WARN)
|
||||||
|
global[symbol] = log => log.level >= level && transport(log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@@ -72,5 +73,5 @@ prototype.wrap = function(message, fn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const createLogger = namespace => new Logger(namespace)
|
export const createLogger = namespace => new Logger(namespace)
|
||||||
export { createLogger as default }
|
export { createLogger as default }
|
||||||
|
|||||||
@@ -13,11 +13,22 @@ for (const name in LEVELS) {
|
|||||||
NAMES[LEVELS[name]] = name
|
NAMES[LEVELS[name]] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
export const resolve = level => {
|
// resolves to the number representation of a level
|
||||||
if (typeof level === 'string') {
|
//
|
||||||
level = LEVELS[level.toUpperCase()]
|
// returns `defaultLevel` if invalid
|
||||||
|
export const resolve = (level, defaultLevel) => {
|
||||||
|
const type = typeof level
|
||||||
|
if (type === 'number') {
|
||||||
|
if (level in NAMES) {
|
||||||
|
return level
|
||||||
|
}
|
||||||
|
} else if (type === 'string') {
|
||||||
|
const nLevel = LEVELS[level.toUpperCase()]
|
||||||
|
if (nLevel !== undefined) {
|
||||||
|
return nLevel
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return level
|
return defaultLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.freeze(LEVELS)
|
Object.freeze(LEVELS)
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
import LEVELS, { NAMES } from '../levels'
|
import LEVELS, { NAMES } from '../levels'
|
||||||
|
|
||||||
// Bind console methods (necessary for browsers)
|
|
||||||
const debugConsole = console.log.bind(console)
|
|
||||||
const infoConsole = console.info.bind(console)
|
|
||||||
const warnConsole = console.warn.bind(console)
|
|
||||||
const errorConsole = console.error.bind(console)
|
|
||||||
|
|
||||||
const { ERROR, INFO, WARN } = LEVELS
|
const { ERROR, INFO, WARN } = LEVELS
|
||||||
|
|
||||||
const consoleTransport = ({ data, level, namespace, message, time }) => {
|
const consoleTransport = ({ data, level, namespace, message, time }) => {
|
||||||
const fn =
|
const fn =
|
||||||
|
/* eslint-disable no-console */
|
||||||
level < INFO
|
level < INFO
|
||||||
? debugConsole
|
? console.log
|
||||||
: level < WARN
|
: level < WARN
|
||||||
? infoConsole
|
? console.info
|
||||||
: level < ERROR
|
: level < ERROR
|
||||||
? warnConsole
|
? console.warn
|
||||||
: errorConsole
|
: console.error
|
||||||
|
/* eslint-enable no-console */
|
||||||
|
|
||||||
fn('%s - %s - [%s] %s', time.toISOString(), namespace, NAMES[level], message)
|
const args = [time.toISOString(), namespace, NAMES[level], message]
|
||||||
data != null && fn(data)
|
if (data != null) {
|
||||||
|
args.push(data)
|
||||||
|
}
|
||||||
|
fn.apply(console, args)
|
||||||
}
|
}
|
||||||
export default () => consoleTransport
|
export default () => consoleTransport
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import fromCallback from 'promise-toolbox/fromCallback'
|
import fromCallback from 'promise-toolbox/fromCallback'
|
||||||
import splitHost from 'split-host' // eslint-disable-line node/no-extraneous-import node/no-missing-import
|
import splitHost from 'split-host'
|
||||||
import startsWith from 'lodash/startsWith'
|
import { createClient, Facility, Severity, Transport } from 'syslog-client'
|
||||||
import { createClient, Facility, Severity, Transport } from 'syslog-client' // eslint-disable-line node/no-extraneous-import node/no-missing-import
|
|
||||||
|
|
||||||
import LEVELS from '../levels'
|
import LEVELS from '../levels'
|
||||||
|
|
||||||
@@ -19,10 +18,10 @@ const facility = Facility.User
|
|||||||
export default target => {
|
export default target => {
|
||||||
const opts = {}
|
const opts = {}
|
||||||
if (target !== undefined) {
|
if (target !== undefined) {
|
||||||
if (startsWith(target, 'tcp://')) {
|
if (target.startsWith('tcp://')) {
|
||||||
target = target.slice(6)
|
target = target.slice(6)
|
||||||
opts.transport = Transport.Tcp
|
opts.transport = Transport.Tcp
|
||||||
} else if (startsWith(target, 'udp://')) {
|
} else if (target.startsWith('udp://')) {
|
||||||
target = target.slice(6)
|
target = target.slice(6)
|
||||||
opts.transport = Transport.Udp
|
opts.transport = Transport.Udp
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# ${pkg.name} [](https://travis-ci.org/${pkg.shortGitHubPath})
|
# @xen-orchestra/mixin [](https://travis-ci.org/${pkg.shortGitHubPath})
|
||||||
|
|
||||||
> ${pkg.description}
|
> ${pkg.description}
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Installation of the [npm package](https://npmjs.org/package/${pkg.name}):
|
Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/mixin):
|
||||||
|
|
||||||
```
|
```
|
||||||
> npm install --save ${pkg.name}
|
> npm install --save @xen-orchestra/mixin
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -35,15 +35,15 @@ Installation of the [npm package](https://npmjs.org/package/${pkg.name}):
|
|||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are *very* welcomed, either on the documentation or on
|
Contributions are _very_ welcomed, either on the documentation or on
|
||||||
the code.
|
the code.
|
||||||
|
|
||||||
You may:
|
You may:
|
||||||
|
|
||||||
- report any [issue](${pkg.bugs})
|
- report any [issue](https://github.com/vatesfr/xen-orchestra/issues)
|
||||||
you've encountered;
|
you've encountered;
|
||||||
- fork and create a pull request.
|
- fork and create a pull request.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
${pkg.license} © [${pkg.author.name}](${pkg.author.url})
|
ISC © [Vates SAS](https://vates.fr)
|
||||||
|
|||||||
@@ -36,8 +36,8 @@
|
|||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"babel-plugin-dev": "^1.0.0",
|
"babel-plugin-dev": "^1.0.0",
|
||||||
"babel-plugin-lodash": "^3.3.2",
|
"babel-plugin-lodash": "^3.3.2",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run prebuild",
|
"predev": "yarn run prebuild",
|
||||||
"prepublishOnly": "yarn run build"
|
"prepublishOnly": "yarn run build",
|
||||||
|
"postversion": "npm publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
@xen-orchestra/template/README.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# @xen-orchestra/template [](https://travis-ci.org/vatesfr/xen-orchestra)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Installation of the [npm package](https://npmjs.org/package/@xen-orchestra/template):
|
||||||
|
|
||||||
|
```
|
||||||
|
> npm install --save @xen-orchestra/template
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Create a string replacer based on a pattern and a list of rules.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const myReplacer = compileTemplate('{name}_COPY_{name}_{id}_%%', {
|
||||||
|
'{name}': vm => vm.name_label,
|
||||||
|
'{id}': vm => vm.id,
|
||||||
|
'%': (_, i) => i,
|
||||||
|
})
|
||||||
|
|
||||||
|
const newString = myReplacer(
|
||||||
|
{
|
||||||
|
name_label: 'foo',
|
||||||
|
id: 42,
|
||||||
|
},
|
||||||
|
32
|
||||||
|
)
|
||||||
|
|
||||||
|
newString === 'foo_COPY_{name}_42_32%' // true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```
|
||||||
|
# Install dependencies
|
||||||
|
> yarn
|
||||||
|
|
||||||
|
# Run the tests
|
||||||
|
> yarn test
|
||||||
|
|
||||||
|
# Continuously compile
|
||||||
|
> yarn dev
|
||||||
|
|
||||||
|
# Continuously run the tests
|
||||||
|
> yarn dev-test
|
||||||
|
|
||||||
|
# Build for production (automatically called by npm install)
|
||||||
|
> yarn build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributions
|
||||||
|
|
||||||
|
Contributions are _very_ welcomed, either on the documentation or on
|
||||||
|
the code.
|
||||||
|
|
||||||
|
You may:
|
||||||
|
|
||||||
|
- report any [issue](https://github.com/vatesfr/xen-orchestra/issues)
|
||||||
|
you've encountered;
|
||||||
|
- fork and create a pull request.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
ISC © [Vates SAS](https://vates.fr)
|
||||||
@@ -1,46 +1,35 @@
|
|||||||
{
|
{
|
||||||
"name": "xo-server-cloud",
|
"name": "@xen-orchestra/template",
|
||||||
"version": "0.2.4",
|
"version": "0.1.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "",
|
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@xen-orchestra/template",
|
||||||
"keywords": [
|
|
||||||
"cloud",
|
|
||||||
"orchestra",
|
|
||||||
"plugin",
|
|
||||||
"xen",
|
|
||||||
"xen-orchestra",
|
|
||||||
"xo-server"
|
|
||||||
],
|
|
||||||
"homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-cloud",
|
|
||||||
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
|
"bugs": "https://github.com/vatesfr/xen-orchestra/issues",
|
||||||
"repository": {
|
"repository": {
|
||||||
"directory": "packages/xo-server-cloud",
|
"directory": "@xen-orchestra/template",
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
"url": "https://github.com/vatesfr/xen-orchestra.git"
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Pierre Donias",
|
"name": "Julien Fontanet",
|
||||||
"email": "pierre.donias@gmail.com"
|
"email": "julien.fontanet@vates.fr"
|
||||||
},
|
},
|
||||||
"preferGlobal": false,
|
"preferGlobal": false,
|
||||||
"main": "dist/",
|
"main": "dist/",
|
||||||
"bin": {},
|
|
||||||
"files": [
|
"files": [
|
||||||
"dist/"
|
"dist/"
|
||||||
],
|
],
|
||||||
|
"browserslist": [
|
||||||
|
">2%"
|
||||||
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
|
||||||
"http-request-plus": "^0.7.2",
|
|
||||||
"jsonrpc-websocket-client": "^0.4.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.0.0",
|
"@babel/cli": "^7.0.0",
|
||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.0.0",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^6.0.3",
|
||||||
"rimraf": "^2.5.4"
|
"rimraf": "^3.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
"build": "cross-env NODE_ENV=production babel --source-maps --out-dir=dist/ src/",
|
||||||
@@ -48,6 +37,10 @@
|
|||||||
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
"dev": "cross-env NODE_ENV=development babel --watch --source-maps --out-dir=dist/ src/",
|
||||||
"prebuild": "yarn run clean",
|
"prebuild": "yarn run clean",
|
||||||
"predev": "yarn run prebuild",
|
"predev": "yarn run prebuild",
|
||||||
"prepublishOnly": "yarn run build"
|
"prepublishOnly": "yarn run build",
|
||||||
|
"postversion": "npm publish --access public"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": "^4.17.15"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
19
@xen-orchestra/template/src/index.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import escapeRegExp from 'lodash/escapeRegExp'
|
||||||
|
|
||||||
|
const compareLengthDesc = (a, b) => b.length - a.length
|
||||||
|
|
||||||
|
export function compileTemplate(pattern, rules) {
|
||||||
|
const matches = Object.keys(rules)
|
||||||
|
.sort(compareLengthDesc)
|
||||||
|
.map(escapeRegExp)
|
||||||
|
.join('|')
|
||||||
|
const regExp = new RegExp(`\\\\(?:\\\\|${matches})|${matches}`, 'g')
|
||||||
|
return (...params) =>
|
||||||
|
pattern.replace(regExp, match => {
|
||||||
|
if (match[0] === '\\') {
|
||||||
|
return match.slice(1)
|
||||||
|
}
|
||||||
|
const rule = rules[match]
|
||||||
|
return typeof rule === 'function' ? rule(...params) : rule
|
||||||
|
})
|
||||||
|
}
|
||||||
14
@xen-orchestra/template/src/index.spec.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* eslint-env jest */
|
||||||
|
import { compileTemplate } from '.'
|
||||||
|
|
||||||
|
it("correctly replaces the template's variables", () => {
|
||||||
|
const replacer = compileTemplate(
|
||||||
|
'{property}_\\{property}_\\\\{property}_{constant}_%_FOO',
|
||||||
|
{
|
||||||
|
'{property}': obj => obj.name,
|
||||||
|
'{constant}': 1235,
|
||||||
|
'%': (_, i) => i,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
expect(replacer({ name: 'bar' }, 5)).toBe('bar_{property}_\\bar_1235_5_FOO')
|
||||||
|
})
|
||||||
443
CHANGELOG.md
@@ -1,5 +1,448 @@
|
|||||||
# ChangeLog
|
# ChangeLog
|
||||||
|
|
||||||
|
## **next**
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
## **5.41.0** (2019-11-29)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- [Backup NG] Make report recipients configurable in the backup settings [#4581](https://github.com/vatesfr/xen-orchestra/issues/4581) (PR [#4646](https://github.com/vatesfr/xen-orchestra/pull/4646))
|
||||||
|
- [Host] Advanced Live Telemetry (PR [#4680](https://github.com/vatesfr/xen-orchestra/pull/4680))
|
||||||
|
- [Plugin] [Web hooks](https://xen-orchestra.com/docs/web-hooks.html) [#1946](https://github.com/vatesfr/xen-orchestra/issues/1946) (PR [#3155](https://github.com/vatesfr/xen-orchestra/pull/3155))
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [SAML] Setting to disable requested authentication context (helps with _Active Directory_) (PR [#4675](https://github.com/vatesfr/xen-orchestra/pull/4675))
|
||||||
|
- The default sign-in page can be configured via `authentication.defaultSignInPage` (PR [#4678](https://github.com/vatesfr/xen-orchestra/pull/4678))
|
||||||
|
- [SR] Allow import of VHD and VMDK disks [#4137](https://github.com/vatesfr/xen-orchestra/issues/4137) (PR [#4138](https://github.com/vatesfr/xen-orchestra/pull/4138) )
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [Metadata backup] Add 10 minutes timeout to avoid stuck jobs [#4657](https://github.com/vatesfr/xen-orchestra/issues/4657) (PR [#4666](https://github.com/vatesfr/xen-orchestra/pull/4666))
|
||||||
|
- [Metadata backups] Fix out-of-date listing for 1 minute due to cache (PR [#4672](https://github.com/vatesfr/xen-orchestra/pull/4672))
|
||||||
|
- [Delta backup] Limit the number of merged deltas per run to avoid interrupted jobs (PR [#4674](https://github.com/vatesfr/xen-orchestra/pull/4674))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- vhd-lib v0.7.2
|
||||||
|
- xo-vmdk-to-vhd v0.1.8
|
||||||
|
- xo-server-auth-ldap v0.6.6
|
||||||
|
- xo-server-auth-saml v0.7.0
|
||||||
|
- xo-server-backup-reports v0.16.4
|
||||||
|
- xo-server-web-hooks v0.1.0
|
||||||
|
- @xen-orchestra/fs v0.10.2
|
||||||
|
- xo-server v5.53.0
|
||||||
|
- xo-web v5.53.3
|
||||||
|
|
||||||
|
## **5.40.2** (2019-11-22)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [Logs] Ability to report a bug with attached log (PR [#4201](https://github.com/vatesfr/xen-orchestra/pull/4201))
|
||||||
|
- [Backup] Reduce _VDI chain protection error_ occurrence by being more tolerant (configurable via `xo-server`'s `xapiOptions.maxUncoalescedVdis` setting) [#4124](https://github.com/vatesfr/xen-orchestra/issues/4124) (PR [#4651](https://github.com/vatesfr/xen-orchestra/pull/4651))
|
||||||
|
- [Tables] Always put the tables' search in the URL [#4542](https://github.com/vatesfr/xen-orchestra/issues/4542) (PR [#4637](https://github.com/vatesfr/xen-orchestra/pull/4637))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [SDN controller] Prevent private network creation on bond slave PIF (Fixes https://github.com/xcp-ng/xcp/issues/300) (PR [4633](https://github.com/vatesfr/xen-orchestra/pull/4633))
|
||||||
|
- [Metadata backup] Fix failed backup reported as successful [#4596](https://github.com/vatesfr/xen-orchestra/issues/4596) (PR [#4598](https://github.com/vatesfr/xen-orchestra/pull/4598))
|
||||||
|
- [Backup NG] Fix "task cancelled" error when the backup job timeout exceeds 596 hours [#4662](https://github.com/vatesfr/xen-orchestra/issues/4662) (PR [#4663](https://github.com/vatesfr/xen-orchestra/pull/4663))
|
||||||
|
- Fix `promise rejected with non-error` warnings in logs (PR [#4659](https://github.com/vatesfr/xen-orchestra/pull/4659))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xen-api v0.27.3
|
||||||
|
- xo-server-backup-reports v0.16.3
|
||||||
|
- vhd-lib v0.7.1
|
||||||
|
- xo-server v5.52.1
|
||||||
|
- xo-web v5.52.0
|
||||||
|
|
||||||
|
## **5.40.1** (2019-10-29)
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [XOSAN] Fix "Install Cloud plugin" warning (PR [#4631](https://github.com/vatesfr/xen-orchestra/pull/4631))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xo-web v5.51.1
|
||||||
|
|
||||||
|
## **5.40.0** (2019-10-29)
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
|
||||||
|
- `xo-server` requires Node 8.
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- [Backup NG] Offline backup feature [#3449](https://github.com/vatesfr/xen-orchestra/issues/3449) (PR [#4470](https://github.com/vatesfr/xen-orchestra/pull/4470))
|
||||||
|
- [Menu] Remove legacy backup entry [#4467](https://github.com/vatesfr/xen-orchestra/issues/4467) (PR [#4476](https://github.com/vatesfr/xen-orchestra/pull/4476))
|
||||||
|
- [Hub] Ability to update existing template (PR [#4613](https://github.com/vatesfr/xen-orchestra/pull/4613))
|
||||||
|
- [Support] Ability to open and close support tunnel from the user interface [#4513](https://github.com/vatesfr/xen-orchestra/issues/4513) (PR [#4616](https://github.com/vatesfr/xen-orchestra/pull/4616))
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [Hub] Ability to select SR in hub VM installation (PR [#4571](https://github.com/vatesfr/xen-orchestra/pull/4571))
|
||||||
|
- [Hub] Display more info about downloadable templates (PR [#4593](https://github.com/vatesfr/xen-orchestra/pull/4593))
|
||||||
|
- [xo-server-transport-icinga2] Add support of [icinga2](https://icinga.com/docs/icinga2/latest/doc/12-icinga2-api/) for reporting services status [#4563](https://github.com/vatesfr/xen-orchestra/issues/4563) (PR [#4573](https://github.com/vatesfr/xen-orchestra/pull/4573))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [SR] Fix `[object HTMLInputElement]` name after re-attaching a SR [#4546](https://github.com/vatesfr/xen-orchestra/issues/4546) (PR [#4550](https://github.com/vatesfr/xen-orchestra/pull/4550))
|
||||||
|
- [Schedules] Prevent double runs [#4625](https://github.com/vatesfr/xen-orchestra/issues/4625) (PR [#4626](https://github.com/vatesfr/xen-orchestra/pull/4626))
|
||||||
|
- [Schedules] Properly enable/disable on config import (PR [#4624](https://github.com/vatesfr/xen-orchestra/pull/4624))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- @xen-orchestra/cron v1.0.6
|
||||||
|
- xo-server-transport-icinga2 v0.1.0
|
||||||
|
- xo-server-sdn-controller v0.3.1
|
||||||
|
- xo-server v5.51.1
|
||||||
|
- xo-web v5.51.0
|
||||||
|
|
||||||
|
### Dropped packages
|
||||||
|
|
||||||
|
- xo-server-cloud : this package was useless for OpenSource installations because it required a complete XOA environment
|
||||||
|
|
||||||
|
|
||||||
|
## **5.39.1** (2019-10-11)
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [Support] Ability to check the XOA on the user interface [#4513](https://github.com/vatesfr/xen-orchestra/issues/4513) (PR [#4574](https://github.com/vatesfr/xen-orchestra/pull/4574))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [VM/new-vm] Fix template selection on creating new VM for resource sets [#4565](https://github.com/vatesfr/xen-orchestra/issues/4565) (PR [#4568](https://github.com/vatesfr/xen-orchestra/pull/4568))
|
||||||
|
- [VM] Clearer invalid cores per socket error [#4120](https://github.com/vatesfr/xen-orchestra/issues/4120) (PR [#4187](https://github.com/vatesfr/xen-orchestra/pull/4187))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xo-web v5.50.3
|
||||||
|
|
||||||
|
|
||||||
|
## **5.39.0** (2019-09-30)
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- [VM/console] Add a button to connect to the VM via the local SSH client (PR [#4415](https://github.com/vatesfr/xen-orchestra/pull/4415))
|
||||||
|
- [SDN Controller] Add possibility to encrypt private networks (PR [#4441](https://github.com/vatesfr/xen-orchestra/pull/4441))
|
||||||
|
- [Backups] Improve performance by caching VM backups listing (PR [#4509](https://github.com/vatesfr/xen-orchestra/pull/4509))
|
||||||
|
- [HUB] VM template store [#1918](https://github.com/vatesfr/xen-orchestra/issues/1918) (PR [#4442](https://github.com/vatesfr/xen-orchestra/pull/4442))
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [SR/new] Clarify address formats [#4450](https://github.com/vatesfr/xen-orchestra/issues/4450) (PR [#4460](https://github.com/vatesfr/xen-orchestra/pull/4460))
|
||||||
|
- [Backup NG/New] Show warning if zstd compression is not supported on a VM [#3892](https://github.com/vatesfr/xen-orchestra/issues/3892) (PRs [#4411](https://github.com/vatesfr/xen-orchestra/pull/4411))
|
||||||
|
- [VM/disks] Don't hide disks that are attached to the same VM twice [#4400](https://github.com/vatesfr/xen-orchestra/issues/4400) (PR [#4414](https://github.com/vatesfr/xen-orchestra/pull/4414))
|
||||||
|
- [SDN Controller] Ability to configure MTU for private networks (PR [#4491](https://github.com/vatesfr/xen-orchestra/pull/4491))
|
||||||
|
- [VM Export] Filenames are now prefixed with datetime [#4503](https://github.com/vatesfr/xen-orchestra/issues/4503)
|
||||||
|
- [Settings/Logs] Differenciate XS/XCP-ng errors from XO errors [#4101](https://github.com/vatesfr/xen-orchestra/issues/4101) (PR [#4385](https://github.com/vatesfr/xen-orchestra/pull/4385))
|
||||||
|
- [Backups] Improve performance by caching logs consolidation (PR [#4541](https://github.com/vatesfr/xen-orchestra/pull/4541))
|
||||||
|
- [New VM] Cloud Init available for all plans (PR [#4543](https://github.com/vatesfr/xen-orchestra/pull/4543))
|
||||||
|
- [Servers] IPv6 addresses can be used [#4520](https://github.com/vatesfr/xen-orchestra/issues/4520) (PR [#4521](https://github.com/vatesfr/xen-orchestra/pull/4521)) \
|
||||||
|
Note: They must enclosed in brackets to differentiate with the port, e.g.: `[2001:db8::7334]` or `[ 2001:db8::7334]:4343`
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [PBD] Obfuscate cifs password from device config [#4384](https://github.com/vatesfr/xen-orchestra/issues/4384) (PR [#4401](https://github.com/vatesfr/xen-orchestra/pull/4401))
|
||||||
|
- [XOSAN] Fix "invalid parameters" error on creating a SR (PR [#4478](https://github.com/vatesfr/xen-orchestra/pull/4478))
|
||||||
|
- [Patching] Avoid overloading XCP-ng by reducing the frequency of yum update checks [#4358](https://github.com/vatesfr/xen-orchestra/issues/4358) (PR [#4477](https://github.com/vatesfr/xen-orchestra/pull/4477))
|
||||||
|
- [Network] Fix inability to create a bonded network (PR [#4489](https://github.com/vatesfr/xen-orchestra/pull/4489))
|
||||||
|
- [Backup restore & Replication] Don't copy `sm_config` to new VDIs which might leads to useless coalesces [#4482](https://github.com/vatesfr/xen-orchestra/issues/4482) (PR [#4484](https://github.com/vatesfr/xen-orchestra/pull/4484))
|
||||||
|
- [Home] Fix intermediary "no results" display showed on filtering items [#4420](https://github.com/vatesfr/xen-orchestra/issues/4420) (PR [#4456](https://github.com/vatesfr/xen-orchestra/pull/4456)
|
||||||
|
- [Backup NG/New schedule] Properly show user errors in the form [#3831](https://github.com/vatesfr/xen-orchestra/issues/3831) (PR [#4131](https://github.com/vatesfr/xen-orchestra/pull/4131))
|
||||||
|
- [VM/Advanced] Fix `"vm.set_domain_type" is not a function` error on switching virtualization mode (PV/HVM) [#4348](https://github.com/vatesfr/xen-orchestra/issues/4348) (PR [#4504](https://github.com/vatesfr/xen-orchestra/pull/4504))
|
||||||
|
- [Backup NG/logs] Show warning when zstd compression is selected but not supported [#3892](https://github.com/vatesfr/xen-orchestra/issues/3892) (PR [#4375](https://github.com/vatesfr/xen-orchestra/pull/4375)
|
||||||
|
- [Patches] Fix patches installation for CH 8.0 (PR [#4511](https://github.com/vatesfr/xen-orchestra/pull/4511))
|
||||||
|
- [Network] Fix inability to set a network name [#4514](https://github.com/vatesfr/xen-orchestra/issues/4514) (PR [4510](https://github.com/vatesfr/xen-orchestra/pull/4510))
|
||||||
|
- [Backup NG] Fix race conditions that could lead to disabled jobs still running (PR [4510](https://github.com/vatesfr/xen-orchestra/pull/4510))
|
||||||
|
- [XOA] Remove "Updates" and "Licenses" tabs for non admin users (PR [#4526](https://github.com/vatesfr/xen-orchestra/pull/4526))
|
||||||
|
- [New VM] Ability to escape [cloud config template](https://xen-orchestra.com/blog/xen-orchestra-5-21/#cloudconfigtemplates) variables [#4486](https://github.com/vatesfr/xen-orchestra/issues/4486) (PR [#4501](https://github.com/vatesfr/xen-orchestra/pull/4501))
|
||||||
|
- [Backup NG] Properly log and report if job is already running [#4497](https://github.com/vatesfr/xen-orchestra/issues/4497) (PR [4534](https://github.com/vatesfr/xen-orchestra/pull/4534))
|
||||||
|
- [Host] Fix an issue where host was wrongly reporting time inconsistency (PR [#4540](https://github.com/vatesfr/xen-orchestra/pull/4540))
|
||||||
|
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xen-api v0.27.2
|
||||||
|
- xo-server-cloud v0.3.0
|
||||||
|
- @xen-orchestra/cron v1.0.4
|
||||||
|
- xo-server-sdn-controller v0.3.0
|
||||||
|
- @xen-orchestra/template v0.1.0
|
||||||
|
- xo-server v5.50.1
|
||||||
|
- xo-web v5.50.2
|
||||||
|
|
||||||
|
|
||||||
|
## **5.38.0** (2019-08-29)
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [VM/Attach disk] Display confirmation modal when VDI is already attached [#3381](https://github.com/vatesfr/xen-orchestra/issues/3381) (PR [#4366](https://github.com/vatesfr/xen-orchestra/pull/4366))
|
||||||
|
- [Zstd]
|
||||||
|
- [VM/copy, VM/export] Only show zstd option when it's supported [#3892](https://github.com/vatesfr/xen-orchestra/issues/3892) (PRs [#4326](https://github.com/vatesfr/xen-orchestra/pull/4326) [#4368](https://github.com/vatesfr/xen-orchestra/pull/4368))
|
||||||
|
- [VM/Bulk copy] Show warning if zstd compression is not supported on a VM [#3892](https://github.com/vatesfr/xen-orchestra/issues/3892) (PR [#4346](https://github.com/vatesfr/xen-orchestra/pull/4346))
|
||||||
|
- [VM import & Continuous Replication] Enable `guessVhdSizeOnImport` by default, this fix some `VDI_IO_ERROR` with XenServer 7.1 and XCP-ng 8.0 (PR [#4436](https://github.com/vatesfr/xen-orchestra/pull/4436))
|
||||||
|
- [SDN Controller] Add possibility to create multiple GRE networks and VxLAN networks within a same pool (PR [#4435](https://github.com/vatesfr/xen-orchestra/pull/4435))
|
||||||
|
- [SDN Controller] Add possibility to create cross-pool private networks (PR [#4405](https://github.com/vatesfr/xen-orchestra/pull/4405))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [SR/General] Display VDI VM name in SR usage graph (PR [#4370](https://github.com/vatesfr/xen-orchestra/pull/4370))
|
||||||
|
- [VM/Attach disk] Fix checking VDI mode (PR [#4373](https://github.com/vatesfr/xen-orchestra/pull/4373))
|
||||||
|
- [VM revert] Snapshot before: add admin ACLs on created snapshot [#4331](https://github.com/vatesfr/xen-orchestra/issues/4331) (PR [#4391](https://github.com/vatesfr/xen-orchestra/pull/4391))
|
||||||
|
- [Network] Fixed "invalid parameters" error when creating bonded network [#4425](https://github.com/vatesfr/xen-orchestra/issues/4425) (PR [#4429](https://github.com/vatesfr/xen-orchestra/pull/4429))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xo-server-sdn-controller v0.2.0
|
||||||
|
- xo-server-usage-report v0.7.3
|
||||||
|
- xo-server v5.48.0
|
||||||
|
- xo-web v5.48.1
|
||||||
|
|
||||||
|
## **5.37.1** (2019-08-06)
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [SDN Controller] Let the user choose on which PIF to create a private network (PR [#4379](https://github.com/vatesfr/xen-orchestra/pull/4379))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [SDN Controller] Better detect host shutting down to adapt network topology (PR [#4314](https://github.com/vatesfr/xen-orchestra/pull/4314))
|
||||||
|
- [SDN Controller] Add new hosts to pool's private networks (PR [#4382](https://github.com/vatesfr/xen-orchestra/pull/4382))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xo-server-sdn-controller v0.1.2
|
||||||
|
|
||||||
|
## **5.37.0** (2019-07-25)
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- [Pool] Ability to add multiple hosts on the pool [#2402](https://github.com/vatesfr/xen-orchestra/issues/2402) (PR [#3716](https://github.com/vatesfr/xen-orchestra/pull/3716))
|
||||||
|
- [SR/General] Improve SR usage graph [#3608](https://github.com/vatesfr/xen-orchestra/issues/3608) (PR [#3830](https://github.com/vatesfr/xen-orchestra/pull/3830))
|
||||||
|
- [VM] Permission to revert to any snapshot for VM operators [#3928](https://github.com/vatesfr/xen-orchestra/issues/3928) (PR [#4247](https://github.com/vatesfr/xen-orchestra/pull/4247))
|
||||||
|
- [Backup NG] Ability to bypass unhealthy VDI chains check [#4324](https://github.com/vatesfr/xen-orchestra/issues/4324) (PR [#4340](https://github.com/vatesfr/xen-orchestra/pull/4340))
|
||||||
|
- [VM/console] Multiline copy/pasting [#4261](https://github.com/vatesfr/xen-orchestra/issues/4261) (PR [#4341](https://github.com/vatesfr/xen-orchestra/pull/4341))
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [Stats] Ability to display last day stats [#4160](https://github.com/vatesfr/xen-orchestra/issues/4160) (PR [#4168](https://github.com/vatesfr/xen-orchestra/pull/4168))
|
||||||
|
- [Settings/servers] Display servers connection issues [#4300](https://github.com/vatesfr/xen-orchestra/issues/4300) (PR [#4310](https://github.com/vatesfr/xen-orchestra/pull/4310))
|
||||||
|
- [VM] Show current operations and progress [#3811](https://github.com/vatesfr/xen-orchestra/issues/3811) (PR [#3982](https://github.com/vatesfr/xen-orchestra/pull/3982))
|
||||||
|
- [Backup NG/New] Generate default schedule if no schedule is specified [#4036](https://github.com/vatesfr/xen-orchestra/issues/4036) (PR [#4183](https://github.com/vatesfr/xen-orchestra/pull/4183))
|
||||||
|
- [Host/Advanced] Ability to edit iSCSI IQN [#4048](https://github.com/vatesfr/xen-orchestra/issues/4048) (PR [#4208](https://github.com/vatesfr/xen-orchestra/pull/4208))
|
||||||
|
- [VM,host] Improved state icons/pills (colors and tooltips) (PR [#4363](https://github.com/vatesfr/xen-orchestra/pull/4363))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [Settings/Servers] Fix read-only setting toggling
|
||||||
|
- [SDN Controller] Do not choose physical PIF without IP configuration for tunnels. (PR [#4319](https://github.com/vatesfr/xen-orchestra/pull/4319))
|
||||||
|
- [Xen servers] Fix `no connection found for object` error if pool master is reinstalled [#4299](https://github.com/vatesfr/xen-orchestra/issues/4299) (PR [#4302](https://github.com/vatesfr/xen-orchestra/pull/4302))
|
||||||
|
- [Backup-ng/restore] Display correct size for full VM backup [#4316](https://github.com/vatesfr/xen-orchestra/issues/4316) (PR [#4332](https://github.com/vatesfr/xen-orchestra/pull/4332))
|
||||||
|
- [VM/tab-advanced] Fix CPU limits edition (PR [#4337](https://github.com/vatesfr/xen-orchestra/pull/4337))
|
||||||
|
- [Remotes] Fix `EIO` errors due to massive parallel fs operations [#4323](https://github.com/vatesfr/xen-orchestra/issues/4323) (PR [#4330](https://github.com/vatesfr/xen-orchestra/pull/4330))
|
||||||
|
- [VM/Advanced] Fix virtualization mode switch (PV/HVM) (PR [#4349](https://github.com/vatesfr/xen-orchestra/pull/4349))
|
||||||
|
- [Task] fix hidden notification by search field [#3874](https://github.com/vatesfr/xen-orchestra/issues/3874) (PR [#4305](https://github.com/vatesfr/xen-orchestra/pull/4305)
|
||||||
|
- [VM] Fail to change affinity (PR [#4361](https://github.com/vatesfr/xen-orchestra/pull/4361)
|
||||||
|
- [VM] Number of CPUs not correctly changed on running VMs (PR [#4360](https://github.com/vatesfr/xen-orchestra/pull/4360)
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- @xen-orchestra/fs v0.10.1
|
||||||
|
- xo-server-sdn-controller v0.1.1
|
||||||
|
- xen-api v0.27.1
|
||||||
|
- xo-server v5.46.0
|
||||||
|
- xo-web v5.46.0
|
||||||
|
|
||||||
|
## **5.36.0** (2019-06-27)
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- [SR/new] Create ZFS storage [#4260](https://github.com/vatesfr/xen-orchestra/issues/4260) (PR [#4266](https://github.com/vatesfr/xen-orchestra/pull/4266))
|
||||||
|
- [Host/advanced] Fix host CPU hyperthreading detection [#4262](https://github.com/vatesfr/xen-orchestra/issues/4262) (PR [#4285](https://github.com/vatesfr/xen-orchestra/pull/4285))
|
||||||
|
- [VM/Advanced] Ability to use UEFI instead of BIOS [#4264](https://github.com/vatesfr/xen-orchestra/issues/4264) (PR [#4268](https://github.com/vatesfr/xen-orchestra/pull/4268))
|
||||||
|
- [Backup-ng/restore] Display size for full VM backup [#4009](https://github.com/vatesfr/xen-orchestra/issues/4009) (PR [#4245](https://github.com/vatesfr/xen-orchestra/pull/4245))
|
||||||
|
- [Sr/new] Ability to select NFS version when creating NFS storage [#3951](https://github.com/vatesfr/xen-orchestra/issues/3951) (PR [#4277](https://github.com/vatesfr/xen-orchestra/pull/4277))
|
||||||
|
- [Host/storages, SR/hosts] Display PBD details [#4264](https://github.com/vatesfr/xen-orchestra/issues/4161) (PR [#4268](https://github.com/vatesfr/xen-orchestra/pull/4284))
|
||||||
|
- [auth-saml] Improve compatibility with Microsoft Azure Active Directory (PR [#4294](https://github.com/vatesfr/xen-orchestra/pull/4294))
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [Host] Display warning when "Citrix Hypervisor" license has restrictions [#4251](https://github.com/vatesfr/xen-orchestra/issues/4164) (PR [#4235](https://github.com/vatesfr/xen-orchestra/pull/4279))
|
||||||
|
- [VM/Backup] Create backup bulk action [#2573](https://github.com/vatesfr/xen-orchestra/issues/2573) (PR [#4257](https://github.com/vatesfr/xen-orchestra/pull/4257))
|
||||||
|
- [Host] Display warning when host's time differs too much from XOA's time [#4113](https://github.com/vatesfr/xen-orchestra/issues/4113) (PR [#4173](https://github.com/vatesfr/xen-orchestra/pull/4173))
|
||||||
|
- [VM/network] Display and set bandwidth rate-limit of a VIF [#4215](https://github.com/vatesfr/xen-orchestra/issues/4215) (PR [#4293](https://github.com/vatesfr/xen-orchestra/pull/4293))
|
||||||
|
- [SDN Controller] New plugin which enables creating pool-wide private networks [xcp-ng/xcp#175](https://github.com/xcp-ng/xcp/issues/175) (PR [#4269](https://github.com/vatesfr/xen-orchestra/pull/4269))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [XOA] Don't require editing the _email_ field in case of re-registration (PR [#4259](https://github.com/vatesfr/xen-orchestra/pull/4259))
|
||||||
|
- [Metadata backup] Missing XAPIs should trigger a failure job [#4281](https://github.com/vatesfr/xen-orchestra/issues/4281) (PR [#4283](https://github.com/vatesfr/xen-orchestra/pull/4283))
|
||||||
|
- [iSCSI] Fix fibre channel paths display [#4291](https://github.com/vatesfr/xen-orchestra/issues/4291) (PR [#4303](https://github.com/vatesfr/xen-orchestra/pull/4303))
|
||||||
|
- [New VM] Fix tooltips not displayed on disabled elements in some browsers (e.g. Google Chrome) [#4304](https://github.com/vatesfr/xen-orchestra/issues/4304) (PR [#4309](https://github.com/vatesfr/xen-orchestra/pull/4309))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xo-server-auth-ldap v0.6.5
|
||||||
|
- xen-api v0.26.0
|
||||||
|
- xo-server-sdn-controller v0.1
|
||||||
|
- xo-server-auth-saml v0.6.0
|
||||||
|
- xo-server-backup-reports v0.16.2
|
||||||
|
- xo-server v5.44.0
|
||||||
|
- xo-web v5.44.0
|
||||||
|
|
||||||
|
## **5.35.0** (2019-05-29)
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [VM/general] Display 'Started... ago' instead of 'Halted... ago' for paused state [#3750](https://github.com/vatesfr/xen-orchestra/issues/3750) (PR [#4170](https://github.com/vatesfr/xen-orchestra/pull/4170))
|
||||||
|
- [Metadata backup] Ability to define when the backup report will be sent (PR [#4149](https://github.com/vatesfr/xen-orchestra/pull/4149))
|
||||||
|
- [XOA/Update] Ability to select release channel [#4200](https://github.com/vatesfr/xen-orchestra/issues/4200) (PR [#4202](https://github.com/vatesfr/xen-orchestra/pull/4202))
|
||||||
|
- [User] Forget connection tokens on password change or on demand [#4214](https://github.com/vatesfr/xen-orchestra/issues/4214) (PR [#4224](https://github.com/vatesfr/xen-orchestra/pull/4224))
|
||||||
|
- [Settings/Logs] LICENCE_RESTRICTION errors: suggest XCP-ng as an Open Source alternative [#3876](https://github.com/vatesfr/xen-orchestra/issues/3876) (PR [#4238](https://github.com/vatesfr/xen-orchestra/pull/4238))
|
||||||
|
- [VM/Migrate] Display VDI size on migrate modal [#2534](https://github.com/vatesfr/xen-orchestra/issues/2534) (PR [#4250](https://github.com/vatesfr/xen-orchestra/pull/4250))
|
||||||
|
- [Host] Display hyperthreading status on advanced tab [#4262](https://github.com/vatesfr/xen-orchestra/issues/4262) (PR [#4263](https://github.com/vatesfr/xen-orchestra/pull/4263))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [Pool/Patches] Fix "an error has occurred" in "Applied patches" [#4192](https://github.com/vatesfr/xen-orchestra/issues/4192) (PR [#4193](https://github.com/vatesfr/xen-orchestra/pull/4193))
|
||||||
|
- [Backup NG] Fix report sent even though "Never" is selected [#4092](https://github.com/vatesfr/xen-orchestra/issues/4092) (PR [#4178](https://github.com/vatesfr/xen-orchestra/pull/4178))
|
||||||
|
- [Remotes] Fix issues after a config import (PR [#4197](https://github.com/vatesfr/xen-orchestra/pull/4197))
|
||||||
|
- [Charts] Fixed the chart lines sometimes changing order/color (PR [#4221](https://github.com/vatesfr/xen-orchestra/pull/4221))
|
||||||
|
- Prevent non-admin users to access admin pages with URL (PR [#4220](https://github.com/vatesfr/xen-orchestra/pull/4220))
|
||||||
|
- [Upgrade] Fix alert before upgrade while running backup jobs [#4164](https://github.com/vatesfr/xen-orchestra/issues/4164) (PR [#4235](https://github.com/vatesfr/xen-orchestra/pull/4235))
|
||||||
|
- [Import] Fix import OVA files (PR [#4232](https://github.com/vatesfr/xen-orchestra/pull/4232))
|
||||||
|
- [VM/network] Fix duplicate IPv4 (PR [#4239](https://github.com/vatesfr/xen-orchestra/pull/4239))
|
||||||
|
- [Remotes] Fix disconnected remotes which may appear to work
|
||||||
|
- [Host] Fix incorrect hypervisor name [#4246](https://github.com/vatesfr/xen-orchestra/issues/4246) (PR [#4248](https://github.com/vatesfr/xen-orchestra/pull/4248))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xo-server-backup-reports v0.16.1
|
||||||
|
- @xen-orchestra/fs v0.9.0
|
||||||
|
- vhd-lib v0.7.0
|
||||||
|
- xo-server v5.42.1
|
||||||
|
- xo-web v5.42.1
|
||||||
|
|
||||||
|
## **5.34.0** (2019-04-30)
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- [Self/New VM] Add network config box to custom cloud-init [#3872](https://github.com/vatesfr/xen-orchestra/issues/3872) (PR [#4150](https://github.com/vatesfr/xen-orchestra/pull/4150))
|
||||||
|
- [Metadata backup] Detailed logs [#4005](https://github.com/vatesfr/xen-orchestra/issues/4005) (PR [#4014](https://github.com/vatesfr/xen-orchestra/pull/4014))
|
||||||
|
- [Backup reports] Support metadata backups (PR [#4084](https://github.com/vatesfr/xen-orchestra/pull/4084))
|
||||||
|
- [VM migration] Auto select default SR and collapse optional actions [#3326](https://github.com/vatesfr/xen-orchestra/issues/3326) (PR [#4121](https://github.com/vatesfr/xen-orchestra/pull/4121))
|
||||||
|
- Unlock basic stats on all editions [#4166](https://github.com/vatesfr/xen-orchestra/issues/4166) (PR [#4172](https://github.com/vatesfr/xen-orchestra/pull/4172))
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [Settings/remotes] Expose mount options field for SMB [#4063](https://github.com/vatesfr/xen-orchestra/issues/4063) (PR [#4067](https://github.com/vatesfr/xen-orchestra/pull/4067))
|
||||||
|
- [Backup/Schedule] Add warning regarding DST when you add a schedule [#4042](https://github.com/vatesfr/xen-orchestra/issues/4042) (PR [#4056](https://github.com/vatesfr/xen-orchestra/pull/4056))
|
||||||
|
- [Import] Avoid blocking the UI when dropping a big OVA file on the UI (PR [#4018](https://github.com/vatesfr/xen-orchestra/pull/4018))
|
||||||
|
- [Backup NG/Overview] Make backup list title clearer [#4111](https://github.com/vatesfr/xen-orchestra/issues/4111) (PR [#4129](https://github.com/vatesfr/xen-orchestra/pull/4129))
|
||||||
|
- [Dashboard] Hide "Report" section for non-admins [#4123](https://github.com/vatesfr/xen-orchestra/issues/4123) (PR [#4126](https://github.com/vatesfr/xen-orchestra/pull/4126))
|
||||||
|
- [Self/New VM] Display confirmation modal when user will use a large amount of resources [#4044](https://github.com/vatesfr/xen-orchestra/issues/4044) (PR [#4127](https://github.com/vatesfr/xen-orchestra/pull/4127))
|
||||||
|
- [VDI migration, New disk] Warning when SR host is different from the other disks [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#4035](https://github.com/vatesfr/xen-orchestra/pull/4035))
|
||||||
|
- [Attach disk] Display warning message when VDI SR is on different host from the other disks [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#4117](https://github.com/vatesfr/xen-orchestra/pull/4117))
|
||||||
|
- [Editable] Notify user when editable undo fails [#3799](https://github.com/vatesfr/xen-orchestra/issues/3799) (PR [#4150](https://github.com/vatesfr/xen-orchestra/pull/4157))
|
||||||
|
- [XO] Add banner for sources users to clarify support conditions [#4165](https://github.com/vatesfr/xen-orchestra/issues/4165) (PR [#4167](https://github.com/vatesfr/xen-orchestra/pull/4167))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [Continuous Replication] Fix VHD size guess for empty files [#4105](https://github.com/vatesfr/xen-orchestra/issues/4105) (PR [#4107](https://github.com/vatesfr/xen-orchestra/pull/4107))
|
||||||
|
- [Backup NG] Only display full backup interval in case of a delta backup (PR [#4125](https://github.com/vatesfr/xen-orchestra/pull/4107))
|
||||||
|
- [Dashboard/Health] fix 'an error has occurred' on the storage state table [#4128](https://github.com/vatesfr/xen-orchestra/issues/4128) (PR [#4132](https://github.com/vatesfr/xen-orchestra/pull/4132))
|
||||||
|
- [Menu] XOA: Fixed empty slot when menu is collapsed [#4012](https://github.com/vatesfr/xen-orchestra/issues/4012) (PR [#4068](https://github.com/vatesfr/xen-orchestra/pull/4068)
|
||||||
|
- [Self/New VM] Fix missing templates when refreshing page [#3265](https://github.com/vatesfr/xen-orchestra/issues/3265) (PR [#3565](https://github.com/vatesfr/xen-orchestra/pull/3565))
|
||||||
|
- [Home] No more false positives when select Tag on Home page [#4087](https://github.com/vatesfr/xen-orchestra/issues/4087) (PR [#4112](https://github.com/vatesfr/xen-orchestra/pull/4112))
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xo-server-backup-reports v0.16.0
|
||||||
|
- complex-matcher v0.6.0
|
||||||
|
- xo-vmdk-to-vhd v0.1.7
|
||||||
|
- vhd-lib v0.6.1
|
||||||
|
- xo-server v5.40.0
|
||||||
|
- xo-web v5.40.1
|
||||||
|
|
||||||
|
## **5.33.1** (2019-04-04)
|
||||||
|
|
||||||
|
### Bug fix
|
||||||
|
|
||||||
|
- Fix major memory leak [2563be4](https://github.com/vatesfr/xen-orchestra/commit/2563be472bfd84c6ed867efd21c4aeeb824d387f)
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xen-api v0.25.1
|
||||||
|
- xo-server v5.38.2
|
||||||
|
|
||||||
|
## **5.33.0** (2019-03-29)
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
- [SR/Disk] Disable actions on unmanaged VDIs [#3988](https://github.com/vatesfr/xen-orchestra/issues/3988) (PR [#4000](https://github.com/vatesfr/xen-orchestra/pull/4000))
|
||||||
|
- [Pool] Specify automatic networks on a Pool [#3916](https://github.com/vatesfr/xen-orchestra/issues/3916) (PR [#3958](https://github.com/vatesfr/xen-orchestra/pull/3958))
|
||||||
|
- [VM/advanced] Manage start delay for VM [#3909](https://github.com/vatesfr/xen-orchestra/issues/3909) (PR [#4002](https://github.com/vatesfr/xen-orchestra/pull/4002))
|
||||||
|
- [New/Vm] SR section: Display warning message when the selected SRs aren't in the same host [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#3967](https://github.com/vatesfr/xen-orchestra/pull/3967))
|
||||||
|
- Enable compression for HTTP requests (and initial objects fetch)
|
||||||
|
- [VDI migration] Display same-pool SRs first in the selector [#3945](https://github.com/vatesfr/xen-orchestra/issues/3945) (PR [#3996](https://github.com/vatesfr/xen-orchestra/pull/3996))
|
||||||
|
- [Home] Save the current page in url [#3993](https://github.com/vatesfr/xen-orchestra/issues/3993) (PR [#3999](https://github.com/vatesfr/xen-orchestra/pull/3999))
|
||||||
|
- [VDI] Ensure suspend VDI is destroyed when destroying a VM [#4027](https://github.com/vatesfr/xen-orchestra/issues/4027) (PR [#4038](https://github.com/vatesfr/xen-orchestra/pull/4038))
|
||||||
|
- [VM/disk]: Warning when 2 VDIs are on 2 different hosts' local SRs [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#3969](https://github.com/vatesfr/xen-orchestra/pull/3969))
|
||||||
|
- [Remotes] Benchmarks (read and write rate speed) added when remote is tested [#3991](https://github.com/vatesfr/xen-orchestra/issues/3991) (PR [#4015](https://github.com/vatesfr/xen-orchestra/pull/4015))
|
||||||
|
- [Cloud Config] Support both NoCloud and Config Drive 2 datasources for maximum compatibility (PR [#4053](https://github.com/vatesfr/xen-orchestra/pull/4053))
|
||||||
|
- [Advanced] Configurable cookie validity (PR [#4059](https://github.com/vatesfr/xen-orchestra/pull/4059))
|
||||||
|
- [Plugins] Display number of installed plugins [#4008](https://github.com/vatesfr/xen-orchestra/issues/4008) (PR [#4050](https://github.com/vatesfr/xen-orchestra/pull/4050))
|
||||||
|
- [Continuous Replication] Opt-in mode to guess VHD size, should help with XenServer 7.1 CU2 and various `VDI_IO_ERROR` errors (PR [#3726](https://github.com/vatesfr/xen-orchestra/pull/3726))
|
||||||
|
- [VM/Snapshots] Always delete broken quiesced snapshots [#4074](https://github.com/vatesfr/xen-orchestra/issues/4074) (PR [#4075](https://github.com/vatesfr/xen-orchestra/pull/4075))
|
||||||
|
- [Settings/Servers] Display link to pool [#4041](https://github.com/vatesfr/xen-orchestra/issues/4041) (PR [#4045](https://github.com/vatesfr/xen-orchestra/pull/4045))
|
||||||
|
- [Import] Change wording of drop zone (PR [#4020](https://github.com/vatesfr/xen-orchestra/pull/4020))
|
||||||
|
- [Backup NG] Ability to set the interval of the full backups [#1783](https://github.com/vatesfr/xen-orchestra/issues/1783) (PR [#4083](https://github.com/vatesfr/xen-orchestra/pull/4083))
|
||||||
|
- [Hosts] Display a warning icon if you have XenServer license restrictions [#4091](https://github.com/vatesfr/xen-orchestra/issues/4091) (PR [#4094](https://github.com/vatesfr/xen-orchestra/pull/4094))
|
||||||
|
- [Restore] Ability to restore a metadata backup [#4004](https://github.com/vatesfr/xen-orchestra/issues/4004) (PR [#4023](https://github.com/vatesfr/xen-orchestra/pull/4023))
|
||||||
|
- Improve connection to XCP-ng/XenServer hosts:
|
||||||
|
- never disconnect by itself even in case of errors
|
||||||
|
- never stop watching events
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- [New network] PIF was wrongly required which prevented from creating a private network (PR [#4010](https://github.com/vatesfr/xen-orchestra/pull/4010))
|
||||||
|
- [Google authentication] Migrate to new endpoint
|
||||||
|
- [Backup NG] Better handling of huge logs [#4025](https://github.com/vatesfr/xen-orchestra/issues/4025) (PR [#4026](https://github.com/vatesfr/xen-orchestra/pull/4026))
|
||||||
|
- [Home/VM] Bulk migration: fixed VM VDIs not migrated to the selected SR [#3986](https://github.com/vatesfr/xen-orchestra/issues/3986) (PR [#3987](https://github.com/vatesfr/xen-orchestra/pull/3987))
|
||||||
|
- [Stats] Fix cache usage with simultaneous requests [#4017](https://github.com/vatesfr/xen-orchestra/issues/4017) (PR [#4028](https://github.com/vatesfr/xen-orchestra/pull/4028))
|
||||||
|
- [Backup NG] Fix compression displayed for the wrong backup mode (PR [#4021](https://github.com/vatesfr/xen-orchestra/pull/4021))
|
||||||
|
- [Home] Always sort the items by their names as a secondary sort criteria [#3983](https://github.com/vatesfr/xen-orchestra/issues/3983) (PR [#4047](https://github.com/vatesfr/xen-orchestra/pull/4047))
|
||||||
|
- [Remotes] Fixes `spawn mount EMFILE` error during backup
|
||||||
|
- Properly redirect to sign in page instead of being stuck in a refresh loop
|
||||||
|
- [Backup-ng] No more false positives when list matching VMs on Home page [#4078](https://github.com/vatesfr/xen-orchestra/issues/4078) (PR [#4085](https://github.com/vatesfr/xen-orchestra/pull/4085))
|
||||||
|
- [Plugins] Properly remove optional settings when unchecking _Fill information_ (PR [#4076](https://github.com/vatesfr/xen-orchestra/pull/4076))
|
||||||
|
- [Patches] (PR [#4077](https://github.com/vatesfr/xen-orchestra/pull/4077))
|
||||||
|
- Add a host to a pool: fixes the auto-patching of the host on XenServer < 7.2 [#3783](https://github.com/vatesfr/xen-orchestra/issues/3783)
|
||||||
|
- Add a host to a pool: homogenizes both the host and **pool**'s patches [#2188](https://github.com/vatesfr/xen-orchestra/issues/2188)
|
||||||
|
- Safely install a subset of patches on a pool [#3777](https://github.com/vatesfr/xen-orchestra/issues/3777)
|
||||||
|
- XCP-ng: no longer requires to run `yum install xcp-ng-updater` when it's already installed [#3934](https://github.com/vatesfr/xen-orchestra/issues/3934)
|
||||||
|
|
||||||
|
### Released packages
|
||||||
|
|
||||||
|
- xen-api v0.25.0
|
||||||
|
- vhd-lib v0.6.0
|
||||||
|
- @xen-orchestra/fs v0.8.0
|
||||||
|
- xo-server-usage-report v0.7.2
|
||||||
|
- xo-server v5.38.1
|
||||||
|
- xo-web v5.38.0
|
||||||
|
|
||||||
## **5.32.2** (2019-02-28)
|
## **5.32.2** (2019-02-28)
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|||||||
@@ -1,28 +1,24 @@
|
|||||||
> This file contains all changes that have not been released yet.
|
> This file contains all changes that have not been released yet.
|
||||||
|
>
|
||||||
|
> Keep in mind the changelog is addressed to **users** and should be
|
||||||
|
> understandable by them.
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
|
|
||||||
- [SR/Disk] Disable actions on unmanaged VDIs [#3988](https://github.com/vatesfr/xen-orchestra/issues/3988) (PR [#4000](https://github.com/vatesfr/xen-orchestra/pull/4000))
|
> Users must be able to say: “Nice enhancement, I'm eager to test it”
|
||||||
- [Pool] Specify automatic networks on a Pool [#3916](https://github.com/vatesfr/xen-orchestra/issues/3916) (PR [#3958](https://github.com/vatesfr/xen-orchestra/pull/3958))
|
|
||||||
- [VM/advanced] Manage start delay for VM [#3909](https://github.com/vatesfr/xen-orchestra/issues/3909) (PR [#4002](https://github.com/vatesfr/xen-orchestra/pull/4002))
|
- [SDN Controller] Allow private network creation on bond and VLAN (PR [#4682](https://github.com/vatesfr/xen-orchestra/pull/4682))
|
||||||
- [New/Vm] SR section: Display warning message when the selected SRs aren't in the same host [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#3967](https://github.com/vatesfr/xen-orchestra/pull/3967))
|
|
||||||
- Enable compression for HTTP requests (and initial objects fetch)
|
|
||||||
- [VDI migration] Display same-pool SRs first in the selector [#3945](https://github.com/vatesfr/xen-orchestra/issues/3945) (PR [#3996](https://github.com/vatesfr/xen-orchestra/pull/3996))
|
|
||||||
- [Home] Save the current page in url [#3993](https://github.com/vatesfr/xen-orchestra/issues/3993) (PR [#3999](https://github.com/vatesfr/xen-orchestra/pull/3999))
|
|
||||||
- [VDI] Ensure suspend VDI is destroyed when destroying a VM [#4027](https://github.com/vatesfr/xen-orchestra/issues/4027) (PR [#4038](https://github.com/vatesfr/xen-orchestra/pull/4038))
|
|
||||||
- [VM/disk]: Warning when 2 VDIs are on 2 different hosts' local SRs [#3911](https://github.com/vatesfr/xen-orchestra/issues/3911) (PR [#3969](https://github.com/vatesfr/xen-orchestra/pull/3969))
|
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|
||||||
- [New network] PIF was wrongly required which prevented from creating a private network (PR [#4010](https://github.com/vatesfr/xen-orchestra/pull/4010))
|
> Users must be able to say: “I had this issue, happy to know it's fixed”
|
||||||
- [Google authentication] Migrate to new endpoint
|
|
||||||
- [Backup NG] Better handling of huge logs [#4025](https://github.com/vatesfr/xen-orchestra/issues/4025) (PR [#4026](https://github.com/vatesfr/xen-orchestra/pull/4026))
|
|
||||||
- [Home/VM] Bulk migration: fixed VM VDIs not migrated to the selected SR [#3986](https://github.com/vatesfr/xen-orchestra/issues/3986) (PR [#3987](https://github.com/vatesfr/xen-orchestra/pull/3987))
|
|
||||||
- [Stats] Fix cache usage with simultaneous requests [#4017](https://github.com/vatesfr/xen-orchestra/issues/4017) (PR [#4028](https://github.com/vatesfr/xen-orchestra/pull/4028))
|
|
||||||
- [Backup NG] Fix compression displayed for the wrong backup mode (PR [#4021](https://github.com/vatesfr/xen-orchestra/pull/4021))
|
|
||||||
|
|
||||||
### Released packages
|
### Released packages
|
||||||
|
|
||||||
- xo-server-auth-google v0.2.1
|
> Packages will be released in the order they are here, therefore, they should
|
||||||
- xo-server v5.37.0
|
> be listed by inverse order of dependency.
|
||||||
- xo-web v5.37.0
|
>
|
||||||
|
> Rule of thumb: add packages on top.
|
||||||
|
|
||||||
|
- xo-server v5.54.0
|
||||||
|
- xo-web v5.54.0
|
||||||
|
|||||||
@@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
|
|||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment include:
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
- Using welcoming and inclusive language
|
||||||
* Being respectful of differing viewpoints and experiences
|
- Being respectful of differing viewpoints and experiences
|
||||||
* Gracefully accepting constructive criticism
|
- Gracefully accepting constructive criticism
|
||||||
* Focusing on what is best for the community
|
- Focusing on what is best for the community
|
||||||
* Showing empathy towards other community members
|
- Showing empathy towards other community members
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
## Our Responsibilities
|
## Our Responsibilities
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ the issues :)
|
|||||||
|
|
||||||
- **XO origin**: the sources / XO Appliance
|
- **XO origin**: the sources / XO Appliance
|
||||||
- **Versions**:
|
- **Versions**:
|
||||||
- Node: **FILL HERE**
|
- Node: **FILL HERE**
|
||||||
- xo-web: **FILL HERE**
|
- xo-web: **FILL HERE**
|
||||||
- xo-server: **FILL HERE**
|
- xo-server: **FILL HERE**
|
||||||
|
|
||||||
### Expected behavior
|
### Expected behavior
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,28 @@
|
|||||||
### Check list
|
### Check list
|
||||||
|
|
||||||
> Check items when done or if not relevant
|
> Check if done, if not relevant leave unchecked.
|
||||||
|
|
||||||
- [ ] PR reference the relevant issue (e.g. `Fixes #007`)
|
- [ ] PR reference the relevant issue (e.g. `Fixes #007` or `See xoa-support#42`)
|
||||||
- [ ] if UI changes, a screenshot has been added to the PR
|
- [ ] if UI changes, a screenshot has been added to the PR
|
||||||
- [ ] `CHANGELOG.unreleased.md`:
|
|
||||||
- enhancement/bug fix entry added
|
|
||||||
- list of packages to release updated (`${name} v${new version}`)
|
|
||||||
- [ ] documentation updated
|
- [ ] documentation updated
|
||||||
- [ ] **I have tested added/updated features** (and impacted code)
|
- `CHANGELOG.unreleased.md`:
|
||||||
|
- [ ] enhancement/bug fix entry added
|
||||||
|
- [ ] list of packages to release updated (`${name} v${new version}`)
|
||||||
|
- **I have tested added/updated features** (and impacted code)
|
||||||
|
- [ ] unit tests (e.g. [`cron/parse.spec.js`](https://github.com/vatesfr/xen-orchestra/blob/b24400b21de1ebafa1099c56bac1de5c988d9202/%40xen-orchestra/cron/src/parse.spec.js))
|
||||||
|
- [ ] if `xo-server` API changes, the corresponding test has been added to/updated on [`xo-server-test`](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-test)
|
||||||
|
- [ ] at least manual testing
|
||||||
|
|
||||||
### Process
|
### Process
|
||||||
|
|
||||||
1. create a PR as soon as possible
|
1. create a PR as soon as possible
|
||||||
1. mark it as `WiP:` (Work in Progress) if not ready to be merged
|
1. mark it as `WiP:` (Work in Progress) if not ready to be merged
|
||||||
1. when you want a review, add a reviewer
|
1. when you want a review, add a reviewer (and only one)
|
||||||
1. if necessary, update your PR, and re- add a reviewer
|
1. if necessary, update your PR, and re- add a reviewer
|
||||||
|
|
||||||
|
From [_the Four Agreements_](https://en.wikipedia.org/wiki/Don_Miguel_Ruiz#The_Four_Agreements):
|
||||||
|
|
||||||
|
1. Be impeccable with your word.
|
||||||
|
1. Don't take anything personally.
|
||||||
|
1. Don't make assumptions.
|
||||||
|
1. Always do your best.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Xen Orchestra [](https://go.crisp.im/chat/embed/?website_id=-JzqzzwddSV7bKGtEyAQ) [](https://travis-ci.org/vatesfr/xen-orchestra)
|
# Xen Orchestra [](https://travis-ci.org/vatesfr/xen-orchestra)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Xen Orchestra
|
# Xen Orchestra
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
@@ -13,19 +12,19 @@ It aims to be easy to use on any device supporting modern web technologies (HTML
|
|||||||
|
|
||||||
## XOA quick deploy
|
## XOA quick deploy
|
||||||
|
|
||||||
SSH to your XenServer, and execute the following:
|
Log in to your account and use the deploy form available on [this page](https://xen-orchestra.com/#!/xoa)
|
||||||
|
|
||||||
```
|
> **Note:** no data will be sent to our servers, it's running only between your browser and your host!
|
||||||
bash -c "$(curl -s http://xoa.io/deploy)"
|
|
||||||
```
|
[](https://xen-orchestra.com/#!/xoa)
|
||||||
|
|
||||||
### XOA credentials
|
### XOA credentials
|
||||||
|
|
||||||
* Web UI: `admin@admin.net` / `admin`
|
- Web UI: `admin@admin.net` / `admin`
|
||||||
* Console/SSH: `xoa` / `xoa` (first login)
|
- Console/SSH: `xoa` / `xoa` (first login)
|
||||||
|
|
||||||
## Must read
|
## Must read
|
||||||
|
|
||||||
* [XOA installation](xoa.md)
|
- [XOA installation](xoa.md)
|
||||||
* [Main features](features.md)
|
- [Main features](features.md)
|
||||||
* [Pro Support](support.md)
|
- [Pro Support](support.md)
|
||||||
|
|||||||
156
docs/SUMMARY.md
@@ -1,79 +1,81 @@
|
|||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
* [Introduction](README.md)
|
- [Introduction](README.md)
|
||||||
* [Architecture](architecture.md)
|
- [Architecture](architecture.md)
|
||||||
* [xo-server](xo-server.md)
|
- [xo-server](xo-server.md)
|
||||||
* [xo-web](xo-web.md)
|
- [xo-web](xo-web.md)
|
||||||
* [xo-cli](xo-cli.md)
|
- [xo-cli](xo-cli.md)
|
||||||
* [others](others.md)
|
- [others](others.md)
|
||||||
* [Installation](installation.md)
|
- [Installation](installation.md)
|
||||||
* [XOA](xoa.md)
|
- [XOA](xoa.md)
|
||||||
* [Updater](updater.md)
|
- [Updater](updater.md)
|
||||||
* [Trial activation](trial_activation.md)
|
- [Trial activation](trial_activation.md)
|
||||||
* [Plugins](plugins.md)
|
- [Plugins](plugins.md)
|
||||||
* [Logs](logs.md)
|
- [Logs](logs.md)
|
||||||
* [Compatibility](supported-version.md)
|
- [Compatibility](supported-version.md)
|
||||||
* [Troubleshooting](troubleshooting.md)
|
- [Troubleshooting](troubleshooting.md)
|
||||||
* [From the sources](from_the_sources.md)
|
- [From the sources](from_the_sources.md)
|
||||||
* [Configuration](configuration.md)
|
- [Configuration](configuration.md)
|
||||||
* [Features](features.md)
|
- [Features](features.md)
|
||||||
* [Administration](administration.md)
|
- [Administration](administration.md)
|
||||||
* [Home view](user_interface.md)
|
- [Home view](user_interface.md)
|
||||||
* [Search and filters](search.md)
|
- [Search and filters](search.md)
|
||||||
* [VM management](vm_management.md)
|
- [VM management](vm_management.md)
|
||||||
* [VM creation](vm_creation.md)
|
- [VM creation](vm_creation.md)
|
||||||
* [VM import and export](vm_import_export.md)
|
- [VM import and export](vm_import_export.md)
|
||||||
* [XenServer Patching](patching.md)
|
- [XenServer Patching](patching.md)
|
||||||
* [Docker support](docker_support.md)
|
- [Docker support](docker_support.md)
|
||||||
* [Backup and DR](backups.md)
|
- [Backup and DR](backups.md)
|
||||||
* [Full backups](full_backups.md)
|
- [Full backups](full_backups.md)
|
||||||
* [Rolling snapshots](rolling_snapshots.md)
|
- [Rolling snapshots](rolling_snapshots.md)
|
||||||
* [Continuous Delta backups](delta_backups.md)
|
- [Continuous Delta backups](delta_backups.md)
|
||||||
* [Continuous Replication](continuous_replication.md)
|
- [Continuous Replication](continuous_replication.md)
|
||||||
* [Disaster recovery](disaster_recovery.md)
|
- [Disaster recovery](disaster_recovery.md)
|
||||||
* [Smart Backup](smart_backup.md)
|
- [Smart Backup](smart_backup.md)
|
||||||
* [File level Restore](file_level_restore.md)
|
- [File level Restore](file_level_restore.md)
|
||||||
* [Metadata Backup](metadata_backup.md)
|
- [Metadata Backup](metadata_backup.md)
|
||||||
* [Backup Concurrency](concurrency.md)
|
- [Backup Concurrency](concurrency.md)
|
||||||
* [Configure backup reports](backup_reports.md)
|
- [Configure backup reports](backup_reports.md)
|
||||||
* [Backup troubleshooting](backup_troubleshooting.md)
|
- [Backup troubleshooting](backup_troubleshooting.md)
|
||||||
* [User authentication](authentication.md)
|
- [User authentication](authentication.md)
|
||||||
* [Built-in](built-in.md)
|
- [Built-in](built-in.md)
|
||||||
* [LDAP](ldap.md)
|
- [LDAP](ldap.md)
|
||||||
* [SAML](saml.md)
|
- [SAML](saml.md)
|
||||||
* [GitHub](github.md)
|
- [GitHub](github.md)
|
||||||
* [Google](google.md)
|
- [Google](google.md)
|
||||||
* [Resources delegation](resources_delegation.md)
|
- [Resources delegation](resources_delegation.md)
|
||||||
* [ACLs](acls.md)
|
- [ACLs](acls.md)
|
||||||
* [CloudInit](cloudinit.md)
|
- [CloudInit](cloudinit.md)
|
||||||
* [Self Service](self_service.md)
|
- [Self Service](self_service.md)
|
||||||
* [Visualizations](visualizations.md)
|
- [Visualizations](visualizations.md)
|
||||||
* [Health](health.md)
|
- [Health](health.md)
|
||||||
* [Job manager](scheduler.md)
|
- [Job manager](scheduler.md)
|
||||||
* [Alerts](alerts.md)
|
- [Alerts](alerts.md)
|
||||||
* [Load balancing](load_balancing.md)
|
- [Web hooks](web-hooks.md)
|
||||||
* [Emergency Shutdown](emergency_shutdown.md)
|
- [Load balancing](load_balancing.md)
|
||||||
* [Auto scalability](auto_scalability.md)
|
- [Emergency Shutdown](emergency_shutdown.md)
|
||||||
* [Forecaster](forecaster.md)
|
- [Auto scalability](auto_scalability.md)
|
||||||
* [Recipes](recipes.md)
|
- [Forecaster](forecaster.md)
|
||||||
* [Reverse proxy](reverse_proxy.md)
|
- [SDN Controller](sdn_controller.md)
|
||||||
* [How to contribute?](contributing.md)
|
- [Recipes](recipes.md)
|
||||||
* [Support](support.md)
|
- [Reverse proxy](reverse_proxy.md)
|
||||||
* [Roadmap](roadmap.md)
|
- [How to contribute?](contributing.md)
|
||||||
* [Purchase](purchase.md)
|
- [Support](support.md)
|
||||||
* [Direct purchase](directpurchase.md)
|
- [Roadmap](roadmap.md)
|
||||||
* [Through purchase department](through_purchase_department.md)
|
- [Purchase](purchase.md)
|
||||||
* [Reseller](reseller.md)
|
- [Direct purchase](directpurchase.md)
|
||||||
* [Editions](editions.md)
|
- [Through purchase department](through_purchase_department.md)
|
||||||
* [Trial](trial.md)
|
- [Reseller](reseller.md)
|
||||||
* [Invoices](invoices.md)
|
- [Editions](editions.md)
|
||||||
* [Upgrade](upgrade.md)
|
- [Trial](trial.md)
|
||||||
* [XOSAN](xosan.md)
|
- [Invoices](invoices.md)
|
||||||
* [Requirements](xosan_requirements.md)
|
- [Upgrade](upgrade.md)
|
||||||
* [Types](xosan_types.md)
|
- [XOSAN](xosan.md)
|
||||||
* [Replicated](xosan_replicated.md)
|
- [Requirements](xosan_requirements.md)
|
||||||
* [Disperse](xosan_disperse.md)
|
- [Types](xosan_types.md)
|
||||||
* [Creation](xosan_create.md)
|
- [Replicated](xosan_replicated.md)
|
||||||
* [Trial](xosan_trial.md)
|
- [Disperse](xosan_disperse.md)
|
||||||
* [General Troubleshooting](general-troubleshooting.md)
|
- [Creation](xosan_create.md)
|
||||||
* [Glossary](glossary.md)
|
- [Trial](xosan_trial.md)
|
||||||
|
- [General Troubleshooting](general-troubleshooting.md)
|
||||||
|
- [Glossary](glossary.md)
|
||||||
|
|||||||
38
docs/acls.md
@@ -23,32 +23,32 @@ You can edit/remove existing ACLs here.
|
|||||||
|
|
||||||
There are 3 different roles for your users:
|
There are 3 different roles for your users:
|
||||||
|
|
||||||
* Admin
|
- Admin
|
||||||
* Operator
|
- Operator
|
||||||
* Viewer
|
- Viewer
|
||||||
|
|
||||||
### Admin
|
### Admin
|
||||||
|
|
||||||
An object admin can do everything on it, even destroy it. E.g with its admin VM:
|
An object admin can do everything on it, even destroy it. E.g with its admin VM:
|
||||||
|
|
||||||
* remove it
|
- remove it
|
||||||
* migrate it (to a host with admin permission on it)
|
- migrate it (to a host with admin permission on it)
|
||||||
* modify the VM resources, name and description
|
- modify the VM resources, name and description
|
||||||
* clone it
|
- clone it
|
||||||
* copy it
|
- copy it
|
||||||
* convert it into a template
|
- convert it into a template
|
||||||
* snapshot it (even revert from a snapshot)
|
- snapshot it (even revert from a snapshot)
|
||||||
* export it
|
- export it
|
||||||
* attach/add visible disks
|
- attach/add visible disks
|
||||||
* same for network cards
|
- same for network cards
|
||||||
|
|
||||||
### Operator
|
### Operator
|
||||||
|
|
||||||
An operator can make everyday operations on assigned objects. E.g on a VM:
|
An operator can make everyday operations on assigned objects. E.g on a VM:
|
||||||
|
|
||||||
* eject a CD
|
- eject a CD
|
||||||
* insert a CD (if he can view the ISO storage repository)
|
- insert a CD (if he can view the ISO storage repository)
|
||||||
* start, restart, shutdown, suspend/resume it
|
- start, restart, shutdown, suspend/resume it
|
||||||
|
|
||||||
All other operations are forbidden.
|
All other operations are forbidden.
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ A viewer can only see the VM state and its metrics. That's all!
|
|||||||
|
|
||||||
Objects have a hierarchy: a Pool contains all its hosts, containing itself all its VMs.
|
Objects have a hierarchy: a Pool contains all its hosts, containing itself all its VMs.
|
||||||
|
|
||||||
If you give a *view* permission to a user (or a group) on a pool, he will automatically see all the objects inside this pool (SRs, hosts, VMs).
|
If you give a _view_ permission to a user (or a group) on a pool, he will automatically see all the objects inside this pool (SRs, hosts, VMs).
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@@ -68,5 +68,5 @@ If you give a *view* permission to a user (or a group) on a pool, he will automa
|
|||||||
|
|
||||||
If the OS install needs an ISO, you need to give this user 2 permissions:
|
If the OS install needs an ISO, you need to give this user 2 permissions:
|
||||||
|
|
||||||
* *Operate* on the VM (e.g to start it)
|
- _Operate_ on the VM (e.g to start it)
|
||||||
* *View* on the ISO Storage containing the needed ISO.
|
- _View_ on the ISO Storage containing the needed ISO.
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
This section contains everyday XenServer administration tasks.
|
This section contains everyday XenServer administration tasks.
|
||||||
|
|
||||||
* [Home view](user_interface.md)
|
- [Home view](user_interface.md)
|
||||||
* [Search and filters](search.md)
|
- [Search and filters](search.md)
|
||||||
* [VM management](vm_management.md)
|
- [VM management](vm_management.md)
|
||||||
* [VM creation](vm_creation.md)
|
- [VM creation](vm_creation.md)
|
||||||
* [VM import and export](vm_import_export.md)
|
- [VM import and export](vm_import_export.md)
|
||||||
* [XenServer Patching](patching.md)
|
- [XenServer Patching](patching.md)
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -8,12 +8,12 @@ The administrator will configure alerts based on performance thresholds.
|
|||||||
|
|
||||||
The configurable metrics are:
|
The configurable metrics are:
|
||||||
|
|
||||||
* CPU usage (VM, host)
|
- CPU usage (VM, host)
|
||||||
* RAM usage (VM, host)
|
- RAM usage (VM, host)
|
||||||
* network bandwidth (VM, host)
|
- network bandwidth (VM, host)
|
||||||
* load average (host)
|
- load average (host)
|
||||||
* disk IO (VM)
|
- disk IO (VM)
|
||||||
* total IO (SR, only for XenServer Dundee and higher)
|
- total IO (SR, only for XenServer Dundee and higher)
|
||||||
|
|
||||||
If any configured values exceed the threshold during a selected period of time, an alert will be sent.
|
If any configured values exceed the threshold during a selected period of time, an alert will be sent.
|
||||||
|
|
||||||
@@ -31,5 +31,5 @@ You can choose to be notified only if it fails or even after each backup job.
|
|||||||
|
|
||||||
Current supported alerts system:
|
Current supported alerts system:
|
||||||
|
|
||||||
* Email
|
- Email
|
||||||
* XMPP
|
- XMPP
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
Xen Orchestra (XO) is software built with a server and clients, such as the web client `xo-web`, but also a CLI capable client, called `xo-cli`.
|
Xen Orchestra (XO) is software built with a server and clients, such as the web client `xo-web`, but also a CLI capable client, called `xo-cli`.
|
||||||
@@ -7,7 +6,7 @@ Xen Orchestra (XO) is software built with a server and clients, such as the web
|
|||||||
|
|
||||||
## XOA
|
## XOA
|
||||||
|
|
||||||
*Xen Orchestra Virtual Appliance* (XOA) is a virtual machine with Xen Orchestra already installed, thus working out-of-the-box.
|
_Xen Orchestra Virtual Appliance_ (XOA) is a virtual machine with Xen Orchestra already installed, thus working out-of-the-box.
|
||||||
|
|
||||||
This is the easiest way to try Xen Orchestra quickly.
|
This is the easiest way to try Xen Orchestra quickly.
|
||||||
|
|
||||||
@@ -20,9 +19,9 @@ Your XOA is connected to all your hosts, or the pool master only if you are usin
|
|||||||

|

|
||||||
|
|
||||||
Xen Orchestra itself is built as a modular solution. Each part has its role:
|
Xen Orchestra itself is built as a modular solution. Each part has its role:
|
||||||
|
|
||||||
- The core is "[xo-server](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server/)" - a daemon dealing directly with XenServer or XAPI capable hosts. This is where users are stored, and it's the center point for talking to your whole Xen infrastructure.
|
- The core is "[xo-server](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server/)" - a daemon dealing directly with XenServer or XAPI capable hosts. This is where users are stored, and it's the center point for talking to your whole Xen infrastructure.
|
||||||
- The web interface is "[xo-web](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-web)" - it runs directly from your browser. The connection with ```xo-server``` is done via *WebSockets*.
|
- The web interface is "[xo-web](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-web)" - it runs directly from your browser. The connection with `xo-server` is done via _WebSockets_.
|
||||||
- "[xo-cli](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-cli)" is a module allowing you to send commands directly from the command line.
|
- "[xo-cli](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-cli)" is a module allowing you to send commands directly from the command line.
|
||||||
|
|
||||||
|
|
||||||
We have other modules as well (like the LDAP plugin for example). It allows us to use this modular architecture to add further parts as we need them. It's completely flexible, allowing us to adapt Xen Orchestra to every existing workflow.
|
We have other modules as well (like the LDAP plugin for example). It allows us to use this modular architecture to add further parts as we need them. It's completely flexible, allowing us to adapt Xen Orchestra to every existing workflow.
|
||||||
|
|||||||
BIN
docs/assets/cr-seed-1.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/assets/cr-seed-2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/assets/cr-seed-3.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/assets/cr-seed-4.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
docs/assets/deploy_form.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
docs/assets/metadata-1.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
docs/assets/metadata-2.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/assets/metadata-3.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/assets/metadata-4.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
docs/assets/metadata-5.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/assets/metadata-6.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
docs/assets/metadata-7.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/assets/release-channels.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
docs/assets/sdn-controller.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
@@ -1,16 +1,14 @@
|
|||||||
# User authentication
|
# User authentication
|
||||||
|
|
||||||
|
|
||||||
Xen Orchestra supports various types of user authentication, internal or even external thanks to the usage of the [Passport library](http://passportjs.org/).
|
Xen Orchestra supports various types of user authentication, internal or even external thanks to the usage of the [Passport library](http://passportjs.org/).
|
||||||
|
|
||||||
There are 2 types of XO users:
|
There are 2 types of XO users:
|
||||||
|
|
||||||
* admins, with all rights on all connected resources
|
- admins, with all rights on all connected resources
|
||||||
* users, with no rights by default
|
- users, with no rights by default
|
||||||
|
|
||||||
All users will land on the "flat" view, which displays no hierarchy, only all their visible objects (or no object if they are not configured).
|
All users will land on the "flat" view, which displays no hierarchy, only all their visible objects (or no object if they are not configured).
|
||||||
|
|
||||||
|
|
||||||
ACLs will thus apply only to "users".
|
ACLs will thus apply only to "users".
|
||||||
|
|
||||||
> Any account created by an external authentication process (LDAP, SSO...) will be a **user** without any permission.
|
> Any account created by an external authentication process (LDAP, SSO...) will be a **user** without any permission.
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ At the end of a backup job, you can configure Xen Orchestra to send backup repor
|
|||||||
|
|
||||||
### Step-by-step
|
### Step-by-step
|
||||||
|
|
||||||
1. On the "settings/plugins" view you have to activate and configure the "Backup-reports" plugin.
|
1. On the "settings/plugins" view you have to activate and configure the "Backup-reports" plugin.
|
||||||

|

|
||||||
|
|
||||||
2. Still in the plugins view, you also have to configure the "transport-email" plugin.
|
2. Still in the plugins view, you also have to configure the "transport-email" plugin.
|
||||||

|

|
||||||
|
|
||||||
3. Once it's done, you can now create your backup job. In the "report" selection you can choose the situation in wish you want to receive an email (always, never or failure).
|
3. Once it's done, you can now create your backup job. In the "report" selection you can choose the situation in wish you want to receive an email (always, never or failure).
|
||||||

|

|
||||||
> Note: You can also modify existing backup jobs and change the behaviour of the report system.
|
> Note: You can also modify existing backup jobs and change the behaviour of the report system.
|
||||||
|
|
||||||
## XMPP nofications
|
## XMPP nofications
|
||||||
|
|
||||||
@@ -67,9 +67,9 @@ Like all other xo-server plugins, it can be configured directly via the web inte
|
|||||||
|
|
||||||
You need to be an admin:
|
You need to be an admin:
|
||||||
|
|
||||||
* Go into the MatterMost menu, then Integration
|
- Go into the MatterMost menu, then Integration
|
||||||
* Click on "Add Incoming webhook"
|
- Click on "Add Incoming webhook"
|
||||||
* "Add Incoming Webhook"
|
- "Add Incoming Webhook"
|
||||||
|
|
||||||
### Testing the plugin
|
### Testing the plugin
|
||||||
|
|
||||||
|
|||||||
@@ -12,33 +12,37 @@ Another good way to check if there is activity is the XOA VM stats view (on the
|
|||||||
|
|
||||||
### VDI chain protection
|
### VDI chain protection
|
||||||
|
|
||||||
This means your previous VM disks and snapshots should be "merged" (*coalesced* in the XenServer world) before we can take a new snapshot. This mechanism is handled by XenServer itself, not Xen Orchestra. But we can check your existing VDI chain and avoid creating more snapshots than your storage can merge. Otherwise, this will lead to catastrophic consequences. Xen Orchestra is the **only** XenServer/XCP backup product dealing with this.
|
Backup jobs regularly delete snapshots. When a snapshot is deleted, either manually or via a backup job, it triggers the need for Xenserver to coalesce the VDI chain - to merge the remaining VDIs and base copies in the chain. This means generally we cannot take too many new snapshots on said VM until Xenserver has finished running a coalesce job on the VDI chain.
|
||||||
|
|
||||||
|
This mechanism and scheduling is handled by XenServer itself, not Xen Orchestra. But we can check your existing VDI chain and avoid creating more snapshots than your storage can merge. If we don't, this will lead to catastrophic consequences. Xen Orchestra is the **only** XenServer/XCP backup product that takes this into account and offers protection.
|
||||||
|
|
||||||
Without this detection, you could have 2 potential issues:
|
Without this detection, you could have 2 potential issues:
|
||||||
|
|
||||||
* `The Snapshot Chain is too Long`
|
- `The Snapshot Chain is too Long`
|
||||||
* `SR_BACKEND_FAILURE_44 (insufficient space)`
|
- `SR_BACKEND_FAILURE_44 (insufficient space)`
|
||||||
|
|
||||||
The first issue is a chain that contains more than 30 elements (fixed XenServer limit), and the other one means it's full because the "coalesce" process couldn't keep up the pace and the storage filled up.
|
The first issue is a chain that contains more than 30 elements (fixed XenServer limit), and the other one means it's full because the "coalesce" process couldn't keep up the pace and the storage filled up.
|
||||||
|
|
||||||
In the end, this message is a **protection mechanism against damaging your SR**. The backup job will fail, but XenServer itself should eventually automatically coalesce the snapshot chain, and the the next time the backup job should complete.
|
In the end, this message is a **protection mechanism preventing damage to your SR**. The backup job will fail, but XenServer itself should eventually automatically coalesce the snapshot chain, and the the next time the backup job should complete.
|
||||||
|
|
||||||
Just remember this: **coalesce will happen every time a snapshot is removed**.
|
Just remember this: **a coalesce should happen every time a snapshot is removed**.
|
||||||
|
|
||||||
> You can read more on this on our dedicated blog post regarding [XenServer coalesce detection](https://xen-orchestra.com/blog/xenserver-coalesce-detection-in-xen-orchestra/).
|
> You can read more on this on our dedicated blog post regarding [XenServer coalesce detection](https://xen-orchestra.com/blog/xenserver-coalesce-detection-in-xen-orchestra/).
|
||||||
|
|
||||||
### Troubleshooting a constant VDI Chain Protection message (XenServer failure to coalesce)
|
### Troubleshooting a constant VDI Chain Protection message (XenServer failure to coalesce)
|
||||||
|
|
||||||
As previously mentioned, this message can be normal and it just means XenServer needs to perform a coalesce to merge old snapshots. However if you repeatedly get this message and it seems XenServer is not coalescing, You can take a few steps to determine why.
|
As previously mentioned, this message can be normal and it just means XenServer needs to perform a coalesce to merge old snapshots. However if you repeatedly get this message and it seems XenServer is not coalescing, You can take a few steps to determine why.
|
||||||
|
|
||||||
First check SMlog on the XenServer host for messages relating to VDI corruption or coalesce job failure. For example, by running `cat /var/log/SMlog | grep -i exception` or `cat /var/log/SMlog | grep -i error` on the XenServer host with the affected storage.
|
First check SMlog on the XenServer host for messages relating to VDI corruption or coalesce job failure. For example, by running `cat /var/log/SMlog | grep -i exception` or `cat /var/log/SMlog | grep -i error` on the XenServer host with the affected storage.
|
||||||
|
|
||||||
Coalesce jobs can also fail to run if the SR does not have enough free space. Check the problematic SR and make sure it has enough free space, generally 30% or more free is recommended depending on VM size. You can check if this is the issue by searching `SMlog` with `grep -i coales /var/log/SMlog` (you may have to look at previous logs such as `SMlog.1`).
|
Coalesce jobs can also fail to run if the SR does not have enough free space. Check the problematic SR and make sure it has enough free space, generally 30% or more free is recommended depending on VM size. You can check if this is the issue by searching `SMlog` with `grep -i coales /var/log/SMlog` (you may have to look at previous logs such as `SMlog.1`).
|
||||||
|
|
||||||
You can check if a coalesce job is currently active by running `ps axf | grep vhd` on the XenServer host and looking for a VHD process in the results (one of the resulting processes will be the grep command you just ran, ignore that one).
|
You can check if a coalesce job is currently active by running `ps axf | grep vhd` on the XenServer host and looking for a VHD process in the results (one of the resulting processes will be the grep command you just ran, ignore that one).
|
||||||
|
|
||||||
If you don't see any running coalesce jobs, and can't find any other reason that XenServer has not started one, you can attempt to make it start a coalesce job by rescanning the SR. This is harmless to try, but will not always result in a coalesce. Visit the problematic SR in the XOA UI, then click the "Rescan All Disks" button towards the top right: it looks like a refresh circle icon. This should begin the coalesce process - if you click the Advanced tab in the SR view, the "disks needing to be coalesced" list should become smaller and smaller.
|
If you don't see any running coalesce jobs, and can't find any other reason that XenServer has not started one, you can attempt to make it start a coalesce job by rescanning the SR. This is harmless to try, but will not always result in a coalesce. Visit the problematic SR in the XOA UI, then click the "Rescan All Disks" button towards the top right: it looks like a refresh circle icon. This should begin the coalesce process - if you click the Advanced tab in the SR view, the "disks needing to be coalesced" list should become smaller and smaller.
|
||||||
|
|
||||||
|
As a last resort, migrating the VM (more specifically, its disks) to a new storage repository will also force a coalesce and solve this issue. That means migrating a VM to another host (with its own storage) and back will force the VDI chain for that VM to be coalesced, and get rid of the `VDI Chain Protection` message.
|
||||||
|
|
||||||
### Parse Error
|
### Parse Error
|
||||||
|
|
||||||
This is most likely due to running a backup job that uses Delta functionality (eg: delta backups, or continuous replication) on a version of XenServer older than 6.5. To use delta functionality you must run [XenServer 6.5 or later](https://xen-orchestra.com/docs/supported-version.html).
|
This is most likely due to running a backup job that uses Delta functionality (eg: delta backups, or continuous replication) on a version of XenServer older than 6.5. To use delta functionality you must run [XenServer 6.5 or later](https://xen-orchestra.com/docs/supported-version.html).
|
||||||
@@ -51,10 +55,10 @@ The Storage Repository (where your VM disks are currently stored) is full. Note
|
|||||||
|
|
||||||
Workarounds:
|
Workarounds:
|
||||||
|
|
||||||
* use a thin provisioned SR (local ext, NFS, XOSAN)
|
- use a thin provisioned SR (local ext, NFS, XOSAN)
|
||||||
* wait for Citrix to release thin provisioning on LVM
|
- wait for Citrix to release thin provisioning on LVM
|
||||||
* wait for Citrix to allow another mechanism besides snapshot to be able to export disks
|
- wait for Citrix to allow another mechanism besides snapshot to be able to export disks
|
||||||
* use less than 50% of SR space or don't backup all VMs
|
- use less than 50% of SR space or don't backup all VMs
|
||||||
|
|
||||||
### Could not find the base VM
|
### Could not find the base VM
|
||||||
|
|
||||||
@@ -68,12 +72,12 @@ To solve it, you have to change a parameter in your VM. `xe vm-param-set has-ven
|
|||||||
|
|
||||||
### ENOSPC: no space left on device
|
### ENOSPC: no space left on device
|
||||||
|
|
||||||
This message appears when you do not have enough free space on the target remote when running a backup to it.
|
This message appears when you do not have enough free space on the target remote when running a backup to it.
|
||||||
|
|
||||||
To check your free space, enter your XOA and run `xoa check` to check free system space and `df -h` to check free space on your chosen remote storage.
|
To check your free space, enter your XOA and run `xoa check` to check free system space and `df -h` to check free space on your chosen remote storage.
|
||||||
|
|
||||||
### Error: no VMs match this pattern
|
### Error: no VMs match this pattern
|
||||||
|
|
||||||
This is happening when you have a *smart backup job* that doesn't match any VMs. For example: you created a job to backup all running VMs. If no VMs are running on backup schedule, you'll have this message. This could also happen if you lost connection with your pool master (the VMs aren't visible anymore from Xen Orchestra).
|
This is happening when you have a _smart backup job_ that doesn't match any VMs. For example: you created a job to backup all running VMs. If no VMs are running on backup schedule, you'll have this message. This could also happen if you lost connection with your pool master (the VMs aren't visible anymore from Xen Orchestra).
|
||||||
|
|
||||||
Edit your job and try to see matching VMs or check if your pool is connected to XOA.
|
Edit your job and try to see matching VMs or check if your pool is connected to XOA.
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ This section is dedicated to all existing methods of rolling back or backing up
|
|||||||
|
|
||||||
There are several ways to protect your VMs:
|
There are several ways to protect your VMs:
|
||||||
|
|
||||||
* [Full Backups](full_backups.md) [*Starter Edition*]
|
- [Full Backups](full_backups.md) [*Starter Edition*]
|
||||||
* [Rolling Snapshots](rolling_snapshots.md) [*Starter Edition*]
|
- [Rolling Snapshots](rolling_snapshots.md) [*Starter Edition*]
|
||||||
* [Delta Backups](delta_backups.md) (best of both previous ones) [*Enterprise Edition*]
|
- [Delta Backups](delta_backups.md) (best of both previous ones) [*Enterprise Edition*]
|
||||||
* [Disaster Recovery](disaster_recovery.md) [*Enterprise Edition*]
|
- [Disaster Recovery](disaster_recovery.md) [*Enterprise Edition*]
|
||||||
* [Metadata Backups](metadata_backup.md) [*Enterprise Edition*]
|
- [Metadata Backups](metadata_backup.md) [*Enterprise Edition*]
|
||||||
* [Continuous Replication](continuous_replication.md) [*Premium Edition*]
|
- [Continuous Replication](continuous_replication.md) [*Premium Edition*]
|
||||||
* [File Level Restore](file_level_restore.md) [*Premium Edition*]
|
- [File Level Restore](file_level_restore.md) [*Premium Edition*]
|
||||||
|
|
||||||
> Don't forget to take a look at the [backup troubleshooting](backup_troubleshooting.md) section. You can also take a look at the [backup reports](backup_reports.md) section for configuring notifications.
|
> Don't forget to take a look at the [backup troubleshooting](backup_troubleshooting.md) section. You can also take a look at the [backup reports](backup_reports.md) section for configuring notifications.
|
||||||
|
|
||||||
@@ -54,16 +54,15 @@ The tooltip confirms this:
|
|||||||
|
|
||||||
## Remotes
|
## Remotes
|
||||||
|
|
||||||
> Remotes are places where your *backup* and *delta backup* files will be stored.
|
> Remotes are places where your _backup_ and _delta backup_ files will be stored.
|
||||||
|
|
||||||
To add a *remote*, go to the **Settings/Remotes** menu.
|
To add a _remote_, go to the **Settings/Remotes** menu.
|
||||||
|
|
||||||
Supported remote types:
|
Supported remote types:
|
||||||
|
|
||||||
* Local (any folder in XOA filesystem)
|
- Local (any folder in XOA filesystem)
|
||||||
* NFS
|
- NFS
|
||||||
* SMB (CIFS)
|
- SMB (CIFS)
|
||||||
|
|
||||||
|
|
||||||
> **WARNING**: the initial "/" or "\\" is automatically added.
|
> **WARNING**: the initial "/" or "\\" is automatically added.
|
||||||
|
|
||||||
@@ -73,15 +72,15 @@ On your NFS server, authorize XOA's IP address and permissions for subfolders. T
|
|||||||
|
|
||||||
### SMB
|
### SMB
|
||||||
|
|
||||||
We support SMB storage on *Windows Server 2012 R2*.
|
We support SMB storage on _Windows Server 2012 R2_.
|
||||||
|
|
||||||
> WARNING: For continuous delta backup, SMB is **NOT** recommended (or only for small VMs, eg < 50GB)
|
> WARNING: For continuous delta backup, SMB is **NOT** recommended (or only for small VMs, eg < 50GB)
|
||||||
|
|
||||||
Also, read the UI twice when you add an SMB store. If you have:
|
Also, read the UI twice when you add an SMB store. If you have:
|
||||||
|
|
||||||
* `192.168.1.99` as SMB host
|
- `192.168.1.99` as SMB host
|
||||||
* `Backups` as folder
|
- `Backups` as folder
|
||||||
* no subfolder
|
- no subfolder
|
||||||
|
|
||||||
You'll have to fill it like this:
|
You'll have to fill it like this:
|
||||||
|
|
||||||
@@ -112,13 +111,13 @@ All your scheduled backups are acccessible in the "Restore" view in the backup s
|
|||||||
|
|
||||||
## About backup compression
|
## About backup compression
|
||||||
|
|
||||||
By default, *Backups* are compressed (using GZIP, done on XenServer side). There is no absolute rule but in general uncompressed backups are faster (but sometimes much larger).
|
By default, _Backups_ are compressed (using GZIP, done on XenServer side). There is no absolute rule but in general uncompressed backups are faster (but sometimes much larger).
|
||||||
|
|
||||||
XenServer uses Gzip compression, which is:
|
XenServer uses Gzip compression, which is:
|
||||||
|
|
||||||
* slow (single threaded)
|
- slow (single threaded)
|
||||||
* space efficient
|
- space efficient
|
||||||
* consumes less bandwidth (helpful if your NFS share is far away)
|
- consumes less bandwidth (helpful if your NFS share is far away)
|
||||||
|
|
||||||
If you have compression on your NFS share (or destination filesystem like ZFS), you can disable compression in Xen Orchestra.
|
If you have compression on your NFS share (or destination filesystem like ZFS), you can disable compression in Xen Orchestra.
|
||||||
|
|
||||||
@@ -152,4 +151,4 @@ Replicated VMs HA are taken into account by XS/XCP-ng. To avoid the resultant tr
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
> The tag won't be automatically removed by XO on the replicated VMs, even if HA is re-enabled.
|
> The tag won't be automatically removed by XO on the replicated VMs, even if HA is re-enabled.
|
||||||
|
|||||||
@@ -22,16 +22,15 @@ All your scheduled backup are acccessible in the "Restore" view in backup sectio
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
### Backup compression
|
### Backup compression
|
||||||
|
|
||||||
By default, Backup are compressed (using GZIP, done in XenServer side). There is no absolute rule about using compression or not, but there is some rules.
|
By default, Backup are compressed (using GZIP, done in XenServer side). There is no absolute rule about using compression or not, but there is some rules.
|
||||||
|
|
||||||
Gzip compression is:
|
Gzip compression is:
|
||||||
|
|
||||||
* slow
|
- slow
|
||||||
* space efficient
|
- space efficient
|
||||||
* consume less bandwidth (if your NFS share is far)
|
- consume less bandwidth (if your NFS share is far)
|
||||||
|
|
||||||
If you have compression on your NFS share (or destination file-system like ZFS), you can disable compression in Xen Orchestra.
|
If you have compression on your NFS share (or destination file-system like ZFS), you can disable compression in Xen Orchestra.
|
||||||
|
|
||||||
@@ -45,4 +44,4 @@ This feature is close to Backups, but it creates a snapshot when planned to do s
|
|||||||
|
|
||||||
**Warning**: snapshots are not backups. They help to rollback to a previous state, but all snapshots are on the same Storage than their original disk. If you lose the original VDI (or the SR), you'll **lose all your snapshots**.
|
**Warning**: snapshots are not backups. They help to rollback to a previous state, but all snapshots are on the same Storage than their original disk. If you lose the original VDI (or the SR), you'll **lose all your snapshots**.
|
||||||
|
|
||||||
[Read more about it](https://xen-orchestra.com/blog/xen-orchestra-4-2/#schedulerollingsnapshots).
|
[Read more about it](https://xen-orchestra.com/blog/xen-orchestra-4-2/#schedulerollingsnapshots).
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
This is the default method. Creating a user is very simple:
|
This is the default method. Creating a user is very simple:
|
||||||
|
|
||||||
1. Go into the Settings view, select "Users"
|
1. Go into the Settings view, select "Users"
|
||||||
2. You can create a *user* or an *admin*, with their password (or generate one)
|
2. You can create a _user_ or an _admin_, with their password (or generate one)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
By default, a *user* won't have any permissions. At the opposite, an *admin* will have all rights.
|
By default, a _user_ won't have any permissions. At the opposite, an _admin_ will have all rights.
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
Cloud-init is a program "that handles the early initialization of a cloud instance"[^n]. In other words, you can, on a "cloud-init"-ready template VM, pass a lot of data at first boot:
|
Cloud-init is a program "that handles the early initialization of a cloud instance"[^n]. In other words, you can, on a "cloud-init"-ready template VM, pass a lot of data at first boot:
|
||||||
|
|
||||||
* setting the hostname
|
- setting the hostname
|
||||||
* add ssh keys
|
- add ssh keys
|
||||||
* automatically grow the file system
|
- automatically grow the file system
|
||||||
* create users
|
- create users
|
||||||
* and a lot more!
|
- and a lot more!
|
||||||
|
|
||||||
This tool is pretty standard and used everywhere. A lot of existing cloud templates are using it.
|
This tool is pretty standard and used everywhere. A lot of existing cloud templates are using it.
|
||||||
|
|
||||||
@@ -40,19 +40,19 @@ Finally, create the VM:
|
|||||||
|
|
||||||
Now start the VM and SSH to its IP:
|
Now start the VM and SSH to its IP:
|
||||||
|
|
||||||
* **the system has the right VM hostname** (from VM name)
|
- **the system has the right VM hostname** (from VM name)
|
||||||
* you don't need to use a password to access it (thanks to your SSH key):
|
- you don't need to use a password to access it (thanks to your SSH key):
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ssh centos@192.168.100.226
|
$ ssh centos@192.168.100.226
|
||||||
[centos@tmp-app1 ~]$
|
[centos@tmp-app1 ~]$
|
||||||
```
|
```
|
||||||
|
|
||||||
The default `cloud-init` configuration can allow you to be to be a sudoer directly:
|
The default `cloud-init` configuration can allow you to be to be a sudoer directly:
|
||||||
|
|
||||||
```
|
```
|
||||||
[centos@tmp-app1 ~]$ sudo -s
|
[centos@tmp-app1 ~]$ sudo -s
|
||||||
[root@tmp-app1 centos]#
|
[root@tmp-app1 centos]#
|
||||||
```
|
```
|
||||||
|
|
||||||
Check the root file system size: indeed, **it was automatically increased** to what you need:
|
Check the root file system size: indeed, **it was automatically increased** to what you need:
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
# Backup Concurrency
|
# Backup Concurrency
|
||||||
|
|
||||||
|
|
||||||
Xen Orchestra 5.20 introduces new tools to manage backup concurrency. Below is an overview of the backup process and ways you can control concurrency in your own environment.
|
Xen Orchestra 5.20 introduces new tools to manage backup concurrency. Below is an overview of the backup process and ways you can control concurrency in your own environment.
|
||||||
|
|
||||||
## Backup process
|
## Backup process
|
||||||
@@ -21,8 +20,8 @@ When it's done exporting, we'll remove the snapshot. Note: this operation will t
|
|||||||
|
|
||||||
Let's say you want to backup 50 VMs (each with 1x disk) at 3:00 AM. There are **2 different strategies**:
|
Let's say you want to backup 50 VMs (each with 1x disk) at 3:00 AM. There are **2 different strategies**:
|
||||||
|
|
||||||
1. backup VM #1 (snapshot, export, delete snapshots) **then** backup VM #2 -> *fully sequential strategy*
|
1. backup VM #1 (snapshot, export, delete snapshots) **then** backup VM #2 -> _fully sequential strategy_
|
||||||
2. snapshot all VMs, **then** export all snapshots, **then** delete all snapshots for finished exports -> *fully parallel strategy*
|
2. snapshot all VMs, **then** export all snapshots, **then** delete all snapshots for finished exports -> _fully parallel strategy_
|
||||||
|
|
||||||
The first purely sequential strategy will lead to a big problem: **you can't predict when a snapshot of your data will occur**. Because you can't predict the first VM export time (let's say 3 hours), then your second VM will have its snapshot taken 3 hours later, at 6 AM. We assume that's not what you meant when you specified "backup everything at 3 AM". You would end up with data from 6 AM (and later) for other VMs.
|
The first purely sequential strategy will lead to a big problem: **you can't predict when a snapshot of your data will occur**. Because you can't predict the first VM export time (let's say 3 hours), then your second VM will have its snapshot taken 3 hours later, at 6 AM. We assume that's not what you meant when you specified "backup everything at 3 AM". You would end up with data from 6 AM (and later) for other VMs.
|
||||||
|
|
||||||
@@ -32,19 +31,18 @@ So what's the best choice? Continue below to learn how to best configure concurr
|
|||||||
|
|
||||||
### Best choice
|
### Best choice
|
||||||
|
|
||||||
By default the *parallel strategy* is, on paper, the most logical one. But we need to give it some limits on concurrency.
|
By default the _parallel strategy_ is, on paper, the most logical one. But we need to give it some limits on concurrency.
|
||||||
|
|
||||||
> Note: Xen Orchestra can be connected to multiple pools at once. So the concurrency number applies **per pool**.
|
> Note: Xen Orchestra can be connected to multiple pools at once. So the concurrency number applies **per pool**.
|
||||||
|
|
||||||
Each step has its own concurrency to fit its requirements:
|
Each step has its own concurrency to fit its requirements:
|
||||||
|
|
||||||
* **snapshot process** needs to be performed with the lowest concurrency possible. 2 is a good compromise: one snapshot is fast, but a stuck snapshot won't block the whole job. That's why a concurrency of 2 is not too bad on your storage. Basically, at 3 AM, we'll do all the VM snapshots needed, 2 at a time.
|
- **snapshot process** needs to be performed with the lowest concurrency possible. 2 is a good compromise: one snapshot is fast, but a stuck snapshot won't block the whole job. That's why a concurrency of 2 is not too bad on your storage. Basically, at 3 AM, we'll do all the VM snapshots needed, 2 at a time.
|
||||||
* **disk export process** is bottlenecked by XCP-ng/XenServer - so to get the most of it, you can use up to 12 in parallel. As soon a snapshot is done, the export process will start, until reaching 12 at once. Then as soon as one in those 12 is finished, another one will appear until there is nothing more to export.
|
- **disk export process** is bottlenecked by XCP-ng/XenServer - so to get the most of it, you can use up to 12 in parallel. As soon a snapshot is done, the export process will start, until reaching 12 at once. Then as soon as one in those 12 is finished, another one will appear until there is nothing more to export.
|
||||||
* **snapshot deletion** can't happen all at once because the previous step durations are random - no need to implement concurrency on this one.
|
- **snapshot deletion** can't happen all at once because the previous step durations are random - no need to implement concurrency on this one.
|
||||||
|
|
||||||
This is how it currently works in Xen Orchestra. But sometimes, you also want to have *sequential* backups combined with the *parallel strategy*. That's why we introduced a sequential option in the advanced section of backup-ng:
|
|
||||||
|
|
||||||
|
This is how it currently works in Xen Orchestra. But sometimes, you also want to have _sequential_ backups combined with the _parallel strategy_. That's why we introduced a sequential option in the advanced section of backup-ng:
|
||||||
|
|
||||||
> Note: 0 means it will be fully **parallel** for all VMs.
|
> Note: 0 means it will be fully **parallel** for all VMs.
|
||||||
|
|
||||||
If you job contains 50 VMs for example, you could specify a sequential backup with a limit of "25 at once" (enter 25 in the concurrency field). This means at 3 AM, we'll do 25 snapshots (2 at a time), then exports. As soon as the first VM backup is completely finished (snapshot removed), then we'll start the 26th and so on, to always keep a max of 25x VM backups going in parallel.
|
If you job contains 50 VMs for example, you could specify a sequential backup with a limit of "25 at once" (enter 25 in the concurrency field). This means at 3 AM, we'll do 25 snapshots (2 at a time), then exports. As soon as the first VM backup is completely finished (snapshot removed), then we'll start the 26th and so on, to always keep a max of 25x VM backups going in parallel.
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ user = 'nobody'
|
|||||||
group = 'nogroup'
|
group = 'nogroup'
|
||||||
```
|
```
|
||||||
|
|
||||||
**Warning!** A non-privileged user requires the use of ``sudo`` to mount NFS shares. See [installation from the sources](from_the_sources.md).
|
**Warning!** A non-privileged user requires the use of `sudo` to mount NFS shares. See [installation from the sources](from_the_sources.md).
|
||||||
|
|
||||||
### HTTP listen address and port
|
### HTTP listen address and port
|
||||||
|
|
||||||
By default, XO-server listens on all addresses (0.0.0.0) and runs on port 80. If you need to, you can change this in the `# Basic HTTP` section:
|
By default, XO-server listens on all addresses (0.0.0.0) and runs on port 80. If you need to, you can change this in the `# Basic HTTP` section:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
host = '0.0.0.0'
|
hostname = '0.0.0.0'
|
||||||
port = 80
|
port = 80
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ port = 80
|
|||||||
XO-server can also run in HTTPS (you can run HTTP and HTTPS at the same time) - just modify what's needed in the `# Basic HTTPS` section, this time with the certificates/keys you need and their path:
|
XO-server can also run in HTTPS (you can run HTTP and HTTPS at the same time) - just modify what's needed in the `# Basic HTTPS` section, this time with the certificates/keys you need and their path:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
host = '0.0.0.0'
|
hostname = '0.0.0.0'
|
||||||
port = 443
|
port = 443
|
||||||
certificate = './certificate.pem'
|
certificate = './certificate.pem'
|
||||||
key = './key.pem'
|
key = './key.pem'
|
||||||
@@ -43,10 +43,10 @@ key = './key.pem'
|
|||||||
|
|
||||||
If you want to redirect everything to HTTPS, you can modify the configuration like this:
|
If you want to redirect everything to HTTPS, you can modify the configuration like this:
|
||||||
|
|
||||||
```
|
```toml
|
||||||
# If set to true, all HTTP traffic will be redirected to the first HTTPs configuration.
|
# If set to true, all HTTP traffic will be redirected to the first HTTPs configuration.
|
||||||
|
|
||||||
redirectToHttps: true
|
redirectToHttps = true
|
||||||
```
|
```
|
||||||
|
|
||||||
This should be written just before the `mount` option, inside the `http:` block.
|
This should be written just before the `mount` option, inside the `http:` block.
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
> WARNING: it works only with XenServer 6.5 or later
|
> WARNING: it works only with XenServer 6.5 or later
|
||||||
|
|
||||||
This feature is a continuous replication system for your XenServer VMs **without any storage vendor lock-in**. You can replicate a VM every *X* minutes/hours to any storage repository. It could be to a distant XenServer host or just another local storage target.
|
This feature is a continuous replication system for your XenServer VMs **without any storage vendor lock-in**. You can replicate a VM every _X_ minutes/hours to any storage repository. It could be to a distant XenServer host or just another local storage target.
|
||||||
|
|
||||||
This feature covers multiple objectives:
|
This feature covers multiple objectives:
|
||||||
|
|
||||||
* no storage vendor lock-in
|
- no storage vendor lock-in
|
||||||
* no configuration (agent-less)
|
- no configuration (agent-less)
|
||||||
* low Recovery Point Objective, from 10 minutes to 24 hours (or more)
|
- low Recovery Point Objective, from 10 minutes to 24 hours (or more)
|
||||||
* flexibility
|
- flexibility
|
||||||
* no intermediate storage needed
|
- no intermediate storage needed
|
||||||
* atomic replication
|
- atomic replication
|
||||||
* efficient DR (disaster recovery) process
|
- efficient DR (disaster recovery) process
|
||||||
|
|
||||||
If you lose your main pool, you can start the copy on the other side, with very recent data.
|
If you lose your main pool, you can start the copy on the other side, with very recent data.
|
||||||
|
|
||||||
@@ -36,18 +36,25 @@ To protect the replication, we removed the possibility to boot your copied VM di
|
|||||||
|
|
||||||
## Manual initial seed
|
## Manual initial seed
|
||||||
|
|
||||||
**If you can't transfer the first backup through your network because it's too large**, you can make a seed locally. In order to do this, follow this procedure (until we make it accessible directly in XO).
|
**If you can't transfer the first backup through your network because it's too large**, you can make a seed locally. In order to do this, follow this procedure (until we make it accessible directly in XO).
|
||||||
|
|
||||||
> This is **only** if you need to make the initial copy without making the whole transfer through your network. Otherwise, **you don't need this**. These instructions are for Backup-NG jobs, and will not work to seed a legacy backup job. Please migrate any legacy jobs to Backup-NG!
|
> This is **only** if you need to make the initial copy without making the whole transfer through your network. Otherwise, **you don't need this**. These instructions are for Backup-NG jobs, and will not work to seed a legacy backup job. Please migrate any legacy jobs to Backup-NG!
|
||||||
|
|
||||||
|
|
||||||
### Job creation
|
### Job creation
|
||||||
|
|
||||||
Create the Continuous Replication backup job, and leave it disabled for now. On the main Backup-NG page, note its identifiers, the main `backupJobId` and the ID of one on the schedules for the job, `backupScheduleId`.
|
Create the Continuous Replication backup job, and leave it disabled for now. On the main Backup-NG page, copy the job's `backupJobId` by hovering to the left of the shortened ID and clicking the copy to clipboard button:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Copy it somewhere temporarily. Now we need to also copy the ID of the job schedule, `backupScheduleId`. Do this by hovering over the schedule name in the same panel as before, and clicking the copy to clipboard button. Keep it with the `backupJobId` you copied previously as we will need them all later:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### Seed creation
|
### Seed creation
|
||||||
|
|
||||||
Manually create a snapshot on the VM to backup, and note its UUID as `snapshotUuid` from the snapshot panel for the VM.
|
Manually create a snapshot on the VM being backed up, then copy this snapshot UUID, `snapshotUuid` from the snapshot panel of the VM:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
> DO NOT ever delete or alter this snapshot, feel free to rename it to make that clear.
|
> DO NOT ever delete or alter this snapshot, feel free to rename it to make that clear.
|
||||||
|
|
||||||
@@ -55,7 +62,9 @@ Manually create a snapshot on the VM to backup, and note its UUID as `snapshotUu
|
|||||||
|
|
||||||
Export this snapshot to a file, then import it on the target SR.
|
Export this snapshot to a file, then import it on the target SR.
|
||||||
|
|
||||||
Note the UUID of this newly created VM as `targetVmUuid`.
|
We need to copy the UUID of this newly created VM as well, `targetVmUuid`:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
> DO not start this VM or it will break the Continuous Replication job! You can rename this VM to more easily remember this.
|
> DO not start this VM or it will break the Continuous Replication job! You can rename this VM to more easily remember this.
|
||||||
|
|
||||||
@@ -77,7 +86,9 @@ Usage: xo-cr-seed <source XAPI URL> <source snapshot UUID> <target XAPI URL> <ta
|
|||||||
|
|
||||||
xo-cr-seed v0.2.0
|
xo-cr-seed v0.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
Putting it altogether and putting our values and UUID's into the command, it will look like this (it is a long command):
|
Putting it altogether and putting our values and UUID's into the command, it will look like this (it is a long command):
|
||||||
|
|
||||||
```
|
```
|
||||||
xo-cr-seed https://root:password@xen1.company.tld 4a21c1cd-e8bd-4466-910a-f7524ecc07b1 https://root:password@xen2.company.tld 5aaf86ca-ae06-4a4e-b6e1-d04f0609e64d 90d11a94-a88f-4a84-b7c1-ed207d3de2f9 369a26f0-da77-41ab-a998-fa6b02c69b9a
|
xo-cr-seed https://root:password@xen1.company.tld 4a21c1cd-e8bd-4466-910a-f7524ecc07b1 https://root:password@xen2.company.tld 5aaf86ca-ae06-4a4e-b6e1-d04f0609e64d 90d11a94-a88f-4a84-b7c1-ed207d3de2f9 369a26f0-da77-41ab-a998-fa6b02c69b9a
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ You can [open bug reports here](https://github.com/vatesfr/xen-orchestra/issues)
|
|||||||
Using the GitHub fork/pull-request feature, you may send us fixes or enhancements.
|
Using the GitHub fork/pull-request feature, you may send us fixes or enhancements.
|
||||||
|
|
||||||
Please, do explain:
|
Please, do explain:
|
||||||
* what you are fixing (issue number if available);
|
|
||||||
* how you did it.
|
- what you are fixing (issue number if available);
|
||||||
|
- how you did it.
|
||||||
|
|
||||||
### Pull requests
|
### Pull requests
|
||||||
|
|
||||||
@@ -22,7 +23,6 @@ to create a [GitHub pull request](https://help.github.com/articles/using-pull-re
|
|||||||
> Your pull request should always be against the `master`
|
> Your pull request should always be against the `master`
|
||||||
> branch and not against `stable` which is the stable branch!
|
> branch and not against `stable` which is the stable branch!
|
||||||
|
|
||||||
|
|
||||||
1. Create a branch for your work
|
1. Create a branch for your work
|
||||||
2. Add a summary of your changes to `CHANGELOG.md` under the `next` section, if your changes do not relate to an existing changelog item
|
2. Add a summary of your changes to `CHANGELOG.md` under the `next` section, if your changes do not relate to an existing changelog item
|
||||||
3. Create a pull request for this branch against the `master` branch
|
3. Create a pull request for this branch against the `master` branch
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> WARNING: Delta backups are only available on XenServer 6.5 or later
|
> WARNING: Delta backups are only available on XenServer 6.5 or later
|
||||||
|
|
||||||
You can export only the delta (difference) between your current VM disks and a previous snapshot (called here the *reference*). They are called *continuous* because you'll **never export a full backup** after the first one.
|
You can export only the delta (difference) between your current VM disks and a previous snapshot (called here the _reference_). They are called _continuous_ because you'll **never export a full backup** after the first one.
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
@@ -10,16 +10,16 @@ Full backups can be represented like this:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
It means huge files for each backups. Delta backups will only export the difference between the previous backup:
|
It means huge files for each backup. Delta backups will only export the difference between the previous backup:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
You can imagine making your first initial full backup during a weekend, and then only delta backups every night. It combines the flexibility of snapshots and the power of full backups, because:
|
You can imagine making your first initial full backup during a weekend, and then only delta backups every night. It combines the flexibility of snapshots and the power of full backups, because:
|
||||||
|
|
||||||
* delta are stored somewhere else than the current VM storage
|
- delta are stored somewhere else than the current VM storage
|
||||||
* they are small
|
- they are small
|
||||||
* quick to create
|
- quick to create
|
||||||
* easy to restore
|
- easy to restore
|
||||||
|
|
||||||
So, if you want to rollback your VM to a previous state, the cost is only one snapshot on your SR (far less than the [rolling snapshot](rolling_snapshot.md) mechanism).
|
So, if you want to rollback your VM to a previous state, the cost is only one snapshot on your SR (far less than the [rolling snapshot](rolling_snapshot.md) mechanism).
|
||||||
|
|
||||||
@@ -41,6 +41,10 @@ This way we can go "forward" and remove this oldest VHD after the merge:
|
|||||||
|
|
||||||
Just go into your "Backup" view, and select Delta Backup. Then, it's the same as a normal backup.
|
Just go into your "Backup" view, and select Delta Backup. Then, it's the same as a normal backup.
|
||||||
|
|
||||||
|
## Snapshots
|
||||||
|
|
||||||
|
Unlike other types of backup jobs which delete the associated snapshot when the job is done and it has been exported, delta backups always keep a snapshot of every VM in the backup job, and uses it for the delta. Do not delete these snapshots!
|
||||||
|
|
||||||
## Exclude disks
|
## Exclude disks
|
||||||
|
|
||||||
During a delta backup job, you can avoid saving all disks of the VM. To do that is trivial: just edit the VM disk name and add `[NOBAK]` before the current name, eg: `data-disk` will become `[NOBAK] data-disk` (with a space or not, doesn't matter).
|
During a delta backup job, you can avoid saving all disks of the VM. To do that is trivial: just edit the VM disk name and add `[NOBAK]` before the current name, eg: `data-disk` will become `[NOBAK] data-disk` (with a space or not, doesn't matter).
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ This is the easiest purchase option: you can buy XOA with your registered email
|
|||||||
|
|
||||||
You can choose the edition you want in two places:
|
You can choose the edition you want in two places:
|
||||||
|
|
||||||
* [the pricing page](https://xen-orchestra.com/#!/pricing)
|
- [the pricing page](https://xen-orchestra.com/#!/pricing)
|
||||||
* [your account/purchases page](https://xen-orchestra.com/#!/purchases)
|
- [your account/purchases page](https://xen-orchestra.com/#!/purchases)
|
||||||
|
|
||||||
|
|
||||||
> You need to be logged in to make a purchase. If you don't have an account, please [register here](https://xen-orchestra.com/#!/signup).
|
> You need to be logged in to make a purchase. If you don't have an account, please [register here](https://xen-orchestra.com/#!/signup).
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ From your account page, click on the purchase menu, then select the edition you
|
|||||||
|
|
||||||
## Purchase options
|
## Purchase options
|
||||||
|
|
||||||
The second step is to select your purchase option:
|
The second step is to select your purchase option:
|
||||||
|
|
||||||
- Subscription: only available with a credit card payment. Choose this option for a monthly payment or a yearly payment **renewed automatically** each year.
|
- Subscription: only available with a credit card payment. Choose this option for a monthly payment or a yearly payment **renewed automatically** each year.
|
||||||
|
|
||||||
@@ -32,16 +31,17 @@ Then you need to fill in your information and select **"Buy for my own use"** (d
|
|||||||

|

|
||||||
|
|
||||||
## Billing information
|
## Billing information
|
||||||
You need to complete all the required information on this page in order to move forward.
|
|
||||||
|
|
||||||
> Note: If you are part of the Eurozone, you will need to provide a valid EU VAT number in order to proceed to payment. Transactions between companies inside the Eurozone are VAT free.
|
You need to complete all the required information on this page in order to move forward.
|
||||||
Transactions outside the Eurozone are VAT free.
|
|
||||||
|
> Note: If you are part of the Eurozone, you will need to provide a valid EU VAT number in order to proceed to payment. Transactions between companies inside the Eurozone are VAT free.
|
||||||
|
> Transactions outside the Eurozone are VAT free.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Select your payment mode
|
## Select your payment mode
|
||||||
|
|
||||||
Credit Card, Wire transfer or Bank check are the three payment methods available on our store. Some methods can be unavailable regarding the purchase option you have selected during step one.
|
Credit Card, Wire transfer or Bank check are the three payment methods available on our store. Some methods can be unavailable regarding the purchase option you have selected during step one.
|
||||||
|
|
||||||
> Wire transfer is not available for monthly and yearly subscription - Credit Card is not available for paid period.
|
> Wire transfer is not available for monthly and yearly subscription - Credit Card is not available for paid period.
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ This category is dedicated to creating a VM with Docker support.
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
* XenServer 6.5 or higher
|
- XenServer 6.5 or higher
|
||||||
* Plugin installation (see below)
|
- Plugin installation (see below)
|
||||||
* CoreOS ISO ([download it here](http://stable.release.core-os.net/amd64-usr/current/coreos_production_iso_image.iso)) for CoreOS installations
|
- CoreOS ISO ([download it here](http://stable.release.core-os.net/amd64-usr/current/coreos_production_iso_image.iso)) for CoreOS installations
|
||||||
* Xen Orchestra 4.10 or newer
|
- Xen Orchestra 4.10 or newer
|
||||||
|
|
||||||
## Docker plugin installation
|
## Docker plugin installation
|
||||||
|
|
||||||
@@ -49,8 +49,8 @@ That's it! You can now enjoy Docker support!
|
|||||||
|
|
||||||
There are two ways to use the newly exposed Docker features:
|
There are two ways to use the newly exposed Docker features:
|
||||||
|
|
||||||
* Install a CoreOS VM
|
- Install a CoreOS VM
|
||||||
* Transform an existing VM into a supported Docker VM
|
- Transform an existing VM into a supported Docker VM
|
||||||
|
|
||||||
### CoreOS
|
### CoreOS
|
||||||
|
|
||||||
@@ -80,7 +80,6 @@ And replace it with your actual SSH public key:
|
|||||||
|
|
||||||
`- ssh-rsa AAAA....kuGgQ me@mypc`
|
`- ssh-rsa AAAA....kuGgQ me@mypc`
|
||||||
|
|
||||||
|
|
||||||
The rest of the configuration is identical to any other VM. Just click on "Create VM" and you are done. After a few seconds, your VM will be ready. Nothing else to do!
|
The rest of the configuration is identical to any other VM. Just click on "Create VM" and you are done. After a few seconds, your VM will be ready. Nothing else to do!
|
||||||
|
|
||||||
You can see it thanks to the docker logo in the main view:
|
You can see it thanks to the docker logo in the main view:
|
||||||
@@ -165,10 +164,10 @@ During the VM creation, the XSContainer plugin will create an extra disk: "Autom
|
|||||||
|
|
||||||
Basically, it reads configuration during the boot, allowing:
|
Basically, it reads configuration during the boot, allowing:
|
||||||
|
|
||||||
* SSH key management for newly created VM/instances
|
- SSH key management for newly created VM/instances
|
||||||
* Root disk filesystem growing
|
- Root disk filesystem growing
|
||||||
* User/group management
|
- User/group management
|
||||||
* Arbitrary command execution (system update, custom scripts etc.)
|
- Arbitrary command execution (system update, custom scripts etc.)
|
||||||
|
|
||||||
In our case, it's used by the XSContainer plugin to allow host communication to the Docker daemon running in the VM, thus exposing Docker commands outside of the VM.
|
In our case, it's used by the XSContainer plugin to allow host communication to the Docker daemon running in the VM, thus exposing Docker commands outside of the VM.
|
||||||
|
|
||||||
@@ -178,9 +177,9 @@ You can also use the XSContainer plugin to "transform" an existing VM into a "Do
|
|||||||
|
|
||||||
You need to have the following installed inside the VM:
|
You need to have the following installed inside the VM:
|
||||||
|
|
||||||
* Docker
|
- Docker
|
||||||
* openssh-server
|
- openssh-server
|
||||||
* ncat
|
- ncat
|
||||||
|
|
||||||
For Debian/Ubuntu like distro: `apt-get install docker.io openssh-server nmap`. For RHEL and derived (CentOS...): `yum install docker openssh-server nmap-ncat`.
|
For Debian/Ubuntu like distro: `apt-get install docker.io openssh-server nmap`. For RHEL and derived (CentOS...): `yum install docker openssh-server nmap-ncat`.
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
There are 4 **editions** of the Xen Orchestra Appliance (XOA):
|
There are 4 **editions** of the Xen Orchestra Appliance (XOA):
|
||||||
|
|
||||||
* Free
|
- Free
|
||||||
* Starter
|
- Starter
|
||||||
* Enterprise
|
- Enterprise
|
||||||
* Premium
|
- Premium
|
||||||
|
|
||||||
**Also, you can try all features in the Premium Edition for free (without any commitment) for 15 days by registering a trial. [Read here for trial instructions](trial.md).**
|
**Also, you can try all features in the Premium Edition for free (without any commitment) for 15 days by registering a trial. [Read here for trial instructions](trial.md).**
|
||||||
|
|
||||||
@@ -13,11 +13,11 @@ There are 4 **editions** of the Xen Orchestra Appliance (XOA):
|
|||||||
|
|
||||||
This is the basic edition, allowing you to perform administrator tasks on a virtualized infrastructure. It's "like" XenCenter. You can:
|
This is the basic edition, allowing you to perform administrator tasks on a virtualized infrastructure. It's "like" XenCenter. You can:
|
||||||
|
|
||||||
* Create VMs, SRs etc.
|
- Create VMs, SRs etc.
|
||||||
* Access to VM consoles (HTML5 web based!)
|
- Access to VM consoles (HTML5 web based!)
|
||||||
* Edit resources (VM, pools etc.)
|
- Edit resources (VM, pools etc.)
|
||||||
* Make snapshots
|
- Make snapshots
|
||||||
* Migrate VMs
|
- Migrate VMs
|
||||||
|
|
||||||
That's more or less the same features you can see on the [administration page](administration.md).
|
That's more or less the same features you can see on the [administration page](administration.md).
|
||||||
|
|
||||||
@@ -27,10 +27,10 @@ The Starter Edition is intended for system administrators who want to do more wi
|
|||||||
|
|
||||||
In addition to the free edition, you get:
|
In addition to the free edition, you get:
|
||||||
|
|
||||||
* [Scheduled backups](full_backups.md)
|
- [Scheduled backups](full_backups.md)
|
||||||
* [Scheduled snapshots](rolling_snapshots.md)
|
- [Scheduled snapshots](rolling_snapshots.md)
|
||||||
* Patch detection and application in one click (even to whole pools at once!)
|
- Patch detection and application in one click (even to whole pools at once!)
|
||||||
* XenServer Docker management via XenServer plugin
|
- XenServer Docker management via XenServer plugin
|
||||||
|
|
||||||
You'll also have access to our ticket system to report issues and be helped in less than 72h.
|
You'll also have access to our ticket system to report issues and be helped in less than 72h.
|
||||||
|
|
||||||
@@ -38,10 +38,10 @@ You'll also have access to our ticket system to report issues and be helped in l
|
|||||||
|
|
||||||
The Enterprise Edition allows you to access a lot more features than Starter:
|
The Enterprise Edition allows you to access a lot more features than Starter:
|
||||||
|
|
||||||
* Disaster Recovery
|
- Disaster Recovery
|
||||||
* Continuous Delta Backup
|
- Continuous Delta Backup
|
||||||
* Live stats
|
- Live stats
|
||||||
* ACLs + LDAP/SSO
|
- ACLs + LDAP/SSO
|
||||||
|
|
||||||
In addition, you'll have faster support to answer your issues/questions (48h or less).
|
In addition, you'll have faster support to answer your issues/questions (48h or less).
|
||||||
|
|
||||||
@@ -49,10 +49,10 @@ In addition, you'll have faster support to answer your issues/questions (48h or
|
|||||||
|
|
||||||
Premium is the highest edition, with all features included without any limitations. This means:
|
Premium is the highest edition, with all features included without any limitations. This means:
|
||||||
|
|
||||||
* Dataviz
|
- Dataviz
|
||||||
* Infrastructure health check
|
- Infrastructure health check
|
||||||
* Job Manager
|
- Job Manager
|
||||||
* Continuous Replication
|
- Continuous Replication
|
||||||
* Self Service
|
- Self Service
|
||||||
|
|
||||||
Along with the fastest guaranteed support - 24 hours or less (typically much less).
|
Along with the fastest guaranteed support - 24 hours or less (typically much less).
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
If you have a UPS for your hosts, and lose power, you may have a limited amount of time to shut down all of your VM infrastructure before the batteries run out. If you find yourself in this situation, or any other situation requiring the fast shutdown of everything, you can use the **Emergency Shutdown** feature.
|
If you have a UPS for your hosts, and lose power, you may have a limited amount of time to shut down all of your VM infrastructure before the batteries run out. If you find yourself in this situation, or any other situation requiring the fast shutdown of everything, you can use the **Emergency Shutdown** feature.
|
||||||
|
|
||||||
## How to activate
|
## How to activate
|
||||||
On the host view, clicking on this button will trigger the _Emergency Shutdown_ procedure:
|
|
||||||
|
On the host view, clicking on this button will trigger the _Emergency Shutdown_ procedure:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
1. **All running VMs will be suspended** (think of it like "hibernate" on your laptop: the RAM will be stored in the storage repository).
|
1. **All running VMs will be suspended** (think of it like "hibernate" on your laptop: the RAM will be stored in the storage repository).
|
||||||
2. Only after this is complete, the host will be halted.
|
2. Only after this is complete, the host will be halted.
|
||||||
|
|
||||||
Here, you can see the running VMs are being suspended:
|
Here, you can see the running VMs are being suspended:
|
||||||
@@ -21,6 +22,7 @@ And finally, that's it. They are cleanly shut down with the RAM saved to disk to
|
|||||||
Now the host is halted automatically.
|
Now the host is halted automatically.
|
||||||
|
|
||||||
## Powering back on
|
## Powering back on
|
||||||
|
|
||||||
When the power outage is over, all you need to do is:
|
When the power outage is over, all you need to do is:
|
||||||
|
|
||||||
1. Start your host.
|
1. Start your host.
|
||||||
|
|||||||
@@ -4,16 +4,17 @@ All the following features are exposed through the web client, XO-Web, which is
|
|||||||
|
|
||||||
We've made multiple categories to help you to find what you need:
|
We've made multiple categories to help you to find what you need:
|
||||||
|
|
||||||
* [XenServer Administration](administration.html)
|
- [XenServer Administration](administration.html)
|
||||||
* [Docker Support](docker_support.html)
|
- [Docker Support](docker_support.html)
|
||||||
* [Backups](backups.html)
|
- [Backups](backups.html)
|
||||||
* [Disaster Recovery](disaster_recovery.html)
|
- [Disaster Recovery](disaster_recovery.html)
|
||||||
* [Resources delegation](resources_delegation.html)
|
- [Resources delegation](resources_delegation.html)
|
||||||
* [CloudInit](cloudinit.md)
|
- [CloudInit](cloudinit.md)
|
||||||
* [Self Service](self_service.html)
|
- [Self Service](self_service.html)
|
||||||
* [Visualizations](visualizations.html)
|
- [Visualizations](visualizations.html)
|
||||||
* [Job Manager](scheduler.html)
|
- [Job Manager](scheduler.html)
|
||||||
* [Alerts](alerts.html)
|
- [Alerts](alerts.html)
|
||||||
* [Load balancing](load_balancing.html)
|
- [Load balancing](load_balancing.html)
|
||||||
|
- [SDN Controller](sdn_controller.html)
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -18,4 +18,4 @@ Then, click on the VM where your files are, and follow the instructions:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
That's it! Your chosen file will be restored.
|
That's it! Your chosen file will be restored.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ We'll consider at this point that you've got a working node on your box. E.g:
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ node -v
|
$ node -v
|
||||||
v8.12.0
|
v8.16.2
|
||||||
```
|
```
|
||||||
|
|
||||||
If not, see [this page](https://nodejs.org/en/download/package-manager/) for instructions on how to install Node.
|
If not, see [this page](https://nodejs.org/en/download/package-manager/) for instructions on how to install Node.
|
||||||
@@ -65,17 +65,13 @@ Now you have to create a config file for `xo-server`:
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cd packages/xo-server
|
$ cd packages/xo-server
|
||||||
$ cp sample.config.toml .xo-server.toml
|
$ mkdir -p ~/.config/xo-server
|
||||||
|
$ cp sample.config.toml ~/.config/xo-server/config.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
Edit and uncomment it to have the right path to serve `xo-web`, because `xo-server` embeds an HTTP server (we assume that `xen-orchestra` and `xo-web` are in the same directory):
|
> Note: If you're installing `xo-server` as a global service, you may want to copy the file to `/etc/xo-server/config.toml` instead.
|
||||||
|
|
||||||
```toml
|
In this config file, you can change default ports (80 and 443) for xo-server. If you are running the server as a non-root user, you will need to set the port to 1024 or higher.
|
||||||
[http.mounts]
|
|
||||||
'/' = '../xo-web/dist/'
|
|
||||||
```
|
|
||||||
|
|
||||||
In this config file, you can also change default ports (80 and 443) for xo-server. If you are running the server as a non-root user, you will need to set the port to 1024 or higher.
|
|
||||||
|
|
||||||
You can try to start xo-server to see if it works. You should have something like this:
|
You can try to start xo-server to see if it works. You should have something like this:
|
||||||
|
|
||||||
@@ -92,6 +88,7 @@ The only part you need to launch is xo-server, which is quite easy to do. From t
|
|||||||
```
|
```
|
||||||
$ yarn start
|
$ yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
That's it! Use your browser to visit the xo-server IP address, and it works! :)
|
That's it! Use your browser to visit the xo-server IP address, and it works! :)
|
||||||
|
|
||||||
## Updating
|
## Updating
|
||||||
@@ -106,6 +103,7 @@ $ git pull --ff-only
|
|||||||
$ yarn
|
$ yarn
|
||||||
$ yarn build
|
$ yarn build
|
||||||
```
|
```
|
||||||
|
|
||||||
Then restart Xen Orchestra if it was running.
|
Then restart Xen Orchestra if it was running.
|
||||||
|
|
||||||
## Always Running
|
## Always Running
|
||||||
@@ -118,7 +116,7 @@ yarn global add forever
|
|||||||
forever start bin/xo-server
|
forever start bin/xo-server
|
||||||
```
|
```
|
||||||
|
|
||||||
- Or you can use [forever-service](https://github.com/zapty/forever-service) to install XO as a system service, so it starts automatically at boot. Run the following as root:
|
- Or you can use [forever-service](https://github.com/zapty/forever-service) to install XO as a system service, so it starts automatically at boot. Run the following as root:
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn global add forever
|
yarn global add forever
|
||||||
@@ -186,7 +184,7 @@ service redis start
|
|||||||
|
|
||||||
## SUDO
|
## SUDO
|
||||||
|
|
||||||
If you are running `xo-server` as a non-root user, you need to use `sudo` to be able to mount NFS remotes. You can do this by editing `xo-server/.xo-server.toml` and setting `useSudo = true`. It's near the end of the file:
|
If you are running `xo-server` as a non-root user, you need to use `sudo` to be able to mount NFS remotes. You can do this by editing `xo-server` configuration file and setting `useSudo = true`. It's near the end of the file:
|
||||||
|
|
||||||
```
|
```
|
||||||
useSudo = true
|
useSudo = true
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# Common errors and troubleshooting
|
# Common errors and troubleshooting
|
||||||
|
|
||||||
## Recommendation
|
## Recommendation
|
||||||
If you think you have a problem with your XOA, start by typing`xoa check`command in your terminal:
|
|
||||||
|
If you think you have a problem with your XOA, start by typing`xoa check`command in your terminal:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ xoa check
|
$ xoa check
|
||||||
@@ -12,27 +13,29 @@ $ xoa check
|
|||||||
✔ xo-server config syntax
|
✔ xo-server config syntax
|
||||||
✔ Appliance registration
|
✔ Appliance registration
|
||||||
✔ Internet connectivity
|
✔ Internet connectivity
|
||||||
```
|
```
|
||||||
|
|
||||||
If the result you have is completely different from that, or if error messages are displayed, lost packets, etc., you have, indeed, a problem. The next step should be to check in this document if there is an existing troubleshooting for the problem you have.
|
If the result you have is completely different from that, or if error messages are displayed, lost packets, etc., you have, indeed, a problem. The next step should be to check in this document if there is an existing troubleshooting for the problem you have.
|
||||||
|
|
||||||
> You can also access the log by using this command: `$ tail -f /var/log/syslog` ([learn more](https://xen-orchestra.com/docs/logs.html))
|
> You can also access the log by using this command: `$ tail -f /var/log/syslog` ([learn more](https://xen-orchestra.com/docs/logs.html))
|
||||||
|
|
||||||
## General
|
## General
|
||||||
|
|
||||||
* [Empty page after login](https://xen-orchestra.com/docs/troubleshooting.html#empty-page-after-login)
|
- [Empty page after login](https://xen-orchestra.com/docs/troubleshooting.html#empty-page-after-login)
|
||||||
* [Can't migrate XOA](https://xen-orchestra.com/docs/troubleshooting.html#xoa-migration-issues)
|
- [Can't migrate XOA](https://xen-orchestra.com/docs/troubleshooting.html#xoa-migration-issues)
|
||||||
* [Can't boot XOA](https://xen-orchestra.com/docs/troubleshooting.html#xoa-boot-issues)
|
- [Can't boot XOA](https://xen-orchestra.com/docs/troubleshooting.html#xoa-boot-issues)
|
||||||
* [Network issues](https://xen-orchestra.com/docs/troubleshooting.html#network-issues)
|
- [Network issues](https://xen-orchestra.com/docs/troubleshooting.html#network-issues)
|
||||||
* [Out of memory](https://xen-orchestra.com/docs/troubleshooting.html#memory)
|
- [Out of memory](https://xen-orchestra.com/docs/troubleshooting.html#memory)
|
||||||
* [Transparent proxy and updater](https://xen-orchestra.com/docs/troubleshooting.html#behind-a-transparent-proxy)
|
- [Transparent proxy and updater](https://xen-orchestra.com/docs/troubleshooting.html#behind-a-transparent-proxy)
|
||||||
* [SSL self-signed certificate expired](https://xen-orchestra.com/docs/troubleshooting.html#updating-ssl-self-signed-certificate)
|
- [SSL self-signed certificate expired](https://xen-orchestra.com/docs/troubleshooting.html#updating-ssl-self-signed-certificate)
|
||||||
* [User authentication](https://xen-orchestra.com/docs/authentication.html#debugging)
|
- [User authentication](https://xen-orchestra.com/docs/authentication.html#debugging)
|
||||||
|
|
||||||
## Backup troubleshooting
|
## Backup troubleshooting
|
||||||
|
|
||||||
* [Unhealthy VDI chain](https://xen-orchestra.com/docs/backup_troubleshooting.html#unhealthy-vdi-chain)
|
- [Unhealthy VDI chain](https://xen-orchestra.com/docs/backup_troubleshooting.html#unhealthy-vdi-chain)
|
||||||
* [SR_backend_failure_44](https://xen-orchestra.com/docs/backup_troubleshooting.html#srbackendfailure44-insufficient-space)
|
- [SR_backend_failure_44](https://xen-orchestra.com/docs/backup_troubleshooting.html#srbackendfailure44-insufficient-space)
|
||||||
* [Could not find the base VM](https://xen-orchestra.com/docs/backup_troubleshooting.html#could-not-find-the-base-vm)
|
- [Could not find the base VM](https://xen-orchestra.com/docs/backup_troubleshooting.html#could-not-find-the-base-vm)
|
||||||
|
|
||||||
## You haven't found a solution here?
|
## You haven't found a solution here?
|
||||||
|
|
||||||
Open a ticket concerning your issue on your personal space [here](https://xen-orchestra.com/#!/member/support)
|
Open a ticket concerning your issue on your personal space [here](https://xen-orchestra.com/#!/member/support)
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
# Glossary
|
# Glossary
|
||||||
|
|
||||||
* CPU: Processor
|
- CPU: Processor
|
||||||
* HA: High Availability
|
- HA: High Availability
|
||||||
* HVM: Hardware virtualization
|
- HVM: Hardware virtualization
|
||||||
* MTU: largest size packet that can be sent in the network
|
- MTU: largest size packet that can be sent in the network
|
||||||
* OS: Operating System
|
- OS: Operating System
|
||||||
* PIF: Physical Network Interface
|
- PIF: Physical Network Interface
|
||||||
* PVM: Paravirtualization
|
- PVM: Paravirtualization
|
||||||
* SR: Storage Repository
|
- SR: Storage Repository
|
||||||
* vCPU: Virtual Processor
|
- vCPU: Virtual Processor
|
||||||
* VDI: Virtual Disk Image
|
- VDI: Virtual Disk Image
|
||||||
* VIF: Virtual Network Interface
|
- VIF: Virtual Network Interface
|
||||||
* VM: Virtual Machine
|
- VM: Virtual Machine
|
||||||
* XO: Xen Orchestra
|
- XO: Xen Orchestra
|
||||||
* XOA: Xen Orchestra Appliance
|
- XOA: Xen Orchestra Appliance
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ This plugin allows Google users to authenticate to Xen-Orchestra.
|
|||||||
|
|
||||||
The first time a user signs in, XO will create a new XO user with the same identifier, without any permissions.
|
The first time a user signs in, XO will create a new XO user with the same identifier, without any permissions.
|
||||||
|
|
||||||
|
|
||||||
## Creating the Google project
|
## Creating the Google project
|
||||||
|
|
||||||
[Create a new project](https://console.developers.google.com/project):
|
[Create a new project](https://console.developers.google.com/project):
|
||||||
@@ -24,9 +23,9 @@ Add OAuth 2.0 credentials:
|
|||||||
|
|
||||||
In Settings, then Plugins, expand the Google plugin detail and provide:
|
In Settings, then Plugins, expand the Google plugin detail and provide:
|
||||||
|
|
||||||
* a `clientID` e.g `326211154583-nt2s112d3t7f4f1hh49oo9164nivvbnu.apps.googleusercontent.com`
|
- a `clientID` e.g `326211154583-nt2s112d3t7f4f1hh49oo9164nivvbnu.apps.googleusercontent.com`
|
||||||
* a `clientSecret`, e.g `HTDb8I4jXiLRMaRL15qCffQ`
|
- a `clientSecret`, e.g `HTDb8I4jXiLRMaRL15qCffQ`
|
||||||
* the `callbackURL`, e.g `http://xo.company.net/signin/google/callback`
|
- the `callbackURL`, e.g `http://xo.company.net/signin/google/callback`
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
SSH to your XenServer and execute the following:
|
Log in to your account and use the deploy form available on [this page](https://xen-orchestra.com/#!/xoa)
|
||||||
|
|
||||||
```
|

|
||||||
bash -c "$(curl -s http://xoa.io/deploy)"
|
|
||||||
```
|
|
||||||
|
|
||||||
This will automatically download/import/start the XOA appliance. Nothing is changed on your XenServer host itself, it's 100% safe.
|
## [More on XOA and alternate deploy](xoa.md)
|
||||||
|
|
||||||
## [More on XOA](xoa.md)
|
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# LDAP
|
# LDAP
|
||||||
|
|
||||||
XO currently supports connections to LDAP directories, like *Open LDAP* or *Active Directory*.
|
XO currently supports connections to LDAP directories, like _Open LDAP_ or _Active Directory_.
|
||||||
|
|
||||||
To configure your LDAP, you need to go into the *Plugins* section in the "Settings" view. Then configure it:
|
To configure your LDAP, you need to go into the _Plugins_ section in the "Settings" view. Then configure it:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -12,8 +12,8 @@ Don't forget to save the configuration, and also check if the plugin is activate
|
|||||||
|
|
||||||
LDAP Filters allow you to properly match your user. It's not an easy task to always find the right filter, and it entirely depends on your LDAP configuration. Still, here is a list of common filters:
|
LDAP Filters allow you to properly match your user. It's not an easy task to always find the right filter, and it entirely depends on your LDAP configuration. Still, here is a list of common filters:
|
||||||
|
|
||||||
* `'(uid={{name}})'` is usually the default filter for *Open LDAP*
|
- `'(uid={{name}})'` is usually the default filter for _Open LDAP_
|
||||||
* `'(cn={{name}})'`, `'(sAMAccountName={{name}})'`, `'(sAMAccountName={{name}}@<domain>)'` or even `'(userPrincipalName={{name}})'` are widely used for *Active Directory*. Please check with your AD Admin to find the right one.
|
- `'(cn={{name}})'`, `'(sAMAccountName={{name}})'`, `'(sAMAccountName={{name}}@<domain>)'` or even `'(userPrincipalName={{name}})'` are widely used for _Active Directory_. Please check with your AD Admin to find the right one.
|
||||||
|
|
||||||
After finishing the configuration, you can try to log in with your LDAP username and password. Finally, right after your initial successful log in, your account will be visible in the user list of Xen Orchestra.
|
After finishing the configuration, you can try to log in with your LDAP username and password. Finally, right after your initial successful log in, your account will be visible in the user list of Xen Orchestra.
|
||||||
|
|
||||||
|
|||||||
@@ -12,18 +12,18 @@ In this coming new view, you'll be able to configure a new load balancing plan,
|
|||||||
|
|
||||||
A plan has:
|
A plan has:
|
||||||
|
|
||||||
* a name
|
- a name
|
||||||
* pool(s) where to apply the policy
|
- pool(s) where to apply the policy
|
||||||
* a mode (see paragraph below)
|
- a mode (see paragraph below)
|
||||||
* a behavior (aggressive, normal, low)
|
- a behavior (aggressive, normal, low)
|
||||||
|
|
||||||
### Plan modes
|
### Plan modes
|
||||||
|
|
||||||
There are 3 modes possible:
|
There are 3 modes possible:
|
||||||
|
|
||||||
* performance
|
- performance
|
||||||
* density
|
- density
|
||||||
* mixed
|
- mixed
|
||||||
|
|
||||||
#### Performance
|
#### Performance
|
||||||
|
|
||||||
@@ -37,8 +37,8 @@ This time, the objective is to use the least hosts possible, and to concentrate
|
|||||||
|
|
||||||
This mode allows you to use both performance and density, but alternatively, depending of a schedule. E.g:
|
This mode allows you to use both performance and density, but alternatively, depending of a schedule. E.g:
|
||||||
|
|
||||||
* **performance** from 6:00 AM to 7:00 PM
|
- **performance** from 6:00 AM to 7:00 PM
|
||||||
* **density** from 7:01 PM to 5:59 AM
|
- **density** from 7:01 PM to 5:59 AM
|
||||||
|
|
||||||
In this case, you'll have the best of both when needed (energy saving during the night and performance during the day).
|
In this case, you'll have the best of both when needed (energy saving during the night and performance during the day).
|
||||||
|
|
||||||
@@ -46,8 +46,8 @@ In this case, you'll have the best of both when needed (energy saving during the
|
|||||||
|
|
||||||
In a plan, you can configure various thresholds:
|
In a plan, you can configure various thresholds:
|
||||||
|
|
||||||
* CPU threshold
|
- CPU threshold
|
||||||
* Free memory
|
- Free memory
|
||||||
|
|
||||||
If the CPU threshold is set to 90%, the load balancer will be only triggered if the average CPU usage on a host is more than 90%.
|
If the CPU threshold is set to 90%, the load balancer will be only triggered if the average CPU usage on a host is more than 90%.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
|
|
||||||
This section will explain how to check the XOA logs, and use them to detect issues.
|
This section will explain how to check the XOA logs, and use them to detect issues.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Metadata backup
|
# Metadata backup
|
||||||
|
|
||||||
> WARNING: Metadata backup is an experimental feature. Restore is not yet available and some unexpected issues may occur.
|
> WARNING: Metadata backup is an experimental feature. Unexpected issues are possible, but unlikely.
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
@@ -8,24 +8,40 @@ XCP-ng and Citrix Hypervisor (Xenserver) hosts use a database to store metadata
|
|||||||
|
|
||||||
In Xen Orchestra, Metadata backup is divided into two different options:
|
In Xen Orchestra, Metadata backup is divided into two different options:
|
||||||
|
|
||||||
* Pool metadata backup
|
- Pool metadata backup
|
||||||
* XO configuration backup
|
- XO configuration backup
|
||||||
|
|
||||||
### How to use metadata backup
|
### Performing a backup
|
||||||
|
|
||||||
In the backup job section, when creating a new backup job, you will now have a choice between backing up VMs and backing up Metadata.
|
In the backup job section, when creating a new backup job, you will now have a choice between backing up VMs and backing up Metadata:
|
||||||

|

|
||||||
|
|
||||||
When you select Metadata backup, you will have a new backup job screen, letting you choose between a pool metadata backup and an XO configuration backup (or both at the same time):
|
When you select Metadata backup, you will have a new backup job screen, letting you choose between a pool metadata backup and an XO configuration backup (or both at the same time):
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Define the name and retention for the job.
|
Define the name and retention for the job.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Once created, the job is displayed with the other classic jobs.
|
Once created, the job is displayed with the other classic jobs.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
> Restore for metadata backup jobs should be available in XO 5.33
|
### Performing a restore
|
||||||
|
|
||||||
|
> WARNING: restoring pool metadata completely overwrites the XAPI database of a host. Only perform a metadata restore if it is a new server with nothing running on it (eg replacing a host with new hardware).
|
||||||
|
|
||||||
|
If you browse to the Backup NG Restore panel, you will now notice a Metadata filter button:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
If you click this button, it will show you Metadata backups available for restore:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can see both our Xen Orchestra config backup, and our pool metadata backup. To restore one, simply click the blue restore arrow, choose a backup date to restore, and click OK:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
That's it!
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
|
|
||||||
# Others
|
# Others
|
||||||
|
|
||||||
We already have other modules in place, e.g for authentication, like a LDAP, SAML, Google or GitHub as external providers.
|
We already have other modules in place, e.g for authentication, like a LDAP, SAML, Google or GitHub as external providers.
|
||||||
|
|
||||||
If you want to understand how modules work, have a look here:
|
If you want to understand how modules work, have a look here:
|
||||||
|
|
||||||
* [LDAP plugin](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-auth-ldap)
|
- [LDAP plugin](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-auth-ldap)
|
||||||
* [GitHub authentication](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-auth-github)
|
- [GitHub authentication](https://github.com/vatesfr/xen-orchestra/tree/master/packages/xo-server-auth-github)
|
||||||
|
|
||||||
XO's API can be explored through the `xo-cli` client (please refer to the previous section for details).
|
XO's API can be explored through the `xo-cli` client (please refer to the previous section for details).
|
||||||
|
|
||||||
There are modules for a lot of various tasks, like:
|
There are modules for a lot of various tasks, like:
|
||||||
|
|
||||||
* performance analysis
|
- performance analysis
|
||||||
* reporting
|
- reporting
|
||||||
* load management
|
- load management
|
||||||
* various authentication providers
|
- various authentication providers
|
||||||
|
|
||||||
Check your Settings/Plugins view in XOA to see them.
|
Check your Settings/Plugins view in XOA to see them.
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ Patching a host manually can be time consuming (and boring). That's why we provi
|
|||||||
|
|
||||||
Your XOA will check the official Citrix servers for missing patches. They will be displayed if any:
|
Your XOA will check the official Citrix servers for missing patches. They will be displayed if any:
|
||||||
|
|
||||||
* in dashboard view
|
- in dashboard view
|
||||||
* in pool view (plus the number of missing patches in a red box)
|
- in pool view (plus the number of missing patches in a red box)
|
||||||
* in host view (in patching tab, same red pill)
|
- in host view (in patching tab, same red pill)
|
||||||
|
|
||||||
### Installing patches
|
### Installing patches
|
||||||
|
|
||||||
When you click on "Install all patches", XOA will do all of the following automatically:
|
When you click on "Install all patches", XOA will do all of the following automatically:
|
||||||
|
|
||||||
* fetch all missing patches from Citrix servers
|
- fetch all missing patches from Citrix servers
|
||||||
* unzip them
|
- unzip them
|
||||||
* upload them
|
- upload them
|
||||||
* apply them in the correct order
|
- apply them in the correct order
|
||||||
|
|
||||||
You can see more screenshots here: https://xen-orchestra.com/blog/hotfix-xs70e004-for-xenserver-7-0/
|
You can see more screenshots here: https://xen-orchestra.com/blog/hotfix-xs70e004-for-xenserver-7-0/
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ You can see more screenshots here: https://xen-orchestra.com/blog/hotfix-xs70e00
|
|||||||
|
|
||||||
## Notes on patching
|
## Notes on patching
|
||||||
|
|
||||||
* Xen Orchestra won't reboot your hosts automatically. That's your call to choose when to do it.
|
- Xen Orchestra won't reboot your hosts automatically. That's your call to choose when to do it.
|
||||||
* Patching doesn't always require rebooting. Check the "Guidance" row: if "restartHost" is displayed, it means you need to reboot to have the patch fully applied (see screenshot below)
|
- Patching doesn't always require rebooting. Check the "Guidance" row: if "restartHost" is displayed, it means you need to reboot to have the patch fully applied (see screenshot below)
|
||||||
* XO will install all patches without rebooting: that's not an issue. Even applying patches manually, **it's not mandatory to reboot after each patch**.
|
- XO will install all patches without rebooting: that's not an issue. Even applying patches manually, **it's not mandatory to reboot after each patch**.
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
|
|
||||||
Xen Orchestra plugins allow you to extend features without rewriting the core of the application.
|
Xen Orchestra plugins allow you to extend features without rewriting the core of the application.
|
||||||
@@ -13,6 +12,6 @@ All plugin configuration should be done in the web interface:
|
|||||||
|
|
||||||
A plugin can be:
|
A plugin can be:
|
||||||
|
|
||||||
* activated/deactivated
|
- activated/deactivated
|
||||||
* loaded on start of the application
|
- loaded on start of the application
|
||||||
* configured (extend the plugin settings by clicking on the "+" icon
|
- configured (extend the plugin settings by clicking on the "+" icon
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
You can buy XOA in multiple ways, depending on your needs. Click on the following links for more documentation:
|
You can buy XOA in multiple ways, depending on your needs. Click on the following links for more documentation:
|
||||||
|
|
||||||
* [for your company (direct purchase)](directpurchase.md)
|
- [for your company (direct purchase)](directpurchase.md)
|
||||||
* [through your purchase department (purchaser)](through_purchase_department.md)
|
- [through your purchase department (purchaser)](through_purchase_department.md)
|
||||||
* [for your own client (reseller)](reseller.md)
|
- [for your own client (reseller)](reseller.md)
|
||||||
|
|
||||||
## XOA Editions
|
## XOA Editions
|
||||||
|
|
||||||
@@ -16,16 +16,16 @@ Invoices are available in PDF format. [Details here](invoices.md).
|
|||||||
|
|
||||||
## Receiving a quote
|
## Receiving a quote
|
||||||
|
|
||||||
You can ask for an automatic quote on our website via the pricing page or directly from you personal account page.
|
You can ask for an automatic quote on our website via the pricing page or directly from you personal account page.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Choose the plan you want, the years of commitment that suits you, then fill out the information required (it should be prefilled with your account information).
|
Choose the plan you want, the years of commitment that suits you, then fill out the information required (it should be prefilled with your account information).
|
||||||
|
|
||||||
If you want to purchase XO using the quote you receive, you just have to enter the quote number into the purchase menu, on your personal account page.
|
If you want to purchase XO using the quote you receive, you just have to enter the quote number into the purchase menu, on your personal account page.
|
||||||
|
|
||||||
## Edit your card information
|
## Edit your card information
|
||||||
|
|
||||||
If you choose a Stripe payment, you can always edit the credit card information in case it changes. To do so, you only have to login to your personal account page and access the *profile* menu.
|
If you choose a Stripe payment, you can always edit the credit card information in case it changes. To do so, you only have to login to your personal account page and access the _profile_ menu.
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Xen Orchestra Partner Program
|
# Xen Orchestra Partner Program
|
||||||
|
|
||||||
The Xen Orchestra partner program is designed to offer you the opportunity to become a reseller of Xen Orchestra and deliver a full stack solution to your customers.
|
The Xen Orchestra partner program is designed to offer you the opportunity to become a reseller of Xen Orchestra and deliver a full stack solution to your customers.
|
||||||
|
|
||||||
> Becoming a reseller will grant you a standard discount. However, **the reseller status is designed for companies that want to actively prospect for new Xen Orchestra users**. That's why we are asking our partners to **resell Xen Orchestra at least two times a year**. If you are acting as a third party purchaser answering to a specific request from one of your customers, you don't need to apply to the reseller program - you can follow [this process](https://xen-orchestra.com/docs/through_purchase_department.html) instead.
|
> Becoming a reseller will grant you a standard discount. However, **the reseller status is designed for companies that want to actively prospect for new Xen Orchestra users**. That's why we are asking our partners to **resell Xen Orchestra at least two times a year**. If you are acting as a third party purchaser answering to a specific request from one of your customers, you don't need to apply to the reseller program - you can follow [this process](https://xen-orchestra.com/docs/through_purchase_department.html) instead.
|
||||||
|
|
||||||
## Apply to the program
|
## Apply to the program
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ Now that you can see the reseller interface:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
You can follow these steps to purchase an XOA edition for your customer.
|
You can follow these steps to purchase an XOA edition for your customer.
|
||||||
|
|
||||||
1. choose the edition you want to purchase for your customer
|
1. choose the edition you want to purchase for your customer
|
||||||
2. Buy it on your reseller page (the discount is automatically applied - once it's done, a new line appears on your reseller page)
|
2. Buy it on your reseller page (the discount is automatically applied - once it's done, a new line appears on your reseller page)
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ This chapter covers how to delegate resources (VM, hosts, etc) to users.
|
|||||||
|
|
||||||
The idea is to allow external users (not admins) to:
|
The idea is to allow external users (not admins) to:
|
||||||
|
|
||||||
* interact only with their objects
|
- interact only with their objects
|
||||||
* delegate VMs to your dev teams...
|
- delegate VMs to your dev teams...
|
||||||
* ... or to your clients
|
- ... or to your clients
|
||||||
|
|
||||||
> Remember: admins can do everything, thus permissions don't apply on them. It's only for *users*.
|
> Remember: admins can do everything, thus permissions don't apply on them. It's only for _users_.
|
||||||
|
|
||||||
## Groups
|
## Groups
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
## Apache
|
## Apache
|
||||||
|
|
||||||
As XO-web and XO-server communicate with *WebSockets*, you need to have the [`mod_proxy`](http://httpd.apache.org/docs/2.4/mod/mod_proxy.html), [`mod_proxy_http`](http://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html), [`mod_proxy_wstunnel`](http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html) and [`mod_rewrite`](http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html) modules enabled.
|
As XO-web and XO-server communicate with _WebSockets_, you need to have the [`mod_proxy`](http://httpd.apache.org/docs/2.4/mod/mod_proxy.html), [`mod_proxy_http`](http://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html), [`mod_proxy_wstunnel`](http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html) and [`mod_rewrite`](http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html) modules enabled.
|
||||||
|
|
||||||
|
|
||||||
Please use this configuration in this order or it will not work. Do not forget the trailing slashes!:
|
Please use this configuration in this order or it will not work. Do not forget the trailing slashes!:
|
||||||
|
|
||||||
@@ -16,12 +15,10 @@ ProxyPass /[<path>]/ http://<xo-server ip>:<xo-server port>/
|
|||||||
ProxyPassReverse /[<path>]/ http://<xo-server ip>:<xo-server port>/
|
ProxyPassReverse /[<path>]/ http://<xo-server ip>:<xo-server port>/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## NGINX
|
## NGINX
|
||||||
|
|
||||||
Just configure your VirtualHost as usual (or your default site), with a `location` section like this one:
|
Just configure your VirtualHost as usual (or your default site), with a `location` section like this one:
|
||||||
|
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
location /[<path>] {
|
location /[<path>] {
|
||||||
# Add some headers
|
# Add some headers
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
# Roadmap
|
# Roadmap
|
||||||
|
|
||||||
> Our roadmap is very flexible - you can check the **milestones** repository for a complete overview of all the features we are currently working on.
|
> Our roadmap is very flexible - you can check the **milestones** repository for a complete overview of all the features we are currently working on.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- [Milestones](https://github.com/vatesfr/xen-orchestra/milestones)
|
- [Milestones](https://github.com/vatesfr/xen-orchestra/milestones)
|
||||||
- [Alerts and reports](alerts.md)
|
- [Alerts and reports](alerts.md)
|
||||||
|
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
- [Known bugs](https://github.com/vatesfr/xen-orchestra/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+bug%22)
|
- [Known bugs](https://github.com/vatesfr/xen-orchestra/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+bug%22)
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ This feature is similar to Backups, but it creates a snapshot when planned to do
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
* Schedule a nightly snapshot for a group of VMs, let's say at 4:30 in the morning. With a max snapshot of 7, you'll have a week of revert possibility
|
- Schedule a nightly snapshot for a group of VMs, let's say at 4:30 in the morning. With a max snapshot of 7, you'll have a week of revert possibility
|
||||||
* Schedule a snapshot every week, but precisely Sunday at 11 PM, with 4 snapshots max. This will give you a month max of revert
|
- Schedule a snapshot every week, but precisely Sunday at 11 PM, with 4 snapshots max. This will give you a month max of revert
|
||||||
* And so forth!
|
- And so forth!
|
||||||
|
|||||||
@@ -35,20 +35,20 @@ The possibilities are infinite! You can schedule a **lot** of things (any action
|
|||||||
|
|
||||||
### Save on your electric bill
|
### Save on your electric bill
|
||||||
|
|
||||||
* plan a live migration of your VMs at 11:00PM to a less powerful host, then shutdown the big one
|
- plan a live migration of your VMs at 11:00PM to a less powerful host, then shutdown the big one
|
||||||
* start the big server at 6:00AM and migrate the VMs back 15 minutes later
|
- start the big server at 6:00AM and migrate the VMs back 15 minutes later
|
||||||
|
|
||||||
### Scale when needed
|
### Scale when needed
|
||||||
|
|
||||||
* schedule the boot of extra VMs during your usual activity spikes (horizontal scaling)
|
- schedule the boot of extra VMs during your usual activity spikes (horizontal scaling)
|
||||||
* also add more vCPUs or RAM to these VMs at the same time
|
- also add more vCPUs or RAM to these VMs at the same time
|
||||||
* go back to the previous state when your planned load is low (e.g: during the night)
|
- go back to the previous state when your planned load is low (e.g: during the night)
|
||||||
|
|
||||||
### Planned reboot
|
### Planned reboot
|
||||||
|
|
||||||
* For example: your client app is not very stable, or you need to reboot every month after kernel updates: schedule this during the weekend!
|
- For example: your client app is not very stable, or you need to reboot every month after kernel updates: schedule this during the weekend!
|
||||||
|
|
||||||
### Add or Remove ACLs
|
### Add or Remove ACLs
|
||||||
|
|
||||||
* revoke your user ACLs Friday at 11:00PM (e.g: no access on the weekend)
|
- revoke your user ACLs Friday at 11:00PM (e.g: no access on the weekend)
|
||||||
* restore them Monday at 6:00AM
|
- restore them Monday at 6:00AM
|
||||||
|
|||||||