mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-21 00:24:07 +08:00
Compare commits
647 Commits
v2.13.2
...
release/2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70be65707a | ||
|
|
e67ded4478 | ||
|
|
ef28c00820 | ||
|
|
ea846d06b9 | ||
|
|
cbd7d4f652 | ||
|
|
90d90eac2d | ||
|
|
95d196b465 | ||
|
|
f6c16dd0b3 | ||
|
|
c7faaa18b8 | ||
|
|
20eedc000d | ||
|
|
95ff50e23b | ||
|
|
4f22331673 | ||
|
|
03ca3febfe | ||
|
|
4aa53ae8fe | ||
|
|
a4cabafcfb | ||
|
|
25d4f102df | ||
|
|
a5ce661648 | ||
|
|
9816ed5878 | ||
|
|
bcae0c1d81 | ||
|
|
0579fc4bb9 | ||
|
|
d2868a7af2 | ||
|
|
0055a08350 | ||
|
|
10e902a837 | ||
|
|
b704a0b067 | ||
|
|
29fd7507f1 | ||
|
|
7bbbccee47 | ||
|
|
b02f01c969 | ||
|
|
9aa90a3b06 | ||
|
|
52f33b0420 | ||
|
|
023b8c6de0 | ||
|
|
b3a603bcc8 | ||
|
|
36e0ce4f87 | ||
|
|
799bb49451 | ||
|
|
93f79bec1b | ||
|
|
fe6b0e38e6 | ||
|
|
eae3b06b96 | ||
|
|
d91086def8 | ||
|
|
2b94a9062d | ||
|
|
e42dc01341 | ||
|
|
399844eef2 | ||
|
|
e440019097 | ||
|
|
f3f13e18cb | ||
|
|
91ed14d40e | ||
|
|
33ac4a6edf | ||
|
|
ab6260d8bc | ||
|
|
bf2589d4fd | ||
|
|
42138c82a9 | ||
|
|
ce72c82bea | ||
|
|
543f83c1c1 | ||
|
|
d5d6ed39c6 | ||
|
|
7716881286 | ||
|
|
cdcf3b6ebf | ||
|
|
017f8adf36 | ||
|
|
70e859ad67 | ||
|
|
dca8d06739 | ||
|
|
c5335acf5c | ||
|
|
31abdc46a2 | ||
|
|
d779fc0528 | ||
|
|
16880022d6 | ||
|
|
ae97d9fa90 | ||
|
|
0b3d80e359 | ||
|
|
3a8aae5a55 | ||
|
|
950aae9895 | ||
|
|
8d002a8e78 | ||
|
|
94b5c8f6df | ||
|
|
946d3232c7 | ||
|
|
e95c7165c4 | ||
|
|
58d5bc0f89 | ||
|
|
25e8ce027a | ||
|
|
841c59e8c3 | ||
|
|
6869846840 | ||
|
|
ee196529f6 | ||
|
|
249db7d9d5 | ||
|
|
8508032c60 | ||
|
|
55fb6930f7 | ||
|
|
f4b7e4c93f | ||
|
|
fe2add1563 | ||
|
|
fe2eeaf97c | ||
|
|
d156d2a648 | ||
|
|
5283c09784 | ||
|
|
b38a17bbc1 | ||
|
|
f951a08008 | ||
|
|
a9043c3423 | ||
|
|
971ed7aee5 | ||
|
|
e8d6024b65 | ||
|
|
2702fd9419 | ||
|
|
f876e3ec66 | ||
|
|
13972ead36 | ||
|
|
64bf28f065 | ||
|
|
6afb54f2ff | ||
|
|
fd556c8cb3 | ||
|
|
26657d8213 | ||
|
|
a2ab3e2e37 | ||
|
|
f7b7c2ca79 | ||
|
|
7e4b8c2f54 | ||
|
|
ae5199417b | ||
|
|
84d9282f61 | ||
|
|
c8642a5055 | ||
|
|
0001287411 | ||
|
|
8bbbe29d74 | ||
|
|
33efca986e | ||
|
|
9463d2647a | ||
|
|
4c9a53e119 | ||
|
|
055edec299 | ||
|
|
9e8a0ec8c4 | ||
|
|
96ba08a0be | ||
|
|
c0d220b0be | ||
|
|
1c6e52e23b | ||
|
|
6482f61358 | ||
|
|
2cb5c91d3f | ||
|
|
efce8fcce2 | ||
|
|
4c9789a3cf | ||
|
|
39d6ec3f99 | ||
|
|
d6ea55819a | ||
|
|
ea2cbcb9dd | ||
|
|
6630b2b616 | ||
|
|
fc81a230d8 | ||
|
|
c187b8815d | ||
|
|
ac8deb50c9 | ||
|
|
3910867270 | ||
|
|
f3e172f9cf | ||
|
|
9ec6f25468 | ||
|
|
9de5c4b12e | ||
|
|
e2e456f71c | ||
|
|
41ec0eef0c | ||
|
|
5d52afc364 | ||
|
|
ea34a7eaf8 | ||
|
|
bd81f14238 | ||
|
|
425ee89d02 | ||
|
|
93146a9906 | ||
|
|
a8ade5bcec | ||
|
|
4dfc5ea305 | ||
|
|
ba1c114ef8 | ||
|
|
1ba74bed22 | ||
|
|
4e9c24192f | ||
|
|
32066e5273 | ||
|
|
aab846429a | ||
|
|
f44a20ca9b | ||
|
|
3cddd57f3f | ||
|
|
cf4f9b5dc2 | ||
|
|
4e34329c79 | ||
|
|
220b061ebb | ||
|
|
4eecb6ec9b | ||
|
|
2a47a4497e | ||
|
|
a28b075517 | ||
|
|
f50b15c4ef | ||
|
|
155d7c0d21 | ||
|
|
b7f15ba70a | ||
|
|
2c73e172ce | ||
|
|
302556814a | ||
|
|
08c24e78c3 | ||
|
|
3b812a74ce | ||
|
|
ddfbaefe15 | ||
|
|
e69130e2d3 | ||
|
|
60fa2466d0 | ||
|
|
33a1c9ad9f | ||
|
|
0b4bf4ad75 | ||
|
|
40633d71b2 | ||
|
|
ed4880dedd | ||
|
|
a7b33d0763 | ||
|
|
06ef8007de | ||
|
|
dd4f1f5e2b | ||
|
|
5ef620eda6 | ||
|
|
8af74bde26 | ||
|
|
10970b5293 | ||
|
|
0dc76d6fce | ||
|
|
713274cb76 | ||
|
|
3c442a2ceb | ||
|
|
59f44aa283 | ||
|
|
2bc6f73bf3 | ||
|
|
c47aa60243 | ||
|
|
d7e1879274 | ||
|
|
b10450232b | ||
|
|
fd30e1f7d6 | ||
|
|
2c4b5d83ba | ||
|
|
b822543513 | ||
|
|
c5ad5c4fd5 | ||
|
|
24c3b516ba | ||
|
|
ea0f474128 | ||
|
|
6f70d31f6e | ||
|
|
5e67253bcc | ||
|
|
650888c10f | ||
|
|
24c645025f | ||
|
|
5faa172bda | ||
|
|
481599ec59 | ||
|
|
f73152496f | ||
|
|
51ccda9d6e | ||
|
|
72bc05401f | ||
|
|
574b3fe93d | ||
|
|
e1fc0dac25 | ||
|
|
d1b60cb99f | ||
|
|
7939127ce1 | ||
|
|
674c1a278c | ||
|
|
cffa941453 | ||
|
|
4e7ca3eddb | ||
|
|
6e2a684330 | ||
|
|
d19a14ec78 | ||
|
|
cb2f1aa4b1 | ||
|
|
ce8c31c84a | ||
|
|
4f5f4a60e2 | ||
|
|
7e040d7aff | ||
|
|
91af65ca94 | ||
|
|
0eadd02531 | ||
|
|
eb9b413e43 | ||
|
|
4bb58627e3 | ||
|
|
c15e23d96d | ||
|
|
cf4241894e | ||
|
|
0c367976e0 | ||
|
|
6cb171533d | ||
|
|
b1984e6634 | ||
|
|
aff70fedc1 | ||
|
|
7f37e300ef | ||
|
|
be2491a89b | ||
|
|
6960dbbf54 | ||
|
|
a1963e5837 | ||
|
|
f5a40c3e02 | ||
|
|
bccf1dc67f | ||
|
|
fd05116707 | ||
|
|
30e451afa7 | ||
|
|
c808bfc47d | ||
|
|
ebd9c788aa | ||
|
|
6b0d54f9c2 | ||
|
|
164de8a9cd | ||
|
|
74865802ba | ||
|
|
0b2eb093af | ||
|
|
02982f7850 | ||
|
|
1db48ed31f | ||
|
|
4422faf411 | ||
|
|
a907289d0f | ||
|
|
3d40f4dd9d | ||
|
|
194f8f9916 | ||
|
|
f912464b49 | ||
|
|
d8f148f791 | ||
|
|
58a4a5cc29 | ||
|
|
1acaac1241 | ||
|
|
58645ae956 | ||
|
|
d718738084 | ||
|
|
9944c0d655 | ||
|
|
de741bd1e3 | ||
|
|
19a1f90a54 | ||
|
|
123b7de76e | ||
|
|
4c83dc9e21 | ||
|
|
c8878ca5a5 | ||
|
|
ae8d10e18e | ||
|
|
710e27ea40 | ||
|
|
b8bd0afeeb | ||
|
|
49eb90b3d2 | ||
|
|
4ddf168402 | ||
|
|
cafdab7d61 | ||
|
|
71d38f4b88 | ||
|
|
ba6045f875 | ||
|
|
a96d820651 | ||
|
|
529a01df4f | ||
|
|
39b8b501fe | ||
|
|
2fc2ff8721 | ||
|
|
2d923f2dcf | ||
|
|
e662b4a750 | ||
|
|
bf945704b6 | ||
|
|
20468aab12 | ||
|
|
e4fad874ac | ||
|
|
11facb6d01 | ||
|
|
238ba18829 | ||
|
|
081f6de5f7 | ||
|
|
dd23fabbd4 | ||
|
|
065cd2a5a6 | ||
|
|
8d953b6937 | ||
|
|
71ad4a7baf | ||
|
|
6c0a2b94fb | ||
|
|
e02b675ee1 | ||
|
|
ae0df7f083 | ||
|
|
6c51584720 | ||
|
|
7ee8d72fe3 | ||
|
|
4491605dad | ||
|
|
7555e13ed6 | ||
|
|
8518ce8ab5 | ||
|
|
3a48f06c6e | ||
|
|
7f4f49e05b | ||
|
|
fd2843b2aa | ||
|
|
338a00de6d | ||
|
|
1e182fdf78 | ||
|
|
a720cd7a4d | ||
|
|
c7f3b5014e | ||
|
|
447c1149b3 | ||
|
|
c6b9908536 | ||
|
|
047492e6ea | ||
|
|
74b9311d33 | ||
|
|
555178c3eb | ||
|
|
48bd78fd68 | ||
|
|
a7269ed6e1 | ||
|
|
080dc22420 | ||
|
|
44daad6372 | ||
|
|
08cb53823f | ||
|
|
481b8cf1a2 | ||
|
|
d46f1a6f4c | ||
|
|
ace9f6e2d4 | ||
|
|
4cc6f3e999 | ||
|
|
d6f9eed05a | ||
|
|
8827d2b15c | ||
|
|
9e4efab13c | ||
|
|
2835fed7dc | ||
|
|
39753f5a76 | ||
|
|
c7f577e08e | ||
|
|
22239cb5ab | ||
|
|
bd80c3a399 | ||
|
|
7c5cd59d90 | ||
|
|
ac6a97fea6 | ||
|
|
a81d7c749a | ||
|
|
265e3f6732 | ||
|
|
c17b058baa | ||
|
|
ea12386358 | ||
|
|
72a787da9a | ||
|
|
f0b166a302 | ||
|
|
68fadf1c18 | ||
|
|
a448a6f3b9 | ||
|
|
f6a3a487d8 | ||
|
|
372e52b638 | ||
|
|
37460bddb9 | ||
|
|
c968eb3fe1 | ||
|
|
3e3a1381a7 | ||
|
|
e4666ffb85 | ||
|
|
bd0f6b9771 | ||
|
|
90bf94ad5e | ||
|
|
aedb61c647 | ||
|
|
fd4434d7af | ||
|
|
7045af048c | ||
|
|
aa93908f6d | ||
|
|
ec63cb5d05 | ||
|
|
8999868e5f | ||
|
|
ae2a798926 | ||
|
|
e4d2d67cd2 | ||
|
|
72e5e95a0a | ||
|
|
211653ea5f | ||
|
|
6895168a6c | ||
|
|
6b659bec11 | ||
|
|
2771bd990e | ||
|
|
86002e3c33 | ||
|
|
29597ae0b5 | ||
|
|
f8813618a2 | ||
|
|
f4811f3509 | ||
|
|
ef14598cea | ||
|
|
b686f609f8 | ||
|
|
504d0e3bdf | ||
|
|
bfadc7b6e7 | ||
|
|
4ea2d318e0 | ||
|
|
db98eee265 | ||
|
|
dd54ff6c6c | ||
|
|
518b05216f | ||
|
|
e1fe28ab95 | ||
|
|
6610e57293 | ||
|
|
5c77969718 | ||
|
|
bc607d8f68 | ||
|
|
59bed062f8 | ||
|
|
26826e3218 | ||
|
|
61e5f5eb74 | ||
|
|
23096b9164 | ||
|
|
7e39c89c4a | ||
|
|
9867fb7dba | ||
|
|
f5cf95fa8b | ||
|
|
08cb039c98 | ||
|
|
0dbd655c17 | ||
|
|
59ec24d13a | ||
|
|
d0edfcb351 | ||
|
|
6d5e1ccab3 | ||
|
|
e12943ea8f | ||
|
|
3d1bd111fb | ||
|
|
fe688862f0 | ||
|
|
651ded2b8f | ||
|
|
b10f4d839d | ||
|
|
872a217b5a | ||
|
|
2718f39c67 | ||
|
|
ab692d05fd | ||
|
|
ca578b4848 | ||
|
|
40b52e027c | ||
|
|
ac5584caae | ||
|
|
2bf1ef40b2 | ||
|
|
6886e20ba3 | ||
|
|
54ced32814 | ||
|
|
f295ac0066 | ||
|
|
33924e56cc | ||
|
|
7af90dc0a5 | ||
|
|
11cc8c7891 | ||
|
|
c7c11a6d5a | ||
|
|
c83aeefc09 | ||
|
|
f40cbe41b6 | ||
|
|
345f008916 | ||
|
|
7be54fefee | ||
|
|
0a4d5b63a0 | ||
|
|
7ce699990a | ||
|
|
a51f74e2d8 | ||
|
|
1fe3213b6e | ||
|
|
cd094ebb32 | ||
|
|
f11f3298d7 | ||
|
|
41c9dd1c5a | ||
|
|
df49302e12 | ||
|
|
1668e2eba0 | ||
|
|
f175a3eb4e | ||
|
|
8a1ee68c05 | ||
|
|
210b8c7349 | ||
|
|
264ffc5cc8 | ||
|
|
235dabdfae | ||
|
|
7e04910c9c | ||
|
|
a40cf5e478 | ||
|
|
81baf01309 | ||
|
|
95e7368f2e | ||
|
|
d1049ca209 | ||
|
|
c10748991b | ||
|
|
ee1dd15bf6 | ||
|
|
cf9f709f9a | ||
|
|
b1f1ed5048 | ||
|
|
a0d2d1961a | ||
|
|
bed7635ff1 | ||
|
|
40af1680ed | ||
|
|
8b067089e1 | ||
|
|
76db8ff957 | ||
|
|
834963ec18 | ||
|
|
21bc1ccd42 | ||
|
|
6bf4b4f168 | ||
|
|
37d19a591f | ||
|
|
74c8d17700 | ||
|
|
c5dfc0dbe8 | ||
|
|
f33f1cb540 | ||
|
|
52c8c32d3b | ||
|
|
7c9659225d | ||
|
|
75b71f6c30 | ||
|
|
165a83adfb | ||
|
|
cf50b302a9 | ||
|
|
8c238edba6 | ||
|
|
2a49903ec4 | ||
|
|
9cfa0baee4 | ||
|
|
9f5bae0848 | ||
|
|
f929b7d04c | ||
|
|
57c21a2eb7 | ||
|
|
3312592a6e | ||
|
|
115fbc9f6c | ||
|
|
1bd2cc7c2a | ||
|
|
d20b7cd8d1 | ||
|
|
2c3e420c9e | ||
|
|
fedbcb7e62 | ||
|
|
2c56e3c0ea | ||
|
|
940626f02b | ||
|
|
6279046908 | ||
|
|
ae4ac10a9d | ||
|
|
603deb46b2 | ||
|
|
9b338f1ac1 | ||
|
|
7b95e9ffcb | ||
|
|
dd932abdea | ||
|
|
4442ec9ef5 | ||
|
|
04118849ca | ||
|
|
fb93c05e8c | ||
|
|
4c7962d4f9 | ||
|
|
cc0ad1bf6c | ||
|
|
9d6cf8c9bb | ||
|
|
5e9ca17c0e | ||
|
|
3efd386239 | ||
|
|
d11deb726e | ||
|
|
00409a5afd | ||
|
|
20895d9d3a | ||
|
|
6858c0bf42 | ||
|
|
016812079e | ||
|
|
98b74e228e | ||
|
|
9e2bf1d7e9 | ||
|
|
f91a3d75e1 | ||
|
|
7c5f0144e2 | ||
|
|
303c250b5c | ||
|
|
af4e49da15 | ||
|
|
39c7b262cd | ||
|
|
b99e734ee7 | ||
|
|
a5eb231c7b | ||
|
|
a322c4eccb | ||
|
|
392ae25406 | ||
|
|
ab27e69059 | ||
|
|
482f91b598 | ||
|
|
24b9d520af | ||
|
|
fea8acee9c | ||
|
|
6c486bea93 | ||
|
|
f3cab30db7 | ||
|
|
5faa9d37ad | ||
|
|
6c2dfb0d95 | ||
|
|
1deec8fff8 | ||
|
|
8b8f133bd6 | ||
|
|
3c969c5b44 | ||
|
|
ede5310326 | ||
|
|
10b0bdc458 | ||
|
|
9acd1caf31 | ||
|
|
98a834ea97 | ||
|
|
6f575a0c36 | ||
|
|
5ca79012a2 | ||
|
|
42f788cf60 | ||
|
|
f55e44a94c | ||
|
|
0b74750d07 | ||
|
|
46d01a63ad | ||
|
|
3bd0e0578d | ||
|
|
51f13cb6f1 | ||
|
|
ae4a5f73fe | ||
|
|
19db4ea583 | ||
|
|
a03084b80e | ||
|
|
2e4c8bdc90 | ||
|
|
16b66b0043 | ||
|
|
c41df78db9 | ||
|
|
078f7f87d3 | ||
|
|
724c82c2b1 | ||
|
|
11cd177576 | ||
|
|
441e533a43 | ||
|
|
26d22319cd | ||
|
|
0d82b55f79 | ||
|
|
49062aa3f9 | ||
|
|
b9c89511a1 | ||
|
|
cdb676ef90 | ||
|
|
36e853e275 | ||
|
|
0218b6ca00 | ||
|
|
780d5022d3 | ||
|
|
2e06d2ab46 | ||
|
|
6bb97acb1e | ||
|
|
228fae2d73 | ||
|
|
7f6435a48a | ||
|
|
96372ac317 | ||
|
|
ceccc16d86 | ||
|
|
e3582e9bd4 | ||
|
|
26ea46bac2 | ||
|
|
062cc32f7b | ||
|
|
13795ae495 | ||
|
|
3180fab209 | ||
|
|
467756521c | ||
|
|
7a1c1b1daa | ||
|
|
a648ef13e4 | ||
|
|
bf34e20c3e | ||
|
|
3834490cca | ||
|
|
9fb52fd57d | ||
|
|
6ea039d2a4 | ||
|
|
9506c4a914 | ||
|
|
9aa0a87ce8 | ||
|
|
24c1f2f3ff | ||
|
|
894f54bd30 | ||
|
|
cbcc0f1137 | ||
|
|
ee1e9cf07f | ||
|
|
6b229bec67 | ||
|
|
918c2e2fdf | ||
|
|
b10e34f90a | ||
|
|
af98bc824b | ||
|
|
f5b871f9a9 | ||
|
|
5ee81acd38 | ||
|
|
07b8db5bd1 | ||
|
|
38950466e2 | ||
|
|
f7767adc4d | ||
|
|
2bbaf4e81a | ||
|
|
391dabc4f9 | ||
|
|
0fd5ff9ecb | ||
|
|
17dfc3d34d | ||
|
|
40acdc8c3f | ||
|
|
ce73403de9 | ||
|
|
83769d4d58 | ||
|
|
33a3dbeaaa | ||
|
|
451de216a0 | ||
|
|
13ca3a82b8 | ||
|
|
b6d7e9f238 | ||
|
|
d5a9e68a71 | ||
|
|
49cf5caec0 | ||
|
|
dee8c2d705 | ||
|
|
24216d97ca | ||
|
|
7d1d6469d9 | ||
|
|
7754887614 | ||
|
|
a6dccf3fb6 | ||
|
|
7c4d703271 | ||
|
|
96d89e4ec7 | ||
|
|
92e492e00e | ||
|
|
6b9a50eb5b | ||
|
|
94e3217702 | ||
|
|
db9ce1114e | ||
|
|
5f586ec8cd | ||
|
|
ee5559801f | ||
|
|
b4c4a14af0 | ||
|
|
ec8d401cf1 | ||
|
|
48c754b194 | ||
|
|
2b2b99a950 | ||
|
|
54eed99893 | ||
|
|
01b6ff6516 | ||
|
|
6631b2cc65 | ||
|
|
ea7aaa640a | ||
|
|
addfe349f1 | ||
|
|
36468628cb | ||
|
|
d86171f906 | ||
|
|
8361b96ef8 | ||
|
|
45177492a5 | ||
|
|
ba2da6707f | ||
|
|
6efd09592f | ||
|
|
4141bd2b7d | ||
|
|
5adeeb145a | ||
|
|
02a8de8993 | ||
|
|
353e7658dc | ||
|
|
b4e712fe7d | ||
|
|
8b9d903098 | ||
|
|
95dd972ff2 | ||
|
|
4fcfbf8c08 | ||
|
|
fd0eb3e12c | ||
|
|
d76f9635f0 | ||
|
|
26bc4b10ad | ||
|
|
f9e57aad03 | ||
|
|
e6f12a7d35 | ||
|
|
50fc75aab6 | ||
|
|
5aab6a4672 | ||
|
|
004f7f78ba | ||
|
|
eb92a59297 | ||
|
|
8ddc46a09f | ||
|
|
4a3088e23e | ||
|
|
4b1ae7ee6a | ||
|
|
6155e6b83e | ||
|
|
52542c4797 | ||
|
|
23288535f0 | ||
|
|
d94401c81f | ||
|
|
0a91b14974 | ||
|
|
a349f18ac8 | ||
|
|
0122a10d13 | ||
|
|
608a81f23d | ||
|
|
13e9e0bac2 | ||
|
|
1967734321 | ||
|
|
0472ad2099 | ||
|
|
1b86e01fa0 | ||
|
|
a10dbb815a | ||
|
|
fb667b4fa1 | ||
|
|
9731377ad7 | ||
|
|
16d4459c87 | ||
|
|
df785375cd | ||
|
|
064ee8cba5 | ||
|
|
82ba269249 | ||
|
|
90bfc06ddc | ||
|
|
14697aea1f | ||
|
|
4f42e496d1 | ||
|
|
8c8c2220ca | ||
|
|
504442e11e | ||
|
|
c8add2b3e4 | ||
|
|
e577937dc7 | ||
|
|
1912ba138b | ||
|
|
6b4cb1d1b2 | ||
|
|
7b8ddc12d3 | ||
|
|
fe5cf5c175 | ||
|
|
d9c6cc2dc4 | ||
|
|
4348939bcd | ||
|
|
2e5cc6bb85 | ||
|
|
789b09d092 | ||
|
|
20fb6991c9 | ||
|
|
30e3c6ac14 | ||
|
|
da3122840e | ||
|
|
5dfdb10a93 | ||
|
|
1d90829e3a | ||
|
|
f38a4ec148 | ||
|
|
fa649cf1c4 | ||
|
|
f9639714e4 |
1
Makefile
1
Makefile
@@ -182,7 +182,6 @@ dep:
|
||||
|
||||
mod:
|
||||
go get $(patsubst %,%@master,$(shell GO111MODULE=on go mod edit -print | sed -n -e 's|.*\(yunion.io/x/[a-z].*\) v.*|\1|p'))
|
||||
go get github.com/Azure/azure-sdk-for-go@latest
|
||||
go mod tidy
|
||||
go mod vendor -v
|
||||
|
||||
|
||||
@@ -134,7 +134,11 @@ fi
|
||||
|
||||
rpmbuild --define "_topdir $BUILDROOT" -bb $SPEC_FILE
|
||||
|
||||
mkdir -p $OUTPUT_DIR
|
||||
cp -fr $RPM_DIR/* $OUTPUT_DIR/
|
||||
find $RPM_DIR -type f | while read f; do
|
||||
d="$(dirname "$f")"
|
||||
d="$OUTPUT_DIR/${d#$RPM_DIR}"
|
||||
mkdir -p "$d"
|
||||
cp $f $d
|
||||
done
|
||||
|
||||
rm -fr $BUILDROOT
|
||||
|
||||
File diff suppressed because one or more lines are too long
44
cmd/climc/shell/associated_bills.go
Normal file
44
cmd/climc/shell/associated_bills.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type AssociatedBillListOptions struct {
|
||||
options.BaseListOptions
|
||||
StartDay int `help:"time range of the associated bills, example: 20060102" required:"true"`
|
||||
EndDay int `help:"time range of the associated bills, example: 20060102" required:"true"`
|
||||
|
||||
ResourceId string `help:"resource id"`
|
||||
}
|
||||
R(&AssociatedBillListOptions{}, "associated-bill-list", "List associated bills",
|
||||
func(s *mcclient.ClientSession, args *AssociatedBillListOptions) error {
|
||||
params, err := options.ListStructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.AssociatedBills.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.AssociatedBills.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -21,10 +21,12 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
objectshell "yunion.io/x/onecloud/pkg/multicloud/objectstore"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -105,9 +107,11 @@ func init() {
|
||||
})
|
||||
|
||||
type BucketListObjectsOptions struct {
|
||||
ID string `help:"ID or name of bucket" json:"-"`
|
||||
Prefix string `help:"List objects with prefix"`
|
||||
Recursive bool `help:"List objects recursively"`
|
||||
ID string `help:"ID or name of bucket" json:"-"`
|
||||
Prefix string `help:"List objects with prefix"`
|
||||
Recursive bool `help:"List objects recursively"`
|
||||
Limit int `help:"maximal items per request"`
|
||||
PagingMarker string `help:"paging marker"`
|
||||
}
|
||||
R(&BucketListObjectsOptions{}, "bucket-object-list", "List objects in a bucket", func(s *mcclient.ClientSession, args *BucketListObjectsOptions) error {
|
||||
params, err := options.StructToParams(args)
|
||||
@@ -119,8 +123,11 @@ func init() {
|
||||
return err
|
||||
}
|
||||
|
||||
arrays, _ := result.GetArray("objects")
|
||||
listResult := modulebase.ListResult{Data: arrays}
|
||||
listResult := modulebase.ListResult{}
|
||||
err = result.Unmarshal(&listResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(&listResult, []string{})
|
||||
return nil
|
||||
})
|
||||
@@ -159,9 +166,10 @@ func init() {
|
||||
Path string `help:"Path to file to upload" required:"true"`
|
||||
|
||||
ContentLength int64 `help:"Content lenght (bytes)" default:"-1"`
|
||||
ContentType string `help:"Content type"`
|
||||
StorageClass string `help:"storage CLass"`
|
||||
Acl string `help:"object acl." choices:"private|public-read|public-read-write"`
|
||||
|
||||
objectshell.ObjectHeaderOptions
|
||||
}
|
||||
R(&BucketUploadObjectsOptions{}, "bucket-object-upload", "Upload an object into a bucket", func(s *mcclient.ClientSession, args *BucketUploadObjectsOptions) error {
|
||||
var body io.Reader
|
||||
@@ -187,7 +195,9 @@ func init() {
|
||||
return fmt.Errorf("required content-length")
|
||||
}
|
||||
|
||||
err := modules.Buckets.Upload(s, args.ID, args.KEY, body, args.ContentLength, args.ContentType, args.StorageClass, args.Acl)
|
||||
meta := args.ObjectHeaderOptions.Options2Header()
|
||||
|
||||
err := modules.Buckets.Upload(s, args.ID, args.KEY, body, args.ContentLength, args.StorageClass, args.Acl, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -290,4 +300,27 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type BucketSetMetadataOptions struct {
|
||||
ID string `help:"ID or name of bucket" json:"-"`
|
||||
|
||||
Key []string `help:"Optional object key" json:"key"`
|
||||
|
||||
objectshell.ObjectHeaderOptions
|
||||
}
|
||||
R(&BucketSetMetadataOptions{}, "bucket-set-metadata", "Set metadata of object", func(s *mcclient.ClientSession, args *BucketSetMetadataOptions) error {
|
||||
input := api.BucketMetadataInput{}
|
||||
input.Key = args.Key
|
||||
input.Metadata = args.ObjectHeaderOptions.Options2Header()
|
||||
err := input.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Buckets.PerformAction(s, args.ID, "metadata", jsonutils.Marshal(input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
@@ -86,6 +87,19 @@ func init() {
|
||||
R(&options.SAliyunCloudAccountCreateOptions{}, "cloud-account-create-aliyun", "Create an Aliyun cloud account", func(s *mcclient.ClientSession, args *options.SAliyunCloudAccountCreateOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Aliyun"), "provider")
|
||||
options := jsonutils.NewDict()
|
||||
if len(args.OptionsBillingReportBucket) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingReportBucket), "billing_report_bucket")
|
||||
}
|
||||
if len(args.OptionsBillingBucketAccount) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingBucketAccount), "billing_bucket_account")
|
||||
}
|
||||
if len(args.OptionsBillingFilePrefix) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingFilePrefix), "billing_file_prefix")
|
||||
}
|
||||
if options.Size() > 0 {
|
||||
params.(*jsonutils.JSONDict).Add(options, "options")
|
||||
}
|
||||
result, err := modules.Cloudaccounts.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -122,6 +136,12 @@ func init() {
|
||||
if len(args.OptionsBillingReportBucket) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingReportBucket), "billing_report_bucket")
|
||||
}
|
||||
if len(args.OptionsBillingBucketAccount) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingBucketAccount), "billing_bucket_account")
|
||||
}
|
||||
if len(args.OptionsBillingFilePrefix) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingFilePrefix), "billing_file_prefix")
|
||||
}
|
||||
if options.Size() > 0 {
|
||||
params.Add(options, "options")
|
||||
}
|
||||
@@ -244,6 +264,34 @@ func init() {
|
||||
if params.Size() == 0 {
|
||||
return InvalidUpdateError()
|
||||
}
|
||||
|
||||
options := jsonutils.NewDict()
|
||||
if len(args.OptionsBillingReportBucket) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingReportBucket), "billing_report_bucket")
|
||||
}
|
||||
if len(args.OptionsBillingBucketAccount) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingBucketAccount), "billing_bucket_account")
|
||||
}
|
||||
if len(args.OptionsBillingFilePrefix) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingFilePrefix), "billing_file_prefix")
|
||||
}
|
||||
if options.Size() > 0 {
|
||||
params.Add(options, "options")
|
||||
}
|
||||
removeOptions := make([]string, 0)
|
||||
if args.RemoveOptionsBillingReportBucket {
|
||||
removeOptions = append(removeOptions, "billing_report_bucket")
|
||||
}
|
||||
if args.RemoveOptionsBillingBucketAccount {
|
||||
removeOptions = append(removeOptions, "billing_bucket_account")
|
||||
}
|
||||
if args.RemoveOptionsBillingFilePrefix {
|
||||
removeOptions = append(removeOptions, "billing_file_prefix")
|
||||
}
|
||||
if len(removeOptions) > 0 {
|
||||
params.Add(jsonutils.NewStringArray(removeOptions), "remove_options")
|
||||
}
|
||||
|
||||
result, err := modules.Cloudaccounts.Update(s, args.ID, params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -301,6 +349,12 @@ func init() {
|
||||
if len(args.OptionsBillingReportBucket) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingReportBucket), "billing_report_bucket")
|
||||
}
|
||||
if len(args.OptionsBillingBucketAccount) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingBucketAccount), "billing_bucket_account")
|
||||
}
|
||||
if len(args.OptionsBillingFilePrefix) > 0 {
|
||||
options.Add(jsonutils.NewString(args.OptionsBillingFilePrefix), "billing_file_prefix")
|
||||
}
|
||||
if options.Size() > 0 {
|
||||
params.Add(options, "options")
|
||||
}
|
||||
@@ -308,6 +362,12 @@ func init() {
|
||||
if args.RemoveOptionsBillingReportBucket {
|
||||
removeOptions = append(removeOptions, "billing_report_bucket")
|
||||
}
|
||||
if args.RemoveOptionsBillingBucketAccount {
|
||||
removeOptions = append(removeOptions, "billing_bucket_account")
|
||||
}
|
||||
if args.RemoveOptionsBillingFilePrefix {
|
||||
removeOptions = append(removeOptions, "billing_file_prefix")
|
||||
}
|
||||
if len(removeOptions) > 0 {
|
||||
params.Add(jsonutils.NewStringArray(removeOptions), "remove_options")
|
||||
}
|
||||
@@ -653,4 +713,19 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type CloudaccountShareModeOptions struct {
|
||||
ID string `help:"ID or name of cloud account"`
|
||||
MODE string `help:"cloud account share mode" choices:"account_domain|system|provider_domain"`
|
||||
}
|
||||
R(&CloudaccountShareModeOptions{}, "cloud-account-share-mode", "Set share_mode of a cloud account", func(s *mcclient.ClientSession, args *CloudaccountShareModeOptions) error {
|
||||
input := api.CloudaccountShareModeInput{}
|
||||
input.ShareMode = args.MODE
|
||||
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "share-mode", jsonutils.Marshal(input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ func init() {
|
||||
* 操作用户的通信地址(如果用户的通信地址不存在则进行添加;如果已存在则进行修改;如果设置空则进行删除。)
|
||||
*/
|
||||
type ContactsUpdateOptions struct {
|
||||
UID string `help:"The user you wanna add contact to (Keystone User ID)"`
|
||||
CONTACTTYPE string `help:"The contact type email|mobile" choices:"email|mobile|dingtalk"`
|
||||
CONTACT string `help:"The contacts details mobile number or email address or dingtalk's userid, if set it the empty str means delete"`
|
||||
Status string `help:"Enabled or disabled contact status" choices:"enable|disable"`
|
||||
UpdateDingtalk bool `help:"if update dingtalk"`
|
||||
UID string `help:"The user you wanna add contact to (Keystone User ID)"`
|
||||
CONTACTTYPE string `help:"The contact type email|mobile" choices:"email|mobile|dingtalk"`
|
||||
CONTACT string `help:"The contacts details mobile number or email address or dingtalk's userid, if set it the empty str means delete"`
|
||||
Status string `help:"Enabled or disabled contact status" choices:"enable|disable"`
|
||||
Pull []string `help:"pull some subcontacts(e.g., dingtalk, feishu, etc) related to mobile"`
|
||||
}
|
||||
R(&ContactsUpdateOptions{}, "contact-update", "Create, delete or update contact for user", func(s *mcclient.ClientSession, args *ContactsUpdateOptions) error {
|
||||
arr := jsonutils.NewArray()
|
||||
@@ -52,12 +52,14 @@ func init() {
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(arr, "contacts")
|
||||
if args.UpdateDingtalk {
|
||||
params.Add(jsonutils.JSONTrue, "update_dingtalk")
|
||||
|
||||
pulls := jsonutils.NewArray()
|
||||
for _, pull := range args.Pull {
|
||||
pulls.Add(jsonutils.NewString(pull))
|
||||
}
|
||||
params.Add(pulls, "pull")
|
||||
|
||||
contact, err := modules.Contacts.PerformAction(s, args.UID, "update-contact", params)
|
||||
|
||||
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,6 +68,22 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type ContactsPullOptions struct {
|
||||
UID string `help:"The user you wanna pull contact"`
|
||||
CONTACTTYPE string `help:"The contact type"`
|
||||
}
|
||||
R(&ContactsPullOptions{}, "contact-pull", "Pull contact", func(s *mcclient.ClientSession, args *ContactsPullOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("contacts", jsonutils.NewArray())
|
||||
params.Set("pull", jsonutils.NewArray(jsonutils.NewString(args.CONTACTTYPE)))
|
||||
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(contact)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ContactsDeleteOptions struct {
|
||||
UID string `help:"The user you wanna add contact to (Keystone User ID)"`
|
||||
CONTACTTYPE string `help:"The contact type email|mobile|dingtalk" choices:"email|mobile|dingtalk"`
|
||||
@@ -78,7 +96,7 @@ func init() {
|
||||
arr.Add(tmpObj)
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(arr, "contacts")
|
||||
contact, err := modules.Contacts.PerformAction(s, args.UID, "update-contact", params)
|
||||
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -133,7 +151,7 @@ func init() {
|
||||
|
||||
params.Add(jsonutils.JSONTrue, "details")
|
||||
|
||||
result, err := modules.Contacts.Get(s, args.UID, params)
|
||||
result, err := modules.Contacts.CustomizedGet(s, args.UID, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -166,19 +184,10 @@ func init() {
|
||||
CONTACT string `help:"The contacts details mobile number or email address"`
|
||||
}
|
||||
R(&ContactsVerifyOptions{}, "contact-verify-trigger", "Trigger contact verify", func(s *mcclient.ClientSession, args *ContactsVerifyOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.CONTACT_TYPE), "contact_type")
|
||||
params.Add(jsonutils.NewString(args.CONTACT), "contact")
|
||||
/*
|
||||
if len(args.Email) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Email), "email")
|
||||
}
|
||||
if len(args.Mobile) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Mobile), "mobile")
|
||||
}
|
||||
*/
|
||||
|
||||
_, err := modules.Contacts.PerformAction(s, args.UID, "verify", params)
|
||||
tmpDict := jsonutils.NewDict()
|
||||
tmpDict.Add(jsonutils.NewString(args.CONTACT_TYPE), "contact_type")
|
||||
tmpDict.Add(jsonutils.NewString(args.CONTACT), "contact")
|
||||
_, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "verify", tmpDict)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
64
cmd/climc/shell/dbinstance_accounts.go
Normal file
64
cmd/climc/shell/dbinstance_accounts.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type DBInstanceAccountListOptions struct {
|
||||
options.BaseListOptions
|
||||
DBInstance string `help:"ID or Name of DBInstance" json:"dbinstance"`
|
||||
}
|
||||
R(&DBInstanceAccountListOptions{}, "dbinstance-account-list", "List DB instance accounts", func(s *mcclient.ClientSession, opts *DBInstanceAccountListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result, err := modules.DBInstanceAccounts.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.DBInstanceAccounts.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type DBInstanceAccountIdOptions struct {
|
||||
ID string `help:"ID or Name of DBInstanceaccount"`
|
||||
}
|
||||
|
||||
R(&DBInstanceAccountIdOptions{}, "dbinstance-account-show", "Show DB instance account", func(s *mcclient.ClientSession, opts *DBInstanceAccountIdOptions) error {
|
||||
account, err := modules.DBInstanceAccounts.Get(s, opts.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(account)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DBInstanceAccountIdOptions{}, "dbinstance-account-delete", "Delete DB instance account", func(s *mcclient.ClientSession, opts *DBInstanceAccountIdOptions) error {
|
||||
account, err := modules.DBInstanceAccounts.Delete(s, opts.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(account)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -312,37 +312,6 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DBInstanceAccountListOptions struct {
|
||||
options.BaseListOptions
|
||||
DBInstance string `help:"ID or Name of DBInstance" json:"dbinstance"`
|
||||
}
|
||||
R(&DBInstanceAccountListOptions{}, "dbinstance-account-list", "List DB instance accounts", func(s *mcclient.ClientSession, opts *DBInstanceAccountListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result, err := modules.DBInstanceAccounts.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.DBInstanceAccounts.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type DBInstanceAccountIdOptions struct {
|
||||
ID string `help:"ID or Name of DBInstanceaccount"`
|
||||
}
|
||||
|
||||
R(&DBInstanceAccountIdOptions{}, "dbinstance-account-show", "Show DB instance account", func(s *mcclient.ClientSession, opts *DBInstanceAccountIdOptions) error {
|
||||
account, err := modules.DBInstanceAccounts.Get(s, opts.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(account)
|
||||
return nil
|
||||
})
|
||||
|
||||
type DBInstancePrivilegeListOptions struct {
|
||||
options.BaseListOptions
|
||||
DBInstanceaccount string `help:"ID or Name of DBInstanceaccount" json:"dbinstanceaccount"`
|
||||
@@ -362,4 +331,21 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DBInstanceChangeOwnerOptions struct {
|
||||
ID string `help:"DBInstance to change owner" json:"-"`
|
||||
PROJECT string `help:"Project ID or change" json:"tenant"`
|
||||
}
|
||||
R(&DBInstanceChangeOwnerOptions{}, "dbinstance-change-owner", "Change owner porject of a dbinstance", func(s *mcclient.ClientSession, opts *DBInstanceChangeOwnerOptions) error {
|
||||
params, err := options.StructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.DBInstance.PerformAction(s, opts.ID, "change-owner", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
users, err := modules.Groups.GetUsers(s, grpId)
|
||||
users, err := modules.Groups.GetUsers(s, grpId, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ func init() {
|
||||
|
||||
Uuid string `help:"find host with given system uuid"`
|
||||
|
||||
CdromBoot *bool `help:"filter hosts list by cdrom_boot=true|false"`
|
||||
|
||||
options.BaseListOptions
|
||||
}
|
||||
R(&HostListOptions{}, "host-list", "List hosts", func(s *mcclient.ClientSession, opts *HostListOptions) error {
|
||||
@@ -133,6 +135,12 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&HostOpsOptions{}, "host-sync-config", "Synchronize config of a host", func(s *mcclient.ClientSession, args *HostOpsOptions) error {
|
||||
results := modules.Hosts.BatchPerformAction(s, args.ID, "sync-config", nil)
|
||||
printBatchResults(results, modules.Hosts.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&HostOpsOptions{}, "host-prepare", "Prepare a host for installation", func(s *mcclient.ClientSession, args *HostOpsOptions) error {
|
||||
results := modules.Hosts.BatchPerformAction(s, args.ID, "prepare", nil)
|
||||
printBatchResults(results, modules.Hosts.GetColumns(s))
|
||||
@@ -200,6 +208,10 @@ func init() {
|
||||
// AccessIp string `help:"Change access ip, CAUTION!!!!"`
|
||||
AccessMac string `help:"Change baremetal access MAC, CAUTION!!!!"`
|
||||
Uuid string `help:"Change baremetal UUID, CAUTION!!!!"`
|
||||
|
||||
IpmiUsername string `help:"IPMI user"`
|
||||
IpmiPassword string `help:"IPMI password"`
|
||||
IpmiIpAddr string `help:"IPMI ip_addr"`
|
||||
}
|
||||
R(&HostUpdateOptions{}, "host-update", "Update information of a host", func(s *mcclient.ClientSession, args *HostUpdateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -230,6 +242,15 @@ func init() {
|
||||
if len(args.Uuid) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Uuid), "uuid")
|
||||
}
|
||||
if len(args.IpmiUsername) > 0 {
|
||||
params.Add(jsonutils.NewString(args.IpmiUsername), "ipmi_username")
|
||||
}
|
||||
if len(args.IpmiPassword) > 0 {
|
||||
params.Add(jsonutils.NewString(args.IpmiPassword), "ipmi_password")
|
||||
}
|
||||
if len(args.IpmiIpAddr) > 0 {
|
||||
params.Add(jsonutils.NewString(args.IpmiIpAddr), "ipmi_ip_addr")
|
||||
}
|
||||
if params.Size() == 0 {
|
||||
return fmt.Errorf("Not data to update")
|
||||
}
|
||||
@@ -352,16 +373,16 @@ func init() {
|
||||
ID string `help:"ID or Name of host"`
|
||||
WIRE string `help:"ID or Name of wire to attach"`
|
||||
MAC string `help:"Mac address of NIC"`
|
||||
INDEX int64 `help:"nic index"`
|
||||
Type string `help:"Nic type" choices:"admin|ipmi"`
|
||||
IpAddr string `help:"IP address"`
|
||||
Index int64 `help:"nic index" default:"-1"`
|
||||
}
|
||||
R(&HostAddNetIfOptions{}, "host-add-netif", "Host add a NIC", func(s *mcclient.ClientSession, args *HostAddNetIfOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.WIRE), "wire")
|
||||
params.Add(jsonutils.NewString(args.MAC), "mac")
|
||||
params.Add(jsonutils.JSONTrue, "link_up")
|
||||
params.Add(jsonutils.NewInt(args.Index), "index")
|
||||
params.Add(jsonutils.NewInt(args.INDEX), "index")
|
||||
if len(args.Type) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Type), "nic_type")
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -165,8 +166,8 @@ func init() {
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
R(&GuestImageOptions{}, "guest-image-mark-unprotected", "Mark image protected", func(s *mcclient.ClientSession,
|
||||
args *GuestImageOptions) error {
|
||||
|
||||
@@ -178,7 +179,55 @@ func init() {
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
type GuestImageOperationOptions struct {
|
||||
ID []string `help:"Guest Image ID or Name"`
|
||||
}
|
||||
|
||||
type GuestImagePublicOptions struct {
|
||||
GuestImageOperationOptions
|
||||
Scope string `help:"sharing scope" choices:"system|domain"`
|
||||
ShareToProject []string `help:"Share to prject"`
|
||||
}
|
||||
|
||||
R(&GuestImageOperationOptions{}, "guest-image-private", "Make a guest image private",
|
||||
func(s *mcclient.ClientSession, args *GuestImageOperationOptions) error {
|
||||
if len(args.ID) == 0 {
|
||||
return errors.Error("No guest image ID provided")
|
||||
} else if len(args.ID) == 1 {
|
||||
result, err := modules.GuestImages.PerformAction(s, args.ID[0], "private", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
} else {
|
||||
results := modules.GuestImages.BatchPerformAction(s, args.ID, "private", nil)
|
||||
printBatchResults(results, modules.GuestImages.GetColumns(s))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
R(&GuestImagePublicOptions{}, "guest-image-public", "Make a guest image public",
|
||||
func(s *mcclient.ClientSession, args *GuestImagePublicOptions) error {
|
||||
params, err := options.StructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(args.ID) == 0 {
|
||||
return errors.Error("No guest image ID provided")
|
||||
} else if len(args.ID) == 1 {
|
||||
result, err := modules.GuestImages.PerformAction(s, args.ID[0], "public", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
} else {
|
||||
results := modules.GuestImages.BatchPerformAction(s, args.ID, "public", params)
|
||||
printBatchResults(results, modules.GuestImages.GetColumns(s))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ func init() {
|
||||
IsPublic string `help:"filter images public or not(True, False or None)" choices:"true|false"`
|
||||
IsStandard string `help:"filter images standard or non-standard" choices:"true|false"`
|
||||
Protected string `help:"filter images by protected" choices:"true|false"`
|
||||
IsUefi bool `help:"list uefi image"`
|
||||
Format []string `help:"Disk formats"`
|
||||
Name string `help:"Name filter"`
|
||||
}
|
||||
@@ -155,6 +156,9 @@ func init() {
|
||||
if len(args.Protected) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Protected), "protected")
|
||||
}
|
||||
if args.IsUefi {
|
||||
params.Add(jsonutils.JSONTrue, "uefi")
|
||||
}
|
||||
if len(args.Tenant) > 0 {
|
||||
tid, e := modules.Projects.GetId(s, args.Tenant, nil)
|
||||
if e != nil {
|
||||
|
||||
@@ -89,4 +89,11 @@ func init() {
|
||||
printObject(lblistenerrule)
|
||||
return nil
|
||||
})
|
||||
R(&options.LoadbalancerListenerRuleGetBackendStatusOptions{}, "lblistenerrule-backend-status", "Get lblistenerrule backend status", func(s *mcclient.ClientSession, opts *options.LoadbalancerListenerRuleGetBackendStatusOptions) error {
|
||||
backendStatus, err := modules.LoadbalancerListenerRules.GetSpecific(s, opts.ID, "backend-status", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printLbBackendStatus(backendStatus)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,13 +15,44 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func printLbBackendStatus(backendStatus jsonutils.JSONObject) error {
|
||||
arr, ok := backendStatus.(*jsonutils.JSONArray)
|
||||
if !ok {
|
||||
return fmt.Errorf("want json array, got %s", backendStatus.String())
|
||||
}
|
||||
objList, err := arr.GetArray()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listResult := &modulebase.ListResult{
|
||||
Data: objList,
|
||||
}
|
||||
columns := []string{
|
||||
"id",
|
||||
"name",
|
||||
"backend_type",
|
||||
"backend_id",
|
||||
"address",
|
||||
"port",
|
||||
"weight",
|
||||
"check_time",
|
||||
"check_status",
|
||||
"check_code",
|
||||
}
|
||||
printList(listResult, columns)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
R(&options.LoadbalancerListenerCreateOptions{}, "lblistener-create", "Create lblistener", func(s *mcclient.ClientSession, opts *options.LoadbalancerListenerCreateOptions) error {
|
||||
@@ -99,4 +130,11 @@ func init() {
|
||||
printObject(lblistener)
|
||||
return nil
|
||||
})
|
||||
R(&options.LoadbalancerListenerGetBackendStatusOptions{}, "lblistener-backend-status", "Get lblistene backend status", func(s *mcclient.ClientSession, opts *options.LoadbalancerListenerGetBackendStatusOptions) error {
|
||||
backendStatus, err := modules.LoadbalancerListeners.GetSpecific(s, opts.ID, "backend-status", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printLbBackendStatus(backendStatus)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -418,7 +418,7 @@ func init() {
|
||||
})
|
||||
|
||||
type NetworkAddressOptions struct {
|
||||
NETWORK string `help:"if of network to query"`
|
||||
NETWORK string `help:"id or name of network to query"`
|
||||
}
|
||||
R(&NetworkAddressOptions{}, "network-addresses", "Query used addresses of network", func(s *mcclient.ClientSession, args *NetworkAddressOptions) error {
|
||||
result, err := modules.Networks.GetSpecific(s, args.NETWORK, "addresses", nil)
|
||||
@@ -433,4 +433,31 @@ func init() {
|
||||
printList(&listResult, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkSyncOptions struct {
|
||||
NETWORK string `help:"id or name of network to sync"`
|
||||
}
|
||||
R(&NetworkSyncOptions{}, "network-sync", "Sync network status", func(s *mcclient.ClientSession, args *NetworkSyncOptions) error {
|
||||
result, err := modules.Networks.PerformAction(s, args.NETWORK, "sync", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NetworkStatusOptions struct {
|
||||
NETWORK string `help:"id or name of network to sync" json:"-"`
|
||||
STATUS string `help:"status of network" choices:"available|unavailable" json:"status"`
|
||||
Reason string `help:"reason to change status" json:"reason"`
|
||||
}
|
||||
R(&NetworkStatusOptions{}, "network-status", "Set on-premise network status", func(s *mcclient.ClientSession, args *NetworkStatusOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, err := modules.Networks.PerformAction(s, args.NETWORK, "status", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -29,20 +29,26 @@ func init() {
|
||||
*/
|
||||
|
||||
type NotificationCreateOptions struct {
|
||||
Uid []string `help:"The user you wanna sent to (Keystone User ID)"`
|
||||
CONTACTTYPE string `help:"User's contacts type" choices:"email|mobile|dingtalk|webconsole"`
|
||||
TOPIC string `help:"Title or topic of the notification"`
|
||||
PRIORITY string `help:"Priority of the notification" choices:"normal|important|fatal"`
|
||||
MSG string `help:"The content of the notification"`
|
||||
Remark string `help:"Remark or description of the notification"`
|
||||
Group bool `help:"Send to group"`
|
||||
CONTACTTYPE string `help:"User's contacts type"`
|
||||
TOPIC string `help:"Title or topic of the notification"`
|
||||
PRIORITY string `help:"Priority of the notification" choices:"normal|important|fatal"`
|
||||
MSG string `help:"The content of the notification"`
|
||||
Remark string `help:"Remark or description of the notification"`
|
||||
Group bool `help:"Send to group"`
|
||||
}
|
||||
R(&NotificationCreateOptions{}, "notify", "Send a notification to sb", func(s *mcclient.ClientSession, args *NotificationCreateOptions) error {
|
||||
type NotificationCreateSingleOptions struct {
|
||||
UID string `help:"The user you wanna sent to (Keystone User ID)"`
|
||||
NotificationCreateOptions
|
||||
}
|
||||
|
||||
R(&NotificationCreateSingleOptions{}, "notify", "Send a notification to someone", func(s *mcclient.ClientSession,
|
||||
args *NotificationCreateSingleOptions) error {
|
||||
|
||||
msg := notify.SNotifyMessage{}
|
||||
if args.Group {
|
||||
msg.Gid = args.Uid
|
||||
msg.Gid = []string{args.UID}
|
||||
} else {
|
||||
msg.Uid = args.Uid
|
||||
msg.Uid = []string{args.UID}
|
||||
}
|
||||
|
||||
msg.ContactType = notify.TNotifyChannel(args.CONTACTTYPE)
|
||||
@@ -57,6 +63,35 @@ func init() {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type NotificationCreateMultiOptions struct {
|
||||
Uid []string `help:"The user you wanna sent to (Keystone User ID)"`
|
||||
NotificationCreateOptions
|
||||
}
|
||||
|
||||
R(&NotificationCreateMultiOptions{}, "notify-batch", "Send a notification to someones",
|
||||
func(s *mcclient.ClientSession, args *NotificationCreateMultiOptions) error {
|
||||
|
||||
msg := notify.SNotifyMessage{}
|
||||
if args.Group {
|
||||
msg.Gid = args.Uid
|
||||
} else {
|
||||
msg.Uid = args.Uid
|
||||
}
|
||||
|
||||
msg.ContactType = notify.TNotifyChannel(args.CONTACTTYPE)
|
||||
msg.Topic = args.TOPIC
|
||||
msg.Priority = notify.TNotifyPriority(args.PRIORITY)
|
||||
msg.Msg = args.MSG
|
||||
msg.Remark = args.Remark
|
||||
|
||||
err := notify.Notifications.Send(s, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
/**
|
||||
* 发送全局通知
|
||||
*/
|
||||
@@ -72,7 +107,7 @@ func init() {
|
||||
R(&NotificationBroadcastOptions{}, "notify-broadcast", "Send a notification to all online users", func(s *mcclient.ClientSession, args *NotificationBroadcastOptions) error {
|
||||
msg := notify.SNotifyMessage{}
|
||||
msg.Broadcast = true
|
||||
msg.ContactType = notify.TNotifyChannel("webconsole")
|
||||
msg.ContactType = notify.NotifyByWebConsole
|
||||
msg.Topic = args.Topic
|
||||
msg.Priority = notify.TNotifyPriority(args.Priority)
|
||||
msg.Msg = args.Msg
|
||||
|
||||
@@ -34,7 +34,24 @@ func init() {
|
||||
}
|
||||
body := jsonutils.NewDict()
|
||||
body.Add(tmp, args.CONTACTTYPE)
|
||||
modules.Configs.Create(s, body)
|
||||
ret, err := modules.Configs.Create(s, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
R(&ConfigCreate2Options{}, "notify-config-validate", "config validate", func(s *mcclient.ClientSession,
|
||||
args *ConfigCreate2Options) error {
|
||||
tmp := jsonutils.NewDict()
|
||||
for i := 0; i+1 < len(args.CONFIGS); i += 2 {
|
||||
tmp.Add(jsonutils.NewString(args.CONFIGS[i+1]), args.CONFIGS[i])
|
||||
}
|
||||
ret, err := modules.Configs.PerformAction(s, args.CONTACTTYPE, "validate", tmp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
90
cmd/climc/shell/notify_template.go
Normal file
90
cmd/climc/shell/notify_template.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type NotifyTemplateUpdateOptions struct {
|
||||
CONTACTTYPE string `help:"the contanct type, such as 'email', 'mobile'"`
|
||||
TOPIC string `help:"the topic of temlate, such as 'VERIFY', 'ALARM'"`
|
||||
TEMPLATETYPE string `help:"the type of template" choices:"content|title|remote"`
|
||||
CONTENT string `help:"the content of template"`
|
||||
}
|
||||
R(&NotifyTemplateUpdateOptions{}, "notify-template-update", "Create, update contact for user", func(s *mcclient.ClientSession,
|
||||
args *NotifyTemplateUpdateOptions) error {
|
||||
arr := jsonutils.NewArray()
|
||||
tmpObj := jsonutils.NewDict()
|
||||
tmpObj.Add(jsonutils.NewString(args.TOPIC), "topic")
|
||||
tmpObj.Add(jsonutils.NewString(args.TEMPLATETYPE), "template_type")
|
||||
tmpObj.Add(jsonutils.NewString(args.CONTENT), "content")
|
||||
arr.Add(tmpObj)
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(arr, "notifytemplates")
|
||||
|
||||
contact, err := modules.NotifyTemplates.PerformAction(s, args.CONTACTTYPE, "update-template", params)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printObject(contact)
|
||||
return nil
|
||||
})
|
||||
|
||||
type NotifyTemplateDeleteOptions struct {
|
||||
CONTACTTYPE string `help:"the contanct type, such as 'email', 'mobile'"`
|
||||
Topic string `help:"the topic of temlate, such as 'VERIFY', 'ALARM'"`
|
||||
}
|
||||
|
||||
R(&NotifyTemplateDeleteOptions{}, "notify-template-delete", "delete notify template",
|
||||
func(s *mcclient.ClientSession, args *NotifyTemplateDeleteOptions) error {
|
||||
|
||||
tmpObj := jsonutils.NewDict()
|
||||
tmpObj.Add(jsonutils.NewString(args.CONTACTTYPE), "contact_type")
|
||||
tmpObj.Add(jsonutils.NewString(args.Topic), "topic")
|
||||
_, err := modules.NotifyTemplates.DeleteContents(s, tmpObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type NotifyTemplateListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
R(&NotifyTemplateListOptions{}, "notify-template-list", "List all notify template",
|
||||
func(s *mcclient.ClientSession, args *NotifyTemplateListOptions) error {
|
||||
|
||||
params, err := args.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.NotifyTemplates.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.NotifyTemplates.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -28,6 +28,7 @@ func init() {
|
||||
NOTES string `help:"Why reserve this IP"`
|
||||
IPS []string `help:"IPs to reserve"`
|
||||
Duration string `help:"reservation duration, e.g. 1I, 1H, 2M"`
|
||||
Status string `help:"ip status"`
|
||||
}
|
||||
R(&NetworkReserveIPOptions{}, "network-reserve-ip", "Reserve an IP address from pool", func(s *mcclient.ClientSession, args *NetworkReserveIPOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -36,6 +37,9 @@ func init() {
|
||||
if len(args.Duration) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Duration), "duration")
|
||||
}
|
||||
if len(args.Status) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Status), "status")
|
||||
}
|
||||
net, err := modules.Networks.PerformAction(s, args.NETWORK, "reserve-ip", params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -177,6 +177,19 @@ func init() {
|
||||
},
|
||||
)
|
||||
|
||||
R(&options.ServerCreateOptions{}, "server-check-create-data", "Check create server data", func(s *mcclient.ClientSession, opts *options.ServerCreateOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
server, err := modules.Servers.PerformClassAction(s, "check-create-data", params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(server)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.ServerCreateOptions{}, "server-create", "Create a server", func(s *mcclient.ClientSession, opts *options.ServerCreateOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
|
||||
@@ -163,8 +163,16 @@ func init() {
|
||||
|
||||
type ServiceConfigOptions struct {
|
||||
SERVICE string `help:"service name or id"`
|
||||
Config []string `help:"config key=value pair"`
|
||||
Remove bool `help:"remove config"`
|
||||
Config []string `help:"config options, can be a JSON, a YAML or a key=value pair, e.g:
|
||||
* JSON
|
||||
'{\"default\":{\"password_expiration_seconds\":300}}'
|
||||
* YAML
|
||||
default:
|
||||
password_expiration_seconds: 300
|
||||
* A key=value pair (under default section)
|
||||
password_expiration_seconds=300
|
||||
"`
|
||||
Remove bool `help:"remove config"`
|
||||
}
|
||||
R(&ServiceConfigOptions{}, "service-config", "Add config to service", func(s *mcclient.ClientSession, args *ServiceConfigOptions) error {
|
||||
config := jsonutils.NewDict()
|
||||
@@ -174,6 +182,24 @@ func init() {
|
||||
config.Add(jsonutils.NewString("update"), "action")
|
||||
}
|
||||
for _, c := range args.Config {
|
||||
json, _ := jsonutils.ParseString(c)
|
||||
if json != nil {
|
||||
if _, ok := json.(*jsonutils.JSONDict); ok {
|
||||
subconf := jsonutils.NewDict()
|
||||
subconf.Add(json, "config")
|
||||
config.Update(subconf)
|
||||
continue
|
||||
}
|
||||
}
|
||||
yaml, _ := jsonutils.ParseYAML(c)
|
||||
if yaml != nil {
|
||||
if _, ok := yaml.(*jsonutils.JSONDict); ok {
|
||||
subconf := jsonutils.NewDict()
|
||||
subconf.Add(yaml, "config")
|
||||
config.Update(subconf)
|
||||
continue
|
||||
}
|
||||
}
|
||||
pos := strings.IndexByte(c, '=')
|
||||
if pos < 0 {
|
||||
return fmt.Errorf("%s is not a key=value pair", c)
|
||||
|
||||
@@ -44,16 +44,13 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&TaskListOptions{}, "region-task-list", "List tasks on region server", func(s *mcclient.ClientSession, suboptions *TaskListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = suboptions.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
type RegionTaskListOptions struct {
|
||||
ObjName string `help:"object name"`
|
||||
ObjId string `help:"object id"`
|
||||
TaskName string `help:"task name"`
|
||||
}
|
||||
R(&RegionTaskListOptions{}, "region-task-list", "List tasks on region server", func(s *mcclient.ClientSession, args *RegionTaskListOptions) error {
|
||||
params := jsonutils.Marshal(args)
|
||||
result, err := modules.ComputeTasks.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -149,15 +149,15 @@ func init() {
|
||||
})
|
||||
|
||||
type UserCreateOptions struct {
|
||||
NAME string `help:"Name of the new user"`
|
||||
Domain string `help:"Domain"`
|
||||
Desc string `help:"Description"`
|
||||
Password string `help:"Password"`
|
||||
Displayname string `help:"Displayname"`
|
||||
Email string `help:"Email"`
|
||||
Mobile string `help:"Mobile"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
NAME string `help:"Name of the new user"`
|
||||
Domain string `help:"Domain"`
|
||||
Desc string `help:"Description"`
|
||||
Password *string `help:"Password"`
|
||||
Displayname string `help:"Displayname"`
|
||||
Email string `help:"Email"`
|
||||
Mobile string `help:"Mobile"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
|
||||
// DefaultProject string `help:"Default project"`
|
||||
SystemAccount bool `help:"is a system account?"`
|
||||
@@ -174,8 +174,8 @@ func init() {
|
||||
}
|
||||
params.Add(jsonutils.NewString(domainId), "domain_id")
|
||||
}
|
||||
if len(args.Password) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Password), "password")
|
||||
if args.Password != nil {
|
||||
params.Add(jsonutils.NewString(*args.Password), "password")
|
||||
}
|
||||
if len(args.Displayname) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Displayname), "displayname")
|
||||
@@ -222,16 +222,16 @@ func init() {
|
||||
})
|
||||
|
||||
type UserUpdateOptions struct {
|
||||
ID string `help:"ID or name of the user"`
|
||||
Domain string `help:"Domain"`
|
||||
Name string `help:"New name of the user"`
|
||||
Password string `help:"New password"`
|
||||
Desc string `help:"Description"`
|
||||
Displayname string `help:"Displayname"`
|
||||
Email string `help:"Email"`
|
||||
Mobile string `help:"Mobile"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
ID string `help:"ID or name of the user"`
|
||||
Domain string `help:"Domain"`
|
||||
Name string `help:"New name of the user"`
|
||||
Password *string `help:"New password"`
|
||||
Desc string `help:"Description"`
|
||||
Displayname string `help:"Displayname"`
|
||||
Email string `help:"Email"`
|
||||
Mobile string `help:"Mobile"`
|
||||
Enabled bool `help:"Enabled"`
|
||||
Disabled bool `help:"Disabled"`
|
||||
|
||||
SystemAccount bool `help:"Turn on is_system_account"`
|
||||
NotSystemAccount bool `help:"Turn off is_system_account"`
|
||||
@@ -262,8 +262,8 @@ func init() {
|
||||
if len(args.Name) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Name), "name")
|
||||
}
|
||||
if len(args.Password) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Password), "password")
|
||||
if args.Password != nil {
|
||||
params.Add(jsonutils.NewString(*args.Password), "password")
|
||||
}
|
||||
if len(args.Displayname) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Displayname), "displayname")
|
||||
|
||||
@@ -158,4 +158,13 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&VpcUpdateStatusOptions{}, "vpc-sync", "Synchronize the status of a vpc", func(s *mcclient.ClientSession, args *VpcUpdateStatusOptions) error {
|
||||
result, err := modules.Vpcs.PerformAction(s, args.ID, "sync", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -661,6 +661,13 @@ InstanceCreate:
|
||||
items:
|
||||
type: string
|
||||
description: 主机组的ID或者Name
|
||||
secgroups:
|
||||
type: array
|
||||
description: 安全组列表
|
||||
items:
|
||||
type: string
|
||||
example: default
|
||||
description: 安全组名称或ID,建议使用ID
|
||||
|
||||
|
||||
InstanceDisk:
|
||||
|
||||
38
go.mod
38
go.mod
@@ -13,7 +13,7 @@ require (
|
||||
github.com/Shopify/sarama v1.20.0 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20180112035716-b5829a0278c8
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20181116160301-c6838fdc33ed
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible
|
||||
github.com/anacrolix/dht v0.0.0-20181129074040-b09db78595aa // indirect
|
||||
github.com/anacrolix/go-libutp v0.0.0-20180808010927-aebbeb60ea05 // indirect
|
||||
github.com/anacrolix/log v0.0.0-20180808012509-286fcf906b48 // indirect
|
||||
@@ -27,13 +27,10 @@ require (
|
||||
github.com/c-bata/go-prompt v0.2.1
|
||||
github.com/ceph/go-ceph v0.0.0-20181217221554-e32f9f0f2e94
|
||||
github.com/coredns/coredns v1.3.0
|
||||
github.com/coreos/bbolt v1.3.3 // indirect
|
||||
github.com/coreos/etcd v3.3.10+incompatible // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a // indirect
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190806190131-db2462fef53b // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||
github.com/dimchansky/utfbom v1.1.0 // indirect
|
||||
github.com/dnaeon/go-vcr v1.0.1 // indirect
|
||||
github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11 // indirect
|
||||
@@ -57,10 +54,7 @@ require (
|
||||
github.com/golang-plus/testing v1.0.0 // indirect
|
||||
github.com/golang-plus/uuid v1.0.0
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
|
||||
github.com/golang/protobuf v1.3.1
|
||||
github.com/google/btree v1.0.0 // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/google/gopacket v1.1.17
|
||||
github.com/google/uuid v1.1.0 // indirect
|
||||
github.com/googleapis/gnostic v0.2.0 // indirect
|
||||
@@ -70,9 +64,6 @@ require (
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282
|
||||
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
|
||||
github.com/hako/durafmt v0.0.0-20180520121703-7b7ae1e72ead
|
||||
github.com/huandu/xstrings v1.2.0 // indirect
|
||||
@@ -80,8 +71,6 @@ require (
|
||||
github.com/jinzhu/gorm v1.9.1
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.0.1 // indirect
|
||||
github.com/jonboulle/clockwork v0.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.5 // indirect
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
|
||||
github.com/kr/pty v1.1.3
|
||||
github.com/lib/pq v1.2.0 // indirect
|
||||
@@ -95,11 +84,8 @@ require (
|
||||
github.com/mholt/caddy v0.10.11
|
||||
github.com/miekg/dns v1.1.1
|
||||
github.com/minio/minio-go v6.0.14+incompatible
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/moul/http2curl v1.0.0
|
||||
github.com/mozillazg/go-httpheader v0.2.1 // indirect
|
||||
github.com/mozillazg/go-pinyin v0.15.0
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect
|
||||
github.com/opentracing/opentracing-go v1.0.2 // indirect
|
||||
@@ -114,30 +100,25 @@ require (
|
||||
github.com/shirou/gopsutil v2.18.10+incompatible
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9
|
||||
github.com/soheilhy/cmux v0.1.4 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.3 // indirect
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181108132626-805d01dd0e2e
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190717101923-c5c1f9751e7f
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20191108095731-8ca4b370cde4
|
||||
github.com/tinylib/msgp v1.1.0 // indirect
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
|
||||
github.com/tredoe/osutil v0.0.0-20161130133508-7d3ee1afa71c
|
||||
github.com/ugorji/go v0.0.0-20161130061742-9c7f9b7a2bc3 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible
|
||||
github.com/vmware/govmomi v0.19.0
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
|
||||
go.etcd.io/bbolt v1.3.3 // indirect
|
||||
go.etcd.io/etcd v3.3.10+incompatible
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20191023171146-3cf2f69b5738
|
||||
go.uber.org/atomic v1.4.0 // indirect
|
||||
go.uber.org/multierr v1.1.0 // indirect
|
||||
go.uber.org/zap v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20191008142428-8d021180e987
|
||||
google.golang.org/grpc v1.19.0
|
||||
google.golang.org/grpc v1.23.1
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
|
||||
@@ -150,12 +131,11 @@ require (
|
||||
k8s.io/client-go v9.0.0+incompatible
|
||||
k8s.io/klog v0.1.0 // indirect
|
||||
k8s.io/kubernetes v1.12.3
|
||||
sigs.k8s.io/yaml v1.1.0 // indirect
|
||||
yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7
|
||||
yunion.io/x/jsonutils v0.0.0-20200303051356-aa609aba0cda
|
||||
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d
|
||||
yunion.io/x/pkg v0.0.0-20191024065906-00964c53d82f
|
||||
yunion.io/x/pkg v0.0.0-20200304112442-9dae9351325e
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
|
||||
yunion.io/x/sqlchemy v0.0.0-20191008135637-33eb2e4f6cc7
|
||||
yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57
|
||||
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3
|
||||
)
|
||||
|
||||
|
||||
99
go.sum
99
go.sum
@@ -17,6 +17,7 @@ github.com/DataDog/zstd v1.3.4 h1:LAGHkXuvC6yky+C2CUG2tD7w8QlrUwpue8XwIh0X4AY=
|
||||
github.com/DataDog/zstd v1.3.4/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Microsoft/azure-vhd-utils v0.0.0-20181115010904-44cbada2ece3 h1:gImoAO1xAcC1oDlYmD/X7dggsodGf2DFJOVE5m0ssms=
|
||||
github.com/Microsoft/azure-vhd-utils v0.0.0-20181115010904-44cbada2ece3/go.mod h1:u0H9gMieFLxkUy8RS0X8VbFWyPs2815qQAaitRbj6x0=
|
||||
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
|
||||
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
github.com/RoaringBitmap/roaring v0.4.16 h1:NholfewybRLOwACgfqfzn/N5xa6keKNs4fP00t0cwLo=
|
||||
github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
@@ -32,8 +33,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20180112035716-b5829a0278c8 h1:mb7rn6WX8viizO36Nv6VVCBrgwaq01HPrZv1qq07/Yg=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20180112035716-b5829a0278c8/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20181116160301-c6838fdc33ed h1:8Nj1ihALo/UVM2EnOVQ1EY/kwNKRwLx1GW/z3Y65czY=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20181116160301-c6838fdc33ed/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible h1:EaK5256H3ELiyaq5O/Zwd6fnghD6DqmZDQmmzzJklUU=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/anacrolix/dht v0.0.0-20180412060941-24cbf25b72a4/go.mod h1:hQfX2BrtuQsLQMYQwsypFAab/GvHg8qxwVi4OJdR1WI=
|
||||
github.com/anacrolix/dht v0.0.0-20181127122252-acaa69c368bb/go.mod h1:Z/mP+H70xwnUv957UXVkTrzYRhKs0mGjS0lyqS331g4=
|
||||
github.com/anacrolix/dht v0.0.0-20181129074040-b09db78595aa h1:5RyX9Tvqa9oewlJhFihkxe8biS0ojTlrNU3ryqm5g2s=
|
||||
@@ -78,6 +79,9 @@ github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
@@ -91,18 +95,20 @@ github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2w
|
||||
github.com/c-bata/go-prompt v0.2.1 h1:HTPxmnfY4y5x3Myo7Gq4ce989jfnvZIBgdBp6y8bjYM=
|
||||
github.com/c-bata/go-prompt v0.2.1/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/coredns/coredns v1.3.0 h1:Ubjr8ZrOpEj95/A9dqQqQAG2k5DWEFdg2ZB3tUXuULA=
|
||||
github.com/coredns/coredns v1.3.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0=
|
||||
github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY=
|
||||
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a h1:W8b4lQ4tFF21aspRGoBuCNV6V2fFJBF+pm1J6OY8Lys=
|
||||
github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -117,6 +123,7 @@ github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyG
|
||||
github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11 h1:m8nX8hsUghn853BJ5qB0lX+VvS6LTJPksWyILFZRYN4=
|
||||
github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -171,6 +178,8 @@ github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang-plus/errors v1.0.0 h1:9Rh4itnph6OYO7wm9u3FUTLMFMKCoL07+bLiYKELxWw=
|
||||
github.com/golang-plus/errors v1.0.0/go.mod h1:YTFZjOTBcUFieeZe4q+7Umfu/sceSr3XQyBIkTkzpd8=
|
||||
github.com/golang-plus/testing v1.0.0 h1:azmFWFV44LHK/j/jAkNTbzB2G2b6HdmqF358r73m8kg=
|
||||
@@ -179,6 +188,7 @@ github.com/golang-plus/uuid v1.0.0 h1:ga84hG89vda++AGpup4N/cbfbM3O4d3R5ON9/jcN6A
|
||||
github.com/golang-plus/uuid v1.0.0/go.mod h1:pBDDRrdgRHHqyYlj1d1i2gwyBq62Zc+sP2cDiCDkBLI=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@@ -187,6 +197,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
@@ -200,12 +212,13 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
|
||||
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s=
|
||||
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
@@ -223,6 +236,7 @@ github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gosuri/uilive v0.0.0-20170323041506-ac356e6e42cd/go.mod h1:qkLSc0A5EXSP6B04TrN4oQoxqFI7A8XvoXSlJi8cwk8=
|
||||
@@ -231,12 +245,12 @@ github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282 h1:KFqmdzEPbU7Uck2t
|
||||
github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
|
||||
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f h1:ShTPMJQes6tubcjzGMODIVG5hlrCeImaBnZzKF2N8SM=
|
||||
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.2 h1:S+ef0492XaIknb8LMjcwgW2i3cNTzDYMmDrOThOJNWc=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
|
||||
github.com/hako/durafmt v0.0.0-20180520121703-7b7ae1e72ead h1:Y9WOGZY2nw5ksbEf5AIpk+vK52Tdg/VN/rHFRfEeeGQ=
|
||||
@@ -248,6 +262,8 @@ github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0
|
||||
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/gorm v1.9.1 h1:lDSDtsCt5AGGSKTs8AHlSDbbgif4G4+CKJ8ETBDVHTA=
|
||||
github.com/jinzhu/gorm v1.9.1/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
|
||||
@@ -260,14 +276,16 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
|
||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
|
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c h1:N7A4JCA2G+j5fuFxCsJqjFU/sZe0mj8H0sSoSwbaikw=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c/go.mod h1:Nn5wlyECw3iJrzi0AhIWg+AJUb4PlRQVW4/3XHH1LZA=
|
||||
@@ -286,11 +304,14 @@ github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/libvirt/libvirt-go-xml v5.2.0+incompatible h1:ALyVpa0/lFfFaUpb5l0fNBohufmQG6jsOGRCl/nKEi8=
|
||||
github.com/libvirt/libvirt-go-xml v5.2.0+incompatible/go.mod h1:oBlgD3xOA01ihiK5stbhFzvieyW+jVS6kbbsMVF623A=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-sqlite3 v1.7.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
@@ -327,10 +348,13 @@ github.com/minio/minio-go/v6 v6.0.33 h1:CNThMAZ9bN6OEIP8DulqlYpaXKJ18rgG/Cqm14Q4
|
||||
github.com/minio/minio-go/v6 v6.0.33/go.mod h1:vaNT59cWULS37E+E9zkuN/BVnKHyXtVGS+b04Boc66Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
|
||||
@@ -342,6 +366,7 @@ github.com/mozillazg/go-pinyin v0.15.0/go.mod h1:bO+dztNW6O2lSJdYLha7LO3bujXzjjU
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
@@ -372,15 +397,23 @@ github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
@@ -415,6 +448,9 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -427,19 +463,21 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/syncthing/syncthing v0.14.48-rc.4/go.mod h1:nw3siZwHPA6M8iSfjDCWQ402eqvEIasMQOE8nFOxy7M=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181108132626-805d01dd0e2e h1:CtKVGXKh2bfmepZ/YogAjvL/CrSy9NGZET500K7arf4=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v0.0.0-20181108132626-805d01dd0e2e/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190717101923-c5c1f9751e7f h1:TzE7Cs9HhTyfot4WIoMnbD1rWfD4Jkwy2M3Zs66CaRE=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190717101923-c5c1f9751e7f/go.mod h1:/4BhymH1yO6ljUGQgcKsd7L3W+pdKRxoRiOuoZPLnGg=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20191108095731-8ca4b370cde4 h1:wVKDVTKxaf0ll8ONv22Q+cazYSSmcWt7JJOeQD0LoKQ=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20191108095731-8ca4b370cde4/go.mod h1:wk2XFUg6egk4tSDNZtXeKfe2G6690UVyt163PuUxBZk=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
|
||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
|
||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tredoe/osutil v0.0.0-20161130133508-7d3ee1afa71c h1:5q7IHeqvAA4hWR1CfpTOS7RFsTDC36TaSZ8Dvc00bPk=
|
||||
github.com/tredoe/osutil v0.0.0-20161130133508-7d3ee1afa71c/go.mod h1:M/I710pXKQToMdqt/D+mJ4QsnW6WDaajyB6DWFmDXBs=
|
||||
github.com/ugorji/go v0.0.0-20161130061742-9c7f9b7a2bc3 h1:KfqgRfYvGRyKOQUx8GphSC8D6vVoBndzco3rESP8I4k=
|
||||
github.com/ugorji/go v0.0.0-20161130061742-9c7f9b7a2bc3/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmware/govmomi v0.19.0 h1:CR6tEByWCPOnRoRyhLzuHaU+6o2ybF3qufNRWS/MGrY=
|
||||
@@ -456,9 +494,10 @@ github.com/yunionio/go-ceph v0.0.0-20190912101231-6f05a06b3859 h1:wu596gn6sV3j5w
|
||||
github.com/yunionio/go-ceph v0.0.0-20190912101231-6f05a06b3859/go.mod h1:8XuBae5AzsgotLArJSewMruYVaQs8AlfsK5jBCG8T9Y=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v3.3.10+incompatible h1:qXVcIR1kU3CYLD8zXDseOmBNwg0uaui53e4Wg4uj0rk=
|
||||
go.etcd.io/etcd v3.3.10+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20191023171146-3cf2f69b5738 h1:lWF4f9Nypl1ZqSb4gLeh/DGvBYVaUYHuiB93teOmwgc=
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
@@ -481,6 +520,7 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -497,6 +537,7 @@ golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954 h1:JGZucVF/L/TotR719NbujzadOZ2AgnYlqphQGHDCKaU=
|
||||
@@ -510,6 +551,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180724212812-e072cadbbdc8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -541,12 +584,15 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.zx2c4.com/wireguard v0.0.20190908 h1:SUoXDdwSMtomLdvke+zz83/u9tNvl4hHmcTIWp38tow=
|
||||
golang.zx2c4.com/wireguard v0.0.20190908/go.mod h1:LhfXh5z6bLC2lW2ve6BzYZFwnnsXK3OQjySR0Yh2dO8=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20191008142428-8d021180e987 h1:26OAgqBTufVr8WKonCEhhjO1oKsYhHv0iM5Dg92G1TM=
|
||||
@@ -562,12 +608,15 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRn
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
@@ -591,6 +640,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.0.0-20181004124137-fd83cbc87e76 h1:cGc6jt7tNK7a2WfgNKjxjoU/UXXr9Q7JTqvCupZ+6+Y=
|
||||
k8s.io/api v0.0.0-20181004124137-fd83cbc87e76/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
||||
k8s.io/apimachinery v0.0.0-20181215012845-4d029f033399 h1:xdXaRQ7uNX4x6NpvxXASvlVXtKa8+WbCXK7Hjr6XZ6c=
|
||||
@@ -605,19 +655,20 @@ sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051 h1:vtZw2iwGrsARNSwRTREGjmr2BWPdxbmXVkb3kI1qu28=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7 h1:9NcHs2OFMyN8O8SmJ3sFm5AJSVXP3u1N3avJsbyX3RI=
|
||||
yunion.io/x/jsonutils v0.0.0-20191005115334-bb1c187fc0e7/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
yunion.io/x/jsonutils v0.0.0-20200303051356-aa609aba0cda h1:wSwQj3MDGchGYM2RAo1riYhrTz4apH+5XyBnchuDi84=
|
||||
yunion.io/x/jsonutils v0.0.0-20200303051356-aa609aba0cda/go.mod h1:T7kxQJR13+t7z0TuT+Wzd7MTxBOk2H9c0pO1ONQSv90=
|
||||
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b h1:Z9z+7iegu0HXuL+S8taVWRd1P4b9JJOgPXIeoqYrj7c=
|
||||
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE=
|
||||
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d h1:59zrDL7Ft+hDukguJRmLr/Gdu/9V75x+yX99ovZwfaA=
|
||||
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
|
||||
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf h1:OsKC+2ghZHwp+Ztm/MwKlLKKRiE7QcPG8eTp0GmsHbg=
|
||||
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20191024065906-00964c53d82f h1:rliduzLUj5k4kuY9kxbMDvMtxAANAOZ/hrsslpGK+fA=
|
||||
yunion.io/x/pkg v0.0.0-20191024065906-00964c53d82f/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20200302034534-fdf44d54b070/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20200304112442-9dae9351325e h1:rBfX77+VEBVpe6Xxy2gDa4WB7qbtndWvXcrVKzleF84=
|
||||
yunion.io/x/pkg v0.0.0-20200304112442-9dae9351325e/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
|
||||
yunion.io/x/sqlchemy v0.0.0-20191008135637-33eb2e4f6cc7 h1:9bxOxNLNN18mJoR8GDPVtRJIpDBgA3dYmEBsuVDy0O4=
|
||||
yunion.io/x/sqlchemy v0.0.0-20191008135637-33eb2e4f6cc7/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
|
||||
yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57 h1:KtQAuLJ00RSUVqkiRmJ1DiDABiw0U3xxXnzD3lGavaY=
|
||||
yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
|
||||
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3 h1:bfC8EhXYvyGYldRWlzxiCM39Zfj3s3+zham9mW2h2LE=
|
||||
yunion.io/x/structarg v0.0.0-20190809075558-115bed041de3/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apigateway/app"
|
||||
"yunion.io/x/onecloud/pkg/apigateway/clientman"
|
||||
"yunion.io/x/onecloud/pkg/apigateway/options"
|
||||
api "yunion.io/x/onecloud/pkg/apis/apigateway"
|
||||
app_common "yunion.io/x/onecloud/pkg/cloudcommon/app"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
@@ -35,11 +36,16 @@ func StartService() {
|
||||
opts := &options.Options
|
||||
baseOpts := &opts.BaseOptions
|
||||
commonOpts := &opts.CommonOptions
|
||||
common_options.ParseOptions(opts, os.Args, "apigateway.conf", "apigateway")
|
||||
common_options.ParseOptions(opts, os.Args, "apigateway.conf", api.SERVICE_TYPE)
|
||||
app_common.InitAuth(commonOpts, func() {
|
||||
log.Infof("Auth complete.")
|
||||
})
|
||||
|
||||
err := app_common.MergeServiceConfig(opts, api.SERVICE_TYPE, api.SERVICE_VERSION)
|
||||
if err != nil {
|
||||
log.Fatalf("[MERGE CONFIG] Fail to merge service config %s", err)
|
||||
}
|
||||
|
||||
if opts.DisableModuleApiVersion {
|
||||
mcclient.DisableApiVersionByModule()
|
||||
}
|
||||
|
||||
20
pkg/apis/apigateway/consts.go
Normal file
20
pkg/apis/apigateway/consts.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package apigateway
|
||||
|
||||
const (
|
||||
SERVICE_TYPE = "apigateway"
|
||||
SERVICE_VERSION = ""
|
||||
)
|
||||
15
pkg/apis/apigateway/doc.go
Normal file
15
pkg/apis/apigateway/doc.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package apigateway // import "yunion.io/x/onecloud/pkg/apis/apigateway"
|
||||
@@ -188,6 +188,7 @@ type ServerCreateInput struct {
|
||||
EipChargeType string `json:"eip_charge_type,omitempty"`
|
||||
Eip string `json:"eip,omitempty"`
|
||||
InstanceSnapshotId string `json:"instance_snapshot_id,omitempty"`
|
||||
Secgroups []string `json:"secgroups"`
|
||||
|
||||
OsType string `json:"os_type"`
|
||||
// Fill by server
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
|
||||
package compute
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
)
|
||||
|
||||
const (
|
||||
BUCKET_OPS_STATS_CHANGE = "stats_change"
|
||||
|
||||
@@ -30,3 +37,39 @@ const (
|
||||
BUCKET_UPLOAD_OBJECT_ACL_HEADER = "X-Yunion-Bucket-Upload-Acl"
|
||||
BUCKET_UPLOAD_OBJECT_STORAGECLASS_HEADER = "X-Yunion-Bucket-Upload-Storageclass"
|
||||
)
|
||||
|
||||
type BucketObjectsActionInput struct {
|
||||
Key []string
|
||||
}
|
||||
|
||||
type BucketAclInput struct {
|
||||
BucketObjectsActionInput
|
||||
|
||||
Acl cloudprovider.TBucketACLType
|
||||
}
|
||||
|
||||
func (input *BucketAclInput) Validate() error {
|
||||
switch input.Acl {
|
||||
case cloudprovider.ACLPrivate, cloudprovider.ACLAuthRead, cloudprovider.ACLPublicRead, cloudprovider.ACLPublicReadWrite:
|
||||
// do nothing
|
||||
default:
|
||||
return httperrors.NewInputParameterError("acl")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BucketMetadataInput struct {
|
||||
BucketObjectsActionInput
|
||||
|
||||
Metadata http.Header
|
||||
}
|
||||
|
||||
func (input *BucketMetadataInput) Validate() error {
|
||||
if len(input.Key) == 0 {
|
||||
return httperrors.NewInputParameterError("key")
|
||||
}
|
||||
if len(input.Metadata) == 0 {
|
||||
return httperrors.NewInputParameterError("metadata")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@ package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
)
|
||||
|
||||
type CloudaccountCreateInput struct {
|
||||
@@ -27,9 +30,7 @@ type CloudaccountCreateInput struct {
|
||||
Brand string
|
||||
IsPublicCloud bool
|
||||
IsOnPremise bool
|
||||
Account string
|
||||
Secret string
|
||||
AccessUrl string
|
||||
Tenant string
|
||||
TenantId string
|
||||
Name string
|
||||
Description string
|
||||
@@ -39,26 +40,22 @@ type CloudaccountCreateInput struct {
|
||||
AutoCreateProject bool
|
||||
Options *jsonutils.JSONObject
|
||||
|
||||
ProjectName string //OpenStack
|
||||
DomainName string //OpenStack
|
||||
Username string //OpenStack Esxi ZStack
|
||||
Password string //OpenStack Esxi ZStack
|
||||
AuthUrl string //OpenStack ZStack
|
||||
|
||||
AccessKeyId string //Huawei Aliyun Ucloud Aws
|
||||
AccessKeySecret string //Huawei Aliyun Ucloud Aws
|
||||
Environment string //Huawei Azure Aws
|
||||
|
||||
DirectoryId string //Azure
|
||||
ClientId string //Azure
|
||||
ClientSecret string //Azure
|
||||
|
||||
Host string //Esxi
|
||||
Port int //Esxi
|
||||
|
||||
Endpoint string
|
||||
|
||||
AppId string //Qcloud
|
||||
SecretId string //Qcloud
|
||||
SecretKey string //Qcloud
|
||||
cloudprovider.SCloudaccount
|
||||
cloudprovider.SCloudaccountCredential
|
||||
}
|
||||
|
||||
type CloudaccountShareModeInput struct {
|
||||
apis.Meta
|
||||
|
||||
ShareMode string
|
||||
}
|
||||
|
||||
func (i CloudaccountShareModeInput) Validate() error {
|
||||
if len(i.ShareMode) == 0 {
|
||||
return httperrors.NewMissingParameterError("share_mode")
|
||||
}
|
||||
if !utils.IsInStringArray(i.ShareMode, CLOUD_ACCOUNT_SHARE_MODES) {
|
||||
return httperrors.NewInputParameterError("invalid share_mode %s", i.ShareMode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -92,3 +92,17 @@ const (
|
||||
|
||||
CLOUD_ENV_PRIVATE_ON_PREMISE = "private_or_onpremise"
|
||||
)
|
||||
|
||||
const (
|
||||
CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN = "account_domain"
|
||||
CLOUD_ACCOUNT_SHARE_MODE_SYSTEM = "system"
|
||||
CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN = "provider_domain"
|
||||
)
|
||||
|
||||
var (
|
||||
CLOUD_ACCOUNT_SHARE_MODES = []string{
|
||||
CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN,
|
||||
CLOUD_ACCOUNT_SHARE_MODE_SYSTEM,
|
||||
CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -35,6 +35,7 @@ const (
|
||||
CITY_TAIPEI = "Taipei" //台北市
|
||||
CITY_KAOHSIUNG = "Kaohsiung" //高雄市
|
||||
CITY_CHENG_DU = "Chengdu" //成都
|
||||
CITY_HE_YUAN = "HeYuan" //河源
|
||||
CITY_CHONG_QING = "Chongqing" //重庆
|
||||
|
||||
// 日本
|
||||
@@ -49,6 +50,20 @@ const (
|
||||
CITY_YARRALUMLA = "Yarralumla" //亚拉伦拉
|
||||
CITY_MELBOURNE = "Melbourne" //墨尔本
|
||||
|
||||
//芬兰
|
||||
CITY_FINLAND = "Finland"
|
||||
|
||||
//比利时
|
||||
CITY_BELGIUM = "Belgium" //比利时
|
||||
|
||||
//瑞士
|
||||
CITY_ZURICH = "Zurich" //苏黎世
|
||||
CITY_GENEVA = "Geneva" //日内瓦
|
||||
|
||||
// 挪威
|
||||
CITY_STAVANGER = "Stavanger" //斯塔万格
|
||||
CITY_OSLO = "Oslo" // 奥斯陆
|
||||
|
||||
// 马来西亚
|
||||
CITY_KUALA_LUMPUR = "Kuala Lumpur" //吉隆坡
|
||||
|
||||
@@ -85,7 +100,8 @@ const (
|
||||
CITY_DUBAI = "Dubai" //迪拜
|
||||
|
||||
// 德国
|
||||
CITY_FRANKFURT = "Frankfurt" //法兰克福
|
||||
CITY_FRANKFURT = "Frankfurt" // 法兰克福
|
||||
CITY_DELMENHORST = "Delmenhorst" // 代尔门霍斯特
|
||||
|
||||
// 韩国
|
||||
CITY_SEOUL = "Seoul" //首尔
|
||||
@@ -154,4 +170,6 @@ const (
|
||||
COUNTRY_CODE_RU = "RU" //俄罗斯
|
||||
COUNTRY_CODE_NG = "NG" //尼日利亚
|
||||
COUNTRY_CODE_VN = "VN" //越南
|
||||
COUNTRY_CODE_CH = "CH" //瑞士
|
||||
COUNTRY_CODE_NO = "NO" //挪威
|
||||
)
|
||||
|
||||
@@ -56,11 +56,12 @@ const (
|
||||
BACKUP_MODE_MANUAL = "manual" //手动
|
||||
|
||||
//实例数据库状态
|
||||
DBINSTANCE_DATABASE_CREATING = "creating" //创建中
|
||||
DBINSTANCE_DATABASE_CREATE_FAILE = "create_failed" //创建失败
|
||||
DBINSTANCE_DATABASE_RUNNING = "running" //正常
|
||||
DBINSTANCE_DATABASE_DELETING = "deleting" //删除中
|
||||
DBINSTANCE_DATABASE_DELETE_FAILED = "delete_failed" //删除失败
|
||||
DBINSTANCE_DATABASE_CREATING = "creating" //创建中
|
||||
DBINSTANCE_DATABASE_CREATE_FAILE = "create_failed" //创建失败
|
||||
DBINSTANCE_DATABASE_RUNNING = "running" //正常
|
||||
DBINSTANCE_DATABASE_GRANT_PRIVILEGE = "grant_privilege" //赋予权限中
|
||||
DBINSTANCE_DATABASE_DELETING = "deleting" //删除中
|
||||
DBINSTANCE_DATABASE_DELETE_FAILED = "delete_failed" //删除失败
|
||||
|
||||
//实例用户状态
|
||||
DBINSTANCE_USER_UNAVAILABLE = "unavailable" //不可用
|
||||
@@ -107,10 +108,10 @@ const (
|
||||
ALIYUN_DBINSTANCE_STORAGE_TYPE_CLOUD_SSD = "cloud_ssd" //SSD云盘
|
||||
|
||||
//华为云存储类型
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_SSD = "SSD" //超高IO云硬盘
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_SAS = "SAS" //高IO云硬盘
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_SATA = "SATA" //普通IO云硬盘
|
||||
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_ULTRAHIGH = "ULTRAHIGH" //超高IO云硬盘
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_ULTRAHIGHPRO = "ULTRAHIGHPRO"
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_COMMON = "COMMON"
|
||||
HUAWEI_DBINSTANCE_STORAGE_TYPE_HIGH = "HIGH"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -18,7 +18,7 @@ import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type SDBInstanceDatabasePrivilege struct {
|
||||
Account string
|
||||
DBInstancedccountId string
|
||||
DBInstanceaccountId string
|
||||
Privilege string
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
EIP_ASSOCIATE_TYPE_SERVER = "server"
|
||||
EIP_ASSOCIATE_TYPE_NAT_GATEWAY = "natgateway"
|
||||
EIP_ASSOCIATE_TYPE_LOADBALANCER = "loadbalancer"
|
||||
EIP_ASSOCIATE_TYPE_UNKNOWN = "unknown"
|
||||
|
||||
EIP_STATUS_READY = "ready"
|
||||
EIP_STATUS_UNKNOWN = "unknown"
|
||||
|
||||
@@ -224,6 +224,7 @@ const (
|
||||
VM_METADATA_CREATE_PARAMS = "create_params"
|
||||
VM_METADATA_LOGIN_ACCOUNT = "login_account"
|
||||
VM_METADATA_LOGIN_KEY = "login_key"
|
||||
VM_METADATA_LAST_LOGIN_KEY = "last_login_key"
|
||||
VM_METADATA_LOGIN_KEY_TIMESTAMP = "login_key_timestamp"
|
||||
VM_METADATA_OS_ARCH = "os_arch"
|
||||
VM_METADATA_OS_DISTRO = "os_distribution"
|
||||
|
||||
38
pkg/apis/compute/guests.go
Normal file
38
pkg/apis/compute/guests.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type ServerRebuildRootInput struct {
|
||||
apis.Meta
|
||||
|
||||
Image string `json:"image"`
|
||||
ImageId string `json:"image_id"`
|
||||
Keypair string `json:"keypair"`
|
||||
KeypairId string `json:"keypair_id"`
|
||||
ResetPassword *bool `json:"reset_password"`
|
||||
Password string `json:"password"`
|
||||
AutoStart *bool `json:"auto_start"`
|
||||
AllDisks *bool `json:"all_disks"`
|
||||
}
|
||||
|
||||
func (i ServerRebuildRootInput) GetImageName() string {
|
||||
if len(i.Image) > 0 {
|
||||
return i.Image
|
||||
}
|
||||
if len(i.ImageId) > 0 {
|
||||
return i.ImageId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (i ServerRebuildRootInput) GetKeypairName() string {
|
||||
if len(i.Keypair) > 0 {
|
||||
return i.Keypair
|
||||
}
|
||||
if len(i.KeypairId) > 0 {
|
||||
return i.KeypairId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -14,6 +14,10 @@
|
||||
|
||||
package compute
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// # DEFAULT_BANDWIDTH = options.default_bandwidth
|
||||
MAX_BANDWIDTH = 100000
|
||||
@@ -40,6 +44,8 @@ const (
|
||||
NETWORK_STATUS_DELETING = "deleting"
|
||||
NETWORK_STATUS_DELETED = "deleted"
|
||||
NETWORK_STATUS_DELETE_FAILED = "delete_failed"
|
||||
NETWORK_STATUS_START_SYNC = "start_sync"
|
||||
NETWORK_STATUS_SYNCING = "sync"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -75,4 +81,5 @@ type SNetworkAddress struct {
|
||||
OwnerType string
|
||||
AssociateId string
|
||||
AssociateType string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
23
pkg/apis/compute/routetable_const.go
Normal file
23
pkg/apis/compute/routetable_const.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
ROUTE_TABLE_TYPE_VPC = "VPC" // VPC路由器
|
||||
ROUTE_TABLE_TYPE_VBR = "VBR" // 边界路由器
|
||||
)
|
||||
|
||||
const (
|
||||
ROUTE_ENTRY_TYPE_CUSTOM = "Custom" // 自定义路由
|
||||
ROUTE_ENTRY_TYPE_SYSTEM = "System" // 系统路由
|
||||
)
|
||||
|
||||
const (
|
||||
Next_HOP_TYPE_INSTANCE = "Instance" // ECS实例。
|
||||
Next_HOP_TYPE_HAVIP = "HaVip" // 高可用虚拟IP。
|
||||
Next_HOP_TYPE_VPN = "VpnGateway" // VPN网关。
|
||||
Next_HOP_TYPE_NAT = "NatGateway" // NAT网关。
|
||||
Next_HOP_TYPE_NETWORK = "NetworkInterface" // 辅助弹性网卡。
|
||||
Next_HOP_TYPE_ROUTER = "RouterInterface" // 路由器接口。
|
||||
Next_HOP_TYPE_IPV6 = "IPv6Gateway" // IPv6网关。
|
||||
Next_HOP_TYPE_INTERNET = "InternetGateway" // Internet网关。
|
||||
Next_HOP_TYPE_EGRESS_INTERNET = "EgressInternetGateway" // egress only Internet网关。
|
||||
)
|
||||
@@ -37,6 +37,7 @@ type SSecgroupRuleCreateInput struct {
|
||||
CIDR string
|
||||
Action string
|
||||
Description string
|
||||
Secgroup string
|
||||
SecgroupId string
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ const (
|
||||
// STORAGE_CLOUD_SSD ="cloud_ssd"
|
||||
STORAGE_LOCAL_BASIC = "local_basic"
|
||||
STORAGE_LOCAL_SSD = "local_ssd"
|
||||
STORAGE_LOCAL_PRO = "local_pro"
|
||||
STORAGE_CLOUD_BASIC = "cloud_basic"
|
||||
STORAGE_CLOUD_PREMIUM = "cloud_premium"
|
||||
|
||||
@@ -59,6 +60,7 @@ const (
|
||||
|
||||
// openstack
|
||||
STORAGE_OPENSTACK_ISCSI = "iscsi"
|
||||
STORAGE_OPENSTACK_NOVA = "nova"
|
||||
|
||||
// Ucloud storage type
|
||||
STORAGE_UCLOUD_CLOUD_NORMAL = "CLOUD_NORMAL" // 普通云盘
|
||||
|
||||
@@ -24,6 +24,8 @@ const (
|
||||
VPC_STATUS_DELETE_FAILED = "delete_failed"
|
||||
VPC_STATUS_DELETED = "deleted"
|
||||
VPC_STATUS_UNKNOWN = "unknown"
|
||||
VPC_STATUS_START_SYNC = "start_sync"
|
||||
VPC_STATUS_SYNCING = "sync"
|
||||
|
||||
MAX_VPC_PER_REGION = 3
|
||||
|
||||
|
||||
@@ -88,6 +88,17 @@ type CandidateDisk struct {
|
||||
StorageIds []string `json:"storage_ids"`
|
||||
}
|
||||
|
||||
type CandidateDiskV2 struct {
|
||||
Index int `json:"index"`
|
||||
Storages []*CandidateStorage `json:"storages"`
|
||||
}
|
||||
|
||||
type CandidateStorage struct {
|
||||
Id string
|
||||
Name string
|
||||
FreeCapacity int64
|
||||
}
|
||||
|
||||
type CandidateNet struct {
|
||||
Index int `json:"index"`
|
||||
NetworkIds []string `json:"network_ids"`
|
||||
|
||||
@@ -128,10 +128,13 @@ func (agent *SBaremetalAgent) StartService() error {
|
||||
return fmt.Errorf("New baremetal manager error: %v", err)
|
||||
}
|
||||
|
||||
err = manager.loadConfigs()
|
||||
files, err := manager.loadConfigs()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Baremetal manager load config error: %v", err)
|
||||
}
|
||||
if err := manager.initBaremetals(files); err != nil {
|
||||
log.Warningf("init baremetals by files err: %v", err)
|
||||
}
|
||||
|
||||
agent.Manager = manager
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ func AddHandler2(app *appsrv.Application, method string, prefix string,
|
||||
|
||||
func customizeHandlerInfo(info *appsrv.SHandlerInfo) {
|
||||
if info.GetName(nil) == "baremetal-register" {
|
||||
info.SetProcessTimeout(time.Second * 180).SetWorkerManager(registerWorkMan)
|
||||
info.SetProcessTimeout(time.Second * 300).SetWorkerManager(registerWorkMan)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ func handleServerStatus(ctx *Context, bm *baremetal.SBaremetalInstance, _ bareme
|
||||
|
||||
func handleBaremetalRegister(ctx *Context, input *baremetal.BmRegisterInput) {
|
||||
ctx.DelayProcess(func(data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
baremetal.GetBaremetalManager().RegisterBaremetal(input)
|
||||
baremetal.GetBaremetalManager().RegisterBaremetal(ctx, input)
|
||||
return nil, nil
|
||||
}, nil)
|
||||
}
|
||||
|
||||
@@ -176,13 +176,8 @@ func bmRegisterMiddleware(h bmRegisterFunc) appsrv.FilterHandler {
|
||||
newCtx.ResponseError(httperrors.NewMissingParameterError("password"))
|
||||
return
|
||||
}
|
||||
ipAddr, err := newCtx.Data().GetString("ip_addr")
|
||||
if err != nil {
|
||||
newCtx.ResponseError(httperrors.NewMissingParameterError("ip_addr"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Second*175)
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Second*298)
|
||||
defer cancel()
|
||||
|
||||
data := &baremetal.BmRegisterInput{
|
||||
@@ -196,7 +191,6 @@ func bmRegisterMiddleware(h bmRegisterFunc) appsrv.FilterHandler {
|
||||
RemoteIp: remoteIp,
|
||||
Username: username,
|
||||
Password: password,
|
||||
IpAddr: ipAddr,
|
||||
}
|
||||
|
||||
h(newCtx, data)
|
||||
|
||||
@@ -40,7 +40,6 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
o "yunion.io/x/onecloud/pkg/baremetal/options"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/profiles"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/pxe"
|
||||
@@ -104,12 +103,16 @@ func (m *SBaremetalManager) GetZoneName() string {
|
||||
return m.Agent.Zone.Name
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) loadConfigs() error {
|
||||
func (m *SBaremetalManager) loadConfigs() ([]os.FileInfo, error) {
|
||||
m.killAllIPMITool()
|
||||
files, err := ioutil.ReadDir(m.configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) initBaremetals(files []os.FileInfo) error {
|
||||
bmIds := make([]string, 0)
|
||||
for _, file := range files {
|
||||
if file.IsDir() && regutils.MatchUUID(file.Name()) {
|
||||
@@ -265,10 +268,8 @@ type BmRegisterInput struct {
|
||||
IpAddr string
|
||||
}
|
||||
|
||||
func (i *BmRegisterInput) responseOk() {
|
||||
obj := jsonutils.NewDict()
|
||||
obj.Add(jsonutils.NewString("ok"), "result")
|
||||
appsrv.SendJSON(i.W, obj)
|
||||
func (i *BmRegisterInput) responseSucc(bmId string) {
|
||||
fmt.Fprintf(i.W, bmId)
|
||||
close(i.C)
|
||||
}
|
||||
|
||||
@@ -287,7 +288,7 @@ func (i *BmRegisterInput) isTimeout() bool {
|
||||
}
|
||||
|
||||
// delay task
|
||||
func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) {
|
||||
func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, input *BmRegisterInput) {
|
||||
adminWire, err := m.checkNetworkFromIp(input.RemoteIp)
|
||||
if input.isTimeout() {
|
||||
return
|
||||
@@ -295,21 +296,6 @@ func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) {
|
||||
input.responseErr(httperrors.NewBadRequestError("Verify network failed: %s", err))
|
||||
return
|
||||
}
|
||||
ipmiWire, err := m.checkNetworkFromIp(input.IpAddr)
|
||||
if input.isTimeout() {
|
||||
return
|
||||
} else if err != nil {
|
||||
input.responseErr(httperrors.NewBadRequestError("Verify network failed: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
ipmiMac, err := m.checkIpmiInfo(input.Username, input.Password, input.IpAddr)
|
||||
if input.isTimeout() {
|
||||
return
|
||||
} else if err != nil {
|
||||
input.responseErr(httperrors.NewBadRequestError("IPMI login info not correct: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
sshCli, err := m.checkSshInfo(input)
|
||||
if input.isTimeout() {
|
||||
@@ -319,6 +305,32 @@ func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) {
|
||||
return
|
||||
}
|
||||
|
||||
input.IpAddr, err = m.fetchIpmiIp(sshCli)
|
||||
|
||||
if input.isTimeout() {
|
||||
return
|
||||
} else if err != nil {
|
||||
input.responseErr(httperrors.NewBadRequestError("Fetch ipmi address failed: %s", err))
|
||||
return
|
||||
}
|
||||
log.Infof("Find ipmi address %s", input.IpAddr)
|
||||
|
||||
ipmiWire, err := m.checkNetworkFromIp(input.IpAddr)
|
||||
if input.isTimeout() {
|
||||
return
|
||||
} else if err != nil {
|
||||
input.responseErr(httperrors.NewBadRequestError("Verify network failed: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
ipmiLanChannel, ipmiMac, err := m.checkIpmiInfo(input.Username, input.Password, input.IpAddr)
|
||||
if input.isTimeout() {
|
||||
return
|
||||
} else if err != nil {
|
||||
input.responseErr(httperrors.NewBadRequestError("IPMI login info not correct: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = m.verifyMacAddr(sshCli)
|
||||
if input.isTimeout() {
|
||||
return
|
||||
@@ -330,9 +342,9 @@ func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) {
|
||||
registerTask := tasks.NewBaremetalRegisterTask(
|
||||
m, sshCli, input.Hostname, input.RemoteIp,
|
||||
input.Username, input.Password, input.IpAddr,
|
||||
ipmiMac, adminWire, ipmiWire,
|
||||
ipmiMac, ipmiLanChannel, adminWire, ipmiWire,
|
||||
)
|
||||
err = registerTask.CreateBaremetal()
|
||||
bmId, err := registerTask.CreateBaremetal()
|
||||
if input.isTimeout() {
|
||||
return
|
||||
} else if err != nil {
|
||||
@@ -340,8 +352,22 @@ func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) {
|
||||
return
|
||||
}
|
||||
|
||||
input.responseOk()
|
||||
registerTask.DoPrepare(sshCli)
|
||||
input.responseSucc(bmId)
|
||||
registerTask.DoPrepare(ctx, sshCli)
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) fetchIpmiIp(sshCli *ssh.Client) (string, error) {
|
||||
res, err := sshCli.RawRun(`/usr/bin/ipmitool lan print | grep "IP Address "`)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(res) == 1 {
|
||||
segs := strings.Fields(res[0])
|
||||
if len(segs) == 4 {
|
||||
return strings.TrimSpace(segs[3]), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("Failed to find ipmi ip address")
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) checkNetworkFromIp(ip string) (string, error) {
|
||||
@@ -407,11 +433,11 @@ func (m *SBaremetalManager) checkSshInfo(input *BmRegisterInput) (*ssh.Client, e
|
||||
return sshCLi, nil
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (net.HardwareAddr, error) {
|
||||
func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (int, net.HardwareAddr, error) {
|
||||
lanPlusTool := ipmitool.NewLanPlusIPMI(ipAddr, username, password)
|
||||
sysInfo, err := ipmitool.GetSysInfo(lanPlusTool)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return -1, nil, err
|
||||
}
|
||||
|
||||
for _, lanChannel := range ipmitool.GetLanChannels(sysInfo) {
|
||||
@@ -423,9 +449,9 @@ func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (ne
|
||||
if len(config.Mac) == 0 {
|
||||
continue
|
||||
}
|
||||
return config.Mac, nil
|
||||
return lanChannel, config.Mac, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Ipmi can't fetch lan config")
|
||||
return -1, nil, fmt.Errorf("Ipmi can't fetch lan config")
|
||||
}
|
||||
|
||||
func (m *SBaremetalManager) Stop() {
|
||||
@@ -1861,7 +1887,7 @@ func (b *SBaremetalInstance) doCronJobs(ctx context.Context) {
|
||||
for _, job := range b.cronJobs {
|
||||
now := time.Now().UTC()
|
||||
if job.NeedsToRun(now) {
|
||||
log.Debugf("need to run %s", job.Name())
|
||||
// log.Debugf("need to run %s", job.Name())
|
||||
func() {
|
||||
job.StartRun()
|
||||
defer job.StopRun()
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -27,6 +28,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/redfish"
|
||||
"yunion.io/x/onecloud/pkg/util/ssh"
|
||||
"yunion.io/x/onecloud/pkg/util/sysutils"
|
||||
)
|
||||
@@ -44,47 +46,84 @@ type sBaremetalRegisterTask struct {
|
||||
IpmiPassword string
|
||||
IpmiIpAddr string
|
||||
IpmiMac net.HardwareAddr
|
||||
AdminWire string
|
||||
IpmiWire string
|
||||
|
||||
IpmiLanChannel int
|
||||
|
||||
AdminWire string
|
||||
IpmiWire string
|
||||
|
||||
accessNic *types.SNicDevInfo
|
||||
}
|
||||
|
||||
func NewBaremetalRegisterTask(bmManager IBmManager, sshCli *ssh.Client,
|
||||
hostname, remoteIp, ipmiUsername, ipmiPassword, ipmiIpAddr string,
|
||||
ipmiMac net.HardwareAddr, adminWire, ipmiWire string) *sBaremetalRegisterTask {
|
||||
ipmiMac net.HardwareAddr, ipmiLanChannel int, adminWire, ipmiWire string) *sBaremetalRegisterTask {
|
||||
return &sBaremetalRegisterTask{
|
||||
BmManager: bmManager,
|
||||
SshCli: sshCli,
|
||||
Hostname: hostname,
|
||||
RemoteIp: remoteIp,
|
||||
IpmiUsername: ipmiUsername,
|
||||
IpmiPassword: ipmiPassword,
|
||||
IpmiIpAddr: ipmiIpAddr,
|
||||
IpmiMac: ipmiMac,
|
||||
AdminWire: adminWire,
|
||||
IpmiWire: ipmiWire,
|
||||
BmManager: bmManager,
|
||||
SshCli: sshCli,
|
||||
Hostname: hostname,
|
||||
RemoteIp: remoteIp,
|
||||
IpmiUsername: ipmiUsername,
|
||||
IpmiPassword: ipmiPassword,
|
||||
IpmiIpAddr: ipmiIpAddr,
|
||||
IpmiMac: ipmiMac,
|
||||
IpmiLanChannel: ipmiLanChannel,
|
||||
AdminWire: adminWire,
|
||||
IpmiWire: ipmiWire,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sBaremetalRegisterTask) CreateBaremetal() error {
|
||||
func (s *sBaremetalRegisterTask) getAccessDevMacAddr(ip string) (string, error) {
|
||||
nicsRet, err := s.SshCli.Run("/sbin/ip -o -4 addr show")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed get access nic %s", err)
|
||||
}
|
||||
|
||||
var dev string
|
||||
for i := 0; i < len(nicsRet); i++ {
|
||||
if strings.Contains(nicsRet[i], ip+"/") {
|
||||
segs := strings.Split(nicsRet[i], " ")
|
||||
if len(segs) > 1 {
|
||||
dev = segs[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(dev) == 0 {
|
||||
return "", fmt.Errorf("Can't get access dev")
|
||||
}
|
||||
log.Infof("Access dev is %s", dev)
|
||||
macRet, err := s.SshCli.Run("/sbin/ip a show " + dev)
|
||||
if err != nil || len(macRet) < 2 {
|
||||
return "", fmt.Errorf("Failed get access nic mac address %s", err)
|
||||
}
|
||||
segs := strings.Fields(macRet[1])
|
||||
if len(segs) < 2 {
|
||||
return "", fmt.Errorf("Failed to find mac address")
|
||||
}
|
||||
return segs[1], nil
|
||||
}
|
||||
|
||||
func (s *sBaremetalRegisterTask) CreateBaremetal() (string, error) {
|
||||
zoneId := s.BmManager.GetZoneId()
|
||||
ret, err := s.SshCli.Run("/lib/mos/lsnic")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Register baremeatl failed on lsnic: %s", err)
|
||||
return "", fmt.Errorf("Register baremeatl failed on lsnic: %s", err)
|
||||
}
|
||||
|
||||
accessMac, err := s.getAccessDevMacAddr(s.RemoteIp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
accessMacAddr, err := net.ParseMAC(accessMac)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed parse access mac %s", accessMac)
|
||||
}
|
||||
|
||||
nicinfo := sysutils.ParseNicInfo(ret)
|
||||
for _, nic := range nicinfo {
|
||||
ret, err := s.SshCli.RawRun("/sbin/ip a show " + nic.Dev)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Register baremeatl failed on ip command: %s", err)
|
||||
}
|
||||
if strings.Index(ret[0], s.RemoteIp) >= 0 {
|
||||
if nic.Mac.String() == accessMacAddr.String() {
|
||||
s.accessNic = nic
|
||||
break
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if s.accessNic == nil {
|
||||
@@ -99,21 +138,22 @@ func (s *sBaremetalRegisterTask) CreateBaremetal() error {
|
||||
params.Set("is_import", jsonutils.JSONTrue)
|
||||
res, err := modules.Hosts.CreateInContext(s.BmManager.GetClientSession(), params, &modules.Zones, zoneId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Create baremetal failed: %s", err)
|
||||
return "", fmt.Errorf("Create baremetal failed: %s", err)
|
||||
}
|
||||
pxeBm, err := s.BmManager.AddBaremetal(res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("BmManager add baremetal failed: %s", err)
|
||||
return "", fmt.Errorf("BmManager add baremetal failed: %s", err)
|
||||
}
|
||||
|
||||
err = pxeBm.InitAdminNetif(
|
||||
s.accessNic.Mac, s.AdminWire, api.NIC_TYPE_ADMIN, api.NETWORK_TYPE_PXE, true, s.RemoteIp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("BmManager add admin netif failed: %s", err)
|
||||
return "", fmt.Errorf("BmManager add admin netif failed: %s", err)
|
||||
}
|
||||
err = pxeBm.InitAdminNetif(
|
||||
s.IpmiMac, s.IpmiWire, api.NIC_TYPE_IPMI, api.NETWORK_TYPE_IPMI, true, s.IpmiIpAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("BmManager add ipmi netif failed: %s", err)
|
||||
return "", fmt.Errorf("BmManager add ipmi netif failed: %s", err)
|
||||
}
|
||||
for _, nic := range nicinfo {
|
||||
if nic.Dev != s.accessNic.Dev {
|
||||
@@ -121,22 +161,41 @@ func (s *sBaremetalRegisterTask) CreateBaremetal() error {
|
||||
}
|
||||
}
|
||||
s.baremetal = pxeBm.(IBaremetal)
|
||||
return nil
|
||||
bmInstanceId, _ := res.GetString("id")
|
||||
return bmInstanceId, nil
|
||||
}
|
||||
|
||||
func (s *sBaremetalRegisterTask) update() {
|
||||
|
||||
}
|
||||
|
||||
func (s *sBaremetalRegisterTask) DoPrepare(cli *ssh.Client) error {
|
||||
func (s *sBaremetalRegisterTask) doRedfishProbe(ctx context.Context) (redfishSupport bool, cdromBoot bool) {
|
||||
redfishCli := redfish.NewRedfishDriver(ctx, "https://"+s.IpmiIpAddr, s.IpmiUsername, s.IpmiPassword, false)
|
||||
if redfishCli != nil {
|
||||
_, cdInfo, _ := redfishCli.GetVirtualCdromInfo(ctx)
|
||||
redfishSupport = true
|
||||
cdromBoot = cdInfo.SupportAction
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sBaremetalRegisterTask) DoPrepare(ctx context.Context, cli *ssh.Client) error {
|
||||
infos, err := s.prepareBaremetalInfo(cli)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
redfishSupport, cdromSupport := s.doRedfishProbe(ctx)
|
||||
|
||||
infos.ipmiInfo.IpAddr = s.IpmiIpAddr
|
||||
infos.ipmiInfo.Username = s.IpmiUsername
|
||||
infos.ipmiInfo.Password = s.IpmiPassword
|
||||
infos.ipmiInfo.LanChannel = s.IpmiLanChannel
|
||||
infos.ipmiInfo.Verified = true
|
||||
infos.ipmiInfo.Present = true
|
||||
infos.ipmiInfo.RedfishApi = redfishSupport
|
||||
infos.ipmiInfo.CdromBoot = cdromSupport
|
||||
|
||||
s.updateIpmiInfo(cli)
|
||||
|
||||
return s.updateBmInfo(cli, infos)
|
||||
|
||||
@@ -106,6 +106,7 @@ func (self *SBaremetalCdromTask) DoInsertISO(ctx context.Context, args interface
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "MountVirtualCdrom")
|
||||
}
|
||||
self.Baremetal.AutoSyncStatus()
|
||||
SetTaskComplete(self, nil)
|
||||
return nil
|
||||
}
|
||||
@@ -119,6 +120,7 @@ func (self *SBaremetalCdromTask) DoEjectISO(ctx context.Context, args interface{
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "UmountVirtualCdrom")
|
||||
}
|
||||
self.Baremetal.AutoSyncStatus()
|
||||
SetTaskComplete(self, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -688,7 +688,7 @@ func (adapter *MegaRaidAdaptor) storcliIsJBODEnabled() bool {
|
||||
line = strings.ToLower(line)
|
||||
if strings.HasPrefix(line, "jbod") {
|
||||
data := strings.Split(line, " ")
|
||||
if strings.TrimSpace(data[1]) == "on" {
|
||||
if strings.TrimSpace(data[len(data)-1]) == "on" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -16,10 +16,10 @@ package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
@@ -30,23 +30,19 @@ import (
|
||||
func InitAuth(options *common_options.CommonOptions, authComplete auth.AuthCompletedCallback) {
|
||||
|
||||
if len(options.AuthURL) == 0 {
|
||||
fmt.Println("Missing AuthURL")
|
||||
os.Exit(1)
|
||||
log.Fatalln("Missing AuthURL")
|
||||
}
|
||||
|
||||
if len(options.AdminUser) == 0 {
|
||||
fmt.Println("Mising AdminUser")
|
||||
os.Exit(1)
|
||||
log.Fatalln("Mising AdminUser")
|
||||
}
|
||||
|
||||
if len(options.AdminPassword) == 0 {
|
||||
fmt.Println("Missing AdminPasswd")
|
||||
os.Exit(1)
|
||||
log.Fatalln("Missing AdminPasswd")
|
||||
}
|
||||
|
||||
if len(options.AdminProject) == 0 {
|
||||
fmt.Println("Missing AdminProject")
|
||||
os.Exit(1)
|
||||
log.Fatalln("Missing AdminProject")
|
||||
}
|
||||
|
||||
a := auth.NewAuthInfo(
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
@@ -65,19 +66,21 @@ func MergeServiceConfig(opts interface{}, serviceType string, serviceVersion str
|
||||
if len(serviceId) > 0 {
|
||||
serviceConf, err := getServiceConfig(s, serviceId)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getServiceConfig")
|
||||
log.Errorf("getServiceConfig for %s failed: %s", serviceType, err)
|
||||
} else {
|
||||
conf.Update(serviceConf)
|
||||
merged = true
|
||||
}
|
||||
conf.Update(serviceConf)
|
||||
merged = true
|
||||
}
|
||||
commonServiceId, _ := getServiceIdByType(s, consts.COMMON_SERVICE, "")
|
||||
if len(commonServiceId) > 0 {
|
||||
commonConf, err := getServiceConfig(s, commonServiceId)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getServiceConfig common service")
|
||||
log.Errorf("getServiceConfig for %s failed: %s", consts.COMMON_SERVICE, err)
|
||||
} else {
|
||||
conf.Update(commonConf)
|
||||
merged = true
|
||||
}
|
||||
conf.Update(commonConf)
|
||||
merged = true
|
||||
}
|
||||
if merged {
|
||||
err := conf.Unmarshal(opts)
|
||||
@@ -89,7 +92,8 @@ func MergeServiceConfig(opts interface{}, serviceType string, serviceVersion str
|
||||
nconf.Add(conf, "config", "default")
|
||||
_, err := modules.ServicesV3.PerformAction(s, serviceId, "config", nconf)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "modules.ServicesV3.PerformAction")
|
||||
// ignore the error
|
||||
log.Errorf("fail to save config: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,6 +401,7 @@ func FetchServerCreateInputByJSON(obj jsonutils.JSONObject) (*compute.ServerCrea
|
||||
if secgroup := jsonutils.GetAnyString(obj, []string{"secgroup", "secgroup_id", "secgrp_id"}); len(secgroup) != 0 {
|
||||
input.SecgroupId = secgroup
|
||||
}
|
||||
input.Secgroups, _ = jsonutils.GetStringArray(obj, "secgroups")
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ var (
|
||||
tenantCacheExpireSeconds = 900
|
||||
|
||||
nonDefaultDomainProjects = false
|
||||
|
||||
defaultPagingLimit int64 = 2048
|
||||
maxPagingLimit int64 = 2048
|
||||
)
|
||||
|
||||
func SetRegion(region string) {
|
||||
@@ -61,3 +64,11 @@ func SetNonDefaultDomainProjects(val bool) {
|
||||
func GetNonDefaultDomainProjects() bool {
|
||||
return nonDefaultDomainProjects
|
||||
}
|
||||
|
||||
func GetDefaultPagingLimit() int64 {
|
||||
return defaultPagingLimit
|
||||
}
|
||||
|
||||
func GetMaxPagingLimit() int64 {
|
||||
return maxPagingLimit
|
||||
}
|
||||
|
||||
@@ -52,9 +52,31 @@ func InitDB(options *common_options.DBOptions) {
|
||||
}
|
||||
sqlchemy.SetDB(dbConn)
|
||||
|
||||
lm := lockman.NewInMemoryLockManager()
|
||||
switch options.LockmanMethod {
|
||||
case "inmemory", "":
|
||||
log.Infof("using inmemory lockman")
|
||||
lm := lockman.NewInMemoryLockManager()
|
||||
lockman.Init(lm)
|
||||
case "etcd":
|
||||
log.Infof("using etcd lockman")
|
||||
tlsCfg, err := options.GetEtcdTLSConfig()
|
||||
if err != nil {
|
||||
log.Fatalln(err.Error())
|
||||
}
|
||||
lm, err := lockman.NewEtcdLockManager(&lockman.SEtcdLockManagerConfig{
|
||||
Endpoints: options.EtcdEndpoints,
|
||||
Username: options.EtcdUsername,
|
||||
Password: options.EtcdPassword,
|
||||
LockTTL: options.EtcdLockTTL,
|
||||
LockPrefix: options.EtcdLockPrefix,
|
||||
TLS: tlsCfg,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("etcd lockman: %v", err)
|
||||
}
|
||||
lockman.Init(lm)
|
||||
}
|
||||
// lm := lockman.NewNoopLockManager()
|
||||
lockman.Init(lm)
|
||||
}
|
||||
|
||||
func CloseDB() {
|
||||
|
||||
@@ -442,7 +442,7 @@ func fetchContextObject(manager IModelManager, ctx context.Context, userCred mcc
|
||||
|
||||
func ListItems(manager IModelManager, ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, ctxIds []dispatcher.SResourceContext) (*modulebase.ListResult, error) {
|
||||
var err error
|
||||
var maxLimit int64 = 2048
|
||||
var maxLimit int64 = consts.GetMaxPagingLimit()
|
||||
limit, _ := query.Int("limit")
|
||||
offset, _ := query.Int("offset")
|
||||
pagingMarker, _ := query.GetString("paging_marker")
|
||||
@@ -473,6 +473,9 @@ func ListItems(manager IModelManager, ctx context.Context, userCred mcclient.Tok
|
||||
var totalCnt int
|
||||
pagingConf := manager.GetPagingConfig()
|
||||
if pagingConf == nil {
|
||||
if limit == 0 {
|
||||
limit = consts.GetDefaultPagingLimit()
|
||||
}
|
||||
totalCnt, err = q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -572,10 +575,7 @@ func ListItems(manager IModelManager, ctx context.Context, userCred mcclient.Tok
|
||||
}
|
||||
nextMarker := ""
|
||||
if int64(len(retList)) > limit {
|
||||
markerObj, _ := retList[limit].Get(pagingConf.MarkerField)
|
||||
if markerObj != nil {
|
||||
nextMarker = fmt.Sprintf("%s", markerObj)
|
||||
}
|
||||
nextMarker, _ = retList[limit].GetString(pagingConf.MarkerField)
|
||||
retList = retList[:limit]
|
||||
}
|
||||
retResult := modulebase.ListResult{
|
||||
@@ -670,14 +670,14 @@ func getModelExtraDetails(item IModel, ctx context.Context, extra *jsonutils.JSO
|
||||
err := item.ValidateDeleteCondition(ctx)
|
||||
if err != nil {
|
||||
extra.Add(jsonutils.JSONFalse, "can_delete")
|
||||
extra.Add(jsonutils.NewString(httputils.ErrorMsg(err)), "delete_fail_reason")
|
||||
extra.Add(jsonutils.NewString(err.Error()), "delete_fail_reason")
|
||||
} else {
|
||||
extra.Add(jsonutils.JSONTrue, "can_delete")
|
||||
}
|
||||
err = item.ValidateUpdateCondition(ctx)
|
||||
if err != nil {
|
||||
extra.Add(jsonutils.JSONFalse, "can_update")
|
||||
extra.Add(jsonutils.NewString(httputils.ErrorMsg(err)), "update_fail_reason")
|
||||
extra.Add(jsonutils.NewString(err.Error()), "update_fail_reason")
|
||||
} else {
|
||||
extra.Add(jsonutils.JSONTrue, "can_update")
|
||||
}
|
||||
@@ -794,16 +794,16 @@ func (dispatcher *DBModelDispatcher) Get(ctx context.Context, idStr string, quer
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// log.Debugf("Get found %s", model)
|
||||
var isAllow bool
|
||||
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isObjectRbacAllowed(model, userCred, policy.PolicyActionGet)
|
||||
} else {
|
||||
isAllow = model.AllowGetDetails(ctx, userCred, query)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isObjectRbacAllowed(model, userCred, policy.PolicyActionGet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !model.AllowGetDetails(ctx, userCred, query) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to get details")
|
||||
}
|
||||
|
||||
if userCred.HasSystemAdminPrivilege() && dispatcher.modelManager.GetSkipLog(ctx, userCred, query) {
|
||||
appParams := appsrv.AppContextGetParams(ctx)
|
||||
if appParams != nil {
|
||||
@@ -831,9 +831,11 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
|
||||
specCamel := utils.Kebab2Camel(spec, "-")
|
||||
modelValue := reflect.ValueOf(model)
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isObjectRbacAllowed(model, userCred, policy.PolicyActionGet, spec)
|
||||
err := isObjectRbacAllowed(model, userCred, policy.PolicyActionGet, spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
funcName := fmt.Sprintf("AllowGetDetails%s", specCamel)
|
||||
|
||||
@@ -846,11 +848,9 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
|
||||
if len(outs) != 1 {
|
||||
return nil, httperrors.NewInternalServerError("Invald %s return value", funcName)
|
||||
}
|
||||
isAllow = outs[0].Bool()
|
||||
}
|
||||
|
||||
if !isAllow {
|
||||
return nil, httperrors.NewForbiddenError("%s not allow to get spec %s", dispatcher.Keyword(), spec)
|
||||
if !outs[0].Bool() {
|
||||
return nil, httperrors.NewForbiddenError("%s not allow to get spec %s", dispatcher.Keyword(), spec)
|
||||
}
|
||||
}
|
||||
|
||||
funcName := fmt.Sprintf("GetDetails%s", specCamel)
|
||||
@@ -1082,13 +1082,12 @@ func (dispatcher *DBModelDispatcher) Create(ctx context.Context, query jsonutils
|
||||
}
|
||||
}
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isClassRbacAllowed(dispatcher.modelManager, userCred, ownerId, policy.PolicyActionCreate)
|
||||
} else {
|
||||
isAllow = dispatcher.modelManager.AllowCreateItem(ctx, userCred, query, data)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isClassRbacAllowed(dispatcher.modelManager, userCred, ownerId, policy.PolicyActionCreate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !dispatcher.modelManager.AllowCreateItem(ctx, userCred, query, data) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to create item")
|
||||
}
|
||||
|
||||
@@ -1152,13 +1151,12 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
|
||||
}
|
||||
}
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isClassRbacAllowed(manager, userCred, ownerId, policy.PolicyActionCreate)
|
||||
} else {
|
||||
isAllow = manager.AllowCreateItem(ctx, userCred, query, data)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isClassRbacAllowed(manager, userCred, ownerId, policy.PolicyActionCreate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !manager.AllowCreateItem(ctx, userCred, query, data) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to create item")
|
||||
}
|
||||
|
||||
@@ -1252,19 +1250,14 @@ func managerPerformCheckCreateData(
|
||||
query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
body, err := data.(*jsonutils.JSONDict).Get(manager.Keyword())
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
bodyDict := body.(*jsonutils.JSONDict)
|
||||
bodyDict := data.(*jsonutils.JSONDict)
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isClassRbacAllowed(manager, userCred, ownerId, policy.PolicyActionPerform, action)
|
||||
} else {
|
||||
isAllow = manager.AllowPerformCheckCreateData(ctx, userCred, query, data)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isClassRbacAllowed(manager, userCred, ownerId, policy.PolicyActionPerform, action)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !manager.AllowPerformCheckCreateData(ctx, userCred, query, data) {
|
||||
return nil, httperrors.NewForbiddenError("not allow to perform %s", action)
|
||||
}
|
||||
|
||||
@@ -1380,16 +1373,21 @@ func reflectDispatcherInternal(
|
||||
}
|
||||
}
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
if model == nil {
|
||||
ownerId, err := fetchOwnerId(ctx, dispatcher.modelManager, userCred, data)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
isAllow = isClassRbacAllowed(dispatcher.modelManager, userCred, ownerId, operator, spec)
|
||||
err = isClassRbacAllowed(dispatcher.modelManager, userCred, ownerId, operator, spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
isAllow = isObjectRbacAllowed(model, userCred, operator, spec)
|
||||
err := isObjectRbacAllowed(model, userCred, operator, spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
allowFuncName := "Allow" + funcName
|
||||
@@ -1405,10 +1403,9 @@ func reflectDispatcherInternal(
|
||||
return nil, httperrors.NewInternalServerError("Invald %s return value", allowFuncName)
|
||||
}
|
||||
|
||||
isAllow = outs[0].Bool()
|
||||
}
|
||||
if !isAllow {
|
||||
return nil, httperrors.NewForbiddenError("%s not allow to %s %s", dispatcher.Keyword(), operator, spec)
|
||||
if !outs[0].Bool() {
|
||||
return nil, httperrors.NewForbiddenError("%s not allow to %s %s", dispatcher.Keyword(), operator, spec)
|
||||
}
|
||||
}
|
||||
|
||||
outs := funcValue.Call(params)
|
||||
@@ -1495,13 +1492,12 @@ func (dispatcher *DBModelDispatcher) Update(ctx context.Context, idStr string, q
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isObjectRbacAllowed(model, userCred, policy.PolicyActionUpdate)
|
||||
} else {
|
||||
isAllow = model.AllowUpdateItem(ctx, userCred)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isObjectRbacAllowed(model, userCred, policy.PolicyActionUpdate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !model.AllowUpdateItem(ctx, userCred) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to update item")
|
||||
}
|
||||
|
||||
@@ -1599,14 +1595,12 @@ func (dispatcher *DBModelDispatcher) Delete(ctx context.Context, idstr string, q
|
||||
}
|
||||
// log.Debugf("Delete %s", model.GetShortDesc(ctx))
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isObjectRbacAllowed(model, userCred, policy.PolicyActionDelete)
|
||||
} else {
|
||||
isAllow = model.AllowDeleteItem(ctx, userCred, query, data)
|
||||
}
|
||||
if !isAllow {
|
||||
log.Errorf("not allow to delete")
|
||||
err := isObjectRbacAllowed(model, userCred, policy.PolicyActionDelete)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !model.AllowDeleteItem(ctx, userCred, query, data) {
|
||||
return nil, httperrors.NewForbiddenError("%s(%s) not allow to delete", dispatcher.modelManager.KeywordPlural(), model.GetId())
|
||||
}
|
||||
|
||||
|
||||
@@ -144,27 +144,28 @@ func (dispatcher *DBJointModelDispatcher) Get(ctx context.Context, id1 string, i
|
||||
} else if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isJointObjectRbacAllowed(item, userCred, policy.PolicyActionGet)
|
||||
} else {
|
||||
isAllow = item.AllowGetJointDetails(ctx, userCred, query, item)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isJointObjectRbacAllowed(item, userCred, policy.PolicyActionGet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !item.AllowGetJointDetails(ctx, userCred, query, item) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to get details")
|
||||
}
|
||||
return getItemDetails(dispatcher.JointModelManager(), item, ctx, userCred, query)
|
||||
}
|
||||
|
||||
func attachItems(dispatcher *DBJointModelDispatcher, master IStandaloneModel, slave IStandaloneModel, ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isObjectRbacAllowed(master, userCred, policy.PolicyActionPerform, "attach") &&
|
||||
isObjectRbacAllowed(slave, userCred, policy.PolicyActionPerform, "attach")
|
||||
} else {
|
||||
isAllow = dispatcher.JointModelManager().AllowAttach(ctx, userCred, master, slave)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isObjectRbacAllowed(master, userCred, policy.PolicyActionPerform, "attach")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = isObjectRbacAllowed(slave, userCred, policy.PolicyActionPerform, "attach")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !dispatcher.JointModelManager().AllowAttach(ctx, userCred, master, slave) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to attach")
|
||||
}
|
||||
// ownerProjId, err := fetchOwnerId(ctx, dispatcher.JointModelManager(), userCred, data)
|
||||
@@ -236,13 +237,12 @@ func (dispatcher *DBJointModelDispatcher) Update(ctx context.Context, id1 string
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isJointObjectRbacAllowed(item, userCred, policy.PolicyActionUpdate)
|
||||
} else {
|
||||
isAllow = item.AllowUpdateJointItem(ctx, userCred, item)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isJointObjectRbacAllowed(item, userCred, policy.PolicyActionUpdate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !item.AllowUpdateJointItem(ctx, userCred, item) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to update item")
|
||||
}
|
||||
|
||||
@@ -260,14 +260,16 @@ func (dispatcher *DBJointModelDispatcher) Detach(ctx context.Context, id1 string
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isObjectRbacAllowed(master, userCred, policy.PolicyActionPerform, "detach") &&
|
||||
isObjectRbacAllowed(slave, userCred, policy.PolicyActionPerform, "detach")
|
||||
} else {
|
||||
isAllow = item.AllowDetach(ctx, userCred, query, data)
|
||||
}
|
||||
if !isAllow {
|
||||
err := isObjectRbacAllowed(master, userCred, policy.PolicyActionPerform, "detach")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = isObjectRbacAllowed(slave, userCred, policy.PolicyActionPerform, "detach")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if !item.AllowDetach(ctx, userCred, query, data) {
|
||||
return nil, httperrors.NewForbiddenError("Not allow to attach")
|
||||
}
|
||||
|
||||
|
||||
@@ -386,7 +386,7 @@ func FetchCheckQueryOwnerScope(ctx context.Context, userCred mcclient.TokenCrede
|
||||
requireScope = queryScope
|
||||
}
|
||||
if doCheckRbac && requireScope.HigherThan(allowScope) {
|
||||
return nil, scope, httperrors.NewForbiddenError(fmt.Sprintf("not enough privilleges(require:%s,allow:%s,query:%s)", requireScope, allowScope, queryScope))
|
||||
return nil, scope, httperrors.NewForbiddenError(fmt.Sprintf("not enough privilege(require:%s,allow:%s,query:%s)", requireScope, allowScope, queryScope))
|
||||
}
|
||||
return ownerId, queryScope, nil
|
||||
}
|
||||
|
||||
@@ -177,6 +177,8 @@ type IModel interface {
|
||||
IsSharable(reqCred mcclient.IIdentityProvider) bool
|
||||
|
||||
CustomizedGetDetailsBody(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error)
|
||||
MarkDeletePreventionOn()
|
||||
MarkDeletePreventionOff()
|
||||
}
|
||||
|
||||
type IResourceModelManager interface {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017 The etcd Authors
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -12,19 +12,16 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package clientv3
|
||||
package lockman
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"yunion.io/x/log"
|
||||
)
|
||||
|
||||
// TODO: remove this when "FailFast=false" is fixed.
|
||||
// See https://github.com/grpc/grpc-go/issues/1532.
|
||||
func readyWait(rpcCtx, clientCtx context.Context, ready <-chan struct{}) error {
|
||||
select {
|
||||
case <-ready:
|
||||
return nil
|
||||
case <-rpcCtx.Done():
|
||||
return rpcCtx.Err()
|
||||
case <-clientCtx.Done():
|
||||
return clientCtx.Err()
|
||||
}
|
||||
type bugFunc func(fmtStr string, fmtArgs ...interface{})
|
||||
|
||||
var defaultBugFunc bugFunc = func(fmtStr string, fmtArgs ...interface{}) {
|
||||
log.Errorf("BUG: "+fmtStr, fmtArgs...)
|
||||
}
|
||||
|
||||
var bug bugFunc = defaultBugFunc
|
||||
267
pkg/cloudcommon/db/lockman/etcd.go
Normal file
267
pkg/cloudcommon/db/lockman/etcd.go
Normal file
@@ -0,0 +1,267 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package lockman
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
"go.etcd.io/etcd/clientv3/concurrency"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/atexit"
|
||||
)
|
||||
|
||||
type SEtcdLockRecord struct {
|
||||
m *sync.Mutex
|
||||
depth int
|
||||
|
||||
pfx string
|
||||
sess *concurrency.Session
|
||||
em *concurrency.Mutex
|
||||
}
|
||||
|
||||
func newEtcdLockRecord(ctx context.Context, lockman *SEtcdLockManager, key string) *SEtcdLockRecord {
|
||||
pfx := fmt.Sprintf("%s/%s", lockman.config.LockPrefix, key)
|
||||
sess, err := concurrency.NewSession(lockman.cli, concurrency.WithTTL(lockman.config.LockTTL))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("%s: create etcd session: %v", pfx, err))
|
||||
}
|
||||
em := concurrency.NewMutex(sess, pfx)
|
||||
rec := SEtcdLockRecord{
|
||||
m: &sync.Mutex{},
|
||||
depth: 0,
|
||||
|
||||
pfx: pfx,
|
||||
sess: sess,
|
||||
em: em,
|
||||
}
|
||||
return &rec
|
||||
}
|
||||
|
||||
func (rec *SEtcdLockRecord) lockContext(ctx context.Context) {
|
||||
rec.m.Lock()
|
||||
defer rec.m.Unlock()
|
||||
|
||||
rec.depth += 1
|
||||
if rec.depth > 32 {
|
||||
// NOTE callers are responsible for ensuring unlock got called
|
||||
bug("%s: depth > 32", rec.pfx)
|
||||
panic(debug.Stack())
|
||||
}
|
||||
|
||||
if err := rec.em.Lock(ctx); err != nil {
|
||||
msg := fmt.Sprintf("%s: etcd lock: %v", rec.pfx, err)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
if debug_log {
|
||||
log.Infof("%s: lock depth %d\n%s", rec.pfx, rec.depth, debug.Stack())
|
||||
}
|
||||
}
|
||||
|
||||
func (rec *SEtcdLockRecord) unlockContext(ctx context.Context) (needClean bool) {
|
||||
rec.m.Lock()
|
||||
defer rec.m.Unlock()
|
||||
|
||||
if debug_log {
|
||||
log.Infof("%s: unlock depth %d\n%s", rec.pfx, rec.depth, debug.Stack())
|
||||
}
|
||||
|
||||
rec.depth -= 1
|
||||
if rec.depth <= 0 {
|
||||
if rec.depth < 0 {
|
||||
bug("%s: overly unlocked", rec.pfx)
|
||||
}
|
||||
|
||||
// Other players can make progress once lock record got removed
|
||||
// after this
|
||||
//
|
||||
// There is no need to unlock rec.em. Revoke the session lease
|
||||
// will trigger etcd to do that. Should the remote revoke call
|
||||
// fail, we expect the lease auto-refresh to stop and the lease
|
||||
// will expire in known time limit.
|
||||
closed := false
|
||||
for i := 0; i < 3; i++ {
|
||||
if err := rec.sess.Close(); err != nil {
|
||||
log.Errorf("%s: session close: %s", rec.pfx, err)
|
||||
if i < 2 {
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
continue
|
||||
}
|
||||
closed = true
|
||||
break
|
||||
}
|
||||
if !closed {
|
||||
log.Errorf("%s: session close failure", rec.pfx)
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type SEtcdLockManagerConfig struct {
|
||||
Endpoints []string
|
||||
Username string
|
||||
Password string
|
||||
TLS *tls.Config
|
||||
|
||||
LockTTL int
|
||||
LockPrefix string
|
||||
|
||||
dialOptions []grpc.DialOption
|
||||
dialTimeout time.Duration
|
||||
}
|
||||
|
||||
func (config *SEtcdLockManagerConfig) validate() error {
|
||||
if len(config.Endpoints) == 0 {
|
||||
return fmt.Errorf("no etcd endpoint configured")
|
||||
}
|
||||
if config.dialTimeout <= 0 {
|
||||
config.dialTimeout = 3 * time.Second
|
||||
}
|
||||
if len(config.dialOptions) == 0 {
|
||||
// let it fail right away
|
||||
config.dialOptions = []grpc.DialOption{
|
||||
grpc.WithBlock(),
|
||||
grpc.WithTimeout(500 * time.Millisecond),
|
||||
}
|
||||
}
|
||||
if config.LockTTL <= 0 {
|
||||
config.LockTTL = 10
|
||||
}
|
||||
config.LockPrefix = strings.TrimSpace(config.LockPrefix)
|
||||
config.LockPrefix = strings.TrimRight(config.LockPrefix, "/")
|
||||
if config.LockPrefix == "" {
|
||||
config.LockPrefix = "/"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type SLockTableIndex struct {
|
||||
key string
|
||||
holder context.Context
|
||||
}
|
||||
|
||||
type SEtcdLockManager struct {
|
||||
tableLock *sync.Mutex
|
||||
lockTable map[SLockTableIndex]*SEtcdLockRecord
|
||||
|
||||
config *SEtcdLockManagerConfig
|
||||
cli *clientv3.Client
|
||||
}
|
||||
|
||||
func NewEtcdLockManager(config *SEtcdLockManagerConfig) (ILockManager, error) {
|
||||
if err := config.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cli, err := clientv3.New(clientv3.Config{
|
||||
Endpoints: config.Endpoints,
|
||||
Username: config.Username,
|
||||
Password: config.Password,
|
||||
TLS: config.TLS,
|
||||
|
||||
DialOptions: config.dialOptions,
|
||||
DialTimeout: config.dialTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new etcd client")
|
||||
}
|
||||
lockman := SEtcdLockManager{
|
||||
tableLock: &sync.Mutex{},
|
||||
lockTable: map[SLockTableIndex]*SEtcdLockRecord{},
|
||||
|
||||
cli: cli,
|
||||
config: config,
|
||||
}
|
||||
atexit.Register(atexit.ExitHandler{
|
||||
Prio: atexit.PRIO_LOG_OTHER,
|
||||
Reason: "etcd-lockman",
|
||||
Value: lockman,
|
||||
Func: atexit.ExitHandlerFunc(lockman.destroyAtExit),
|
||||
})
|
||||
return &lockman, nil
|
||||
}
|
||||
|
||||
func (lockman *SEtcdLockManager) destroyAtExit(eh atexit.ExitHandler) {
|
||||
log.Infof("closing etcd lockman session")
|
||||
for _, rec := range lockman.lockTable {
|
||||
if err := rec.sess.Close(); err != nil {
|
||||
log.Errorf("%s: session close: %v", rec.pfx, err)
|
||||
}
|
||||
}
|
||||
if err := lockman.cli.Close(); err != nil {
|
||||
log.Errorf("etcd lockman client close: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (lockman *SEtcdLockManager) getRecordWithLock(ctx context.Context, key string) *SEtcdLockRecord {
|
||||
lockman.tableLock.Lock()
|
||||
defer lockman.tableLock.Unlock()
|
||||
|
||||
return lockman.getRecord(ctx, key, true)
|
||||
}
|
||||
|
||||
func (lockman *SEtcdLockManager) getRecord(ctx context.Context, key string, alloc bool) *SEtcdLockRecord {
|
||||
idx := SLockTableIndex{
|
||||
key: key,
|
||||
holder: ctx,
|
||||
}
|
||||
_, ok := lockman.lockTable[idx]
|
||||
if !ok {
|
||||
if !alloc {
|
||||
return nil
|
||||
}
|
||||
lockman.lockTable[idx] = newEtcdLockRecord(ctx, lockman, key)
|
||||
}
|
||||
return lockman.lockTable[idx]
|
||||
}
|
||||
|
||||
func (lockman *SEtcdLockManager) LockKey(ctx context.Context, key string) {
|
||||
record := lockman.getRecordWithLock(ctx, key)
|
||||
|
||||
record.lockContext(ctx)
|
||||
}
|
||||
|
||||
func (lockman *SEtcdLockManager) UnlockKey(ctx context.Context, key string) {
|
||||
lockman.tableLock.Lock()
|
||||
defer lockman.tableLock.Unlock()
|
||||
|
||||
record := lockman.getRecord(ctx, key, false)
|
||||
if record == nil {
|
||||
bug("%s: unlock a non-existent lock\n%s", key, debug.Stack())
|
||||
return
|
||||
}
|
||||
|
||||
needClean := record.unlockContext(ctx)
|
||||
if needClean {
|
||||
idx := SLockTableIndex{
|
||||
key: key,
|
||||
holder: ctx,
|
||||
}
|
||||
delete(lockman.lockTable, idx)
|
||||
}
|
||||
}
|
||||
52
pkg/cloudcommon/db/lockman/etcd_test.go
Normal file
52
pkg/cloudcommon/db/lockman/etcd_test.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package lockman
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/atexit"
|
||||
)
|
||||
|
||||
func TestEctdLockManager(t *testing.T) {
|
||||
cfgs := []*testLockManagerConfig{}
|
||||
shared := newSharedObject()
|
||||
for i := 0; i < 4; i++ {
|
||||
lockman, err := NewEtcdLockManager(&SEtcdLockManagerConfig{
|
||||
Endpoints: []string{"localhost:2379"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Skipf("new etcd lockman: %v", err)
|
||||
}
|
||||
cfg := &testLockManagerConfig{
|
||||
players: 3,
|
||||
cycles: 3,
|
||||
lockman: lockman,
|
||||
shared: shared,
|
||||
}
|
||||
cfgs = append(cfgs, cfg)
|
||||
}
|
||||
defer atexit.Handle()
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(len(cfgs))
|
||||
for _, cfg := range cfgs {
|
||||
go func(cfg *testLockManagerConfig) {
|
||||
testLockManager(t, cfg)
|
||||
wg.Done()
|
||||
}(cfg)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func (lockman *SInMemoryLockManager) UnlockKey(ctx context.Context, key string)
|
||||
|
||||
record := lockman.getRecord(ctx, key, false)
|
||||
if record == nil {
|
||||
log.Warningf("unlock an none exist lock????")
|
||||
log.Errorf("BUG: unlock an non-existent lock\n%s", debug.Stack())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -15,56 +15,17 @@
|
||||
package lockman
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
)
|
||||
|
||||
type FakeObject struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
func (o *FakeObject) GetId() string {
|
||||
return o.Id
|
||||
}
|
||||
|
||||
func (o *FakeObject) Keyword() string {
|
||||
return "fake"
|
||||
}
|
||||
|
||||
func run(t *testing.T, ctx context.Context, obj ILockedObject, id int, sleep time.Duration) {
|
||||
t.Logf("ready to run at %d [%p]", id, ctx)
|
||||
LockObject(ctx, obj)
|
||||
defer ReleaseObject(ctx, obj)
|
||||
t.Logf("Acquire obj at %d [%p]", id, ctx)
|
||||
time.Sleep(sleep)
|
||||
t.Logf("Release obj at %d [%p]", id, ctx)
|
||||
}
|
||||
|
||||
func TestInMemoryLockManager(t *testing.T) {
|
||||
Init(NewInMemoryLockManager())
|
||||
objId := stringutils.UUID4()
|
||||
cycle := 1
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
t.Log("Start")
|
||||
|
||||
for id := 0; id <= 3; id += 1 {
|
||||
wg.Add(1)
|
||||
go func(localId int) {
|
||||
t.Logf("Start %d", localId)
|
||||
ctx := context.WithValue(context.Background(), "ID", localId)
|
||||
for i := 0; i < cycle; i += 1 {
|
||||
obj := &FakeObject{Id: objId}
|
||||
run(t, ctx, obj, localId, time.Duration(localId)*time.Second)
|
||||
}
|
||||
wg.Done()
|
||||
}(id)
|
||||
lockman := NewInMemoryLockManager()
|
||||
shared := newSharedObject()
|
||||
cfg := &testLockManagerConfig{
|
||||
players: 3,
|
||||
cycles: 3,
|
||||
lockman: lockman,
|
||||
shared: shared,
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
testLockManager(t, cfg)
|
||||
}
|
||||
|
||||
126
pkg/cloudcommon/db/lockman/lockman_test.go
Normal file
126
pkg/cloudcommon/db/lockman/lockman_test.go
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package lockman
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
)
|
||||
|
||||
type FakeObject struct {
|
||||
Id string
|
||||
|
||||
playerId int
|
||||
playerIdCount int
|
||||
}
|
||||
|
||||
func (o *FakeObject) GetId() string {
|
||||
return o.Id
|
||||
}
|
||||
|
||||
func (o *FakeObject) Keyword() string {
|
||||
return "fake"
|
||||
}
|
||||
|
||||
func (o *FakeObject) push(playerId int) {
|
||||
if o.playerId >= 0 {
|
||||
if o.playerId != playerId {
|
||||
panic(fmt.Sprintf("obj locked by %d, locked again by %d", o.playerId, playerId))
|
||||
}
|
||||
} else {
|
||||
if o.playerIdCount != 0 {
|
||||
panic(fmt.Sprintf("obj unlocked but player id count %d", o.playerIdCount))
|
||||
}
|
||||
o.playerId = playerId
|
||||
}
|
||||
o.playerIdCount += 1
|
||||
}
|
||||
|
||||
func (o *FakeObject) pop(playerId int) {
|
||||
if o.playerId != playerId {
|
||||
panic(fmt.Sprintf("obj previously locked by %d, now unlocked by %d", o.playerId, playerId))
|
||||
}
|
||||
o.playerIdCount -= 1
|
||||
if o.playerIdCount < 0 {
|
||||
panic(fmt.Sprintf("obj overly unlocked"))
|
||||
} else if o.playerIdCount == 0 {
|
||||
o.playerId = -1
|
||||
}
|
||||
}
|
||||
|
||||
func newSharedObject() *FakeObject {
|
||||
obj := &FakeObject{
|
||||
Id: stringutils.UUID4(),
|
||||
|
||||
playerId: -1,
|
||||
playerIdCount: 0,
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
type testLockManagerConfig struct {
|
||||
players int
|
||||
cycles int
|
||||
shared *FakeObject
|
||||
lockman ILockManager
|
||||
}
|
||||
|
||||
func testLockManager(t *testing.T, cfg *testLockManagerConfig) {
|
||||
players := cfg.players
|
||||
cycles := cfg.cycles
|
||||
shared := cfg.shared
|
||||
lockman := cfg.lockman
|
||||
|
||||
bug = func(fmtStr string, fmtArgs ...interface{}) {
|
||||
t.Fatalf(fmtStr, fmtArgs...)
|
||||
}
|
||||
run := func(ctx context.Context, id int, cycle int, sleep time.Duration) {
|
||||
key := getObjectKey(shared)
|
||||
indents := []string{" ", " "}
|
||||
logpref := fmt.Sprintf("%p: %02d: %p", lockman, id, ctx)
|
||||
func() {
|
||||
fmt.Printf("%s: %s >acquire\n", logpref, indents[0])
|
||||
lockman.LockKey(ctx, key)
|
||||
shared.push(id)
|
||||
fmt.Printf("%s: %s >>acquired\n", logpref, indents[1])
|
||||
}()
|
||||
defer func() {
|
||||
fmt.Printf("%s: %s <<release\n", logpref, indents[1])
|
||||
shared.pop(id)
|
||||
lockman.UnlockKey(ctx, key)
|
||||
fmt.Printf("%s: %s <released\n", logpref, indents[0])
|
||||
}()
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for id := 0; id < players; id += 1 {
|
||||
wg.Add(1)
|
||||
go func(localId int) {
|
||||
ctx := context.WithValue(context.Background(), "ID", localId)
|
||||
for i := 0; i < cycles; i += 1 {
|
||||
run(ctx, localId, i, time.Duration(localId)*time.Second)
|
||||
}
|
||||
wg.Done()
|
||||
}(id)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
@@ -156,16 +157,20 @@ func (manager *SMetadataManager) ListItemFilter(ctx context.Context, q *sqlchemy
|
||||
}
|
||||
}
|
||||
conditions := []sqlchemy.ICondition{}
|
||||
admin := jsonutils.QueryBoolean(query, "admin", false)
|
||||
for _, resource := range resources {
|
||||
if man, ok := ResourceMap[resource]; ok {
|
||||
resourceView := man.Query().SubQuery()
|
||||
prefix := sqlchemy.NewStringField(fmt.Sprintf("%s::", man.Keyword()))
|
||||
field := sqlchemy.CONCAT(man.Keyword(), prefix, resourceView.Field("id"))
|
||||
sq := resourceView.Query(field)
|
||||
if !admin && !IsAllowList(rbacutils.ScopeSystem, userCred, man) {
|
||||
sq = man.FilterByOwner(sq, userCred, man.ResourceScope())
|
||||
ownerId, queryScope, err := FetchCheckQueryOwnerScope(ctx, userCred, query, man, policy.PolicyActionList, true)
|
||||
if err != nil {
|
||||
log.Warningf("FetchCheckQueryOwnerScope.%s error: %v", man.Keyword(), err)
|
||||
continue
|
||||
}
|
||||
sq = man.FilterByOwner(sq, ownerId, queryScope)
|
||||
sq = man.FilterBySystemAttributes(sq, userCred, query, queryScope)
|
||||
sq = man.FilterByHiddenSystemAttributes(sq, userCred, query, queryScope)
|
||||
conditions = append(conditions, sqlchemy.In(q.Field("id"), sq))
|
||||
} else {
|
||||
return nil, httperrors.NewInputParameterError("Not support resource %s tag filter", resource)
|
||||
@@ -224,7 +229,7 @@ func (manager *SMetadataManager) GetJsonValue(model IModel, key string, userCred
|
||||
type sMetadataChange struct {
|
||||
Key string
|
||||
OValue string
|
||||
NValue string
|
||||
NValue string `json:",allowempty"`
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) RemoveAll(ctx context.Context, model IModel, userCred mcclient.TokenCredential) error {
|
||||
|
||||
@@ -100,6 +100,14 @@ func (manager *SModelBaseManager) ValidateName(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SModelBase) MarkDeletePreventionOn() {
|
||||
return
|
||||
}
|
||||
|
||||
func (model *SModelBase) MarkDeletePreventionOff() {
|
||||
return
|
||||
}
|
||||
|
||||
// list hooks
|
||||
func (manager *SModelBaseManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return false
|
||||
|
||||
@@ -77,7 +77,7 @@ func CheckSync(autoSync bool) bool {
|
||||
}
|
||||
} else {
|
||||
for _, sql := range dropFKSqls {
|
||||
fmt.Println(sql)
|
||||
log.Infof("%s;", sql)
|
||||
}
|
||||
inSync = false
|
||||
}
|
||||
@@ -96,7 +96,7 @@ func CheckSync(autoSync bool) bool {
|
||||
}
|
||||
} else {
|
||||
for _, sql := range sqls {
|
||||
fmt.Println(sql)
|
||||
log.Infof("%s;", sql)
|
||||
}
|
||||
inSync = false
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ type SOpsLog struct {
|
||||
ObjId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=False)
|
||||
ObjName string `width:"128" charset:"utf8" nullable:"false" list:"user" create:"required"` //= Column(VARCHAR(128, charset='utf8'), nullable=False)
|
||||
Action string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"required"` //= Column(VARCHAR(32, charset='ascii'), nullable=False)
|
||||
Notes string `width:"2048" charset:"utf8" list:"user" create:"required"` // = Column(VARCHAR(2048, charset='utf8'))
|
||||
Notes string `charset:"utf8" list:"user" create:"required"`
|
||||
|
||||
ProjectId string `name:"tenant_id" width:"128" charset:"ascii" list:"user" create:"required" index:"true"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'))
|
||||
Project string `name:"tenant" width:"128" charset:"utf8" list:"user" create:"required"` // tenant = Column(VARCHAR(128, charset='utf8'))
|
||||
|
||||
@@ -52,9 +52,7 @@ func getAllProjectResourceCounts() (map[string][]SProjectResourceCount, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getProjectResourceCount")
|
||||
}
|
||||
if len(resCnt) > 0 {
|
||||
ret[virtman.KeywordPlural()] = resCnt
|
||||
}
|
||||
ret[virtman.KeywordPlural()] = resCnt
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
||||
@@ -15,17 +15,20 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
func IsObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
|
||||
func IsObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
|
||||
return isObjectRbacAllowed(model, userCred, action, extra...)
|
||||
}
|
||||
|
||||
func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
|
||||
func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
|
||||
manager := model.GetModelManager()
|
||||
objOwnerId := model.GetOwnerId()
|
||||
|
||||
@@ -65,17 +68,21 @@ func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), action, extra...)
|
||||
|
||||
if !requireScope.HigherThan(scope) {
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
return false
|
||||
return httperrors.NewForbiddenError(fmt.Sprintf("not enough privillege(require:%s,allow:%s)", requireScope, scope))
|
||||
}
|
||||
|
||||
func isJointObjectRbacAllowed(item IJointModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
|
||||
return isObjectRbacAllowed(item.Master(), userCred, action, extra...) || isObjectRbacAllowed(item.Slave(), userCred, action, extra...)
|
||||
func isJointObjectRbacAllowed(item IJointModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
|
||||
err1 := isObjectRbacAllowed(item.Master(), userCred, action, extra...)
|
||||
err2 := isObjectRbacAllowed(item.Slave(), userCred, action, extra...)
|
||||
if err1 == nil || err2 == nil {
|
||||
return nil
|
||||
}
|
||||
return err1
|
||||
}
|
||||
|
||||
func isClassRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential, objOwnerId mcclient.IIdentityProvider, action string, extra ...string) bool {
|
||||
func isClassRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential, objOwnerId mcclient.IIdentityProvider, action string, extra ...string) error {
|
||||
var ownerId mcclient.IIdentityProvider
|
||||
if userCred != nil {
|
||||
ownerId = userCred
|
||||
@@ -113,10 +120,9 @@ func isClassRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential
|
||||
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), action, extra...)
|
||||
|
||||
if !requireScope.HigherThan(allowScope) {
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
return false
|
||||
return httperrors.NewForbiddenError(fmt.Sprintf("not enough privilege(require:%s,allow:%s)", requireScope, allowScope))
|
||||
}
|
||||
|
||||
type IResource interface {
|
||||
|
||||
@@ -43,13 +43,23 @@ func (m *SScopedResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, userCred
|
||||
}
|
||||
switch scope {
|
||||
case rbacutils.ScopeDomain:
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("domain_id"), userCred.GetDomainId()))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("domain_id"), userCred.GetProjectDomainId()),
|
||||
sqlchemy.IsNullOrEmpty(q.Field("domain_id")),
|
||||
))
|
||||
case rbacutils.ScopeProject:
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("tenant_id"), userCred.GetProjectId()))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("tenant_id"), userCred.GetProjectId()),
|
||||
sqlchemy.IsNullOrEmpty(q.Field("tenant_id")),
|
||||
))
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func (m *SScopedResourceBaseManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
return FetchProjectInfo(ctx, data)
|
||||
}
|
||||
|
||||
func (m *SScopedResourceBaseManager) ValidateCreateData(man IScopedResourceManager, ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
scope, _ := data.GetString("scope")
|
||||
if scope == "" {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
@@ -66,12 +67,12 @@ func (model *SStatusStandaloneResourceBase) AllowPerformStatus(ctx context.Conte
|
||||
}
|
||||
|
||||
func (model *SStatusStandaloneResourceBase) PerformStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
status, err := data.GetString("status")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
status, _ := data.GetString("status")
|
||||
if len(status) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("status")
|
||||
}
|
||||
reason, _ := data.GetString("reason")
|
||||
err = model.SetStatus(userCred, status, reason)
|
||||
err := model.SetStatus(userCred, status, reason)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ func RegistUserCredCacheUpdater() {
|
||||
auth.RegisterAuthHook(onAuthCompleteUpdateCache)
|
||||
}
|
||||
|
||||
func onAuthCompleteUpdateCache(userCred mcclient.TokenCredential) {
|
||||
TenantCacheManager.updateTenantCache(userCred)
|
||||
func onAuthCompleteUpdateCache(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
TenantCacheManager.updateTenantCache(ctx, userCred)
|
||||
UserCacheManager.updateUserCache(userCred)
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ func (manager *STenantCacheManager) InitializeData() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *STenantCacheManager) updateTenantCache(userCred mcclient.TokenCredential) {
|
||||
manager.Save(context.Background(), userCred.GetProjectId(), userCred.GetProjectName(),
|
||||
func (manager *STenantCacheManager) updateTenantCache(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
manager.Save(ctx, userCred.GetProjectId(), userCred.GetProjectName(),
|
||||
userCred.GetProjectDomainId(), userCred.GetProjectDomain())
|
||||
}
|
||||
|
||||
@@ -174,8 +174,13 @@ func (manager *STenantCacheManager) fetchTenantFromKeystone(ctx context.Context,
|
||||
log.Debugf("fetch empty tenant!!!!\n%s", debug.Stack())
|
||||
return nil, fmt.Errorf("Empty idStr")
|
||||
}
|
||||
|
||||
// It is to query all domain's project.
|
||||
query := jsonutils.NewDict()
|
||||
query.Set("scope", jsonutils.NewString("system"))
|
||||
|
||||
s := auth.GetAdminSession(ctx, consts.GetRegion(), "v1")
|
||||
tenant, err := modules.Projects.GetById(s, idStr, nil)
|
||||
tenant, err := modules.Projects.GetById(s, idStr, query)
|
||||
if err != nil {
|
||||
if je, ok := err.(*httputils.JSONClientError); ok && je.Code == 404 {
|
||||
return nil, sql.ErrNoRows
|
||||
@@ -298,9 +303,9 @@ func (manager *STenantCacheManager) Save(ctx context.Context, idStr string, name
|
||||
obj.Domain = domain
|
||||
obj.DomainId = domainId
|
||||
obj.LastCheck = now
|
||||
err = manager.TableSpec().Insert(obj)
|
||||
err = manager.TableSpec().InsertOrUpdate(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "InsertOrUpdate")
|
||||
} else {
|
||||
return obj, nil
|
||||
}
|
||||
@@ -343,14 +348,14 @@ func (manager *STenantCacheManager) findFirstProjectOfDomain(domainId string) (*
|
||||
return &tenant, nil
|
||||
}
|
||||
|
||||
func (manager *STenantCacheManager) fetchDomainTenantsFromKeystone(domainId string) error {
|
||||
func (manager *STenantCacheManager) fetchDomainTenantsFromKeystone(ctx context.Context, domainId string) error {
|
||||
if len(domainId) == 0 {
|
||||
log.Debugf("fetch empty domain!!!!")
|
||||
debug.PrintStack()
|
||||
return fmt.Errorf("Empty domainId")
|
||||
}
|
||||
|
||||
s := auth.GetAdminSession(context.Background(), consts.GetRegion(), "v1")
|
||||
s := auth.GetAdminSession(ctx, consts.GetRegion(), "v1")
|
||||
params := jsonutils.Marshal(map[string]string{"domain_id": domainId})
|
||||
tenants, err := modules.Projects.List(s, params)
|
||||
if err != nil {
|
||||
@@ -361,7 +366,7 @@ func (manager *STenantCacheManager) fetchDomainTenantsFromKeystone(domainId stri
|
||||
tenantName, _ := tenant.GetString("name")
|
||||
domainId, _ := tenant.GetString("domain_id")
|
||||
domainName, _ := tenant.GetString("project_domain")
|
||||
_, err = manager.Save(context.Background(), tenantId, tenantName, domainId, domainName)
|
||||
_, err = manager.Save(ctx, tenantId, tenantName, domainId, domainName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -369,11 +374,11 @@ func (manager *STenantCacheManager) fetchDomainTenantsFromKeystone(domainId stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *STenantCacheManager) FindFirstProjectOfDomain(domainId string) (*STenant, error) {
|
||||
func (manager *STenantCacheManager) FindFirstProjectOfDomain(ctx context.Context, domainId string) (*STenant, error) {
|
||||
tenant, err := manager.findFirstProjectOfDomain(domainId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
err = manager.fetchDomainTenantsFromKeystone(domainId)
|
||||
err = manager.fetchDomainTenantsFromKeystone(ctx, domainId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetchDomainTenantsFromKeystone")
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
@@ -103,22 +105,33 @@ func (manager *SUserCacheManager) fetchUser(
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
return manager.fetchUserFromKeystone(ctx, idStr)
|
||||
return manager.FetchUserFromKeystone(ctx, idStr)
|
||||
}
|
||||
|
||||
func (manager *SUserCacheManager) fetchUserFromKeystone(ctx context.Context, idStr string) (*SUser, error) {
|
||||
func (manager *SUserCacheManager) FetchUserFromKeystone(ctx context.Context, idStr string) (*SUser, error) {
|
||||
if len(idStr) == 0 {
|
||||
log.Debugf("fetch empty user!!!!\n%s", debug.Stack())
|
||||
return nil, fmt.Errorf("Empty idStr")
|
||||
}
|
||||
|
||||
// It's to query the full list of users(contains other domain's ones and system ones)
|
||||
query := jsonutils.NewDict()
|
||||
query.Set("scope", jsonutils.NewString("system"))
|
||||
query.Set("system", jsonutils.JSONTrue)
|
||||
|
||||
s := auth.GetAdminSession(ctx, consts.GetRegion(), "v1")
|
||||
user, err := modules.UsersV3.GetById(s, idStr, nil)
|
||||
user, err := modules.UsersV3.GetById(s, idStr, query)
|
||||
if err != nil {
|
||||
if je, ok := err.(*httputils.JSONClientError); ok && je.Code == 404 {
|
||||
return nil, sql.ErrNoRows
|
||||
user, err = modules.UsersV3.GetByName(s, idStr, query)
|
||||
if je, ok := err.(*httputils.JSONClientError); ok && je.Code == 404 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("fetch user %s fail %s", idStr, err)
|
||||
return nil, errors.Wrap(err, "modules.UsersV3.Get")
|
||||
}
|
||||
log.Errorf("fetch user %s fail %s", idStr, err)
|
||||
return nil, errors.Wrap(err, "modules.UsersV3.Get")
|
||||
}
|
||||
id, _ := user.GetString("id")
|
||||
name, _ := user.GetString("name")
|
||||
@@ -133,7 +146,7 @@ func (manager *SUserCacheManager) Save(ctx context.Context, idStr string, name s
|
||||
|
||||
objo, err := manager.FetchById(idStr)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
log.Errorf("FetchTenantbyId fail %s", err)
|
||||
log.Errorf("FetchUserbyId fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
if err == nil {
|
||||
@@ -143,6 +156,7 @@ func (manager *SUserCacheManager) Save(ctx context.Context, idStr string, name s
|
||||
obj.Name = name
|
||||
obj.Domain = domain
|
||||
obj.DomainId = domainId
|
||||
obj.LastCheck = time.Now().UTC()
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -157,7 +171,8 @@ func (manager *SUserCacheManager) Save(ctx context.Context, idStr string, name s
|
||||
obj.Name = name
|
||||
obj.Domain = domain
|
||||
obj.DomainId = domainId
|
||||
err = manager.TableSpec().Insert(obj)
|
||||
obj.LastCheck = time.Now().UTC()
|
||||
err = manager.TableSpec().InsertOrUpdate(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
|
||||
@@ -111,6 +111,15 @@ func (manager *SVirtualResourceBaseManager) FilterByHiddenSystemAttributes(q *sq
|
||||
return q
|
||||
}
|
||||
|
||||
func (model *SVirtualResourceBase) SetProjectInfo(ctx context.Context, userCred mcclient.TokenCredential, projectId, domainId string) error {
|
||||
_, err := Update(model, func() error {
|
||||
model.ProjectId = projectId
|
||||
model.DomainId = domainId
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (manager *SVirtualResourceBaseManager) FilterBySystemAttributes(q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
q = manager.SStatusStandaloneResourceBaseManager.FilterBySystemAttributes(q, userCred, query, scope)
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -23,6 +26,7 @@ import (
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/log/hooks"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/reflectutils"
|
||||
"yunion.io/x/pkg/util/version"
|
||||
"yunion.io/x/pkg/utils"
|
||||
@@ -99,6 +103,71 @@ type DBOptions struct {
|
||||
DebugSqlchemy bool `default:"false" help:"Print SQL executed by sqlchemy"`
|
||||
|
||||
QueryOffsetOptimization bool `help:"apply query offset optimization"`
|
||||
|
||||
LockmanMethod string `help:"method for lock synchronization" choices:"inmemory|etcd" default:"inmemory"`
|
||||
EtcdLockPrefix string `help:"prefix of etcd lock records" default:"/locks"`
|
||||
EtcdLockTTL int `help:"ttl of etcd lock records"`
|
||||
EtcdEndpoints []string `help:"endpoints of etcd cluster"`
|
||||
|
||||
EtcdUsername string `help:"username of etcd cluster"`
|
||||
EtcdPassword string `help:"password of etcd cluster"`
|
||||
|
||||
EtcdUseTLS bool `help:"use tls transport to connect etcd cluster" default:"false"`
|
||||
EtcdSkipTLSVerify bool `help:"skip tls verification" default:"false"`
|
||||
EtcdCacert string `help:"path to cacert for connecting to etcd cluster"`
|
||||
EtcdCert string `help:"path to cert file for connecting to etcd cluster"`
|
||||
EtcdKey string `help:"path to key file for connecting to etcd cluster"`
|
||||
}
|
||||
|
||||
func (this *DBOptions) GetEtcdTLSConfig() (*tls.Config, error) {
|
||||
var (
|
||||
cert tls.Certificate
|
||||
certLoaded bool
|
||||
capool *x509.CertPool
|
||||
)
|
||||
if this.EtcdCert != "" && this.EtcdKey != "" {
|
||||
var err error
|
||||
cert, err = tls.LoadX509KeyPair(this.EtcdCert, this.EtcdKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "load etcd cert and key")
|
||||
}
|
||||
certLoaded = true
|
||||
this.EtcdUseTLS = true
|
||||
}
|
||||
if this.EtcdCacert != "" {
|
||||
data, err := ioutil.ReadFile(this.EtcdCacert)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "read cacert file")
|
||||
}
|
||||
capool = x509.NewCertPool()
|
||||
for {
|
||||
var block *pem.Block
|
||||
block, data = pem.Decode(data)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
cacert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parse cacert file")
|
||||
}
|
||||
capool.AddCert(cacert)
|
||||
}
|
||||
this.EtcdUseTLS = true
|
||||
}
|
||||
if this.EtcdSkipTLSVerify { // it's false by default, true means user intends to use tls
|
||||
this.EtcdUseTLS = true
|
||||
}
|
||||
if this.EtcdUseTLS {
|
||||
cfg := &tls.Config{
|
||||
RootCAs: capool,
|
||||
InsecureSkipVerify: this.EtcdSkipTLSVerify,
|
||||
}
|
||||
if certLoaded {
|
||||
cfg.Certificates = []tls.Certificate{cert}
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (this *DBOptions) GetDBConnection() (dialect, connstr string, err error) {
|
||||
|
||||
@@ -102,18 +102,6 @@ var (
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "cloudproviders",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "cloudproviders",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "cachedimages",
|
||||
@@ -150,6 +138,18 @@ var (
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "elasticcacheskus",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "elasticcacheskus",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "secgrouprules",
|
||||
@@ -162,6 +162,12 @@ var (
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "loadbalancerclusters",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "yunionagent",
|
||||
Resource: "notices",
|
||||
@@ -180,6 +186,18 @@ var (
|
||||
Action: PolicyActionCreate,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: identityapi.SERVICE_TYPE,
|
||||
Resource: "services",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: identityapi.SERVICE_TYPE,
|
||||
Resource: "services",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -276,6 +294,24 @@ var (
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "notify",
|
||||
Resource: "contacts",
|
||||
Action: PolicyActionCreate,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "notify",
|
||||
Resource: "contacts",
|
||||
Action: PolicyActionUpdate,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "notify",
|
||||
Resource: "contacts",
|
||||
Action: PolicyActionDelete,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -356,6 +392,18 @@ var (
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "cloudproviders",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "cloudproviders",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ package policy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -168,11 +169,6 @@ func (manager *SPolicyManager) start(refreshInterval time.Duration, retryInterva
|
||||
}
|
||||
|
||||
manager.cache = hashcache.NewCache(2048, manager.refreshInterval/2)
|
||||
err := manager.doSync()
|
||||
if err != nil {
|
||||
log.Errorf("doSync error %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
manager.SyncOnce()
|
||||
}
|
||||
@@ -182,9 +178,16 @@ func (manager *SPolicyManager) SyncOnce() {
|
||||
}
|
||||
|
||||
func (manager *SPolicyManager) doSync() error {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Errorf("policyManager doSync error %s", r)
|
||||
debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
|
||||
policies, err := DefaultPolicyFetcher()
|
||||
if err != nil {
|
||||
// log.Errorf("sync rbac policy failed: %s", err)
|
||||
log.Errorf("sync rbac policy failed: %s", err)
|
||||
return errors.Wrap(err, "DefaultPolicyFetcher")
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ var (
|
||||
}
|
||||
computeDomainResources = []string{
|
||||
"cloudaccounts",
|
||||
"cloudproviders",
|
||||
"recyclebins",
|
||||
}
|
||||
computeUserResources = []string{
|
||||
|
||||
@@ -103,7 +103,7 @@ func (man *SRouteManager) ValidateCreateData(ctx context.Context, userCred mccli
|
||||
router.Name+"-"+iface.Name+"-"+rand.String(4)),
|
||||
)
|
||||
}
|
||||
return nil, nil
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (man *SRouteManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
|
||||
@@ -115,7 +115,7 @@ func (man *SRuleManager) validateData(ctx context.Context, userCred mcclient.Tok
|
||||
protoV := validators.NewStringChoicesValidator("match_proto", protoChoices)
|
||||
srcPortV := validators.NewPortValidator("match_src_port")
|
||||
destPortV := validators.NewPortValidator("match_dest_port")
|
||||
actionV := validators.NewStringChoicesValidator("action", protoChoices)
|
||||
actionV := validators.NewStringChoicesValidator("action", actionChoices)
|
||||
actionOptsV := validators.NewStringLenRangeValidator("action_options", 0, 256)
|
||||
if isUpdate {
|
||||
inIfnameV.Default(rule.MatchInIfname)
|
||||
@@ -200,7 +200,7 @@ func (man *SRuleManager) ValidateCreateData(ctx context.Context, userCred mcclie
|
||||
if err := man.validateData(ctx, userCred, ownerId, query, data, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (man *SRuleManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
@@ -31,9 +30,40 @@ const (
|
||||
ErrNoSuchProvder = errors.Error("no such provider")
|
||||
)
|
||||
|
||||
type SCloudaccountCredential struct {
|
||||
ProjectName string //OpenStack
|
||||
DomainName string //OpenStack
|
||||
Username string //OpenStack Esxi ZStack
|
||||
Password string //OpenStack Esxi ZStack
|
||||
AuthUrl string //OpenStack ZStack
|
||||
|
||||
AccessKeyId string //Huawei Aliyun Ucloud Aws
|
||||
AccessKeySecret string //Huawei Aliyun Ucloud Aws
|
||||
Environment string //Huawei Azure Aws
|
||||
|
||||
DirectoryId string //Azure
|
||||
ClientId string //Azure
|
||||
ClientSecret string //Azure
|
||||
|
||||
Host string //Esxi
|
||||
Port int //Esxi
|
||||
|
||||
Endpoint string
|
||||
|
||||
AppId string //Qcloud
|
||||
SecretId string //Qcloud
|
||||
SecretKey string //Qcloud
|
||||
|
||||
ClientEmail string //Google
|
||||
ProjectId string //Google
|
||||
PrivateKeyId string //Google
|
||||
PrivateKey string //Google
|
||||
}
|
||||
|
||||
type SCloudaccount struct {
|
||||
Account string
|
||||
Secret string
|
||||
Account string
|
||||
Secret string
|
||||
AccessUrl string
|
||||
}
|
||||
|
||||
type ICloudProviderFactory interface {
|
||||
@@ -45,8 +75,8 @@ type ICloudProviderFactory interface {
|
||||
GetName() string
|
||||
|
||||
ValidateChangeBandwidth(instanceId string, bandwidth int64) error
|
||||
ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input *api.CloudaccountCreateInput) error
|
||||
ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, cloudaccount string) (*SCloudaccount, error)
|
||||
ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input SCloudaccountCredential) (SCloudaccount, error)
|
||||
ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, input SCloudaccountCredential, cloudaccount string) (SCloudaccount, error)
|
||||
GetSupportedBrands() []string
|
||||
|
||||
IsPublicCloud() bool
|
||||
@@ -203,14 +233,6 @@ func (factory *baseProviderFactory) GetSupportedBrands() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (factory *baseProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input *api.CloudaccountCreateInput) error {
|
||||
return httperrors.NewNotImplementedError("Not Implemented ValidateCreateCloudaccountData")
|
||||
}
|
||||
|
||||
func (factory *baseProviderFactory) ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, cloudaccount string) (*SCloudaccount, error) {
|
||||
return nil, httperrors.NewNotImplementedError("Not Implemented ValidateUpdateCloudaccountCredential")
|
||||
}
|
||||
|
||||
func (factory *baseProviderFactory) GetProvider(providerId, providerName, url, username, password string) (ICloudProvider, error) {
|
||||
return nil, httperrors.NewNotImplementedError("Not Implemented GetProvider")
|
||||
}
|
||||
|
||||
@@ -22,3 +22,9 @@ type SEip struct {
|
||||
NetworkExternalId string
|
||||
IP string
|
||||
}
|
||||
|
||||
type AssociateConfig struct {
|
||||
InstanceId string
|
||||
AssociateType string
|
||||
Bandwidth int
|
||||
}
|
||||
|
||||
@@ -93,6 +93,10 @@ func (region *SFakeOnPremiseRegion) GetISecurityGroupById(id string) (ICloudSecu
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (region *SFakeOnPremiseRegion) GetISecurityGroupByName(vpcId string, name string) (ICloudSecurityGroup, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (region *SFakeOnPremiseRegion) CreateISecurityGroup(conf *SecurityGroupCreateInput) (ICloudSecurityGroup, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package cloudprovider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
@@ -77,7 +78,7 @@ func (vmConfig *SManagedVMCreateConfig) GetConfig(config *jsonutils.JSONDict) er
|
||||
vmConfig.PublicKey = publicKey
|
||||
}
|
||||
//目前所写的userData格式仅支持Linux
|
||||
if vmConfig.OsType == osprofile.OS_TYPE_LINUX {
|
||||
if strings.ToLower(vmConfig.OsType) == strings.ToLower(osprofile.OS_TYPE_LINUX) {
|
||||
adminPublicKey, _ := config.GetString("admin_public_key")
|
||||
projectPublicKey, _ := config.GetString("project_public_key")
|
||||
oUserData, _ := config.GetString("user_data")
|
||||
|
||||
@@ -70,4 +70,18 @@ type SLoadbalancerListenerRule struct {
|
||||
BackendGroupType string
|
||||
|
||||
Condition string // for aws only
|
||||
|
||||
Scheduler string // for qcloud only
|
||||
HealthCheck string // for qcloud only
|
||||
HealthCheckType string // for qcloud only
|
||||
HealthCheckTimeout int // for qcloud only
|
||||
HealthCheckDomain string // for qcloud only
|
||||
HealthCheckHttpCode string // for qcloud only
|
||||
HealthCheckURI string // for qcloud only
|
||||
HealthCheckInterval int // for qcloud only
|
||||
|
||||
HealthCheckRise int // for qcloud only
|
||||
HealthCheckFail int // for qcloud only
|
||||
|
||||
StickySessionCookieTimeout int // for qcloud only
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -42,6 +44,15 @@ const (
|
||||
ACLPublicRead = TBucketACLType(s3cli.CANNED_ACL_PUBLIC_READ)
|
||||
ACLPublicReadWrite = TBucketACLType(s3cli.CANNED_ACL_PUBLIC_READ_WRITE)
|
||||
ACLUnknown = TBucketACLType("")
|
||||
|
||||
META_HEADER_CACHE_CONTROL = "Cache-Control"
|
||||
META_HEADER_CONTENT_TYPE = "Content-Type"
|
||||
META_HEADER_CONTENT_DISPOSITION = "Content-Disposition"
|
||||
META_HEADER_CONTENT_ENCODING = "Content-Encoding"
|
||||
META_HEADER_CONTENT_LANGUAGE = "Content-Language"
|
||||
META_HEADER_CONTENT_MD5 = "Content-MD5"
|
||||
|
||||
META_HEADER_PREFIX = "X-Yunion-Meta-"
|
||||
)
|
||||
|
||||
type SBucketStats struct {
|
||||
@@ -69,7 +80,7 @@ type SBaseCloudObject struct {
|
||||
StorageClass string
|
||||
ETag string
|
||||
LastModified time.Time
|
||||
ContentType string
|
||||
Meta http.Header
|
||||
}
|
||||
|
||||
type SListObjectResult struct {
|
||||
@@ -138,16 +149,16 @@ type ICloudBucket interface {
|
||||
SetAcl(acl TBucketACLType) error
|
||||
|
||||
ListObjects(prefix string, marker string, delimiter string, maxCount int) (SListObjectResult, error)
|
||||
GetIObjects(prefix string, isRecursive bool) ([]ICloudObject, error)
|
||||
|
||||
CopyObject(ctx context.Context, destKey string, srcBucket, srcKey string, contType string, cannedAcl TBucketACLType, storageClassStr string) error
|
||||
CopyObject(ctx context.Context, destKey string, srcBucket, srcKey string, cannedAcl TBucketACLType, storageClassStr string, meta http.Header) error
|
||||
GetObject(ctx context.Context, key string, rangeOpt *SGetObjectRange) (io.ReadCloser, error)
|
||||
|
||||
DeleteObject(ctx context.Context, keys string) error
|
||||
GetTempUrl(method string, key string, expire time.Duration) (string, error)
|
||||
|
||||
PutObject(ctx context.Context, key string, input io.Reader, sizeBytes int64, contType string, cannedAcl TBucketACLType, storageClassStr string) error
|
||||
NewMultipartUpload(ctx context.Context, key string, contType string, cannedAcl TBucketACLType, storageClassStr string) (string, error)
|
||||
PutObject(ctx context.Context, key string, input io.Reader, sizeBytes int64, cannedAcl TBucketACLType, storageClassStr string, meta http.Header) error
|
||||
|
||||
NewMultipartUpload(ctx context.Context, key string, cannedAcl TBucketACLType, storageClassStr string, meta http.Header) (string, error)
|
||||
UploadPart(ctx context.Context, key string, uploadId string, partIndex int, input io.Reader, partSize int64) (string, error)
|
||||
CopyPart(ctx context.Context, key string, uploadId string, partIndex int, srcBucketName string, srcKey string, srcOffset int64, srcLength int64) (string, error)
|
||||
CompleteMultipartUpload(ctx context.Context, key string, uploadId string, partEtags []string) error
|
||||
@@ -162,7 +173,9 @@ type ICloudObject interface {
|
||||
GetLastModified() time.Time
|
||||
GetStorageClass() string
|
||||
GetETag() string
|
||||
GetContentType() string
|
||||
|
||||
GetMeta() http.Header
|
||||
SetMeta(ctx context.Context, meta http.Header) error
|
||||
|
||||
GetAcl() TBucketACLType
|
||||
SetAcl(acl TBucketACLType) error
|
||||
@@ -175,7 +188,7 @@ func ICloudObject2JSONObject(obj ICloudObject) jsonutils.JSONObject {
|
||||
StorageClass string
|
||||
ETag string
|
||||
LastModified time.Time
|
||||
ContentType string
|
||||
Meta http.Header
|
||||
Acl string
|
||||
}{
|
||||
Key: obj.GetKey(),
|
||||
@@ -183,7 +196,7 @@ func ICloudObject2JSONObject(obj ICloudObject) jsonutils.JSONObject {
|
||||
StorageClass: obj.GetStorageClass(),
|
||||
ETag: obj.GetETag(),
|
||||
LastModified: obj.GetLastModified(),
|
||||
ContentType: obj.GetContentType(),
|
||||
Meta: obj.GetMeta(),
|
||||
Acl: string(obj.GetAcl()),
|
||||
}
|
||||
return jsonutils.Marshal(obj2)
|
||||
@@ -209,10 +222,14 @@ func (o *SBaseCloudObject) GetETag() string {
|
||||
return o.ETag
|
||||
}
|
||||
|
||||
func (o *SBaseCloudObject) GetContentType() string {
|
||||
return o.ContentType
|
||||
func (o *SBaseCloudObject) GetMeta() http.Header {
|
||||
return o.Meta
|
||||
}
|
||||
|
||||
//func (o *SBaseCloudObject) SetMeta(meta http.Header) error {
|
||||
// return nil
|
||||
//}
|
||||
|
||||
func GetIBucketById(region ICloudRegion, name string) (ICloudBucket, error) {
|
||||
buckets, err := region.GetIBuckets()
|
||||
if err != nil {
|
||||
@@ -240,57 +257,82 @@ func GetIBucketByName(region ICloudRegion, name string) (ICloudBucket, error) {
|
||||
}
|
||||
|
||||
func GetIBucketStats(bucket ICloudBucket) (SBucketStats, error) {
|
||||
stats := SBucketStats{}
|
||||
objs, err := bucket.GetIObjects("", true)
|
||||
stats := SBucketStats{
|
||||
ObjectCount: -1,
|
||||
SizeBytes: -1,
|
||||
}
|
||||
objs, err := bucket.ListObjects("", "", "", 1000)
|
||||
if err != nil {
|
||||
stats.ObjectCount = -1
|
||||
stats.SizeBytes = -1
|
||||
return stats, errors.Wrap(err, "GetIObjects")
|
||||
}
|
||||
for _, obj := range objs {
|
||||
if objs.IsTruncated {
|
||||
return stats, errors.Error("too many objects")
|
||||
}
|
||||
for _, obj := range objs.Objects {
|
||||
stats.SizeBytes += obj.GetSizeBytes()
|
||||
stats.ObjectCount += 1
|
||||
}
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func GetIObjects(bucket ICloudBucket, objectPrefix string, isRecursive bool) ([]ICloudObject, error) {
|
||||
type cloudObjectList []ICloudObject
|
||||
|
||||
func (a cloudObjectList) Len() int { return len(a) }
|
||||
func (a cloudObjectList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a cloudObjectList) Less(i, j int) bool { return a[i].GetKey() < a[j].GetKey() }
|
||||
|
||||
func GetPagedObjects(bucket ICloudBucket, objectPrefix string, isRecursive bool, marker string, maxCount int) ([]ICloudObject, string, error) {
|
||||
delimiter := "/"
|
||||
if isRecursive {
|
||||
delimiter = ""
|
||||
}
|
||||
if maxCount > 1000 || maxCount <= 0 {
|
||||
maxCount = 1000
|
||||
}
|
||||
ret := make([]ICloudObject, 0)
|
||||
result, err := bucket.ListObjects(objectPrefix, marker, delimiter, maxCount)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrap(err, "bucket.ListObjects")
|
||||
}
|
||||
// Send all objects
|
||||
for i := range result.Objects {
|
||||
// if delimited, skip the first object ends with delimiter
|
||||
if !isRecursive && result.Objects[i].GetKey() == objectPrefix && strings.HasSuffix(objectPrefix, delimiter) {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, result.Objects[i])
|
||||
marker = result.Objects[i].GetKey()
|
||||
}
|
||||
// Send all common prefixes if any.
|
||||
// NOTE: prefixes are only present if the request is delimited.
|
||||
if len(result.CommonPrefixes) > 0 {
|
||||
ret = append(ret, result.CommonPrefixes...)
|
||||
}
|
||||
// sort prefix by name in ascending order
|
||||
sort.Sort(cloudObjectList(ret))
|
||||
// If next marker present, save it for next request.
|
||||
if result.NextMarker != "" {
|
||||
marker = result.NextMarker
|
||||
}
|
||||
// If not truncated, no more objects
|
||||
if !result.IsTruncated {
|
||||
marker = ""
|
||||
}
|
||||
return ret, marker, nil
|
||||
}
|
||||
|
||||
func GetAllObjects(bucket ICloudBucket, objectPrefix string, isRecursive bool) ([]ICloudObject, error) {
|
||||
ret := make([]ICloudObject, 0)
|
||||
// Save marker for next request.
|
||||
var marker string
|
||||
for {
|
||||
// Get list of objects a maximum of 1000 per request.
|
||||
result, err := bucket.ListObjects(objectPrefix, marker, delimiter, 1000)
|
||||
result, marker, err := GetPagedObjects(bucket, objectPrefix, isRecursive, marker, 1000)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "bucket.ListObjects")
|
||||
}
|
||||
|
||||
// Send all objects
|
||||
for i := range result.Objects {
|
||||
if !isRecursive && result.Objects[i].GetKey() == objectPrefix {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, result.Objects[i])
|
||||
marker = result.Objects[i].GetKey()
|
||||
}
|
||||
|
||||
// Send all common prefixes if any.
|
||||
// NOTE: prefixes are only present if the request is delimited.
|
||||
if len(result.CommonPrefixes) > 0 {
|
||||
ret = append(ret, result.CommonPrefixes...)
|
||||
}
|
||||
|
||||
// If next marker present, save it for next request.
|
||||
if result.NextMarker != "" {
|
||||
marker = result.NextMarker
|
||||
}
|
||||
|
||||
// Listing ends result is not truncated, break the loop
|
||||
if !result.IsTruncated {
|
||||
ret = append(ret, result...)
|
||||
if marker == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -323,14 +365,14 @@ func Makedir(ctx context.Context, bucket ICloudBucket, key string) error {
|
||||
}
|
||||
}
|
||||
path := strings.Join(segs, "/") + "/"
|
||||
err := bucket.PutObject(ctx, path, strings.NewReader(""), 0, "", ACLPrivate, "")
|
||||
err := bucket.PutObject(ctx, path, strings.NewReader(""), 0, bucket.GetAcl(), "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "PutObject")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UploadObject(ctx context.Context, bucket ICloudBucket, key string, blocksz int64, input io.Reader, sizeBytes int64, contType string, cannedAcl TBucketACLType, storageClass string, debug bool) error {
|
||||
func UploadObject(ctx context.Context, bucket ICloudBucket, key string, blocksz int64, input io.Reader, sizeBytes int64, cannedAcl TBucketACLType, storageClass string, meta http.Header, debug bool) error {
|
||||
if blocksz <= 0 {
|
||||
blocksz = MAX_PUT_OBJECT_SIZEBYTES
|
||||
}
|
||||
@@ -338,7 +380,7 @@ func UploadObject(ctx context.Context, bucket ICloudBucket, key string, blocksz
|
||||
if debug {
|
||||
log.Debugf("too small, put object in one shot")
|
||||
}
|
||||
return bucket.PutObject(ctx, key, input, sizeBytes, contType, cannedAcl, storageClass)
|
||||
return bucket.PutObject(ctx, key, input, sizeBytes, cannedAcl, storageClass, meta)
|
||||
}
|
||||
partSize := blocksz
|
||||
partCount := sizeBytes / partSize
|
||||
@@ -358,7 +400,7 @@ func UploadObject(ctx context.Context, bucket ICloudBucket, key string, blocksz
|
||||
if debug {
|
||||
log.Debugf("multipart upload part count %d part size %d", partCount, partSize)
|
||||
}
|
||||
uploadId, err := bucket.NewMultipartUpload(ctx, key, contType, cannedAcl, storageClass)
|
||||
uploadId, err := bucket.NewMultipartUpload(ctx, key, cannedAcl, storageClass, meta)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "bucket.NewMultipartUpload")
|
||||
}
|
||||
@@ -394,7 +436,7 @@ func UploadObject(ctx context.Context, bucket ICloudBucket, key string, blocksz
|
||||
}
|
||||
|
||||
func DeletePrefix(ctx context.Context, bucket ICloudBucket, prefix string) error {
|
||||
objs, err := bucket.GetIObjects(prefix, true)
|
||||
objs, err := GetAllObjects(bucket, prefix, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "bucket.GetIObjects")
|
||||
}
|
||||
@@ -407,7 +449,31 @@ func DeletePrefix(ctx context.Context, bucket ICloudBucket, prefix string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func CopyObject(ctx context.Context, blocksz int64, dstBucket ICloudBucket, dstKey string, srcBucket ICloudBucket, srcKey string, debug bool) error {
|
||||
func MergeMeta(src http.Header, dst http.Header) http.Header {
|
||||
if src != nil && dst != nil {
|
||||
ret := http.Header{}
|
||||
for k, vs := range src {
|
||||
for _, v := range vs {
|
||||
ret.Add(k, v)
|
||||
}
|
||||
}
|
||||
for k, vs := range dst {
|
||||
for _, v := range vs {
|
||||
ret.Add(k, v)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
} else if src != nil && dst == nil {
|
||||
return src
|
||||
} else if src == nil && dst != nil {
|
||||
return dst
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func CopyObject(ctx context.Context, blocksz int64, dstBucket ICloudBucket, dstKey string, srcBucket ICloudBucket, srcKey string, dstMeta http.Header, debug bool) error {
|
||||
|
||||
srcObj, err := GetIObject(srcBucket, srcKey)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetIObject")
|
||||
@@ -425,7 +491,7 @@ func CopyObject(ctx context.Context, blocksz int64, dstBucket ICloudBucket, dstK
|
||||
return errors.Wrap(err, "srcBucket.GetObject")
|
||||
}
|
||||
defer srcStream.Close()
|
||||
err = dstBucket.PutObject(ctx, dstKey, srcStream, sizeBytes, srcObj.GetContentType(), srcObj.GetAcl(), srcObj.GetStorageClass())
|
||||
err = dstBucket.PutObject(ctx, dstKey, srcStream, sizeBytes, srcObj.GetAcl(), srcObj.GetStorageClass(), MergeMeta(srcObj.GetMeta(), dstMeta))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "dstBucket.PutObject")
|
||||
}
|
||||
@@ -449,7 +515,7 @@ func CopyObject(ctx context.Context, blocksz int64, dstBucket ICloudBucket, dstK
|
||||
if debug {
|
||||
log.Debugf("multipart upload part count %d part size %d", partCount, partSize)
|
||||
}
|
||||
uploadId, err := dstBucket.NewMultipartUpload(ctx, dstKey, srcObj.GetContentType(), srcObj.GetAcl(), srcObj.GetStorageClass())
|
||||
uploadId, err := dstBucket.NewMultipartUpload(ctx, dstKey, srcObj.GetAcl(), srcObj.GetStorageClass(), MergeMeta(srcObj.GetMeta(), dstMeta))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "bucket.NewMultipartUpload")
|
||||
}
|
||||
@@ -513,3 +579,58 @@ func CopyPart(ctx context.Context,
|
||||
}
|
||||
return etag, nil
|
||||
}
|
||||
|
||||
func ObjectSetMeta(ctx context.Context,
|
||||
bucket ICloudBucket, obj ICloudObject,
|
||||
meta http.Header,
|
||||
) error {
|
||||
return bucket.CopyObject(ctx, obj.GetKey(), bucket.GetName(), obj.GetKey(), obj.GetAcl(), obj.GetStorageClass(), meta)
|
||||
}
|
||||
|
||||
func MetaToHttpHeader(metaPrefix string, meta http.Header) http.Header {
|
||||
hdr := http.Header{}
|
||||
for k, v := range meta {
|
||||
if len(v) == 0 || len(v[0]) == 0 {
|
||||
continue
|
||||
}
|
||||
k = http.CanonicalHeaderKey(k)
|
||||
switch k {
|
||||
case META_HEADER_CACHE_CONTROL,
|
||||
META_HEADER_CONTENT_TYPE,
|
||||
META_HEADER_CONTENT_DISPOSITION,
|
||||
META_HEADER_CONTENT_ENCODING,
|
||||
META_HEADER_CONTENT_LANGUAGE,
|
||||
META_HEADER_CONTENT_MD5:
|
||||
hdr.Set(k, v[0])
|
||||
default:
|
||||
hdr.Set(fmt.Sprintf("%s%s", metaPrefix, k), v[0])
|
||||
}
|
||||
}
|
||||
return hdr
|
||||
}
|
||||
|
||||
func FetchMetaFromHttpHeader(metaPrefix string, headers http.Header) http.Header {
|
||||
metaPrefix = http.CanonicalHeaderKey(metaPrefix)
|
||||
meta := http.Header{}
|
||||
for hdr, vals := range headers {
|
||||
hdr = http.CanonicalHeaderKey(hdr)
|
||||
if strings.HasPrefix(hdr, metaPrefix) {
|
||||
for _, val := range vals {
|
||||
meta.Add(hdr[len(metaPrefix):], val)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, hdr := range []string{
|
||||
META_HEADER_CONTENT_TYPE,
|
||||
META_HEADER_CONTENT_ENCODING,
|
||||
META_HEADER_CONTENT_DISPOSITION,
|
||||
META_HEADER_CONTENT_LANGUAGE,
|
||||
META_HEADER_CACHE_CONTROL,
|
||||
} {
|
||||
val := headers.Get(hdr)
|
||||
if len(val) > 0 {
|
||||
meta.Set(hdr, val)
|
||||
}
|
||||
}
|
||||
return meta
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ type ICloudRegion interface {
|
||||
GetIDiskById(id string) (ICloudDisk, error)
|
||||
|
||||
GetISecurityGroupById(secgroupId string) (ICloudSecurityGroup, error)
|
||||
GetISecurityGroupByName(vpcId string, name string) (ICloudSecurityGroup, error)
|
||||
CreateISecurityGroup(conf *SecurityGroupCreateInput) (ICloudSecurityGroup, error)
|
||||
|
||||
CreateIVpc(name string, desc string, cidr string) (ICloudVpc, error)
|
||||
@@ -227,6 +228,7 @@ type ICloudHost interface {
|
||||
GetCpuCmtbound() float32
|
||||
GetMemSizeMB() int
|
||||
GetMemCmtbound() float32
|
||||
GetReservedMemoryMb() int
|
||||
GetStorageSizeMB() int
|
||||
GetStorageType() string
|
||||
GetHostType() string
|
||||
@@ -301,6 +303,7 @@ type ICloudVM interface {
|
||||
type ICloudNic interface {
|
||||
GetIP() string
|
||||
GetMAC() string
|
||||
InClassicNetwork() bool
|
||||
GetDriver() string
|
||||
GetINetwork() ICloudNetwork
|
||||
}
|
||||
@@ -321,7 +324,7 @@ type ICloudEIP interface {
|
||||
|
||||
Delete() error
|
||||
|
||||
Associate(instanceId string) error
|
||||
Associate(conf *AssociateConfig) error
|
||||
Dissociate() error
|
||||
|
||||
ChangeBandwidth(bw int) error
|
||||
|
||||
@@ -61,6 +61,11 @@ func WaitStatusWithInstanceErrorCheck(res ICloudResource, expect string, interva
|
||||
return ErrTimeout
|
||||
}
|
||||
|
||||
func WaitDeletedWithDelay(res ICloudResource, delay time.Duration, interval time.Duration, timeout time.Duration) error {
|
||||
time.Sleep(delay)
|
||||
return WaitDeleted(res, interval, timeout)
|
||||
}
|
||||
|
||||
func WaitDeleted(res ICloudResource, interval time.Duration, timeout time.Duration) error {
|
||||
startTime := time.Now()
|
||||
for time.Now().Sub(startTime) < timeout {
|
||||
|
||||
@@ -65,23 +65,23 @@ var (
|
||||
)
|
||||
|
||||
type BaremetalStorage struct {
|
||||
Size int64 `json:"size"`
|
||||
Size int64 `json:"size,allowzero"`
|
||||
Driver string `json:"driver"`
|
||||
Rotate bool `json:"rotate"`
|
||||
Rotate bool `json:"rotate,allowfalse"`
|
||||
Dev string `json:"dev,omitempty"`
|
||||
Sector int64 `json:"sector,omitempty"`
|
||||
Block int64 `json:"block,omitempty"`
|
||||
ModuleInfo string `json:"module,omitempty"`
|
||||
Kernel string `json:"kernel,omitempty"`
|
||||
PCIClass string `json:"pci_class,omitempty"`
|
||||
Slot int `json:"slot,omitempty"`
|
||||
Slot int `json:"slot,allowzero"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Adapter int `json:"adapter,omitempty"`
|
||||
Adapter int `json:"adapter,allowzero"`
|
||||
Model string `json:"model,omitempty"`
|
||||
Enclosure int `json:"enclousure,omitempty"`
|
||||
Enclosure int `json:"enclousure,allowzero"`
|
||||
MinStripSize int64 `json:"min_strip_size,omitempty"`
|
||||
MaxStripSize int64 `json:"max_strip_size,omitempty"`
|
||||
Index int64 `json:"index"`
|
||||
Index int64 `json:"index,allowzero"`
|
||||
Addr string `json:"addr,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -28,6 +29,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
@@ -141,6 +143,23 @@ func (self *SAwsGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
if len(input.Eip) > 0 || input.EipBw > 0 {
|
||||
// 未明确指定network时,由调度器进行调度,跳过support_eip检查
|
||||
if len(input.Networks) > 0 && len(input.Networks[0].Network) > 0 {
|
||||
inetwork, err := db.FetchByIdOrName(models.NetworkManager, userCred, input.Networks[0].Network)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SAwsGuestDriver.ValidateCreateData.Networks.FetchByIdOrName")
|
||||
}
|
||||
|
||||
support_eip := inetwork.(*models.SNetwork).GetMetadataJson("ext:support_eip", nil)
|
||||
if support_eip != nil {
|
||||
if ok, _ := support_eip.Bool(); !ok {
|
||||
return nil, httperrors.NewInputParameterError("network %s associated route table has no internet gateway attached.", inetwork.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
}
|
||||
|
||||
@@ -181,11 +200,22 @@ func (self *SAwsGuestDriver) RequestAssociateEip(ctx context.Context, userCred m
|
||||
return nil, fmt.Errorf("SAwsGuestDriver.RequestAssociateEip fail to find iEIP for eip %s", err)
|
||||
}
|
||||
|
||||
err = extEip.Associate(server.ExternalId)
|
||||
conf := &cloudprovider.AssociateConfig{
|
||||
InstanceId: server.ExternalId,
|
||||
Bandwidth: eip.Bandwidth,
|
||||
AssociateType: api.EIP_ASSOCIATE_TYPE_SERVER,
|
||||
}
|
||||
|
||||
err = extEip.Associate(conf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SAwsGuestDriver.RequestAssociateEip fail to remote associate EIP %s", err)
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(extEip, api.EIP_STATUS_READY, 3*time.Second, 60*time.Second)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SAwsGuestDriver.RequestAssociateEip.WaitStatus")
|
||||
}
|
||||
|
||||
err = eip.AssociateVM(ctx, userCred, server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SAwsGuestDriver.RequestAssociateEip fail to local associate EIP %s", err)
|
||||
|
||||
@@ -143,7 +143,3 @@ func (self *SAzureGuestDriver) GetLinuxDefaultAccount(desc cloudprovider.SManage
|
||||
func (self *SAzureGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SAzureGuestDriver) NeedStopForChangeSpec(guest *models.SGuest) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -258,12 +258,16 @@ func (self *SBaremetalGuestDriver) RequestGuestCreateAllDisks(ctx context.Contex
|
||||
if storageCache == nil {
|
||||
return fmt.Errorf("no valid storage cache")
|
||||
}
|
||||
return storageCache.StartImageCacheTask(ctx, task.GetUserCred(), imageId, diskCat.Root.DiskFormat, false, task.GetTaskId())
|
||||
return storageCache.StartImageCacheTask(ctx, task.GetUserCred(), imageId, "qcow2", false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error {
|
||||
func (self *SBaremetalGuestDriver) NeedRequestGuestHotAddIso(ctx context.Context, guest *models.SGuest) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error {
|
||||
host := guest.GetHost()
|
||||
return host.StartInsertIsoTask(ctx, task.GetUserCred(), filepath.Base(path), false, task.GetTaskId())
|
||||
return host.StartInsertIsoTask(ctx, task.GetUserCred(), filepath.Base(path), boot, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestGuestHotRemoveIso(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
@@ -272,8 +276,7 @@ func (self *SBaremetalGuestDriver) RequestGuestHotRemoveIso(ctx context.Context,
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, guest *models.SGuest, task taskman.ITask) error {
|
||||
host := guest.GetHost()
|
||||
return host.StartInsertIsoTask(ctx, task.GetUserCred(), imageId, true, task.GetTaskId())
|
||||
return guest.StartInsertIsoTask(ctx, imageId, true, guest.HostId, task.GetUserCred(), task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestStartOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, userCred mcclient.TokenCredential, task taskman.ITask) (jsonutils.JSONObject, error) {
|
||||
@@ -398,6 +401,15 @@ func (self *SBaremetalGuestDriver) GetGuestVncInfo(ctx context.Context, userCred
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) RequestRebuildRootDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
subtask, err := taskman.TaskManager.NewTask(ctx, "ManagedGuestRebuildRootTask", guest, task.GetUserCred(), task.GetParams(), task.GetTaskId(), "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subtask.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, data *jsonutils.JSONDict) error {
|
||||
return guest.StartGueststartTask(ctx, userCred, data, "")
|
||||
}
|
||||
@@ -455,6 +467,8 @@ func (self *SBaremetalGuestDriver) RequestDeployGuestOnHost(ctx context.Context,
|
||||
}
|
||||
if val == "rebuild" && jsonutils.QueryBoolean(task.GetParams(), "auto_start", false) {
|
||||
config.Set("on_finish", jsonutils.NewString("restart"))
|
||||
} else if val == "deploy" && jsonutils.QueryBoolean(task.GetParams(), "restart", false) {
|
||||
config.Set("on_finish", jsonutils.NewString("shutdown"))
|
||||
}
|
||||
url := fmt.Sprintf("/baremetals/%s/servers/%s/%s", host.Id, guest.Id, val)
|
||||
headers := task.GetTaskRequestHeader()
|
||||
|
||||
@@ -175,6 +175,9 @@ func (self *SBaseGuestDriver) StartGuestResetTask(guest *models.SGuest, ctx cont
|
||||
func (self *SBaseGuestDriver) StartGuestRestartTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, isForce bool, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Set("is_force", jsonutils.NewBool(isForce))
|
||||
if err := guest.SetStatus(userCred, api.VM_STOPPING, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestRestartTask", guest, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -199,7 +202,11 @@ func (self *SBaseGuestDriver) RequestChangeVmConfig(ctx context.Context, guest *
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error {
|
||||
func (self *SBaseGuestDriver) NeedRequestGuestHotAddIso(ctx context.Context, guest *models.SGuest) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement")
|
||||
}
|
||||
|
||||
@@ -239,6 +246,10 @@ func (self *SBaseGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle)
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) IsSupportPostpaidExpire() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestRenewInstance(guest *models.SGuest, bc billing.SBillingCycle) (time.Time, error) {
|
||||
return time.Time{}, nil
|
||||
}
|
||||
@@ -251,8 +262,8 @@ func (self *SBaseGuestDriver) RequestAssociateEip(ctx context.Context, userCred
|
||||
return fmt.Errorf("SBaseGuestDriver: Not Implement RequestAssociateEip")
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) NeedStopForChangeSpec(guest *models.SGuest) bool {
|
||||
return true
|
||||
func (self *SBaseGuestDriver) NeedStopForChangeSpec(guest *models.SGuest, cpuChanged, memChanged bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RemoteDeployGuestForCreate(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, desc cloudprovider.SManagedVMCreateConfig) (jsonutils.JSONObject, error) {
|
||||
|
||||
@@ -77,7 +77,7 @@ func (self *SContainerDriver) RequestGuestCreateAllDisks(ctx context.Context, gu
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SContainerDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error {
|
||||
func (self *SContainerDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error {
|
||||
// do nothing, call next stage
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user