Compare commits

...

159 Commits

Author SHA1 Message Date
Jian Qiu
c6d5c9ea0a fix: ensure s3 client init for s3 storage driver (#24319)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2026-02-11 22:08:19 +08:00
wanyaoqi
ecb65c2563 fix(host): set dmesg parse failed log level to debug (#24308) 2026-02-11 00:59:48 +08:00
屈轩
7dc2246c10 fix(notify): notify receiver (#24300) 2026-02-09 20:42:52 +08:00
wanyaoqi
0b02c49c7c fix(host): deploy nics config defore do add nics (#24275) 2026-02-09 08:38:16 +08:00
屈轩
5e565cf2be fix(region): vendor update (#24268) 2026-02-07 13:52:21 +08:00
wanyaoqi
aef2e3e956 fix(region,host): rename screen dump info structure (#24257) 2026-02-06 18:08:35 +08:00
屈轩
335cdf37b4 fix(region): snapshot policy operation (#24251) 2026-02-05 16:40:40 +08:00
wanyaoqi
43bb829edc fix(glance): set s3 bucket name before s3 init check (#24236) 2026-02-04 19:33:28 +08:00
屈轩
217496161a fix(yunionconf): support tags (#24234) 2026-02-04 17:14:12 +08:00
屈轩
f2d2495be3 fix(region): public cloud sku create (#24229) 2026-02-04 14:57:45 +08:00
屈轩
b333d023f9 fix(region): support cloudpods vm disk driver (#24224) 2026-02-04 14:28:21 +08:00
Zexi Li
29d1a9beb3 fix(region,climc): persist netinterface vlan_id to hostnetwork (#24214)
- climc: add VlanId to host-add-netif, host-remove-netif, host-enable-netif,
  host-disable-netif
- region: set bn.VlanId from netif.VlanId when attaching to network
- mcclient: include Vlan_ID in baremetalnetworks list columns
2026-02-04 11:03:59 +08:00
屈轩
8a70ad1fe1 fix(region): avoid duplicate check when update account aksk (#24208) 2026-02-03 20:53:06 +08:00
屈轩
55c139f4ab fix(region): init snapshot policy disk table (#24201) 2026-02-02 20:38:08 +08:00
wanyaoqi
24fdc3782f fix(host): guestnetworksync do nothing on detach vfio nic (#24177) 2026-02-02 19:02:59 +08:00
屈轩
69fce36cab fix(climc): sku create support arch (#24189) 2026-02-02 14:17:23 +08:00
屈轩
aef3f68fd5 fix(notify): support webhook sign (#24184) 2026-02-02 12:54:06 +08:00
wanyaoqi
67566abfbb fix(host): live migrate add timeout (#24164) 2026-02-01 20:24:53 +08:00
wanyaoqi
382ec17c04 fix(region): server add set network num queues (#24165) 2026-02-01 20:12:08 +08:00
wanyaoqi
28f83d8dac fix(glance): set glance s3 bucket name default onecloud-images (#24170) 2026-02-01 20:10:05 +08:00
wanyaoqi
bdd024d699 fix(region): have agent add check is telegraf deployed (#24146) 2026-01-29 10:34:25 +08:00
屈轩
8f03c28919 fix(region): billing resource create time (#24143) 2026-01-28 20:00:02 +08:00
屈轩
246721c529 fix(glance): support prob iso image (#24136) 2026-01-28 15:31:34 +08:00
屈轩
60ae50c608 fix(region): vendor update (#24121) 2026-01-23 17:03:48 +08:00
Jian Qiu
60082c3534 fix: update deps version 3.11.13 (#24105)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2026-01-20 01:38:20 +08:00
Jian Qiu
4a512da8a8 fix: user filter revisit (#24104)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2026-01-20 00:45:35 +08:00
Jian Qiu
4a6adeea1f fix: notify receiver update precedure recode (#24102)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2026-01-20 00:15:43 +08:00
wanyaoqi
65cbea196f fix(host): ensure scsi pci addr on add scsi disk (#24096) 2026-01-19 20:16:20 +08:00
屈轩
45e6c8cf59 fix(region): vendor update (#24093) 2026-01-19 14:45:51 +08:00
Zexi Li
a36039ccc1 fix(telegraf-raid-plugin): working for victoria metrics (#24086) 2026-01-15 17:20:52 +08:00
Jian Qiu
a4b5078997 fix: detailed apigateway auth failure log (#24078)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2026-01-15 10:13:42 +08:00
屈轩
4ba88e37cd fix(region): vendor update (#24081) 2026-01-14 14:05:35 +08:00
屈轩
411a6df9f9 fix(glance): avoid context warnning (#24075) 2026-01-14 10:54:58 +08:00
屈轩
2ba0bdfee7 fix(region): avoid panic when update user resource (#24072) 2026-01-13 18:21:04 +08:00
屈轩
dffd2aa2d9 fix(common): skip octet-stream warnning (#24069) 2026-01-13 18:20:40 +08:00
屈轩
fec5f1f8a7 fix(region): remove useless mod (#24062) 2026-01-12 14:15:00 +08:00
屈轩
23e3234d8d fix(region): add billing resource check (#24059) 2026-01-12 12:37:38 +08:00
屈轩
f6928c9ca9 fix(region): host schedtag sync (#24057) 2026-01-11 18:33:51 +08:00
屈轩
e479741459 fix(region): allow batch resize disk (#24051) 2026-01-09 14:05:01 +08:00
屈轩
5560cc9371 fix(monitor): optimized common alert list (#24044) 2026-01-09 10:10:04 +08:00
wanyaoqi
91061f28cc fix(host): add query id on detect qemu machine info (#24045) 2026-01-09 08:24:53 +08:00
屈轩
f359c67632 fix(monitor): optimized monitor resource list (#24040) 2026-01-08 15:23:33 +08:00
Zexi Li
7355547b2b fix(monitor): resource id deduplication of alert record (#24034) 2026-01-07 11:16:17 +08:00
Zexi Li
bcf544574f fix(monitor): fill resource ids of the cloud account (#24031) 2026-01-06 19:44:50 +08:00
屈轩
9a01e1fdb3 fix(region): show pretty error (#24022) 2026-01-06 10:29:45 +08:00
wanyaoqi
7d92eb9a63 fix(scheduler): correct mem_free = (mem_total - mem_reserved) * mem_cmtbound (#23982) 2025-12-29 11:17:53 +08:00
wanyaoqi
6bf92e0ea7 fix(climc): host set memory commit bound incorrect params (#23973) 2025-12-29 11:01:43 +08:00
wanyaoqi
5eae491d47 fix(glance): image disk_format use String2ImageFormat (#23991) 2025-12-29 11:01:22 +08:00
Jian Qiu
532f4eb1db fix: change OutOfResource http status code to 507 (#23988)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-12-29 10:59:22 +08:00
屈轩
26fd3424f3 fix(region): show host cpu and mem usage (#23999) 2025-12-25 21:58:07 +08:00
屈轩
395bc3f317 fix(region): update private cloud host cpu and mem usage by cloudmon (#23985) 2025-12-24 19:21:30 +08:00
屈轩
865a019ba3 fix(region): show guest nic index (#23957) 2025-12-24 11:33:30 +08:00
Jian Qiu
16ce2a6a66 feature: assume user login support (#23961)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-12-23 13:53:54 +08:00
wanyaoqi
7c69f96725 feat(baremetal-agent): Linux PCIE disk support mdadm soft raid (#23725)
* feat(baremetal-agent): Linux PCIE disk support mdadm soft raid

* fix(baremeta-agent): soft raid support intel imsm

* fix: update baremetal-agent base
2025-12-22 13:29:47 +08:00
wanyaoqi
231711d0fb fix(region): guest usage by arch (#23954) 2025-12-22 11:42:34 +08:00
屈轩
7c3929bc5e fix(region): allow clean history data (#23950) 2025-12-19 12:42:18 +08:00
屈轩
c6f3e714ee fix(region): disable sync schedtags (#23943) 2025-12-16 20:41:02 +08:00
屈轩
73076cfc19 fix(region): disable cloudpods auto create project (#23938) 2025-12-15 15:51:43 +08:00
屈轩
4455a99645 fix(region): add provider info for sync log (#23933) 2025-12-15 13:47:31 +08:00
Zexi Li
c6502eebd7 fix(monitor): meter alert panic (#23919) 2025-12-12 10:20:03 +08:00
屈轩
3b7615b264 fix(region): aliyun system disk size (#23927) 2025-12-12 10:19:47 +08:00
Jian Qiu
7132a3be67 fix: splitable not function due to empty datefield (#23907)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-12-09 13:34:16 +08:00
Zexi Li
06482d2f20 fix(monitor): filter baremetal host for no data query (#23892) 2025-12-03 16:18:01 +08:00
屈轩
557715bea3 fix(region): optimized backend sync (#23891) 2025-12-03 15:14:22 +08:00
屈轩
0d2cb66dc1 fix(region): aliyun vnc addr (#23885) 2025-12-03 14:04:22 +08:00
wanyaoqi
166b4b34f5 fix(host,host-deployer): host-deployer add password quality check (#23873) 2025-12-02 17:02:24 +08:00
屈轩
27f44e909a fix(region): vendor update (#23869) 2025-11-30 17:23:59 +08:00
Zexi Li
52962980c5 fix(monitor): filter alertrecords by alert_name and res_name (#23866) 2025-11-28 18:58:31 +08:00
屈轩
01cd87d8eb fix(region): vendor update (#23860) 2025-11-27 20:36:01 +08:00
wanyaoqi
323b64116a fix(host): host handlers use gotypes check ret value is nil (#23848) 2025-11-27 19:19:44 +08:00
Zexi Li
4a3a9f1b11 fix(monitor): alert shield is not working (#23863) 2025-11-27 19:18:56 +08:00
屈轩
f22db65285 fix(keystone): change token AuditIds width (#23850) 2025-11-27 17:19:28 +08:00
Zexi Li
9024e78dfc fix(monitor): threshold_range message (#23856) 2025-11-27 16:47:32 +08:00
Zexi Li
92be2b6d11 feat(monitor): support threashold range (#23854) 2025-11-27 15:11:28 +08:00
Zexi Li
859384643f feat(climc): support --ouput option for pprof command (#23841) 2025-11-27 14:18:46 +08:00
屈轩
d8ea9f576a fix(region): vendor update (#23845) 2025-11-26 16:57:09 +08:00
wanyaoqi
56711f01f2 fix(region,host): perform screendump no save to s3 (#23824) 2025-11-26 01:00:12 +08:00
wanyaoqi
d9660431fd fix(region): disk take snapshot check backing snapshot is merged (#23823) 2025-11-26 00:58:45 +08:00
屈轩
2e58bba807 fix(region): support vmware resource pool (#23828) 2025-11-25 19:07:27 +08:00
屈轩
19c0680c4b fix(region): vendor update (#23821) 2025-11-24 14:20:33 +08:00
Jian Qiu
d2c6e5514f fix: validate policy role delete condition (#23810)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-11-21 12:03:20 +08:00
Zexi Li
e175225af5 fix(monitor): alerting level (#23802) 2025-11-21 10:27:13 +08:00
Jian Qiu
3fccc13548 fix: region-dns not support dameng dialect (#23797)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-11-21 09:55:56 +08:00
屈轩
4b78268ff6 fix(region): snapshot policy resource purge (#23804) 2025-11-20 23:42:00 +08:00
Zexi Li
ae45d0d1d1 fix(monitor): title of notification by language context (#23798) 2025-11-20 20:11:42 +08:00
屈轩
8e9f4c12c2 fix(monitor): avoid panic (#23796) 2025-11-20 18:43:24 +08:00
屈轩
6e9b1e790f fix(host): format sLsusbTree field content json tag (#23793)
Co-authored-by: 云原生驿站 <33771248+CloudCourierStation@users.noreply.github.com>
2025-11-20 18:26:27 +08:00
Zexi Li
2fc05e9bbb fix(monitor): check if LastSendNotification is zero (#23783) 2025-11-20 18:03:57 +08:00
屈轩
ef046d10c9 fix(region): migrate snapshot policy resource (#23790) 2025-11-20 17:38:35 +08:00
屈轩
350028425e fix(cloudmon): account balance metric with tenant_id (#23786) 2025-11-20 14:22:33 +08:00
屈轩
49b7f9df7e fix(cloudmon): avoid undetected new resources (#23779) 2025-11-20 10:46:07 +08:00
Zexi Li
11ec38b8b7 fix(baremetal-agent): msdos typo in grub configuration (#23774) 2025-11-20 10:39:04 +08:00
Jian Qiu
0de6db47a8 fix: diskbackup fail to syncstatus on offline backend (#23763)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-11-19 10:46:37 +08:00
屈轩
9e72da7b1e fix(region): esxi vm folder (#23751) 2025-11-17 18:10:02 +08:00
屈轩
1875cf7bd6 fix(region): server sku create status (#23750) 2025-11-17 17:01:08 +08:00
wanyaoqi
c1e814ba6e feat(region,host): host dmesg collect (#23721) 2025-11-17 15:44:33 +08:00
Jian Qiu
ea87fbb8aa fix: filter schedtags by zones (#23744)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-11-15 18:30:15 +08:00
Zexi Li
453d47c99b feat(cloudcommon): add ExtraHook steps to joint model (#23741) 2025-11-14 10:50:58 +08:00
Zexi Li
3ae144e233 fix(host): SHostPingTask was stuck by calling docker command (#23734) 2025-11-13 20:19:28 +08:00
屈轩
873a5d6b16 fix(region): scope resource (#23737) 2025-11-13 14:43:52 +08:00
wanyaoqi
1b212051a9 fix(region,scheduler): check is BIOS boot request on uefi predicate (#23717) 2025-11-11 13:45:11 +08:00
Zexi Li
a34da1092c fix(baremetal): power status of server is not synced (#23689) 2025-11-10 09:56:39 +08:00
屈轩
aa394ead62 fix(region): allow delete server sku (#23695) 2025-11-05 18:19:59 +08:00
屈轩
039a69eed6 fix(region): add device for disk (#23692) 2025-11-05 15:57:50 +08:00
屈轩
8ddca94bdc fix(scheduler): sku predicate with empty zone id (#23686) 2025-11-04 20:56:30 +08:00
Zexi Li
beb3e9f9fd fix(baremetal-agent): chose root disk by pci path (#23682) 2025-11-04 20:09:12 +08:00
Jian Qiu
bdc3693c2b fix: rename check when change project (#23676)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-11-04 16:07:59 +08:00
屈轩
260b8557d8 fix(region): optimized aws server sku sync (#23675) 2025-11-03 22:32:27 +08:00
屈轩
e0706a1b43 fix(region): metadata filter by value (#23672) 2025-11-03 19:24:40 +08:00
屈轩
0ba9578ec7 fix(region): optimzed server sku sync (#23664) 2025-11-03 15:13:55 +08:00
屈轩
1a1feba74d fix(region): disk filter by server (#23660) 2025-11-01 13:32:35 +08:00
屈轩
5427facb6a fix(region): optimized filter sku by zone (#23657) 2025-11-01 13:04:56 +08:00
屈轩
6b347bf00c fix(region): vendor update (#23654) 2025-11-01 13:04:07 +08:00
Zexi Li
357a0f22e3 fix(scheduler): enable profiling (#23642)
* fix(scheduler): enable profiling

* feat(scheduler): cache NetworkAdditionalWire
2025-10-31 10:19:24 +08:00
屈轩
b4fd2eb122 fix(region): sku cpu mem sync (#23650) 2025-10-30 22:32:11 +08:00
屈轩
a846649f1c fix(region): filter disks by server list (#23645) 2025-10-30 17:24:47 +08:00
Zexi Li
a10ea01c84 fix: backend proxy worker count (#23636)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-30 10:07:01 +08:00
屈轩
2bb2742bf0 fix(region): vendor update (#23640) 2025-10-30 10:06:28 +08:00
Zexi Li
cd68e4c156 fix(host): move the hostInstance.Init() step after InitAuth (#23622) 2025-10-28 19:28:46 +08:00
屈轩
78fa396097 fix(region): set ksyun tag (#23612) 2025-10-24 22:59:17 +08:00
Zexi Li
b4876fa013 chore(ci): turn off goimports-check rule (#23609) 2025-10-24 15:49:14 +08:00
Jian Qiu
ea51d3f05f fix: rpm/deb support postinst/preinst/prerm/postrm hooks (#23595)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-23 01:03:33 +08:00
Jian Qiu
d74b732b86 fix: suport bulding multi-arch rpm deb (#23571)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-22 23:53:36 +08:00
屈轩
7d36c1fe1b fix(keystone): fetch domain user count (#23592) 2025-10-22 16:25:59 +08:00
wanyaoqi
606916760b fix(region,host,scheduler): add check kvm cpu max on cpu predicate (#23513) 2025-10-22 15:04:58 +08:00
屈轩
106f7b3d2a fix(region): disable cloudprovider when sync lost (#23583) 2025-10-22 11:30:29 +08:00
屈轩
807454ab63 fix(region): vendor update (#23580) 2025-10-22 11:12:12 +08:00
屈轩
d5711d7d64 fix(region): adjust the ip_addr character length (#23564) 2025-10-21 10:45:15 +08:00
屈轩
b999ad72ac fix(glance): add notify for image create (#23555) 2025-10-16 14:31:02 +08:00
wanyaoqi
fedf62f75b fix(webconsole): baremteasl ipmi sol instance_name hide password (#23536) 2025-10-16 00:02:18 +08:00
屈轩
451d289903 fix(region): valid essd pl0 disk resize (#23547) 2025-10-15 17:25:14 +08:00
屈轩
93101837f7 fix(region): vendor update (#23541) 2025-10-15 10:57:57 +08:00
屈轩
a7bc8c0fff fix(region): support change storage type (#23531) 2025-10-14 19:06:08 +08:00
屈轩
d913be0312 fix(region): healt status (#23526) 2025-10-13 18:51:12 +08:00
屈轩
c8efe3d1e6 fix(keystone): distribute permissions when the organization changes (#23503) 2025-10-13 18:49:53 +08:00
屈轩
d7b0a10ad9 fix(region): private zone create status (#23522) 2025-10-13 18:05:33 +08:00
wanyaoqi
73049f487a fix(host): ensure host wire marshal nil value (#23500) 2025-10-12 11:04:11 +08:00
屈轩
d9060328fc fix(region): server sku create with region id (#23510) 2025-10-11 16:55:02 +08:00
wanyaoqi
ccf1694237 fix(region,glance,host-deployer): guest image support bios boot mode detect (#23284) 2025-10-11 10:20:45 +08:00
Zexi Li
2cb0437596 fix(baremetal): ensure the execution of the BaremetalServerDestroyTask (#23495) 2025-10-09 17:07:10 +08:00
Jian Qiu
c88e8fef1b fix: ignore e2fsck errors if retcode < 4 (#23487)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-09 16:31:16 +08:00
wanyaoqi
2ca2435595 fix(host): disk resize error input params (#23491) 2025-10-09 13:26:29 +08:00
Jian Qiu
30bac52d1c fix: network manager supports ipv4 static routes for 3.11 (#23484)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-08 13:18:00 +08:00
Jian Qiu
74a8b5667f fix: support network manager connection profiles (#23467)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-03 09:24:59 +08:00
Jian Qiu
ec3b52930e fix: default cloud region init error (#23472)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-03 09:24:34 +08:00
屈轩
4703a7094d fix(cloudmon): metric sync (#23463) 2025-09-30 16:53:03 +08:00
屈轩
f8a46a06fc fix(region): vendor update (#23460) 2025-09-30 15:09:50 +08:00
屈轩
a64749ef31 fix(region): host order by virt cpu (#23455) 2025-09-30 13:19:04 +08:00
Jian Qiu
defb33a861 fix: hostman master nic may be nil (#23448)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-30 11:17:37 +08:00
Jian Qiu
ab6f22c5db fix: s3 common options (#23443)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-29 19:22:14 +08:00
Jian Qiu
7947bd6686 fix: disable password history unique check by default (#23436)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-29 15:48:41 +08:00
屈轩
50ab8bf4d4 fix(cloudevent): options changed with etcd (#23434) 2025-09-29 12:24:23 +08:00
屈轩
5a5dbed43b fix(region): vendor update (#23417) 2025-09-28 18:04:13 +08:00
wanyaoqi
96b330b6c4 fix(host-deployer): update host-deployer-base to 1.4.11 (#23412) 2025-09-28 17:25:49 +08:00
屈轩
d62f1c1149 fix(region): vendor update (#23406) 2025-09-28 14:59:03 +08:00
wanyaoqi
2b90c029ee fix(region,host): guest add vnc screen dump support (#23374)
* fix(host): update nic confs inside vm on qga delete nics

Signed-off-by: wanyaoqi <wanyaoqi@yunion.cn>

* fix(region,host): guest add vnc screen dump support

---------

Signed-off-by: wanyaoqi <wanyaoqi@yunion.cn>
2025-09-27 12:03:10 +08:00
wanyaoqi
edefdd6ca1 Automated cherry pick of #23386: fix(host-deployer): allow growpart on primary partition (#23393)
* fix(host): init cgroup ignore disable cgroup option

* fix(host-deployer): allow growpart on primary partition
2025-09-27 12:01:44 +08:00
屈轩
b6c3aa0a7a fix(region): vendor update (#23399) 2025-09-26 18:05:30 +08:00
屈轩
85bc3abc77 fix(region): vendor update (#23384) 2025-09-26 13:53:45 +08:00
670 changed files with 30846 additions and 24671 deletions

View File

@@ -253,7 +253,7 @@ hostdeployer-grpc-gen:
check: fmt-check
check: gendocgo-check
check: goimports-check
#check: goimports-check
#check: vet-check
#check: y18n-check
.PHONY: check
@@ -277,7 +277,7 @@ dep:
@echo "$$depDeprecated"
@$(MAKE) mod
RELEASE_BRANCH:=release/3.11
RELEASE_BRANCH:=release/3.11.13
GOPROXY ?= direct
mod:

View File

@@ -36,6 +36,12 @@ fi
. $ROOT/vars
BUILDROOT=$(mktemp -d 2>/dev/null || mktemp -d -t 'yunion')
function cleanup {
rm -rf "$BUILDROOT"
echo "Deleted temp working directory $BUILDROOT"
}
# register the cleanup function to be called on the EXIT signal
trap cleanup EXIT
echo "Build root ${BUILDROOT}"
@@ -104,41 +110,84 @@ if [ -d $ROOT/root ]; then
rsync -a $ROOT/root/ \$RPM_BUILD_ROOT
fi
%pre
%pre" > $SPEC_FILE
if [ -f $ROOT/preinst ]; then
cat $ROOT/preinst >> $SPEC_FILE
else
echo "
%if %{use_systemd}
getent group %{owner} >/dev/null || /usr/sbin/groupadd -r %{owner}
getent passwd %{owner} >/dev/null || /usr/sbin/useradd -r -s /sbin/nologin -d %{homedir} -M -g %{owner} %{owner}
%endif
" >> $SPEC_FILE
fi
%post
echo "
%post" >> $SPEC_FILE
if [ -f $ROOT/postinst ]; then
cat $ROOT/postinst >> $SPEC_FILE
else
echo "
%if %{use_systemd}
mkdir -p /var/run/%{owner}
chown -R %{owner}:%{owner} /var/run/%{owner}
/usr/bin/systemctl preset %{pkgname}.service >/dev/null 2>&1 ||:
%endif
" >> $SPEC_FILE
fi
%preun
echo "
%preun" >> $SPEC_FILE
if [ -f $ROOT/prerm ]; then
cat $ROOT/prerm >> $SPEC_FILE
else
echo "
%if %{use_systemd}
/usr/bin/systemctl --no-reload disable %{pkgname}.service >/dev/null 2>&1 || :
/usr/bin/systemctl stop %{pkgname}.service >/dev/null 2>&1 ||:
%endif
" >> $SPEC_FILE
fi
%postun
echo "
%postun" >> $SPEC_FILE
if [ -f $ROOT/postrm ]; then
cat $ROOT/postrm >> $SPEC_FILE
else
echo "
%if %{use_systemd}
/usr/bin/systemctl daemon-reload >/dev/null 2>&1 ||:
%endif
" >> $SPEC_FILE
fi
echo -n "
%files
%doc
$BIN_PATH/$PKG
$(for b in $EXTRA_BINS; do echo $BIN_PATH/$b; done)
" > $SPEC_FILE
" >> $SPEC_FILE
for b in $EXTRA_BINS; do
echo $BIN_PATH/$b >> $SPEC_FILE
done
if [ -d $ROOT/root/ ]; then
find $ROOT/root/ -type f | sed -e "s:$ROOT/root::g" >> $SPEC_FILE
fi
rpmbuild --define "_topdir $BUILDROOT" -bb $SPEC_FILE
TARGET=
case "$GOARCH" in
"arm64" | "aarch64" | "arm")
TARGET="--target aarch64-redhat-linux"
;;
"amd64" | "x86" | "i686" | "i386" | "x86_64")
TARGET="--target x86_64-redhat-linux"
;;
esac
rpmbuild --define "_topdir $BUILDROOT" -bb $SPEC_FILE $TARGET
find $RPM_DIR -type f | while read f; do
d="$(dirname "$f")"
@@ -146,5 +195,3 @@ find $RPM_DIR -type f | while read f; do
mkdir -p "$d"
cp $f $d
done
rm -fr $BUILDROOT

View File

@@ -35,26 +35,6 @@ fi
. $ROOT/vars
if [ -z "$VERSION" ]; then
TAG=$(git describe --abbrev=0 --tags || echo 000000)
VERSION=${TAG/\//-}
VERSION=${VERSION/v/}
fi
RELEASE=`date +"%y%m%d%H"`
FULL_VERSION=$VERSION-$RELEASE
BUILDROOT=$OUTPUT_DIR/yunion-$1-$FULL_VERSION
rm -rf $BUILDROOT
mkdir -p $BUILDROOT/DEBIAN
mkdir -p $BUILDROOT/$BIN_PATH
cp -rf $BIN $BUILDROOT/$BIN_PATH
if [ -d $ROOT/root ]; then
cp -rf $ROOT/root/* $BUILDROOT/
fi
echo "Build root ${BUILDROOT}"
case $(uname -m) in
x86_64)
CURRENT_ARCH=amd64
@@ -64,15 +44,123 @@ case $(uname -m) in
;;
esac
echo "Package: yunion-$1
if [[ -n "$GOARCH" ]]; then
case "$GOARCH" in
"arm64" | "arm" | "aarch64")
CURRENT_ARCH="arm64"
;;
"x86" | "x86_64" | "i686" | "i386" | "amd64")
CURRENT_ARCH="amd64"
;;
esac
fi
if [ -z "$VERSION" ]; then
TAG=$(git describe --abbrev=0 --tags || echo 000000)
VERSION=${TAG/\//-}
VERSION=${VERSION/v/}
VERSION=${VERSION/master-/}
fi
RELEASE=`date +"%y%m%d%H"`
FULL_VERSION=$VERSION-$RELEASE
BUILDROOT=$OUTPUT_DIR/yunion-${PKG}-${FULL_VERSION}_${CURRENT_ARCH}
function cleanup {
rm -rf "$BUILDROOT"
echo "Deleted temp working directory $BUILDROOT"
}
# register the cleanup function to be called on the EXIT signal
trap cleanup EXIT
rm -rf $BUILDROOT
mkdir -p $BUILDROOT/DEBIAN
mkdir -p $BUILDROOT/$BIN_PATH
cp -rf $BIN $BUILDROOT/$BIN_PATH
if [ -d $ROOT/root ]; then
cp -rf $ROOT/root/* $BUILDROOT/
fi
echo "Build root ${BUILDROOT}"
echo "Package: yunion-$PKG
Version: $FULL_VERSION
Section: base
Priority: optional
Architecture: $CURRENT_ARCH
Maintainer: wanyaoqi@yunionyun.com
Description: Yunion $1
" > $BUILDROOT/DEBIAN/control
Description: $DESCRIPTION" > $BUILDROOT/DEBIAN/control
if [ ${#REQUIRES[@]} -gt 0 ]; then
DEPS=$(IFS=, ; echo "${REQUIRES[*]}")
echo "Depends: $DEPS" >> $BUILDROOT/DEBIAN/control
fi
chmod 0755 $BUILDROOT/DEBIAN/control
cat $BUILDROOT/DEBIAN/control
dpkg-deb --build $BUILDROOT
echo "#!/bin/bash
" > $BUILDROOT/DEBIAN/preinst
if [ -f $ROOT/preinst ]; then
cat $ROOT/preinst >> $BUILDROOT/DEBIAN/preinst
else
if [ "$SERVICE" == "yes" ] && [ -n "$OWNER" ]; then
echo "
getent group ${OWNER} >/dev/null || /usr/sbin/groupadd -r ${OWNER}
getent passwd ${OWNER} >/dev/null || /usr/sbin/useradd -r -s /sbin/nologin -d /home/${OWNER} -M -g ${OWNER} ${OWNER}
" >> $BUILDROOT/DEBIAN/preinst
fi
fi
chmod 0755 $BUILDROOT/DEBIAN/preinst
echo "#!/bin/bash
" > $BUILDROOT/DEBIAN/postinst
if [ -f $ROOT/postinst ]; then
cat $ROOT/postinst >> $BUILDROOT/DEBIAN/postinst
else
if [ "$SERVICE" == "yes" ]; then
echo "
/usr/bin/systemctl preset yunion-${PKG}.service >/dev/null 2>&1 ||:
" >> $BUILDROOT/DEBIAN/postinst
fi
fi
chmod 0755 $BUILDROOT/DEBIAN/postinst
echo "#!/bin/bash
" > $BUILDROOT/DEBIAN/prerm
if [ -f $ROOT/prerm ]; then
cat $ROOT/prerm >> $BUILDROOT/DEBIAN/prerm
else
if [ "$SERVICE" == "yes" ]; then
echo "
/usr/bin/systemctl --no-reload disable yunion-${PKG}.service >/dev/null 2>&1 || :
/usr/bin/systemctl stop yunion-${PKG}.service >/dev/null 2>&1 ||:
" >> $BUILDROOT/DEBIAN/prerm
fi
fi
chmod 0755 $BUILDROOT/DEBIAN/prerm
echo "#!/bin/bash
" > $BUILDROOT/DEBIAN/postrm
if [ -f $ROOT/postrm ]; then
cat $ROOT/postrm >> $BUILDROOT/DEBIAN/postrm
else
if [ "$SERVICE" == "yes" ]; then
echo "
/usr/bin/systemctl daemon-reload >/dev/null 2>&1 ||:
" >> $BUILDROOT/DEBIAN/postrm
fi
fi
chmod 0755 $BUILDROOT/DEBIAN/postrm
dpkg-deb --build $BUILDROOT
case "$CURRENT_ARCH" in
"amd64")
DSTARCH="x86_64"
;;
"arm64")
DSTARCH="aarch64"
;;
esac
mkdir -p ${OUTPUT_DIR}/${DSTARCH}
mv ${BUILDROOT}.deb ${OUTPUT_DIR}/${DSTARCH}/

View File

@@ -1,4 +1,4 @@
FROM registry.cn-beijing.aliyuncs.com/yunionio/baremetal-base:v0.3.9-20231219.0
FROM registry.cn-beijing.aliyuncs.com/yunionio/baremetal-base:v0.3.9-20251215.0
MAINTAINER "Zexi Li <lizexi@yunionyun.com>"

View File

@@ -1,7 +1,7 @@
#FROM --platform=linux/amd64 registry.cn-beijing.aliyuncs.com/yunionio/centos-build:1.1-4 as build
#RUN yum install -y https://iso.yunion.cn/vm-images/baremetal-pxerom-1.1.0-21092209.x86_64.rpm
#RUN yum install -y http://192.168.23.50:8083/baremetal-pxerom-1.1.0-21092209.x86_64.rpm
FROM registry.cn-beijing.aliyuncs.com/yunionio/yunionos:v3.10.8-20231215.0 as yunionos
FROM registry.cn-beijing.aliyuncs.com/yunionio/yunionos:v4.0.0-20251201.0 as yunionos
FROM centos:8 as grub-stage

View File

@@ -1,4 +1,4 @@
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.9
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.11
MAINTAINER "Yaoqi Wan wanyaoqi@yunionyun.com"

View File

@@ -30,7 +30,7 @@ WEBCONSOLE_BASE_VERSION = 20230731.2
webconsole-base:
$(DOCKER_BUILDX)/webconsole-base:$(WEBCONSOLE_BASE_VERSION) -f ./Dockerfile.webconsole-base .
BAREMETAL_BASE_VERSION = v0.3.9-20231219.1
BAREMETAL_BASE_VERSION = v0.3.9-20251112.1
baremetal-base:
$(DOCKER_BUILDX)/baremetal-base:$(BAREMETAL_BASE_VERSION) -f ./Dockerfile.baremetal-base .

View File

@@ -1,5 +1,5 @@
DESCRIPTION="Yunion Cloud Image Service"
REQUIRES=(
yunion-qemu-2.12.1
yunion-qemu-4.2.0
)

View File

@@ -1,4 +1,3 @@
{{.title}}
策略名称: {{.name}}
触发时间: {{.start_time}}
报警级别: {{.level}}

View File

@@ -1,4 +1,3 @@
{{.title}}
AlertName: {{.name}}
Time: {{.start_time}}
Level: {{.level}}

View File

@@ -1 +1 @@
{{.title}}
{{monitorTitle .}}

View File

@@ -1 +1 @@
{{.title}}
{{monitorTitle .}}

View File

@@ -1 +1 @@
{{.title}}
{{monitorTitle .}}

View File

@@ -1 +1 @@
{{.title}}
{{monitorTitle .}}

View File

@@ -42,30 +42,17 @@ import (
func init() {
cmd := shell.NewResourceCmd(&modules.Disks)
cmd.List(&compute_options.DiskListOptions{})
cmd.Show(&compute_options.DiskIdOptions{})
cmd.Perform("public", &compute_options.DiskIdOptions{})
cmd.Perform("private", &compute_options.DiskIdOptions{})
cmd.Perform("syncstatus", &compute_options.DiskIdOptions{})
cmd.Perform("change-owner-candidate-domains", &compute_options.DiskIdOptions{})
cmd.Perform("disk-cancel-delete", &compute_options.DiskIdOptions{})
cmd.Perform("set-class-metadata", &options.ResourceMetadataOptions{})
cmd.Perform("rebuild", &options.ResourceIdOptions{})
cmd.Perform("migrate", &compute_options.DiskMigrateOptions{})
cmd.Perform("change-billing-type", new(compute_options.DiskChangeBillingTypeOptions))
type DiskDetailOptions struct {
ID string `help:"ID or Name of disk"`
}
R(&DiskDetailOptions{}, "disk-show", "Show details of disk", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
disk, e := modules.Disks.Get(s, args.ID, nil)
if e != nil {
return e
}
printObject(disk)
return nil
})
R(&DiskDetailOptions{}, "disk-cancel-delete", "Cancel pending delete disks", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
disk, e := modules.Disks.PerformAction(s, args.ID, "cancel-delete", nil)
if e != nil {
return e
}
printObject(disk)
return nil
})
cmd.Perform("change-storage-type", &compute_options.DiskChangeStorageTypeOptions{})
type DiskDeleteOptions struct {
ID []string `help:"ID of disks to delete" metavar:"DISK"`
@@ -95,25 +82,7 @@ func init() {
return nil
})
R(&DiskDetailOptions{}, "disk-public", "Make a disk public", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
disk, e := modules.Disks.PerformAction(s, args.ID, "public", nil)
if e != nil {
return e
}
printObject(disk)
return nil
})
R(&DiskDetailOptions{}, "disk-private", "Make a disk private", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
disk, e := modules.Disks.PerformAction(s, args.ID, "private", nil)
if e != nil {
return e
}
printObject(disk)
return nil
})
R(&DiskDetailOptions{}, "disk-metadata", "Get metadata of a disk", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
R(&compute_options.DiskIdOptions{}, "disk-metadata", "Get metadata of a disk", func(s *mcclient.ClientSession, args *compute_options.DiskIdOptions) error {
meta, e := modules.Disks.GetMetadata(s, args.ID, nil)
if e != nil {
return e
@@ -122,15 +91,6 @@ func init() {
return nil
})
R(&DiskDetailOptions{}, "disk-syncstatus", "Sync status for disk", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
ret, e := modules.Disks.PerformAction(s, args.ID, "syncstatus", nil)
if e != nil {
return e
}
printObject(ret)
return nil
})
type DiskUpdateOptions struct {
ID string `help:"ID or name of disk"`
Name string `help:"New name of disk"`
@@ -299,7 +259,7 @@ func init() {
return nil
})
R(&DiskDetailOptions{}, "disk-change-owner-candidate-domains", "Get change owner candidate domain list", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
R(&compute_options.DiskIdOptions{}, "disk-change-owner-candidate-domains", "Get change owner candidate domain list", func(s *mcclient.ClientSession, args *compute_options.DiskIdOptions) error {
result, err := modules.Disks.GetSpecific(s, args.ID, "change-owner-candidate-domains", nil)
if err != nil {
return err

View File

@@ -333,6 +333,7 @@ func init() {
IpAddr string `help:"IP address"`
Bridge string `help:"Bridge of hostwire"`
Interface string `help:"Interface name, eg:eth0, en0"`
VlanId int `help:"Vlan ID"`
}
R(&HostAddNetIfOptions{}, "host-add-netif", "Host add a NIC", func(s *mcclient.ClientSession, args *HostAddNetIfOptions) error {
params := jsonutils.NewDict()
@@ -352,6 +353,7 @@ func init() {
if len(args.Interface) > 0 {
params.Add(jsonutils.NewString(args.Interface), "interface")
}
addVlanIdToParams(params, args.VlanId)
result, err := modules.Hosts.PerformAction(s, args.ID, "add-netif", params)
if err != nil {
return err
@@ -361,12 +363,14 @@ func init() {
})
type HostRemoveNetIfOptions struct {
ID string `help:"ID or Name of host"`
MAC string `help:"MAC of NIC to remove"`
ID string `help:"ID or Name of host"`
MAC string `help:"MAC of NIC to remove"`
VlanId int `help:"Vlan Id"`
}
R(&HostRemoveNetIfOptions{}, "host-remove-netif", "Remove NIC from host", func(s *mcclient.ClientSession, args *HostRemoveNetIfOptions) error {
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(args.MAC), "mac")
addVlanIdToParams(params, args.VlanId)
result, err := modules.Hosts.PerformAction(s, args.ID, "remove-netif", params)
if err != nil {
return err
@@ -381,6 +385,7 @@ func init() {
Ip string `help:"IP address"`
Network string `help:"network to connect"`
Reserved bool `help:"fetch IP from reserved pool"`
VlanId int `help:"Vlan ID"`
}
R(&HostEnableNetIfOptions{}, "host-enable-netif", "Enable a network interface for a host", func(s *mcclient.ClientSession, args *HostEnableNetIfOptions) error {
params := jsonutils.NewDict()
@@ -394,6 +399,7 @@ func init() {
if len(args.Network) > 0 {
params.Add(jsonutils.NewString(args.Network), "network")
}
addVlanIdToParams(params, args.VlanId)
result, err := modules.Hosts.PerformAction(s, args.ID, "enable-netif", params)
if err != nil {
return err
@@ -406,6 +412,7 @@ func init() {
ID string `help:"ID or Name of host"`
MAC string `help:"MAC of NIC to disable"`
Reserve bool `help:"Reserve the IP address"`
VlanId int `help:"Vlan Id"`
}
R(&HostDisableNetIfOptions{}, "host-disable-netif", "Disable a network interface", func(s *mcclient.ClientSession, args *HostDisableNetIfOptions) error {
params := jsonutils.NewDict()
@@ -413,6 +420,7 @@ func init() {
if args.Reserve {
params.Add(jsonutils.JSONTrue, "reserve")
}
addVlanIdToParams(params, args.VlanId)
result, err := modules.Hosts.PerformAction(s, args.ID, "disable-netif", params)
if err != nil {
return err
@@ -754,3 +762,9 @@ func init() {
},
)
}
func addVlanIdToParams(params *jsonutils.JSONDict, vlanId int) {
if vlanId > 1 {
params.Add(jsonutils.NewInt(int64(vlanId)), "vlan_id")
}
}

View File

@@ -37,7 +37,7 @@ func init() {
return nil
})
R(&options.TagListOptions{}, "tag-list", "List tags", func(s *mcclient.ClientSession, opts *options.TagListOptions) error {
R(&options.TagListOptions{}, "service-metadata-list", "List service metadata", func(s *mcclient.ClientSession, opts *options.TagListOptions) error {
var mod modulebase.IResourceManager
switch opts.Service {
case "compute":

View File

@@ -143,6 +143,9 @@ func init() {
cmd.Get("sshport", new(options.ServerIdOptions))
cmd.Get("qemu-info", new(options.ServerIdOptions))
cmd.Get("hardware-info", new(options.ServerIdOptions))
cmd.Get("screen-dump-show", new(options.ServerScreenDumpOptions))
cmd.BatchPerform("screen-dump", new(options.ServerIdsOptions))
cmd.Perform("set-network-num-queues", new(options.ServerSetNetworkNumQueues))
cmd.GetProperty(&options.ServerStatusStatisticsOptions{})
cmd.GetProperty(&options.ServerProjectStatisticsOptions{})

View File

@@ -0,0 +1,23 @@
package compute
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/cmd/climc/shell"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/mcclient/options"
)
type ServerScreenDumpListOptions struct {
options.BaseListOptions
Server string `help:"Id or name of server"`
}
func (o *ServerScreenDumpListOptions) Params() (jsonutils.JSONObject, error) {
return jsonutils.Marshal(o), nil
}
func init() {
cmd := shell.NewResourceCmd(&modules.ServerScreenDumps)
cmd.List(new(ServerScreenDumpListOptions))
}

View File

@@ -23,7 +23,7 @@ import (
func init() {
type WorkerListOptions struct {
ServiceType string `choices:"image|cloudid|cloudevent|devtool|ansible|identity|notify|log|compute|compute_v2"`
ServiceType string `choices:"image|cloudid|cloudevent|devtool|ansible|identity|notify|log|compute|compute_v2|meter|suggestion|cloudmon|cloudproxy|dns|monitor|scheduler|vpcagent|webconsole|yunionconf|bastionhost|extdb|yunionapi|report"`
}
R(&WorkerListOptions{}, "worker-list", "List workers", func(s *mcclient.ClientSession, args *WorkerListOptions) error {
result, err := modules.Workers.List(s, jsonutils.Marshal(args))

View File

@@ -83,6 +83,10 @@ func doK8sEventList(s *mcclient.ClientSession, args *EventListOptions) error {
return DoEventList(*k8s.Logs.ResourceManager, s, args)
}
func doHostDmesgList(s *mcclient.ClientSession, args *EventListOptions) error {
return DoEventList(modules.DmesgLogs, s, args)
}
func DoEventList(man modulebase.ResourceManager, s *mcclient.ClientSession, args *EventListOptions) error {
params := jsonutils.NewDict()
if len(args.Type) > 0 {
@@ -157,6 +161,7 @@ func init() {
R(&EventListOptions{}, "monitor-event-show", "Show operation event logs", doMonitorEventList)
R(&EventListOptions{}, "notify-event-show", "Show operation event logs", doNotifyEventList)
R(&EventListOptions{}, "kube-event-show", "Show operation event logs", doK8sEventList)
R(&EventListOptions{}, "host-dmesg-show", "Show host dmesgs", doHostDmesgList)
R(&TypeEventListOptions{}, "server-event", "Show operation event logs of server", func(s *mcclient.ClientSession, args *TypeEventListOptions) error {
nargs := EventListOptions{BaseEventListOptions: args.BaseEventListOptions, Id: args.ID, Type: []string{"server"}}

View File

@@ -28,6 +28,7 @@ func init() {
MODULE string `help:"module name"`
FIELD string `help:"distinct field name to query"`
Extra bool `help:"query extra distinct field"`
Scope string `help:"resource scope" choices:"system|domain|project"`
}
R(&DistinctFieldOption{}, "distinct-field", "Query values of a distinct field for a module", func(s *mcclient.ClientSession, args *DistinctFieldOption) error {
mod, err := modulebase.GetModule(s, args.MODULE)
@@ -43,6 +44,9 @@ func init() {
} else {
params.Add(jsonutils.NewString(args.FIELD), "field")
}
if len(args.Scope) > 0 {
params.Add(jsonutils.NewString(args.Scope), "scope")
}
result, err := mod.Get(s, "distinct-field", params)
if err != nil {
return err
@@ -56,6 +60,7 @@ func init() {
Field []string `help:"distinct field name to query"`
ExtraField []string `help:"distinct field name to query"`
ExtraResource string
Scope string `help:"resource scope" choices:"system|domain|project"`
}
R(&DistinctFieldsOption{}, "distinct-fields", "Query values of a distinct fields for a module", func(s *mcclient.ClientSession, args *DistinctFieldsOption) error {
mod, err := modulebase.GetModule(s, args.MODULE)

View File

@@ -0,0 +1,37 @@
// 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 misc
import (
"fmt"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
)
func init() {
type HistoryDataCleanOptions struct {
SERVICE string `help:"Service type"`
Day *int `default:"30"`
}
R(&HistoryDataCleanOptions{}, "history-data-clean", "clean history data", func(s *mcclient.ClientSession, args *HistoryDataCleanOptions) error {
body, err := modules.HistoryDataClean(s, args.SERVICE, args.Day)
if err != nil {
return err
}
fmt.Println(body.PrettyString())
return nil
})
}

View File

@@ -38,6 +38,23 @@ func init() {
Service string `help:"Service type"`
Address string `help:"Service listen address"`
Gc bool `help:"run GC before taking the heap sample"`
Output string `help:"Save pprof file to specified path instead of opening with go tool" short-token:"o"`
}
writeReaderToFile := func(input io.Reader, file *os.File) error {
if _, err := io.Copy(file, input); err != nil {
return err
}
return nil
}
downloadToFile := func(input io.Reader, filepath string) error {
file, err := os.Create(filepath)
if err != nil {
return err
}
defer file.Close()
return writeReaderToFile(input, file)
}
downloadToTemp := func(input io.Reader, pattern string) (string, error) {
@@ -46,7 +63,7 @@ func init() {
return "", err
}
defer tmpfile.Close()
if _, err := io.Copy(tmpfile, input); err != nil {
if err := writeReaderToFile(input, tmpfile); err != nil {
return "", err
}
return tmpfile.Name(), nil
@@ -83,6 +100,15 @@ func init() {
return err
}
// If output path is specified, save file and return
if len(opts.Output) > 0 {
if err := downloadToFile(src, opts.Output); err != nil {
return errors.Wrapf(err, "save pprof file to %s", opts.Output)
}
fmt.Printf("pprof file saved to: %s\n", opts.Output)
return nil
}
tempfile, err := downloadToTemp(src, pType)
if err != nil {
return err

View File

@@ -34,7 +34,7 @@ type CommonAlertTerm struct {
Comparator string
Threshold float64
Filters []monitorapi.MetricQueryTag
FieldOpt string
FieldOpt monitorapi.CommonAlertFieldOpt
Name string
ConditionType string
From string
@@ -94,7 +94,7 @@ func newCommonAlertQuery(tem *CommonAlertTerm) *monitorapi.CommonAlertQuery {
Operator: tem.Operator,
}
if tem.FieldOpt != "" {
commonAlert.FieldOpt = monitorapi.CommonAlertFieldOpt_Division
commonAlert.FieldOpt = monitorapi.CommonAlertFieldOptDivision
}
if len(tem.ConditionType) != 0 {
commonAlert.ConditionType = tem.ConditionType

View File

@@ -16,6 +16,9 @@ package notify
import (
"yunion.io/x/onecloud/cmd/climc/shell"
identity_api "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/mcclient"
identity_modules "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/notify"
options "yunion.io/x/onecloud/pkg/mcclient/options/notify"
)
@@ -36,4 +39,32 @@ func init() {
cmd.PerformClass("get-types", new(options.ReceiverGetTypeOptions))
cmd.Perform("get-subscription", new(options.ReceiverGetSubscriptionOptions))
cmd.GetProperty(new(options.SReceiverRoleContactType))
type SyncUserContactOptions struct {
USERID string `json:"user_id"`
Mobile string `json:"mobile"`
Email string `json:"email"`
}
R(&SyncUserContactOptions{}, "sync-user-contacts", "Sync user contact", func(s *mcclient.ClientSession, args *SyncUserContactOptions) error {
userObj, err := identity_modules.UsersV3.Get(s, args.USERID, nil)
if err != nil {
return err
}
user := identity_api.UserDetails{}
err = userObj.Unmarshal(&user)
if err != nil {
return err
}
if len(args.Mobile) == 0 {
args.Mobile = user.Mobile
}
if len(args.Email) == 0 {
args.Email = user.Email
}
err = modules.NotifyReceiver.SyncUserContact(s, user.Id, args.Mobile, args.Email)
if err != nil {
return err
}
return nil
})
}

87
cmd/isocli/main.go Normal file
View File

@@ -0,0 +1,87 @@
// 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 main
import (
"fmt"
"os"
"yunion.io/x/pkg/util/shellutils"
"yunion.io/x/structarg"
_ "yunion.io/x/onecloud/cmd/isocli/shell"
)
type BaseOptions struct {
Debug bool `help:"debug mode"`
SUBCOMMAND string `help:"aliyuncli subcommand" subcommand:"true"`
}
func getSubcommandParser() (*structarg.ArgumentParser, error) {
parse, e := structarg.NewArgumentParserWithHelp(&BaseOptions{},
"isocli",
"Command-line ISO tools.",
`See "isocli COMMAND --help" for help on a specific command.`)
if e != nil {
return nil, e
}
subcmd := parse.GetSubcommand()
if subcmd == nil {
return nil, fmt.Errorf("No subcommand argument.")
}
for _, v := range shellutils.CommandTable {
_, e := subcmd.AddSubParserWithHelp(v.Options, v.Command, v.Desc, v.Callback)
if e != nil {
return nil, e
}
}
return parse, nil
}
func showErrorAndExit(e error) {
fmt.Fprintf(os.Stderr, "%s", e)
fmt.Fprintln(os.Stderr)
os.Exit(1)
}
func main() {
parser, e := getSubcommandParser()
if e != nil {
showErrorAndExit(e)
}
e = parser.ParseArgs(os.Args[1:], false)
if parser.IsHelpSet() {
fmt.Print(parser.HelpString())
return
}
subcmd := parser.GetSubcommand()
subparser := subcmd.GetSubParser()
if e != nil || subparser == nil {
if subparser != nil {
fmt.Print(subparser.Usage())
} else {
fmt.Print(parser.Usage())
}
showErrorAndExit(e)
}
suboptions := subparser.Options()
e = subcmd.Invoke(suboptions)
if e != nil {
showErrorAndExit(e)
}
}

82
cmd/isocli/shell/iso.go Normal file
View File

@@ -0,0 +1,82 @@
// 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 (
"fmt"
"os"
"path/filepath"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/util/shellutils"
"yunion.io/x/onecloud/pkg/util/isoutils"
)
func init() {
type DetectOSOptions struct {
ISO string `help:"ISO file"`
}
shellutils.R(&DetectOSOptions{}, "detect", "Detect", func(args *DetectOSOptions) error {
stat, err := os.Stat(args.ISO)
if err != nil {
return err
}
if stat.IsDir() {
// 如果是目录,仅遍历一层目录下的 .iso 文件
entries, err := os.ReadDir(args.ISO)
if err != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
continue // 跳过子目录
}
if strings.HasSuffix(strings.ToLower(entry.Name()), ".iso") {
path := filepath.Join(args.ISO, entry.Name())
fmt.Printf("Processing: %s\n", path)
f, err := os.Open(path)
if err != nil {
fmt.Printf("Error opening %s: %v\n", path, err)
continue // 继续处理其他文件
}
isoInfo, err := isoutils.DetectOSFromISO(f)
f.Close()
if err != nil {
fmt.Printf("Error detecting OS from %s: %v\n", path, err)
continue
}
fmt.Printf("%s: %s\n", path, jsonutils.Marshal(isoInfo))
}
}
return nil
}
// 如果是文件,按原逻辑处理
f, err := os.Open(args.ISO)
if err != nil {
return err
}
defer f.Close()
isoInfo, err := isoutils.DetectOSFromISO(f)
if err != nil {
return err
}
fmt.Printf("%s: %s\n", args.ISO, jsonutils.Marshal(isoInfo))
return nil
})
}

View File

@@ -164,19 +164,32 @@ func (c *RaidInfoCollector) toTelegrafReportData(raidDiskInfo []*baremetal.Barem
tag := fmt.Sprintf("%s=%s,%s=%s", "hostname", c.Hostname, "host_ip", c.HostIp)
ret := []string{}
for i := 0; i < len(raidDiskInfo); i++ {
statArr := []string{}
fieldArr := []string{}
tagArr := []string{}
raidDiskInfo[i].Status = strings.ToLower(raidDiskInfo[i].Status)
jStat := jsonutils.Marshal(raidDiskInfo[i])
jMap, _ := jStat.GetMap()
for k, v := range jMap {
statArr = append(statArr, fmt.Sprintf("%s=%s", k, v.String()))
vStr, _ := v.GetString()
if vStr == "" {
continue
}
vStr = strings.ReplaceAll(vStr, " ", "\\ ")
kv := fmt.Sprintf("%s=%s", k, vStr)
switch k {
case "adapter", "slot":
fieldArr = append(fieldArr, kv)
case "model", "driver", "status":
tagArr = append(tagArr, kv)
case "index":
continue
default:
tagArr = append(tagArr, kv)
}
}
stat := strings.Join(statArr, ",")
diskTag := fmt.Sprintf(
"%s,%s=%s,%s=%d,%s=%d", tag, "driver", raidDiskInfo[i].Driver,
"adapter", raidDiskInfo[i].Adapter, "slot", raidDiskInfo[i].Slot,
)
line := fmt.Sprintf("%s,%s %s", MEASUREMENT, diskTag, stat)
field := strings.Join(fieldArr, ",")
diskTag := tag + "," + strings.Join(tagArr, ",")
line := fmt.Sprintf("%s,%s %s", MEASUREMENT, diskTag, field)
ret = append(ret, line)
}
return strings.Join(ret, "\n")
@@ -185,7 +198,7 @@ func (c *RaidInfoCollector) toTelegrafReportData(raidDiskInfo []*baremetal.Barem
func (c *RaidInfoCollector) reportRaidInfoToTelegraf(data string) {
body := strings.NewReader(data)
res, err := httputils.Request(
httputils.GetDefaultClient(), context.Background(), "POST", TelegrafServer, nil, body, false)
httputils.GetDefaultClient(), context.Background(), "POST", TelegrafServer, nil, body, true)
if err != nil {
log.Errorf("Upload guest metric failed: %s", err)
return

30
go.mod
View File

@@ -6,6 +6,7 @@ require (
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669
github.com/360EntSecGroup-Skylar/excelize v1.4.0
github.com/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2
github.com/Microsoft/go-winio v0.6.2
github.com/aliyun/alibaba-cloud-sdk-go v1.61.684
github.com/anacrolix/torrent v0.0.0-20181129073333-cc531b8c4a80
github.com/benbjohnson/clock v1.0.0
@@ -23,6 +24,7 @@ require (
github.com/go-yaml/yaml v2.1.0+incompatible
github.com/golang-plus/uuid v1.0.0
github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.5.3
github.com/google/gopacket v1.1.17
github.com/google/uuid v1.6.0
github.com/googollee/go-socket.io v0.0.0-20181214084611-0ad7206c347a
@@ -33,6 +35,7 @@ require (
github.com/influxdata/influxql v1.1.0
github.com/influxdata/promql/v2 v2.12.0
github.com/jaypipes/ghw v0.11.0
github.com/kdomanski/iso9660 v0.4.0
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/lestrrat-go/jwx v1.0.2
github.com/lestrrat/go-jwx v0.0.0-20180221005942-b7d4802280ae
@@ -44,6 +47,7 @@ require (
github.com/mholt/caddy v0.10.11
github.com/miekg/dns v1.1.25
github.com/minio/minio-go v6.0.14+incompatible
github.com/mogaika/udf v0.0.0-20171019171931-167f0ab01c73
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb
github.com/pierrec/lz4/v4 v4.1.15
github.com/pkg/errors v0.9.1
@@ -55,7 +59,7 @@ require (
github.com/sevlyar/go-daemon v0.1.5
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/shirou/gopsutil/v3 v3.22.10
github.com/sirupsen/logrus v1.9.0
github.com/sirupsen/logrus v1.9.3
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9
github.com/smartystreets/goconvey v1.7.2
github.com/stretchr/testify v1.9.0
@@ -66,6 +70,7 @@ require (
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74
github.com/vmihailenco/msgpack v4.0.4+incompatible
github.com/xuri/excelize/v2 v2.7.1
github.com/zeebo/xxh3 v1.0.2
github.com/zexi/influxql-to-metricsql v0.1.1
go.etcd.io/etcd/api/v3 v3.5.0
go.etcd.io/etcd/client/v3 v3.5.0
@@ -80,6 +85,7 @@ require (
google.golang.org/grpc v1.62.0
google.golang.org/protobuf v1.32.0
gopkg.in/fatih/set.v0 v0.2.1
gopkg.in/ini.v1 v1.62.0
gopkg.in/mail.v2 v2.3.1
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.19.3
@@ -87,14 +93,14 @@ require (
k8s.io/client-go v0.19.3
k8s.io/cluster-bootstrap v0.19.3
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250924031624-e6936c793c60
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260207043119-2907d68518c5
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0
yunion.io/x/pkg v1.10.4-0.20260127060125-8939521ef75e
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372
yunion.io/x/sqlchemy v1.1.3-0.20251231025938-b0a38f6e9fab
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
)
@@ -105,8 +111,6 @@ require (
cloud.google.com/go/iam v1.1.6 // indirect
cloud.google.com/go/storage v1.39.1 // indirect
gitee.com/chunanyong/dm v1.8.14 // indirect
github.com/Azure/azure-sdk-for-go v36.1.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.9.6 // indirect
github.com/Azure/go-autorest/autorest/adal v0.8.2 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 // indirect
@@ -117,8 +121,7 @@ require (
github.com/ClickHouse/clickhouse-go v1.5.4 // indirect
github.com/DataDog/dd-trace-go v0.6.1 // indirect
github.com/DataDog/zstd v1.3.4 // indirect
github.com/Microsoft/azure-vhd-utils v0.0.0-20181115010904-44cbada2ece3 // indirect
github.com/RoaringBitmap/roaring v0.4.16 // indirect
github.com/RoaringBitmap/roaring v1.2.3 // indirect
github.com/Shopify/sarama v1.20.0 // indirect
github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
@@ -137,6 +140,7 @@ require (
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313 // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/boltdb/bolt v1.3.1 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
@@ -162,7 +166,6 @@ require (
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
github.com/frankban/quicktest v1.14.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-logfmt/logfmt v0.5.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
@@ -176,7 +179,6 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-plus/errors v1.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/go-querystring v1.0.0 // indirect
@@ -197,6 +199,7 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/ks3sdklib/aws-sdk-go v1.8.1 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
@@ -220,13 +223,12 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/mozillazg/go-pinyin v0.19.0 // indirect
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect
github.com/opentracing/opentracing-go v1.0.2 // indirect
github.com/openzipkin/zipkin-go-opentracing v0.3.4 // indirect
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
github.com/philhofer/fwd v1.0.0 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/pkg/term v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -247,7 +249,6 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.413 // indirect
github.com/tencentyun/cos-go-sdk-v5 v0.7.24 // indirect
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e // indirect
github.com/tinylib/msgp v1.1.0 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
@@ -279,7 +280,6 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.20.0 // indirect
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 // indirect
@@ -288,5 +288,3 @@ require (
)
replace github.com/influxdata/promql/v2 => github.com/zexi/promql/v2 v2.12.1
replace github.com/Azure/azure-sdk-for-go => github.com/Azure/azure-sdk-for-go v36.1.0+incompatible

53
go.sum
View File

@@ -48,10 +48,6 @@ gitee.com/chunanyong/dm v1.8.14 h1:1S9+aD0fY/HXkcm8dKh2HjYsDlcdXNG+4IOX9JtrSjA=
gitee.com/chunanyong/dm v1.8.14/go.mod h1:EPRJnuPFgbyOFgJ0TRYCTGzhq+ZT4wdyaj/GW/LLcNg=
github.com/360EntSecGroup-Skylar/excelize v1.4.0 h1:43rak9uafmwSJpXfFO1heKQph8tP3nlfWJWFQQtW1R0=
github.com/360EntSecGroup-Skylar/excelize v1.4.0/go.mod h1:R8KYLmGns0vDPe6/HyphW0mzW+MFexlGDafU0ykVEnU=
github.com/Azure/azure-sdk-for-go v36.1.0+incompatible h1:smHlbChr/JDmsyUqELZXLs0YIgpXecIGdUibuc2983s=
github.com/Azure/azure-sdk-for-go v36.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0=
@@ -72,8 +68,6 @@ github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxB
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
@@ -88,8 +82,8 @@ 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/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2 h1:XGB3B0651J1uKOE1KJa1gsrV/DO1kthhk2NTDUHATgs=
github.com/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2/go.mod h1:tiLv6VBLH4Z3KdBSe2qIKRwQDGCVQ9/F5fOKpQGvyoA=
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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@@ -97,8 +91,8 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
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=
github.com/RoaringBitmap/roaring v1.2.3 h1:yqreLINqIrX22ErkKI0vY47/ivtJr6n+kMhVOVmhWBY=
github.com/RoaringBitmap/roaring v1.2.3/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE=
github.com/Shopify/sarama v1.20.0 h1:wAMHhl1lGRlobeoV/xOKpbqD2OQsOvY4A/vIOGroIe8=
github.com/Shopify/sarama v1.20.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
@@ -173,6 +167,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
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/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
@@ -222,8 +218,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
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/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
@@ -277,9 +271,6 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4=
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493 h1:OTanQnFt0bi5iLFSdbEVA/idR6Q2WhCm+deb7ir2CcM=
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
@@ -496,9 +487,13 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kdomanski/iso9660 v0.4.0 h1:BPKKdcINz3m0MdjIMwS0wx1nofsOjxOq8TOr45WGHFg=
github.com/kdomanski/iso9660 v0.4.0/go.mod h1:OxUSupHsO9ceI8lBLPJKWBTphLemjrCQY8LPXM7qSzU=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
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=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -593,14 +588,17 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mogaika/udf v0.0.0-20171019171931-167f0ab01c73 h1:HpHNB68mF30LkUorpr7B22Xy0XwParP/n+AL0z4VlFc=
github.com/mogaika/udf v0.0.0-20171019171931-167f0ab01c73/go.mod h1:OVErfG87tRGCHZpQGO8pL4vDZuY0qr4blPOTR0go6e8=
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/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
github.com/mozillazg/go-pinyin v0.19.0 h1:p+J8/kjJ558KPvVGYLvqBhxf8jbZA2exSLCs2uUVN8c=
github.com/mozillazg/go-pinyin v0.19.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
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/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -623,7 +621,6 @@ github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35uk
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb h1:3PrKuO92dUTMrQ9dx0YNejC6U/Si6jqKmyQ9vWjwqR4=
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
@@ -701,8 +698,9 @@ github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
github.com/smartystreets/assertions v0.0.0-20180607162144-eb5b59917fa2/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -749,8 +747,6 @@ github.com/tencentyun/cos-go-sdk-v5 v0.7.24/go.mod h1:wQBO5HdAkLjj2q6XQiIfDSP8DX
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/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
@@ -797,6 +793,10 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
github.com/zexi/influxql-to-metricsql v0.1.1 h1:dXnVzlxVLuo88zGkDca7erEnmvprGWjzsBcs8qIoQGQ=
github.com/zexi/influxql-to-metricsql v0.1.1/go.mod h1:JlC5FY+6De9ZPxG47G5DOgva8P9X1VaKS4ExzCmhSCc=
github.com/zexi/promql/v2 v2.12.1 h1:crHKpULdLLsBZ9b78Rg6qQkugzlk6BHeCj93tw/F5RU=
@@ -1225,7 +1225,6 @@ gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.19.1/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1273,8 +1272,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250924031624-e6936c793c60 h1:TK1qL43Foc8T3L4cxE7psEYas66Pn4GfaaEZJE/zCmQ=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250924031624-e6936c793c60/go.mod h1:S9o/TRZsnYWGaGe7o3PpeOv6CgMY8ZJwITYsEnGfOgQ=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260207043119-2907d68518c5 h1:CqO2GuJk/pT4yjI3OTeLm+/mY1H+aUK+B6hxhzIdUQ4=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260207043119-2907d68518c5/go.mod h1:GdAwZ78fiqj13i2r1zNuE/D6YOlhh2q4jZjuyHiZTq8=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
@@ -1288,11 +1287,11 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0 h1:/vHcYqzQInxqR1jjS+e7A0owRXj+/rvrIgES6uadUqs=
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/pkg v1.10.4-0.20260127060125-8939521ef75e h1:py5Kd6cgP6pxB9pSc4ry/gnmA6rJZwMVOnAjra4sb2g=
yunion.io/x/pkg v1.10.4-0.20260127060125-8939521ef75e/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372 h1:8lR9HzYTxSgxcVv6uC2Ogkk1Y3FEEanABfgeleCzhfA=
yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/sqlchemy v1.1.3-0.20251231025938-b0a38f6e9fab h1:5m/bSzW3uTAk83rp9eethbYsxJFYInFVeU1RDkteW4E=
yunion.io/x/sqlchemy v1.1.3-0.20251231025938-b0a38f6e9fab/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ=
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=

View File

@@ -74,7 +74,7 @@ func (app *Application) InitHandlers() *Application {
if options.Options.EnableBackendServiceProxy {
// bind backend service API proxy
log.Infof("enable backend service proxy")
app.BackendServiceProxyHandler = handler.NewBackendServiceProxyHandler("/api/s/<service>")
app.BackendServiceProxyHandler = handler.NewBackendServiceProxyHandler("/api/s/<service>", options.Options.BackendProxyReadWorkerCount, options.Options.BackendProxyWriteWorkerCount)
}
app.CloudIdSAMLHandler = handler.NewProxyHandlerWithService(cloudid.SAML_IDP_PREFIX, cloudid.SERVICE_TYPE)

View File

@@ -17,7 +17,7 @@ package clientman
import (
"crypto/rand"
"crypto/rsa"
"io/ioutil"
"os"
"github.com/pkg/errors"
@@ -27,9 +27,9 @@ import (
func InitClient() error {
if options.Options.EnableSsl {
privData, err := ioutil.ReadFile(options.Options.SslKeyfile)
privData, err := os.ReadFile(options.Options.SslKeyfile)
if err != nil {
return errors.Wrapf(err, "ioutil.ReadFile %s", options.Options.SslKeyfile)
return errors.Wrapf(err, "os.ReadFile %s", options.Options.SslKeyfile)
}
privateKey, err := seclib2.DecodePrivateKey(privData)
if err != nil {

View File

@@ -0,0 +1,102 @@
// 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 handler
import (
"context"
"net/http"
"strings"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/apigateway/clientman"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/netutils2"
)
const (
ASSUME_TOKEN_HEADER = "X-Assume-Token"
)
type SAssumeToken struct {
Token string `json:"token"`
UserId string `json:"user_id"`
ProjectId string `json:"project_id"`
}
func getAssumeToken(r *http.Request) (*SAssumeToken, error) {
auth := r.Header.Get(ASSUME_TOKEN_HEADER)
if auth == "" {
return nil, errors.Wrap(httperrors.ErrInputParameter, "Assume token header is empty")
}
parts := strings.Split(strings.TrimSpace(auth), ":")
if len(parts) != 3 {
return nil, errors.Wrap(httperrors.ErrInputParameter, "Assume token header is invalid")
}
return &SAssumeToken{
Token: parts[0],
UserId: parts[1],
ProjectId: parts[2],
}, nil
}
func doAssumeLogin(assumeToken *SAssumeToken, w http.ResponseWriter, req *http.Request) (mcclient.TokenCredential, error) {
cliIp := netutils2.GetHttpRequestIp(req)
token, err := auth.Client().AuthenticateAssume(assumeToken.Token, assumeToken.UserId, assumeToken.ProjectId, cliIp)
if err != nil {
return nil, errors.Wrapf(httperrors.ErrInvalidCredential, "AuthenticateAssume fail %s", err)
}
authToken := clientman.NewAuthToken(token.GetTokenString(), false, false, false)
saveLoginCookies(w, authToken, token, nil)
return token, nil
}
func (h *AuthHandlers) handleAssumeLogin(ctx context.Context, w http.ResponseWriter, req *http.Request) {
// no auth cookie, try to get get assume user token from header
assumeToken, err := getAssumeToken(req)
if err != nil {
appsrv.Send(w, err.Error())
return
}
token, err := doAssumeLogin(assumeToken, w, req)
if err != nil {
appsrv.Send(w, err.Error())
return
}
_, query, _ := appsrv.FetchEnv(ctx, w, req)
redirect := ""
if query != nil {
queryMap, err := query.GetMap()
if err != nil {
appsrv.Send(w, err.Error())
return
}
for k, v := range queryMap {
if k == "p" {
redirect, _ = v.GetString()
} else {
value, _ := v.GetString()
saveCookie(w, k, value, "", token.GetExpires(), false)
}
}
}
if !strings.HasPrefix(redirect, "/") {
redirect = "/" + redirect
}
appsrv.SendRedirect(w, redirect)
}

View File

@@ -85,6 +85,7 @@ func (h *AuthHandlers) AddMethods() {
NewHP(handleOIDCJWKeys, "oidc", "keys"),
NewHP(handleOIDCUserInfo, "oidc", "user"),
NewHP(handleOIDCRPInitLogout, "oidc", "logout"),
NewHP(h.handleAssumeLogin, "assume"),
)
h.AddByMethod(POST, nil,
NewHP(h.initTotpSecrets, "initcredential"),
@@ -661,31 +662,34 @@ func (h *AuthHandlers) doLogin(ctx context.Context, w http.ResponseWriter, req *
return httperrors.NewForbiddenError("user forbidden login from web")
}
saveLoginCookies(w, authToken, token, body)
return nil
}
func saveLoginCookies(w http.ResponseWriter, authToken *clientman.SAuthToken, token mcclient.TokenCredential, body jsonutils.JSONObject) {
saveAuthCookie(w, authToken, token)
if len(token.GetProjectId()) > 0 {
if body.Contains("isadmin") {
if body != nil && body.Contains("isadmin") {
adminVal := "false"
if policy.PolicyManager.IsScopeCapable(token, rbacscope.ScopeSystem) {
adminVal, _ = body.GetString("isadmin")
}
saveCookie(w, "isadmin", adminVal, "", token.GetExpires(), false)
}
if body.Contains("scope") {
if body != nil && body.Contains("scope") {
scopeStr, _ := body.GetString("scope")
if !policy.PolicyManager.IsScopeCapable(token, rbacscope.TRbacScope(scopeStr)) {
scopeStr = string(rbacscope.ScopeProject)
}
saveCookie(w, "scope", scopeStr, "", token.GetExpires(), false)
}
if body.Contains("domain") {
if body != nil && body.Contains("domain") {
domainStr, _ := body.GetString("domain")
saveCookie(w, "domain", domainStr, "", token.GetExpires(), false)
}
saveCookie(w, "tenant", token.GetProjectId(), "", token.GetExpires(), false)
}
return nil
}
func doLogout(ctx context.Context, w http.ResponseWriter, req *http.Request) {

View File

@@ -33,11 +33,18 @@ import (
type SBackendServiceProxyHandler struct {
prefix string
readWorker *appsrv.SWorkerManager
writeWorker *appsrv.SWorkerManager
}
func NewBackendServiceProxyHandler(prefix string) *SBackendServiceProxyHandler {
func NewBackendServiceProxyHandler(prefix string, readWorkerCount, writeWorkerCount int) *SBackendServiceProxyHandler {
log.Infof("NewBackendServiceProxyHandler: %s, readWorkerCount: %d, writeWorkerCount: %d", prefix, readWorkerCount, writeWorkerCount)
return &SBackendServiceProxyHandler{
prefix: prefix,
readWorker: appsrv.NewWorkerManager("apigateway-backend-api-read", readWorkerCount, appsrv.DEFAULT_BACKLOG, false),
writeWorker: appsrv.NewWorkerManager("apigateway-backend-api-write", writeWorkerCount, appsrv.DEFAULT_BACKLOG, false),
}
}
@@ -96,9 +103,9 @@ func (h *SBackendServiceProxyHandler) Bind(app *appsrv.Application) {
}
var worker *appsrv.SWorkerManager
if method == "GET" || method == "HEAD" {
worker = appsrv.NewWorkerManager("apigateway-backend-api-read", 8, appsrv.DEFAULT_BACKLOG, false)
worker = h.readWorker
} else {
worker = appsrv.NewWorkerManager("apigateway-backend-api-write", 4, appsrv.DEFAULT_BACKLOG, false)
worker = h.writeWorker
}
hi.SetWorkerManager(worker)
return hi

View File

@@ -21,6 +21,7 @@ import (
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/appctx"
"yunion.io/x/pkg/errors"
@@ -95,10 +96,12 @@ func fetchAuthInfo(ctx context.Context, r *http.Request) (mcclient.TokenCredenti
var err error
authToken, err = clientman.Decode(auth)
if err != nil {
log.Errorf("clientman.Decode auth token fail: %v", err)
return nil, nil, errors.Wrap(httperrors.ErrInputParameter, "clientman.Decode auth token fail")
}
token, err = authToken.GetToken(ctx)
if err != nil {
log.Errorf("authToken.GetToken fail: %v", err)
return nil, nil, errors.Wrap(httperrors.ErrInputParameter, "authToken.GetToken fail")
}
}

View File

@@ -44,7 +44,9 @@ type GatewayOptions struct {
DisableReporting bool `default:"false" help:"Reporting data every 24 hours, report data incloud version, os, platform and usages"`
// 启用后端服务反向代理网关
EnableBackendServiceProxy bool `default:"false" help:"Proxy API request to backend services"`
EnableBackendServiceProxy bool `default:"true" help:"Proxy API request to backend services"`
BackendProxyReadWorkerCount int `default:"8" help:"Request worker thread count, default is 8"`
BackendProxyWriteWorkerCount int `default:"4" help:"Request worker thread count, default is 4"`
common_options.CommonOptions `"request_worker_count->default":"32"`

View File

@@ -17,7 +17,8 @@ package cloudevent
import "yunion.io/x/onecloud/pkg/apis"
const (
SERVICE_TYPE = apis.SERVICE_TYPE_CLOUDEVENT
SERVICE_TYPE = apis.SERVICE_TYPE_CLOUDEVENT
SERVICE_VERSION = ""
CLOUD_EVENT_SERVICE_COMPUTE = "compute"
CLOUD_EVENT_SERVICE_UNKNOWN = "unknown"

View File

@@ -312,6 +312,7 @@ type BaremetalDiskConfig struct {
RA *bool `json:"ra,omitempty"`
WT *bool `json:"wt,omitempty"`
Direct *bool `json:"direct,omitempty"`
SoftRaidIdx *int `json:"soft_raid_idx"`
}
type RootDiskMatcherSizeMBRange struct {
@@ -327,6 +328,7 @@ type BaremetalRootDiskMatcher struct {
Device string `json:"device"`
SizeMB int64 `json:"size_mb"`
SizeMBRange *RootDiskMatcherSizeMBRange `json:"size_mb_range"`
PCIPath string `json:"pci_path"`
}
type ServerConfigs struct {

View File

@@ -64,6 +64,11 @@ var (
DISK_DRIVER_ADAPTECRAID,
)
DISK_DRIVERS_SOFT_RAID = sets.NewString(
DISK_DRIVER_LINUX,
DISK_DRIVER_PCIE,
)
DISK_DRIVERS = sets.NewString(
DISK_DRIVER_LINUX,
DISK_DRIVER_PCIE).Union(DISK_DRIVERS_RAID)

View File

@@ -1,21 +1,25 @@
package version
// Copyright (c) Microsoft and contributors. All rights reserved.
// 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
//
// 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.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
// Number contains the semantic version of this SDK.
const Number = "v36.1.0"
package compute
import (
"yunion.io/x/onecloud/pkg/apis"
)
type BillingResourceCheckListInput struct {
apis.VirtualResourceListInput
ResourceType []string `json:"resource_type"`
}

View File

@@ -87,6 +87,6 @@ type CachedimageListInput struct {
// valid cachedimage
Valid bool `json:"valid"`
// enum: [public, private]
// enum: ["public", "private"]
CloudEnv string `json:"cloud_env"`
}

View File

@@ -368,6 +368,9 @@ func (self CloudaccountDetail) GetMetricTags() map[string]string {
"domain_id": self.DomainId,
"project_domain": self.ProjectDomain,
"currency": self.Currency,
"tenant_id": self.ProjectId,
"tenant": self.Project,
"status": self.Status,
}
return AppendMetricTags(ret, self.MetadataResourceInfo, self.ProjectizedResourceInfo)
}

View File

@@ -117,7 +117,10 @@ type DiskListInput struct {
StorageFilterListInput
SnapshotPolicyFilterListInput
ServerFilterListInput
// 虚拟机ID或Name列表
ServerId []string `json:"server_id"`
// swagger:ignore
Server []string `json:"server" yunion-deprecated-by:"server_id"`
// filter disk by whether it is being used
Unused *bool `json:"unused"`
@@ -166,6 +169,8 @@ type DiskListInput struct {
// 根据是否绑定快照策略过滤
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
// 根据是否磁盘所在虚拟机是否绑定主机快照策略
BindingServerSnapshotpolicy *bool `json:"binding_server_snapshotpolicy"`
}
type DiskResourceInput struct {
@@ -210,13 +215,22 @@ type SimpleGuest struct {
Bps int `json:"bps"`
// 计费类型
BillingType string `json:"billing_type"`
// 磁盘绑定的快照策略列表
Snapshotpolicy []SimpleSnapshotPolicy `json:"snapshotpolicy"`
}
type SimpleSnapshotPolicy struct {
Id string `json:"id"`
Name string `json:"name"`
RepeatWeekdays []int `json:"repeat_weekdays"`
TimePoints []int `json:"time_points"`
// 快照策略ID
Id string `json:"id"`
// 快照策略名称
Name string `json:"name"`
// 快照策略类型
ResourceType string `json:"resource_type"`
// 快照策略重复周期
RepeatWeekdays []int `json:"repeat_weekdays"`
// 快照策略时间点
TimePoints []int `json:"time_points"`
}
type DiskDetails struct {
@@ -236,11 +250,11 @@ type DiskDetails struct {
GuestStatus string `json:"guest_status"`
// 所挂载虚拟机计费类型
GuestBillingType string `json:"guest_billing_type"`
// 磁盘所在虚拟机绑定的主机快照策略数量
GuestSnapshotpolicyCount int `json:"guest_snapshotpolicy_count"`
// 自动清理时间
AutoDeleteAt time.Time `json:"auto_delete_at"`
// 自动快照策略状态
SnapshotpolicyStatus string `json:"snapshotpolicy_status,allowempty"`
// 自动快照策略
Snapshotpolicies []SimpleSnapshotPolicy `json:"snapshotpolicies"`
@@ -342,7 +356,13 @@ type DiskMigrateInput struct {
TargetStorageId string `json:"target_storage_id"`
}
type DiskChagneStorageTypeInput struct {
// 目标存储类型
StorageType string `json:"storage_type"`
}
type DiskSnapshotpolicyInput struct {
// 快照策略ID
SnapshotpolicyId string `json:"snapshotpolicy_id"`
}

View File

@@ -94,6 +94,7 @@ type GuestdiskJsonDesc struct {
IsSSD bool `json:"is_ssd"`
NumQueues uint8 `json:"num_queues"`
AutoReset bool `json:"auto_reset"`
PCIPath string `json:"pci_path"`
// esxi
ImageInfo struct {

View File

@@ -27,3 +27,26 @@ type SImagesInGuest struct {
RootImage SSubImage
DataImages []SSubImage
}
type SGuestScreenDumpInfo struct {
S3AccessKey string
S3SecretKey string
S3Endpoint string
S3BucketName string
S3ObjectName string
S3UseSSL bool
}
type GuestScreenDumpListInput struct {
Server string
}
type GetDetailsGuestScreenDumpInput struct {
ObjectName string
}
type GetDetailsGuestScreenDumpOutput struct {
GuestId string
Name string
ScreenDump string
}

View File

@@ -53,6 +53,8 @@ type GuestnetworkShortDesc struct {
NetworkId string `json:"network_id"`
// 附属IP
SubIps string `json:"sub_ips"`
// 网卡序号
Index int `json:"index"`
}
type GuestnetworkListInput struct {

View File

@@ -134,6 +134,14 @@ type ServerListInput struct {
// 根据是否绑定快照策略过滤
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
// 根据虚机关联的磁盘是否绑定快照策略过滤
BindingDisksSnapshotpolicy *bool `json:"binding_disks_snapshotpolicy"`
}
// 主机快照策略绑定/设置接口入参
type ServerSnapshotpolicyInput struct {
// 快照策略ID
SnapshotpolicyId string `json:"snapshotpolicy_id"`
}
func (input *ServerListInput) AfterUnmarshal() {
@@ -183,6 +191,11 @@ type ServerDetails struct {
// 磁盘概要
Disks string `json:"disks"`
// 主机快照策略数量
SnapshotpolicyCount int `json:"snapshotpolicy_count"`
// 磁盘快照策略数量
DisksSnapshotpolicyCount int `json:"disks_snapshotpolicy_count"`
// 磁盘详情
DisksInfo []GuestDiskInfo `json:"disks_info"`
// 虚拟机Ip列表
@@ -712,6 +725,13 @@ func (input ServerDetachnetworkInput) IsForce() bool {
return input.Force != nil && *input.Force
}
type ServerSetNetworkNumQueuesInput struct {
// 虚机网卡 mac addr
MacAddr string `json:"mac_addr"`
// 网卡队列数
NumQueues int `json:"num_queues"`
}
type ServerMigrateForecastInput struct {
PreferHostId string `json:"prefer_host_id"`
// Deprecated

View File

@@ -419,6 +419,8 @@ type HostSizeAttributes struct {
CpuMicrocode string `json:"cpu_microcode"`
// CPU架构
CpuArchitecture string `json:"cpu_architecture"`
// KVM 允许单台虚机最大 vcpu 个数
KvmCapMaxVcpu *int `json:"kvm_cap_max_vcpu"`
// 内存大小(单位MB)
MemSize string `json:"mem_size"`
@@ -579,6 +581,17 @@ type SHostPingInput struct {
QgaRunningGuestIds []string `json:"qga_running_guests"`
}
type SKmsgEntry struct {
Level int `json:"level"`
Seq int `json:"sql"`
Message string `json:"message"`
Time time.Time `json:"time"`
}
type SHostReportDmesgInput struct {
Entries []SKmsgEntry `json:"entries"`
}
type HostReserveCpusInput struct {
Cpus string
Mems string

View File

@@ -69,6 +69,9 @@ type SchedtagListInput struct {
Type string `json:"type" yunion-deprecated-by:"resource_type"`
DefaultStrategy []string `json:"default_strategy"`
// filter by zone_id
ZoneId []string `json:"zone_id"`
}
type SchedtagDetails struct {

View File

@@ -46,6 +46,8 @@ type SnapshotPolicyDetails struct {
BindingDiskCount int `json:"binding_disk_count"`
BindingResourceCount int `json:"binding_resource_count"`
// 快照数量
SnapshotCount int `json:"snapshot_count"`
}
type SSnapshotPolicyCreateInput struct {

View File

@@ -133,6 +133,21 @@ const (
STORAGE_ECLOUD_SSD = compute.STORAGE_ECLOUD_SSD // 高性能盘
STORAGE_ECLOUD_SSDEBS = compute.STORAGE_ECLOUD_SSDEBS // 性能优化盘
STORAGE_ECLOUD_SYSTEM = compute.STORAGE_ECLOUD_SYSTEM // 系统盘
STORAGE_BAIDU_SSD = compute.STORAGE_BAIDU_SSD
STORAGE_BAIDU_PREMIUM_SSD = compute.STORAGE_BAIDU_PREMIUM_SSD
STORAGE_BAIDU_HDD = compute.STORAGE_BAIDU_HDD
STORAGE_BAIDU_ENHANCED_SSD_PL1 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL1
STORAGE_BAIDU_ENHANCED_SSD_PL2 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL2
STORAGE_BAIDU_ENHANCED_SSD_PL3 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL3
// ksyun storage type
STORAGE_KSYUN_ESSD_AUTO_PL = compute.STORAGE_KSYUN_ESSD_AUTO_PL
STORAGE_KSYUN_SSD3_0 = compute.STORAGE_KSYUN_SSD3_0
STORAGE_KSYUN_EHDD = compute.STORAGE_KSYUN_EHDD
STORAGE_KSYUN_ESSD_PL1 = compute.STORAGE_KSYUN_ESSD_PL1
STORAGE_KSYUN_ESSD_PL2 = compute.STORAGE_KSYUN_ESSD_PL2
STORAGE_KSYUN_ESSD_PL3 = compute.STORAGE_KSYUN_ESSD_PL3
)
const (
@@ -169,7 +184,7 @@ var (
}
STORAGE_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_SHEEPDOG,
STORAGE_RBD, STORAGE_DOCKER, STORAGE_NAS, STORAGE_VSAN, STORAGE_NFS,
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD, STORAGE_CLOUD_ESSD_PL2, STORAGE_CLOUD_ESSD_PL3,
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD_PL0, STORAGE_CLOUD_ESSD, STORAGE_CLOUD_ESSD_PL2, STORAGE_CLOUD_ESSD_PL3,
STORAGE_EPHEMERAL_SSD, STORAGE_CLOUD_EFFICIENCY,
STORAGE_STANDARD_LRS, STORAGE_STANDARDSSD_LRS, STORAGE_PREMIUM_LRS,
STORAGE_GP2_SSD, STORAGE_GP3_SSD, STORAGE_IO1_SSD, STORAGE_ST1_HDD, STORAGE_SC1_HDD, STORAGE_STANDARD_HDD,

View File

@@ -586,6 +586,7 @@ type SDisk struct {
DiskSize int `json:"disk_size"`
// 磁盘路径
AccessPath string `json:"access_path"`
PCIPath string `json:"pci_path"`
// 备份磁盘实例的存储ID
BackupStorageId string `json:"backup_storage_id"`
// 镜像Id

View File

@@ -121,6 +121,8 @@ const (
)
const (
OS_ARCH_ALL = "all"
OS_ARCH_X86 = "x86"
OS_ARCH_ARM = "arm"

View File

@@ -38,6 +38,7 @@ const (
AUTH_METHOD_OIDC = "oidc"
AUTH_METHOD_OAuth2 = "oauth2"
AUTH_METHOD_VERIFY = "verify"
AUTH_METHOD_ASSUME = "assume"
// AUTH_METHOD_ID_PASSWORD = 1
// AUTH_METHOD_ID_TOKEN = 2

View File

@@ -197,11 +197,11 @@ type UserListInput struct {
RoleAssignmentProjectId string `json:"role_assignment_project_id"`
// email
Email string `json:"email"`
Email []string `json:"email"`
// mobile
Mobile string `json:"mobile"`
Mobile []string `json:"mobile"`
// displayname
Displayname string `json:"displayname"`
Displayname []string `json:"displayname"`
// 是否允许web控制台登录
AllowWebConsole *bool `json:"allow_web_console"`

View File

@@ -59,8 +59,10 @@ const (
IMAGE_OS_DISTRO = "os_distribution"
IMAGE_OS_TYPE = "os_type"
IMAGE_OS_VERSION = "os_version"
IMAGE_OS_LANGUAGE = "os_language"
IMAGE_DISK_FORMAT = "disk_format"
IMAGE_UEFI_SUPPORT = "uefi_support"
IMAGE_BIOS_SUPPORT = "bios_support"
IMAGE_IS_LVM_PARTITION = "is_lvm_partition"
IMAGE_IS_READONLY = "is_readonly"
IMAGE_PARTITION_TYPE = "partition_type"

View File

@@ -383,6 +383,14 @@ type OpsLogListInput struct {
Until time.Time `json:"until"`
}
type HostDmesgLogListInput struct {
OpsLogListInput
LogLevels []string `json:"log_levels"`
ShowDmesgLog bool `json:"show_dmesg_log"`
}
type IdNameDetails struct {
Id string `json:"id"`
Name string `json:"name"`

View File

@@ -56,6 +56,8 @@ type MetadataBaseFilterInput struct {
// 按key模糊匹配
KeyLike string `json:"key_like"`
// 按value模糊匹配
ValueLike string `json:"value_like"`
// 按Key过滤
Key []string `json:"key"`

View File

@@ -238,3 +238,13 @@ func init() {
return &AlertSetting{}
})
}
type EvaluatorType string
const (
EvaluatorTypeGT EvaluatorType = "gt"
EvaluatorTypeLT EvaluatorType = "lt"
EvaluatorTypeEQ EvaluatorType = "eq"
EvaluatorTypeWithinRange EvaluatorType = "within_range"
EvaluatorTypeOutsideRange EvaluatorType = "outside_range"
)

View File

@@ -33,13 +33,14 @@ type AlertRecordListInput struct {
apis.EnabledResourceBaseListInput
apis.StatusStandaloneResourceListInput
AlertId string `json:"alert_id"`
Level string `json:"level"`
State string `json:"state"`
ResType string `json:"res_type"`
Alerting bool `json:"alerting"`
ResName string `json:"res_name"`
ResId string `json:"res_id"`
AlertId string `json:"alert_id"`
AlertName string `json:"alert_name"`
Level string `json:"level"`
State string `json:"state"`
ResType string `json:"res_type"`
Alerting bool `json:"alerting"`
ResName string `json:"res_name"`
ResId string `json:"res_id"`
}
type AlertRecordDetails struct {
@@ -77,10 +78,12 @@ type AlertRecordRule struct {
// 比较运算符, 比如: >, <, >=, <=
Comparator string `json:"comparator"`
// 报警阀值
Threshold string `json:"threshold"`
Period string `json:"period"`
AlertDuration int64 `json:"alert_duration"`
ConditionType string `json:"condition_type"`
Threshold string `json:"threshold"`
ThresholdRange []float64 `json:"threshold_range"`
Unit string `json:"unit"`
Period string `json:"period"`
AlertDuration int64 `json:"alert_duration"`
ConditionType string `json:"condition_type"`
// 静默期
SilentPeriod string `json:"silent_period"`
Reducer string `json:"reducer"`

View File

@@ -34,9 +34,6 @@ const (
CommonAlertDefaultRecipient = "commonalert-default"
//metirc fields 之间的运算
CommonAlertFieldOpt_Division = "/"
DEFAULT_SEND_NOTIFY_CHANNEL = "users"
METRIC_QUERY_TYPE_NO_DATA = "nodata_query"
@@ -47,6 +44,13 @@ const (
CommonAlertLevelFatal = "fatal"
)
type CommonAlertFieldOpt string
const (
//metirc fields 之间的运算
CommonAlertFieldOptDivision CommonAlertFieldOpt = "/"
)
var CommonAlertLevels = []string{CommonAlertLevelNormal, CommonAlertLevelImportant, CommonAlertLevelFatal}
type CommonAlertCreateBaseInput struct {
@@ -96,13 +100,15 @@ type CommonAlertQuery struct {
*AlertQuery
// metric points'value的运算方式
Reduce string `json:"reduce"`
// 比较运算符, 比如: >, <, >=, <=
// 比较运算符, 比如: >, <, >=, <=, within_range, outside_range
Comparator string `json:"comparator"`
// 报警阀值
// 报警阀值 (用于 gt, lt, eq)
Threshold float64 `json:"threshold"`
//field yunsuan
FieldOpt string `json:"field_opt"`
ConditionType string `json:"condition_type"`
// 范围参数 (用于 within_range, outside_range)
ThresholdRange []float64 `json:"threshold_range"`
// field 运算
FieldOpt CommonAlertFieldOpt `json:"field_opt"`
ConditionType string `json:"condition_type"`
// Operator should be chosen from 'and | or'
Operator string `json:"operator"`
}
@@ -161,12 +167,12 @@ type CommonAlertDetails struct {
}
type CommonAlertMetricDetails struct {
Operator string `json:"operator"`
Comparator string `json:"comparator"`
Threshold float64 `json:"threshold"`
WithinRange []float64 `json:"within_range"`
ConditionType string `json:"condition_type"`
ThresholdStr string `json:"threshold_str"`
Operator string `json:"operator"`
Comparator string `json:"comparator"`
Threshold float64 `json:"threshold"`
ThresholdRange []float64 `json:"threshold_range"`
ConditionType string `json:"condition_type"`
ThresholdStr string `json:"threshold_str"`
// metric points'value的运算方式
Reduce string `json:"reduce"`
DB string `json:"db"`

View File

@@ -168,15 +168,15 @@ const (
)
func GetNodeAlertEvaluator(comparator string, threshold float64) Condition {
typ := ConditionGreaterThan
typ := EvaluatorType(ConditionGreaterThan)
switch comparator {
case ">=", ">":
typ = ConditionGreaterThan
typ = EvaluatorType(ConditionGreaterThan)
case "<=", "<":
typ = ConditionLessThan
typ = EvaluatorType(ConditionLessThan)
}
return Condition{
Type: typ,
Type: string(typ),
Params: []float64{threshold},
}
}

View File

@@ -162,6 +162,7 @@ type SendParams struct {
Header jsonutils.JSONObject
Body jsonutils.JSONObject
MsgKey string
SecretKey string `json:"secret_key"`
DomainId string
RemoteTemplateParam SRemoteTemplateParam
GroupKey string

View File

@@ -22,51 +22,87 @@ import (
var (
Event SNotifyEvent
ActionCreate SAction = "create"
ActionDelete SAction = "delete"
ActionPendingDelete SAction = "pending_delete"
ActionUpdate SAction = "update"
ActionRebuildRoot SAction = "rebuild_root"
ActionResetPassword SAction = "reset_password"
ActionChangeConfig SAction = "change_config"
ActionResize SAction = "resize"
// 创建
ActionCreate SAction = "create"
// 删除
ActionDelete SAction = "delete"
// 放入回收站
ActionPendingDelete SAction = "pending_delete"
// 更新
ActionUpdate SAction = "update"
// 重装系统
ActionRebuildRoot SAction = "rebuild_root"
// 重置密码
ActionResetPassword SAction = "reset_password"
// 配置变更
ActionChangeConfig SAction = "change_config"
// 扩容
ActionResize SAction = "resize"
// 到期释放
ActionExpiredRelease SAction = "expired_release"
ActionExecute SAction = "execute"
ActionChangeIpaddr SAction = "change_ipaddr"
ActionSyncStatus SAction = "sync_status"
ActionCleanData SAction = "clean_data"
ActionMigrate SAction = "migrate"
// 执行,例如自动快照策略执行创建快照、弹性伸缩策略执行扩容、定时任务执行等
ActionExecute SAction = "execute"
// IP变更
ActionChangeIpaddr SAction = "change_ipaddr"
// 同步状态
ActionSyncStatus SAction = "sync_status"
// 清理数据
ActionCleanData SAction = "clean_data"
// 迁移
ActionMigrate SAction = "migrate"
// 添加备份服务器
ActionCreateBackupServer SAction = "add_backup_server"
ActionDelBackupServer SAction = "delete_backup_server"
// 删除备份服务器
ActionDelBackupServer SAction = "delete_backup_server"
ActionSyncCreate SAction = "sync_create"
ActionSyncUpdate SAction = "sync_update"
ActionSyncDelete SAction = "sync_delete"
// 同步新建
ActionSyncCreate SAction = "sync_create"
// 同步更新
ActionSyncUpdate SAction = "sync_update"
// 同步删除
ActionSyncDelete SAction = "sync_delete"
// 同步账号状态
ActionSyncAccountStatus SAction = "sync_account_status"
ActionOffline SAction = "offline"
ActionSystemPanic SAction = "panic"
// 下线
ActionOffline SAction = "offline"
// 系统崩溃
ActionSystemPanic SAction = "panic"
// 系统异常
ActionSystemException SAction = "exception"
ActionChecksumTest SAction = "checksum_test"
// 锁定,例如用户锁定
ActionLock SAction = "lock"
ActionExceedCount SAction = "exceed_count"
ActionPasswordExpireSoon SAction = "password_expire_soon"
ActionWorkerBlock SAction = "woker_block"
ActionNetOutOfSync SAction = "net_out_of_sync"
ActionMysqlOutOfSync SAction = "mysql_out_of_sync"
ActionServiceAbnormal SAction = "service_abnormal"
ActionServerPanicked SAction = "server_panicked"
ActionAttach SAction = "attach"
ActionDetach SAction = "detach"
// 超出数量
ActionExceedCount SAction = "exceed_count"
// 密码即将过期
ActionPasswordExpireSoon SAction = "password_expire_soon"
// 一致性检查
ActionChecksumTest SAction = "checksum_test"
// 任务队列阻塞
ActionWorkerBlock SAction = "woker_block"
// 网络同步失败
ActionNetOutOfSync SAction = "net_out_of_sync"
// MySQL同步失败
ActionMysqlOutOfSync SAction = "mysql_out_of_sync"
// 服务异常
ActionServiceAbnormal SAction = "service_abnormal"
// 服务器崩溃
ActionServerPanicked SAction = "server_panicked"
// 挂载
ActionAttach SAction = "attach"
// 卸载
ActionDetach SAction = "detach"
// 透传设备创建
ActionIsolatedDeviceCreate SAction = "isolated_device_create"
// 透传设备更新
ActionIsolatedDeviceUpdate SAction = "isolated_device_update"
// 透传设备删除
ActionIsolatedDeviceDelete SAction = "isolated_device_delete"
ActionStatusChanged SAction = "status_changed"
ActionRunTask SAction = "run_task"
// 状态变更
ActionStatusChanged SAction = "status_changed"
// 运行任务
ActionRunTask SAction = "run_task"
ResultFailed SResult = "failed"
ResultSucceed SResult = "succeed"

View File

@@ -19,6 +19,8 @@ import (
"regexp"
"strings"
"yunion.io/x/pkg/tristate"
"yunion.io/x/onecloud/pkg/apis"
)
@@ -65,6 +67,9 @@ var (
func ParseInternationalMobile(mobile string) SInternationalMobile {
matchs := pareser.FindStringSubmatch(mobile)
if len(matchs) == 0 {
if len(mobile) == 0 {
return SInternationalMobile{}
}
return SInternationalMobile{
AreaCode: defaultAreaCode,
Mobile: mobile,
@@ -85,7 +90,7 @@ func (im *SInternationalMobile) AcceptExtMobile() {
// 对传入的手机号去除地区编号
func moveAreaCode(mobile string) string {
// 所有地区编号
allArea := `283|282|281|280|269|268|267|266|265|264|263|262|261|260|259|258|257|256|255|254|253|252|251|250|249|248|247|246|245|244|243|242|241|240|239|238|237|236|235|234|233|232|231|230|229|228|227|226|225|224|223|222|221|220|219|218|217|216|215|214|213|212|211|210|98|95|94|93|92|91|90|86|84|82|81|66|65|64|63|62|61|60|58|57|56|55|54|53|52|51|49|48|47|46|45|44|43|41|40|39|36|34|33|32|31|30|27|20|7|1`
allArea := `852|283|282|281|280|269|268|267|266|265|264|263|262|261|260|259|258|257|256|255|254|253|252|251|250|249|248|247|246|245|244|243|242|241|240|239|238|237|236|235|234|233|232|231|230|229|228|227|226|225|224|223|222|221|220|219|218|217|216|215|214|213|212|211|210|98|95|94|93|92|91|90|86|84|82|81|66|65|64|63|62|61|60|58|57|56|55|54|53|52|51|49|48|47|46|45|44|43|41|40|39|36|34|33|32|31|30|27|20|7|1`
temp := strings.Split(allArea, "|")
for _, area := range temp {
if strings.HasPrefix(mobile, "+"+area) {
@@ -111,6 +116,9 @@ func moveExtStr(mobile string) string {
}
func (im SInternationalMobile) String() string {
if len(im.Mobile) == 0 {
return ""
}
if im.AreaCode == "" {
return im.Mobile
}
@@ -159,6 +167,17 @@ type ReceiverUpdateInput struct {
// example: example@gmail.com
Email string `json:"email"`
// swagger:ignore
EnabledEmail tristate.TriState `json:"enabled_email"`
// swagger:ignore
VerifiedEmail tristate.TriState `json:"verified_email"`
// swagger:ignore
EnabledMobile tristate.TriState `json:"enabled_mobile"`
// swagger:ignore
VerifiedMobile tristate.TriState `json:"verified_mobile"`
// swagger:ignore
Mobile string `json:"mobile"`
InternationalMobile SInternationalMobile `json:"international_mobile"`
// description: enabled contacts for user

View File

@@ -23,15 +23,15 @@ func TestMobileExt(t *testing.T) {
}{
{
SInternationalMobile{
"+8612345678901",
"+86",
Mobile: "+8612345678901",
AreaCode: "+86",
},
"12345678901",
},
{
SInternationalMobile{
"+8612345678901;ext=2",
"+86",
Mobile: "+8612345678901;ext=2",
AreaCode: "+86",
},
"12345678901",
},
@@ -56,6 +56,20 @@ func TestMobileExt(t *testing.T) {
},
"12345678901",
},
{
SInternationalMobile{
"13811111111",
"",
},
"13811111111",
},
{
SInternationalMobile{
"+85213811111111",
"",
},
"13811111111",
},
}
for _, c := range cases {

View File

@@ -21,6 +21,10 @@ import (
"yunion.io/x/onecloud/pkg/apis"
)
const (
WEBHOOK_SIGNATURE_HEADER = "X-Auth-Token"
)
type RobotCreateInput struct {
apis.SharableVirtualResourceCreateInput
apis.EnabledBaseResourceCreateInput
@@ -37,6 +41,7 @@ type RobotCreateInput struct {
Header jsonutils.JSONObject `json:"header"`
Body jsonutils.JSONObject `json:"body"`
MsgKey string `json:"msg_key"`
SecretKey string `json:"secret_key"`
UseTemplate tristate.TriState `json:"use_template"`
}
@@ -63,8 +68,9 @@ type RobotUpdateInput struct {
Address string `json:"address"`
// description: Language preference
// example: en
Lang string `json:"lang"`
Header jsonutils.JSONObject `json:"header"`
Body jsonutils.JSONObject `json:"body"`
MsgKey string `json:"msg_key"`
Lang string `json:"lang"`
Header jsonutils.JSONObject `json:"header"`
Body jsonutils.JSONObject `json:"body"`
MsgKey string `json:"msg_key"`
SecretKey string `json:"secret_key"`
}

View File

@@ -52,6 +52,7 @@ type ServerConfig struct {
Name string `json:"name"`
GuestStatus string `json:"guest_status"`
Cdrom string `json:"cdrom"`
Bios string `json:"bios"`
// owner project id
Project string `json:"project_id"`

View File

@@ -38,4 +38,8 @@ const (
CLOUDPODS = "cloudpods"
PROXMOX = "proxmox"
VOLC_ENGINE = "volcengine"
BAIDU = "baidu"
SANGFOR = "sangfor"
CNWARE = "cnware"
KSYUN = "ksyun"
)

View File

@@ -17,7 +17,8 @@ package yunionconf
import "yunion.io/x/onecloud/pkg/apis"
const (
SERVICE_TYPE = apis.SERVICE_TYPE_YUNIONCONF
SERVICE_TYPE = apis.SERVICE_TYPE_YUNIONCONF
SERVICE_VERSION = ""
)
const (

View File

@@ -0,0 +1,31 @@
// 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 yunionconf
import "yunion.io/x/onecloud/pkg/apis"
type TagListInput struct {
apis.InfrasResourceBaseListInput
}
type TagDetails struct {
apis.InfrasResourceBaseDetails
}
type TagCreateInput struct {
apis.InfrasResourceBaseCreateInput
Values []string `json:"values"`
}

View File

@@ -631,9 +631,10 @@ func (app *Application) listenAndServeInternal(s *http.Server, certFile, keyFile
type TContentType string
const (
ContentTypeJson = TContentType("Json")
ContentTypeForm = TContentType("Form")
ContentTypeUnknown = TContentType("Unknown")
ContentTypeJson = TContentType("Json")
ContentTypeForm = TContentType("Form")
ContentTypeOctetStream = TContentType("OctetStream")
ContentTypeUnknown = TContentType("Unknown")
)
func getContentType(r *http.Request) TContentType {
@@ -649,6 +650,7 @@ func getContentType(r *http.Request) TContentType {
for k, v := range map[string]TContentType{
"application/json": ContentTypeJson,
"application/x-www-form-urlencoded": ContentTypeForm,
"application/octet-stream": ContentTypeOctetStream,
} {
if strings.HasPrefix(contType, k) {
return v
@@ -664,7 +666,6 @@ func FetchEnv(ctx context.Context, w http.ResponseWriter, r *http.Request) (para
if err != nil {
log.Errorf("Parse query string %s failed: %v", r.URL.RawQuery, err)
}
//var body jsonutils.JSONObject = nil
if r.Method == "PUT" || r.Method == "POST" || r.Method == "DELETE" || r.Method == "PATCH" {
switch getContentType(r) {
case ContentTypeJson:
@@ -683,6 +684,7 @@ func FetchEnv(ctx context.Context, w http.ResponseWriter, r *http.Request) (para
if err != nil {
log.Warningf("Parse query string %s failed: %v", r.PostForm.Encode(), err)
}
case ContentTypeOctetStream:
default:
log.Warningf("%s invalid contentType with header %v", r.URL.String(), r.Header)
}

View File

@@ -94,7 +94,7 @@ func (job *SStatusProbeJob) Name() string {
func (job *SStatusProbeJob) Do(ctx context.Context, now time.Time) error {
if job.baremetal.IsHypervisorHost() {
log.Infof("baremetal %q is host, skipping status probe", job.baremetal.GetName())
log.Debugf("baremetal %q is host, skipping status probe", job.baremetal.GetName())
return nil
}
bStatus := job.baremetal.GetStatus()

View File

@@ -56,7 +56,9 @@ import (
"yunion.io/x/onecloud/pkg/baremetal/utils/disktool"
"yunion.io/x/onecloud/pkg/baremetal/utils/grub"
"yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool"
raid2 "yunion.io/x/onecloud/pkg/baremetal/utils/raid"
raiddrivers "yunion.io/x/onecloud/pkg/baremetal/utils/raid/drivers"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid/mdadm"
"yunion.io/x/onecloud/pkg/baremetal/utils/uefi"
"yunion.io/x/onecloud/pkg/cloudcommon/types"
"yunion.io/x/onecloud/pkg/compute/baremetal"
@@ -826,7 +828,7 @@ func (b *SBaremetalInstance) ServerLoadDesc(ctx context.Context) error {
}
}
func PowerStatusToBaremetalStatus(status string) string {
func PowerStatusToBaremetalStatus(status types.PowerStatus) string {
switch status {
case types.POWER_STATUS_ON:
return baremetalstatus.RUNNING
@@ -836,7 +838,7 @@ func PowerStatusToBaremetalStatus(status string) string {
return baremetalstatus.UNKNOWN
}
func PowerStatusToServerStatus(bm *SBaremetalInstance, status string) string {
func PowerStatusToServerStatus(bm *SBaremetalInstance, status types.PowerStatus) string {
switch status {
case types.POWER_STATUS_ON:
if conf, _ := bm.GetSSHConfig(); conf == nil {
@@ -890,7 +892,7 @@ func (b *SBaremetalInstance) DelayedSyncStatus(ctx context.Context, data jsonuti
return nil, nil
}
func (b *SBaremetalInstance) SyncAllStatus(ctx context.Context, status string) {
func (b *SBaremetalInstance) SyncAllStatus(ctx context.Context, status types.PowerStatus) {
var err error
if status == "" {
status, err = b.GetPowerStatus()
@@ -898,24 +900,26 @@ func (b *SBaremetalInstance) SyncAllStatus(ctx context.Context, status string) {
log.Errorf("Get power status error: %v", err)
}
}
b.SyncStatus(ctx, PowerStatusToBaremetalStatus(status), "")
b.SyncServerStatus(PowerStatusToServerStatus(b, status))
b.SyncStatus(ctx, PowerStatusToBaremetalStatus(status), "SyncAllStatus by baremetal-agent")
b.SyncServerStatus(status)
}
func (b *SBaremetalInstance) SyncServerStatus(status string) {
func (b *SBaremetalInstance) SyncServerStatus(powerStatus types.PowerStatus) {
if b.GetServerId() == "" {
return
}
if status == "" {
status := PowerStatusToServerStatus(b, powerStatus)
if powerStatus == "" {
powerStatus, err := b.GetPowerStatus()
if err != nil {
log.Errorf("Get power status error: %v", err)
}
status = PowerStatusToServerStatus(b, powerStatus)
}
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(status), "status")
_, err := modules.Servers.PerformAction(b.GetClientSession(), b.GetServerId(), "status", params)
params := &apis.PerformStatusInput{}
params.Status = status
params.PowerStates = string(powerStatus)
_, err := modules.Servers.PerformAction(b.GetClientSession(), b.GetServerId(), "status", jsonutils.Marshal(params))
if err != nil {
log.Errorf("Update server %s status %s error: %v", b.GetServerName(), status, err)
return
@@ -1311,10 +1315,17 @@ func (b *SBaremetalInstance) GetTask() tasks.ITask {
}
func (b *SBaremetalInstance) SetTask(task tasks.ITask) {
// hack: clear exist tasks if task is server destroy task
if task.GetName() == tasks.BAREMETAL_SERVER_DESTROY_TASK {
log.Infof("clear tasks of baremetal %s before executing %s", b.GetName(), task.GetName())
b.taskQueue.ClearTasks()
}
b.taskQueue.AppendTask(task)
if reflect.DeepEqual(task, b.taskQueue.GetTask()) {
log.Infof("Set task equal, ExecuteTask %s", task.GetName())
log.Infof("Execute task %s of baremetal %s", task.GetName(), b.GetName())
tasks.ExecuteTask(task, nil)
} else {
log.Warningf("Append task %s of baremetal %s before executing %s", task.GetName(), b.GetName(), b.taskQueue.DebugString())
}
}
@@ -1856,7 +1867,7 @@ func (b *SBaremetalInstance) DoDiskBoot() error {
}
*/
func (b *SBaremetalInstance) GetPowerStatus() (string, error) {
func (b *SBaremetalInstance) GetPowerStatus() (types.PowerStatus, error) {
status, err := b.getPowerStatus()
if err != nil {
if errors.Cause(err) != types.ErrIPMIToolNull {
@@ -1868,7 +1879,7 @@ func (b *SBaremetalInstance) GetPowerStatus() (string, error) {
return status, nil
}
func (b *SBaremetalInstance) getPowerStatus() (string, error) {
func (b *SBaremetalInstance) getPowerStatus() (types.PowerStatus, error) {
ipmiCli := b.GetIPMITool()
if ipmiCli == nil {
if cli, err := b.GetHostSSHClient(); err == nil {
@@ -1886,7 +1897,11 @@ func (b *SBaremetalInstance) getPowerStatus() (string, error) {
}
return "", errors.Wrapf(types.ErrIPMIToolNull, "Baremetal %s", b.GetId())
}
return ipmitool.GetChassisPowerStatus(ipmiCli)
cps, err := ipmitool.GetChassisPowerStatus(ipmiCli)
if err != nil {
return "", errors.Wrap(err, "ipmitool.GetChassisPowerStatus")
}
return types.PowerStatus(cps), nil
}
func (b *SBaremetalInstance) DoPowerShutdown(soft bool) error {
@@ -2582,6 +2597,25 @@ func (s *SBaremetalServer) GetMetadata() (*jsonutils.JSONDict, error) {
}
func (s *SBaremetalServer) GetRootDiskMatcher() (*api.BaremetalRootDiskMatcher, error) {
matcher, err := s.getRootDiskMatcher()
if err != nil && errors.Cause(err) != errors.ErrNotFound {
return nil, errors.Wrap(err, "getRootDiskMatcher")
}
if matcher == nil {
matcher = &api.BaremetalRootDiskMatcher{}
}
rootDiskObj, err := s.GetRootDiskObj()
if err != nil {
return nil, errors.Wrap(err, "GetRootDiskObj")
}
pciPath, _ := rootDiskObj.GetString("pci_path")
if pciPath != "" {
matcher.PCIPath = pciPath
}
return matcher, nil
}
func (s *SBaremetalServer) getRootDiskMatcher() (*api.BaremetalRootDiskMatcher, error) {
metadata, err := s.GetMetadata()
if err != nil {
return nil, errors.Wrap(err, "get metadata")
@@ -2619,6 +2653,14 @@ func (s *SBaremetalServer) GetDiskConfig() ([]*api.BaremetalDiskConfig, error) {
return baremetal.GetLayoutRaidConfig(layouts), nil
}
func (s *SBaremetalServer) GetRootDiskObj() (*jsonutils.JSONDict, error) {
disks, _ := s.desc.GetArray("disks")
if len(disks) == 0 {
return nil, errors.Error("Empty disks in desc")
}
return disks[0].(*jsonutils.JSONDict), nil
}
func (s *SBaremetalServer) NewConfigedSSHPartitionTool(term *ssh.Client) (*disktool.SSHPartitionTool, error) {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
if err != nil {
@@ -2637,15 +2679,32 @@ func (s *SBaremetalServer) NewConfigedSSHPartitionTool(term *ssh.Client) (*diskt
return nil, fmt.Errorf("CalculateLayout: %v", err)
}
log.Errorf("NewConfigedSSHPartitionTool layouts: %s", jsonutils.Marshal(layouts))
diskConfs := baremetal.GroupLayoutResultsByDriverAdapter(layouts)
for _, dConf := range diskConfs {
driver := dConf.Driver
adapter := dConf.Adapter
isSoftRaid := baremetal.DISK_DRIVERS_SOFT_RAID.Has(driver)
raidDrv := raiddrivers.GetDriver(driver, term)
if raidDrv != nil {
if err := raidDrv.ParsePhyDevs(); err != nil {
return nil, fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
}
if isSoftRaid {
devs := make([]*baremetal.BaremetalStorage, 0)
for _, layout := range layouts {
if len(layout.Disks) > 0 && layout.Disks[0].Driver == driver && layout.Disks[0].Adapter == dConf.Adapter {
devs = append(devs, layout.Disks...)
}
}
log.Infof("SetDevicesForAdapter %v", jsonutils.Marshal(devs))
if mdadmDrver, ok := raidDrv.(raid2.IRaidDeviceSetter); ok {
mdadmDrver.SetDevicesForAdapter(dConf.Adapter, devs)
}
}
if err := raiddrivers.PostBuildRaid(raidDrv, adapter); err != nil {
return nil, fmt.Errorf("Build %s raid failed: %v", raidDrv.GetName(), err)
}
@@ -2681,9 +2740,8 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitio
if err != nil {
return nil, fmt.Errorf("CalculateLayout: %v", err)
}
log.Errorf("===layouts: %s", jsonutils.Marshal(layouts).PrettyString())
diskConfs := baremetal.GroupLayoutResultsByDriverAdapter(layouts)
log.Errorf("===diskConfs: %s", jsonutils.Marshal(diskConfs).PrettyString())
log.Errorf("%s layouts: %s, diskConfs: %s", s.GetName(), jsonutils.Marshal(layouts).PrettyString(), jsonutils.Marshal(diskConfs).PrettyString())
for _, dConf := range diskConfs {
driver := dConf.Driver
raidDrv := raiddrivers.GetDriver(driver, term)
@@ -2698,11 +2756,27 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitio
for _, dConf := range diskConfs {
driver := dConf.Driver
adapter := dConf.Adapter
isSoftRaid := baremetal.DISK_DRIVERS_SOFT_RAID.Has(driver)
raidDrv := raiddrivers.GetDriver(driver, term)
if raidDrv != nil {
if err := raidDrv.ParsePhyDevs(); err != nil {
return nil, fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
}
if isSoftRaid {
devs := make([]*baremetal.BaremetalStorage, 0)
for _, layout := range layouts {
if len(layout.Disks) > 0 && layout.Disks[0].Driver == driver && layout.Disks[0].Adapter == dConf.Adapter {
devs = append(devs, layout.Disks...)
}
}
log.Infof("SetDevicesForAdapter %v", jsonutils.Marshal(devs))
if mdadmDriver, ok := raidDrv.(raid2.IRaidDeviceSetter); ok {
mdadmDriver.SetDevicesForAdapter(dConf.Adapter, devs)
}
}
if err := raiddrivers.BuildRaid(raidDrv, dConf.Configs, adapter); err != nil {
return nil, fmt.Errorf("Build %s raid failed: %v", raidDrv.GetName(), err)
}
@@ -2721,7 +2795,7 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitio
maxTries := 60
for tried := 0; !tool.IsAllDisksReady() && tried < maxTries; tried++ {
time.Sleep(5 * time.Second)
tool.RetrieveDiskInfo()
tool.RetrieveDiskInfo(matcher)
log.Warningf("disktool not ready string: %s", tool.DebugString())
}
@@ -2746,6 +2820,10 @@ func (s *SBaremetalServer) DoDiskUnconfig(term *ssh.Client) error {
}
func (s *SBaremetalServer) DoEraseDisk(term *ssh.Client) error {
// soft raid should stop mdadm first
if err := mdadm.CleanRaid(term); err != nil {
return err
}
cmd := "/lib/mos/partdestroy.sh"
_, err := term.Run(cmd)
return err
@@ -2775,10 +2853,10 @@ func (s *SBaremetalServer) doCreateRoot(term *ssh.Client, devName string, disabl
return nil
}
func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) {
func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error) {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
if err != nil {
return nil, err
return nil, nil, errors.Wrap(err, "DetectStorageInfo")
}
storages := make([]*baremetal.BaremetalStorage, 0)
storages = append(storages, raid...)
@@ -2800,33 +2878,35 @@ func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term
disks, _ := s.desc.GetArray("disks")
if len(disks) == 0 {
return nil, errors.Error("Empty disks in desc")
return nil, nil, errors.Error("Empty disks in desc")
}
rootImageId := s.GetRootTemplateId()
diskOffset := 0
rootDisk := tool.GetRootDisk()
log.Infof("root disk name %s", rootDisk.GetDevName())
if len(rootImageId) > 0 {
rootDisk := disks[0]
rootSize, _ := rootDisk.Int("size")
err = s.doCreateRoot(term, tool.GetRootDisk().GetDevName(), disableImageCache)
rootDiskObj := disks[0]
rootSize, _ := rootDiskObj.Int("size")
err = s.doCreateRoot(term, rootDisk.GetDevName(), disableImageCache)
if err != nil {
return nil, errors.Wrap(err, "Failed to create root")
return rootDisk, nil, errors.Wrap(err, "Failed to create root")
}
tool.RetrievePartitionInfo()
parts := tool.GetPartitions()
if len(parts) == 0 {
return nil, errors.Error("Root disk create failed, no partitions")
return rootDisk, nil, errors.Error("Root disk create failed, no partitions")
}
log.Infof("Resize root to %d MB", rootSize)
if err := tool.ResizePartition(0, rootSize); err != nil {
return nil, errors.Wrapf(err, "Fail to resize root to %d", rootSize)
return rootDisk, nil, errors.Wrapf(err, "Fail to resize root to %d", rootSize)
}
diskOffset = 1
} else {
tool.RetrievePartitionInfo()
parts := tool.GetPartitions()
if len(parts) > 0 {
return nil, errors.Error("should no partition!!!")
return rootDisk, nil, errors.Error("should no partition!!!")
}
}
@@ -2841,16 +2921,16 @@ func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term
driver, _ := disk.GetString("driver")
log.Infof("Create partition %d %s", sz, fs)
if err := tool.CreatePartition(-1, sz, fs, true, driver, uuid); err != nil {
return nil, errors.Wrapf(err, "Fail to create disk %s", disk.String())
return rootDisk, nil, errors.Wrapf(err, "Fail to create disk %s", disk.String())
}
}
}
log.Infof("Finish create partitions")
return tool.GetPartitions(), nil
return rootDisk, tool.GetPartitions(), nil
}
func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) {
func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error) {
// raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
// if err != nil {
// return nil, err
@@ -2875,7 +2955,7 @@ func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, te
disks, _ := s.desc.GetArray("disks")
if len(disks) == 0 {
return nil, fmt.Errorf("Empty disks in desc")
return nil, nil, fmt.Errorf("Empty disks in desc")
}
rootDisk := disks[0]
@@ -2883,16 +2963,16 @@ func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, te
rd := tool.GetRootDisk()
err := s.doCreateRoot(term, rd.GetDevName(), disableImageCache)
if err != nil {
return nil, fmt.Errorf("Failed to create root: %v", err)
return rd, nil, fmt.Errorf("Failed to create root: %v", err)
}
tool.RetrievePartitionInfo()
if err := rd.ReInitInfo(); err != nil {
return nil, errors.Wrap(err, "Reinit root disk after create root")
return rd, nil, errors.Wrap(err, "Reinit root disk after create root")
}
log.Infof("Resize root to %d MB", rootSize)
if err := rd.ResizePartition(rootSize); err != nil {
return nil, fmt.Errorf("Fail to resize root to %d, err: %v", rootSize, err)
return rd, nil, fmt.Errorf("Fail to resize root to %d, err: %v", rootSize, err)
}
if len(disks) > 1 {
for _, disk := range disks[1:] {
@@ -2919,10 +2999,10 @@ func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, te
for _, d := range restDisks {
parts = append(parts, d.GetPartitions()...)
}
return parts, nil
return rd, parts, nil
}
func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, parts []*disktool.Partition) ([]jsonutils.JSONObject, error) {
func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, rootDisk *disktool.DiskPartitions, parts []*disktool.Partition) ([]jsonutils.JSONObject, error) {
disks, _ := s.desc.GetArray("disks")
// calculate root partitions count
@@ -2934,27 +3014,35 @@ func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, parts []*disktool
rootParts := parts[0:rootPartsCnt]
dataParts := parts[rootPartsCnt:]
idx := 0
// set root disk attributes that returns to region service
size := (rootParts[len(rootParts)-1].GetEnd() + 1) * 512 / 1024 / 1024
disks[idx].(*jsonutils.JSONDict).Set("size", jsonutils.NewInt(int64(size)))
rootDiskObj := disks[idx].(*jsonutils.JSONDict)
rootDiskObj.Set("size", jsonutils.NewInt(int64(size)))
rootDiskObj.Set("pci_path", jsonutils.NewString(rootDisk.GetPCIPath()))
idx += 1
for _, p := range dataParts {
sizeMB, err := p.GetSizeMB()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "GetSizeMB")
}
disks[idx].(*jsonutils.JSONDict).Set("size", jsonutils.NewInt(int64(sizeMB)))
disks[idx].(*jsonutils.JSONDict).Set("dev", jsonutils.NewString(p.GetDev()))
idx++
}
s.desc.Set("disks", jsonutils.NewArray(disks...))
return disks, nil
}
func (s *SBaremetalServer) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error) {
publicKey := deployapi.GetKeys(data)
isRandomPassword := false
password, _ := data.GetString("password")
resetPassword := jsonutils.QueryBoolean(data, "reset_password", false)
if resetPassword && len(password) == 0 {
password = seclib.RandomPassword(12)
isRandomPassword = true
}
deployArray := make([]*deployapi.DeployContent, 0)
if data.Contains("deploys") {
@@ -2965,7 +3053,7 @@ func (s *SBaremetalServer) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.C
}
userData, _ := s.desc.GetString("user_data")
deployInfo := deployapi.NewDeployInfo(publicKey, deployArray,
password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false, "",
password, isRandomPassword, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false, "",
false, "",
userData,
)

View File

@@ -180,6 +180,25 @@ func (q *TaskQueue) AppendTask(task ITask) *TaskQueue {
return q
}
func (q *TaskQueue) ClearTasks() {
for {
existTask := q.PopTask()
if existTask != nil {
log.Warningf("Clear task %s", existTask.GetName())
} else {
break
}
}
}
func (q *TaskQueue) DebugString() string {
str := ""
for e := q.objList.Front(); e != nil; e = e.Next() {
str += fmt.Sprintf("%s, ", e.Value.(ITask).GetName())
}
return str
}
type TaskFactory func(userCred mcclient.TokenCredential, bm IBaremetal, taskId string, data jsonutils.JSONObject) ITask
type SBaremetalTaskBase struct {

View File

@@ -54,22 +54,23 @@ func (self *SBaremetalServerCreateTask) RemoveEFIOSEntry() bool {
}
func (self *SBaremetalServerCreateTask) DoDeploys(ctx context.Context, term *ssh.Client) (jsonutils.JSONObject, error) {
if err := self.Baremetal.GetServer().DoEraseDisk(term); err != nil {
return nil, self.onError(ctx, term, err)
}
time.Sleep(2 * time.Second)
// Build raid
tool, err := self.Baremetal.GetServer().DoDiskConfig(term)
if err != nil {
return nil, self.onError(ctx, term, err)
}
time.Sleep(2 * time.Second)
if err := self.Baremetal.GetServer().DoEraseDisk(term); err != nil {
return nil, self.onError(ctx, term, err)
}
time.Sleep(2 * time.Second)
parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term, self.IsDisableImageCache())
rootDisk, parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term, self.IsDisableImageCache())
if err != nil {
return nil, self.onError(ctx, term, err)
}
data := jsonutils.NewDict()
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, parts)
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, rootDisk, parts)
if err != nil {
return nil, self.onError(ctx, term, err)
}

View File

@@ -26,6 +26,10 @@ import (
var _ IServerBaseDeployTask = new(SBaremetalServerDestroyTask)
const (
BAREMETAL_SERVER_DESTROY_TASK = "BaremetalServerDestroyTask"
)
type SBaremetalServerDestroyTask struct {
SBaremetalServerBaseDeployTask
}
@@ -45,7 +49,7 @@ func NewBaremetalServerDestroyTask(
}
func (self *SBaremetalServerDestroyTask) GetName() string {
return "BaremetalServerDestroyTask"
return BAREMETAL_SERVER_DESTROY_TASK
}
func (self *SBaremetalServerDestroyTask) RemoveEFIOSEntry() bool {

View File

@@ -50,10 +50,10 @@ type IBaremetal interface {
SyncStatus(ctx context.Context, status, reason string)
AutoSyncStatus(ctx context.Context)
SyncAllStatus(ctx context.Context, status string)
SyncAllStatus(ctx context.Context, status types.PowerStatus)
AutoSyncAllStatus(ctx context.Context)
GetPowerStatus() (string, error)
GetPowerStatus() (types.PowerStatus, error)
DoPowerShutdown(soft bool) error
DoPXEBoot() error
// DoDiskBoot() error

View File

@@ -58,11 +58,11 @@ func (self *SBaremetalServerRebuildTask) DoDeploys(ctx context.Context, term *ss
if err != nil {
return nil, errors.Wrap(err, "NewConfigedSSHPartitionTool")
}
parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(tool, term, self.IsDisableImageCache())
rootDisk, parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(tool, term, self.IsDisableImageCache())
if err != nil {
return nil, fmt.Errorf("Rebuild root disk: %v", err)
}
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, parts)
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, rootDisk, parts)
if err != nil {
return nil, fmt.Errorf("SyncPartitionSize: %v", err)
}

View File

@@ -71,7 +71,7 @@ func (self *SBaremetalResetBMCTask) WaitForBMCReady(ctx context.Context, args in
if err != nil {
return err
}
if status != "" && status == types.POWER_STATUS_ON {
if status != "" && status == string(types.POWER_STATUS_ON) {
ExecuteTask(self, nil)
}
return nil

View File

@@ -31,10 +31,10 @@ type IBaremetalServer interface {
DoDiskUnconfig(term *ssh.Client) error
DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitionTool, error)
DoEraseDisk(term *ssh.Client) error
DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error)
DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error)
NewConfigedSSHPartitionTool(term *ssh.Client) (*disktool.SSHPartitionTool, error)
DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error)
SyncPartitionSize(term *ssh.Client, parts []*disktool.Partition) ([]jsonutils.JSONObject, error)
DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error)
SyncPartitionSize(term *ssh.Client, rootDisk *disktool.DiskPartitions, parts []*disktool.Partition) ([]jsonutils.JSONObject, error)
DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error)
SaveDesc(desc jsonutils.JSONObject) error
GetNics() []types.SServerNic

View File

@@ -17,8 +17,10 @@ package disktool
import (
"fmt"
"math"
"strconv"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
@@ -224,10 +226,11 @@ type DiskPartitions struct {
rotate bool
desc string
label string
pciPath string
partitions []*Partition
}
func newDiskPartitions(driver string, adapter int, raidConfig string, sizeMB int64, blockSize int64, diskType string, tool *PartitionTool) *DiskPartitions {
func newDiskPartitions(driver string, adapter int, raidConfig string, sizeMB int64, blockSize int64, diskType string, softRaidIdx *int, tool *PartitionTool) *DiskPartitions {
ps := new(DiskPartitions)
ps.driver = driver
ps.adapter = adapter
@@ -237,9 +240,32 @@ func newDiskPartitions(driver string, adapter int, raidConfig string, sizeMB int
ps.blockSize = blockSize
ps.diskType = diskType
ps.partitions = make([]*Partition, 0)
// soft raid, mdadm
if softRaidIdx != nil {
ps.GetMdadmInfo(softRaidIdx)
}
return ps
}
func (ps *DiskPartitions) GetMdadmInfo(softRaidIdx *int) {
devLinkName := fmt.Sprintf("/dev/md/md%d", *softRaidIdx)
devLinkNickname := fmt.Sprintf("/dev/md/md%d_0", *softRaidIdx)
cmd := fmt.Sprintf("readlink -f $(test -e %s && echo %s || echo %s)", devLinkName, devLinkName, devLinkNickname)
out, err := ps.tool.Run(cmd)
if err != nil || len(out) == 0 {
log.Errorf("failed readlink of %s: %s", devLinkName, err)
return
}
ps.dev = strings.TrimSpace(out[0])
ps.devName = ps.dev
uuid, sectors := ps.tool.GetMdadmUuidAndSector(ps.dev)
ps.pciPath = uuid
ps.sectors = sectors
ps.blockSize = 512
}
func (p *DiskPartitions) IsRaidDriver() bool {
return utils.IsInStringArray(p.driver, []string{
baremetal.DISK_DRIVER_MEGARAID,
@@ -253,7 +279,13 @@ func (p *DiskPartitions) GetDev() string {
return p.dev
}
func (p *DiskPartitions) SetInfo(info *types.SDiskInfo) *DiskPartitions {
func getPCIPathPrefix(input string) string {
input = strings.TrimSpace(input)
parts := strings.Split(input, "/")
return strings.Join(parts[0:len(parts)-2], "/")
}
func (p *DiskPartitions) SetInfo(info *types.SDiskInfo) (*DiskPartitions, error) {
p.dev = fmt.Sprintf("/dev/%s", info.Dev)
p.devName = info.Dev
p.sectors = info.Sector
@@ -262,7 +294,17 @@ func (p *DiskPartitions) SetInfo(info *types.SDiskInfo) *DiskPartitions {
if p.blockSize == 4096 {
p.sectors = (p.sectors >> 3)
}
return p
// /sys/block/sda => /sys/devices/pci0000:00/0000:00:04.0/virtio1/host0/target0:0:0/0:0:0:0/block/sda
// /sys/block/nvme1n1 => /sys/devices/pci0000:00/0000:00:1a.0/0000:03:00.0/nvme/nvme1/nvme1n1
outputs, err := p.Run(fmt.Sprintf("readlink -f /sys/block/%s", info.Dev))
if err != nil {
return nil, errors.Wrapf(err, "failed to read device %s pci path", p.dev)
}
if len(outputs) > 0 {
p.pciPath = getPCIPathPrefix(outputs[0])
}
return p, nil
}
func (p *DiskPartitions) ReInitInfo() error {
@@ -273,7 +315,9 @@ func (p *DiskPartitions) ReInitInfo() error {
}
for _, disk := range sysutils.ParseDiskInfo(lines, p.driver) {
if disk.Dev == p.GetDevName() {
p.SetInfo(disk)
if _, err := p.SetInfo(disk); err != nil {
return errors.Wrapf(err, "set info of disk %v", disk)
}
}
}
return p.RetrievePartitionInfo()
@@ -304,7 +348,7 @@ func (ps *DiskPartitions) IsReady() bool {
func (ps *DiskPartitions) GetDevName() string {
devName := ps.devName
if !ps.IsRaidDriver() || ps.raidConfig == baremetal.DISK_CONF_NONE {
if ps.raidConfig == baremetal.DISK_CONF_NONE {
return devName
}
raidDrv, err := raiddrivers.GetDriverWithInit(ps.driver, ps.tool.runner.Term())
@@ -326,6 +370,10 @@ func (ps *DiskPartitions) GetDevName() string {
return devName
}
func (ps *DiskPartitions) GetPCIPath() string {
return ps.pciPath
}
func (ps *DiskPartitions) RetrievePartitionInfo() error {
ps.partitions = make([]*Partition, 0)
cmd := []string{"parted", "-s", ps.dev, "--", "unit", "s", "print"}
@@ -664,14 +712,15 @@ func (tool *PartitionTool) parseLsDisk(lines []string, driver string) {
}
}
func (tool *PartitionTool) FetchDiskConfs(diskConfs []baremetal.DiskConfiguration, rootMatcher *api.BaremetalRootDiskMatcher) *PartitionTool {
func (tool *PartitionTool) FetchDiskConfs(diskConfs []baremetal.DiskConfiguration) *PartitionTool {
for _, d := range diskConfs {
disk := newDiskPartitions(d.Driver, d.Adapter, d.RaidConfig, d.Size, d.Block, d.DiskType, tool)
disk := newDiskPartitions(d.Driver, d.Adapter, d.RaidConfig, d.Size, d.Block, d.DiskType, d.SoftRaidIdx, tool)
tool.disks = append(tool.disks, disk)
isSoftRaid := d.RaidConfig != baremetal.DISK_CONF_NONE
var key string
if d.Driver == baremetal.DISK_DRIVER_LINUX {
if d.Driver == baremetal.DISK_DRIVER_LINUX && !isSoftRaid {
key = NONRAID_DRIVER
} else if d.Driver == baremetal.DISK_DRIVER_PCIE {
} else if d.Driver == baremetal.DISK_DRIVER_PCIE && !isSoftRaid {
key = PCIE_DRIVER
} else {
key = RAID_DRVIER
@@ -681,16 +730,10 @@ func (tool *PartitionTool) FetchDiskConfs(diskConfs []baremetal.DiskConfiguratio
}
tool.diskTable[key] = append(tool.diskTable[key], disk)
}
// reorder tool.disks
if rootMatcher != nil {
tool.reorderRootDisk(rootMatcher)
}
return tool
}
func (tool *PartitionTool) reorderRootDisk(matcher *api.BaremetalRootDiskMatcher) {
var rootDiskIdx = 0
isDiskMatch := func(disk *DiskPartitions, matcher *api.BaremetalRootDiskMatcher) bool {
if matcher.Device != "" {
if disk.dev == matcher.Device {
@@ -710,16 +753,25 @@ func (tool *PartitionTool) reorderRootDisk(matcher *api.BaremetalRootDiskMatcher
return true
}
}
if matcher.PCIPath != "" {
if disk.pciPath == matcher.PCIPath {
return true
}
}
return false
}
var rootDiskStr string
var rootDiskIdx = 0
for idx, disk := range tool.disks {
if isDiskMatch(disk, matcher) {
rootDiskIdx = idx
rootDiskStr = disk.String()
break
}
}
log.Infof("Select %d as root disk", rootDiskIdx)
log.Infof("Select %d %q as root disk by matcher: %s", rootDiskIdx, rootDiskStr, jsonutils.Marshal(matcher))
newDisks := make([]*DiskPartitions, 0)
newDisks = append(newDisks, tool.disks[rootDiskIdx])
for idx := range tool.disks {
@@ -741,7 +793,42 @@ func (tool *PartitionTool) IsAllDisksReady() bool {
return true
}
func (tool *PartitionTool) RetrieveDiskInfo() error {
func (tool *PartitionTool) GetMdadmUuidAndSector(devPath string) (string, int64) {
var uuid string
var sectorsRet int64
// get md uuid as pci path
cmd := fmt.Sprintf("/sbin/mdadm --detail %s | grep UUID", devPath)
output, err := tool.Run(cmd)
if err == nil && len(output) > 0 {
uuidSeg := output[0]
segs := strings.SplitN(strings.TrimSpace(uuidSeg), ":", 2)
if len(segs) == 2 {
uuid = strings.TrimSpace(segs[1])
}
}
// get block size
cmd = fmt.Sprintf("blockdev --getsz %s 2>/dev/null || echo 0", devPath)
output, err = tool.Run(cmd)
if err == nil && len(output) > 0 {
if sectors, err := strconv.ParseInt(strings.TrimSpace(output[0]), 10, 64); err == nil {
sectorsRet = sectors
}
}
return uuid, sectorsRet
}
func (tool *PartitionTool) RetrieveDiskInfo(rootMatcher *api.BaremetalRootDiskMatcher) error {
for _, disk := range tool.disks {
if baremetal.DISK_DRIVERS_SOFT_RAID.Has(disk.driver) && disk.raidConfig != baremetal.DISK_CONF_NONE {
log.Infof("Soft raid mdadm set diskinfo dev %s", disk.dev)
uuid, sectors := tool.GetMdadmUuidAndSector(disk.dev)
disk.pciPath = uuid
disk.sectors = sectors
disk.blockSize = 512
}
}
for _, driver := range []string{RAID_DRVIER, NONRAID_DRIVER, PCIE_DRIVER} {
cmd := fmt.Sprintf("/lib/mos/lsdisk --%s", driver)
ret, err := tool.Run(cmd)
@@ -750,6 +837,10 @@ func (tool *PartitionTool) RetrieveDiskInfo() error {
}
tool.parseLsDisk(ret, driver)
}
// reorder tool.disks
if rootMatcher != nil {
tool.reorderRootDisk(rootMatcher)
}
return nil
}
@@ -837,8 +928,8 @@ func newSSHPartitionTool(term *ssh.Client) *SSHPartitionTool {
func NewSSHPartitionTool(term *ssh.Client, layouts []baremetal.Layout, rootMatcher *api.BaremetalRootDiskMatcher) (*SSHPartitionTool, error) {
tool := newSSHPartitionTool(term)
tool.FetchDiskConfs(baremetal.GetDiskConfigurations(layouts), rootMatcher)
if err := tool.RetrieveDiskInfo(); err != nil {
tool.FetchDiskConfs(baremetal.GetDiskConfigurations(layouts))
if err := tool.RetrieveDiskInfo(rootMatcher); err != nil {
return nil, errors.Wrapf(err, "RetrieveDiskInfo")
}
return tool, nil

View File

@@ -14,6 +14,8 @@
package disktool
import "testing"
// TODO: use mock ssh server backend test disktool
/*
import (
@@ -64,3 +66,26 @@ func TestSSHCreate(t *testing.T) {
t.Errorf("Failed to resize fs: %v", err)
}
}*/
func Test_getPCIPathPrefix(t *testing.T) {
tests := []struct {
input string
want string
}{
{
input: "/sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/host0/target0:1:0/0:1:0:0/block/sda",
want: "/sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/host0/target0:1:0/0:1:0:0",
},
{
input: "/sys/devices/pci0000:00/0000:00:06.0/0000:02:00.0/nvme/nvme0/nvme0n1",
want: "/sys/devices/pci0000:00/0000:00:06.0/0000:02:00.0/nvme",
},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
if got := getPCIPathPrefix(tt.input); got != tt.want {
t.Errorf("getPCIPathPrefix() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -42,8 +42,8 @@ menuentry 'YunionOS for PXE' --class os {
var (
BOOT_EFI_MATCHER = "(hd*,gpt*)/EFI/BOOT/BOOTX64.EFI (hd*,msdos*)/EFI/BOOT/BOOTX64.EFI (hd*,gpt*)/EFI/BOOT/BOOTAA64.EFI (hd*,msdos*)/EFI/BOOT/BOOTAA64.EFI"
GRUB_EFI_MATCHER = "(md*)/EFI/*/shimx64.efi (md*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimx64.efi (hd*,msdos*)/EFI/*/shimx64.efi (hd*,gpt*)/EFI/*/grubx64.efi (hd*,mosdos*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimaa64.efi (hd*,msdos*)/EFI/*/shimaa64.efi (hd*,gpt*)/EFI/*/grubaa64.efi (hd*,mosdos*)/EFI/*/grubaa64.efi"
GRUB_CFG_MATCHER = "(md*)/boot/*/grub.cfg (md*)/*/grub.cfg (md*)/grub.cfg (md*)/EFI/*/grub.cfg (md*)/EFI/*/*/grub.cfg (hd*,gpt*)/boot/*/grub.cfg (hd*,gpt*)/*/grub.cfg (hd*,gpt*)/grub.cfg (hd*,gpt*)/EFI/*/grub.cfg (hd*,gpt*)/EFI/*/*/grub.cfg (hd*,mosdos*)/boot/*/grub.cfg (hd*,mosdos*)/*/grub.cfg (hd*,mosdos*)/grub.cfg (hd*,mosdos*)/EFI/*/grub.cfg (hd*,mosdos*)/EFI/*/*/grub.cfg"
GRUB_EFI_MATCHER = "(md*)/EFI/*/shimx64.efi (md*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimx64.efi (hd*,msdos*)/EFI/*/shimx64.efi (hd*,gpt*)/EFI/*/grubx64.efi (hd*,msdos*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimaa64.efi (hd*,msdos*)/EFI/*/shimaa64.efi (hd*,gpt*)/EFI/*/grubaa64.efi (hd*,msdos*)/EFI/*/grubaa64.efi"
GRUB_CFG_MATCHER = "(md*)/boot/*/grub.cfg (md*)/*/grub.cfg (md*)/grub.cfg (md*)/EFI/*/grub.cfg (md*)/EFI/*/*/grub.cfg (hd*,gpt*)/boot/*/grub.cfg (hd*,gpt*)/*/grub.cfg (hd*,gpt*)/grub.cfg (hd*,gpt*)/EFI/*/grub.cfg (hd*,gpt*)/EFI/*/*/grub.cfg (hd*,msdos*)/boot/*/grub.cfg (hd*,msdos*)/*/grub.cfg (hd*,msdos*)/grub.cfg (hd*,msdos*)/EFI/*/grub.cfg (hd*,msdos*)/EFI/*/*/grub.cfg"
)
// REF: https://github.com/bluebanquise/infrastructure/blob/master/packages/bluebanquise-ipxe/grub2-efi-autofind.cfg

View File

@@ -520,7 +520,7 @@ func DoReboot(exector IPMIExecutor) error {
}
isValidStatus := func(s string) bool {
return utils.IsInStringArray(s, []string{types.POWER_STATUS_ON, types.POWER_STATUS_OFF})
return utils.IsInStringArray(s, []string{string(types.POWER_STATUS_ON), string(types.POWER_STATUS_OFF)})
}
for tried := 0; !isValidStatus(status) && tried <= maxTries; tried++ {
@@ -536,7 +536,7 @@ func DoReboot(exector IPMIExecutor) error {
}
// do shutdown
if status == types.POWER_STATUS_ON {
if status == string(types.POWER_STATUS_ON) {
if err := DoHardShutdown(exector); err != nil {
log.Errorf("DoHardShutdown: %v", err)
}
@@ -546,7 +546,7 @@ func DoReboot(exector IPMIExecutor) error {
if err != nil {
log.Errorf("DoReboot %d tries to get power status: %v", tried, err)
}
if status == types.POWER_STATUS_OFF {
if status == string(types.POWER_STATUS_OFF) {
break
}
time.Sleep(10 * time.Second)
@@ -555,7 +555,7 @@ func DoReboot(exector IPMIExecutor) error {
// do power on
status, _ = GetChassisPowerStatus(exector)
for tried := 0; status != types.POWER_STATUS_ON && tried < maxTries; tried++ {
for tried := 0; status != string(types.POWER_STATUS_ON) && tried < maxTries; tried++ {
if err := DoPowerOn(exector); err != nil {
log.Errorf("DoReboot %d tries to power on: %v", tried, err)
}
@@ -570,7 +570,7 @@ func DoReboot(exector IPMIExecutor) error {
if err != nil {
return errors.Wrap(err, "Get power status after power on")
}
if status != types.POWER_STATUS_ON {
if status != string(types.POWER_STATUS_ON) {
return errors.Errorf("do reboot fail to poweron, current status: %s", status)
}
return nil

View File

@@ -25,6 +25,7 @@ import (
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/adaptec"
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/hpssactl"
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/mdadm"
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/megactl"
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/mvcli"
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/sas2iru"

View File

@@ -45,6 +45,10 @@ type IRaidAdapter interface {
PostBuildRaid() error
}
type IRaidDeviceSetter interface {
SetDevicesForAdapter(int, []*baremetal.BaremetalStorage)
}
type IExecTerm interface {
Run(cmds ...string) ([]string, error)
RunWithInput(input io.Reader, cmds ...string) ([]string, error)

View File

@@ -0,0 +1 @@
package mdadm // import "yunion.io/x/onecloud/pkg/baremetal/utils/raid/mdadm"

View File

@@ -0,0 +1,434 @@
// 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 mdadm
import (
"fmt"
"path"
"regexp"
"strconv"
"strings"
"time"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/ssh"
"yunion.io/x/onecloud/pkg/util/sysutils"
)
const (
MDADM_BIN = "/sbin/mdadm"
)
func init() {
raid.RegisterDriver(baremetal.DISK_DRIVER_LINUX, NewMdadmRaidLinux)
raid.RegisterDriver(baremetal.DISK_DRIVER_PCIE, NewMdadmRaidPcie)
}
type MdadmRaid struct {
term raid.IExecTerm
adapter *MdadmRaidAdapter
driverName string
}
func NewMdadmRaidLinux(term raid.IExecTerm) raid.IRaidDriver {
return &MdadmRaid{
term: term,
driverName: baremetal.DISK_DRIVER_LINUX,
}
}
func NewMdadmRaidPcie(term raid.IExecTerm) raid.IRaidDriver {
return &MdadmRaid{
term: term,
driverName: baremetal.DISK_DRIVER_PCIE,
}
}
func (r *MdadmRaid) GetName() string {
return r.driverName
}
func (r *MdadmRaid) ParsePhyDevs() error {
if r.adapter == nil {
r.adapter = &MdadmRaidAdapter{
raid: r,
term: r.term,
index: 0,
}
}
return nil
}
func (r *MdadmRaid) SetDevicesForAdapter(adapterIdx int, devs []*baremetal.BaremetalStorage) {
r.adapter.setDevices(devs)
for i := range devs {
devPath := path.Join("/dev", devs[i].Dev)
cmd := fmt.Sprintf("%s --examine %s | grep UUID", MDADM_BIN, devPath)
output, err := r.term.Run(cmd)
if err == nil && len(output) > 0 {
for _, line := range output {
segs := strings.SplitN(strings.TrimSpace(line), ":", 2)
if len(segs) == 2 {
uuid := strings.TrimSpace(segs[1])
cmd = fmt.Sprintf("%s --assemble --scan --uuid=%s", MDADM_BIN, uuid)
output, err := r.term.Run(cmd)
if err != nil {
log.Errorf("faield assemble mdadm %s: %s", uuid, output)
}
}
}
}
}
}
func (r *MdadmRaid) GetAdapters() []raid.IRaidAdapter {
return []raid.IRaidAdapter{r.adapter}
}
func (r *MdadmRaid) PreBuildRaid(confs []*api.BaremetalDiskConfig, adapterIdx int) error {
return nil
}
func deviceHasRaid(devPath string, term *ssh.Client) bool {
cmd := fmt.Sprintf("%s --examine %s 2>/dev/null || true", MDADM_BIN, devPath)
output, err := term.Run(cmd)
if err != nil {
log.Errorf("examine device %s: %s", devPath, err)
return false
}
for _, line := range output {
if strings.Contains(line, "mdadm") || strings.Contains(line, "ARRAY") {
return true
}
}
return false
}
func (r *MdadmRaid) CleanRaid() error {
return nil
}
func CleanMdadmPartitions(term *ssh.Client) {
out, err := term.Run("ls -1 /dev/md/")
if err != nil {
log.Errorf("failed get md devices %s, %s", out, err)
return
}
// destory mdadm soft raid
for _, line := range out {
dev := strings.TrimSpace(line)
if !strings.HasPrefix(dev, "md") {
continue
}
out, err = term.Run(fmt.Sprintf("dd if=/dev/zero of=/dev/md/%s bs=512 count=34", dev))
if err != nil {
log.Errorf("failed clean mdadm partitions %s %s", out, err)
}
out, err = term.Run(fmt.Sprintf("dd if=/dev/zero of=/dev/md/%s bs=512 count=34 seek=$(( $(blockdev --getsz /dev/md/%s) - 34 ))", dev, dev))
if err != nil {
log.Errorf("failed clean mdadm partitions %s %s", out, err)
}
out, err = term.Run(fmt.Sprintf("hdparm -z /dev/md/%s", dev))
if err != nil {
log.Errorf("failed clean mdadm partitions %s %s", out, err)
}
}
}
func CleanRaid(term *ssh.Client) error {
CleanMdadmPartitions(term)
// stop md devices
cmd := fmt.Sprintf("%s --stop --scan", MDADM_BIN)
_, err := term.Run(cmd)
if err != nil {
log.Warningf("Stop md devices: %s", err)
}
pcieRet, err := term.Run("/lib/mos/lsdisk --pcie")
if err != nil {
log.Warningf("Fail to retrieve PCIE DISK info %s", err)
} else {
pcieDiskInfo := sysutils.ParsePCIEDiskInfo(pcieRet)
for i := range pcieDiskInfo {
devPath := path.Join("/dev", pcieDiskInfo[i].Dev)
if deviceHasRaid(devPath, term) {
cmd := fmt.Sprintf("%s --zero-superblock --force %s", MDADM_BIN, devPath)
out, err := term.Run(cmd)
if err != nil {
return errors.Wrapf(err, "zero superblock on %s: %s", devPath, out)
}
}
}
}
nonraidRet, err := term.Run("/lib/mos/lsdisk --nonraid")
if err != nil {
log.Warningf("Fail to retrieve SCSI DISK info %s", err)
} else {
nonraidDiskInfo := sysutils.ParseSCSIDiskInfo(nonraidRet)
for i := range nonraidDiskInfo {
devPath := path.Join("/dev", nonraidDiskInfo[i].Dev)
if deviceHasRaid(devPath, term) {
cmd := fmt.Sprintf("%s --zero-superblock --force %s", MDADM_BIN, devPath)
out, err := term.Run(cmd)
if err != nil {
return errors.Wrapf(err, "zero superblock on %s: %s", devPath, out)
}
}
}
}
out, err := term.Run("rm /dev/md/*")
if err != nil {
log.Warningf("failed soft link at /dev/md %s", out)
}
return nil
}
type MdadmRaidAdapter struct {
raid *MdadmRaid
term raid.IExecTerm
index int
devs []*baremetal.BaremetalStorage
}
func (a *MdadmRaidAdapter) GetIndex() int {
return a.index
}
func (a *MdadmRaidAdapter) PreBuildRaid(confs []*api.BaremetalDiskConfig) error {
return nil
}
func (a *MdadmRaidAdapter) GetLogicVolumes() ([]*raid.RaidLogicalVolume, error) {
lvs := make([]*raid.RaidLogicalVolume, 0)
cmd := "ls -1 /dev/md/* 2>/dev/null || true"
output, err := a.term.Run(cmd)
if err != nil {
return lvs, nil
}
for _, line := range output {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "/dev/md/md") {
mdPath := line
numStr := strings.TrimPrefix(line, "/dev/md/md")
if strings.HasSuffix(numStr, "_0") {
numStr = strings.TrimSuffix(numStr, "_0")
}
if num, err := strconv.Atoi(numStr); err == nil {
res, err := a.term.Run(fmt.Sprintf("readlink -f %s", line))
if err == nil && len(res) > 0 {
mdPath = strings.TrimSpace(res[0])
lv := &raid.RaidLogicalVolume{
Index: num,
Adapter: a.index,
BlockDev: mdPath,
}
lvs = append(lvs, lv)
}
}
}
}
return lvs, nil
}
func (a *MdadmRaidAdapter) RemoveLogicVolumes() error {
//cmd := fmt.Sprintf("%s --stop --scan", MDADM_BIN)
//_, err := a.term.Run(cmd)
//if err != nil {
// log.Warningf("Stop md devices: %v", err)
//}
return nil
}
func (a *MdadmRaidAdapter) GetDevices() []*baremetal.BaremetalStorage {
return a.devs
}
func (a *MdadmRaidAdapter) setDevices(devs []*baremetal.BaremetalStorage) {
a.devs = devs
}
func (a *MdadmRaidAdapter) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
return a.buildRaid("0", devs, conf)
}
func (a *MdadmRaidAdapter) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
return a.buildRaid("1", devs, conf)
}
func (a *MdadmRaidAdapter) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
return a.buildRaid("5", devs, conf)
}
func (a *MdadmRaidAdapter) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
return a.buildRaid("10", devs, conf)
}
func (a *MdadmRaidAdapter) BuildNoneRaid(devs []*baremetal.BaremetalStorage) error {
return nil
}
func (a *MdadmRaidAdapter) PostBuildRaid() error {
return nil
}
func (a *MdadmRaidAdapter) buildRaid(level string, devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
if len(devs) == 0 {
return fmt.Errorf("no devices provided for RAID %s", level)
}
var mdNum int
var err error
if conf.SoftRaidIdx != nil {
mdNum = *conf.SoftRaidIdx
} else {
mdNum, err = a.getNextMdNum()
if err != nil {
return errors.Wrap(err, "get next md number")
}
}
devPaths := make([]string, 0, len(devs))
for _, dev := range devs {
if dev.Dev == "" {
return fmt.Errorf("device path is empty for storage")
}
devPaths = append(devPaths, path.Join("/dev", dev.Dev))
}
for _, dev := range devPaths {
if err := a.ensureDeviceClean(dev); err != nil {
return errors.Wrapf(err, "clean device %s", dev)
}
}
mdDev := fmt.Sprintf("/dev/md/md%d", mdNum)
imsmDev := fmt.Sprintf("/dev/md/imsm%d", mdNum)
cmdImsm := fmt.Sprintf("%s --create %s --metadata=imsm --raid-devices=%d --run --force %s", MDADM_BIN, imsmDev, len(devs), strings.Join(devPaths, " "))
output, err := a.term.Run(cmdImsm)
if err != nil {
log.Errorf("mdadm create imsm raid %s failed, output: %v %s", level, output, err)
} else {
a.term.Run(fmt.Sprintf("%s --wait %s", MDADM_BIN, imsmDev))
time.Sleep(time.Second * 3)
}
args := []string{
"--create",
mdDev,
fmt.Sprintf("--level=%s", level),
fmt.Sprintf("--raid-devices=%d", len(devs)),
"--force",
"--run",
}
for _, dev := range devPaths {
args = append(args, dev)
}
args = append(args, "--assume-clean")
cmd := fmt.Sprintf("%s %s", MDADM_BIN, strings.Join(args, " "))
log.Infof("Building software RAID %s: %s", level, cmd)
output, err = a.term.Run(cmd)
if err != nil {
return errors.Wrapf(err, "mdadm create raid %s failed, output: %v", level, output)
}
cmd = fmt.Sprintf("%s --wait %s", MDADM_BIN, mdDev)
output, err = a.term.Run(cmd)
if err != nil {
log.Errorf("mdadm wait raid %s failed: %s", mdDev, output)
//return errors.Wrapf(err, "mdadm wait raid %s failed, output: %v", mdDev, output)
}
log.Infof("Successfully created software RAID %s: /dev/md/md%d, start sync block devs", level, mdNum)
for i := range devPaths {
flushCmd := fmt.Sprintf("blockdev --flushbufs %s", devPaths[i])
output, err = a.term.Run(flushCmd)
if err != nil {
return errors.Wrapf(err, "mdadm blockdev flushbufs %s failed, output: %v", devPaths[i], output)
}
}
output, err = a.term.Run("sync")
if err != nil {
return errors.Wrapf(err, "mdadm %s sync failed, output: %v", mdDev, output)
}
return nil
}
func (a *MdadmRaidAdapter) getNextMdNum() (int, error) {
cmd := "ls -1 /dev/md/ 2>/dev/null | grep -E '/dev/md/md[0-9]+$' || true"
output, err := a.term.Run(cmd)
if err != nil {
return 0, errors.Wrap(err, "list md devices")
}
usedNums := make(map[int]bool)
mdNumRe := regexp.MustCompile(`/dev/md/md(\d+)`)
for _, line := range output {
matches := mdNumRe.FindStringSubmatch(line)
if len(matches) > 1 {
if num, err := strconv.Atoi(matches[1]); err == nil {
usedNums[num] = true
}
}
}
for i := 0; i < 256; i++ {
if !usedNums[i] {
return i, nil
}
}
return 0, fmt.Errorf("no available md device number")
}
func (a *MdadmRaidAdapter) ensureDeviceClean(dev string) error {
cmd := fmt.Sprintf("%s --examine %s 2>/dev/null || true", MDADM_BIN, dev)
output, err := a.term.Run(cmd)
if err != nil {
return errors.Wrapf(err, "examine device %s", dev)
}
for _, line := range output {
if strings.Contains(line, "mdadm") || strings.Contains(line, "ARRAY") {
cmd := fmt.Sprintf("%s --zero-superblock --force %s", MDADM_BIN, dev)
_, err := a.term.Run(cmd)
if err != nil {
return errors.Wrapf(err, "zero superblock on %s", dev)
}
break
}
}
return nil
}

View File

@@ -39,29 +39,7 @@ import (
"yunion.io/x/onecloud/pkg/util/dbutils"
)
func InitDB(options *common_options.DBOptions) {
if options.DebugSqlchemy {
log.Warningf("debug Sqlchemy is turned on")
sqlchemy.DEBUG_SQLCHEMY = true
}
log.Infof("Registered SQL drivers: %s", strings.Join(sql.Drivers(), ", "))
consts.QueryOffsetOptimization = options.QueryOffsetOptimization
if options.HistoricalUniqueName {
consts.EnableHistoricalUniqueName()
} else {
consts.DisableHistoricalUniqueName()
}
if options.OpsLogMaxKeepMonths > 0 {
consts.SetSplitableMaxKeepMonths(options.OpsLogMaxKeepMonths)
}
if options.SplitableMaxDurationHours > 0 {
consts.SetSplitableMaxDurationHours(options.SplitableMaxDurationHours)
}
func InitDBConn(options *common_options.DBOptions) {
dialect, sqlStr, err := options.GetDBConnection()
if err != nil {
log.Fatalf("Invalid SqlConnection string: %s error: %v", options.SqlConnection, err)
@@ -103,8 +81,10 @@ func InitDB(options *common_options.DBOptions) {
dbConn.SetConnMaxLifetime(time.Duration(options.DbMaxWaitTimeoutSeconds) * time.Second)
// ConnMaxIdleTime should be half of ConnMaxLifetime
dbConn.SetConnMaxIdleTime(time.Duration(options.DbMaxWaitTimeoutSeconds/2) * time.Second)
}
dialect, sqlStr, err = options.GetClickhouseConnStr()
func InitClickhouseConn(options *common_options.DBOptions) {
dialect, sqlStr, err := options.GetClickhouseConnStr()
if err == nil {
// connect to clickcloud
// force convert sqlstr from clickhouse v2 to v1
@@ -126,6 +106,33 @@ func InitDB(options *common_options.DBOptions) {
consts.OpsLogWithClickhouse = true
}
}
}
func InitDB(options *common_options.DBOptions) {
if options.DebugSqlchemy {
log.Warningf("debug Sqlchemy is turned on")
sqlchemy.DEBUG_SQLCHEMY = true
}
log.Infof("Registered SQL drivers: %s", strings.Join(sql.Drivers(), ", "))
consts.QueryOffsetOptimization = options.QueryOffsetOptimization
if options.HistoricalUniqueName {
consts.EnableHistoricalUniqueName()
} else {
consts.DisableHistoricalUniqueName()
}
if options.OpsLogMaxKeepMonths > 0 {
consts.SetSplitableMaxKeepMonths(options.OpsLogMaxKeepMonths)
}
if options.SplitableMaxDurationHours > 0 {
consts.SetSplitableMaxDurationHours(options.SplitableMaxDurationHours)
}
InitDBConn(options)
InitClickhouseConn(options)
switch options.LockmanMethod {
case common_options.LockMethodInMemory, "":

View File

@@ -27,6 +27,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient/auth"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
"yunion.io/x/onecloud/pkg/util/ctx"
)
type domainCacheSyncWorker struct {
@@ -35,7 +36,7 @@ type domainCacheSyncWorker struct {
func (w *domainCacheSyncWorker) Run() {
log.Debugf("[domainCacheSyncWorker] Run domain cache sync worker ...")
err := syncDomains(context.Background(), w.ids)
err := syncDomains(ctx.CtxWithTime(), w.ids)
if err != nil {
log.Errorf("fail to syncDomains %s", err)
}

View File

@@ -1085,12 +1085,15 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
funcName := fmt.Sprintf("GetDetails%s", specCamel)
funcValue := modelValue.MethodByName(funcName)
log.Errorf("MethodByName %s", funcName)
if !funcValue.IsValid() || funcValue.IsNil() {
log.Errorf("MethodByName2 %s", funcName)
return nil, httperrors.NewSpecNotFoundError("%s %s %s not found", dispatcher.Keyword(), idStr, spec)
}
outs, err := callFunc(funcValue, funcName, params...)
if err != nil {
log.Errorf("MethodByName4 %s", funcName)
return nil, err
}
if len(outs) != 2 {
@@ -1100,6 +1103,7 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
resVal := outs[0]
errVal := outs[1].Interface()
if !gotypes.IsNil(errVal) {
log.Errorf("MethodByName3 %s", funcName)
return nil, errVal.(error)
} else {
if gotypes.IsNil(resVal.Interface()) {
@@ -1848,6 +1852,10 @@ func updateItem(manager IModelManager, item IModel, ctx context.Context, userCre
item.PostUpdate(ctx, userCred, query, data)
if err := manager.GetExtraHook().AfterPostUpdate(ctx, userCred, item, query, data); err != nil {
logclient.AddActionLogWithContext(ctx, item, logclient.ACT_POST_UPDATE_HOOK, err, userCred, false)
}
return getItemDetails(manager, item, ctx, userCred, query)
}

View File

@@ -28,6 +28,7 @@ import (
"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/logclient"
)
type DBJointModelDispatcher struct {
@@ -210,6 +211,9 @@ func attachItems(
return nil, httperrors.NewGeneralError(err)
}
item.PostCreate(ctx, userCred, nil, query, data)
if err := dispatcher.JointModelManager().GetExtraHook().AfterPostCreate(ctx, userCred, item.GetOwnerId(), item, query, data); err != nil {
logclient.AddActionLogWithContext(ctx, item, logclient.ACT_POST_CREATE_HOOK, err, userCred, false)
}
OpsLog.LogAttachEvent(ctx, master, slave, userCred, jsonutils.Marshal(item))
dispatcher.manager.OnCreateComplete(ctx, []IModel{item}, userCred, nil, query, []jsonutils.JSONObject{data})
@@ -322,5 +326,8 @@ func DetachJoint(ctx context.Context, userCred mcclient.TokenCredential, item IJ
if err == nil {
OpsLog.LogDetachEvent(ctx, JointMaster(item), JointSlave(item), userCred, item.GetShortDesc(ctx))
}
if err := item.GetModelManager().GetExtraHook().AfterPostDelete(ctx, userCred, item, nil); err != nil {
logclient.AddActionLogWithContext(ctx, item, logclient.ACT_POST_DELETE_HOOK, err, userCred, false)
}
return err
}

View File

@@ -0,0 +1,71 @@
// 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 db
import (
"context"
"fmt"
"net/http"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient/auth"
)
func AddHistoryDataCleanHandler(prefix string, app *appsrv.Application) {
prefix = fmt.Sprintf("%s/history-data-clean", prefix)
app.AddHandler2("POST", prefix, auth.Authenticate(historyDataCleanHandler), nil, "history_data_clean", nil)
}
func historyDataCleanHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
userCred := fetchUserCredential(ctx)
if !userCred.HasSystemAdminPrivilege() {
httperrors.ForbiddenError(ctx, w, "only sysadmin can clean history data")
return
}
input, err := appsrv.FetchJSON(r)
if err != nil {
httperrors.InputParameterError(ctx, w, "FetchJSON")
return
}
date := time.Now().AddDate(0, -1, 0)
if !gotypes.IsNil(input) && input.Contains("day") {
day, _ := input.Int("day")
date = time.Now().AddDate(0, 0, int(day)*-1)
}
go func() {
for _, manager := range globalTables {
if hM, ok := manager.(IHistoryDataManager); ok {
start := time.Now()
cnt, err := hM.HistoryDataClean(ctx, date)
if err != nil {
log.Errorf("clean %s data error: %v", manager.Keyword(), err)
continue
}
log.Debugf("clean %d %s history data cost %s", cnt, manager.Keyword(), time.Now().Sub(start).Round(time.Second))
}
}
}()
appsrv.SendJSON(w, jsonutils.Marshal(map[string]string{"status": "ok"}))
}
type IHistoryDataManager interface {
HistoryDataClean(ctx context.Context, timeBefor time.Time) (int, error)
}

View File

@@ -152,6 +152,7 @@ type IModelManager interface {
type IModelManagerExtraHook interface {
AfterPostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, model IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) error
AfterPostUpdate(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) error
AfterPostDelete(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject) error
}

View File

@@ -16,8 +16,11 @@ package db
import (
"context"
"database/sql"
"fmt"
"reflect"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -27,6 +30,7 @@ import (
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
@@ -255,3 +259,67 @@ func (model *SJointResourceBase) ValidateUpdateData(
}
return input, nil
}
func (manager *SJointResourceBaseManager) HistoryDataClean(ctx context.Context, timeBefor time.Time) (int, error) {
q := manager.RawQuery("row_id").IsTrue("deleted").LE("deleted_at", timeBefor)
rows, err := q.Rows()
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return 0, nil
}
return 0, errors.Wrap(err, "Query")
}
defer rows.Close()
ids := []string{}
for rows.Next() {
var id string
err := rows.Scan(&id)
if err != nil {
return 0, errors.Wrap(err, "rows.Scan")
}
ids = append(ids, id)
}
var purge = func(ids []string) error {
vars := []interface{}{}
placeholders := make([]string, len(ids))
for i := range placeholders {
placeholders[i] = "?"
vars = append(vars, ids[i])
}
placeholder := strings.Join(placeholders, ",")
sql := fmt.Sprintf(
"delete from %s where row_id in (%s)",
manager.TableSpec().Name(), placeholder,
)
lockman.LockRawObject(ctx, manager.Keyword(), "purge")
defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "purge")
_, err = sqlchemy.GetDB().Exec(
sql, vars...,
)
if err != nil {
return errors.Wrapf(err, strings.ReplaceAll(sql, "?", "%s"), vars...)
}
return nil
}
var splitByLen = func(data []string, splitLen int) [][]string {
var result [][]string
for i := 0; i < len(data); i += splitLen {
end := i + splitLen
if end > len(data) {
end = len(data)
}
result = append(result, data[i:end])
}
return result
}
idsArr := splitByLen(ids, 100)
for i := range idsArr {
err = purge(idsArr[i])
if err != nil {
return 0, err
}
}
return len(ids), nil
}

View File

@@ -344,6 +344,9 @@ func (manager *SMetadataManager) metadataBaseFilter(q *sqlchemy.SQuery, input ap
if len(input.KeyLike) > 0 {
q = q.Contains("key", input.KeyLike)
}
if len(input.ValueLike) > 0 {
q = q.Contains("value", input.ValueLike)
}
if len(input.Key) > 0 {
q = q.In("key", input.Key)
}

View File

@@ -880,3 +880,7 @@ func (e SEmptyExtraHook) AfterPostCreate(ctx context.Context, userCred mcclient.
func (e SEmptyExtraHook) AfterPostDelete(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject) error {
return nil
}
func (e SEmptyExtraHook) AfterPostUpdate(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
return nil
}

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