Compare commits

...

178 Commits

Author SHA1 Message Date
屈轩
84b0f1075a fix(region): optimized cached image list (#23155) 2025-08-22 15:44:44 +08:00
Zexi Li
66587b4e52 fix(region): update the image status to save_fail when OnImageSavedFailed (#23140) 2025-08-21 18:12:24 +08:00
wanyaoqi
206a4b5b19 fix(scheduler): add session usage timeout options (#23143) 2025-08-21 18:10:51 +08:00
屈轩
90f479bafc fix(region): dns zone registrar charset (#23150) 2025-08-21 11:34:42 +08:00
屈轩
1df9c11501 fix(region): add change_config status for aigateway (#23138) 2025-08-20 17:05:34 +08:00
屈轩
79561cd8ef fix(region): avoid update guest disable_delete attribute error when host id is empty (#23135) 2025-08-20 16:21:24 +08:00
Zexi Li
435344ee1d fix(baremetal): update the grub auto configuration to fix the aarch64 disk boot (#23132) 2025-08-20 15:11:31 +08:00
屈轩
15d079f966 fix(region): sync lb eip (#23125) 2025-08-20 14:13:59 +08:00
Zexi Li
90aef7ef0c feat(region): fix ISO size display (#23128)
SGuestcdrom.Size is Byte, not MB

Co-authored-by: happygame <happygame1024@gmail.com>
2025-08-20 12:08:23 +08:00
Zexi Li
390feec8ec fix(baremetal-agent): error occurred when removing logical volumes on the arm64 host (#23122) 2025-08-20 12:00:19 +08:00
屈轩
911694c9fe fix(region): sync dns zone ns info (#23116) 2025-08-19 17:28:32 +08:00
屈轩
73199002c3 fix(region): sync eip associate resource (#23112) 2025-08-19 14:54:49 +08:00
屈轩
0dc21f1b69 fix(region): allow update vpc network cidr (#23110) 2025-08-19 14:38:53 +08:00
屈轩
f593f7f660 fix(region): add storage filter for snapshot (#23108) 2025-08-18 14:57:55 +08:00
wanyaoqi
046a6ac6cb fix(host): persistent ceph config for qemu connection (#23089) 2025-08-16 14:47:00 +08:00
Jian Qiu
7733907f9b fix: webconsole skip refererer check by default (#23092)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-16 14:45:45 +08:00
wanyaoqi
b43953fc29 fix(vpcagent): dhcp enable default gateway on default network (#23097) 2025-08-16 14:44:39 +08:00
屈轩
5f708fe816 fix(scheduledtask): force sync account (#23085) 2025-08-14 19:36:10 +08:00
Zexi Li
69056db01a fix(region): filter host by ips (#23083) 2025-08-14 18:35:28 +08:00
wanyaoqi
d48bab9ddd Automated cherry pick of #23072: fix(host): cephutil and nbd ipv6 compat (#23073)
* fix(region,host,host-image): host-image and qemu-nbd compat ipv6

* fix(host,host-deployer): cephutils add ipv6 compat
2025-08-14 18:34:44 +08:00
屈轩
d10a322aec fix(region): server snapshot policy (#23078) 2025-08-14 10:42:35 +08:00
屈轩
f694fead2e fix(region): dns record policy type (#23076) 2025-08-13 17:49:22 +08:00
屈轩
d4b04f3f2e fix(region): The eip displays the internal ip address of the virtual machine (#23068) 2025-08-12 09:59:08 +08:00
wanyaoqi
6d633b5647 feat(host): container cpufreq realtime simulate (#23051) 2025-08-11 10:24:28 +08:00
Jian Qiu
b7870e0453 fix: ipv6 compatibility issues fixes 20250809 (#23061)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-10 10:07:50 +08:00
Jian Qiu
4eb90fc442 fix: task obj_type and object nullable and default empty (#23059)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-10 08:46:59 +08:00
wanyaoqi
35093fb7a7 fix(host): lvm guest reload disk before delete snapshot (#23053) 2025-08-08 20:57:24 +08:00
Jian Qiu
9a3871014e fix: filter guest by multiple ips with exact match (#23039)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-08 17:56:10 +08:00
Zexi Li
b4e3d17178 fix(host): 修复 loop 设备被其它进程创建而导致分配失败的问题 (#23041) 2025-08-08 17:51:20 +08:00
Jian Qiu
4fa4cadb69 fix: host metrics tag add hypervisor (#23034)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-07 22:26:11 +08:00
Jian Qiu
d0ec6885d6 fix: ipv6-only mode compatibility fixes (#23031)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-06 22:02:08 +08:00
屈轩
634bdf7b90 fix(region): support lb health check sync status (#23029) 2025-08-06 17:37:44 +08:00
屈轩
117efad40d fix(region): disk update tag (#23025) 2025-08-06 15:52:11 +08:00
Jian Qiu
35aaafc09f fix: always update hostname for rhel-like os (#23017)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-06 01:06:23 +08:00
wanyaoqi
421a3e9e87 fix(region,host): host nic add default secret ipv4 address (#23015) 2025-08-02 23:07:07 +08:00
Jian Qiu
fbefeae06f fix: host network ipv6 support (#23013)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-02 12:15:07 +08:00
Zexi Li
ef04ac2dac feat(region): list gpu by index and device_minor (#23012) 2025-08-01 18:46:22 +08:00
屈轩
52d54cfc00 fix(region): support lb health check (#23009) 2025-08-01 18:38:41 +08:00
Zexi Li
33936c937c feat(region,host): upload index and minor info of a nvidia GPU (#23005) 2025-08-01 10:36:11 +08:00
Zexi Li
3b2632fb26 feat(region,host): auto create the file or dir of hostPath (#23001) 2025-07-31 14:01:06 +08:00
屈轩
412413c2f5 fix(region): cloudflare redirect pool (#22998) 2025-07-30 20:17:44 +08:00
屈轩
0970725598 fix(region): cloudflare lb backend operation (#22996) 2025-07-30 19:02:30 +08:00
屈轩
1012991176 fix(region): support cloudflare lb (#22993) 2025-07-30 14:51:48 +08:00
Jian Qiu
120725c311 fix: unify guest sync status and upload status procedure (#22983)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-30 10:38:11 +08:00
Jian Qiu
ea88b81f3f fix: inconsist checksum between image and its same format subimage (#22987)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-30 01:44:10 +08:00
wanyaoqi
c26ad31c8d fix(host,glance): only target qcow2 set cluster size on image convert (#22979) 2025-07-30 00:43:15 +08:00
Jian Qiu
4b0f3b4dd1 fix: glance converts all queued subimages, regardless of format (#22971)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-29 10:26:09 +08:00
wanyaoqi
5a3bc2acb6 fix(host): set qemuimg convert cluster_size 64k on compat image (#22965) 2025-07-29 00:01:10 +08:00
Jian Qiu
4080c2ddfb fix: set default worker parameter (#22958)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-28 14:12:18 +08:00
Jian Qiu
10a2c41d37 fix: host clean image with regards of container image deps (#22955)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-26 08:50:17 +08:00
wanyaoqi
a196b19b0c fix(region): iso boot do not check boot mode (#22950) 2025-07-26 02:26:55 +08:00
wanyaoqi
50519e9099 fix(host): host init no numa node (#22945) 2025-07-25 00:32:50 +08:00
屈轩
44c487eeb1 fix(region): init guest secgroup (#22941) 2025-07-24 17:15:56 +08:00
Zexi Li
1a7327c244 feat(host): 保存容器 volume 镜像时设置 min_disk 大小 (#22932) 2025-07-23 20:24:38 +08:00
屈轩
f5839b560e fix(region): add guest billing type for disk (#22936) 2025-07-23 18:53:48 +08:00
wanyaoqi
3e0231ae31 fix(region): ipv6 change ipaddr (#22924) 2025-07-23 09:29:18 +08:00
屈轩
003de57c91 fix(region): host order (#22927) 2025-07-22 15:20:01 +08:00
屈轩
ddb64eaf2e fix(region): vendor update (#22920) 2025-07-21 17:33:36 +08:00
屈轩
8248bcd67e fix(region): support ssl delete (#22912) 2025-07-16 19:55:21 +08:00
Jian Qiu
39a3918bb8 fix: dhcpv6 client id change by slice overwritten (#22906)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-16 16:19:27 +08:00
屈轩
47d9f2f434 fix(region): add is expired for certificate (#22908) 2025-07-16 15:36:00 +08:00
Zexi Li
5bdf4d1d30 fix(scheduler): netinterface cache is not informed (#22901) 2025-07-15 19:59:43 +08:00
Jian Qiu
3e5e6e175c fix: deploy ipv6 scripts fixes (#22900)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-15 18:59:42 +08:00
wanyaoqi
42e58b4996 feat(region,host-deployer): ipv6 only guest support (#22897) 2025-07-15 16:21:49 +08:00
wanyaoqi
a071cd2287 fix(host): check storage id is correct on src migrate prepare (#22892)
correct disk storage id on dest migrate prepare
2025-07-15 16:12:57 +08:00
屈轩
66748dbfcd fix(region): ssl create with zone info (#22889) 2025-07-14 18:32:15 +08:00
屈轩
d27c9be330 fix(region): ssl certificate create (#22887) 2025-07-14 16:06:22 +08:00
Jian Qiu
ea8f6c8221 fix: host metrics error for missing ip (#22883)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-12 18:00:46 +08:00
Jian Qiu
c6f84dfa94 fix: dhcpv6 support phase 3 (#22881)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-12 12:10:31 +08:00
屈轩
382c2bc6cd fix(region): add sort for host (#22877) 2025-07-11 19:08:59 +08:00
Zexi Li
598f68a7e9 fix(region): allow stopping the container in probe_failed status (#22873) 2025-07-11 10:42:07 +08:00
Jian Qiu
967d52f874 fix: host no default routes due to empty ipv6 addr (#22871)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-10 22:34:07 +08:00
wanyaoqi
d1dcfc9ed3 fix(region): do not set guest to resuce status on guest running (#22867) 2025-07-10 22:11:11 +08:00
屈轩
ebd7298d0d fix(region): 修复本地到期释放功能和资源同步冲突 (#22860) 2025-07-10 19:37:58 +08:00
Jian Qiu
992c5f498e fix: dhcpv6 support, phase 2 (#22852)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-09 14:41:34 +08:00
wanyaoqi
570b371290 fix(host): add check mem dev is null on guest setup (#22848) 2025-07-09 14:16:08 +08:00
屈轩
0b6a23e2fb fix(region): 避免删除虚拟机时,未能正常删除后挂载的磁盘 (#22841) 2025-07-07 14:46:10 +08:00
Zexi Li
da501a34d8 feat(host): support pod post cleanup configuration (#22839) 2025-07-04 17:12:22 +08:00
屈轩
34fd2c5ca4 fix(region): create disk with tags (#22833) 2025-07-04 17:08:05 +08:00
屈轩
afe4afe095 fix(region): vendor update (#22828) 2025-07-03 15:16:35 +08:00
屈轩
9121720e21 fix: compatible with other os netutils (#22826) 2025-07-03 15:01:44 +08:00
Jian Qiu
b527b1ad6b fix: dhcpv6 support, initial support (#22823)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-03 14:37:17 +08:00
屈轩
bdcbc15cf5 fix(region): vendor update for sync mongodb ip addr (#22817) 2025-07-03 05:33:12 +08:00
wanyaoqi
397f165d37 fix(host): set arm guest max mems to host mem (#22814) 2025-07-03 05:32:20 +08:00
wanyaoqi
f29a1d8567 fix(host): enable qemu cap detect (#22799) 2025-07-03 05:30:45 +08:00
wanyaoqi
47a9fa3505 fix(region): host calculate set mem_cmt_bound 1 on host enable hugepage (#22810) 2025-07-03 05:29:20 +08:00
wanyaoqi
7df2a43d22 fix(host): qemuimg convert add cluster_size (#22792) 2025-07-03 05:27:35 +08:00
屈轩
826f4df8f7 fix(region): vendor update (#22806) 2025-07-02 21:01:57 +08:00
屈轩
7cee63907b fix(esxi-agent): avoid esxi cache image error (#22803) 2025-07-02 19:25:32 +08:00
Zexi Li
0e50049ab1 fix(host): adjuest max loop device count to 512 (#22788) 2025-07-01 15:25:26 +08:00
屈轩
975f4ed864 fix(region): add ai gateway (#22785) 2025-06-27 22:38:21 +08:00
屈轩
5643619a7c fix(region): vendor update for cdn attribute (#22778) 2025-06-24 17:43:09 +08:00
屈轩
3e35ea56df fix(notify): support dingtalk robot sign (#22767) 2025-06-23 16:59:40 +08:00
屈轩
1ba251f053 fix(cloudmon): cloudpods collect metric interval (#22764) 2025-06-23 16:17:24 +08:00
屈轩
25d1b699c9 fix(region): vendor update for aliyun alb and nlb (#22762) 2025-06-23 10:30:26 +08:00
屈轩
19143c134a fix(region): sync remove backend group (#22759) 2025-06-20 19:38:27 +08:00
Zexi Li
27a8e098d6 feat(region,host): support port mapping rule (#22756) 2025-06-20 19:17:04 +08:00
屈轩
cb12c9fe1c fix(region): support skip sync server by tag value (#22754) 2025-06-20 18:40:35 +08:00
屈轩
fc2603ce4d fix(region): vendor update (#22750) 2025-06-20 18:12:44 +08:00
Jian Qiu
d9c5d5657e fix: task filter by owner sql revisit (#22746)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-06-20 16:06:27 +08:00
屈轩
b6b5c6041b fix(region): ssl certificate purge (#22743) 2025-06-19 17:53:10 +08:00
Jian Qiu
c1345560bb fix: use goid to identify differnt goroutine (#22740)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-06-19 14:50:47 +08:00
屈轩
8448395003 fix(region): waf rule create (#22738) 2025-06-18 20:06:16 +08:00
Zexi Li
5058f02538 Automated cherry pick of #22729: Monitor worker alert (#22730)
* fix(monitor): GetMetricMeasurement 接口只查询过去30m的数据

避免数据过多导致 victoria-metrics 报错

* fix(monitor): wildchar of alert group by field
2025-06-18 14:25:43 +08:00
屈轩
31b766a7d6 fix(region): lb listener rule associate backend group (#22734) 2025-06-18 14:15:01 +08:00
Zexi Li
650acf4ea9 fix: panic when there is no secondary IP on the host. (#22726)
Co-authored-by: glzjin <glzjin2015@gmail.com>
2025-06-17 11:15:01 +08:00
屈轩
1322a21445 fix(region): vendor update (#22725) 2025-06-16 20:07:32 +08:00
屈轩
fb26af0566 fix(region): vendor update for lb multi eip sync (#22720) 2025-06-16 17:17:27 +08:00
wanyaoqi
af0559ac35 fix(region,host): add auto merge snapshots options, preallocation options (#22713) 2025-06-13 15:19:50 +08:00
Zexi Li
72f68dd541 fix(host): dirty shutdown pod is not auto started (#22705) 2025-06-10 10:18:31 +08:00
Jian Qiu
ae09aa3c82 fix: remove cgo deps for ioctl (#22701)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-06-07 08:42:14 +08:00
屈轩
b677cef407 fix(region): vendor update (#22698) 2025-06-06 19:22:45 +08:00
屈轩
9ae9879c56 fix(region): enable cloud dns record (#22695) 2025-06-06 18:32:01 +08:00
Jian Qiu
2f8c719f03 fix: http perf stats monitor (#22689)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-06-06 18:12:16 +08:00
Zexi Li
712059cedb fix(host): marshal update status input inside error (#22692) 2025-06-06 17:27:51 +08:00
屈轩
4bbc651732 fix(region): waf rule enable disable (#22688) 2025-06-06 14:53:25 +08:00
Jian Qiu
24e525926b fix: update vendor release/4.0 20250606 (#22685)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-06-06 14:23:50 +08:00
wanyaoqi
119140fe93 fix(host): pass decoded userdata to host-deployer (#22681) 2025-06-05 23:50:51 +08:00
屈轩
1b45c3d174 fix(region): vendor update (#22678) 2025-06-05 19:28:02 +08:00
Zexi Li
9675f1d4e4 fix(host): change mount context timeout to 30s (#22676) 2025-06-05 18:40:30 +08:00
Jian Qiu
e7e13552d9 fix: cloudmon high cpu loads for bucket probing (#22658)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-06-05 17:51:26 +08:00
屈轩
91ad8f038e fix(region): vendor update (#22670) 2025-06-04 17:37:36 +08:00
Zexi Li
c5e70ed1aa fix(scheduler): wrong sort order of instance group selection (#22666) 2025-06-04 14:27:30 +08:00
Zexi Li
cdd46c490d feat(host): containerd snapshot rootfs service (#22661) 2025-06-04 11:00:42 +08:00
Zexi Li
1d69a15372 fix(host): sync container crash status (#22655) 2025-06-03 20:16:12 +08:00
Zexi Li
5237beb197 fix(host): retry stopping container forcibly (#22650) 2025-06-03 17:12:07 +08:00
Zexi Li
ffdf7a3a6e fix(host): losetup package initialization order (#22652) 2025-06-03 13:39:30 +08:00
Jian Qiu
c835c87afc fix: update vendor to fix keystone user join project not found (#22645)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-31 18:47:54 +08:00
Jian Qiu
58e2ea41af fix: disk statu sync recover (#22633)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-31 09:04:25 +08:00
Jian Qiu
addbe7f9ea fix: bucket perform mon random string generation consume high cpu load (#22639)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-31 09:03:21 +08:00
wanyaoqi
618722bc16 fix(host): change log level to debug on get numa node faild (#22641) 2025-05-31 09:01:55 +08:00
Zexi Li
fd0c96e6f9 refactor(region,host): container status management (#22635) 2025-05-30 17:48:42 +08:00
wanyaoqi
5a17a9e37b feat(host-deployer): deploy vlan subinterface on baremetal hypervisor (#22629)
- host-deployer add deploy vlan subinterface on baremetal hypervisor
- fix baremetal-agent cache image parse input data
2025-05-30 10:32:01 +08:00
wanyaoqi
44ed13473a feat(region,host,host-deployer): support set uefi boot order (#22560) 2025-05-30 10:31:03 +08:00
wanyaoqi
d8b00188a0 feat(region,host): qga deploy network config on attach nics (#22548) 2025-05-30 10:29:48 +08:00
屈轩
0b61ca0432 fix(region): vendor update (#22624) 2025-05-29 11:23:02 +08:00
屈轩
b9a9151555 fix(region): secgroup rule filter (#22619) 2025-05-28 18:38:37 +08:00
wanyaoqi
17db7be134 fix(host): qemu extra params format (#22609) 2025-05-27 13:34:48 +08:00
屈轩
892431d5b9 fix(region): update qcloud storage type (#22615) 2025-05-27 12:44:12 +08:00
屈轩
3d36c293e5 fix(region): add region driver for cloudflare (#22606) 2025-05-26 16:22:25 +08:00
Jian Qiu
3ff50f0d11 fix: tar ignore error revisit (#22604)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-26 12:35:10 +08:00
Jian Qiu
6144325daf fix: container save image with leading prefix (#22602)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-26 12:34:48 +08:00
Zexi Li
bf3b83870c fix: ignore init loop device error (#22601)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-26 11:36:09 +08:00
wanyaoqi
62b7eea828 fix(host): check min_free_kbytes size is enough (#22592) 2025-05-24 01:11:09 +08:00
Zexi Li
4e07811e2f fix(monitor): not filter status tag key (#22596) 2025-05-23 09:59:43 +08:00
Zexi Li
f819e021b3 feat(host): loop device manager (#22590) 2025-05-22 13:24:24 +08:00
屈轩
3224eac821 fix(cloudmon): add vm_ip metric for vm (#22586) 2025-05-22 10:53:59 +08:00
屈轩
a1fce125da fix(cloudmon): vm metrics with ips (#22583) 2025-05-22 10:41:11 +08:00
屈轩
aa0a6b58d3 fix(region): add filter for secgroup rule (#22580) 2025-05-21 19:27:29 +08:00
屈轩
0c9a44e279 fix(region): add account info for sec rules (#22577) 2025-05-21 18:40:18 +08:00
Zexi Li
4dd92825a8 fix(host): ignore internal stopped event of primary container (#22574) 2025-05-21 16:23:17 +08:00
屈轩
30a319fe5e fix(region): allow create public server sku (#22571) 2025-05-21 14:43:28 +08:00
Zexi Li
faf35a6879 fix(host): status of stopping primary container (#22568) 2025-05-21 12:23:33 +08:00
屈轩
4520b54a5b fix(region): init aliyun storage medium type (#22564) 2025-05-20 21:48:33 +08:00
wanyaoqi
fa53aea075 fix error when create vm with ceph disk (#22561)
Co-authored-by: liangkaijun <liangkaijun52013@gmail.com>
2025-05-20 21:28:00 +08:00
Jian Qiu
36b5532b04 feature: monitor bucket formance and resource status (#22553)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-19 22:28:32 +08:00
Zexi Li
01ab43941e fix(host): clean loop device before deleting (#22558) 2025-05-19 19:47:28 +08:00
屈轩
249569be9f fix(region): user sync with ctx (#22555) 2025-05-19 18:09:26 +08:00
Jian Qiu
db0b275772 fix: host files not initialized when host reboot (#22551)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-19 01:57:58 +08:00
wanyaoqi
e6bb86c934 fix: vendor update 2505013 (#22521) 2025-05-19 01:50:32 +08:00
屈轩
c53f707089 fix(region): vendor update (#22544) 2025-05-16 11:19:49 +08:00
屈轩
ef36176130 fix(region): guest disk iops (#22542) 2025-05-15 15:46:12 +08:00
屈轩
edd11ea1cd fix(region): show correct disk iops (#22538) 2025-05-15 12:48:51 +08:00
屈轩
4ad7d635bc fix(region): change disk billing type (#22533) 2025-05-15 11:48:26 +08:00
Zexi Li
18604b46b1 feat(region,host): change ownership of post overlay merged dir (#22525) 2025-05-13 19:52:52 +08:00
屈轩
4609c543c9 fix(region): add dns brand (#22523) 2025-05-13 16:30:57 +08:00
屈轩
779559dbdc fix(region): add proxied for dns record (#22514) 2025-05-12 17:52:46 +08:00
Zexi Li
27c6c82b82 fix(monitor): return measurements info from db directly (#22512) 2025-05-12 17:17:36 +08:00
屈轩
fa99905bf6 fix(common): avoid empty context (#22509) 2025-05-12 16:21:18 +08:00
屈轩
608e4edb4e fix(region): add cloudflare const (#22507) 2025-05-12 14:10:58 +08:00
屈轩
43c646b537 fix(notify): support notify with robotids (#22503) 2025-05-09 21:23:07 +08:00
屈轩
ad798d7bbe fix(notify): optimized notify error msg (#22501) 2025-05-09 17:35:17 +08:00
屈轩
238458066a fix(region): vendor update (#22498) 2025-05-09 14:56:01 +08:00
屈轩
90a8b10401 fix(common): obj id cache (#22495) 2025-05-09 14:50:24 +08:00
Jian Qiu
46195f72ee fix: hostfile delete validation (#22493)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-08 23:50:06 +08:00
屈轩
05829a225a fix(region): vendor update (#22491) 2025-05-08 18:36:31 +08:00
屈轩
f0858ce4d2 fix(common): policy tag filter cache (#22485) 2025-05-08 15:56:57 +08:00
Jian Qiu
cc3477415d fix: host files support (#22481)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-05-07 11:28:47 +08:00
1324 changed files with 90414 additions and 14612 deletions

View File

@@ -84,9 +84,6 @@ vet:
# cmd/esxi-agent: prepare_dir
# CGO_ENABLED=0 $(GO_BUILD) -o $(BIN_DIR)/$(shell basename $@) $(REPO_PREFIX)/$@
cmd/host: prepare_dir
CGO_ENABLED=1 $(GO_BUILD) -o $(BIN_DIR)/$(shell basename $@) $(REPO_PREFIX)/$@
cmd/%: prepare_dir
CGO_ENABLED=0 $(GO_BUILD) -o $(BIN_DIR)/$(shell basename $@) $(REPO_PREFIX)/$@
@@ -277,12 +274,12 @@ dep:
@echo "$$depDeprecated"
@$(MAKE) mod
RELEASE_BRANCH:=master
RELEASE_BRANCH:=release/4.0
GOPROXY ?= direct
mod:
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get -d yunion.io/x/cloudmux@$(RELEASE_BRANCH)
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get -d $(patsubst %,%@master,$(shell GO111MODULE=on go mod edit -print | sed -n -e 's|.*\(yunion.io/x/[a-z].*\) v.*|\1|p' | grep -v '/cloudmux$$'))
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get yunion.io/x/cloudmux@$(RELEASE_BRANCH)
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get $(patsubst %,%@master,$(shell GO111MODULE=on go mod edit -print | sed -n -e 's|.*\(yunion.io/x/[a-z].*\) v.*|\1|p' | grep -v '/cloudmux$$'))
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go mod tidy
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go mod vendor -v

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.10
MAINTAINER "Yaoqi Wan wanyaoqi@yunionyun.com"

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 compute
import (
"yunion.io/x/onecloud/cmd/climc/shell"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/mcclient/options"
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
)
func init() {
cmd := shell.NewResourceCmd(&modules.AiGateways).WithKeyword("ai-gateway")
cmd.List(&compute.AiGatewayListOptions{})
cmd.Delete(&options.BaseIdOptions{})
cmd.Create(&compute.AiGatewayCreateOptions{})
cmd.Perform("syncstatus", &options.BaseIdOptions{})
cmd.Perform("change-config", &compute.AiGatewayChangeConfigOptions{})
}

View File

@@ -19,178 +19,71 @@ import (
"io"
"os"
"yunion.io/x/cloudmux/pkg/multicloud/objectstore"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/util/fileutils"
"yunion.io/x/pkg/util/printutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/mcclient"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/mcclient/options"
computeoptions "yunion.io/x/onecloud/pkg/mcclient/options/compute"
)
func init() {
type BucketListOptions struct {
options.BaseListOptions
DistinctField string `help:"query specified distinct field"`
}
R(&BucketListOptions{}, "bucket-list", "List all buckets", func(s *mcclient.ClientSession, args *BucketListOptions) error {
params, err := options.ListStructToParams(args)
if err != nil {
return err
}
if len(args.DistinctField) > 0 {
params.Add(jsonutils.NewString(args.DistinctField), "extra_field")
result, err := modules.Buckets.Get(s, "distinct-field", params)
if err != nil {
return err
}
fmt.Println(result)
return nil
}
result, err := modules.Buckets.List(s, params)
if err != nil {
return err
}
printList(result, modules.Buckets.GetColumns(s))
return nil
})
type BucketIdOptions struct {
ID string `help:"ID or name of bucket"`
}
R(&BucketIdOptions{}, "bucket-show", "Id details of bucket", func(s *mcclient.ClientSession, args *BucketIdOptions) error {
result, err := modules.Buckets.Get(s, args.ID, nil)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&BucketIdOptions{}, "bucket-syncstatus", "Sync bucket statust", func(s *mcclient.ClientSession, args *BucketIdOptions) error {
result, err := modules.Buckets.PerformAction(s, args.ID, "syncstatus", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketUpdateOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
Name string `help:"new name of bucket" json:"name"`
Desc string `help:"Description of bucket" json:"description" token:"desc"`
}
R(&BucketUpdateOptions{}, "bucket-update", "update bucket", func(s *mcclient.ClientSession, args *BucketUpdateOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Buckets.Update(s, args.ID, params)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketDeleteOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketDeleteOptions{}, "bucket-delete", "delete bucket", func(s *mcclient.ClientSession, args *BucketDeleteOptions) error {
result, err := modules.Buckets.Delete(s, args.ID, nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketCreateOptions struct {
NAME string `help:"name of bucket" json:"name"`
CLOUDREGION string `help:"location of bucket" json:"cloudregion"`
MANAGER string `help:"cloud provider" json:"manager"`
StorageClass string `help:"bucket storage class"`
Acl string `help:"bucket ACL"`
}
R(&BucketCreateOptions{}, "bucket-create", "Create a bucket", func(s *mcclient.ClientSession, args *BucketCreateOptions) error {
params, err := options.StructToParams(args)
if err != nil {
return err
}
result, err := modules.Buckets.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketListObjectsOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
Prefix string `help:"List objects with prefix"`
Recursive bool `help:"List objects recursively"`
Limit int `help:"maximal items per request"`
PagingMarker string `help:"paging marker"`
}
R(&BucketListObjectsOptions{}, "bucket-object-list", "List objects in a bucket", func(s *mcclient.ClientSession, args *BucketListObjectsOptions) error {
params, err := options.StructToParams(args)
if err != nil {
return err
}
result, err := modules.Buckets.GetSpecific(s, args.ID, "objects", params)
if err != nil {
return err
}
cmd := shell.NewResourceCmd(&modules.Buckets)
cmd.List(&computeoptions.BucketListOptions{})
cmd.GetProperty(&computeoptions.BucketGetPropertyOptions{})
cmd.Show(&computeoptions.BucketIdOptions{})
cmd.Perform("syncstatus", &computeoptions.BucketIdOptions{})
cmd.Update(&computeoptions.BucketUpdateOptions{})
cmd.Delete(&computeoptions.BucketIdOptions{})
cmd.Create(&computeoptions.BucketCreateOptions{})
cmd.GetWithCustomOptionShow("objects", func(data jsonutils.JSONObject, args shell.IGetOpt) {
listResult := printutils.ListResult{}
err = result.Unmarshal(&listResult)
err := data.Unmarshal(&listResult)
if err != nil {
return err
return
}
printList(&listResult, []string{})
return nil
})
}, &computeoptions.BucketListObjectsOptions{})
cmd.Perform("delete", &computeoptions.BucketDeleteObjectsOptions{})
cmd.Perform("makedir", &computeoptions.BucketMakeDirOptions{})
cmd.Perform("temp-url", &computeoptions.BucketPresignObjectsOptions{})
cmd.Perform("acl", &computeoptions.BucketSetAclOptions{})
cmd.GetWithCustomOptionShow("acl", func(data jsonutils.JSONObject, args shell.IGetOpt) {
printObject(data)
}, &computeoptions.BucketAclOptions{})
cmd.Perform("sync", &computeoptions.BucketSyncOptions{})
cmd.Perform("limit", &computeoptions.BucketLimitOptions{})
cmd.GetWithCustomOptionShow("access-info", func(data jsonutils.JSONObject, args shell.IGetOpt) {
printObject(data)
}, &computeoptions.BucketAccessInfoOptions{})
cmd.Perform("metadata", &computeoptions.BucketSetMetadataOptions{})
cmd.Perform("set-website", &computeoptions.BucketSetWebsiteOption{})
cmd.GetWithCustomOptionShow("website", func(data jsonutils.JSONObject, args shell.IGetOpt) {
printObject(data)
}, &computeoptions.BucketGetWebsiteConfOption{})
cmd.Perform("delete-website", &computeoptions.BucketDeleteWebsiteConfOption{})
cmd.Perform("set-cors", &computeoptions.BucketSetCorsOption{})
cmd.GetWithCustomOptionShow("cors", func(data jsonutils.JSONObject, args shell.IGetOpt) {
printObject(data)
}, &computeoptions.BucketGetCorsOption{})
cmd.Perform("delete-cors", &computeoptions.BucketDeleteCorsOption{})
cmd.Perform("set-referer", &computeoptions.BucketSetRefererOption{})
cmd.GetWithCustomOptionShow("referer", func(data jsonutils.JSONObject, args shell.IGetOpt) {
printObject(data)
}, &computeoptions.BucketGetRefererOption{})
cmd.GetWithCustomOptionShow("cdn-domain", func(data jsonutils.JSONObject, args shell.IGetOpt) {
printObject(data)
}, &computeoptions.BucketGetCdnDomainOption{})
cmd.GetWithCustomOptionShow("policy", func(data jsonutils.JSONObject, args shell.IGetOpt) {
printObject(data)
}, &computeoptions.BucketGetPolicyOption{})
cmd.Perform("set-policy", &computeoptions.BucketSetPolicyOption{})
cmd.Perform("delete-policy", &computeoptions.BucketDeletePolicyOption{})
type BucketDeleteObjectsOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
KEYS []string `help:"List of objects to delete"`
}
R(&BucketDeleteObjectsOptions{}, "bucket-object-delete", "Delete objects in a bucket", func(s *mcclient.ClientSession, args *BucketDeleteObjectsOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Buckets.PerformAction(s, args.ID, "delete", params)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketMakeDirOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
KEY string `help:"DIR key to create"`
}
R(&BucketMakeDirOptions{}, "bucket-mkdir", "Mkdir in a bucket", func(s *mcclient.ClientSession, args *BucketMakeDirOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Buckets.PerformAction(s, args.ID, "makedir", params)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketUploadObjectsOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
KEY string `help:"Key of object to upload"`
Path string `help:"Path to file to upload" required:"true"`
ContentLength int64 `help:"Content lenght (bytes)" default:"-1"`
StorageClass string `help:"storage CLass"`
Acl string `help:"object acl." choices:"private|public-read|public-read-write"`
objectstore.ObjectHeaderOptions
}
R(&BucketUploadObjectsOptions{}, "bucket-object-upload", "Upload an object into a bucket", func(s *mcclient.ClientSession, args *BucketUploadObjectsOptions) error {
R(&computeoptions.BucketUploadObjectsOptions{}, "bucket-object-upload", "Upload an object into a bucket", func(s *mcclient.ClientSession, args *computeoptions.BucketUploadObjectsOptions) error {
var body io.Reader
if len(args.Path) > 0 {
file, err := os.Open(args.Path)
@@ -223,332 +116,36 @@ func init() {
return nil
})
type BucketPresignObjectsOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
KEY string `help:"Key of object to upload"`
Method string `help:"Request method" choices:"GET|PUT|DELETE"`
ExpireSeconds int `help:"expire in seconds" default:"60"`
}
R(&BucketPresignObjectsOptions{}, "bucket-object-tempurl", "Get temporal URL for an object in a bucket", func(s *mcclient.ClientSession, args *BucketPresignObjectsOptions) error {
params, err := options.StructToParams(args)
R(&computeoptions.BucketPerfMonOptions{}, "bucket-perf-mon", "Bucket performance monitor", func(s *mcclient.ClientSession, args *computeoptions.BucketPerfMonOptions) error {
result, err := modules.Buckets.Get(s, args.ID, nil)
if err != nil {
return err
}
result, err := modules.Buckets.PerformAction(s, args.ID, "temp-url", params)
bucketDetails := compute.BucketDetails{}
err = result.Unmarshal(&bucketDetails)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketSetAclOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
ACL string `help:"ACL to set" choices:"default|private|public-read|public-read-write" json:"acl"`
Key []string `help:"Optional object key" json:"key"`
}
R(&BucketSetAclOptions{}, "bucket-set-acl", "Set ACL of bucket or object", func(s *mcclient.ClientSession, args *BucketSetAclOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Buckets.PerformAction(s, args.ID, "acl", params)
bucket, err := modules.GetIBucket(s.GetContext(), s, &bucketDetails)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketAclOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
Key string `help:"Optional object key"`
}
R(&BucketAclOptions{}, "bucket-acl", "Get ACL of bucket or object", func(s *mcclient.ClientSession, args *BucketAclOptions) error {
params, err := options.StructToParams(args)
payload, err := fileutils.GetSizeBytes(args.Payload, 1024)
if err != nil {
return err
}
result, err := modules.Buckets.GetSpecific(s, args.ID, "acl", params)
stats, err := modules.ProbeBucketStats(s.GetContext(), bucket, "test", int64(payload))
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketSyncOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
StatsOnly bool `help:"sync statistics only"`
}
R(&BucketSyncOptions{}, "bucket-sync", "Sync bucket", func(s *mcclient.ClientSession, args *BucketSyncOptions) error {
params, err := options.StructToParams(args)
if err != nil {
return err
}
result, err := modules.Buckets.PerformAction(s, args.ID, "sync", params)
if err != nil {
return err
}
printObject(result)
return nil
})
fmt.Printf("Upload delay %f ms throughput %f MB/s\n", stats.UploadDelayMs(), stats.UploadThroughputMbps(payload/1024/1024))
fmt.Printf("Download delay %f ms throughput %f MB/s\n", stats.DownloadDelayMs(), stats.DownloadThroughputMbps(payload/1024/1024))
fmt.Printf("Delete delay %f ms\n", stats.DeleteDelayMs())
type BucketLimitOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
SizeBytes int64 `help:"size limit in bytes"`
ObjectCount int64 `help:"object count limit"`
}
R(&BucketLimitOptions{}, "bucket-limit", "Set limit of bucket", func(s *mcclient.ClientSession, args *BucketLimitOptions) error {
limit := jsonutils.Marshal(args)
params := jsonutils.NewDict()
params.Set("limit", limit)
result, err := modules.Buckets.PerformAction(s, args.ID, "limit", params)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketAccessInfoOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketAccessInfoOptions{}, "bucket-access-info", "Show backend access info of a bucket", func(s *mcclient.ClientSession, args *BucketAccessInfoOptions) error {
result, err := modules.Buckets.GetSpecific(s, args.ID, "access-info", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketSetMetadataOptions struct {
ID string `help:"ID or name of bucket" json:"-"`
Key []string `help:"Optional object key" json:"key"`
objectstore.ObjectHeaderOptions
}
R(&BucketSetMetadataOptions{}, "bucket-set-metadata", "Set metadata of object", func(s *mcclient.ClientSession, args *BucketSetMetadataOptions) error {
input := api.BucketMetadataInput{}
input.Key = args.Key
input.Metadata = args.ObjectHeaderOptions.Options2Header()
err := input.Validate()
if err != nil {
return err
}
result, err := modules.Buckets.PerformAction(s, args.ID, "metadata", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketSetWebsiteOption struct {
ID string `help:"ID or name of bucket" json:"-"`
// 主页
Index string `help:"main page"`
// 错误时返回的文档
ErrorDocument string `help:"error return"`
// http或https
Protocol string `help:"force https" choices:"http|https"`
}
R(&BucketSetWebsiteOption{}, "bucket-set-website", "Set bucket website", func(s *mcclient.ClientSession, args *BucketSetWebsiteOption) error {
conf := api.BucketWebsiteConf{
Index: args.Index,
ErrorDocument: args.ErrorDocument,
Protocol: args.Protocol,
}
result, err := modules.Buckets.PerformAction(s, args.ID, "set-website", jsonutils.Marshal(conf))
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketGetWebsiteConfOption struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketGetWebsiteConfOption{}, "bucket-get-website", "Get bucket website", func(s *mcclient.ClientSession, args *BucketGetWebsiteConfOption) error {
result, err := modules.Buckets.GetSpecific(s, args.ID, "website", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketDeleteWebsiteConfOption struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketDeleteWebsiteConfOption{}, "bucket-delete-website", "Delete bucket website", func(s *mcclient.ClientSession, args *BucketDeleteWebsiteConfOption) error {
result, err := modules.Buckets.PerformAction(s, args.ID, "delete-website", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketSetCorsOption struct {
ID string `help:"ID or name of bucket" json:"-"`
AllowedMethods []string `help:"allowed http method" choices:"PUT|GET|POST|DELETE|HEAD"`
// 允许的源站,可以设为*
AllowedOrigins []string
AllowedHeaders []string
MaxAgeSeconds int
ExposeHeaders []string
RuleId string
}
R(&BucketSetCorsOption{}, "bucket-set-cors", "Set bucket cors", func(s *mcclient.ClientSession, args *BucketSetCorsOption) error {
rule := api.BucketCORSRule{
AllowedOrigins: args.AllowedOrigins,
AllowedMethods: args.AllowedMethods,
AllowedHeaders: args.AllowedHeaders,
MaxAgeSeconds: args.MaxAgeSeconds,
ExposeHeaders: args.ExposeHeaders,
Id: args.RuleId,
}
rules := api.BucketCORSRules{Data: []api.BucketCORSRule{rule}}
result, err := modules.Buckets.PerformAction(s, args.ID, "set-cors", jsonutils.Marshal(rules))
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketGetCorsOption struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketGetCorsOption{}, "bucket-get-cors", "Get bucket cors", func(s *mcclient.ClientSession, args *BucketGetCorsOption) error {
result, err := modules.Buckets.GetSpecific(s, args.ID, "cors", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketDeleteCorsOption struct {
ID string `help:"ID or name of bucket" json:"-"`
Id []string `"help:Id of rules to delete"`
}
R(&BucketDeleteCorsOption{}, "bucket-delete-cors", "Delete bucket cors", func(s *mcclient.ClientSession, args *BucketDeleteCorsOption) error {
input := api.BucketCORSRuleDeleteInput{}
input.Id = args.Id
result, err := modules.Buckets.PerformAction(s, args.ID, "delete-cors", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketSetRefererOption struct {
ID string `help:"ID or name of bucket" json:"-"`
// 域名列表
DomainList []string
// 是否允许空referer 访问
AllowEmptyRefer bool `help:"all empty refer access"`
Enabled bool
RerererType string `help:"Referer type" choices:"Black-List|White-List"`
}
R(&BucketSetRefererOption{}, "bucket-set-referer", "Set bucket referer", func(s *mcclient.ClientSession, args *BucketSetRefererOption) error {
conf := api.BucketRefererConf{
Enabled: args.Enabled,
AllowEmptyRefer: args.AllowEmptyRefer,
RefererType: args.RerererType,
DomainList: args.DomainList,
}
result, err := modules.Buckets.PerformAction(s, args.ID, "set-referer", jsonutils.Marshal(conf))
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketGetRefererOption struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketGetRefererOption{}, "bucket-get-referer", "get bucket referer", func(s *mcclient.ClientSession, args *BucketGetRefererOption) error {
result, err := modules.Buckets.GetSpecific(s, args.ID, "referer", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketGetCdnDomainOption struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketGetRefererOption{}, "bucket-get-cdn-domain", "get bucket cdn domain", func(s *mcclient.ClientSession, args *BucketGetRefererOption) error {
result, err := modules.Buckets.GetSpecific(s, args.ID, "cdn-domain", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketGetPolicyOption struct {
ID string `help:"ID or name of bucket" json:"-"`
}
R(&BucketGetPolicyOption{}, "bucket-get-policy", "get bucket policy", func(s *mcclient.ClientSession, args *BucketGetPolicyOption) error {
result, err := modules.Buckets.GetSpecific(s, args.ID, "policy", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketSetPolicyOption struct {
ID string `help:"ID or name of bucket" json:"-"`
// 格式主账号id:子账号id
PrincipalId []string `help:"ext account id, accountId:subaccountId"`
// Read|ReadWrite|FullControl
CannedAction string `help:"authority action" choice:"Read|FullControl"`
// Allow|Deny
Effect string `help:"allow or deny" choice:"Allow|Deny"`
// 被授权的资源地址
ResourcePath []string
// ip 条件
IpEquals []string
IpNotEquals []string
}
R(&BucketSetPolicyOption{}, "bucket-set-policy", "set bucket policy", func(s *mcclient.ClientSession, args *BucketSetPolicyOption) error {
opts := api.BucketPolicyStatementInput{}
opts.CannedAction = args.CannedAction
opts.Effect = args.Effect
opts.IpEquals = args.IpEquals
opts.IpNotEquals = args.IpNotEquals
opts.ResourcePath = args.ResourcePath
opts.PrincipalId = args.PrincipalId
result, err := modules.Buckets.PerformAction(s, args.ID, "set-policy", jsonutils.Marshal(opts))
if err != nil {
return err
}
printObject(result)
return nil
})
type BucketDeletePolicyOption struct {
ID string `help:"ID or name of bucket" json:"-"`
Id []string
}
R(&BucketDeletePolicyOption{}, "bucket-delete-policy", "delete bucket policy", func(s *mcclient.ClientSession, args *BucketDeletePolicyOption) error {
input := api.BucketPolicyDeleteInput{}
input.Id = args.Id
result, err := modules.Buckets.PerformAction(s, args.ID, "delete-policy", jsonutils.Marshal(input))
if err != nil {
return err
}
printObject(result)
return nil
})
}

View File

@@ -28,4 +28,8 @@ func init() {
cmd.Update(&compute.CDNDomainUpdateOptions{})
cmd.Delete(&options.BaseIdOptions{})
cmd.Create(&compute.CDNDomainCreateOptions{})
cmd.Perform("clear-cache", &compute.CDNClearCacheOptions{})
cmd.Perform("change-config", &compute.CDNChangeConfigOptions{})
cmd.Perform("delete-custom-hostname", &compute.CDNDeleteCustomHostnameOptions{})
cmd.Get("custom-hostnames", &compute.CDNCustomHostnameOptions{})
}

View File

@@ -46,6 +46,7 @@ func init() {
cmd.Perform("rebuild", &compute_options.DiskRebuildOptions{})
cmd.Perform("migrate", &compute_options.DiskMigrateOptions{})
cmd.Perform("reset-template", &compute_options.DiskResetTemplateOptions{})
cmd.Perform("change-billing-type", new(compute_options.DiskChangeBillingTypeOptions))
type DiskDetailOptions struct {
ID string `help:"ID or Name of disk"`

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 compute
import (
"yunion.io/x/onecloud/cmd/climc/shell"
computemodules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
)
func init() {
cmd := shell.NewResourceCmd(&computemodules.HostFiles)
cmd.List(&compute.HostFileListOptions{})
cmd.Create(&compute.HostFileCreateOptions{})
cmd.Show(&compute.HostFileShowOptions{})
cmd.Update(&compute.HostFileUpdateOptions{})
cmd.Edit(&compute.HostFileEditOptions{})
cmd.Delete(&compute.HostFileDeleteOptions{})
}

View File

@@ -55,8 +55,8 @@ func init() {
cmd.Perform("class-metadata", &options.ResourceMetadataOptions{})
cmd.Perform("set-class-metadata", &options.ResourceMetadataOptions{})
cmd.PerformClass("validate-ipmi", &compute.HostValidateIPMI{})
cmd.Perform("set-commit-bound", &compute.HostSetCommitBoundOptions{})
cmd.BatchPerform("set-commit-bound", &compute.HostSetCommitBoundOptions{})
cmd.BatchPerform("enable", &options.BaseIdsOptions{})
cmd.BatchPerform("disable", &options.BaseIdsOptions{})
cmd.BatchPerform("syncstatus", &options.BaseIdsOptions{})
@@ -67,6 +67,7 @@ func init() {
cmd.BatchPerform("unreserve-cpus", &options.BaseIdsOptions{})
cmd.BatchPerform("auto-migrate-on-host-down", &compute.HostAutoMigrateOnHostDownOptions{})
cmd.BatchPerform("restart-host-agent", &options.BaseIdsOptions{})
cmd.BatchPerform("set-host-files", &compute.HostSetHostFilesOptions{})
cmd.Get("ipmi", &options.BaseIdOptions{})
cmd.Get("vnc", &options.BaseIdOptions{})
@@ -93,6 +94,9 @@ func init() {
fmt.Println("error", err)
}
}, &options.BaseIdOptions{})
cmd.GetWithCustomShow("host-files", func(data jsonutils.JSONObject) {
printObject(data)
}, &options.BaseIdOptions{})
R(&compute.HostShowOptions{}, "host-show", "Show details of a host", func(s *mcclient.ClientSession, args *compute.HostShowOptions) error {
params, err := args.Params()
@@ -259,6 +263,7 @@ func init() {
INDEX int64 `help:"nic index"`
Type string `help:"Nic type" choices:"admin|ipmi"`
IpAddr string `help:"IP address"`
Ip6Addr string `help:"IPv6 address"`
Bridge string `help:"Bridge of hostwire"`
Interface string `help:"Interface name, eg:eth0, en0"`
}
@@ -274,6 +279,9 @@ func init() {
if len(args.IpAddr) > 0 {
params.Add(jsonutils.NewString(args.IpAddr), "ip_addr")
}
if len(args.Ip6Addr) > 0 {
params.Add(jsonutils.NewString(args.Ip6Addr), "ip6_addr")
}
if len(args.Bridge) > 0 {
params.Add(jsonutils.NewString(args.Bridge), "bridge")
}
@@ -306,7 +314,8 @@ func init() {
type HostEnableNetIfOptions struct {
ID string `help:"ID or Name of host"`
MAC string `help:"MAC of NIC to enable"`
Ip string `help:"IP address"`
Ip string `help:"IPv4 address"`
Ip6 string `help:"IPv6 address"`
Network string `help:"network to connect"`
Reserved bool `help:"fetch IP from reserved pool"`
}
@@ -315,6 +324,11 @@ func init() {
params.Add(jsonutils.NewString(args.MAC), "mac")
if len(args.Ip) > 0 {
params.Add(jsonutils.NewString(args.Ip), "ip_addr")
}
if len(args.Ip6) > 0 {
params.Add(jsonutils.NewString(args.Ip6), "ip6_addr")
}
if len(args.Ip) > 0 || len(args.Ip6) > 0 {
if args.Reserved {
params.Add(jsonutils.JSONTrue, "reserve")
}

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 compute
import (
"yunion.io/x/onecloud/cmd/climc/shell"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
options "yunion.io/x/onecloud/pkg/mcclient/options/compute"
)
func init() {
cmd := shell.NewResourceCmd(&modules.LoadbalancerHealthChecks).WithKeyword("lb-health-check")
cmd.List(&options.LoadbalancerHealthCheckListOptions{})
cmd.Show(&options.LoadbalancerHealthCheckIdOptions{})
cmd.Create(&options.LoadbalancerHealthCheckCreateOptions{})
cmd.Delete(&options.LoadbalancerHealthCheckIdOptions{})
cmd.Update(&options.LoadbalancerHealthCheckUpdateOptions{})
cmd.Perform("syncstatus", &options.LoadbalancerHealthCheckIdOptions{})
}

View File

@@ -234,7 +234,7 @@ func init() {
fmt.Println("[Slave Addresses]")
for _, addr := range netIf.GetSlaveAddresses() {
fmt.Printf("%s/%s\n", addr[0], addr[1])
fmt.Printf("%s/%d\n", addr.Addr, addr.MaskLen)
}
fmt.Println("[Routes]")
for _, r := range netIf.GetRouteSpecs() {

View File

@@ -32,6 +32,7 @@ func init() {
cmd.Perform("syncstatus", &options.SecgroupIdOptions{})
cmd.Perform("private", &options.SecgroupIdOptions{})
cmd.Perform("add-rule", &options.SecgroupsAddRuleOptions{})
cmd.Perform("clone", &options.SecgroupCloneOptions{})
cmd.Perform("change-owner", &options.SecgroupChangeOwnerOptions{})
cmd.Perform("import-rules", &options.SecgroupImportRulesOptions{})
cmd.PerformClass("clean", &options.SecgroupCleanOptions{})

View File

@@ -165,8 +165,9 @@ func init() {
})
type ServerAttachNetworkOptions struct {
SERVER string `help:"ID or Name of server"`
NETDESC []string `help:"Network description"`
SERVER string `help:"ID or Name of server"`
DisableSyncConfig bool `help:"Disable sync config"`
NETDESC []string `help:"Network description"`
}
R(&ServerAttachNetworkOptions{}, "server-attach-network", "Attach a server to a virtual network", func(s *mcclient.ClientSession, args *ServerAttachNetworkOptions) error {
input := compute.AttachNetworkInput{}
@@ -177,6 +178,7 @@ func init() {
}
input.Nets = append(input.Nets, conf)
}
input.DisableSyncConfig = &args.DisableSyncConfig
params := jsonutils.Marshal(input)
srv, err := modules.Servers.PerformAction(s, args.SERVER, "attachnetwork", params)
if err != nil {

View File

@@ -129,7 +129,7 @@ func init() {
cmd.BatchPerform("stop-rescue", &options.ServerStartOptions{})
cmd.BatchPerform("sync-os-info", &options.ServerIdsOptions{})
cmd.BatchPerform("set-root-disk-matcher", &options.ServerSetRootDiskMatcher{})
cmd.Perform("disable-auto-merge-snapshot", &options.ServerDisableAutoMergeSnapshot{})
cmd.Get("vnc", new(options.ServerVncOptions))
cmd.Get("desc", new(options.ServerIdOptions))
cmd.Get("status", new(options.ServerIdOptions))

View File

@@ -28,5 +28,7 @@ func init() {
cmd.Create(&compute.SnapshotPolicyCreateOptions{})
cmd.Perform("bind-disks", &compute.SnapshotPolicyDisksOptions{})
cmd.Perform("unbind-disks", &compute.SnapshotPolicyDisksOptions{})
cmd.Perform("bind-resources", &compute.SnapshotPolicyResourcesOptions{})
cmd.Perform("unbind-resources", &compute.SnapshotPolicyResourcesOptions{})
cmd.Perform("syncstatus", &options.BaseIdOptions{})
}

View File

@@ -33,6 +33,7 @@ func init() {
DiskType string `help:"Filter by disk type" choices:"sys|data"`
Server string `help:"Filter by server" json:"server_id"`
Unused bool
StorageId string `help:"Filter by storage id"`
OrderByGuest string
OrderByDiskName string

View File

@@ -24,6 +24,7 @@ import (
func init() {
cmd := shell.NewResourceCmd(&modules.SslCerticicate).WithKeyword("ssl-certificate")
cmd.List(&compute.SslCertificateListOptions{})
cmd.Create(&compute.SslCertificateCreateOptions{})
cmd.Show(&options.BaseShowOptions{})
cmd.Delete(&options.BaseIdOptions{})
}

View File

@@ -74,12 +74,7 @@ func init() {
if info.StorageType != "rbd" {
return errors.Errorf("invalid storage_type %s", info.StorageType)
}
cli, err := cephutils.NewClient(
info.StorageConf.MonHost,
info.StorageConf.Key,
info.StorageConf.Pool,
info.StorageConf.EnableMessengerV2,
)
cli, err := cephutils.NewClient(info.StorageConf.MonHost, info.StorageConf.Key, info.StorageConf.Pool, info.StorageConf.EnableMessengerV2, 0, 0, 0)
if err != nil {
return errors.Wrap(err, "cephutils.NewClient")
}

View File

@@ -29,4 +29,6 @@ func init() {
cmd.Show(&options.BaseIdOptions{})
cmd.Delete(&options.BaseIdOptions{})
cmd.Perform("syncstatus", &options.BaseIdOptions{})
cmd.Perform("enable", &options.BaseIdOptions{})
cmd.Perform("disable", &options.BaseIdOptions{})
}

View File

@@ -21,6 +21,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/util/printutils"
"yunion.io/x/pkg/util/shellutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -544,6 +545,81 @@ func (cmd ResourceCmd) Update(args IUpdateOpt) {
cmd.UpdateWithKeyword("update", args)
}
type EditType string
const (
EditTypeText EditType = "text"
EditTypeYaml EditType = "yaml"
EditTypeJson EditType = "json"
)
type IEditOpt interface {
IGetOpt
EditType() EditType
EditFields() []string
}
func (cmd ResourceCmd) Edit(args IEditOpt) {
man := cmd.manager
callback := func(s *mcclient.ClientSession, args IEditOpt) error {
params, err := args.Params()
if err != nil {
return err
}
obj, err := man.(modulebase.Manager).Get(s, args.GetId(), params)
if err != nil {
return err
}
format := args.EditType()
fields := args.EditFields()
var editText string
switch format {
case EditTypeText:
editText, _ = obj.GetString(fields...)
default:
editJson, _ := obj.Get(fields...)
if editJson == nil {
editJson = jsonutils.NewDict()
}
if format == EditTypeYaml {
editText = editJson.YAMLString()
} else if format == EditTypeJson {
editText = editJson.PrettyString()
}
}
editText, err = shellutils.Edit(editText)
if err != nil {
return err
}
updateParams := jsonutils.NewDict()
switch format {
case EditTypeText:
updateParams.Add(jsonutils.NewString(editText), fields...)
case EditTypeYaml:
yamlObj, err := jsonutils.ParseYAML(editText)
if err != nil {
return err
}
updateParams.Add(yamlObj, fields...)
case EditTypeJson:
jsonObj, err := jsonutils.ParseString(editText)
if err != nil {
return err
}
updateParams.Add(jsonObj, fields...)
}
updateResult, err := man.(modulebase.Manager).Update(s, args.GetId(), updateParams)
if err != nil {
return err
}
PrintObject(updateResult)
return nil
}
cmd.Run("edit", args, callback)
}
type IMetadataOpt interface {
IIdOpt
IOpt

View File

@@ -1,3 +1,17 @@
// 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 (

View File

@@ -27,11 +27,17 @@ import (
)
type Options struct {
Help bool `help:"Show help"`
Help bool `help:"Show help"`
Interface string `help:"Listening interface, e.g. eth0"`
Ip string `help:"Listening interface IP, e.g. 192.168.22.2"`
Port int `help:"listening port" default:"67"`
Relay string `help:"Relay server address, e.g. 192.168.22.23"`
Ip string `help:"Listening interface IP, e.g. 192.168.22.2"`
Port int `help:"listening port" default:"67"`
Relay string `help:"Relay server address, e.g. 192.168.22.23"`
Ip6 string `help:"Listening interface IP, e.g. 2001:db8::1"`
Port6 int `help:"listening port" default:"547"`
Relay6 string `help:"Relay server address, e.g. 2001:db8::23"`
}
func relayMain() error {
@@ -45,6 +51,10 @@ func relayMain() error {
}
err = parse.ParseArgs(os.Args[1:], false)
if err != nil {
return err
}
options := parse.Options().(*Options)
if options.Help {
@@ -55,24 +65,45 @@ func relayMain() error {
if len(options.Interface) == 0 {
return errors.Error("Missing interface")
}
if len(options.Ip) == 0 {
return errors.Error("Missing interface IP")
}
if len(options.Relay) == 0 {
return errors.Error("Missing DHCP relay server")
if len(options.Ip) == 0 && len(options.Ip6) == 0 {
return errors.Error("Missing interface IP or IP6")
}
srv, err := hostdhcp.NewGuestDHCPServer(options.Interface, options.Port, []string{
options.Relay, "67",
})
if len(options.Ip) > 0 {
if len(options.Relay) == 0 {
return errors.Error("Missing DHCP relay server or relay server6")
}
if err != nil {
return errors.Wrap(err, "NewGuestDHCPServer")
relayConfig := &hostdhcp.SDHCPRelayUpstream{}
relayConfig.IP = options.Relay
relayConfig.Port = 67
srv, err := hostdhcp.NewGuestDHCPServer(options.Interface, options.Port, relayConfig)
if err != nil {
return errors.Wrap(err, "NewGuestDHCPServer")
}
srv.Start(false)
srv.RelaySetup(options.Ip)
}
srv.Start(false)
if len(options.Ip6) > 0 {
if len(options.Relay6) == 0 {
return errors.Error("Missing DHCP relay server or relay server6")
}
srv.RelaySetup(options.Ip)
relayConfig6 := &hostdhcp.SDHCPRelayUpstream{}
relayConfig6.IP = options.Relay6
relayConfig6.Port = options.Port6
srv6, err := hostdhcp.NewGuestDHCP6Server(options.Interface, options.Port6, relayConfig6)
if err != nil {
return errors.Wrap(err, "NewGuestDHCP6Server")
}
srv6.Start(false)
srv6.RelaySetup(options.Ip6)
}
for {
time.Sleep(time.Hour)

34
go.mod
View File

@@ -12,11 +12,13 @@ require (
github.com/bitly/go-simplejson v0.5.0
github.com/c-bata/go-prompt v0.2.4
github.com/cheggaaa/pb/v3 v3.0.8
github.com/containerd/containerd v1.4.1
github.com/coredns/coredns v1.3.0
github.com/coreos/go-iptables v0.6.0
github.com/creack/pty v1.1.18
github.com/docker/docker v17.12.0-ce-rc1.0.20200916142827-bd33bbf0497b+incompatible
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/eggsampler/acme/v3 v3.6.2
github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e
github.com/fsnotify/fsnotify v1.4.9
github.com/ghodss/yaml v1.0.0
@@ -24,6 +26,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/cadvisor v0.38.5
github.com/google/gopacket v1.1.17
github.com/google/uuid v1.6.0
@@ -32,7 +35,6 @@ require (
github.com/gorilla/websocket v1.4.1
github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282
github.com/hako/durafmt v0.0.0-20180520121703-7b7ae1e72ead
github.com/hugozhu/godingtalk v1.0.6
github.com/influxdata/influxql v1.1.0
github.com/influxdata/promql/v2 v2.12.0
github.com/jaypipes/ghw v0.11.0
@@ -48,6 +50,7 @@ require (
github.com/miekg/dns v1.1.25
github.com/minio/minio-go v6.0.14+incompatible
github.com/mitchellh/go-wordwrap v1.0.1
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb
github.com/pierrec/lz4/v4 v4.1.15
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.6
@@ -58,7 +61,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
@@ -74,14 +77,14 @@ require (
go.etcd.io/etcd/client/v3 v3.5.0
golang.org/x/crypto v0.19.0
golang.org/x/net v0.21.0
golang.org/x/sync v0.6.0
golang.org/x/sys v0.17.0
golang.org/x/sync v0.8.0
golang.org/x/sys v0.26.0
golang.org/x/text v0.14.0
golang.org/x/time v0.5.0
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde
google.golang.org/grpc v1.62.0
google.golang.org/protobuf v1.32.0
google.golang.org/protobuf v1.35.1
gopkg.in/fatih/set.v0 v0.2.1
gopkg.in/ldap.v3 v3.0.3
gopkg.in/mail.v2 v2.3.1
@@ -93,14 +96,14 @@ require (
k8s.io/cri-api v0.22.17
k8s.io/klog/v2 v2.20.0
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250427071042-3ec467b38f4d
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256
yunion.io/x/jsonutils v1.0.1-0.20250406102002-98c9140a9edd
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024120-20f73c47b078
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.20250403114914-586e94d39281
yunion.io/x/pkg v1.10.4-0.20250814065738-8df5d9d07297
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
yunion.io/x/sqlchemy v1.1.3-0.20250420094945-40f40c75a31f
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
)
@@ -125,7 +128,8 @@ require (
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/Microsoft/go-winio v0.4.15 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.8.14 // indirect
github.com/RoaringBitmap/roaring v0.4.16 // indirect
github.com/Shopify/sarama v1.20.0 // indirect
github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect
@@ -155,9 +159,12 @@ require (
github.com/checkpoint-restore/go-criu/v4 v4.1.0 // indirect
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 // indirect
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 // indirect
github.com/containerd/console v1.0.0 // indirect
github.com/containerd/containerd v1.4.1 // indirect
github.com/containerd/continuity v0.4.5 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/ttrpc v1.0.2 // indirect
github.com/containerd/typeurl v1.0.1 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/cyphar/filepath-securejoin v0.2.2 // indirect
@@ -167,6 +174,7 @@ require (
github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11 // indirect
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/eapache/go-resiliency v1.1.0 // indirect
@@ -195,7 +203,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
@@ -292,6 +299,7 @@ require (
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect

80
go.sum
View File

@@ -93,8 +93,12 @@ github.com/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2 h1:XGB3B065
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.4.15 h1:qkLXKzb1QoVatRyd/YlXZ/Kg0m5K3SPuoD82jjSOaBc=
github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.8.14 h1:lbPVK25c1cu5xTLITwpUcxoA9vKrKErASPYygvouJns=
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
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=
@@ -207,6 +211,7 @@ github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/o
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 h1:cHzBGGVew0ezFsq2grfy2RsB8hO/eNyBgOLHBCqfR1U=
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -216,12 +221,25 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk=
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v1.0.0 h1:fU3UuQapBs+zLJu82NhR11Rif1ny2zfMMAyPJzSN5tQ=
github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.4.1 h1:pASeJT3R3YyVn+94qEPk0SnU1OQ20Jd/T+SPKy9xehY=
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v1.0.2 h1:2/O3oTZN36q2xRolk0a2WWGgh7/Vf/liElg5hFYLX9U=
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/containerd/typeurl v1.0.1 h1:PvuK4E3D5S5q6IqsPDCy928FhP0LUIGcmZ/Yhgp5Djw=
github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
github.com/coredns/coredns v1.3.0 h1:Ubjr8ZrOpEj95/A9dqQqQAG2k5DWEFdg2ZB3tUXuULA=
@@ -230,10 +248,12 @@ github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@@ -256,6 +276,8 @@ github.com/docker/docker v20.10.27+incompatible h1:Id/ZooynV4ZlD6xX20RCd3SR0Ikn7
github.com/docker/docker v20.10.27+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk=
github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
@@ -273,6 +295,8 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/eggsampler/acme/v3 v3.6.2 h1:gvyZbQ92wNQLDASVftGpHEdFwPSfg0+17P0lLt09Tp8=
github.com/eggsampler/acme/v3 v3.6.2/go.mod h1:/qh0rKC/Dh7Jj+p4So7DbWmFNzC4dpcpK53r226Fhuo=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elgatito/upnp v0.0.0-20180711183757-2f244d205f9a h1:2Zw3pxDRTs4nX1WCLAEm27UN0hvjZSge7EaUUQexRZw=
github.com/elgatito/upnp v0.0.0-20180711183757-2f244d205f9a/go.mod h1:afkYpY8JAIL4341N7Zj9xJ5yTovsg6BkWfBFlCzIoF4=
@@ -430,7 +454,6 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -496,15 +519,12 @@ github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
github.com/huaweicloud/huaweicloud-sdk-go v1.0.26 h1:aWTl4Ng9lZUW1DupYyqYiqkTwuTKMmqUZBKLmX0iWxo=
github.com/huaweicloud/huaweicloud-sdk-go v1.0.26/go.mod h1:YHXxw/bm7AohI4jTY8Z43JYw+DPCDLqjxoLTqmcyja4=
github.com/hugozhu/godingtalk v1.0.6 h1:K280OQGbYVS/UQuVWJz5cHhv/Wvfj1FHNo8lbbLGsNQ=
github.com/hugozhu/godingtalk v1.0.6/go.mod h1:Je6PSjUH7IKCPpFq5ti2I9ak1szzSNgCIMlP0s+8pbQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/influxdata/influxql v1.1.0 h1:sPsaumLFRPMwR5QtD3Up54HXpNND8Eu7G1vQFmi3quQ=
github.com/influxdata/influxql v1.1.0/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo=
github.com/ipandtcp/godingtalk v0.0.0-20180410032244-ca3d6ac197fb/go.mod h1:3umLciE1jBnh2LgrL15R2zbEe+HVPRZXnlSjjb/dYiw=
github.com/jaypipes/ghw v0.11.0 h1:i0pKvAM7eZk0KvLm9vzpcpDKTRnfR6AQ5pFkPVnYJXU=
github.com/jaypipes/ghw v0.11.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g=
github.com/jdcloud-api/jdcloud-sdk-go v1.55.0 h1:mzVj8r6fluEwjn8ogqtGfYW2qSIVUaEq0JAsvjCav3A=
@@ -669,12 +689,15 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc92 h1:+IczUKCRzDzFDnw99O/PAqrcBBCoRp9xN3cB1SYSNS4=
github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6 h1:NhsM2gc769rVWDqJvapK37r+7+CBXI8xHhnfnt8uQsg=
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.6.0 h1:+bIAS/Za3q5FTwWym4fTB0vObnfCf3G/NC7K6Jx62mY=
@@ -688,6 +711,8 @@ github.com/openzipkin/zipkin-go-opentracing v0.3.4/go.mod h1:js2AbwmHW0YD9DwIw2J
github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU=
github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
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=
@@ -727,6 +752,7 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@@ -773,8 +799,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
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=
@@ -840,6 +867,7 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
@@ -879,6 +907,8 @@ github.com/zexi/influxql-to-metricsql v0.1.1 h1:dXnVzlxVLuo88zGkDca7erEnmvprGWjz
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=
github.com/zexi/promql/v2 v2.12.1/go.mod h1:2UtzWZGmth95n2qdIZWpJ5yQ0cE5hEvz0dGsajI1Sqg=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU=
@@ -984,6 +1014,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -1032,8 +1063,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180724212812-e072cadbbdc8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1059,6 +1090,7 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1089,6 +1121,7 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1107,8 +1140,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1201,7 +1234,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
@@ -1220,7 +1252,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.4/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
@@ -1269,6 +1300,7 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@@ -1294,8 +1326,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
@@ -1376,13 +1408,13 @@ 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.20250427071042-3ec467b38f4d h1:RnK6jhPwXRkQUDRL96YV7qeKbGq5zSZ2SQ/T6Jur574=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250427071042-3ec467b38f4d/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256 h1:kLKQ6zbgPDQflRwoHFAjxNChcbhXIFgsUVLkJwiXu/8=
yunion.io/x/executor v0.0.0-20241205080005-48f5b1212256/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024120-20f73c47b078 h1:KaAEKjdAcpRrJlrJfOtcXCz5IUgPdv7dqeZnLswxLXE=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250820024120-20f73c47b078/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
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=
yunion.io/x/jsonutils v1.0.1-0.20250406102002-98c9140a9edd h1:FWwB4CXiyIrh2YvxPliC9ZmrzXcFv+nuG3lhpipR4Sk=
yunion.io/x/jsonutils v1.0.1-0.20250406102002-98c9140a9edd/go.mod h1:VK4Z93dgiKgAijcSqbMKmGaBMJuHulR16Hz4K015ZPo=
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1 h1:/+THlvf/MvgCW+7KeCDCr33e81KSRa5JmdZ1IIyLOXQ=
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1/go.mod h1:VK4Z93dgiKgAijcSqbMKmGaBMJuHulR16Hz4K015ZPo=
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91 h1:inY5o3LDa/zgsIZuPN0HmpzKIsu/lLgsBmMttuDPGj4=
@@ -1391,11 +1423,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.20250403114914-586e94d39281 h1:P22/MaBc9bqE9DyHvS3oQjc4XsaIEbIVGMLdTSroDew=
yunion.io/x/pkg v1.10.4-0.20250403114914-586e94d39281/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/pkg v1.10.4-0.20250814065738-8df5d9d07297 h1:rnU78gHJ+2nEgjpwWN+FclED/nFeuMkrrBWgnTz0ykc=
yunion.io/x/pkg v1.10.4-0.20250814065738-8df5d9d07297/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.20250420094945-40f40c75a31f h1:xuy9a8Hg0d8dfD8j13f687eKPCxEvttgpLQWb4NvKpI=
yunion.io/x/sqlchemy v1.1.3-0.20250420094945-40f40c75a31f/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0 h1:Eha/ywh4foMJm7VJ8ibFOi+WPHacuTWtosAGpOld5vo=
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0/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

@@ -15,28 +15,5 @@
package handler
import (
_ "yunion.io/x/onecloud/pkg/mcclient/modules/ansible"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/cloudevent"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/cloudid"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/cloudnet"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/cloudproxy"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/devtool"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/etcd"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/image"
"yunion.io/x/onecloud/pkg/mcclient/modules/k8s"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/logger"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/notify"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/quota"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/scheduledtask"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/scheduler"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/webconsole"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/yunionconf"
_ "yunion.io/x/onecloud/pkg/mcclient/modules/loader"
)
func init() {
modules.InitUsages()
modules.Usages.RegisterManager(modules.UsageManagerK8s, k8s.Usages)
}

View File

@@ -0,0 +1,47 @@
// 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 compute
import (
"yunion.io/x/onecloud/pkg/apis"
)
type AiGatewayCreateInput struct {
apis.VirtualResourceCreateInput
CloudproviderResourceInput
Authentication bool `json:"authentication"`
CacheInvalidateOnUpdate bool `json:"cache_invalidate_on_update"`
CacheTTL int `json:"cache_ttl"`
CollectLogs bool `json:"collect_logs"`
RateLimitingInterval int `json:"rate_limiting_interval"`
RateLimitingLimit int `json:"rate_limiting_limit"`
RateLimitingTechnique string `json:"rate_limiting_technique"`
}
type AiGatewayListInput struct {
apis.VirtualResourceListInput
apis.ExternalizedResourceBaseListInput
ManagedResourceListInput
}
type AiGatewayDetails struct {
apis.VirtualResourceDetails
ManagedResourceInfo
}
type AiGatewayUpdateInput struct {
apis.VirtualResourceBaseUpdateInput
}

View File

@@ -15,6 +15,8 @@
package compute
import (
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/apis"
@@ -88,6 +90,10 @@ type NetworkConfig struct {
// required: false
RequireIPv6 bool `json:"require_ipv6"`
// 只分配IPv6地址禁用IPv4
// required: false
StrictIPv6 bool `json:"strict_ipv6"`
// 驱动方式
// 若指定镜像的网络驱动方式,此参数会被覆盖
Driver string `json:"driver"`
@@ -648,6 +654,8 @@ type ServerCreateInput struct {
BillingType string `json:"billing_type"`
// swagger:ignore
BillingCycle string `json:"billing_cycle"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// swagger:ignore
// Deprecated

View File

@@ -17,6 +17,7 @@ package compute
import (
"net/http"
"reflect"
"time"
"yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
@@ -53,6 +54,8 @@ type BucketCreateInput struct {
CloudproviderResourceInput
StorageClass string `json:"storage_class"`
EnablePerfMon *bool `json:"enable_perf_mon"`
}
type BucketDetails struct {
@@ -66,28 +69,28 @@ type BucketDetails struct {
AccessUrls []cloudprovider.SBucketAccessUrl `json:"access_urls"`
}
func (self BucketDetails) GetMetricTags() map[string]string {
func (bucket BucketDetails) GetMetricTags() map[string]string {
ret := map[string]string{
"id": self.Id,
"brand": self.Brand,
"cloudregion": self.Cloudregion,
"cloudregion_id": self.CloudregionId,
"domain_id": self.DomainId,
"oss_id": self.Id,
"oss_name": self.Name,
"project_domain": self.ProjectDomain,
"region_ext_id": self.RegionExtId,
"status": self.Status,
"tenant": self.Project,
"tenant_id": self.ProjectId,
"account": self.Account,
"account_id": self.AccountId,
"external_id": self.ExternalId,
"id": bucket.Id,
"brand": bucket.Brand,
"cloudregion": bucket.Cloudregion,
"cloudregion_id": bucket.CloudregionId,
"domain_id": bucket.DomainId,
"oss_id": bucket.Id,
"oss_name": bucket.Name,
"project_domain": bucket.ProjectDomain,
"region_ext_id": bucket.RegionExtId,
"status": bucket.Status,
"tenant": bucket.Project,
"tenant_id": bucket.ProjectId,
"account": bucket.Account,
"account_id": bucket.AccountId,
"external_id": bucket.ExternalId,
}
return AppendMetricTags(ret, self.MetadataResourceInfo, self.ProjectizedResourceInfo)
return AppendMetricTags(ret, bucket.MetadataResourceInfo, bucket.ProjectizedResourceInfo)
}
func (self BucketDetails) GetMetricPairs() map[string]string {
func (bucket BucketDetails) GetMetricPairs() map[string]string {
ret := map[string]string{}
return ret
}
@@ -150,6 +153,8 @@ type BucketSyncstatusInput struct {
type BucketUpdateInput struct {
apis.SharableVirtualResourceBaseUpdateInput
EnablePerfMon *bool `json:"enable_perf_mon"`
}
type BucketPerformTempUrlInput struct {
@@ -370,3 +375,29 @@ func init() {
return &SBackupStorageAccessInfo{}
})
}
type BucketProbeResult struct {
UploadTime time.Duration
DownloadTime time.Duration
DeleteTime time.Duration
}
func (result BucketProbeResult) UploadDelayMs() float64 {
return float64(result.UploadTime) / float64(time.Millisecond)
}
func (result BucketProbeResult) DownloadDelayMs() float64 {
return float64(result.DownloadTime) / float64(time.Millisecond)
}
func (result BucketProbeResult) DeleteDelayMs() float64 {
return float64(result.DeleteTime) / float64(time.Millisecond)
}
func (result BucketProbeResult) UploadThroughputMbps(sizeMBytes int) float64 {
return float64(sizeMBytes) * 8 / float64(result.UploadTime.Seconds())
}
func (result BucketProbeResult) DownloadThroughputMbps(sizeMBytes int) float64 {
return float64(sizeMBytes) * 8 / float64(result.DownloadTime.Seconds())
}

View File

@@ -95,3 +95,11 @@ type CDNDomainListInput struct {
ManagedResourceListInput
}
type CDNCustomHostnameOutput struct {
Data []cloudprovider.CustomHostname
}
type CDNDeleteCustomHostnameInput struct {
Id string
}

View File

@@ -75,6 +75,7 @@ const (
CLOUD_PROVIDER_ZETTAKIT = compute.CLOUD_PROVIDER_ZETTAKIT
CLOUD_PROVIDER_UIS = compute.CLOUD_PROVIDER_UIS
CLOUD_PROVIDER_CAS = compute.CLOUD_PROVIDER_CAS
CLOUD_PROVIDER_CLOUDFLARE = compute.CLOUD_PROVIDER_CLOUDFLARE
CLOUD_PROVIDER_GENERICS3 = compute.CLOUD_PROVIDER_GENERICS3
CLOUD_PROVIDER_CEPH = compute.CLOUD_PROVIDER_CEPH
@@ -143,6 +144,7 @@ var (
CLOUD_PROVIDER_JDCLOUD,
CLOUD_PROVIDER_VOLCENGINE,
CLOUD_PROVIDER_ORACLE,
CLOUD_PROVIDER_CLOUDFLARE,
}
CLOUD_PROVIDERS = []string{
@@ -181,6 +183,7 @@ var (
CLOUD_PROVIDER_ZETTAKIT,
CLOUD_PROVIDER_UIS,
CLOUD_PROVIDER_CAS,
CLOUD_PROVIDER_CLOUDFLARE,
}
CLOUD_PROVIDER_HOST_TYPE_MAP = map[string][]string{

View File

@@ -130,6 +130,7 @@ const (
type ContainerSpec struct {
apis.ContainerSpec
// Volume mounts
RootFs *apis.ContainerRootfs `json:"rootfs"`
VolumeMounts []*apis.ContainerVolumeMount `json:"volume_mounts"`
Devices []*ContainerDevice `json:"devices"`
}
@@ -207,6 +208,8 @@ type ContainerSaveVolumeMountToImageInput struct {
Index int `json:"index"`
Dirs []string `json:"dirs"`
UsedByPostOverlay bool `json:"used_by_post_overlay"`
DirPrefix string `json:"dir_prefix"`
}
type ContainerExecInfoOutput struct {

View File

@@ -82,8 +82,8 @@ type DBInstanceCreateInput struct {
// default: false
AutoRenew bool `json:"auto_renew"`
// swagger:ignore
ExpiredAt time.Time `json:"expired_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]

View File

@@ -171,6 +171,9 @@ type DiskListInput struct {
// 根据虚拟机状态过滤
GuestStatus string `json:"guest_status"`
// 根据是否绑定快照策略过滤
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
}
type DiskResourceInput struct {
@@ -213,6 +216,8 @@ type SimpleGuest struct {
Iops int `json:"iops"`
// 磁盘吞吐
Bps int `json:"bps"`
// 计费类型
BillingType string `json:"billing_type"`
}
type SimpleSnapshotPolicy struct {
@@ -237,6 +242,8 @@ type DiskDetails struct {
GuestCount int `json:"guest_count"`
// 所挂载虚拟机状态
GuestStatus string `json:"guest_status"`
// 所挂载虚拟机计费类型
GuestBillingType string `json:"guest_billing_type"`
// 自动清理时间
AutoDeleteAt time.Time `json:"auto_delete_at"`
@@ -376,3 +383,11 @@ func (d *DiskFsFeatures) IsZero() bool {
}
return false
}
type DiskChangeBillingTypeInput struct {
// 仅在磁盘挂载在虚拟机上时调用
// 目前支持阿里云
// enmu: [postpaid, prepaid]
// required: true
BillingType string `json:"billing_type"`
}

View File

@@ -36,6 +36,7 @@ type DnsRecordCreateInput struct {
DnsValue string `json:"dns_value"`
TTL int64 `json:"ttl"`
MxPriority int64 `json:"mx_priority"`
Proxied *bool `json:"proxied"`
PolicyType string `json:"policy_type"`
PolicyValue string `json:"policy_value"`
@@ -48,6 +49,7 @@ type DnsRecordUpdateInput struct {
DnsValue string `json:"dns_value"`
TTL *int64 `json:"ttl"`
MxPriority *int64 `json:"mx_priority"`
Proxied *bool `json:"proxied"`
}
type DnsRecordDetails struct {

View File

@@ -15,7 +15,11 @@
package compute
import (
"reflect"
"yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/onecloud/pkg/apis"
)
@@ -97,3 +101,19 @@ type DnsZoneRemoveVpcsInput struct {
type DnsZonePurgeInput struct {
}
type SNameServers []string
func (ns SNameServers) String() string {
return jsonutils.Marshal(ns).String()
}
func (ns SNameServers) IsZero() bool {
return len(ns) == 0
}
func init() {
gotypes.RegisterSerializable(reflect.TypeOf(&SNameServers{}), func() gotypes.ISerializable {
return &SNameServers{}
})
}

View File

@@ -246,13 +246,13 @@ type ElasticcacheCreateInput struct {
// 包年包月时间周期
Duration string `json:"duration"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 是否自动续费(仅包年包月时生效)
// default: false
AutoRenew bool `json:"auto_renew"`
// swagger:ignore
ExpiredAt time.Time `json:"expired_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]
BillingType string

View File

@@ -94,6 +94,9 @@ type ElasticipDetails struct {
// 绑定资源名称
AssociateName string `json:"associate_name"`
// 虚拟机内网IP
ServerPrivateIp string `json:"server_private_ip"`
}
func (self ElasticipDetails) GetMetricTags() map[string]string {

View File

@@ -87,8 +87,8 @@ type FileSystemCreateInput struct {
// default: false
AutoRenew bool `json:"auto_renew"`
// 到期释放时间,仅后付费支持
ExpiredAt time.Time `json:"expired_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]

View File

@@ -180,10 +180,6 @@ const (
VM_QGA_SET_NETWORK = "qga_set_network"
VM_QGA_SET_NETWORK_FAILED = "qga_set_network_failed"
// 更改计费模式
VM_CHANGE_BILLING_TYPE = "change_billing_type"
VM_CHANGE_BILLING_TYPE_FAILED = "change_billing_type_failed"
SHUTDOWN_STOP = "stop"
SHUTDOWN_TERMINATE = "terminate"
SHUTDOWN_STOP_RELEASE_GPU = "stop_release_gpu"
@@ -265,6 +261,9 @@ const (
VM_VIDEO_STANDARD = "std"
VM_VIDEO_QXL = "qxl"
VM_VIDEO_VIRTIO = "virtio"
VM_BOOT_MODE_BIOS = "BIOS"
VM_BOOT_MODE_UEFI = "UEFI"
)
var VM_RUNNING_STATUS = []string{VM_START_START, VM_STARTING, VM_RUNNING, VM_BLOCK_STREAM, VM_BLOCK_STREAM_FAIL}
@@ -317,22 +316,23 @@ const (
VM_AZURE_DEFAULT_LOGIN_USER = compute.VM_AZURE_DEFAULT_LOGIN_USER
VM_ZSTACK_DEFAULT_LOGIN_USER = compute.VM_ZSTACK_DEFAULT_LOGIN_USER
VM_METADATA_APP_TAGS = "app_tags"
VM_METADATA_CREATE_PARAMS = "create_params"
VM_METADATA_LOGIN_ACCOUNT = "login_account"
VM_METADATA_LOGIN_KEY = "login_key"
VM_METADATA_LAST_LOGIN_KEY = "last_login_key"
VM_METADATA_LOGIN_KEY_TIMESTAMP = "login_key_timestamp"
VM_METADATA_OS_ARCH = "os_arch"
VM_METADATA_OS_DISTRO = "os_distribution"
VM_METADATA_OS_NAME = "os_name"
VM_METADATA_OS_VERSION = "os_version"
VM_METADATA_CGROUP_CPUSET = "cgroup_cpuset"
VM_METADATA_ENABLE_MEMCLEAN = "enable_memclean"
VM_METADATA_HOTPLUG_CPU_MEM = "hotplug_cpu_mem"
VM_METADATA_HOT_REMOVE_NIC = "hot_remove_nic"
VM_METADATA_START_VMEM_MB = "start_vmem_mb"
VM_METADATA_START_VCPU_COUNT = "start_vcpu_count"
VM_METADATA_APP_TAGS = "app_tags"
VM_METADATA_CREATE_PARAMS = "create_params"
VM_METADATA_LOGIN_ACCOUNT = "login_account"
VM_METADATA_LOGIN_KEY = "login_key"
VM_METADATA_LAST_LOGIN_KEY = "last_login_key"
VM_METADATA_LOGIN_KEY_TIMESTAMP = "login_key_timestamp"
VM_METADATA_OS_ARCH = "os_arch"
VM_METADATA_OS_DISTRO = "os_distribution"
VM_METADATA_OS_NAME = "os_name"
VM_METADATA_OS_VERSION = "os_version"
VM_METADATA_CGROUP_CPUSET = "cgroup_cpuset"
VM_METADATA_ENABLE_MEMCLEAN = "enable_memclean"
VM_METADATA_HOTPLUG_CPU_MEM = "hotplug_cpu_mem"
VM_METADATA_HOT_REMOVE_NIC = "hot_remove_nic"
VM_METADATA_START_VMEM_MB = "start_vmem_mb"
VM_METADATA_START_VCPU_COUNT = "start_vcpu_count"
VM_METADATA_DISABLE_AUTO_MERGE_SNAPSHOT = "disable_auto_merge_snapshot"
VM_METADATA_RELEASED_DEVICES = "released_devices"

View File

@@ -36,6 +36,14 @@ type GuestnetworkDetails struct {
EipAddr string `json:"eip_addr"`
NetworkAddresses []NetworkAddrConf `json:"network_addresses"`
GuestIpMask int8 `json:"guest_ip_mask"`
// 网关地址
GuestGateway string `json:"guest_gateway"`
GuestIp6Mask uint8 `json:"guest_ip6_mask"`
// 网关地址
GuestGateway6 string `json:"guest_gateway6"`
}
type GuestnetworkShortDesc struct {
@@ -58,6 +66,8 @@ type GuestnetworkShortDesc struct {
SubIps string `json:"sub_ips"`
// 端口映射
PortMappings GuestPortMappings `json:"port_mappings"`
IsDefault bool `json:"is_default"`
}
type GuestnetworkListInput struct {
@@ -127,6 +137,8 @@ type GuestnetworkBaseDesc struct {
Id string `json:"id"`
Provider string `json:"provider"`
MappedIpAddr string `json:"mapped_ip_addr"`
MappedIp6Addr string `json:"mapped_ip6_addr"`
} `json:"vpc"`
Networkaddresses jsonutils.JSONObject `json:"networkaddresses"`
@@ -180,14 +192,33 @@ type GuestPortMappingPortRange struct {
End int `json:"end"`
}
type GuestPortMappingEnvValueFrom string
const (
GuestPortMappingEnvValueFromPort GuestPortMappingEnvValueFrom = "port"
GuestPortMappingEnvValueFromHostPort GuestPortMappingEnvValueFrom = "host_port"
)
type GuestPortMappingEnv struct {
Key string `json:"key"`
ValueFrom GuestPortMappingEnvValueFrom `json:"value_from"`
}
type GuestPortMapping struct {
Protocol GuestPortMappingProtocol `json:"protocol"`
Protocol GuestPortMappingProtocol `json:"protocol"`
// 容器内部 Port 端口范围 1-65535-1表示由宿主机自动分配和 HostPort 相同的端口
Port int `json:"port"`
HostPort *int `json:"host_port,omitempty"`
HostIp string `json:"host_ip"`
HostPortRange *GuestPortMappingPortRange `json:"host_port_range,omitempty"`
// whitelist for remote ips
RemoteIps []string `json:"remote_ips"`
RemoteIps []string `json:"remote_ips"`
Rule *GuestPortMappingRule `json:"rule,omitempty"`
Envs []GuestPortMappingEnv `json:"envs,omitempty"`
}
type GuestPortMappingRule struct {
FirstPortOffset *int `json:"first_port_offset"`
}
type GuestPortMappings []*GuestPortMapping

View File

@@ -128,8 +128,13 @@ type ServerListInput struct {
// 根据镜像发行版排序
OrderByOsDist string `json:"order_by_os_dist"`
SnapshotpolicyId string `json:"snapshotpolicy_id"`
// 是否调度到宿主机上
WithHost *bool `json:"with_host"`
// 根据是否绑定快照策略过滤
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
}
func (input *ServerListInput) AfterUnmarshal() {
@@ -324,6 +329,8 @@ func (self ServerDetails) GetMetricTags() map[string]string {
"paltform": self.Hypervisor,
"host": self.Host,
"host_id": self.HostId,
"ips": self.IPs,
"vm_ip": self.IPs,
"vm_id": self.Id,
"vm_name": self.Name,
"zone": self.Zone,
@@ -377,6 +384,7 @@ type GuestDiskInfo struct {
MediumType string `json:"medium_type"`
StorageType string `json:"storage_type"`
Iops int `json:"iops"`
Throughput int `json:"throughput"`
Bps int `json:"bps"`
ImageId string `json:"image_id,omitempty"`
Image string `json:"image,omitemtpy"`
@@ -706,6 +714,8 @@ type ServerDetachnetworkInput struct {
NetId string `json:"net_id"`
// 通过IP解绑网卡, 优先级高于mac
IpAddr string `json:"ip_addr"`
// 通过IP6 addr解绑网卡, 优先级高于mac
Ip6Addr string `json:"ip6_addr"`
// 通过Mac解绑网卡, 优先级低于ip_addr
Mac string `json:"mac"`
// 解绑后不立即同步配置
@@ -1201,7 +1211,7 @@ type ServerQgaGetNetworkInput struct {
}
type ServerQgaTimeoutInput struct {
// qga execute timeout millisecond
// qga execute timeout second
Timeout int
}
@@ -1421,3 +1431,8 @@ type ServerChangeBillingTypeInput struct {
// required: true
BillingType string `json:"billing_type"`
}
type ServerPerformStatusInput struct {
apis.PerformStatusInput
Containers map[string]*ContainerPerformStatusInput `json:"containers"`
}

View File

@@ -96,6 +96,8 @@ type HostListInput struct {
AccessMac []string `json:"access_mac"`
// 管理口Ip地址
AccessIp []string `json:"access_ip"`
// 公网IP地址
PublicIp []string `json:"public_ip"`
// 物理机序列号信息
SN []string `json:"sn"`
// CPU大小
@@ -163,6 +165,30 @@ type HostListInput struct {
// 按内存分配大小排序
// enmu: asc,desc
OrderByMemCommit string `json:"order_by_mem_commit"`
// 按物理cpu使用率排序
// enmu: asc,desc
OrderByCpuUsage string `json:"order_by_cpu_usage"`
// 按物理内存使用率排序
// enmu: asc,desc
OrderByMemUsage string `json:"order_by_mem_usage"`
// 按物理存储使用率排序
// enmu: asc,desc
OrderByStorageUsage string `json:"order_by_storage_usage"`
// 按虚拟内存使用率排序
// enmu: asc,desc
OrderByVirtualMemUsage string `json:"order_by_virtual_mem_usage"`
// 按虚拟cpu使用率排序
// enmu: asc,desc
OrderByVirtualCpuUsage string `json:"order_by_virtual_cpu_usage"`
// 按虚拟存储使用率排序
// enmu: asc,desc
OrderByVirtualStorageUsage string `json:"order_by_virtual_storage_usage"`
}
type HostDetails struct {
@@ -250,6 +276,8 @@ type HostDetails struct {
SysWarn string `json:"sys_warn"`
// host init error info
SysError string `json:"sys_error"`
HostFiles []string `json:"host_files"`
}
func (self HostDetails) GetMetricTags() map[string]string {
@@ -646,6 +674,12 @@ type HostAddNetifInput struct {
Reserve *bool `json:"reserve"`
RequireDesignatedIp *bool `json:"require_designated_ip"`
Ip6Addr string `json:"ip6_addr"`
RequireIpv6 *bool `json:"require_ipv6"`
StrictIpv6 *bool `json:"strict_ipv6"`
}
type HostEnableNetifInput struct {
@@ -664,6 +698,12 @@ type HostEnableNetifInput struct {
Reserve *bool `json:"reserve"`
RequireDesignatedIp *bool `json:"require_designated_ip"`
Ip6Addr string `json:"ip6_addr"`
RequireIpv6 *bool `json:"require_ipv6"`
StrictIpv6 *bool `json:"strict_ipv6"`
}
type HostDisableNetifInput struct {
@@ -711,13 +751,13 @@ type HostUploadGuestsStatusRequest struct {
GuestIds []string `json:"guest_ids"`
}
type HostUploadGuestStatusResponse struct {
type HostUploadGuestStatusInput struct {
apis.PerformStatusInput
Containers map[string]*ContainerPerformStatusInput `json:"containers"`
}
type HostUploadGuestsStatusResponse struct {
Guests map[string]*HostUploadGuestStatusResponse `json:"guests"`
type HostUploadGuestsStatusInput struct {
Guests map[string]*HostUploadGuestStatusInput `json:"guests"`
}
type GuestUploadContainerStatusResponse struct {

View File

@@ -123,6 +123,11 @@ const (
HostResourceTypeDedicated = "dedicated"
)
const (
HOST_METADATA_CPU_USAGE_PERCENT = "cpu_usage_percent"
HOST_METADATA_MEMORY_USED_MB = "memory_used_mb"
)
var HOST_TYPES = []string{
HOST_TYPE_BAREMETAL,
HOST_TYPE_HYPERVISOR,

View File

@@ -0,0 +1,62 @@
// 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 compute
import (
"yunion.io/x/onecloud/pkg/apis"
)
type HostFileType string
const (
PlainFile HostFileType = "plain"
ScriptFile HostFileType = "script"
TelegrafConf HostFileType = "telegraf"
ApparmorProfile HostFileType = "apparmor"
)
type HostFileCreateInput struct {
apis.InfrasResourceBaseCreateInput
Path string `json:"path" help:"Path of the host file"`
Content string `json:"content" help:"Content of the host file"`
Type HostFileType `json:"type" help:"Type of the host file"`
}
type HostFileUpdateInput struct {
apis.InfrasResourceBaseUpdateInput
Path string `json:"path"`
Content string `json:"content"`
}
type HostFileListInput struct {
apis.InfrasResourceBaseListInput
Type []string `json:"type"`
Path string `json:"path"`
}
type HostSetHostFilesInput struct {
HostFiles []string `json:"host_files"`
}
type HostFileDetails struct {
apis.InfrasResourceBaseDetails
Hosts []string `json:"hosts"`
SHostFile
}

View File

@@ -147,6 +147,8 @@ type SnapshotPolicyListInput struct {
// 按绑定的磁盘数量排序
// pattern:asc|desc
OrderByBindDiskCount string `json:"order_by_bind_disk_count"`
// 按类型过滤
Type string `json:"type"`
}
type HostnameInput struct {

View File

@@ -78,6 +78,11 @@ type IsolatedDeviceListInput struct {
// 列出虚拟机上挂载的设备
GuestId string `json:"guest_id"`
// GPU index
Index *int `json:"index"`
// Nvidia GPU minor number, parsing from /proc/driver/nvidia/gpus/*/information
DeviceMinor *int `json:"device_minor"`
}
type IsolatedDeviceCreateInput struct {
@@ -127,7 +132,9 @@ type IsolatedDeviceUpdateInput struct {
// PCIE information
PCIEInfo *IsolatedDevicePCIEInfo `json:"pcie_info"`
// Host device path
DevicePath string `json:"device_path"`
DevicePath string `json:"device_path"`
Index int `json:"index"`
DeviceMinor int `json:"device_minor"`
}
type IsolatedDeviceJsonDesc struct {

View File

@@ -67,6 +67,17 @@ type LoadbalancerListInput struct {
UsableLoadbalancerForEip string `json:"usable_loadbalancer_for_eip"`
}
type LbEip struct {
// 公网IP地址
Eip string `json:"eip"`
EipId string `json:"eip_id"`
// 公网IP地址类型: 弹性、非弹性
// example: public_ip
EipMode string `json:"eip_mode"`
}
type LoadbalancerDetails struct {
apis.VirtualResourceDetails
@@ -82,14 +93,9 @@ type LoadbalancerDetails struct {
SLoadbalancer
// 公网IP地址
Eip string `json:"eip"`
LbEip
EipId string `json:"eip_id"`
// 公网IP地址类型: 弹性、非弹性
// example: public_ip
EipMode string `json:"eip_mode"`
Eips []LbEip `json:"eips"`
// 后端服务器组名称
BackendGroup string `json:"backend_group"`

View File

@@ -381,9 +381,10 @@ var LB_ALIYUN_COMMON_SCHEDULER_TYPES = choices.NewChoices(
// TODO raw type
const (
LB_BACKEND_GUEST = compute.LB_BACKEND_GUEST
LB_BACKEND_HOST = compute.LB_BACKEND_HOST
LB_BACKEND_IP = compute.LB_BACKEND_IP
LB_BACKEND_GUEST = compute.LB_BACKEND_GUEST
LB_BACKEND_HOST = compute.LB_BACKEND_HOST
LB_BACKEND_IP = compute.LB_BACKEND_IP
LB_BACKEND_ADDRESS = compute.LB_BACKEND_ADDRESS
)
var LB_BACKEND_TYPES = []string{

View File

@@ -0,0 +1,61 @@
// 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 compute
import (
"yunion.io/x/onecloud/pkg/apis"
)
type LoadbalancerHealthCheckDetails struct {
apis.VirtualResourceDetails
ManagedResourceInfo
CloudregionResourceInfo
}
type LoadbalancerHealthCheckListInput struct {
apis.VirtualResourceListInput
apis.ExternalizedResourceBaseListInput
ManagedResourceListInput
RegionalFilterListInput
}
type SLoadbalancerHealthCheckCreateInput struct {
apis.VirtualResourceCreateInput
CloudregionResourceInput
CloudproviderResourceInput
HealthCheckType string
HealthCheckDomain string
HealthCheckURI string
HealthCheckHttpCode string
HealthCheckMethod string
HealthCheckPort int
HealthCheckRise int
HealthCheckFall int
HealthCheckTimeout int
HealthCheckInterval int
HealthCheckReq string
HealthCheckExp string
}
type SLoadbalancerHealthCheckUpdateInput struct {
apis.VirtualResourceBaseUpdateInput
}

View File

@@ -14,7 +14,14 @@
package compute
import "yunion.io/x/onecloud/pkg/apis"
import (
"reflect"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/onecloud/pkg/apis"
)
type LoadbalancerBackendGroupDetails struct {
apis.StatusStandaloneResourceDetails
@@ -22,6 +29,8 @@ type LoadbalancerBackendGroupDetails struct {
SLoadbalancerBackendGroup
LoadbalancerHealthCheck string `json:"loadbalancer_health_check"`
LbListenerCount int `json:"lb_listener_count"`
IsDefault bool `json:"is_default"`
@@ -62,7 +71,9 @@ type LoadbalancerBackendGroupCreateInput struct {
//swagger: ignore
Loadbalancer string `json:"loadbalancer" yunion-deprecated-by:"loadbalancer_id"`
// 负载均衡ID
LoadbalancerId string `json:"loadbalancer_id"`
LoadbalancerId string `json:"loadbalancer_id"`
Scheduler string `json:"scheduler"`
LoadbalancerHealthCheckId string `json:"loadbalancer_health_check_id"`
Type string `json:"type"`
@@ -92,3 +103,45 @@ type LoadbalancerBackendGroupListInput struct {
Type []string `json:"type"`
}
type ListenerRuleBackendGroup struct {
// 后端服务器组组ID
Id string
// swagger:ignore
Name string
// swagger:ignore
ExternalId string
}
type ListenerRuleBackendGroups []ListenerRuleBackendGroup
func (groups ListenerRuleBackendGroups) String() string {
return jsonutils.Marshal(groups).String()
}
func (groups ListenerRuleBackendGroups) IsZero() bool {
return len(groups) == 0
}
type ListenerRuleRedirectPool struct {
RegionPools map[string]ListenerRuleBackendGroups
CountryPools map[string]ListenerRuleBackendGroups
}
func (pool ListenerRuleRedirectPool) String() string {
return jsonutils.Marshal(pool).String()
}
func (pool ListenerRuleRedirectPool) IsZero() bool {
return len(pool.RegionPools) == 0 && len(pool.CountryPools) == 0
}
func init() {
gotypes.RegisterSerializable(reflect.TypeOf(&ListenerRuleBackendGroups{}), func() gotypes.ISerializable {
return &ListenerRuleBackendGroups{}
})
gotypes.RegisterSerializable(reflect.TypeOf(&ListenerRuleRedirectPool{}), func() gotypes.ISerializable {
return &ListenerRuleRedirectPool{}
})
}

View File

@@ -29,6 +29,7 @@ type LoadbalancerListenerRuleDetails struct {
LoadbalancerListenerResourceInfo
SLoadbalancerListenerRule
LoadbalancerCertificateResourceInfo
BackendGroup string `json:"backend_group"`
@@ -57,9 +58,18 @@ type LoadbalancerListenerRuleCreateInput struct {
Listener string `json:"listener" yunion-deprecated-by:"listener_id"`
ListenerId string `json:"listener_id"`
BackendGroup string `json:"backend_group" yunion-deprecated-by:"backend_group_id"`
CertificateId string `json:"certificate_id"`
// swagger:ignore
BackendGroup string `json:"backend_group" yunion-deprecated-by:"backend_group_id"`
// 默认后端服务器组ID
BackendGroupId string `json:"backend_group_id"`
// 后端服务器组列表
BackendGroups ListenerRuleBackendGroups `json:"backend_groups"`
RedirectPool ListenerRuleRedirectPool `json:"redirect_pool"`
Domain string `json:"domain"`
Path string `json:"path"`
HttpRequstRate int `json:"http_request_rate"`

View File

@@ -117,8 +117,8 @@ type NatgatewayCreateInput struct {
// default: false
AutoRenew bool `json:"auto_renew"`
// 到期释放时间,仅后付费支持
ExpiredAt time.Time `json:"expired_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
// 计费方式
// enum: ["postpaid", "prepaid"]

View File

@@ -36,9 +36,10 @@ const (
)
const (
POD_METADATA_CRI_ID = "cri_id"
POD_METADATA_CRI_CONFIG = "cri_config"
POD_METADATA_PORT_MAPPINGS = "port_mappings"
POD_METADATA_CRI_ID = "cri_id"
POD_METADATA_CRI_CONFIG = "cri_config"
POD_METADATA_PORT_MAPPINGS = "port_mappings"
POD_METADATA_POST_STOP_CLEANUP_CONFIG = "post_stop_cleanup_config"
)
type PodContainerCreateInput struct {
@@ -164,3 +165,7 @@ func ValidatePodLogOptions(opts *PodLogOptions) error {
}
return nil
}
type PodPostStopCleanupConfig struct {
Dirs []string `json:"dirs"`
}

View File

@@ -255,6 +255,8 @@ type SecgroupResourceInput struct {
type SecgroupFilterListInput struct {
SecgroupResourceInput
RegionalFilterListInput
ManagedResourceListInput
// 以安全组排序
OrderBySecgroup string `json:"order_by_secgroup"`
@@ -291,6 +293,16 @@ type SecgroupDetails struct {
type SecurityGroupResourceInfo struct {
// 安全组名称
Secgroup string `json:"secgroup"`
// VPC归属区域ID
CloudregionId string `json:"cloudregion_id"`
CloudregionResourceInfo
// VPC归属云订阅ID
ManagerId string `json:"manager_id"`
ManagedResourceInfo
}
type GuestsecgroupListInput struct {

View File

@@ -77,6 +77,9 @@ type SnapshotListInput struct {
// 未关联任何磁盘
Unused bool `json:"unused"`
// 按存储过滤
StorageId string `json:"storage_id"`
// 按虚拟机名称排序
// pattern:asc|desc
OrderByGuest string `json:"order_by_guest"`

View File

@@ -30,6 +30,9 @@ const (
SNAPSHOT_POLICY_APPLY_FAILED = "apply_failed"
SNAPSHOT_POLICY_CANCEL = "canceling"
SNAPSHOT_POLICY_CANCEL_FAILED = "cancel_failed"
SNAPSHOT_POLICY_TYPE_DISK = "disk"
SNAPSHOT_POLICY_TYPE_SERVER = "server"
)
type SnapshotPolicyDetails struct {
@@ -41,7 +44,8 @@ type SnapshotPolicyDetails struct {
RetentionDays int `json:"retention_days"`
BindingDiskCount int `json:"binding_disk_count"`
BindingDiskCount int `json:"binding_disk_count"`
BindingResourceCount int `json:"binding_resource_count"`
}
type SSnapshotPolicyCreateInput struct {
@@ -49,7 +53,10 @@ type SSnapshotPolicyCreateInput struct {
CloudproviderResourceInput
CloudregionResourceInput
RetentionDays int `json:"retention_days"`
RetentionDays int `json:"retention_days"`
RetentionCount int `json:"retention_count"`
// 快照类型, 目前支持 disk, server
Type string `json:"type"`
RepeatWeekdays []int `json:"repeat_weekdays"`
@@ -92,7 +99,8 @@ func (self *SSnapshotPolicyCreateInput) Validate() error {
type SSnapshotPolicyUpdateInput struct {
apis.VirtualResourceBaseUpdateInput
RetentionDays *int
RetentionDays *int
RegentionCount *int
RepeatWeekdays *[]int `json:"repeat_weekdays"`
TimePoints *[]int `json:"time_points"`
@@ -131,6 +139,13 @@ type SnapshotPolicyDisksInput struct {
Disks []string `json:"disk"`
}
type SnapshotPolicyResourcesInput struct {
Resources []struct {
Id string `json:"id"`
Type string `json:"type"`
} `json:"resources"`
}
type RepeatWeekdays []int
func (days RepeatWeekdays) String() string {

View File

@@ -14,20 +14,42 @@
package compute
import "yunion.io/x/onecloud/pkg/apis"
import (
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/apis"
)
const (
SSL_ISSUER_LETSENCRYPT = cloudprovider.SSL_ISSUER_LETSENCRYPT
SSL_ISSUER_ZEROSSL = cloudprovider.SSL_ISSUER_ZEROSSL
)
// 资源创建参数, 目前仅占位
type SSLCertificateCreateInput struct {
apis.VirtualResourceCreateInput
Issuer string `json:"issuer"`
DnsZoneId string `json:"dns_zone_id"`
Sans string `json:"sans"`
Province string
Common string
Country string
City string
OrgName string
Certificate string
PrivateKey string
}
// 资源返回详情
type SSLCertificateDetails struct {
apis.VirtualResourceDetails
ManagedResourceInfo
CloudregionResourceInfo
// 是否过期
IsExpired bool `json:"is_expired"`
}
// 资源列表请求参数
type SSLCertificateListInput struct {
apis.VirtualResourceListInput
apis.ExternalizedResourceBaseListInput
@@ -35,4 +57,7 @@ type SSLCertificateListInput struct {
RegionalFilterListInput
ManagedResourceListInput
DnsZoneFilterListBase
IsExpired *bool `json:"is_expired"`
}

View File

@@ -74,6 +74,8 @@ const (
STORAGE_CLOUD_BASIC = compute.STORAGE_CLOUD_BASIC
STORAGE_CLOUD_PREMIUM = compute.STORAGE_CLOUD_PREMIUM //高性能云硬盘
STORAGE_CLOUD_HSSD = compute.STORAGE_CLOUD_HSSD //增强型SSD云硬盘
STORAGE_CLOUD_BSSD = compute.STORAGE_CLOUD_BSSD //增强型SSD云硬盘
STORAGE_CLOUD_TSSD = compute.STORAGE_CLOUD_TSSD //极速型SSD云硬盘
// huawei storage type
STORAGE_HUAWEI_SSD = compute.STORAGE_HUAWEI_SSD // 超高IO云硬盘

View File

@@ -168,6 +168,7 @@ type NetworkTopologyOutput struct {
type HostnetworkTopologyOutput struct {
IpAddr string `json:"ip_addr"`
Ip6Addr string `json:"ip6_addr"`
MacAddr string `json:"mac_addr"`
}

View File

@@ -16,6 +16,7 @@ package compute
import (
"fmt"
"strings"
"yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/pkg/util/netutils"
@@ -51,12 +52,22 @@ const (
sVpcInterExtIP2 = "100.65.0.2"
VpcInterExtMac1 = "ee:ee:ee:ee:ee:f0"
VpcInterExtMac2 = "ee:ee:ee:ee:ee:f1"
sVpcInterCidr6 = "fc00::fffe:100:65:0:0/100"
sVpcInterExtCidr6 = "fc00::fffe:100:65:0:0/112"
VpcInterExtMask6 = 112
sVpcInterExtIP16 = "fc00::fffe:100:65:0:1"
sVpcInterExtIP26 = "fc00::fffe:100:65:0:2"
)
var (
vpcInterCidr netutils.IPV4Prefix
vpcInterExtIP1 netutils.IPV4Addr
vpcInterExtIP2 netutils.IPV4Addr
vpcInterCidr6 netutils.IPV6Prefix
vpcInterExtIP16 netutils.IPV6Addr
vpcInterExtIP26 netutils.IPV6Addr
)
func VpcInterCidr() netutils.IPV4Prefix {
@@ -71,12 +82,28 @@ func VpcInterExtIP2() netutils.IPV4Addr {
return vpcInterExtIP2
}
func VpcInterCidr6() netutils.IPV6Prefix {
return vpcInterCidr6
}
func VpcInterExtIP16() netutils.IPV6Addr {
return vpcInterExtIP16
}
func VpcInterExtIP26() netutils.IPV6Addr {
return vpcInterExtIP26
}
const (
sVpcMappedCidr = "100.64.0.0/17"
VpcMappedIPMask = 17
sVpcMappedGatewayIP = "100.64.0.1"
VpcMappedGatewayMac = "ee:ee:ee:ee:ee:ee"
sVpcMappedCidr6 = "fc00::fffe:100:64:0:0/100"
VpcMappedIPMask6 = 100
sVpcMappedGatewayIP6 = "fc00::fffe:100:64:0:1"
// reserved: [100.64.0.2, 100.64.0.127]
// [128, 2176 (128+2048)]
@@ -98,18 +125,31 @@ const (
sVpcEipGatewayIP = "100.64.128.2"
VpcEipGatewayMac = "ee:ee:ee:ee:ee:ef"
sVpcEipGatewayCidr6 = "fc00::fffe:100:64:f000:0/100"
VpcEipGatewayIPMask6 = 100
sVpcEipGatewayIP6 = "fc00::fffe:100:64:f000:2"
sVpcEipGatewayIP3 = "100.64.128.3"
VpcEipGatewayMac3 = "ee:ee:ee:ee:ee:f0"
sVpcEipGatewayIP63 = "fc00::fffe:100:64:f000:3"
)
var (
vpcMappedCidr netutils.IPV4Prefix
vpcMappedGatewayIP netutils.IPV4Addr
vpcMappedCidr6 netutils.IPV6Prefix
vpcMappedGatewayIP6 netutils.IPV6Addr
vpcEipGatewayCidr netutils.IPV4Prefix
vpcEipGatewayIP netutils.IPV4Addr
vpcEipGatewayIP3 netutils.IPV4Addr
vpcEipGatewayCidr6 netutils.IPV6Prefix
vpcEipGatewayIP6 netutils.IPV6Addr
vpcEipGatewayIP63 netutils.IPV6Addr
vpcMappedHostIPStart netutils.IPV4Addr
vpcMappedHostIPEnd netutils.IPV4Addr
@@ -131,17 +171,41 @@ func init() {
return v
}
mi6 := func(v netutils.IPV6Addr, err error) netutils.IPV6Addr {
if err != nil {
panic(err.Error())
}
return v
}
mp6 := func(v netutils.IPV6Prefix, err error) netutils.IPV6Prefix {
if err != nil {
panic(err.Error())
}
return v
}
vpcInterCidr = mp(netutils.NewIPV4Prefix(sVpcInterCidr))
vpcInterExtIP1 = mi(netutils.NewIPV4Addr(sVpcInterExtIP1))
vpcInterExtIP2 = mi(netutils.NewIPV4Addr(sVpcInterExtIP2))
vpcInterCidr6 = mp6(netutils.NewIPV6Prefix(sVpcInterCidr6))
vpcInterExtIP16 = mi6(netutils.NewIPV6Addr(sVpcInterExtIP16))
vpcInterExtIP26 = mi6(netutils.NewIPV6Addr(sVpcInterExtIP26))
vpcMappedCidr = mp(netutils.NewIPV4Prefix(sVpcMappedCidr))
vpcMappedGatewayIP = mi(netutils.NewIPV4Addr(sVpcMappedGatewayIP))
vpcMappedCidr6 = mp6(netutils.NewIPV6Prefix(sVpcMappedCidr6))
vpcMappedGatewayIP6 = mi6(netutils.NewIPV6Addr(sVpcMappedGatewayIP6))
vpcEipGatewayCidr = mp(netutils.NewIPV4Prefix(sVpcEipGatewayCidr))
vpcEipGatewayIP = mi(netutils.NewIPV4Addr(sVpcEipGatewayIP))
vpcEipGatewayIP3 = mi(netutils.NewIPV4Addr(sVpcEipGatewayIP3))
vpcEipGatewayCidr6 = mp6(netutils.NewIPV6Prefix(sVpcEipGatewayCidr6))
vpcEipGatewayIP6 = mi6(netutils.NewIPV6Addr(sVpcEipGatewayIP6))
vpcEipGatewayIP63 = mi6(netutils.NewIPV6Addr(sVpcEipGatewayIP63))
vpcMappedHostIPStart = mi(netutils.NewIPV4Addr(sVpcMappedHostIPStart))
vpcMappedHostIPEnd = mi(netutils.NewIPV4Addr(sVpcMappedHostIPEnd))
@@ -153,22 +217,42 @@ func VpcMappedCidr() netutils.IPV4Prefix {
return vpcMappedCidr
}
func VpcMappedCidr6() netutils.IPV6Prefix {
return vpcMappedCidr6
}
func VpcMappedGatewayIP() netutils.IPV4Addr {
return vpcMappedGatewayIP
}
func VpcMappedGatewayIP6() netutils.IPV6Addr {
return vpcMappedGatewayIP6
}
func VpcEipGatewayCidr() netutils.IPV4Prefix {
return vpcEipGatewayCidr
}
func VpcEipGatewayCidr6() netutils.IPV6Prefix {
return vpcEipGatewayCidr6
}
func VpcEipGatewayIP() netutils.IPV4Addr {
return vpcEipGatewayIP
}
func VpcEipGatewayIP6() netutils.IPV6Addr {
return vpcEipGatewayIP6
}
func VpcEipGatewayIP3() netutils.IPV4Addr {
return vpcEipGatewayIP3
}
func VpcEipGatewayIP63() netutils.IPV6Addr {
return vpcEipGatewayIP63
}
func VpcMappedHostIPStart() netutils.IPV4Addr {
return vpcMappedHostIPStart
}
@@ -188,3 +272,8 @@ func VpcMappedIPEnd() netutils.IPV4Addr {
func VpcOvnEncapCostStr() string {
return fmt.Sprintf("%d", VPC_OVN_ENCAP_COST)
}
func GenVpcMappedIP6(ip string) string {
segs := strings.Split(ip, ".")
return fmt.Sprintf("fc00::fffe:100:64:%s:%s", segs[2], segs[3])
}

View File

@@ -16,6 +16,7 @@ package compute
import (
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/apis"
)
@@ -32,7 +33,7 @@ const (
)
type WafRuleListInput struct {
apis.StatusStandaloneResourceListInput
apis.EnabledStatusStandaloneResourceListInput
apis.ExternalizedResourceBaseListInput
// WAF实例Id
@@ -40,13 +41,21 @@ type WafRuleListInput struct {
// WAF规则组Id
WafRuleGroupId string `json:"waf_rule_group_id"`
Type string `json:"type"`
}
type WafRuleCreateInput struct {
apis.StatusStandaloneResourceCreateInput
apis.EnabledStatusStandaloneResourceCreateInput
// WAF实例Id
WafInstanceId string `json:"waf_instance_id"`
// 规则类型
Type string `json:"type"`
// 规则表达式
Expression string `json:"expression"`
// 规则配置
Config jsonutils.JSONObject `json:"config"`
// 优先级,不可重复
// Azure优先级范围1-100
@@ -65,14 +74,31 @@ type WafRuleCreateInput struct {
}
type WafRuleDetails struct {
apis.StatusStandaloneResourceDetails
apis.EnabledStatusStandaloneResourceDetails
SWafRule
Statements []cloudprovider.SWafStatement
}
type WafRuleUpdateInput struct {
apis.StatusStandaloneResourceBaseUpdateInput
apis.EnabledStatusStandaloneResourceBaseUpdateInput
// 规则表达式
Expression string `json:"expression"`
// 规则配置
Config jsonutils.JSONObject `json:"config"`
// 匹配后默认行为
Action *cloudprovider.DefaultAction `json:"action"`
// 优先级
Priority *int `json:"priority"`
// 条件表达式
Statements []cloudprovider.SWafStatement
}
type WafRuleEnableInput struct {
apis.PerformEnableInput
}
type WafRuleDisableInput struct {
apis.PerformDisableInput
}

View File

@@ -247,7 +247,6 @@ type SCloudaccount struct {
// 云系统信息
Sysinfo jsonutils.JSONObject `json:"sysinfo"`
// 品牌信息, 一般和provider相同
// example: DStack
Brand string `json:"brand"`
// 额外信息
Options *jsonutils.JSONDict `json:"options"`
@@ -568,6 +567,8 @@ type SDisk struct {
Preallocation string `json:"preallocation"`
// # is persistent
Nonpersistent bool `json:"nonpersistent"`
// auto reset disk after guest shutdown
AutoReset bool `json:"auto_reset"`
// 是否标记为SSD磁盘
IsSsd bool `json:"is_ssd"`
// 最大连接数
@@ -1014,6 +1015,8 @@ type SGuest struct {
VmemSize int `json:"vmem_size"`
// CPU 内存绑定信息
CpuNumaPin jsonutils.JSONObject `json:"cpu_numa_pin"`
// 额外分配的 CPU 数量
ExtraCpuCount int `json:"extra_cpu_count"`
// 启动顺序
BootOrder string `json:"boot_order"`
// 关机操作类型
@@ -1266,6 +1269,21 @@ type SHostBackupstorage struct {
BackupstorageId string `json:"backupstorage_id"`
}
// SHostFile is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SHostFile.
type SHostFile struct {
apis.SInfrasResourceBase
Type string `json:"type"`
Path string `json:"path"`
Content string `json:"content"`
}
// SHostFileJoint is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SHostFileJoint.
type SHostFileJoint struct {
HostId string `json:"host_id"`
HostFileId string `json:"host_file_id"`
Deleted bool `json:"deleted"`
}
// SHostJointsBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SHostJointsBase.
type SHostJointsBase struct {
apis.SJointResourceBase
@@ -1449,6 +1467,8 @@ type SInterVpcNetworkVpc struct {
// SIsolatedDevice is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SIsolatedDevice.
type SIsolatedDevice struct {
apis.SStandaloneResourceBase
apis.SExternalizedResourceBase
apis.SSharableBaseResource
SHostResourceBase
// # PCI / GPU-HPC / GPU-VGA / USB / NIC
// 设备类型

View File

@@ -53,11 +53,16 @@ const (
STATUS_SYNC_STATUS = "sync_status"
STATUS_DELETING = "deleting"
STATUS_DELETE_FAILED = "delete_failed"
STATUS_CHANGE_CONFIG = "change_config"
STATUS_UNKNOWN = "unknown"
STATUS_CREATING = "creating"
STATUS_AVAILABLE = "available"
STATUS_CREATE_FAILED = "create_failed"
// 更改计费模式
STATUS_CHANGE_BILLING_TYPE = "change_billing_type"
STATUS_CHANGE_BILLING_TYPE_FAILED = "change_billing_type_failed"
CLOUD_TAG_PREFIX = "ext:"
USER_TAG_PREFIX = "user:"
SYS_CLOUD_TAG_PREFIX = "sys:"
@@ -69,7 +74,7 @@ const (
SKU_STATUS_AVAILABLE = "available"
SKU_STATUS_SOLDOUT = "soldout"
MetaServiceMonitorAgentUrl = "http://169.254.169.254/monitor"
MetaServiceMonitorAgentUrl = "http://%s/monitor"
)
var (
@@ -86,6 +91,7 @@ var (
SERVICE_TYPE_CLOUDEVENT,
SERVICE_TYPE_ANSIBLE,
SERVICE_TYPE_INFLUXDB,
SERVICE_TYPE_VICTORIA_METRICS,
SERVICE_TYPE_APIMAP,
SERVICE_TYPE_LOG,
"autoupdate",
@@ -108,6 +114,30 @@ var (
SERVICE_TYPE_ETCD,
"itsm",
SERVICE_TYPE_NTP,
"kafka",
}
EXTERNAL_SERVICES = []string{
SERVICE_TYPE_OFFLINE_CLOUDMETA,
SERVICE_TYPE_CLOUDMETA,
SERVICE_TYPE_SCHEDULER,
SERVICE_TYPE_VNCPROXY,
SERVICE_TYPE_ETCD,
SERVICE_TYPE_INFLUXDB,
SERVICE_TYPE_INFLUXDB,
SERVICE_TYPE_VICTORIA_METRICS,
SERVICE_TYPE_LOG,
"s3gateway",
"common",
"websocket",
"echarts-ssr",
"cloudwatcher",
"cloudnet",
"repo",
SERVICE_TYPE_ETCD,
"itsm",
SERVICE_TYPE_NTP,
"kafka",
}
)

View File

@@ -90,8 +90,10 @@ const (
)
type ContainerIsolatedDeviceOnlyEnv struct {
Key string `json:"key"`
FromRenderPath bool `json:"from_render_path"`
Key string `json:"key"`
FromRenderPath bool `json:"from_render_path"`
FromIndex bool `json:"from_index"`
FromDeviceMinor bool `json:"from_device_minor"`
}
type ContainerSpec struct {
@@ -275,6 +277,8 @@ type ContainerVolumeMountDiskPostOverlay struct {
// 合并后要挂载到容器的目录
ContainerTargetDir string `json:"container_target_dir"`
Image *ContainerVolumeMountDiskPostImageOverlay `json:"image"`
FsUser *int64 `json:"fs_user,omitempty"`
FsGroup *int64 `json:"fs_group,omitempty"`
}
func (o ContainerVolumeMountDiskPostOverlay) IsEqual(input ContainerVolumeMountDiskPostOverlay) bool {
@@ -320,9 +324,17 @@ const (
CONTAINER_VOLUME_MOUNT_HOST_PATH_TYPE_FILE ContainerVolumeMountHostPathType = "file"
)
type ContainerVolumeMountHostPathAutoCreateConfig struct {
Uid uint `json:"uid"`
Gid uint `json:"gid"`
Permissions string `json:"permissions"`
}
type ContainerVolumeMountHostPath struct {
Type ContainerVolumeMountHostPathType `json:"type"`
Path string `json:"path"`
Type ContainerVolumeMountHostPathType `json:"type"`
Path string `json:"path"`
AutoCreate bool `json:"auto_create"`
AutoCreateConfig *ContainerVolumeMountHostPathAutoCreateConfig `json:"auto_create_config,omitempty"`
}
type ContainerVolumeMountText struct {
@@ -344,3 +356,9 @@ type ContainerPullImageAuthConfig struct {
// RegistryToken is a bearer token to be sent to a registry
RegistryToken string `json:"registry_token,omitempty"`
}
type ContainerRootfs struct {
Type ContainerVolumeMountType `json:"type"`
Disk *ContainerVolumeMountDisk `json:"disk"`
//CephFS *ContainerVolumeMountCephFS `json:"ceph_fs"`
}

View File

@@ -41,6 +41,12 @@ type ContainerVolumeMountCephFS struct {
Name string `json:"name"`
}
type ContainerRootfs struct {
Type apis.ContainerVolumeMountType `json:"type"`
Disk *ContainerVolumeMountDisk `json:"disk"`
// CephFS *ContainerVolumeMountCephFS `json:"ceph_fs"`
}
type ContainerVolumeMount struct {
// 用于标识当前 pod volume mount 的唯一性
UniqueName string `json:"unique_name"`
@@ -65,6 +71,7 @@ type ContainerVolumeMount struct {
type ContainerSpec struct {
apis.ContainerSpec
ImageCredentialToken string `json:"image_credential_token"`
Rootfs *ContainerRootfs `json:"rootfs"`
VolumeMounts []*ContainerVolumeMount `json:"volume_mounts"`
Devices []*ContainerDevice `json:"devices"`
}
@@ -79,13 +86,15 @@ type ContainerDevice struct {
}
type ContainerIsolatedDevice struct {
Id string `json:"id"`
Addr string `json:"addr"`
Path string `json:"path"`
DeviceType string `json:"device_type"`
CardPath string `json:"card_path"`
RenderPath string `json:"render_path"`
OnlyEnv []*apis.ContainerIsolatedDeviceOnlyEnv `json:"only_env"`
Id string `json:"id"`
Addr string `json:"addr"`
Path string `json:"path"`
DeviceType string `json:"device_type"`
CardPath string `json:"card_path"`
RenderPath string `json:"render_path"`
Index int `json:"index"`
DeviceMinor int `json:"device_minor"`
OnlyEnv []*apis.ContainerIsolatedDeviceOnlyEnv `json:"only_env"`
}
type ContainerHostDevice struct {
@@ -130,6 +139,8 @@ type ContainerSaveVolumeMountToImageInput struct {
VolumeMountIndex int `json:"volume_mount_index"`
VolumeMount *ContainerVolumeMount `json:"volume_mount"`
VolumeMountDirs []string `json:"volume_mount_dirs"`
VolumeMountPrefix string `json:"volume_mount_prefix"`
}
type ContainerCommitInput struct {

View File

@@ -119,6 +119,8 @@ var (
"platform_names",
"enable_change_owner_auto_rename",
"default_handlers_whitelist_user_agents",
"metadata_server_ip4s",
"metadata_server_ip6s",
},
}

View File

@@ -14,7 +14,13 @@
package apis
import "time"
import (
"time"
"yunion.io/x/pkg/util/billing"
"yunion.io/x/onecloud/pkg/httperrors"
)
type DomainizedResourceInput struct {
// 指定项目归属域名称或ID
@@ -390,8 +396,25 @@ type DistinctFieldsInput struct {
}
type PostpaidExpireInput struct {
Duration string `json:"duration"`
ExpireTime time.Time `json:"expire_time"`
Duration string `json:"duration"`
// swagger:ignore
ExpireTime time.Time `json:"expire_time" yunion-deprecated-by:"release_at"`
// 到期释放时间
ReleaseAt time.Time `json:"release_at"`
}
func (input *PostpaidExpireInput) GetReleaseAt() (time.Time, error) {
if !input.ReleaseAt.IsZero() {
return input.ReleaseAt, nil
}
if len(input.Duration) == 0 {
return time.Time{}, httperrors.NewInputParameterError("missing duration/expire_time")
}
bc, err := billing.ParseBillingCycle(input.Duration)
if err != nil {
return time.Time{}, httperrors.NewInputParameterError("invalid duration: %s", input.Duration)
}
return bc.EndAt(time.Now()), nil
}
type AutoRenewInput struct {

View File

@@ -14,7 +14,11 @@
package monitor
import "yunion.io/x/onecloud/pkg/apis"
import (
"yunion.io/x/pkg/util/sets"
"yunion.io/x/onecloud/pkg/apis"
)
const EXT_PREFIX = "ext"
@@ -59,19 +63,33 @@ const (
)
var (
MetricCloudResTypes = sets.NewString(
METRIC_RES_TYPE_HOST,
METRIC_RES_TYPE_AGENT,
METRIC_RES_TYPE_GUEST,
METRIC_RES_TYPE_CONTAINER,
METRIC_RES_TYPE_OSS,
METRIC_RES_TYPE_RDS,
METRIC_RES_TYPE_REDIS,
METRIC_RES_TYPE_TENANT,
METRIC_RES_TYPE_DOMAIN,
METRIC_RES_TYPE_STORAGE,
METRIC_RES_TYPE_CLOUDACCOUNT)
MetricResType = []string{METRIC_RES_TYPE_GUEST, METRIC_RES_TYPE_HOST, METRIC_RES_TYPE_REDIS, METRIC_RES_TYPE_OSS,
METRIC_RES_TYPE_RDS, METRIC_RES_TYPE_CLOUDACCOUNT}
MetricUnit = []string{METRIC_UNIT_PERCENT, METRIC_UNIT_BPS, METRIC_UNIT_MBPS, METRIC_UNIT_BYTEPS, "count/s",
METRIC_UNIT_COUNT, METRIC_UNIT_MS, METRIC_UNIT_BYTE, METRIC_UNIT_NULL}
ResTypeScoreMap = map[string]float64{
METRIC_RES_TYPE_GUEST: 1,
METRIC_RES_TYPE_AGENT: 1.1,
METRIC_RES_TYPE_HOST: 2,
METRIC_RES_TYPE_OSS: 3,
METRIC_RES_TYPE_RDS: 4,
METRIC_RES_TYPE_REDIS: 5,
METRIC_RES_TYPE_CLOUDACCOUNT: 6,
METRIC_RES_TYPE_STORAGE: 7,
METRIC_RES_TYPE_HOST: -100,
METRIC_RES_TYPE_GUEST: -99,
METRIC_RES_TYPE_AGENT: -98,
METRIC_RES_TYPE_CONTAINER: -97,
METRIC_RES_TYPE_SYSTEM: -96,
METRIC_RES_TYPE_K8S: -95,
METRIC_RES_TYPE_ELB: -94,
METRIC_RES_TYPE_CLOUDACCOUNT: -93,
METRIC_RES_TYPE_STORAGE: -93,
}
)

View File

@@ -108,6 +108,9 @@ type SimpleQueryInput struct {
EndTime time.Time `json:"end_time"`
// 指定标签
Tags map[string]string `json:"tag_pairs"`
// 间隔周期
// default: 5m
Interval string `json:"interval"`
}
type CdfQueryInput struct {

View File

@@ -80,7 +80,7 @@ type SAlertPanel struct {
type SAlertRecord struct {
// db.SVirtualResourceBase
apis.SEnabledResourceBase
apis.SStatusStandaloneResourceBase
apis.SStandaloneAnonResourceBase
SMonitorScopedResource
AlertId string `json:"alert_id"`
Level string `json:"level"`
@@ -89,6 +89,7 @@ type SAlertRecord struct {
EvalData jsonutils.JSONObject `json:"eval_data"`
AlertRule jsonutils.JSONObject `json:"alert_rule"`
ResType string `json:"res_type"`
ResIds string `json:"res_ids"`
}
// SAlertRecordShield is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertRecordShield.

View File

@@ -102,6 +102,8 @@ type NotificationManagerEventNotifyInput struct {
// description: direct contact, admin privileges required
// required: false
Contacts []SContact `json:"contacts"`
// 消息机器人列表
RobotIds []string `json:"robot_ids"`
// description: contact types
// required: false
// example: email

View File

@@ -123,16 +123,6 @@ type SNotificationLog struct {
SendTimes int `json:"send_times"`
}
// SNotifyAction is an autogenerated struct via yunion.io/x/onecloud/pkg/notify/models.SNotifyAction.
type SNotifyAction struct {
apis.SEnabledStatusStandaloneResourceBase
}
// SNotifyResource is an autogenerated struct via yunion.io/x/onecloud/pkg/notify/models.SNotifyResource.
type SNotifyResource struct {
apis.SEnabledStatusStandaloneResourceBase
}
// SReceiver is an autogenerated struct via yunion.io/x/onecloud/pkg/notify/models.SReceiver.
type SReceiver struct {
apis.SVirtualResourceBase
@@ -216,14 +206,14 @@ type STopic struct {
// STopicAction is an autogenerated struct via yunion.io/x/onecloud/pkg/notify/models.STopicAction.
type STopicAction struct {
apis.SJointResourceBase
apis.SResourceBase
ActionId string `json:"action_id"`
TopicId string `json:"topic_id"`
}
// STopicResource is an autogenerated struct via yunion.io/x/onecloud/pkg/notify/models.STopicResource.
type STopicResource struct {
apis.SJointResourceBase
apis.SResourceBase
ResourceId string `json:"resource_id"`
TopicId string `json:"topic_id"`
}

View File

@@ -93,13 +93,13 @@ const (
var quitHandlerRegisted bool
func NewApplication(name string, connMax int, db bool) *Application {
func NewApplication(name string, connMax int, queueSize int, db bool) *Application {
app := Application{name: name,
context: ctx.CtxWithTime(),
connMax: connMax,
session: NewWorkerManager("HttpRequestWorkerManager", connMax, DEFAULT_BACKLOG, db),
readSession: NewWorkerManager("HttpGetRequestWorkerManager", connMax, DEFAULT_BACKLOG, db),
systemSession: NewWorkerManager("InternalHttpRequestWorkerManager", 1, DEFAULT_BACKLOG, false),
session: NewWorkerManager("HttpRequestWorkerManager", connMax, connMax*queueSize, db),
readSession: NewWorkerManager("HttpGetRequestWorkerManager", connMax, connMax*queueSize, db),
systemSession: NewWorkerManager("InternalHttpRequestWorkerManager", 1, queueSize, false),
roots: make(map[string]*RadixNode),
rootLock: &sync.RWMutex{},
idleTimeout: DEFAULT_IDLE_TIMEOUT,
@@ -424,7 +424,7 @@ func (app *Application) defaultHandle(w http.ResponseWriter, r *http.Request, ri
task.appParams.Body, _ = jsonutils.Parse(data)
r.Body = io.NopCloser(bytes.NewBuffer(data))
}
session.Run(
inqueue := session.Run(
task,
currentWorker,
func(err error) {
@@ -432,13 +432,17 @@ func (app *Application) defaultHandle(w http.ResponseWriter, r *http.Request, ri
task.fw.closeChannels()
},
)
runErr := task.fw.wait(task.ctx, currentWorker)
if runErr != nil {
switch je := runErr.(type) {
case *httputils.JSONClientError:
httperrors.GeneralServerError(task.ctx, w, je)
default:
httperrors.InternalServerError(task.ctx, w, "Internal server error")
if !inqueue {
httperrors.TooManyRequestsError(task.ctx, w, "Request queue is full")
} else {
runErr := task.fw.wait(task.ctx, currentWorker)
if runErr != nil {
switch je := runErr.(type) {
case *httputils.JSONClientError:
httperrors.GeneralServerError(task.ctx, w, je)
default:
httperrors.InternalServerError(task.ctx, w, "Internal server error")
}
}
}
task.fw.closeChannels()

View File

@@ -49,7 +49,7 @@ type ApplicationTestSuit struct {
}
func (suite *ApplicationTestSuit) SetupTest() {
suite.app = NewApplication("test", 4, false)
suite.app = NewApplication("test", 4, 10, false)
suite.app.AddHandler("GET", "/delay", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
time.Sleep(time.Second * 1)
Send(w, "delay pong")

View File

@@ -191,6 +191,12 @@ func NewWorkerManager(name string, workerCount int, backlog int, dbWorker bool)
}
func NewWorkerManagerIgnoreOverflow(name string, workerCount int, backlog int, dbWorker bool, ignoreOverflow bool) *SWorkerManager {
if workerCount <= 0 {
workerCount = 1
}
if backlog <= 0 {
backlog = 128
}
manager := SWorkerManager{name: name,
queue: NewRing(workerCount * backlog),
workerCount: workerCount,

View File

@@ -1040,20 +1040,22 @@ func (b *SBaremetalInstance) GetIPMINicIPAddr() string {
func (b *SBaremetalInstance) GetDHCPConfig(cliMac net.HardwareAddr) (*dhcp.ResponseConfig, error) {
var nic *types.SNic
var hostname string
var osName string
if b.GetServer() != nil && (b.GetTask() == nil || !b.GetTask().NeedPXEBoot()) {
nic = b.GetServer().GetNicByMac(cliMac)
hostname = b.GetServer().GetName()
hostname = b.GetServer().GetHostName()
osName = b.GetServer().GetOsName()
} else {
nic = b.GetNicByMac(cliMac)
}
if nic == nil {
return nil, fmt.Errorf("GetNicDHCPConfig no nic found by mac: %s", cliMac)
}
return b.getDHCPConfig(nic, hostname, false, 0)
return b.getDHCPConfig(nic, hostname, false, 0, osName)
}
func (b *SBaremetalInstance) GetPXEDHCPConfig(arch uint16) (*dhcp.ResponseConfig, error) {
return b.getDHCPConfig(b.GetAdminNic(), "", true, arch)
return b.getDHCPConfig(b.GetAdminNic(), "", true, arch, "Linux")
}
func (b *SBaremetalInstance) getDHCPConfig(
@@ -1061,10 +1063,14 @@ func (b *SBaremetalInstance) getDHCPConfig(
hostName string,
isPxe bool,
arch uint16,
osName string,
) (*dhcp.ResponseConfig, error) {
if hostName == "" {
hostName = b.GetName()
}
if osName == "" {
osName = "Linux"
}
serverIP, err := b.manager.Agent.GetDHCPServerIP()
if err != nil {
return nil, err
@@ -1078,7 +1084,7 @@ func (b *SBaremetalInstance) getDHCPConfig(
return nil, errors.Errorf("Baremetal %s not need UEFI PXE boot", b.GetName())
}
}
return GetNicDHCPConfig(nic, serverIP.String(), hostName, isPxe, arch)
return GetNicDHCPConfig(nic, serverIP, b.manager.Agent.ListenInterface.HardwareAddr, hostName, isPxe, arch, osName)
}
func (b *SBaremetalInstance) GetNotifyUrl() string {
@@ -2550,6 +2556,22 @@ func (server *SBaremetalServer) GetName() string {
return id
}
func (server *SBaremetalServer) GetHostName() string {
hostname, err := server.desc.GetString("hostname")
if err != nil {
log.Errorf("Get hostname from desc %s error: %v", server.desc.String(), err)
}
return hostname
}
func (server *SBaremetalServer) GetOsName() string {
osName, err := server.desc.GetString("os_name")
if err != nil {
log.Errorf("Get os name from desc %s error: %v", server.desc.String(), err)
}
return osName
}
func (server *SBaremetalServer) SaveDesc(desc jsonutils.JSONObject) error {
if desc != nil {
server.desc = desc.(*jsonutils.JSONDict)

View File

@@ -15,84 +15,155 @@
package baremetal
import (
"fmt"
"net"
"os"
"path/filepath"
"strings"
"time"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/util/regutils"
o "yunion.io/x/onecloud/pkg/baremetal/options"
"yunion.io/x/onecloud/pkg/cloudcommon/types"
"yunion.io/x/onecloud/pkg/util/dhcp"
"yunion.io/x/onecloud/pkg/util/netutils2"
)
func GetNicDHCPConfig(
n *types.SNic,
serverIP string,
serverIP net.IP,
serverMac net.HardwareAddr,
hostName string,
isPxe bool,
arch uint16,
osName string,
) (*dhcp.ResponseConfig, error) {
if n == nil {
return nil, fmt.Errorf("Nic is nil")
return nil, errors.Wrap(errors.ErrEmpty, "Nic is nil")
}
if n.IpAddr == "" {
return nil, fmt.Errorf("Nic no ip address")
}
ipAddr, err := netutils.NewIPV4Addr(n.IpAddr)
if err != nil {
return nil, fmt.Errorf("Parse IP address error: %q", n.IpAddr)
if n.IpAddr == "" && n.Ip6Addr == "" {
return nil, errors.Wrap(errors.ErrEmpty, "Nic no ip or ip6 address")
}
subnetMask := net.ParseIP(netutils.Masklen2Mask(n.Masklen).String())
routes := make([][]string, 0)
routes4 := make([]netutils2.SRouteInfo, 0)
routes6 := make([]netutils2.SRouteInfo, 0)
for _, route := range n.Routes {
routes = append(routes, []string{route[0], route[1]})
routeInfo, err := netutils2.ParseRouteInfo([]string{route[0], route[1]})
if err != nil {
return nil, errors.Wrapf(err, "Parse route %s error: %q", route, err)
}
if regutils.MatchCIDR6(route[0]) {
routes6 = append(routes6, *routeInfo)
} else {
routes4 = append(routes4, *routeInfo)
}
}
parseIPs := func(ips string) []net.IP {
ret := make([]net.IP, 0)
iplist := strings.Split(ips, ",")
for _, ip := range iplist {
ret = append(ret, net.ParseIP(ip))
}
return ret
}
isDefaultGW := false
if n.IsDefault == nil || *n.IsDefault {
isDefaultGW = true
parseDomains := func(domains string) []net.IP {
ret := make([]net.IP, 0)
domainlist := strings.Split(domains, ",")
for _, domain := range domainlist {
addrs, _ := net.LookupHost(domain)
for _, addr := range addrs {
ret = append(ret, net.ParseIP(addr))
}
if n.Gateway != "" && !strings.HasPrefix(strings.ToLower(osName), "win") {
routes4 = append(routes4, netutils2.SRouteInfo{
SPrefixInfo: netutils2.SPrefixInfo{
Prefix: net.ParseIP("0.0.0.0"),
PrefixLen: 0,
},
Gateway: net.ParseIP(n.Gateway),
})
}
if n.Gateway6 != "" {
routes6 = append(routes6, netutils2.SRouteInfo{
SPrefixInfo: netutils2.SPrefixInfo{
Prefix: net.ParseIP("::"),
PrefixLen: 0,
},
Gateway: net.ParseIP(n.Gateway6),
})
}
return ret
}
conf := &dhcp.ResponseConfig{
ServerIP: net.ParseIP(serverIP),
ClientIP: net.ParseIP(ipAddr.String()),
Gateway: net.ParseIP(n.Gateway),
SubnetMask: subnetMask,
BroadcastAddr: net.ParseIP(ipAddr.BroadcastAddr(n.Masklen).String()),
DNSServers: parseIPs(n.Dns),
NTPServers: parseDomains(n.Ntp),
Domain: n.Domain,
OsName: "Linux",
Hostname: hostName,
Routes: routes,
LeaseTime: time.Duration(o.Options.DhcpLeaseTime) * time.Second,
RenewalTime: time.Duration(o.Options.DhcpRenewalTime) * time.Second,
InterfaceMac: serverMac,
VlanId: uint16(n.VlanId),
ServerIP: serverIP,
Domain: n.Domain,
OsName: osName,
Hostname: strings.ToLower(hostName),
Routes: routes4,
Routes6: routes6,
LeaseTime: time.Duration(o.Options.DhcpLeaseTime) * time.Second,
RenewalTime: time.Duration(o.Options.DhcpRenewalTime) * time.Second,
IsDefaultGW: isDefaultGW,
}
if n.IpAddr != "" {
ipAddr, err := netutils.NewIPV4Addr(n.IpAddr)
if err != nil {
return nil, errors.Wrapf(err, "Parse IP address error: %q", n.IpAddr)
}
subnetMask := net.ParseIP(netutils.Masklen2Mask(n.Masklen).String())
conf.ClientIP = net.ParseIP(ipAddr.String())
conf.SubnetMask = subnetMask
conf.BroadcastAddr = net.ParseIP(ipAddr.BroadcastAddr(n.Masklen).String())
conf.Gateway = net.ParseIP(n.Gateway)
}
if n.Ip6Addr != "" {
ip6Addr, err := netutils.NewIPV6Addr(n.Ip6Addr)
if err != nil {
return nil, errors.Wrapf(err, "Parse IPv6 address error: %q", n.Ip6Addr)
}
conf.ClientIP6 = net.ParseIP(ip6Addr.String())
conf.PrefixLen6 = n.Masklen6
conf.Gateway6 = net.ParseIP(n.Gateway6)
}
if len(n.Dns) > 0 {
conf.DNSServers = make([]net.IP, 0)
conf.DNSServers6 = make([]net.IP, 0)
for _, dns := range strings.Split(n.Dns, ",") {
if regutils.MatchIP4Addr(dns) {
conf.DNSServers = append(conf.DNSServers, net.ParseIP(dns))
} else if regutils.MatchIP6Addr(dns) {
conf.DNSServers6 = append(conf.DNSServers6, net.ParseIP(dns))
}
}
}
if len(n.Ntp) > 0 {
conf.NTPServers = make([]net.IP, 0)
conf.NTPServers6 = make([]net.IP, 0)
for _, ntp := range strings.Split(n.Ntp, ",") {
if regutils.MatchIP4Addr(ntp) {
conf.NTPServers = append(conf.NTPServers, net.ParseIP(ntp))
} else if regutils.MatchIP6Addr(ntp) {
conf.NTPServers6 = append(conf.NTPServers6, net.ParseIP(ntp))
} else if regutils.MatchDomainName(ntp) {
ntpAddrs, _ := net.LookupHost(ntp)
for _, ntpAddr := range ntpAddrs {
if regutils.MatchIP4Addr(ntpAddr) {
conf.NTPServers = append(conf.NTPServers, net.ParseIP(ntpAddr))
} else if regutils.MatchIP6Addr(ntpAddr) {
conf.NTPServers6 = append(conf.NTPServers6, net.ParseIP(ntpAddr))
}
}
}
}
}
if n.Mtu > 0 {
conf.MTU = uint16(n.Mtu)
}
if isPxe {
conf.BootServer = serverIP
conf.BootServer = serverIP.String()
if len(o.Options.TftpBootServer) > 0 {
conf.BootServer = o.Options.TftpBootServer
}

View File

@@ -33,6 +33,7 @@ import (
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
"yunion.io/x/onecloud/pkg/util/ctx"
"yunion.io/x/onecloud/pkg/util/dhcp"
)
@@ -70,7 +71,7 @@ type dhcpRequest struct {
netConfig *types.SNetworkConfig
}
func (h *DHCPHandler) ServeDHCP(ctx context.Context, pkt dhcp.Packet, _ *net.UDPAddr, _ *net.Interface) (dhcp.Packet, []string, error) {
func (h *DHCPHandler) ServeDHCP(pkt dhcp.Packet, _ net.HardwareAddr, _ *net.UDPAddr) (dhcp.Packet, []string, error) {
req, err := h.newRequest(pkt, h.baremetalManager)
if err != nil {
log.Errorf("[DHCP] new request by packet error: %v", err)
@@ -82,7 +83,7 @@ func (h *DHCPHandler) ServeDHCP(ctx context.Context, pkt dhcp.Packet, _ *net.UDP
return nil, nil, fmt.Errorf("Request not from a DHCP relay, ignore mac: %s", req.ClientMac)
}
log.Infof("[DHCP] from relay %s packet, mac: %s", req.RelayAddr, req.ClientMac)
conf, targets, err := req.fetchConfig(ctx, h.baremetalManager.GetClientSession())
conf, targets, err := req.fetchConfig(ctx.CtxWithTime(), h.baremetalManager.GetClientSession())
if err != nil {
return nil, nil, errors.Wrapf(err, "fetchConfig for %s", req.ClientMac.String())
}

View File

@@ -41,4 +41,7 @@ type IBaremetalServer interface {
GetNicByMac(mac net.HardwareAddr) *types.SNic
GetRootTemplateId() string
GetHostName() string
GetOsName() string
}

View File

@@ -40,7 +40,13 @@ menuentry 'YunionOS for PXE' --class os {
`, sleepTime, kernel, kernel, kernelArgs, initrd, initrd)
}
// REF: https://github.com/bluebanquise/infrastructure/blob/master/packages/ipxe-bluebanquise/grub2-efi-autofind.cfg
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"
)
// REF: https://github.com/bluebanquise/infrastructure/blob/master/packages/bluebanquise-ipxe/grub2-efi-autofind.cfg
const autoFindCfg = `
echo "Loading modules..."
insmod part_gpt
@@ -48,34 +54,114 @@ insmod fat
insmod chain
insmod part_msdos
insmod ext2
insmod regexp
insmod xfs
insmod mdraid1x
insmod mdraid09
echo
echo "Scanning, first pass..."
for cfg in (*,gpt*)/efi/*/grub.cfg (*,gpt*)/efi/*/*/grub.cfg (*,gpt*)/grub.cfg (*,gpt*)/*/grub.cfg (*,gpt*)/*/*/grub.cfg (*,msdos*)/grub.cfg (*,msdos*)/*/grub.cfg (*,mosdos*)/*/*/grub.cfg; do
regexp --set=1:cfg_device '^\((.*)\)/' "${cfg}"
echo "======================= lsmod ======================================="
lsmod
echo
echo "======================= devices ====================================="
ls
echo
echo "======================= Searching for the BOOT EFI executable ======="
echo "Scanning, 1st pass"
for efi in %s; do
regexp --set=1:root '^\(([^)]+)\)/' "${efi}"
echo "- Scanning: $efi"
if [ -e "$efi" ] ; then
echo " Found: $efi"
else
echo " $efi does not exist"
fi
done
echo "Scanning, second pass..."
for cfg in (*,gpt*)/efi/*/grub.cfg (*,gpt*)/efi/*/*/grub.cfg (*,gpt*)/grub.cfg (*,gpt*)/*/grub.cfg (*,gpt*)/*/*/grub.cfg (*,msdos*)/grub.cfg (*,msdos*)/*/grub.cfg (*,mosdos*)/*/*/grub.cfg; do
regexp --set=1:cfg_device '^\((.*)\)/' "${cfg}"
echo "Try configfile ${cfg}"
if [ -e "${cfg}" ]; then
cfg_found=true
echo " >> Found operating system grub config! <<"
echo " Path: ${cfg}"
echo " Booting in 5s..."
sleep --interruptible --verbose 5
configfile "${cfg}"
echo
echo "Scanning, 2nd pass..."
for efi in %s; do
echo "- Scanning: $efi"
if [ -e "$efi" ] ; then
regexp --set 1:root '^\(([^)]+)\)/' "${efi}"
echo " Found: $efi"
echo " Root: $root"
echo " Chainloading $efi"
chainloader "$efi"
boot
fi
done
echo "No grub.cfg known OS found. Fall back on shell after 5s."
sleep 5s
echo
echo " Found no BOOT EFI executable. Falling back to shell..."
echo
echo "======================= Searching for Grub EFI executables =========="
echo "Scanning, 1st pass"
for efi in %s ; do
regexp --set=1:root '^\(([^)]+)\)/' "${efi}"
echo "- Scanning: $efi"
if [ -e "$efi" ] ; then
echo " Found: $efi"
else
echo " $efi does not exist"
fi
done
echo
echo "Scanning, 2nd pass..."
for efi in %s ; do
echo "- Scanning: $efi"
if [ -e "$efi" ] ; then
regexp --set 1:root '^\(([^)]+)\)/' "${efi}"
echo " Found: $efi"
echo " Root: $root"
echo " Chainloading $efi"
chainloader "$efi"
boot
fi
done
echo
echo " Found no Grub EFI executable to load an OS."
echo
echo "======================= Searching for grub.cfg on local disks ======="
echo "Scanning, 1st pass..."
for grubcfg in %s ; do
regexp --set=1:root '^\(([^)]+)\)/' "${grubcfg}"
if [ -e "$grubcfg" ] ; then
echo " Found: $grubcfg"
else
echo " $grubcfg does not exist"
fi
done
echo
echo "Scanning, 2nd pass..."
for grubcfg in %s ; do
echo "- Scanning: $grubcfg"
if [ -e "${grubcfg}" ]; then
regexp --set=1:root '^\(([^)]+)\)/' "${grubcfg}"
echo " Found: $grubcfg"
echo " Root: $root"
# echo " Contents:"
# cat "$grubcfg"
configfile "${grubcfg}"
boot
fi
done
echo
echo " Found no grub.cfg configuration file to load."
sleep 4s
`
func GetAutoFindConfig() string {
return autoFindCfg
return fmt.Sprintf(autoFindCfg, BOOT_EFI_MATCHER, BOOT_EFI_MATCHER, GRUB_EFI_MATCHER, GRUB_EFI_MATCHER, GRUB_CFG_MATCHER, GRUB_CFG_MATCHER)
}
// REF: https://archived.forum.manjaro.org/t/detecting-efi-files-and-booting-them-from-grub/38083

View File

@@ -445,13 +445,13 @@ func (adapter *MegaRaidAdaptor) GetDevices() []*baremetal.BaremetalStorage {
func (adapter *MegaRaidAdaptor) GetLogicVolumes() ([]*raiddrivers.RaidLogicalVolume, error) {
errs := make([]error, 0)
megaLvs, err := adapter.getMegacliLogicVolumes()
if err != nil {
errs = append(errs, err)
megaLvs, megacliErr := adapter.getMegacliLogicVolumes()
if megacliErr != nil {
errs = append(errs, megacliErr)
}
storeLvs, err := adapter.getStorcliLogicVolums()
if err != nil {
errs = append(errs, err)
storeLvs, storcliErr := adapter.getStorcliLogicVolums()
if storcliErr != nil {
errs = append(errs, storcliErr)
}
if len(megaLvs) > 0 {
return megaLvs, nil
@@ -459,7 +459,7 @@ func (adapter *MegaRaidAdaptor) GetLogicVolumes() ([]*raiddrivers.RaidLogicalVol
if len(storeLvs) > 0 {
return storeLvs, nil
}
if len(errs) == 0 {
if len(errs) == 0 || megacliErr == nil || storcliErr == nil {
// no error, no volume
return []*raiddrivers.RaidLogicalVolume{}, nil
}

View File

@@ -19,6 +19,7 @@ import (
"fmt"
"net/http"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/workmanager"
"yunion.io/x/onecloud/pkg/hostman/hostutils"
@@ -48,12 +49,13 @@ func performImageCache(
) {
_, _, body := appsrv.FetchEnv(ctx, w, r)
disk, err := body.Get("disk")
input := compute.CacheImageInput{}
err := body.Unmarshal(&input, "disk")
if err != nil {
httperrors.MissingParameterError(ctx, w, "disk")
httperrors.BadRequestError(ctx, w, "unmarshal disk %s", err)
return
}
hostutils.DelayImageCacheTask(ctx, performTask, disk)
hostutils.DelayImageCacheTask(ctx, performTask, input)
hostutils.ResponseOk(ctx, w)
}

View File

@@ -30,7 +30,7 @@ import (
func InitApp(options *common_options.BaseOptions, dbAccess bool) *appsrv.Application {
// cache := appsrv.NewCache(options.AuthTokenCacheSize)
log.Infof("RequestWorkerCount: %d", options.RequestWorkerCount)
app := appsrv.NewApplication(options.ApplicationID, options.RequestWorkerCount, dbAccess)
app := appsrv.NewApplication(options.ApplicationID, options.RequestWorkerCount, options.RequestWorkerQueueSize, dbAccess)
app.CORSAllowHosts(options.CorsHosts)
app.SetDefaultTimeout(time.Duration(options.DefaultProcessTimeoutSeconds) * time.Second)
// app.SetContext(appsrv.APP_CONTEXT_KEY_CACHE, cache)

View File

@@ -336,6 +336,9 @@ func ParseNetworkConfig(desc string, idx int) (*compute.NetworkConfig, error) {
netConfig.IsDefault = true
} else if p == "ipv6" {
netConfig.RequireIPv6 = true
} else if p == "strict-ipv6" {
netConfig.RequireIPv6 = true
netConfig.StrictIPv6 = true
} else if strings.HasPrefix(p, "standby-port=") {
netConfig.StandbyPortCount, _ = strconv.Atoi(p[len("standby-port="):])
} else if strings.HasPrefix(p, "standby-addr=") {

View File

@@ -26,6 +26,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 tenantCacheSyncWorker struct {
@@ -34,7 +35,7 @@ type tenantCacheSyncWorker struct {
func (w *tenantCacheSyncWorker) Run() {
log.Debugf("[tenantCacheSyncWorker] Run project cache sync worker ...")
err := syncProjects(context.Background(), w.ids)
err := syncProjects(ctx.CtxWithTime(), w.ids)
if err != nil {
log.Errorf("fail to syncProjects %s", err)
}

View File

@@ -26,6 +26,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 userCacheSyncWorker struct {
@@ -34,7 +35,7 @@ type userCacheSyncWorker struct {
func (w *userCacheSyncWorker) Run() {
log.Debugf("[userCacheSyncWorker] Run project cache sync worker ...")
err := syncUsers(context.Background(), w.ids)
err := syncUsers(ctx.CtxWithTime(), w.ids)
if err != nil {
log.Errorf("fail to syncUsers %s", err)
}

View File

@@ -281,6 +281,11 @@ func listItemQueryFiltersRaw(
}
}
q, err = ListItemFilter(manager, ctx, q, userCred, query)
if err != nil {
return nil, errors.Wrap(err, "ListItemFilter")
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// TURN ON automatic filter by column name, ONLY if query key starts with @!!!!
// example: @name=abc&@city=111
@@ -312,10 +317,6 @@ func listItemQueryFiltersRaw(
return nil, errors.Wrap(err, "applyListItemsGeneralJointFilters")
}
}
q, err = ListItemFilter(manager, ctx, q, userCred, query)
if err != nil {
return nil, errors.Wrap(err, "ListItemFilter")
}
if !useRawQuery {
// Specifically for joint resource, these filters will exclude

View File

@@ -19,10 +19,12 @@ import (
"runtime/debug"
"sync"
"github.com/petermattis/goid"
"yunion.io/x/log"
)
const (
var (
debug_log = false
)
@@ -34,15 +36,15 @@ type SInMemoryLockRecord struct {
key string
lock *sync.Mutex
cond *sync.Cond
holder context.Context
holder int64
depth int
waiter *FIFO
}
func newInMemoryLockRecord(ctx context.Context) *SInMemoryLockRecord {
func newInMemoryLockRecord(ctxDummy context.Context) *SInMemoryLockRecord {
lock := &sync.Mutex{}
cond := sync.NewCond(lock)
rec := SInMemoryLockRecord{lock: lock, cond: cond, holder: ctx, depth: 0, waiter: NewFIFO()}
rec := SInMemoryLockRecord{lock: lock, cond: cond, holder: -1, depth: 0, waiter: NewFIFO()}
return &rec
}
@@ -51,24 +53,29 @@ func (rec *SInMemoryLockRecord) fatalf(fmtStr string, args ...interface{}) {
log.Fatalf(fmtStr, args...)
}
func (rec *SInMemoryLockRecord) lockContext(ctx context.Context) {
func (rec *SInMemoryLockRecord) lockContext(ctxDummy context.Context) {
rec.lock.Lock()
defer rec.lock.Unlock()
if rec.holder == nil {
rec.holder = ctx
curGoid := goid.Get()
if rec.holder < 0 {
if debug_log {
log.Debugf("lockContext: curGoid=[%d] key=[%s] create new record", curGoid, rec.key)
}
rec.holder = curGoid
rec.depth = 1
return
}
if debug_log {
log.Debugf("rec.hold=[%p] ctx=[%p] %v key=[%s]", rec.holder, ctx, rec.holder == ctx, rec.key)
log.Debugf("rec.hold=[%d] ctx=[%d] %v key=[%s]", rec.holder, curGoid, rec.holder == curGoid, rec.key)
}
if rec.holder == ctx {
if rec.holder == curGoid {
rec.depth += 1
if debug_log {
log.Infof("lockContext: same ctx, depth: %d [%p] key=[%s]", rec.depth, rec.holder, rec.key)
log.Infof("lockContext: same ctx, depth: %d holder=[%d] ctx=[%d] key=[%s]", rec.depth, rec.holder, curGoid, rec.key)
}
if rec.depth > 32 {
// XXX MUST BE BUG ???
@@ -79,57 +86,59 @@ func (rec *SInMemoryLockRecord) lockContext(ctx context.Context) {
// check
rec.waiter.Enum(func(ele interface{}) {
electx := ele.(context.Context)
if electx == ctx {
rec.fatalf("try to lock from a waiter context???? key=[%s]", rec.key)
electx := ele.(int64)
if electx == curGoid {
rec.fatalf("try to lock from a waiter context???? curGoid=[%d] waiterGoid=[%d] key=[%s]", curGoid, electx, rec.key)
}
})
rec.waiter.Push(ctx)
rec.waiter.Push(curGoid)
if debug_log {
log.Debugf("waiter size %d after push", rec.waiter.Len())
log.Debugf("Start to wait ... [%p] key=[%s]", ctx, rec.key)
log.Debugf("waiter size %d after push curGoid=[%d]", rec.waiter.Len(), curGoid)
log.Debugf("Start to wait ... holder=[%d] curGoid [%d] key=[%s]", rec.holder, curGoid, rec.key)
}
for rec.holder != nil {
for rec.holder >= 0 {
rec.cond.Wait()
}
if debug_log {
log.Debugf("End of wait ... [%p] key=[%s]", ctx, rec.key)
log.Debugf("End of wait ... holder=[%d] curGoid [%d] key=[%s]", rec.holder, curGoid, rec.key)
}
rec.waiter.Pop(ctx)
rec.waiter.Pop(curGoid)
if debug_log {
log.Debugf("waiter size %d after pop key=[%s]", rec.waiter.Len(), rec.key)
log.Debugf("waiter size %d after pop curGoid=[%d] key=[%s]", rec.waiter.Len(), curGoid, rec.key)
}
rec.holder = ctx
rec.holder = curGoid
rec.depth = 1
}
func (rec *SInMemoryLockRecord) unlockContext(ctx context.Context) (needClean bool) {
func (rec *SInMemoryLockRecord) unlockContext(ctxDummy context.Context) (needClean bool) {
rec.lock.Lock()
defer rec.lock.Unlock()
if rec.holder != ctx {
rec.fatalf("try to unlock a wait context??? key=[%s]", rec.key)
curGoid := goid.Get()
if rec.holder != curGoid {
rec.fatalf("try to unlock a wait context??? key=[%s] holder=[%d] curGoid=[%d]", rec.key, rec.holder, curGoid)
}
if debug_log {
log.Debugf("unlockContext depth %d [%p] key=[%s]", rec.depth, ctx, rec.key)
log.Debugf("unlockContext depth %d curGoid=[%d] key=[%s]", rec.depth, curGoid, rec.key)
}
rec.depth -= 1
if rec.depth <= 0 {
if debug_log {
log.Debugf("depth 0, to release lock for context [%p] key=[%s]", ctx, rec.key)
log.Debugf("depth 0, to release lock for context curGoid=[%d] key=[%s]", curGoid, rec.key)
}
rec.holder = nil
rec.holder = -1
if rec.waiter.Len() == 0 {
return true
}
@@ -154,11 +163,11 @@ func NewInMemoryLockManager() ILockManager {
return &lockMan
}
func (lockman *SInMemoryLockManager) getRecordWithLock(ctx context.Context, key string) *SInMemoryLockRecord {
func (lockman *SInMemoryLockManager) getRecordWithLock(ctx context.Context, key string, new bool) *SInMemoryLockRecord {
lockman.tableLock.Lock()
defer lockman.tableLock.Unlock()
return lockman.getRecord(ctx, key, true)
return lockman.getRecord(ctx, key, new)
}
func (lockman *SInMemoryLockManager) getRecord(ctx context.Context, key string, new bool) *SInMemoryLockRecord {
@@ -175,23 +184,16 @@ func (lockman *SInMemoryLockManager) getRecord(ctx context.Context, key string,
}
func (lockman *SInMemoryLockManager) LockKey(ctx context.Context, key string) {
record := lockman.getRecordWithLock(ctx, key)
record := lockman.getRecordWithLock(ctx, key, true)
record.lockContext(ctx)
}
func (lockman *SInMemoryLockManager) UnlockKey(ctx context.Context, key string) {
lockman.tableLock.Lock()
defer lockman.tableLock.Unlock()
record := lockman.getRecord(ctx, key, false)
record := lockman.getRecordWithLock(ctx, key, false)
if record == nil {
log.Errorf("BUG: unlock an non-existent lock\n%s", debug.Stack())
log.Errorf("BUG: unlock an non-existent lock ctx: %p key: %s\n%s", ctx, key, debug.Stack())
return
}
needClean := record.unlockContext(ctx)
if needClean {
delete(lockman.lockTable, key)
}
record.unlockContext(ctx)
}

View File

@@ -16,9 +16,17 @@ package lockman
import (
"context"
"fmt"
"math/rand"
"os"
"sync"
"testing"
"time"
"github.com/petermattis/goid"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
)
func TestInMemoryLockManager(t *testing.T) {
@@ -56,3 +64,74 @@ func TestRunManu(t *testing.T) {
}
t.Logf("complete")
}
type app struct {
ctx context.Context
key string
lockman ILockManager
}
func (app *app) run() {
app.lockman.LockKey(app.ctx, app.key)
defer app.lockman.UnlockKey(app.ctx, app.key)
fmt.Printf("run for goid: %d key %s\n", goid.Get(), app.key)
}
type emptyKey struct{}
func TestRunManu3(t *testing.T) {
for i := 0; i < 100; i++ {
TestRunManu2(t)
}
}
func TestRunManu2(t *testing.T) {
rand.Seed(100)
lockman := NewInMemoryLockManager()
debug_log = true
// 使用 WaitGroup 来等待所有 goroutine 完成
var wg sync.WaitGroup
MAX_GOROUTINE := 4096
MAX_KEY := 4
complete := make(chan struct{})
go func() {
for {
select {
case <-time.After(time.Second):
t.Logf("timeout")
utils.DumpAllGoroutineStack(os.Stdout)
case <-complete:
return
}
}
}()
bgCtx := context.Background()
// 为每个 goroutine 创建独立的 context
for i := 0; i < MAX_GOROUTINE; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
// 为每个 goroutine 创建新的 context
ctx := context.WithValue(bgCtx, emptyKey{}, id)
log.Infof("ctx for id %d: %p", id, ctx)
app := &app{
ctx: ctx,
key: fmt.Sprintf("test-%d", id%MAX_KEY),
lockman: lockman,
}
app.run()
}(i)
}
// 等待所有 goroutine 完成
wg.Wait()
close(complete)
t.Logf("complete")
}

View File

@@ -66,13 +66,12 @@ func ObjectIdQueryWithTagFiltersOptimized(ctx context.Context, q *sqlchemy.SQuer
if len(filters.Filters) > 0 || len(filters.NoFilters) > 0 {
idSubQ := q.Copy().SubQuery().Query()
idSubQ.AppendField(sqlchemy.DISTINCT(idField, idSubQ.Field(idField)))
subQ := idSubQ.SubQuery()
if len(filters.Filters) > 0 {
if GetMetadaManagerInContext(ctx) == Metadata {
sq := tenantIdQueryWithTags(ctx, modelName, filters.Filters)
q = q.In(idField, sq.SubQuery())
} else { // clickhouse
ids := objIdQueryWithTagsOptimized(ctx, subQ, idField, modelName, filters.Filters)
ids := tenantIdQueryWithTagsWithCache(ctx, modelName, filters.Filters)
if len(ids) > 0 {
q = q.In(idField, ids)
}
@@ -83,7 +82,7 @@ func ObjectIdQueryWithTagFiltersOptimized(ctx context.Context, q *sqlchemy.SQuer
sq := tenantIdQueryWithTags(ctx, modelName, filters.Filters)
q = q.NotIn(idField, sq.SubQuery())
} else { // clickhouse
ids := objIdQueryWithTagsOptimized(ctx, subQ, idField, modelName, filters.NoFilters)
ids := tenantIdQueryWithTagsWithCache(ctx, modelName, filters.NoFilters)
if len(ids) > 0 {
q = q.NotIn(idField, ids)
}
@@ -153,6 +152,50 @@ func tenantIdQueryWithTags(ctx context.Context, modelName string, tagsList []map
return sq.Filter(sqlchemy.OR(conditions...)).Distinct()
}
var (
tagsCache = hashcache.NewCache(1024, time.Minute*15)
)
func tenantIdQueryWithTagsWithCache(ctx context.Context, modelName string, tagsList []map[string][]string) []string {
manager := Metadata
ret := []string{}
sq := manager.Query("obj_id")
for _, tags := range tagsList {
if len(tags) == 0 {
continue
}
hashKeys := []string{modelName, jsonutils.Marshal(tags).String()}
hash := fmt.Sprintf("%x", md5.Sum([]byte(jsonutils.Marshal(hashKeys).String())))
cache := tagsCache.Get(hash)
if cache != nil {
ids := cache.([]string)
ret = append(ret, ids...)
log.Debugf("cache hit %s %s %s", hash, hashKeys, ids)
continue
}
conditions := []sqlchemy.ICondition{}
for key, val := range tags {
if len(val) > 0 {
sqq := sq.Copy().Equals("obj_type", modelName).Equals("key", key).In("value", val)
conditions = append(conditions, sqlchemy.In(sq.Field("obj_id"), sqq.SubQuery()))
} else {
sqq := sq.Copy().Equals("obj_type", modelName).Equals("key", key)
conditions = append(conditions, sqlchemy.In(sq.Field("obj_id"), sqq.SubQuery()))
}
}
ids, err := FetchIds(sq.Copy().Filter(sqlchemy.AND(conditions...)).Distinct())
if err != nil {
log.Errorf("FetchIds %s %v", sq.String(), err)
continue
}
ret = append(ret, ids...)
log.Debugf("cache miss %s %s %s", hash, hashKeys, ids)
tagsCache.AtomicSet(hash, ids)
}
return ret
}
func objIdQueryWithTags(ctx context.Context, objIdSubQ *sqlchemy.SSubQuery, idField string, modelName string, tagsList []map[string][]string) *sqlchemy.SQuery {
manager := GetMetadaManagerInContext(ctx)
@@ -192,53 +235,6 @@ func objIdQueryWithTags(ctx context.Context, objIdSubQ *sqlchemy.SSubQuery, idFi
return query
}
var (
tagsCache = hashcache.NewCache(1024, time.Minute*15)
)
func objIdQueryWithTagsOptimized(ctx context.Context, objIdSubQ *sqlchemy.SSubQuery, idField string, modelName string, tagsList []map[string][]string) []string {
manager := GetMetadaManagerInContext(ctx)
ret := []string{}
for _, tags := range tagsList {
if len(tags) == 0 {
continue
}
objIdQ := objIdSubQ.Query()
objIdQ = objIdQ.AppendField(objIdQ.Field(idField))
for key, val := range tags {
hashKeys := []string{idField, key, modelName}
hashKeys = append(hashKeys, val...)
hash := fmt.Sprintf("%x", md5.Sum([]byte(jsonutils.Marshal(hashKeys).String())))
cache := tagsCache.Get(hash)
if cache != nil {
ids := cache.([]string)
ret = append(ret, ids...)
continue
}
sq := manager.Query("obj_id").Equals("obj_type", modelName).Equals("key", key)
if len(val) > 0 {
ssq := sq.In("value", val).SubQuery()
if utils.IsInArray(tagutils.NoValue, val) {
objIdQ = objIdQ.LeftJoin(ssq, sqlchemy.Equals(objIdQ.Field(idField), ssq.Field("obj_id")))
} else {
objIdQ = objIdQ.Join(ssq, sqlchemy.Equals(objIdQ.Field(idField), ssq.Field("obj_id")))
}
} else {
ssq := sq.SubQuery()
objIdQ = objIdQ.Join(ssq, sqlchemy.Equals(objIdQ.Field(idField), ssq.Field("obj_id")))
}
ids, err := FetchIds(objIdQ)
if err != nil {
continue
}
ret = append(ret, ids...)
tagsCache.AtomicSet(hash, ids)
}
}
return ret
}
func (meta *SMetadataResourceBaseModelManager) ListItemFilter(
ctx context.Context,
manager IModelManager,

View File

@@ -51,6 +51,8 @@ const (
ACT_BACKUP_START = "backup_start"
ACT_BACKUP_START_FAILED = "backup_start_fail"
ACT_SET_RELEASE_TIME = "set_release_time"
ACT_FREEZE = "freeze"
ACT_FREEZE_FAIL = "freeze_fail"
ACT_UNFREEZE = "unfreeze"

View File

@@ -31,10 +31,10 @@ type STaskBase struct {
// 完成任务时间
EndAt time.Time `nullable:"true" list:"user" json:"end_at"`
ObjType string `old_name:"obj_name" json:"obj_type" width:"128" charset:"utf8" nullable:"true" list:"user"`
Object string `json:"object" width:"128" charset:"utf8" nullable:"true" list:"user"` // Column(VARCHAR(128, charset='utf8'), nullable=False)
ObjId string `width:"128" charset:"ascii" nullable:"false" list:"user" index:"true"` // Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=False)
TaskName string `width:"64" charset:"ascii" nullable:"false" list:"user" index:"true"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
ObjType string `old_name:"obj_name" json:"obj_type" width:"128" charset:"utf8" nullable:"false" default:"" list:"user"`
Object string `json:"object" width:"128" charset:"utf8" nullable:"false" default:"" list:"user"` // Column(VARCHAR(128, charset='utf8'), nullable=False)
ObjId string `width:"128" charset:"ascii" nullable:"false" list:"user" index:"true"` // Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=False)
TaskName string `width:"64" charset:"ascii" nullable:"false" list:"user" index:"true"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
UserCred mcclient.TokenCredential `width:"1024" charset:"utf8" nullable:"false" get:"user"` // Column(VARCHAR(1024, charset='ascii'), nullable=False)
// OwnerCred string `width:"512" charset:"ascii" nullable:"true"` // Column(VARCHAR(512, charset='ascii'), nullable=True)

View File

@@ -173,7 +173,7 @@ func (manager *STaskManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQue
taskQ = taskQ.Snapshot()
taskQ = manager.SProjectizedResourceBaseManager.FilterByOwner(ctx, taskQ, man, userCred, owner, scope)
if taskQ.IsAltered() {
taskSubQ := taskQ.Distinct().SubQuery()
taskSubQ := taskQ.SubQuery()
q = q.Join(taskSubQ, sqlchemy.Equals(q.Field("id"), taskSubQ.Field("task_id")))
}

View File

@@ -182,13 +182,18 @@ func lang(ctx context.Context, contactType npk.TNotifyChannel, reIds []string, c
return langMap, nil
}
func isEmptyRecipients(recipientId []string) bool {
func isEmptyRecipients(recipientId, robots []string) bool {
var recvs []string
for _, c := range recipientId {
if len(c) > 0 {
recvs = append(recvs, c)
}
}
for _, robot := range robots {
if len(robot) > 0 {
recvs = append(recvs, robot)
}
}
return len(recvs) == 0
}
@@ -216,7 +221,7 @@ func genMsgViaLang(ctx context.Context, p sNotifyParams) ([]npk.SNotifyMessage,
reIds = p.recipientId
}
if isEmptyRecipients(p.recipientId) {
if isEmptyRecipients(p.recipientId, p.robots) {
return nil, errors.Wrap(errors.ErrEmpty, "empty receipients")
}
@@ -414,10 +419,10 @@ func (t *notifyTask) Run() {
}
func intelliNotify(ctx context.Context, p sNotifyParams) {
if isEmptyRecipients(p.recipientId) {
if isEmptyRecipients(p.recipientId, p.robots) {
return
}
log.Infof("recipientId: %v, contacts: %v, event %s priority %s", p.recipientId, p.contacts, p.event, p.priority)
log.Infof("recipientId: %v, robots: %v, contacts: %v, event %s priority %s", p.recipientId, p.robots, p.contacts, p.event, p.priority)
msgs, err := genMsgViaLang(ctx, p)
if err != nil {
log.Errorf("unable send notification: %v", err)

View File

@@ -15,6 +15,7 @@
package options
import (
"reflect"
"sort"
"yunion.io/x/log"
@@ -22,6 +23,7 @@ import (
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/util/netutils2"
)
func OnBaseOptionsChange(oOpts, nOpts interface{}) bool {
@@ -63,6 +65,14 @@ func OnBaseOptionsChange(oOpts, nOpts interface{}) bool {
if oldOpts.ApiServer != newOpts.ApiServer {
log.Debugf("api_server changed from %s to %s", oldOpts.ApiServer, newOpts.ApiServer)
}
if !reflect.DeepEqual(oldOpts.MetadataServerIp4s, newOpts.MetadataServerIp4s) {
netutils2.SetIp4MetadataServers(newOpts.MetadataServerIp4s)
log.Debugf("Metadata server IPv4 address changed to %s", newOpts.MetadataServerIp4s)
}
if !reflect.DeepEqual(oldOpts.MetadataServerIp6s, newOpts.MetadataServerIp6s) {
netutils2.SetIp6MetadataServers(newOpts.MetadataServerIp6s)
log.Debugf("Metadata server IPv6 address changed to %s", newOpts.MetadataServerIp6s)
}
if oldOpts.TaskWorkerCount != newOpts.TaskWorkerCount {
consts.SetTaskWorkerCount(newOpts.TaskWorkerCount)
}

View File

@@ -43,6 +43,7 @@ import (
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/util/atexit"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/netutils2"
)
const (
@@ -71,6 +72,8 @@ type BaseOptions struct {
ApplicationID string `help:"Application ID"`
RequestWorkerCount int `default:"8" help:"Request worker thread count, default is 8"`
RequestWorkerQueueSize int `default:"10" help:"Request worker queue size, default is 10"`
TaskWorkerCount int `default:"4" help:"Task manager worker thread count, default is 4"`
LocalTaskWorkerCount int `default:"4" help:"Worker thread count that runs local tasks, default is 4"`
@@ -114,6 +117,9 @@ type BaseOptions struct {
CustomizedPrivatePrefixes []string `help:"customized private prefixes"`
MetadataServerIp4s []string `help:"metadata server IPv4 addresses, default is 169.254.169.254" default:"169.254.169.254"`
MetadataServerIp6s []string `help:"metadata server IPv6 addresses, default is fd00:ec2::254" default:"'fd00:ec2::254'"`
structarg.BaseOptions
GlobalHTTPProxy string `help:"Global http proxy"`
@@ -166,6 +172,7 @@ type HostCommonOptions struct {
ExecutorConnectTimeoutSeconds int `help:"executor client connection timeout in seconds, default is 30" default:"30"`
ImageDeployDriver string `help:"Image deploy driver" default:"qemu-kvm" choices:"qemu-kvm|nbd|libguestfs"`
DeployConcurrent int `help:"qemu-kvm deploy driver concurrent" default:"5"`
Qcow2Preallocation string `help:"Qcow2 image create preallocation" default:"metadata" choices:"disable|metadata|falloc|full"`
}
type DBOptions struct {
@@ -362,6 +369,8 @@ func parseOptions(optStruct interface{}, args []string, configFileName string, s
consts.SetServiceName(optionsRef.ApplicationID)
httperrors.SetTimeZone(optionsRef.TimeZone)
netutils2.SetIp4MetadataServers(optionsRef.MetadataServerIp4s)
netutils2.SetIp6MetadataServers(optionsRef.MetadataServerIp6s)
// log configuration
log.SetVerboseLevel(int32(optionsRef.LogVerboseLevel))
@@ -409,6 +418,10 @@ func parseOptions(optStruct interface{}, args []string, configFileName string, s
consts.SetTaskWorkerCount(optionsRef.TaskWorkerCount)
consts.SetLocalTaskWorkerCount(optionsRef.LocalTaskWorkerCount)
consts.SetTaskArchiveThresholdHours(optionsRef.TaskArchiveThresholdHours)
if optionsRef.Address == "0.0.0.0" {
optionsRef.Address = ""
}
}
func (self *BaseOptions) HttpTransportProxyFunc() httputils.TransportProxyFunc {

View File

@@ -31,12 +31,12 @@ import (
"yunion.io/x/onecloud/pkg/apis"
identity_api "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules/identity"
"yunion.io/x/onecloud/pkg/util/ctx"
"yunion.io/x/onecloud/pkg/util/hashcache"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/onecloud/pkg/util/tagutils"
@@ -76,7 +76,7 @@ type SPolicyManager struct {
policyCache *hashcache.Cache // policy cache
permissionCache *hashcache.Cache // permission cache
fetchWorker *appsrv.SWorkerManager
// fetchWorker *appsrv.SWorkerManager
lock *sync.Mutex
}
@@ -146,19 +146,19 @@ func (manager *SPolicyManager) init(refreshInterval time.Duration, workerCount i
defaultFetcherFuncAddr := reflect.ValueOf(DefaultPolicyFetcher).Pointer()
remoteFetcherFuncAddr := reflect.ValueOf(auth.FetchMatchPolicies).Pointer()
log.Debugf("DefaultPolicyFetcher: %x RemotePolicyFetcher: %x", defaultFetcherFuncAddr, remoteFetcherFuncAddr)
var isDB bool
if defaultFetcherFuncAddr == remoteFetcherFuncAddr {
// remote fetcher, so start watcher
isDB = false
} else {
isDB = true
}
// var isDB bool
// if defaultFetcherFuncAddr == remoteFetcherFuncAddr {
// remote fetcher, so start watcher
// isDB = false
// } else {
// isDB = true
// }
if workerCount <= 0 {
workerCount = 1
}
log.Infof("policy fetch worker count %d", workerCount)
manager.fetchWorker = appsrv.NewWorkerManager("policyFetchWorker", workerCount, 2048, isDB)
// if workerCount <= 0 {
// workerCount = 1
// }
// log.Infof("policy fetch worker count %d", workerCount)
// manager.fetchWorker = appsrv.NewWorkerManager("policyFetchWorker", workerCount, 2048, isDB)
}
func getMaskedLoginIp(userCred mcclient.TokenCredential) string {
@@ -255,53 +255,22 @@ func (manager *SPolicyManager) Allow(targetScope rbacscope.TRbacScope, userCred
return rbacutils.PolicyDeny
}
type fetchResult struct {
output *mcclient.SFetchMatchPoliciesOutput
err error
}
type policyTask struct {
manager *SPolicyManager
key string
userCred mcclient.TokenCredential
resChan chan fetchResult
}
func (t *policyTask) Run() {
val := t.manager.policyCache.AtomicGet(t.key)
result := fetchResult{}
if gotypes.IsNil(val) {
pg, err := DefaultPolicyFetcher(context.Background(), t.userCred)
if err != nil {
result.err = errors.Wrap(err, "DefaultPolicyFetcher")
} else {
t.manager.policyCache.AtomicSet(t.key, pg)
result.output = pg
}
} else {
result.output = val.(*mcclient.SFetchMatchPoliciesOutput)
}
t.resChan <- result
}
func (t *policyTask) Dump() string {
return ""
}
func (manager *SPolicyManager) fetchMatchedPolicies(userCred mcclient.TokenCredential) (*mcclient.SFetchMatchPoliciesOutput, error) {
key := policyKey(userCred)
task := policyTask{
manager: manager,
key: key,
userCred: userCred,
val := manager.policyCache.AtomicGet(key)
if !gotypes.IsNil(val) {
// cache hit
return val.(*mcclient.SFetchMatchPoliciesOutput), nil
}
task.resChan = make(chan fetchResult)
manager.fetchWorker.Run(&task, nil, nil)
pg, err := DefaultPolicyFetcher(ctx.CtxWithTime(), userCred)
if err != nil {
return nil, errors.Wrap(err, "DefaultPolicyFetcher")
}
res := <-task.resChan
return res.output, res.err
manager.policyCache.AtomicSet(key, pg)
return pg, nil
}
func (manager *SPolicyManager) allow(scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, service string, resource string, action string, extra ...string) rbacutils.SPolicyResult {

View File

@@ -52,6 +52,8 @@ type SNic struct {
Bandwidth int `json:"bandwidth"`
Index int `json:"index"`
IsDefault *bool `json:"is_default"`
}
type SRoute []string
@@ -65,28 +67,29 @@ func (n SNic) GetMac() net.HardwareAddr {
}
type SServerNic struct {
Name string `json:"name"`
Index int `json:"index"`
Bridge string `json:"bridge"`
Domain string `json:"domain"`
Ip string `json:"ip"`
Vlan int `json:"vlan"`
Driver string `json:"driver"`
Masklen int `json:"masklen"`
Virtual bool `json:"virtual"`
Manual bool `json:"manual"`
WireId string `json:"wire_id"`
NetId string `json:"net_id"`
Mac string `json:"mac"`
BandWidth int `json:"bw"`
Mtu int16 `json:"mtu,omitempty"`
Dns string `json:"dns"`
Ntp string `json:"ntp"`
Net string `json:"net"`
Interface string `json:"interface"`
Gateway string `json:"gateway"`
Ifname string `json:"ifname"`
Routes []SRoute `json:"routes,omitempty"`
Name string `json:"name"`
Index int `json:"index"`
Bridge string `json:"bridge"`
Domain string `json:"domain"`
Ip string `json:"ip"`
Vlan int `json:"vlan"`
VlanInterface bool `json:"vlan_interface"`
Driver string `json:"driver"`
Masklen int `json:"masklen"`
Virtual bool `json:"virtual"`
Manual bool `json:"manual"`
WireId string `json:"wire_id"`
NetId string `json:"net_id"`
Mac string `json:"mac"`
BandWidth int `json:"bw"`
Mtu int16 `json:"mtu,omitempty"`
Dns string `json:"dns"`
Ntp string `json:"ntp"`
Net string `json:"net"`
Interface string `json:"interface"`
Gateway string `json:"gateway"`
Ifname string `json:"ifname"`
Routes []SRoute `json:"routes,omitempty"`
Ip6 string `json:"ip6"`
Masklen6 int `json:"masklen6"`
@@ -131,5 +134,7 @@ func (n SServerNic) ToNic() SNic {
Ip6Addr: n.Ip6,
Masklen6: uint8(n.Masklen6),
Gateway6: n.Gateway6,
IsDefault: &n.IsDefault,
}
}

View File

@@ -0,0 +1,177 @@
// 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 (
"context"
"fmt"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudmon/options"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
computemodules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
baseoptions "yunion.io/x/onecloud/pkg/mcclient/options"
"yunion.io/x/onecloud/pkg/util/influxdb"
)
func BucketProbe(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
if options.Options.EnableBucketProbeDebug {
log.Debugf("BucketProbe start")
}
if !options.Options.EnableBucketProbe {
if options.Options.EnableBucketProbeDebug {
log.Debugf("BucketProbe is disabled")
}
return
}
sess := auth.GetSession(ctx, userCred, options.Options.Region)
metrics, err := gatherBucketMetrics(ctx, sess)
if err != nil {
log.Errorf("BucketProbe gatherBucketMetrics failed: %s", err)
return
}
err = sendMetrics(sess, metrics, "telegraf")
if err != nil {
log.Errorf("StatusProbe SendMetrics error: %s", err)
}
}
func gatherBucketMetrics(ctx context.Context, sess *mcclient.ClientSession) ([]influxdb.SMetricData, error) {
allMetrics := []influxdb.SMetricData{}
params := baseoptions.BaseListOptions{}
params.Scope = "max"
limit := 1000
params.Limit = &limit
params.Filter = []string{
"enable_perf_mon.equals(1)",
}
boolTrue := true
params.Details = &boolTrue
total := -1
offset := 0
for total < 0 || offset < total {
params.Offset = &offset
results, err := computemodules.Buckets.List(sess, jsonutils.Marshal(params))
if err != nil {
return nil, errors.Wrap(err, "computemodules.Buckets.List")
}
total = results.Total
offset = results.Offset + len(results.Data)
for _, bucket := range results.Data {
bucketDetails := computeapi.BucketDetails{}
err = bucket.Unmarshal(&bucketDetails)
if err != nil {
log.Errorf("BucketProbe failed: %s", err)
continue
}
metrics, err := probeBucketStats(ctx, sess, &bucketDetails)
if err != nil {
log.Errorf("BucketProbe failed: %s", err)
continue
}
allMetrics = append(allMetrics, metrics...)
}
}
return allMetrics, nil
}
func probeBucketStats(ctx context.Context, sess *mcclient.ClientSession, bucketDetails *computeapi.BucketDetails) ([]influxdb.SMetricData, error) {
bucket, err := computemodules.GetIBucket(ctx, sess, bucketDetails)
if err != nil {
return nil, errors.Wrap(err, "getIBucket")
}
resultDelay, err := computemodules.ProbeBucketStats(ctx, bucket, options.Options.BucketProbeTestKey, 0)
if err != nil {
return nil, errors.Wrap(err, "doProbeBucketStats zero")
}
resultRate, err := computemodules.ProbeBucketStats(ctx, bucket, options.Options.BucketProbeTestKey, int64(options.Options.BucketProbeTestSizeMb)*1024*1024)
if err != nil {
return nil, errors.Wrap(err, "doProbeBucketStats with payload")
}
metricTags := []influxdb.SKeyValue{}
for k, v := range bucketDetails.GetMetricTags() {
if len(v) == 0 {
continue
}
metricTags = append(metricTags, influxdb.SKeyValue{
Key: k,
Value: v,
})
}
metrics := []influxdb.SKeyValue{}
for k, v := range bucketDetails.GetMetricTags() {
if len(v) == 0 {
continue
}
metrics = append(metrics, influxdb.SKeyValue{
Key: k,
Value: v,
})
}
metrics = append(metrics,
influxdb.SKeyValue{
Key: "upload_delay_ms",
Value: fmt.Sprintf("%f", resultDelay.UploadDelayMs()),
},
influxdb.SKeyValue{
Key: "download_delay_ms",
Value: fmt.Sprintf("%f", resultDelay.DownloadDelayMs()),
},
influxdb.SKeyValue{
Key: "delete_delay_ms",
Value: fmt.Sprintf("%f", resultDelay.DeleteDelayMs()),
},
influxdb.SKeyValue{
Key: "upload_rate_mbps",
Value: fmt.Sprintf("%f", resultRate.UploadThroughputMbps(options.Options.BucketProbeTestSizeMb)),
},
influxdb.SKeyValue{
Key: "download_rate_mbps",
Value: fmt.Sprintf("%f", resultRate.DownloadThroughputMbps(options.Options.BucketProbeTestSizeMb)),
},
)
if options.Options.EnableBucketProbeDebug {
log.Debugf("BucketProbe for bucket %s metrics: %s", bucketDetails.Name, jsonutils.Marshal(metrics))
}
return []influxdb.SMetricData{
{
Name: "bucket_perf",
Tags: metricTags,
Metrics: metrics,
Timestamp: time.Now(),
},
}, nil
}

View File

@@ -0,0 +1,437 @@
// 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"
"time"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudmon/options"
"yunion.io/x/onecloud/pkg/util/influxdb"
)
type SHttpStats struct {
HttpCode2xx float64 `json:"duration.2XX"`
HttpCode4xx float64 `json:"duration.4XX"`
HttpCode5xx float64 `json:"duration.5XX"`
HitHttpCode2xx int64 `json:"hit.2XX"`
HitHttpCode4xx int64 `json:"hit.4XX"`
HitHttpCode5xx int64 `json:"hit.5XX"`
Method string `json:"method"`
Name string `json:"name"`
Path string `json:"path"`
}
type sApiHttpStats struct {
SHttpStats
Paths []SHttpStats `json:"paths"`
}
func (apiStats *sApiHttpStats) convertSnapshot(now time.Time) *sHttpStatsSnapshot {
snapshot := &sHttpStatsSnapshot{
snapshotAt: now,
stats: map[string]*SHttpStats{},
}
apiStats.SHttpStats.Method = "any"
apiStats.SHttpStats.Path = "any"
apiStats.SHttpStats.Name = "any"
snapshot.stats[getStatsKey(apiStats.SHttpStats.Method, apiStats.SHttpStats.Path, apiStats.SHttpStats.Name)] = &apiStats.SHttpStats
for i := range apiStats.Paths {
pathStats := apiStats.Paths[i]
snapshot.stats[getStatsKey(pathStats.Method, pathStats.Path, pathStats.Name)] = &pathStats
}
return snapshot
}
type sHttpStatsExt struct {
Duration2xx float64 `json:"duration_2xx"`
Duration4xx float64 `json:"duration_4xx"`
Duration5xx float64 `json:"duration_5xx"`
Hit2xx int64 `json:"hit_2xx"`
Hit4xx int64 `json:"hit_4xx"`
Hit5xx int64 `json:"hit_5xx"`
Duration2xxDiff float64 `json:"duration_2xx_diff"`
Duration4xxDiff float64 `json:"duration_4xx_diff"`
Duration5xxDiff float64 `json:"duration_5xx_diff"`
Hit2xxDiff int64 `json:"hit_2xx_diff"`
Hit4xxDiff int64 `json:"hit_4xx_diff"`
Hit5xxDiff int64 `json:"hit_5xx_diff"`
Method string `json:"method"`
Path string `json:"path"`
Name string `json:"name"`
HasDiff bool `json:"has_diff"`
}
func (v sHttpStatsExt) DelayMs2xx() float64 {
if v.Hit2xxDiff > 0 {
return v.Duration2xxDiff / float64(v.Hit2xxDiff)
}
return -1
}
func (v sHttpStatsExt) Qps2xx(interval time.Duration) float64 {
if interval > 0 {
return float64(v.Hit2xxDiff) / interval.Seconds()
}
return -1
}
func (v sHttpStatsExt) DelayMs4xx() float64 {
if v.Hit4xxDiff > 0 {
return v.Duration4xxDiff / float64(v.Hit4xxDiff)
}
return -1
}
func (v sHttpStatsExt) Qps4xx(interval time.Duration) float64 {
if interval > 0 {
return float64(v.Hit4xxDiff) / interval.Seconds()
}
return -1
}
func (v sHttpStatsExt) DelayMs5xx() float64 {
if v.Hit5xxDiff > 0 {
return v.Duration5xxDiff / float64(v.Hit5xxDiff)
}
return -1
}
func (v sHttpStatsExt) Qps5xx(interval time.Duration) float64 {
if interval > 0 {
return float64(v.Hit5xxDiff) / interval.Seconds()
}
return -1
}
func (v sHttpStatsExt) Qps(interval time.Duration) float64 {
if interval > 0 {
return float64(v.Hit2xxDiff+v.Hit4xxDiff+v.Hit5xxDiff) / interval.Seconds()
}
return -1
}
func (v sHttpStatsExt) DelayMs() float64 {
if v.HitDiff() > 0 {
return v.DurationMsDiff() / float64(v.HitDiff())
}
return -1
}
func (v sHttpStatsExt) DurationMs() float64 {
return v.Duration2xx + v.Duration4xx + v.Duration5xx
}
func (v sHttpStatsExt) Hit() int64 {
return v.Hit2xx + v.Hit4xx + v.Hit5xx
}
func (v sHttpStatsExt) DurationMsDiff() float64 {
return v.Duration2xxDiff + v.Duration4xxDiff + v.Duration5xxDiff
}
func (v sHttpStatsExt) HitDiff() int64 {
return v.Hit2xxDiff + v.Hit4xxDiff + v.Hit5xxDiff
}
func (v sHttpStatsExt) Percent2xx() float64 {
if v.DurationMsDiff() > 0 {
return v.Duration2xxDiff * 100 / v.DurationMsDiff()
}
return -1
}
func (v sHttpStatsExt) PercentHit2xx() float64 {
if v.HitDiff() > 0 {
return float64(v.Hit2xxDiff) * 100 / float64(v.HitDiff())
}
return -1
}
func (v sHttpStatsExt) Percent4xx() float64 {
if v.DurationMsDiff() > 0 {
return v.Duration4xxDiff * 100 / v.DurationMsDiff()
}
return -1
}
func (v sHttpStatsExt) PercentHit4xx() float64 {
if v.HitDiff() > 0 {
return float64(v.Hit4xxDiff) * 100 / float64(v.HitDiff())
}
return -1
}
func (v sHttpStatsExt) Percent5xx() float64 {
if v.DurationMsDiff() > 0 {
return v.Duration5xxDiff * 100 / v.DurationMsDiff()
}
return -1
}
func (v sHttpStatsExt) PercentHit5xx() float64 {
if v.HitDiff() > 0 {
return float64(v.Hit5xxDiff) * 100 / float64(v.HitDiff())
}
return -1
}
type sHttpStatsSnapshot struct {
snapshotAt time.Time
stats map[string]*SHttpStats
}
type sHttpStatsDiff struct {
snapshotAt time.Time
interval time.Duration
stats map[string]*sHttpStatsExt
}
func calculateHttpStatsDiff(prevSnap *sHttpStatsSnapshot, nowSnap *sHttpStatsSnapshot) *sHttpStatsDiff {
diff := sHttpStatsDiff{
snapshotAt: nowSnap.snapshotAt,
stats: map[string]*sHttpStatsExt{},
}
if prevSnap != nil {
rootKey := getStatsKey("any", "any", "any")
prevRoot := prevSnap.stats[rootKey]
nowRoot := nowSnap.stats[rootKey]
if prevRoot.HttpCode2xx > nowRoot.HttpCode2xx || prevRoot.HttpCode4xx > nowRoot.HttpCode4xx || prevRoot.HttpCode5xx > nowRoot.HttpCode5xx ||
prevRoot.HitHttpCode2xx > nowRoot.HitHttpCode2xx || prevRoot.HitHttpCode4xx > nowRoot.HitHttpCode4xx || prevRoot.HitHttpCode5xx > nowRoot.HitHttpCode5xx {
// detect a reset, skip this round
prevSnap = nil
}
}
if prevSnap != nil {
diff.interval = nowSnap.snapshotAt.Sub(prevSnap.snapshotAt)
} else {
intvMin := options.Options.CollectServiceMetricIntervalMinute
if intvMin <= 0 {
intvMin = 1
}
diff.interval = time.Duration(intvMin) * time.Minute
}
for k := range nowSnap.stats {
v := nowSnap.stats[k]
diffStats := sHttpStatsExt{
Duration2xx: v.HttpCode2xx,
Duration4xx: v.HttpCode4xx,
Duration5xx: v.HttpCode5xx,
Hit2xx: v.HitHttpCode2xx,
Hit4xx: v.HitHttpCode4xx,
Hit5xx: v.HitHttpCode5xx,
Method: v.Method,
Path: v.Path,
Name: v.Name,
}
if prevSnap != nil {
if prevStats, ok := prevSnap.stats[k]; ok {
diffStats.HasDiff = true
diffStats.Duration2xxDiff = v.HttpCode2xx - prevStats.HttpCode2xx
diffStats.Duration4xxDiff = v.HttpCode4xx - prevStats.HttpCode4xx
diffStats.Duration5xxDiff = v.HttpCode5xx - prevStats.HttpCode5xx
diffStats.Hit2xxDiff = v.HitHttpCode2xx - prevStats.HitHttpCode2xx
diffStats.Hit4xxDiff = v.HitHttpCode4xx - prevStats.HitHttpCode4xx
diffStats.Hit5xxDiff = v.HitHttpCode5xx - prevStats.HitHttpCode5xx
}
}
diff.stats[k] = &diffStats
}
return &diff
}
var (
httpStatsSnapshot = map[string]*sHttpStatsSnapshot{}
)
func getStatsKey(method, path, name string) string {
return fmt.Sprintf("%s.%s.%s", method, path, name)
}
func getSnapshotKey(serviceName, url string) string {
return fmt.Sprintf("%s.%s", serviceName, url)
}
func updateHttpStatsSnapshot(serviceName string, url string, now time.Time, apiStats sApiHttpStats, serviceType, regionId, version string) []influxdb.SMetricData {
snapshot := apiStats.convertSnapshot(now)
snapshotKey := getSnapshotKey(serviceName, url)
var vdiffStats *sHttpStatsDiff
if prevSnap, ok := httpStatsSnapshot[snapshotKey]; ok {
vdiffStats = calculateHttpStatsDiff(prevSnap, snapshot)
} else {
// no prev records, just add
vdiffStats = calculateHttpStatsDiff(nil, snapshot)
}
httpStatsSnapshot[snapshotKey] = snapshot
metrics := vdiffStats.metrics(serviceName, serviceType, regionId, version)
log.Debugf("updateHttpStatsSnapshot %s %s snapshotAt: %s diffAt: %s intval: %f metrics: %d", serviceName, url, snapshot.snapshotAt, vdiffStats.snapshotAt, vdiffStats.interval.Seconds(), len(metrics))
return metrics
}
func appendMetric(metrics []influxdb.SKeyValue, key string, v float64) []influxdb.SKeyValue {
if v >= 0 {
metrics = append(metrics, influxdb.SKeyValue{
Key: key,
Value: fmt.Sprintf("%f", v),
})
}
return metrics
}
func (diff *sHttpStatsDiff) metrics(service, serviceType, regionId, version string) []influxdb.SMetricData {
metrics := make([]influxdb.SMetricData, 0)
genTags := func(v *sHttpStatsExt) []influxdb.SKeyValue {
return []influxdb.SKeyValue{
{
Key: "service",
Value: service,
},
{
Key: "service_type",
Value: serviceType,
},
{
Key: "region",
Value: regionId,
},
{
Key: "version",
Value: version,
},
{
Key: "method",
Value: v.Method,
},
{
Key: "path",
Value: v.Path,
},
{
Key: "name",
Value: v.Name,
},
{
Key: "interval_secs",
Value: fmt.Sprintf("%f", diff.interval.Seconds()),
},
}
}
for k := range diff.stats {
v := diff.stats[k]
// ignore stats with no hit
if v.Hit() <= 0 {
continue
}
// ignore stats with no diff
if v.HasDiff && v.HitDiff() <= 0 {
continue
}
metric := influxdb.SMetricData{
Name: METIRCY_TYPE_HTTP_REQUST,
Timestamp: diff.snapshotAt,
Tags: genTags(v),
Metrics: []influxdb.SKeyValue{
{
Key: "duration_ms_any",
Value: fmt.Sprintf("%f", v.DurationMs()),
},
{
Key: "hit_any",
Value: fmt.Sprintf("%d", v.Hit()),
},
},
}
if v.HasDiff {
metric.Metrics = appendMetric(metric.Metrics, "dura_ms_delta_any", v.DurationMsDiff())
metric.Metrics = appendMetric(metric.Metrics, "hit_delta_any", float64(v.HitDiff()))
metric.Metrics = appendMetric(metric.Metrics, "delay_ms_any", v.DelayMs())
metric.Metrics = appendMetric(metric.Metrics, "qps_any", v.Qps(diff.interval))
}
metric.Metrics = append(metric.Metrics, []influxdb.SKeyValue{
{
Key: "duration_ms_2xx",
Value: fmt.Sprintf("%f", v.Duration2xx),
},
{
Key: "hit_2xx",
Value: fmt.Sprintf("%d", v.Hit2xx),
},
}...)
if v.HasDiff {
metric.Metrics = appendMetric(metric.Metrics, "dura_ms_delta_2xx", v.Duration2xxDiff)
metric.Metrics = appendMetric(metric.Metrics, "hit_delta_2xx", float64(v.Hit2xxDiff))
metric.Metrics = appendMetric(metric.Metrics, "delay_ms_2xx", v.DelayMs2xx())
metric.Metrics = appendMetric(metric.Metrics, "percent_hit_2xx", v.PercentHit2xx())
metric.Metrics = appendMetric(metric.Metrics, "percent_duration_2xx", v.Percent2xx())
metric.Metrics = appendMetric(metric.Metrics, "qps_2xx", v.Qps2xx(diff.interval))
}
metric.Metrics = append(metric.Metrics, []influxdb.SKeyValue{
{
Key: "duration_ms_4xx",
Value: fmt.Sprintf("%f", v.Duration4xx),
},
{
Key: "hit_4xx",
Value: fmt.Sprintf("%d", v.Hit4xx),
},
}...)
if v.HasDiff {
metric.Metrics = appendMetric(metric.Metrics, "dura_ms_delta_4xx", v.Duration4xxDiff)
metric.Metrics = appendMetric(metric.Metrics, "hit_delta_4xx", float64(v.Hit4xxDiff))
metric.Metrics = appendMetric(metric.Metrics, "delay_ms_4xx", v.DelayMs4xx())
metric.Metrics = appendMetric(metric.Metrics, "percent_hit_4xx", v.PercentHit4xx())
metric.Metrics = appendMetric(metric.Metrics, "percent_duration_4xx", v.Percent4xx())
metric.Metrics = appendMetric(metric.Metrics, "qps_4xx", v.Qps4xx(diff.interval))
}
metric.Metrics = append(metric.Metrics, []influxdb.SKeyValue{
{
Key: "duration_ms_5xx",
Value: fmt.Sprintf("%f", v.Duration5xx),
},
{
Key: "hit_5xx",
Value: fmt.Sprintf("%d", v.Hit5xx),
},
}...)
if v.HasDiff {
metric.Metrics = appendMetric(metric.Metrics, "dura_ms_delta_5xx", v.Duration5xxDiff)
metric.Metrics = appendMetric(metric.Metrics, "hit_delta_5xx", float64(v.Hit5xxDiff))
metric.Metrics = appendMetric(metric.Metrics, "delay_ms_5xx", v.DelayMs5xx())
metric.Metrics = appendMetric(metric.Metrics, "percent_hit_5xx", v.PercentHit5xx())
metric.Metrics = appendMetric(metric.Metrics, "percent_duration_5xx", v.Percent5xx())
metric.Metrics = appendMetric(metric.Metrics, "qps_5xx", v.Qps5xx(diff.interval))
}
metrics = append(metrics, metric)
}
return metrics
}

View File

@@ -0,0 +1,215 @@
// 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 (
"testing"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/util/timeutils"
)
func TestUnmarshalHttpStats(t *testing.T) {
input := `{"duration.2XX":4532188.710192006, "duration.4XX":196870.22898800002, "duration.5XX":32787.14909299999, "hit.2XX":88678, "hit.4XX":1748, "hit.5XX":179, "paths":[{"duration.2XX":150, "duration.4XX":250, "duration.5XX":310, "hit.2XX":1500, "hit.4XX":2500, "hit.5XX":3500, "method":"GET", "path":"/servers", "name":"list_servers"}, {"duration.2XX":150, "duration.4XX":250, "duration.5XX":350, "hit.2XX":1500, "hit.4XX":2500, "hit.5XX":3500, "method":"POST", "path":"/servers", "name":"create_servers"}]}`
inputJson, err := jsonutils.ParseString(input)
if err != nil {
t.Fatal(err)
}
t.Logf("json: %s", inputJson.PrettyString())
var stats sApiHttpStats
err = inputJson.Unmarshal(&stats)
if err != nil {
t.Fatal(err)
}
if stats.HttpCode2xx != 4532188.710192006 {
t.Fatalf("duration.2XX: %f", stats.HttpCode2xx)
}
if stats.HttpCode4xx != 196870.22898800002 {
t.Fatalf("duration.4XX: %f", stats.HttpCode4xx)
}
if stats.HttpCode5xx != 32787.14909299999 {
t.Fatalf("duration.5XX: %f", stats.HttpCode5xx)
}
if stats.HitHttpCode2xx != 88678 {
t.Fatalf("hit.2XX: %d", stats.HitHttpCode2xx)
}
if stats.HitHttpCode4xx != 1748 {
t.Fatalf("hit.4XX: %d", stats.HitHttpCode4xx)
}
if stats.HitHttpCode5xx != 179 {
t.Fatalf("hit.5XX: %d", stats.HitHttpCode5xx)
}
}
func TestHttpStats(t *testing.T) {
cases := []struct {
prevTime time.Time
nowTime time.Time
prevStats *sApiHttpStats
nowStats sApiHttpStats
}{
{
nowTime: func() time.Time {
tm, _ := timeutils.ParseTimeStr("2025-06-01 00:01:00")
return tm
}(),
nowStats: sApiHttpStats{
SHttpStats: SHttpStats{
HttpCode2xx: 400,
HttpCode4xx: 700,
HttpCode5xx: 1000,
HitHttpCode2xx: 4000,
HitHttpCode4xx: 7000,
HitHttpCode5xx: 10000,
},
Paths: []SHttpStats{
{
HttpCode2xx: 150,
HttpCode4xx: 250,
HttpCode5xx: 310,
HitHttpCode2xx: 1500,
HitHttpCode4xx: 2500,
HitHttpCode5xx: 3500,
Method: "GET",
Path: "/servers",
Name: "list_servers",
},
{
HttpCode2xx: 150,
HttpCode4xx: 250,
HttpCode5xx: 350,
HitHttpCode2xx: 1500,
HitHttpCode4xx: 2500,
HitHttpCode5xx: 3500,
Method: "POST",
Path: "/servers",
Name: "create_servers",
},
{
HttpCode2xx: 100,
HttpCode4xx: 200,
HttpCode5xx: 300,
HitHttpCode2xx: 1000,
HitHttpCode4xx: 2000,
HitHttpCode5xx: 3000,
Method: "PUT",
Path: "/servers/*",
Name: "update_servers",
},
},
},
},
{
prevTime: func() time.Time {
tm, _ := timeutils.ParseTimeStr("2025-06-01 00:00:00")
return tm
}(),
nowTime: func() time.Time {
tm, _ := timeutils.ParseTimeStr("2025-06-01 00:01:00")
return tm
}(),
prevStats: &sApiHttpStats{
SHttpStats: SHttpStats{
HttpCode2xx: 200,
HttpCode4xx: 400,
HttpCode5xx: 600,
HitHttpCode2xx: 2000,
HitHttpCode4xx: 4000,
HitHttpCode5xx: 6000,
},
Paths: []SHttpStats{
{
HttpCode2xx: 100,
HttpCode4xx: 200,
HttpCode5xx: 300,
HitHttpCode2xx: 1000,
HitHttpCode4xx: 2000,
HitHttpCode5xx: 3000,
Method: "GET",
Path: "/servers",
Name: "list_servers",
},
{
HttpCode2xx: 100,
HttpCode4xx: 200,
HttpCode5xx: 300,
HitHttpCode2xx: 1000,
HitHttpCode4xx: 2000,
HitHttpCode5xx: 3000,
Method: "POST",
Path: "/servers",
Name: "create_servers",
},
},
},
nowStats: sApiHttpStats{
SHttpStats: SHttpStats{
HttpCode2xx: 400,
HttpCode4xx: 700,
HttpCode5xx: 1000,
HitHttpCode2xx: 4000,
HitHttpCode4xx: 7000,
HitHttpCode5xx: 10000,
},
Paths: []SHttpStats{
{
HttpCode2xx: 150,
HttpCode4xx: 250,
HttpCode5xx: 310,
HitHttpCode2xx: 1500,
HitHttpCode4xx: 2500,
HitHttpCode5xx: 3500,
Method: "GET",
Path: "/servers",
Name: "list_servers",
},
{
HttpCode2xx: 150,
HttpCode4xx: 250,
HttpCode5xx: 350,
HitHttpCode2xx: 1500,
HitHttpCode4xx: 2500,
HitHttpCode5xx: 3500,
Method: "POST",
Path: "/servers",
Name: "create_servers",
},
{
HttpCode2xx: 100,
HttpCode4xx: 200,
HttpCode5xx: 300,
HitHttpCode2xx: 1000,
HitHttpCode4xx: 2000,
HitHttpCode5xx: 3000,
Method: "PUT",
Path: "/servers/*",
Name: "update_servers",
},
},
},
},
}
for _, c := range cases {
var prev *sHttpStatsSnapshot
if c.prevStats != nil {
prev = c.prevStats.convertSnapshot(c.prevTime)
}
curr := c.nowStats.convertSnapshot(c.nowTime)
diff := calculateHttpStatsDiff(prev, curr)
metrics := diff.metrics("test", "test", "test", "test")
t.Log(jsonutils.Marshal(metrics).PrettyString())
}
}

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