Compare commits

...

223 Commits

Author SHA1 Message Date
Zexi Li
0bece9d948 Merge pull request #10272 from ioito/automated-cherry-pick-of-#10270-upstream-release-3.6
Automated cherry pick of #10270: fix(cloudevent): optimized cloudevent sql
2021-02-25 11:36:00 +08:00
Qu Xuan
14dcb91758 fix(cloudevent): optimized cloudevent sql 2021-02-25 11:34:07 +08:00
Zexi Li
3d869c69bb Merge pull request #10264 from swordqiu/automated-cherry-pick-of-#10262-upstream-release-3.6
Automated cherry pick of #10262: fix(keystone): ensure comparing id with non-utf8 string
2021-02-25 11:24:22 +08:00
Zexi Li
09ef280e33 Merge pull request #10267 from ioito/automated-cherry-pick-of-#10265-upstream-release-3.6
Automated cherry pick of #10265: fix(region): add azure new region
2021-02-25 11:23:09 +08:00
Qu Xuan
4332008c3f fix(region): add azure new region 2021-02-25 10:23:45 +08:00
Qiu Jian
73c0f0350f fix(keystone): ensure comparing id with non-utf8 string 2021-02-25 02:29:55 +08:00
Zexi Li
48a894efdf Merge pull request #10251 from ioito/automated-cherry-pick-of-#10247-upstream-release-3.6
Automated cherry pick of #10247: Automated cherry pick of #10233: fix(region): support peer secgroup
2021-02-24 18:15:41 +08:00
Zexi Li
fc274d5da6 Merge pull request #10260 from tb365/automated-cherry-pick-of-#10258-upstream-release-3.6
Automated cherry pick of #10258: fix(region): redis change spec bugfix
2021-02-24 16:06:40 +08:00
tangbin
e39015fa45 fix(region): redis change spec bugfix 2021-02-24 11:49:23 +08:00
Zexi Li
1bb9801666 Merge pull request #10249 from zexi/automated-cherry-pick-of-#10223-upstream-release-3.6
Automated cherry pick of #10223: fix(host-deployer): mount may fail to lock /etc/mtab, add retrier
2021-02-23 10:36:22 +08:00
Qiu Jian
c22c4f8ef6 fix(host-deployer): mount may fail to lock /etc/mtab, add retrier 2021-02-23 10:25:14 +08:00
Qu Xuan
5584e9af1a fix(region): support peer secgroup 2021-02-23 10:08:54 +08:00
Zexi Li
44e360dcdd Merge pull request #10229 from ioito/automated-cherry-pick-of-#10227-upstream-release-3.6
Automated cherry pick of #10227: fix(region): qcloud quota sync
2021-02-22 20:52:07 +08:00
Zexi Li
a216ef28dd Merge pull request #10243 from zexi/automated-cherry-pick-of-#6083-upstream-release-3.6
Automated cherry pick of #6083: climc: add k8s monitor component
2021-02-22 19:55:51 +08:00
Zexi Li
3b12892172 Merge pull request #10236 from ioito/automated-cherry-pick-of-#10234-upstream-release-3.6
Automated cherry pick of #10234: fix(region): avoid not sync dns zone
2021-02-22 19:49:40 +08:00
Zexi Li
704cce8392 Merge pull request #10242 from tb365/automated-cherry-pick-of-#10240-upstream-release-3.6
Automated cherry pick of #10240: fix(region): set redis reboot timeout to 30 mins
2021-02-22 19:48:17 +08:00
Zexi Li
2fc04497b2 climc: add k8s monitor component 2021-02-22 19:45:40 +08:00
tangbin
bd64be4d8a fix(region): set redis reboot timeout to 30 mins 2021-02-22 18:52:05 +08:00
Qu Xuan
8dd1a897fc fix(region): avoid not sync dns zone 2021-02-22 16:15:12 +08:00
Qu Xuan
57eef5ede6 fix(region): qcloud quota sync 2021-02-22 14:55:54 +08:00
Zexi Li
ff7fa0a520 Merge pull request #10204 from swordqiu/automated-cherry-pick-of-#10202-upstream-release-3.6
Automated cherry pick of #10202: feature(compute): allow live migration without checking Host CPU modes
2021-02-22 08:59:29 +08:00
Zexi Li
0994e8c1ea Merge pull request #10207 from swordqiu/automated-cherry-pick-of-#10205-upstream-release-3.6
Automated cherry pick of #10205: fix(region): host search by any ip
2021-02-18 11:18:33 +08:00
Jian Qiu
d7dc89ccb3 fix(keystone): policy name duplication (#10201)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2021-02-14 19:14:33 +08:00
Qiu Jian
8610731af3 fix(region): host search by any ip 2021-02-13 23:13:43 +08:00
Qiu Jian
3cc72fac65 feature(compute): allow live migration with checking Host CPU modes 2021-02-13 16:33:59 +08:00
Jian Qiu
f7e8c20f43 fix(keystone): hide system scope policies in domain scope view (#10196)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2021-02-08 12:17:18 -03:00
Jian Qiu
dbf8fde45b fix(scheduler): storage medium type should not exact match (#10192)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2021-02-08 12:15:04 -03:00
yunion-ci-robot
a6a3332e64 Merge pull request #10151 from wanyaoqi/automated-cherry-pick-of-#10149-upstream-release-3.6
Automated cherry pick of #10149: chore(utils): add deb build script
2021-02-08 05:51:59 +08:00
yunion-ci-robot
ca55fbd641 Merge pull request #10186 from swordqiu/automated-cherry-pick-of-#10158-upstream-release-3.6
Automated cherry pick of #10158: fix(apigateway): add enable_quota_check and return-domain-list
2021-02-08 05:49:59 +08:00
Qiu Jian
4ee32ef454 fix(apigateway): add enable_quota_check and return-domain-list attributes to fe params 2021-02-07 17:00:17 +08:00
yunion-ci-robot
eeb2fcfbc8 Merge pull request #10185 from zhaoxiangchun/automated-cherry-pick-of-#10183-upstream-release-3.6
Automated cherry pick of #10183: fix(monitor,host): replace space to '+' when write to influxdb and replace '+' to space  when query
2021-02-07 16:07:59 +08:00
zhaoxiangchun
8612095454 fix(monitor,host): replace space to '+' when write to influxdb and replace '+' to space when query
1.写入influxdb时tag 中不允许存在空格
2021-02-07 14:57:51 +08:00
yunion-ci-robot
7612f85c6a Merge pull request #10148 from zexi/automated-cherry-pick-of-#10146-upstream-release-3.6
Automated cherry pick of #10146: Feature/baremetal h3c oem
2021-02-06 13:33:22 +08:00
Zexi Li
c09c5cac79 Merge pull request #10175 from swordqiu/automated-cherry-pick-of-#10173-upstream-release-3.6
Automated cherry pick of #10173: fix(keystone): cas sso may create new project whenever user login
2021-02-06 10:35:56 +08:00
Qiu Jian
50473268f9 fix(keystone): cas sso may create new project whenever user login 2021-02-06 03:21:01 +08:00
Zexi Li
010ed4f9ad Merge pull request #10145 from swordqiu/automated-cherry-pick-of-#10143-upstream-release-3.6
Automated cherry pick of #10143: fix(baremetal): try channel 8 for default profile
2021-02-05 14:54:31 +08:00
Zexi Li
eefe0aa8cb Merge pull request #10165 from ioito/automated-cherry-pick-of-#10163-upstream-release-3.6
Automated cherry pick of #10163: fix(cloudid): sync role policy
2021-02-05 14:36:18 +08:00
Qu Xuan
a11e5d14de fix(cloudid): sync role policy 2021-02-05 14:00:20 +08:00
wanyaoqi
a1eed47e66 chore(utils): add deb build script 2021-02-04 15:13:56 +08:00
Zexi Li
50fe044cfc feat(baremetal): support H3C oem baremetal 2021-02-04 14:11:50 +08:00
Qiu Jian
cdb97511c3 fix(baremetal): try channel 8 for default profile 2021-02-04 13:23:57 +08:00
yunion-ci-robot
6be7e015d3 Merge pull request #10142 from swordqiu/automated-cherry-pick-of-#10140-upstream-release-3.6
Automated cherry pick of #10140: fix(region): bucket size stats should not count invalid sizes of -1
2021-02-04 13:16:51 +08:00
Zexi Li
0eef67fafb Merge pull request #10139 from ioito/automated-cherry-pick-of-#10137-upstream-release-3.6
Automated cherry pick of #10137: fix(region): delete not exist disk failed
2021-02-04 11:37:10 +08:00
Qiu Jian
bbb538b93d fix(region): bucket size stats should not count invalid sizes of -1 2021-02-04 11:24:43 +08:00
Qu Xuan
4acb2757a9 fix(region): delete not exist disk failed 2021-02-04 11:03:56 +08:00
Zexi Li
d85883780d Merge pull request #10132 from ioito/automated-cherry-pick-of-#10130-upstream-release-3.6
Automated cherry pick of #10130: fix(hostman): fix kvm create disk failed error
2021-02-03 20:38:50 +08:00
Qu Xuan
e76abe883b fix(hostman): fix kvm create disk failed error 2021-02-03 20:17:25 +08:00
Zexi Li
a82f00aae7 Merge pull request #10098 from ioito/automated-cherry-pick-of-#10096-upstream-release-3.6
Automated cherry pick of #10096: fix(region): filter resource by classic vpc
2021-02-03 09:48:26 +08:00
Zexi Li
1bfa27bc49 Merge pull request #10101 from ioito/automated-cherry-pick-of-#10099-upstream-release-3.6
Automated cherry pick of #10099: fix(hostman): avoid panic when disk is nil
2021-02-03 09:47:37 +08:00
Zexi Li
ec688fd206 Merge pull request #10111 from ioito/automated-cherry-pick-of-#10109-upstream-release-3.6
Automated cherry pick of #10109: fix(region): avoid sync huawei unusable account
2021-02-02 22:06:29 +08:00
Zexi Li
20f55fe992 Merge pull request #10106 from ioito/automated-cherry-pick-of-#10104-upstream-release-3.6
Automated cherry pick of #10104: fix(region): delete virtual nics with network
2021-02-02 21:04:11 +08:00
Zexi Li
1fe7a54218 Merge pull request #10119 from wanyaoqi/automated-cherry-pick-of-#10117-upstream-release-3.6
Automated cherry pick of #10117: fix(region): add option auto reconcile backup servers
2021-02-02 20:11:12 +08:00
Zexi Li
24bf2a163a Merge pull request #10124 from rainzm/automated-cherry-pick-of-#10122-upstream-release-3.6
Automated cherry pick of #10122: fix(region): check the global network situation when expanding the network
2021-02-02 20:06:19 +08:00
rainzm
ea4505ae55 fix(region): check the global network situation when expanding the network 2021-02-02 19:49:53 +08:00
wanyaoqi
3bcb337a4b fix(region): add option auto reconcile backup servers 2021-02-02 18:32:01 +08:00
Qu Xuan
7ee2026b21 fix(region): avoid sync huawei unusable account 2021-02-02 14:39:28 +08:00
Qu Xuan
ebe79b12d1 fix(region): delete virtual nics with network 2021-02-02 10:53:52 +08:00
Qu Xuan
650ccdd7c7 fix(hostman): avoid panic when disk is nil 2021-02-01 22:02:49 +08:00
Zexi Li
68e006b71c Merge pull request #10095 from ioito/automated-cherry-pick-of-#10093-upstream-release-3.6
Automated cherry pick of #10093: fix(region): avoid update tags task loop
2021-02-01 20:34:48 +08:00
Qu Xuan
57efd8a86b fix(region): filter resource by classic vpc 2021-02-01 20:16:28 +08:00
Qu Xuan
3aa83bb86d fix(region): avoid update tags task loop 2021-02-01 19:59:10 +08:00
Zexi Li
de926037dc Merge pull request #10069 from swordqiu/automated-cherry-pick-of-#10067-upstream-release-3.6
Automated cherry pick of #10067: fix(keystone): SSO created user name may be duplicated
2021-01-30 10:42:03 +08:00
Zexi Li
df4f30ac47 Merge pull request #10075 from wanyaoqi/automated-cherry-pick-of-#10073-upstream-release-3.6
Automated cherry pick of #10073: fix(host-deployer): remove escape character on windows passwd
2021-01-30 10:40:17 +08:00
Zexi Li
96e443f90b Merge pull request #10085 from zhaoxiangchun/automated-cherry-pick-of-#10083-upstream-release-3.6
Automated cherry pick of #10083: fix(monitor): fix alert notify info do not contain resourceName
2021-01-30 10:37:16 +08:00
Zexi Li
dfa4d87702 Merge pull request #10089 from rainzm/automated-cherry-pick-of-#10086-upstream-release-3.6
Automated cherry pick of #10086: fix(notify): be compatible with member's permission changes
2021-01-30 10:36:27 +08:00
rainzm
4e199b84eb fix(notify): be compatible with member's permission changes
every user can create, modify and delete their own receiver info
2021-01-29 20:13:31 +08:00
zhaoxiangchun
c17fe2df22 fix(monitor): fix alert notify info do not contain resourceName 2021-01-29 18:17:47 +08:00
wanyaoqi
754d046d3a fix(host-deployer): remove escape character on windows passwd 2021-01-29 11:57:24 +08:00
Qiu Jian
20380ae9e6 fix(keystone): SSO created user name may be duplicated 2021-01-29 00:01:29 +08:00
Zexi Li
47d38a253a Merge pull request #10046 from rainzm/automated-cherry-pick-of-#10042-upstream-release-3.6
Automated cherry pick of #10042: Optimize the error message when logging in
2021-01-28 20:48:13 +08:00
Zexi Li
d366048e51 Merge pull request #10057 from ioito/automated-cherry-pick-of-#10055-upstream-release-3.6
Automated cherry pick of #10055: fix(region): add aliyun credit amount check
2021-01-28 20:47:00 +08:00
Zexi Li
410fd2936f Merge pull request #10061 from ioito/automated-cherry-pick-of-#10059-upstream-release-3.6
Automated cherry pick of #10059: fix(region): add huawei credit amount check
2021-01-28 20:46:14 +08:00
Zexi Li
90e10db57c Merge pull request #10065 from ioito/automated-cherry-pick-of-#10063-upstream-release-3.6
Automated cherry pick of #10063: fix(region): avoid stuck at http request
2021-01-28 20:04:03 +08:00
Qu Xuan
9975543ddb fix(region): avoid stuck at http request 2021-01-28 18:24:11 +08:00
Qu Xuan
0c658ec53f fix(region): add huawei credit amount check 2021-01-28 16:59:34 +08:00
Qu Xuan
58fb3fc9e2 fix(region): add aliyun credit amount check 2021-01-28 16:01:46 +08:00
Zexi Li
f74635f3da Merge pull request #10050 from ioito/automated-cherry-pick-of-#10048-upstream-release-3.6
Automated cherry pick of #10048: fix(region): secgroup priority fix
2021-01-28 15:12:13 +08:00
Qu Xuan
f4972c22ba fix(region): secgroup priority fix 2021-01-28 14:21:28 +08:00
rainzm
6f2bdfa22f feat(locale): update 2021-01-28 10:26:56 +08:00
rainzm
e3d3c1f029 feat(apigateway): differentiate error messages when logging in 2021-01-28 10:08:35 +08:00
rainzm
2fd40396c4 feat(keystone): more specific error return during authentication
add error class UserNotFound, UserLocked, UserDisabled and WrongPassword
2021-01-28 10:08:35 +08:00
Zexi Li
f416fe126c Merge pull request #10044 from rainzm/automated-cherry-pick-of-#9948-upstream-release-3.6
Automated cherry pick of #9948: feat(keystone,apigateway): return a readable message when the user is locked or disabled
2021-01-28 10:02:01 +08:00
rainzm
cb7956f1f1 feat(keystone,apigateway): return a readable message when the user is locked or disabled 2021-01-28 09:59:35 +08:00
Yousong Zhou
8ca6cfa3d3 Merge pull request #10034 from yousong/automated-cherry-pick-of-#10032-upstream-release-3.6
Automated cherry pick of #10032: Feature/yousong wire bw filter
2021-01-27 18:54:16 +08:00
Yousong Zhou
e467ef6ec7 feat(climc): wires: allow filter by bandwidth 2021-01-27 10:34:49 +08:00
Yousong Zhou
861cd47e62 feat(region): wire: allow filter by bandwidth 2021-01-27 10:34:49 +08:00
Zexi Li
d515e5e32c Merge pull request #9946 from rainzm/automated-cherry-pick-of-#9944-upstream-release-3.6
Automated cherry pick of #9944: fix(notify): add index fro receiver_notification
2021-01-27 09:06:34 +08:00
Zexi Li
71c0cc65ee Merge pull request #10027 from ioito/automated-cherry-pick-of-#10025-upstream-release-3.6
Automated cherry pick of #10025: fix(region): purge snapshot with not status check
2021-01-27 09:03:05 +08:00
Zexi Li
86896da1f6 Merge pull request #10022 from ioito/automated-cherry-pick-of-#10018-upstream-release-3.6
Automated cherry pick of #10018: fix(region): optimized secgroup rule sync
2021-01-26 14:53:34 +08:00
Qu Xuan
67082f32d3 fix(region): purge snapshot with not status check 2021-01-26 14:49:14 +08:00
Qu Xuan
b96b2f0b53 fix(region): optimized secgroup rule sync 2021-01-26 14:11:30 +08:00
Zexi Li
a8a2a248df Merge pull request #10012 from swordqiu/automated-cherry-pick-of-#10010-upstream-release-3.6
Automated cherry pick of #10010: fix(region): exported number of vpcs less than listed
2021-01-25 21:06:33 +08:00
Zexi Li
3997f6fbe6 Merge pull request #10005 from wanyaoqi/automated-cherry-pick-of-#10003-upstream-release-3.6
Automated cherry pick of #10003: fix(host): fix wait time after execute mount fuse fs
2021-01-25 21:05:47 +08:00
Zexi Li
05efb17d35 Merge pull request #10015 from swordqiu/automated-cherry-pick-of-#10013-upstream-release-3.6
Automated cherry pick of #10013: fix(keystone): user create without password can login with any password
2021-01-25 21:03:31 +08:00
Qiu Jian
2af9104d96 fix(keystone): user create without password can login with any password 2021-01-23 23:51:31 +08:00
yunion-ci-robot
a0d99cf879 Merge pull request #9997 from ioito/automated-cherry-pick-of-#9995-upstream-release-3.6
Automated cherry pick of #9995: fix(region): aws not support create server with public ip
2021-01-23 22:47:37 +08:00
Qiu Jian
a8d550d4d8 fix(region): exported number of vpcs less than listed 2021-01-23 20:11:33 +08:00
wanyaoqi
5ccece54ac fix(host): fix wait time after mount fuse fs 2021-01-22 19:19:36 +08:00
Qu Xuan
180b122167 fix(region): aws not support create server with public ip 2021-01-22 10:45:15 +08:00
Zexi Li
78ba5e2fd8 Merge pull request #9968 from ioito/automated-cherry-pick-of-#9966-upstream-release-3.6
Automated cherry pick of #9966: fix(cloudevent): update aliyun lookupevent api
2021-01-22 02:53:38 +08:00
Zexi Li
9f5256c344 Merge pull request #9976 from yousong/automated-cherry-pick-of-#9974-upstream-release-3.6
Automated cherry pick of #9974: fix(region): cloudaccount: allow only one sync func in flight
2021-01-22 02:47:17 +08:00
Zexi Li
cdd032c711 Merge pull request #9986 from ioito/automated-cherry-pick-of-#9973-upstream-release-3.6
Automated cherry pick of #9973: fix(region): avoid clean all rules when sync secgroups
2021-01-22 00:39:04 +08:00
Zexi Li
81133a53a2 Merge pull request #9983 from rainzm/automated-cherry-pick-of-#9981-upstream-release-3.6
Automated cherry pick of #9981: fix(notify): send websocket messages according to language preference
2021-01-21 21:33:49 +08:00
Qu Xuan
c6893892d9 fix(region): avoid clean all rules when sync secgroups 2021-01-21 21:30:47 +08:00
rainzm
8a9f3e09ea fix(notify): send websocket messages according to language preference 2021-01-21 19:51:03 +08:00
Yousong Zhou
606b241b0d fix(region): cloudaccount: allow only one sync func in flight
Ref https://github.com/yunionio/onecloud/pull/6859
2021-01-21 16:23:05 +08:00
Qu Xuan
178a7071f0 fix(cloudevent): update aliyun lookupevent api 2021-01-21 15:18:27 +08:00
Zexi Li
27e5ff8635 Merge pull request #9962 from zhaoxiangchun/automated-cherry-pick-of-#9960-upstream-release-3.6
Automated cherry pick of #9960: fix(monitor): domain view can list scope is domain or project alertrecords; fix nodata alert return info
2021-01-21 12:45:04 +08:00
zhaoxiangchun
5dc1486e7f fix(monitor): domain view can list scope is domain or project alertrecords; fix nodata alert return info 2021-01-20 11:51:46 +08:00
Zexi Li
6a50fce0ab Merge pull request #9936 from rainzm/automated-cherry-pick-of-#9934-upstream-release-3.6
Automated cherry pick of #9934: feat(notify): clean data for receiver_notifications
2021-01-20 03:19:29 +08:00
Zexi Li
132a00d8e0 Merge pull request #9954 from ioito/automated-cherry-pick-of-#9952-upstream-release-3.6
Automated cherry pick of #9952: fix(region): fix zstack delete server with local disks
2021-01-20 02:25:35 +08:00
Qu Xuan
fed6395132 fix(region): fix zstack delete server with local disks 2021-01-19 18:10:38 +08:00
rainzm
7c87d73d95 fix(notify): add index fro receiver_notification 2021-01-19 15:54:04 +08:00
yunion-ci-robot
a73c3c8d0e Merge pull request #9940 from ioito/automated-cherry-pick-of-#9938-upstream-release-3.6
Automated cherry pick of #9938: fix(region): azure default subscription id
2021-01-18 21:41:23 +08:00
Qu Xuan
f3a567f630 fix(region): azure default subscription id 2021-01-18 21:25:20 +08:00
rainzm
5160669550 feat(notify): clean data for receiver_notifications 2021-01-18 19:48:45 +08:00
Zexi Li
e1c5ebc29c Merge pull request #9927 from rainzm/automated-cherry-pick-of-#9925-upstream-release-3.6
Automated cherry pick of #9925: Notify Optimization
2021-01-18 11:47:06 +08:00
rainzm
de1553770c fix(notify): add a time limit for resending notifications 2021-01-18 11:14:45 +08:00
rainzm
928c0602dd feat(notify): delete the notification 1 month ago and remove the data migration 2021-01-18 11:14:45 +08:00
Zexi Li
6cc34c6fb1 Merge pull request #9924 from rainzm/automated-cherry-pick-of-#9922-upstream-release-3.6
Automated cherry pick of #9922: fix(notify): remote 'lang' filter when contact type is 'mobile'
2021-01-18 10:24:23 +08:00
rainzm
4885025618 fix(notify): remote 'lang' filter when contact type is 'mobile' 2021-01-17 20:56:55 +08:00
yunion-ci-robot
68ebbbcbcc Merge pull request #9912 from ioito/automated-cherry-pick-of-#9910-upstream-release-3.6
Automated cherry pick of #9910: fix(region): avoid azure detach disk failed
2021-01-17 11:40:31 +08:00
Jian Qiu
040a45aa46 fix(cloudcommon): missing set_meta opslog (#9916)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2021-01-17 11:33:28 +08:00
Qu Xuan
299d3bed6e fix(region): avoid azure detach disk failed 2021-01-16 18:38:07 +08:00
yunion-ci-robot
c4c302236f Merge pull request #9909 from zhaoxiangchun/automated-cherry-pick-of-#9907-upstream-release-3.6
Automated cherry pick of #9907: feat(monitor): influxQuery add P95 reduce
2021-01-16 12:42:29 +08:00
zhaoxiangchun
88bcb82197 feat(monitor): query reduce percentile
1.增加reduce.type == percentile ,进行对应数值处理
2021-01-16 12:01:15 +08:00
Zexi Li
80a9ed9a79 Merge pull request #9890 from ioito/automated-cherry-pick-of-#9888-upstream-release-3.6
Automated cherry pick of #9888: fix(cloudid): optimized saml sso
2021-01-15 09:08:31 +08:00
Zexi Li
f4f973429d Merge pull request #9897 from ioito/automated-cherry-pick-of-#9895-upstream-release-3.6
Automated cherry pick of #9895: fix(region): update google latitude and langtitude
2021-01-14 23:50:03 +08:00
Qu Xuan
863a28f294 fix(region): update google latitude and langtitude 2021-01-14 20:53:14 +08:00
Qu Xuan
8858e7913c fix(cloudid): optimized saml sso 2021-01-14 18:14:29 +08:00
Zexi Li
6254b64d5d Merge pull request #9886 from ioito/automated-cherry-pick-of-#9856-upstream-release-3.6
Automated cherry pick of #9856: fix(region): optimized azure reset linux pasword
2021-01-14 17:39:46 +08:00
Zexi Li
43f8ac0027 Merge pull request #9884 from rainzm/automated-cherry-pick-of-#9882-upstream-release-3.6
Automated cherry pick of #9882: Fix Notifition about Panic_Error Send too much
2021-01-14 14:50:07 +08:00
Qu Xuan
36bd1baafe fix(region): optimized azure reset linux pasword 2021-01-14 14:44:20 +08:00
rainzm
98ca80e630 feat(notify): change default verify expire interval 5m => 2m 2021-01-14 14:26:04 +08:00
rainzm
a2613e6bce fix(notify): update receiver's lang when update event occurs 2021-01-14 14:26:04 +08:00
rainzm
a8b14bb739 fix(notify): panic for err 2021-01-14 14:26:04 +08:00
Zexi Li
4850c4f8e2 Merge pull request #9880 from zhaoxiangchun/automated-cherry-pick-of-#9879-upstream-release-3.6
Automated cherry pick of #9879: feat(monitor): influxQuery add P95 reduce
2021-01-14 11:05:29 +08:00
zhaoxiangchun
64dec4254f feat(monitor): influxQuery add P95 reduce 2021-01-14 10:48:34 +08:00
Zexi Li
ada90754f9 Merge pull request #9874 from swordqiu/automated-cherry-pick-of-#9872-upstream-release-3.6
Automated cherry pick of #9872: fix(region): AWS buckets in us-east-1 have null location
2021-01-14 09:36:28 +08:00
Qiu Jian
fb3456c42d fix(region): AWS buckets in us-east-1 have null location 2021-01-14 09:12:35 +08:00
Zexi Li
cefbeb7a14 Merge pull request #9867 from zhaoxiangchun/automated-cherry-pick-of-#9865-upstream-release-3.6
Automated cherry pick of #9865: feat(monitor): support monitor overview influxdb query pass through
2021-01-13 21:12:20 +08:00
zhaoxiangchun
1fc01ebe94 feat(monitor): support monitor overview influxdb query pass through
1.监控总览支持查询穿透
2021-01-13 16:19:55 +08:00
Zexi Li
ff0606f166 Merge pull request #9864 from rainzm/automated-cherry-pick-of-#9862-upstream-release-3.6
Automated cherry pick of #9862: fix(notify): set status after sending
2021-01-13 16:10:46 +08:00
rainzm
83dd534241 fix(notify): set status after sending 2021-01-13 15:49:15 +08:00
Zexi Li
a7771885cf Merge pull request #9859 from rainzm/automated-cherry-pick-of-#9857-upstream-release-3.6
Automated cherry pick of #9857: fix(notify): set ModelManager in Receiver()
2021-01-13 14:41:34 +08:00
rainzm
88fa743e4e fix(notify): set ModelManager in Receiver() 2021-01-13 09:56:28 +08:00
Zexi Li
0e917bb275 Merge pull request #9849 from rainzm/automated-cherry-pick-of-#9847-upstream-release-3.6
Automated cherry pick of #9847: feat(notify): send notifications of different templates according to language
2021-01-12 10:29:51 +08:00
Zexi Li
cd76ce27c3 Merge pull request #9838 from swordqiu/automated-cherry-pick-of-#9836-upstream-release-3.6
Automated cherry pick of #9836: fix(keystone): add suggestion previliges to meter admin
2021-01-12 10:26:35 +08:00
Zexi Li
114de75e7e Merge pull request #9834 from ioito/automated-cherry-pick-of-#9833-upstream-release-3.6
Automated cherry pick of #9833: fix(cloudid): multi cloudaccount with saml user
2021-01-12 10:25:25 +08:00
Zexi Li
047509ebb8 Merge pull request #9843 from tb365/automated-cherry-pick-of-#9841-upstream-release-3.6
Automated cherry pick of #9841: server skus filter by mem size fix
2021-01-11 22:37:36 +08:00
Zexi Li
71e79e5a7b Merge pull request #9846 from yousong/automated-cherry-pick-of-#9844-upstream-release-3.6
Automated cherry pick of #9844: Feature/yousong i18n apigateway
2021-01-11 22:27:49 +08:00
Zexi Li
4c62508b01 Merge pull request #9852 from zhaoxiangchun/automated-cherry-pick-of-#9851-upstream-release-3.6
Automated cherry pick of #9851: fix(monitor): monitor overview throw err
2021-01-11 22:25:39 +08:00
zhaoxiangchun
e5b637906c fix(monitor): monitor overview throw err 2021-01-11 21:26:16 +08:00
rainzm
dd7d34402f feat(notify): send notifications of different templates according to language 2021-01-11 19:46:03 +08:00
Yousong Zhou
157bfb696b apigateway: try return httperrors 2021-01-11 18:35:51 +08:00
Yousong Zhou
464e0450f9 locales: generate 2021-01-11 18:35:51 +08:00
Yousong Zhou
a4b5562bd0 locales: zh-CN: add some translations 2021-01-11 18:35:51 +08:00
Yousong Zhou
f0354d0c9b locales: generate 2021-01-11 18:29:14 +08:00
Yousong Zhou
c3c3c00759 locales: zh-CN: extract current 2021-01-11 18:27:30 +08:00
Yousong Zhou
83adeaae4e apigateway: reword error messages 2021-01-11 17:51:33 +08:00
Yousong Zhou
d7f05e983f keystone: reword error messages 2021-01-11 17:51:33 +08:00
tangbin
5d075bbaaf server skus filter by mem size fix 2021-01-11 14:41:51 +08:00
Qiu Jian
86fda0f7d0 fix(keystone): add suggestion previliges to meter admin 2021-01-11 02:07:44 +08:00
Qu Xuan
53c8c16052 fix(cloudid): multi cloudaccount with saml user 2021-01-10 20:00:25 +08:00
Zexi Li
46ba9cd424 Merge pull request #9831 from tb365/automated-cherry-pick-of-#9830-upstream-release-3.6
Automated cherry pick of #9830: loadbalancer add lb purge validate
2021-01-09 19:58:29 +08:00
Zexi Li
ee59f2a410 Merge pull request #9795 from tb365/automated-cherry-pick-of-#9793-upstream-release-3.6
Automated cherry pick of #9793: feat(region): server sku os_arch & cpu_arch checking
2021-01-09 19:57:17 +08:00
Zexi Li
5cfbb416b3 Merge pull request #9818 from zhaoxiangchun/automated-cherry-pick-of-#9817-upstream-release-3.6
Automated cherry pick of #9817: fix(monitor): fix monitoroverview and meter send alerting info to  notify
2021-01-09 19:56:05 +08:00
Zexi Li
a711f832e6 Merge pull request #9827 from rainzm/automated-cherry-pick-of-#9825-upstream-release-3.6
Automated cherry pick of #9825: fix(notify): avoid duplication of notification names
2021-01-09 19:54:51 +08:00
tangbin
f31216be0e loadbalancer add lb purge validate 2021-01-09 19:20:36 +08:00
rainzm
bc0106902a fix(notify): avoid duplication of notification names 2021-01-09 18:46:52 +08:00
yunion-ci-robot
2dbfc80fac Merge pull request #9810 from tb365/automated-cherry-pick-of-#9808-upstream-release-3.6
Automated cherry pick of #9808: fix(region): aws elb backendgroup sync bugfix
2021-01-09 16:55:09 +08:00
tangbin
4fa95bf608 fix(region): aws elb backendgroup sync bugfix 2021-01-09 16:12:44 +08:00
zhaoxiangchun
af0813cd09 fix(monitor): fix monitoroverview and meter send alerting info to notify
1.调整报警总览中今日报警数量计算逻辑
2.报警模版的web路径支持跳转到不同web页面:监控报警和meter
3.nodata 前端可配制功能fix
2021-01-09 15:34:04 +08:00
Zexi Li
3b5602e1ea Merge pull request #9800 from ioito/automated-cherry-pick-of-#9798-upstream-release-3.6
Automated cherry pick of #9798: fix(region): optimized for qcloud prepaid instance delete
2021-01-09 15:33:14 +08:00
Zexi Li
e4f7d3233c Merge pull request #9815 from rainzm/automated-cherry-pick-of-#9813-upstream-release-3.6
Automated cherry pick of #9813: fix(notify): loose phone number rules in updating receiver
2021-01-09 13:03:52 +08:00
rainzm
287f98ac86 fix(notify): loose phone number rules in updating receiver 2021-01-09 11:32:31 +08:00
Zexi Li
bb44f1cdfb Merge pull request #9804 from rainzm/automated-cherry-pick-of-#9802-upstream-release-3.6
Automated cherry pick of #9802: fix(notify): loose mobile phone number matching rules
2021-01-08 14:19:50 +08:00
rainzm
644ab6f925 fix(notify): loose mobile phone number matching rules 2021-01-08 12:03:00 +08:00
Qu Xuan
e775e798aa fix(region): optimized for qcloud prepaid instance delete 2021-01-08 11:32:58 +08:00
tangbin
331d9d2a67 feat(region): server sku os_arch & cpu_arch checking 2021-01-08 10:35:08 +08:00
Zexi Li
d5ed96a651 Merge pull request #9792 from wanyaoqi/automated-cherry-pick-of-#9790-upstream-release-3.6
Automated cherry pick of #9790: fix(host-deployer): add retry on check is vgactived
2021-01-07 21:18:13 +08:00
Zexi Li
4ce85f310b Merge pull request #9787 from yousong/automated-cherry-pick-of-#9785-upstream-release-3.6
Automated cherry pick of #9785: guest_deploy_task: log other deploy details with i18n
2021-01-07 21:16:39 +08:00
Zexi Li
3f6e669324 Merge pull request #9784 from zhaoxiangchun/automated-cherry-pick-of-#9782-upstream-release-3.6
Automated cherry pick of #9782: fix(monitor,suggestion): order commonalert metric and modify alertresoruce type value and add suggestion models climc
2021-01-07 21:14:46 +08:00
wanyaoqi
3f4b2163f3 fix(host-deployer): add retry on check is vgactived 2021-01-07 19:28:09 +08:00
Yousong Zhou
78b6f85662 guest_deploy_task: log other deploy details with i18n
Fixes 9f350392 ("add service tag for actionlog")
2021-01-07 11:40:27 +08:00
zhaoxiangchun
3124113e2f fix(monitor,suggestion): order commonalert metric and modify alertresoruce type value and add suggestion models climc
1.修改监控metric排序
2.统一报警资源type和监控报警中res_type 进行统一,前端可以统一展示
3.增加suggestion服务相关climc
2021-01-06 21:31:31 +08:00
Zexi Li
38b34239cd Merge pull request #9780 from ioito/automated-cherry-pick-of-#9778-upstream-release-3.6
Automated cherry pick of #9778: fix(region): avoid auzre request timeout
2021-01-06 21:23:27 +08:00
Zexi Li
370b35852c Merge pull request #9777 from ioito/automated-cherry-pick-of-#9775-upstream-release-3.6
Automated cherry pick of #9775: fix(cloudevent): default policy
2021-01-06 21:23:08 +08:00
Zexi Li
f7c8bbc00b Merge pull request #9773 from ioito/automated-cherry-pick-of-#9771-upstream-release-3.6
Automated cherry pick of #9771: fix(region): avoid panic when register service not work
2021-01-06 21:21:47 +08:00
Qu Xuan
f64c6c54da fix(region): avoid auzre request timeout 2021-01-06 15:34:14 +08:00
Qu Xuan
c4db4bc43e fix(cloudevent): default policy 2021-01-06 14:05:35 +08:00
Qu Xuan
1afe6ef41b fix(region): avoid panic when register service not work 2021-01-05 21:20:04 +08:00
Zexi Li
83896cdcc3 Merge pull request #9764 from wanyaoqi/automated-cherry-pick-of-#9762-upstream-release-3.6
Automated cherry pick of #9762: feat(region): stop guest before freeze
2021-01-05 18:33:32 +08:00
wanyaoqi
38914b967d feat(region): stop guest before freeze 2021-01-05 15:19:13 +08:00
Zexi Li
7695eb905c Merge pull request #9758 from zhaoxiangchun/automated-cherry-pick-of-#9757-upstream-release-3.6
Automated cherry pick of #9757: fix(monitor): modify totalrecord query
2021-01-04 15:57:09 +08:00
zhaoxiangchun
562aefda85 fix(monitor): modify totalrecord query
1. influxdb 增加abs function
2. 调整total报警记录接口query
2021-01-04 15:40:57 +08:00
Zexi Li
0143d271e1 Merge pull request #9756 from zhaoxiangchun/automated-cherry-pick-of-#9754-upstream-release-3.6
Automated cherry pick of #9754: feat(monitor): get today alerting resource info
2020-12-31 20:23:52 +08:00
zhaoxiangchun
de2b95cab7 feat(monitor): get today alerting resource info
1.提供接口获取当前时间发生报警的资源统计
2020-12-31 20:09:16 +08:00
Zexi Li
fc5a78c7e3 Merge pull request #9751 from rainzm/automated-cherry-pick-of-#9750-upstream-release-3.6
Automated cherry pick of #9750: feat(region): be compatible with changes in monitor api in scaling group
2020-12-30 21:45:01 +08:00
Zexi Li
3986dbc434 Merge pull request #9740 from zhaoxiangchun/automated-cherry-pick-of-#9735-upstream-release-3.6
Automated cherry pick of #9735: fix(monitor): modify rds,redis,oss field descriptions
2020-12-30 21:43:16 +08:00
Zexi Li
192e03fcd7 Merge pull request #9734 from ioito/automated-cherry-pick-of-#9730-upstream-release-3.6
Automated cherry pick of #9730: fix(cloudevent): cloudevent is domain level resource
2020-12-30 21:42:32 +08:00
Zexi Li
44db018039 Merge pull request #9729 from ioito/automated-cherry-pick-of-#9727-upstream-release-3.6
Automated cherry pick of #9727: fix(region): rds list with secgorups info
2020-12-30 21:41:49 +08:00
Zexi Li
6751d1d3af Merge pull request #9736 from wanyaoqi/automated-cherry-pick-of-#9731-upstream-release-3.6
Automated cherry pick of #9731: fix(region): server start check host memory is enough
2020-12-30 21:40:24 +08:00
Zexi Li
5ea100865d Merge pull request #9746 from rainzm/automated-cherry-pick-of-#9744-upstream-release-3.6
Automated cherry pick of #9744: fix(esxiagent): nicIndex should be incremented
2020-12-30 21:35:56 +08:00
rainzm
987b641bd0 feat(region): be compatible with changes in monitor api in scaling group 2020-12-30 19:16:47 +08:00
rainzm
77e56db095 fix(esxiagent): nicIndex should be incremented 2020-12-30 19:02:54 +08:00
Zexi Li
b7629422f7 Merge pull request #9725 from zhaoxiangchun/automated-cherry-pick-of-#9724-upstream-release-3.6
Automated cherry pick of #9724: feat(suggestion,apigateway): add analysispredict climc
2020-12-30 18:54:41 +08:00
zhaoxiangchun
589daf5063 fix(monitor): modify rds,redis,oss field descriptions
1.修改后端redis,rds,oss desc 信息,和前端索引进行对应
2020-12-30 16:09:17 +08:00
wanyaoqi
a066301ae2 fix(region): server start check host memory is enough 2020-12-30 15:50:52 +08:00
Qu Xuan
7d07b4aa5f fix(cloudevent): cloudevent is domain level resource 2020-12-30 15:48:33 +08:00
Qu Xuan
b96f225274 fix(region): rds list with secgorups info 2020-12-30 14:20:03 +08:00
zhaoxiangchun
40c8b54cba feat(suggestion,apigateway): add analysispredict climc 2020-12-30 14:09:02 +08:00
Zexi Li
93879980f5 Merge pull request #9720 from swordqiu/automated-cherry-pick-of-#9719-upstream-release-3.6
Automated cherry pick of #9719: fix(cloudcommon): splitable may not initialize underlying table
2020-12-29 21:17:17 +08:00
Zexi Li
5bb13e48b7 Merge pull request #9716 from wanyaoqi/automated-cherry-pick-of-#9711-upstream-release-3.6
Automated cherry pick of #9711: fix(region,host,host-deployer): sync status chekc block jobs
2020-12-29 20:43:37 +08:00
Zexi Li
64fcdea2b0 Merge pull request #9712 from rainzm/automated-cherry-pick-of-#9693-upstream-release-3.6
Automated cherry pick of #9693: Solve the permission problem of notify to create receiver
2020-12-29 20:41:44 +08:00
Zexi Li
57fa6361fc Merge pull request #9708 from rainzm/automated-cherry-pick-of-#9706-upstream-release-3.6
Automated cherry pick of #9706: feat(region): multilingual timer description
2020-12-29 20:39:31 +08:00
Qiu Jian
732159137b fix(cloudcommon): splitable may not initialize underlying table 2020-12-29 18:54:26 +08:00
wanyaoqi
d2ec564ccc fix(region,host): sync status check block jobs 2020-12-29 15:31:54 +08:00
wanyaoqi
a4323eab43 fix(host-deployer): add log line on blkid failed 2020-12-29 15:31:54 +08:00
wanyaoqi
7335875ef1 fix(climc): host add netif add params bridge/interface 2020-12-29 15:31:54 +08:00
rainzm
8d98218f06 feat(region): multilingual timer description 2020-12-29 15:23:45 +08:00
rainzm
af274d7ad2 feat(db): progressive inspection when determining the required scope 2020-12-29 15:04:28 +08:00
rainzm
25baa6f509 fix(notify): inject domain info in ReceiverManager.FetchOwnerId 2020-12-29 15:04:28 +08:00
244 changed files with 6507 additions and 15011 deletions

View File

@@ -6,6 +6,7 @@ ROOT_DIR := $(CURDIR)
BUILD_DIR := $(ROOT_DIR)/_output
BIN_DIR := $(BUILD_DIR)/bin
BUILD_SCRIPT := $(ROOT_DIR)/build/build.sh
DEB_BUILD_SCRIPT := $(ROOT_DIR)/build/build_deb.sh
ifeq ($(ONECLOUD_CI_BUILD),)
GIT_COMMIT := $(shell git rev-parse --short HEAD)
@@ -64,6 +65,7 @@ endif
cmdTargets:=$(filter-out cmd/host-image,$(wildcard cmd/*))
rpmTargets:=$(foreach b,$(patsubst cmd/%,%,$(cmdTargets)),$(if $(shell [ -f "$(CURDIR)/build/$(b)/vars" ] && echo 1),rpm/$(b)))
debTargets:=$(foreach b,$(patsubst cmd/%,%,$(cmdTargets)),$(if $(shell [ -f "$(CURDIR)/build/$(b)/vars" ] && echo 1),deb/$(b)))
all: build
@@ -93,6 +95,9 @@ cmd/%: prepare_dir
rpm/%: cmd/%
$(BUILD_SCRIPT) $*
deb/%: cmd/%
$(DEB_BUILD_SCRIPT) $*
pkg/%: prepare_dir
$(GO_INSTALL) $(REPO_PREFIX)/$@
@@ -102,6 +107,9 @@ build:
rpm:
$(MAKE) $(rpmTargets)
deb:
$(MAKE) $(debTargets)
rpmclean:
rm -fr $(BUILD_DIR)/rpms

76
build/build_deb.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
set -e
if [ -z "$ROOT_DIR" ]; then
pushd $(dirname $(readlink -f "$BASH_SOURCE")) > /dev/null
ROOT_DIR=$(cd .. && pwd)
popd > /dev/null
fi
SRC_BIN=$ROOT_DIR/_output/bin
SRC_BUILD=$ROOT_DIR/build
OUTPUT_DIR=$ROOT_DIR/_output/debs
PKG=$1
BIN_PATH=${2:-/opt/yunion/bin}
if [ -z "$PKG" ]; then
echo "Usage: $0 <package>"
exit 1
fi
BIN="$SRC_BIN/$PKG"
ROOT="$SRC_BUILD/$PKG"
if [ ! -x "$BIN" ]; then
echo "$BIN not exists"
exit 1
fi
if [ ! -x "$ROOT" ]; then
echo "$ROOT not exists"
exit 1
fi
. $ROOT/vars
if [ -z "$VERSION" ]; then
TAG=$(git describe --abbrev=0 --tags || echo 000000)
VERSION=${TAG/\//-}
VERSION=${VERSION/v/}
fi
RELEASE=`date +"%y%m%d%H"`
FULL_VERSION=$VERSION-$RELEASE
BUILDROOT=$OUTPUT_DIR/yunion-$1-$FULL_VERSION
rm -rf $BUILDROOT
mkdir -p $BUILDROOT/DEBIAN
mkdir -p $BUILDROOT/$BIN_PATH
cp -rf $BIN $BUILDROOT/$BIN_PATH
cp -rf $ROOT/root/* $BUILDROOT/
echo "Build root ${BUILDROOT}"
case $(uname -m) in
x86_64)
CURRENT_ARCH=amd64
;;
aarch64)
CURRENT_ARCH=arm64
;;
esac
echo "Package: yunion-$1
Version: $FULL_VERSION
Section: base
Priority: optional
Architecture: $CURRENT_ARCH
Maintainer: wanyaoqi@yunionyun.com
Description: Yunion $1
" > $BUILDROOT/DEBIAN/control
chmod 0755 $BUILDROOT/DEBIAN/control
dpkg-deb --build $BUILDROOT

View File

@@ -47,7 +47,7 @@
</td>
</tr>
<tr>
<td style="padding-bottom: 10px;">您正在验证邮箱,请在验证码输入框中输入:{{.code}}完成验证。</td>
<td style="padding-bottom: 10px;">您正在验证邮箱,请在验证码输入框中输入:{{.code}}完成验证。</td>
</tr>
</table>
</td>

View File

@@ -0,0 +1 @@
{{.os_type}} image {{.name}} upload completed

View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<table style="width: 650px; margin-bottom: 20px;" border="0" cellpadding="0" cellspacing="0" align="center">
<tr style="height: 50px; background: #333; overflow: hidden;">
<td>
<table style="margin-left: 20px;">
<tr>
<td>
<img src="data:{{.login_logo_format}};base64,{{.login_logo}}" alt="" style="color: #fff; height: 32px; vertical-align: middle;">
</td>
</tr>
</table>
</td>
<td>
<table style="float: right;">
<tr>
<td style="padding-left: 20px; padding-right: 20px;">
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Product</a>
</td>
<td style="padding-left: 20px; padding-right: 20px;">
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Solution</a>
</td>
<td style="padding-left: 20px; padding-right: 20px;">
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Service</a>
</td>
<td style="padding-left: 20px; padding-right: 20px;">
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Help and Documentation</a>
</td>
<td style="padding-left: 20px; padding-right: 20px;">
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">About</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="width: 100%;" colspan="2">
<table style="padding: 20px 10px; width: 100%;">
<tr>
<td style="padding-bottom: 13px;">
Dear {{.name}}
</td>
</tr>
<tr>
<td style="padding-bottom: 13px;">You are verifying your email, please enter the following code on the email verification page:</td>
</tr>
<tr>
<td style="padding-bottom: 10px; font-size: large">{{.code}}</td>
</tr>
</table>
</td>
</tr>
<tr style="width: 96%;">
<td colspan="2" style="border-top: 1px dashed #ccc; color: #333; font-size: 12px; padding-bottom: 10px; font-weight: 100;">If you are not operating by yourself, please log in to the platform in time and change your password to ensure the security of your account.</td>
</tr>
<tr>
<td colspan="2" style="background: #333; text-align: right; padding-right: 20px; font-size: 12px; color: #fff; height: 50px;">Copyrights © {{.copyright}}. All rights reserved.</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1 @@
Image {{.name}} upload completed

View File

@@ -0,0 +1 @@
{{.copyright}} Verify

View File

@@ -34,6 +34,7 @@ import (
_ "yunion.io/x/onecloud/cmd/climc/shell/monitor"
_ "yunion.io/x/onecloud/cmd/climc/shell/notifyv2"
_ "yunion.io/x/onecloud/cmd/climc/shell/servicetree"
_ "yunion.io/x/onecloud/cmd/climc/shell/suggestion"
_ "yunion.io/x/onecloud/cmd/climc/shell/yunionconf"
)

View File

@@ -42,6 +42,7 @@ func init() {
Disabled bool `help:"Show disabled host only" json:"-"`
HostType string `help:"Host type filter" choices:"baremetal|hypervisor|esxi|kubelet|hyperv|aliyun|azure|qcloud|aws|huawei|ucloud|google|ctyun"`
AnyMac string `help:"Mac matches one of the host's interface"`
AnyIp string `help:"IP matches one of the host's interface"`
IsBaremetal *bool `help:"filter host list by is_baremetal=true|false"`
@@ -407,12 +408,14 @@ func init() {
})
type HostAddNetIfOptions struct {
ID string `help:"ID or Name of host"`
WIRE string `help:"ID or Name of wire to attach"`
MAC string `help:"Mac address of NIC"`
INDEX int64 `help:"nic index"`
Type string `help:"Nic type" choices:"admin|ipmi"`
IpAddr string `help:"IP address"`
ID string `help:"ID or Name of host"`
WIRE string `help:"ID or Name of wire to attach"`
MAC string `help:"Mac address of NIC"`
INDEX int64 `help:"nic index"`
Type string `help:"Nic type" choices:"admin|ipmi"`
IpAddr string `help:"IP address"`
Bridge string `help:"Bridge of hostwire"`
Interface string `help:"Interface name, eg:eth0, en0"`
}
R(&HostAddNetIfOptions{}, "host-add-netif", "Host add a NIC", func(s *mcclient.ClientSession, args *HostAddNetIfOptions) error {
params := jsonutils.NewDict()
@@ -426,6 +429,12 @@ func init() {
if len(args.IpAddr) > 0 {
params.Add(jsonutils.NewString(args.IpAddr), "ip_addr")
}
if len(args.Bridge) > 0 {
params.Add(jsonutils.NewString(args.Bridge), "bridge")
}
if len(args.Interface) > 0 {
params.Add(jsonutils.NewString(args.Interface), "interface")
}
result, err := modules.Hosts.PerformAction(s, args.ID, "add-netif", params)
if err != nil {
return err

View File

@@ -15,142 +15,17 @@
package compute
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
)
func init() {
type SecGroupRulesListOptions struct {
options.BaseListOptions
Secgroup string `help:"Secgroup ID or Name"`
SecgroupName string `help:"Search rules by fuzzy secgroup name"`
Projects []string `help:"Filter rules by project"`
Direction string `help:"filter Direction of rule" choices:"in|out"`
Protocol string `help:"filter Protocol of rule" choices:"any|tcp|udp|icmp"`
Action string `help:"filter Actin of rule" choices:"allow|deny"`
Ports string `help:"filter Ports of rule"`
Ip string `help:"filter cidr of rule"`
}
R(&SecGroupRulesListOptions{}, "secgroup-rule-list", "List all security group", func(s *mcclient.ClientSession, args *SecGroupRulesListOptions) error {
params, err := options.ListStructToParams(args)
if err != nil {
return err
}
result, err := modules.SecGroupRules.List(s, params)
if err != nil {
return err
}
printList(result, modules.SecGroupRules.GetColumns(s))
return nil
})
type SecGroupRuleDetailOptions struct {
ID string `help:"ID or Name of security group rule"`
}
R(&SecGroupRuleDetailOptions{}, "secgroup-rule-show", "Show details of rule", func(s *mcclient.ClientSession, args *SecGroupRuleDetailOptions) error {
if rule, e := modules.SecGroupRules.Get(s, args.ID, nil); e != nil {
return e
} else {
printObject(rule)
}
return nil
})
R(&SecGroupRuleDetailOptions{}, "secgroup-rule-delete", "Delete a secgroup rule", func(s *mcclient.ClientSession, args *SecGroupRuleDetailOptions) error {
if rule, e := modules.SecGroupRules.Delete(s, args.ID, nil); e != nil {
return e
} else {
printObject(rule)
}
return nil
})
type SecGroupRulesCreateOptions struct {
SECGROUP string `help:"Secgroup ID or Name" metavar:"Secgroup"`
Direction string `help:"Direction of rule" choices:"in|out"`
Action string `help:"Action of rule" choices:"allow|deny"`
Protocol string `help:"Protocol of rule" choices:"tcp|udp|icmp|any"`
Ports string `help:"Ports of rule"`
Cidr string `help:"Cidr of rule"`
Priority int64 `help:"priority of Rule"`
Desc string `help:"Description"`
}
R(&SecGroupRulesCreateOptions{}, "secgroup-rule-create", "Create all security group rule", func(s *mcclient.ClientSession, args *SecGroupRulesCreateOptions) error {
params := jsonutils.NewDict()
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
}
if args.Priority > 0 {
params.Add(jsonutils.NewInt(args.Priority), "priority")
}
if len(args.Direction) > 0 {
params.Add(jsonutils.NewString(args.Direction), "direction")
}
if len(args.Action) > 0 {
params.Add(jsonutils.NewString(args.Action), "action")
}
if len(args.Protocol) > 0 {
params.Add(jsonutils.NewString(args.Protocol), "protocol")
}
if len(args.Ports) > 0 {
params.Add(jsonutils.NewString(args.Ports), "ports")
}
if len(args.Cidr) > 0 {
params.Add(jsonutils.NewString(args.Cidr), "cidr")
}
params.Add(jsonutils.NewString(args.SECGROUP), "secgroup")
secgrouprules, err := modules.SecGroupRules.Create(s, params)
if err != nil {
return err
}
printObject(secgrouprules)
return nil
})
type SecGroupRulesUpdateOptions struct {
ID string `help:"ID or name of rule"`
Name string `help:"New name of rule"`
Priority int64 `help:"priority of Rule"`
Protocol string `help:"Protocol of rule" choices:"any|tcp|udp|icmp"`
Ports string `help:"Ports of rule"`
Cidr string `help:"Cidr of rule"`
Action string `help:"filter Actin of rule" choices:"allow|deny"`
Desc string `help:"Description" metavar:"Description"`
}
R(&SecGroupRulesUpdateOptions{}, "secgroup-rule-update", "Update property of a security group rule", func(s *mcclient.ClientSession, args *SecGroupRulesUpdateOptions) error {
params := jsonutils.NewDict()
if len(args.Name) > 0 {
params.Add(jsonutils.NewString(args.Name), "name")
}
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
}
if args.Priority > 0 {
params.Add(jsonutils.NewInt(args.Priority), "priority")
}
if len(args.Protocol) > 0 {
params.Add(jsonutils.NewString(args.Protocol), "protocol")
}
if len(args.Ports) > 0 {
params.Add(jsonutils.NewString(args.Ports), "ports")
}
if len(args.Cidr) > 0 {
params.Add(jsonutils.NewString(args.Cidr), "cidr")
}
if len(args.Action) > 0 {
params.Add(jsonutils.NewString(args.Action), "action")
}
if rule, e := modules.SecGroupRules.Update(s, args.ID, params); e != nil {
return e
} else {
printObject(rule)
}
return nil
})
cmd := shell.NewResourceCmd(&modules.SecGroupRules).WithKeyword("secgroup-rule")
cmd.List(&compute.SecGroupRulesListOptions{})
cmd.Show(&options.BaseShowOptions{})
cmd.Delete(&options.BaseIdOptions{})
cmd.Create(&compute.SecGroupRulesCreateOptions{})
cmd.Update(&compute.SecGroupRulesUpdateOptions{})
}

View File

@@ -27,6 +27,8 @@ func init() {
type WireListOptions struct {
options.BaseListOptions
Bandwidth *int `help:"List wires by bandwidth"`
Region string `help:"List wires in region"`
Zone string `help:"list wires in zone" json:"-"`
Vpc string `help:"List wires in vpc"`

View File

@@ -32,6 +32,7 @@ import (
func init() {
type IdentityProviderListOptions struct {
options.BaseListOptions
SsoDomain string `help:"Filter SSO IDP by domain" json:"sso_domain"`
}
R(&IdentityProviderListOptions{}, "idp-list", "List all identity provider", func(s *mcclient.ClientSession, args *IdentityProviderListOptions) error {
params, err := options.ListStructToParams(args)

View File

@@ -115,7 +115,9 @@ func init() {
Enabled bool `help:"update policy enabled"`
Disabled bool `help:"update policy disabled"`
Desc string `help:"Description"`
IsSystem *bool `help:"is_system"`
IsSystem bool `help:"is_system"`
IsNotSystem bool `help:"negative is_system"`
}
updateFunc := func(s *mcclient.ClientSession, args *PolicyPatchOptions) error {
policyId, err := modules.Policies.GetId(s, args.ID, nil)
@@ -141,14 +143,13 @@ func init() {
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
}
if args.IsSystem != nil {
if *args.IsSystem {
params.Add(jsonutils.JSONTrue, "is_system")
} else {
params.Add(jsonutils.JSONFalse, "is_system")
}
if args.IsSystem {
params.Add(jsonutils.JSONTrue, "is_system")
}
result, err := modules.Policies.Patch(s, policyId, params)
if args.IsNotSystem {
params.Add(jsonutils.JSONFalse, "is_system")
}
result, err := modules.Policies.Update(s, policyId, params)
if err != nil {
return err
}

View File

@@ -167,6 +167,32 @@ func initKubeCluster() {
return nil
})
R(&o.ClusterEnableComponentCephCSIOpt{}, cmdN("component-enable-ceph-csi"), "Enable cluster ceph csi component", func(s *mcclient.ClientSession, args *o.ClusterEnableComponentCephCSIOpt) error {
params, err := args.Params()
if err != nil {
return err
}
ret, err := k8s.KubeClusters.PerformAction(s, args.ID, "enable-component", params)
if err != nil {
return err
}
printObject(ret)
return nil
})
R(&o.ClusterEnableComponentMonitorOpt{}, cmdN("component-enable-monitor"), "Enable cluster monitor component", func(s *mcclient.ClientSession, args *o.ClusterEnableComponentMonitorOpt) error {
params, err := args.Params()
if err != nil {
return err
}
ret, err := k8s.KubeClusters.PerformAction(s, args.ID, "enable-component", params)
if err != nil {
return err
}
printObject(ret)
return nil
})
R(&o.ClusterEnableComponentFluentBitOpt{}, cmdN("component-enable-fluentbit"), "Enable cluster fluentbit component", func(s *mcclient.ClientSession, args *o.ClusterEnableComponentFluentBitOpt) error {
params, err := args.Params()
if err != nil {

View File

@@ -10,4 +10,5 @@ func init() {
cmd := shell.NewResourceCmd(modules.AlertRecordManager)
cmd.List(new(options.AlertRecordListOptions))
cmd.Show(new(options.AlertRecordShowOptions))
cmd.Get("", new(options.AlertRecordTotalOptions))
}

View File

@@ -1,67 +0,0 @@
// 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 monitor
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
options "yunion.io/x/onecloud/pkg/mcclient/options/monitor"
)
func init() {
aN := cmdN("suggestsysalert")
R(&options.SuggestSysAlertListOptions{}, aN("list"), "List all suggestsysrules",
func(s *mcclient.ClientSession, args *options.SuggestSysAlertListOptions) error {
params, err := args.Params()
if err != nil {
return err
}
if len(args.Type) > 0 {
params.Add(jsonutils.NewString(args.Type), "type")
}
ret, err := monitor.SuggestSysAlertManager.List(s, params)
if err != nil {
return err
}
printList(ret, monitor.SuggestSysAlertManager.GetColumns(s))
return nil
})
R(&options.SSuggestAlertShowOptions{}, aN("show"), "Show details of a alert rule",
func(s *mcclient.ClientSession, args *options.SSuggestAlertShowOptions) error {
ret, err := monitor.SuggestSysAlertManager.Get(s, args.ID, nil)
if err != nil {
return err
}
printObject(ret)
return nil
})
R(&options.SuggestAlertIgnoreOptions{}, aN("ignore"), "Ignore alert result",
func(s *mcclient.ClientSession, args *options.SuggestAlertIgnoreOptions) error {
params, err := args.Params()
if err != nil {
return err
}
ret, err := monitor.SuggestSysAlertManager.PerformAction(s, args.ID, "ignore", params)
if err != nil {
return err
}
printObject(ret)
return nil
})
}

View File

@@ -111,7 +111,7 @@ func init() {
}
R(&ConfigGetTypesOptions{}, "notify-config-get-types", "Get all Config types", func(s *mcclient.ClientSession, args *ConfigGetTypesOptions) error {
param := jsonutils.Marshal(args)
result, err := modules.NotifyConfig.PerformClassAction(s, "get-types", param)
result, err := modules.NotifyReceiver.PerformClassAction(s, "get-types", param)
if err != nil {
return err
}

View File

@@ -0,0 +1,12 @@
package suggestion
import (
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient/modules"
options "yunion.io/x/onecloud/pkg/mcclient/options/suggestion"
)
func init() {
cmd := shell.NewResourceCmd(modules.AnalysisPredictManager)
cmd.Get("", new(options.AnalysisPredictConfigOptions))
}

View File

@@ -0,0 +1,30 @@
// 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 suggestion
import (
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
options "yunion.io/x/onecloud/pkg/mcclient/options/monitor"
)
func init() {
cmd := shell.NewResourceCmd(monitor.SuggestSysAlertManager)
cmd.List(new(options.SuggestSysAlertListOptions))
cmd.Show(new(options.SSuggestAlertShowOptions))
cmd.Perform("ignore", new(options.SuggestAlertIgnoreOptions))
cmd_ := shell.NewResourceCmd(monitor.SuggestSysAlertCostManager)
cmd_.Get("", new(options.SuggestAlertCostOptions))
}

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package monitor
package suggestion
import (
"yunion.io/x/onecloud/cmd/climc/shell"

2
go.mod
View File

@@ -146,7 +146,7 @@ require (
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
yunion.io/x/pkg v0.0.0-20201123083159-ca3aea986ff2
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/sqlchemy v0.0.0-20201219153152-2d901261898c
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce
)

4
go.sum
View File

@@ -931,7 +931,7 @@ yunion.io/x/pkg v0.0.0-20201123083159-ca3aea986ff2 h1:NeCr2J8HjcIuJvEhP0rwWA1UKP
yunion.io/x/pkg v0.0.0-20201123083159-ca3aea986ff2/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v0.0.0-20201219153152-2d901261898c h1:71nVDQq1oUjvZknEUNfetdiOB1jZMEfmoQlMUaoPIJs=
yunion.io/x/sqlchemy v0.0.0-20201219153152-2d901261898c/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb h1:k7s5xMCd/fw29vUaNsGCrLkyn7w8eSghJ5NChuU9SAk=
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce h1:kU8xE7O5uZ1GSJVMZHoJ+jrNL7csUQHYGyAPW9QfNpE=
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -157,6 +157,9 @@ func (h *AuthHandlers) GetRegionsResponse(ctx context.Context, w http.ResponseWr
}
}
resp.Add(domains, "domains")
resp.Add(jsonutils.JSONTrue, "return_full_domains")
} else {
resp.Add(jsonutils.JSONFalse, "return_full_domains")
}
filters := jsonutils.NewDict()
@@ -309,9 +312,20 @@ func (h *AuthHandlers) doCredentialLogin(ctx context.Context, req *http.Request,
if err != nil {
switch httperr := err.(type) {
case *httputils.JSONClientError:
if httperr.Code >= 500 {
return nil, err
}
if httperr.Code == 409 || httperr.Code == 429 {
return nil, err
}
switch httperr.Class {
case "UserNotFound", "WrongPassword":
return nil, httperrors.NewJsonClientError(httperrors.ErrIncorrectUsernameOrPassword, "incorrect username or password")
case "UserLocked":
return nil, httperrors.NewJsonClientError(httperrors.ErrUserLocked, "The user has been locked, please contact the administrator")
case "UserDisabled":
return nil, httperrors.NewJsonClientError(httperrors.ErrUserDisabled, "The user has been disabled, please contact the administrator")
}
}
return nil, httperrors.NewInvalidCredentialError("invalid credential")
}
@@ -501,34 +515,34 @@ func (h *AuthHandlers) doLogin(ctx context.Context, w http.ResponseWriter, req *
if body.Contains("tenantId") { // switch project
token, authToken, err = doTenantLogin(ctx, req, body)
if err != nil {
return errors.Wrap(err, "doTenantLogin")
return err
}
userInfo, err = fetchUserInfoFromToken(ctx, req, token)
if err != nil {
return errors.Wrap(err, "fetchUserInfoFromToken")
return err
}
} else {
// user/password authenticate
// SSO authentication
token, err = h.doCredentialLogin(ctx, req, body)
if err != nil {
return errors.Wrap(err, "doCredentialLogin")
return err
}
userInfo, err = fetchUserInfoFromToken(ctx, req, token)
if err != nil {
return errors.Wrap(err, "fetchUserInfoFromToken")
return err
}
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
isTotpInit, err := isUserTotpCredInitialed(s, token.GetUserId())
if err != nil {
return errors.Wrap(err, "isUserTotpCredInitialed")
return err
}
isIdpLogin := body.Contains("idp_driver")
authToken = clientman.NewAuthToken(token.GetTokenString(), isUserEnableTotp(userInfo), isTotpInit, isIdpLogin)
}
if !isUserAllowWebconsole(userInfo) {
return errors.Wrap(httperrors.ErrForbidden, "user forbidden login from web")
return httperrors.NewForbiddenError("user forbidden login from web")
}
saveAuthCookie(w, authToken, token)
@@ -986,6 +1000,12 @@ func getUserInfo2(s *mcclient.ClientSession, uid string, pid string, loginIp str
data.Add(jsonutils.JSONFalse, "non_default_domain_projects")
}
if options.Options.EnableQuotaCheck {
data.Add(jsonutils.JSONTrue, "enable_quota_check")
} else {
data.Add(jsonutils.JSONFalse, "enable_quota_check")
}
data.Add(jsonutils.NewString(getSsoCallbackUrl()), "sso_callback_url")
return data, nil
@@ -996,7 +1016,7 @@ func (h *AuthHandlers) getPermissionDetails(ctx context.Context, w http.Response
_, query, body := appsrv.FetchEnv(ctx, w, req)
if body == nil {
httperrors.InvalidInputError(ctx, w, "body is empty")
httperrors.InvalidInputError(ctx, w, "request body is empty")
return
}
var name string
@@ -1030,7 +1050,7 @@ func (h *AuthHandlers) doCreatePolicies(ctx context.Context, w http.ResponseWrit
// }
_, _, body := appsrv.FetchEnv(ctx, w, req)
if body == nil {
httperrors.InvalidInputError(ctx, w, "body is empty")
httperrors.InvalidInputError(ctx, w, "request body is empty")
return
}
s := auth.GetSession(ctx, t, FetchRegion(req), "")
@@ -1114,7 +1134,7 @@ func (h *AuthHandlers) resetUserPassword(ctx context.Context, w http.ResponseWri
_, _, body := appsrv.FetchEnv(ctx, w, req)
if body == nil {
httperrors.InvalidInputError(ctx, w, "body is empty")
httperrors.InvalidInputError(ctx, w, "request body is empty")
return
}
@@ -1150,7 +1170,7 @@ func (h *AuthHandlers) resetUserPassword(ctx context.Context, w http.ResponseWri
return
}
}
httperrors.InputParameterError(ctx, w, "密码错误")
httperrors.InputParameterError(ctx, w, "wrong password")
return
}

View File

@@ -205,7 +205,7 @@ func validateTotpRecoverySecrets(s *mcclient.ClientSession, uid string, question
func initTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
t, authToken, err := fetchAuthInfo(ctx, req)
if err != nil {
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
return
}
if authToken.IsTotpInitialized() {
@@ -232,14 +232,14 @@ func initTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Reque
func validatePasscodeHandler(ctx context.Context, w http.ResponseWriter, req *http.Request) {
t, authToken, err := fetchAuthInfo(ctx, req)
if err != nil {
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
return
}
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
_, _, body := appsrv.FetchEnv(ctx, w, req)
if body == nil {
httperrors.InvalidInputError(ctx, w, "body is empty")
httperrors.InvalidInputError(ctx, w, "request body is empty")
return
}
@@ -271,14 +271,14 @@ func validatePasscodeHandler(ctx context.Context, w http.ResponseWriter, req *ht
func resetTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
t, _, err := fetchAuthInfo(ctx, req)
if err != nil {
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
return
}
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
_, _, body := appsrv.FetchEnv(ctx, w, req)
if body == nil {
httperrors.InvalidInputError(ctx, w, "body is empty")
httperrors.InvalidInputError(ctx, w, "request body is empty")
return
}
@@ -309,7 +309,7 @@ func resetTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Requ
func listTotpRecoveryQuestions(ctx context.Context, w http.ResponseWriter, req *http.Request) {
t, _, err := fetchAuthInfo(ctx, req)
if err != nil {
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
return
}
@@ -335,14 +335,14 @@ func listTotpRecoveryQuestions(ctx context.Context, w http.ResponseWriter, req *
func resetTotpRecoveryQuestions(ctx context.Context, w http.ResponseWriter, req *http.Request) {
t, _, err := fetchAuthInfo(ctx, req)
if err != nil {
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
return
}
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
_, _, body := appsrv.FetchEnv(ctx, w, req)
if body == nil {
httperrors.InvalidInputError(ctx, w, "body is empty")
httperrors.InvalidInputError(ctx, w, "request body is empty")
return
}

View File

@@ -170,7 +170,7 @@ func (h *AuthHandlers) handleSsoLogin(ctx context.Context, w http.ResponseWriter
case "POST":
formData, err := appsrv.Fetch(req)
if err != nil {
httperrors.InputParameterError(ctx, w, "fetch formdata error: %s", err)
httperrors.InputParameterError(ctx, w, "fetch form data error: %s", err)
}
body, err = jsonutils.ParseQueryString(string(formData))
if err != nil {

View File

@@ -42,6 +42,8 @@ import (
"yunion.io/x/onecloud/pkg/util/httputils"
)
const contentTypeSpreadsheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
const (
HOST_MAC = "*MAC地址"
HOST_NAME = "*名称"
@@ -154,8 +156,8 @@ func (mh *MiscHandler) DoBatchHostRegister(ctx context.Context, w http.ResponseW
fileHeader := hostfiles[0].Header
contentType := fileHeader.Get("Content-Type")
if contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" {
e := httperrors.NewInputParameterError("Wrong content type %s, required application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", contentType)
if contentType != contentTypeSpreadsheet {
e := httperrors.NewInputParameterError("Wrong content type %s, want %s", contentType, contentTypeSpreadsheet)
httperrors.JsonClientError(ctx, w, e)
return
}
@@ -199,7 +201,7 @@ func (mh *MiscHandler) DoBatchHostRegister(ctx context.Context, w http.ResponseW
}
if !titlesOk {
httperrors.InputParameterError(ctx, w, "template file is invalid.please check.")
httperrors.InputParameterError(ctx, w, "template file is invalid. please check.")
return
}
@@ -302,8 +304,8 @@ func (mh *MiscHandler) DoBatchUserRegister(ctx context.Context, w http.ResponseW
fileHeader := userfiles[0].Header
contentType := fileHeader.Get("Content-Type")
if contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" {
e := httperrors.NewInputParameterError("Wrong content type %s, required application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", contentType)
if contentType != contentTypeSpreadsheet {
e := httperrors.NewInputParameterError("Wrong content type %s, want %s", contentType, contentTypeSpreadsheet)
httperrors.JsonClientError(ctx, w, e)
return
}
@@ -328,7 +330,7 @@ func (mh *MiscHandler) DoBatchUserRegister(ctx context.Context, w http.ResponseW
// skipped header row
rows := xlsx.GetRows("users")
if len(rows) <= 1 {
e := httperrors.NewInputParameterError("empty file")
e := httperrors.NewInputParameterError("empty file content")
httperrors.JsonClientError(ctx, w, e)
return
} else if len(rows) > BATCH_USER_REGISTER_QUANTITY_LIMITATION {
@@ -431,7 +433,7 @@ func (mh *MiscHandler) getDownloadsHandler(ctx context.Context, w http.ResponseW
params := appctx.AppContextParams(ctx)
template, ok := params["<template_id>"]
if !ok || len(template) == 0 {
httperrors.InvalidInputError(ctx, w, "not found")
httperrors.InvalidInputError(ctx, w, "template_id")
return
}

View File

@@ -142,11 +142,11 @@ func fetchIdList(ctx context.Context, query jsonutils.JSONObject, w http.Respons
if e == nil && len(idlist) > 0 {
queryDict := query.(*jsonutils.JSONDict)
queryDict.Remove("id")
log.Debugf("Get idlist: %s", idlist)
log.Debugf("Get id list: %s", idlist)
return jsonutils.JSONArray2StringArray(idlist)
} else {
log.Debugf("Cannot find idlist in query: %s", query)
httperrors.InvalidInputError(ctx, w, "No idlist found")
log.Debugf("Cannot find id list in query: %s", query)
httperrors.InvalidInputError(ctx, w, "No id list found")
return nil
}
}

View File

@@ -23,7 +23,7 @@ import (
type CloudeventListInput struct {
apis.ModelBaseListInput
apis.ProjectizedResourceListInput
apis.DomainizedResourceListInput
compute.CloudenvResourceListInput
@@ -47,6 +47,6 @@ type CloudeventListInput struct {
type CloudeventDetails struct {
apis.ModelBaseDetails
apis.ProjectizedResourceInfo
apis.DomainizedResourceInfo
SCloudevent
}

View File

@@ -27,6 +27,7 @@ type CloudroleListInput struct {
apis.StatusInfrasResourceBaseListInput
CloudaccountResourceListInput
CloudgroupResourceListInput
}
type CloudroleDetails struct {

View File

@@ -114,6 +114,7 @@ const (
CITY_SOUTH_CAROLINA = "South Carolina" //南卡罗来纳州
CITY_SALT_LAKE_CITY = "Salt Lake City" //盐湖城
CITY_LAS_VEGAS = "Las Vegas" //拉斯维加斯
CITY_PHOENIX = "Phoenix" //菲尼克斯
// 英国
CITY_LONDON = "London" //伦敦
@@ -150,7 +151,8 @@ const (
CITY_STOCKHOLM = "Stockholm" //斯德哥尔摩
// 巴西
CITY_SAO_PAULO = "Sao Paulo" //圣保罗
CITY_SAO_PAULO = "Sao Paulo" //圣保罗
CITY_RIO_DE_JANEIRO = "Rio de Janeiro" // 里约热内卢
// 智利
CITY_SANTIAGO = "Santiago" // 圣地亚哥

View File

@@ -294,6 +294,8 @@ type DBInstanceDetails struct {
SDBInstance
Secgroups []apis.StandaloneShortDesc `json:"secgroups"`
// 安全组名称
// example: Default
Secgroup string `json:"secgroup"`

View File

@@ -372,7 +372,10 @@ type GuestMigrateInput struct {
}
type GuestLiveMigrateInput struct {
// 指定期望的迁移目标宿主机
PreferHost string `json:"prefer_host"`
// 是否跳过CPU检查默认要做CPU检查
SkipCpuCheck *bool `json:"skip_cpu_check"`
}
type GuestSetSecgroupInput struct {

View File

@@ -72,6 +72,8 @@ type HostListInput struct {
ResourceType string `json:"resource_type"`
// filter by mac of any network interface
AnyMac string `json:"any_mac"`
// filter by ip of any network interface
AnyIp string `json:"any_ip"`
// filter storages not attached to this host
StorageNotAttached *bool `json:"storage_not_attached"`
// filter by Hypervisor

View File

@@ -23,6 +23,9 @@ import (
type ScheduledTaskDetails struct {
apis.VirtualResourceDetails
SScheduledTask
// 描述
TimerDesc string `json:"timer_desc"`
// 定时方式触发
Timer TimerDetails `json:"timer"`
// 周期方式触发

View File

@@ -24,14 +24,12 @@ import (
"yunion.io/x/onecloud/pkg/apis"
)
type SSecgroupRuleCreateInput struct {
apis.ResourceBaseCreateInput
type SSecgroupRuleResource struct {
// 优先级, 数字越大优先级越高
// minimum: 1
// maximum: 100
// required: true
Priority int `json:"priority"`
Priority *int `json:"priority"`
// 协议
// required: true
@@ -68,7 +66,7 @@ type SSecgroupRuleCreateInput struct {
// required: true
Direction string `json:"direction"`
// ip或cidr地址
// ip或cidr地址, 若指定peer_secgroup_id此参数不生效
// example: 192.168.222.121
CIDR string `json:"cidr"`
@@ -84,17 +82,36 @@ type SSecgroupRuleCreateInput struct {
// example: test to create rule
Description string `json:"description"`
// 仅单独创建安全组规则时需要指定安全组
// required: true
Secgroup string `json:"secgroup"`
// swagger:ignore
SecgroupId string
// 对端安全组Id, 此参数和cidr参数互斥并且优先级高于cidr, 同事peer_secgroup_id不能和它所在的安全组ID相同
// required: false
PeerSecgroupId string `json:"peer_secgroup_id"`
}
func (input *SSecgroupRuleCreateInput) Check() error {
type SSecgroupRuleCreateInput struct {
apis.ResourceBaseCreateInput
SSecgroupRuleResource
// swagger:ignore
Secgroup string `json:"secgroup" yunion-deprecated-by:"secgroup_id"`
// 安全组ID
// required: true
SecgroupId string `json:"secgroup_id"`
}
type SSecgroupRuleUpdateInput struct {
apis.ResourceBaseUpdateInput
SSecgroupRuleResource
}
func (input *SSecgroupRuleResource) Check() error {
priority := 1
if input.Priority != nil {
priority = *input.Priority
}
rule := secrules.SecurityRule{
Priority: input.Priority,
Priority: priority,
Direction: secrules.TSecurityRuleDirection(input.Direction),
Action: secrules.TSecurityRuleAction(input.Action),
Protocol: input.Protocol,

View File

@@ -22,5 +22,6 @@ type SecgroupRuleDetails struct {
SSecurityGroupRule
SecurityGroupResourceInfo
ProjectId string `json:"tenant_id"`
ProjectId string `json:"tenant_id"`
PeerSecgroup string `json:"peer_secgroup"`
}

View File

@@ -19,12 +19,13 @@ const (
SNAPSHOT_MANUAL = "manual"
SNAPSHOT_AUTO = "auto"
SNAPSHOT_CREATING = "creating"
SNAPSHOT_ROLLBACKING = "rollbacking"
SNAPSHOT_FAILED = "create_failed"
SNAPSHOT_READY = "ready"
SNAPSHOT_DELETING = "deleting"
SNAPSHOT_UNKNOWN = "unknown"
SNAPSHOT_CREATING = "creating"
SNAPSHOT_ROLLBACKING = "rollbacking"
SNAPSHOT_FAILED = "create_failed"
SNAPSHOT_READY = "ready"
SNAPSHOT_DELETE_FAILED = "delete_failed"
SNAPSHOT_DELETING = "deleting"
SNAPSHOT_UNKNOWN = "unknown"
SNAPSHOT_POLICY_CREATING = "creating"

View File

@@ -146,6 +146,25 @@ var (
SHARED_STORAGE = []string{STORAGE_NFS, STORAGE_GPFS, STORAGE_RBD}
)
func IsDiskTypeMatch(t1, t2 string) bool {
switch t1 {
case DISK_TYPE_ROTATE:
if t2 == DISK_TYPE_SSD {
return false
} else {
return true
}
case DISK_TYPE_SSD:
if t2 == DISK_TYPE_ROTATE {
return false
} else {
return true
}
default:
return true
}
}
type StorageResourceInput struct {
// 存储ID或Name
StorageId string `json:"storage_id"`

View File

@@ -33,6 +33,8 @@ const (
DEFAULT_VPC_ID = "default"
NORMAL_VPC_ID = "normal" // 没有关联VPC的安全组统一使用normal
CLASSIC_VPC_NAME = "-"
)
type UsableResourceListInput struct {

View File

@@ -87,4 +87,6 @@ type WireListInput struct {
ZonalFilterListBase
HostResourceInput
Bandwidth *int `json:"bandwidth"`
}

View File

@@ -2068,7 +2068,6 @@ type SScheduledTask struct {
apis.SEnabledResourceBase
ScheduledType string `json:"scheduled_type"`
STimer
TimerDesc string `json:"timer_desc"`
ResourceType string `json:"resource_type"`
Operation string `json:"operation"`
LabelType string `json:"label_type"`

View File

@@ -31,11 +31,12 @@ type SUserExtended struct {
Email string
Mobile string
LocalId int
LocalName string
DomainName string
DomainEnabled bool
IsLocal bool
LocalId int
LocalName string
LocalFailedAuthCount int
DomainName string
DomainEnabled bool
IsLocal bool
// IdpId string
// IdpName string
}

View File

@@ -205,6 +205,8 @@ type PerformStatusInput struct {
// 更改的目标状态值
// required:true
Status string `json:"status"`
// swagger:ignore
BlockJobsCount int `json:"block_jobs_count"`
// 更改状态的原因描述
// required:false

View File

@@ -22,7 +22,7 @@ type AlertResourceType string
const (
// AlertResourceTypeNode means onecloud system infrastructure controller or host node
AlertResourceTypeNode AlertResourceType = "node"
AlertResourceTypeNode AlertResourceType = "host"
// AlertResourceTypeCloudaccount means cloudaccount resource
AlertResourceTypeCloudaccount AlertResourceType = "cloudaccount"
// AlertResourceTypeVM means virtual machine guest resource

View File

@@ -120,10 +120,11 @@ type CommonAlertDetails struct {
}
type CommonAlertMetricDetails struct {
Comparator string `json:"comparator"`
Threshold float64 `json:"threshold"`
ConditionType string `json:"condition_type"`
ThresholdStr string `json:"threshold_str"`
Comparator string `json:"comparator"`
Threshold float64 `json:"threshold"`
WithinRange []float64 `json:"within_range"`
ConditionType string `json:"condition_type"`
ThresholdStr string `json:"threshold_str"`
// metric points'value的运算方式
Reduce string `json:"reduce"`
DB string `json:"db"`

View File

@@ -30,8 +30,8 @@ var (
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_RMB}
ResTypeScoreMap = map[string]int{
METRIC_RES_TYPE_HOST: 1,
METRIC_RES_TYPE_GUEST: 2,
METRIC_RES_TYPE_GUEST: 1,
METRIC_RES_TYPE_HOST: 2,
METRIC_RES_TYPE_OSS: 3,
METRIC_RES_TYPE_RDS: 4,
METRIC_RES_TYPE_REDIS: 5,

View File

@@ -62,6 +62,9 @@ const (
TEMPLATE_TYPE_CONTENT = "content"
TEMPLATE_TYPE_REMOTE = "remote"
TEMPLATE_LANG_EN = "en"
TEMPLATE_LANG_CN = "cn"
CTYPE_ROBOT_YES = "yes"
CTYPE_ROBOT_ONLY = "only"
)

View File

@@ -82,6 +82,8 @@ type ScheduleInput struct {
CpuMode string `json:"cpu_mode"`
OsArch string `json:"os_arch"`
SkipCpuCheck *bool `json:"skip_cpu_check"`
// In the migrate and create backup cases
// we don't need reallocate network
ReuseNetwork bool `json:"reuse_network"`

View File

@@ -27,7 +27,7 @@ type IPMIProfile struct {
func DefaultProfile() IPMIProfile {
return IPMIProfile{
LanChannel: []int{1},
LanChannel: []int{1, 2, 8},
RootName: "root",
RootId: 2,
}
@@ -84,14 +84,24 @@ func QemuProfile() IPMIProfile {
}
}
func H3CProfile() IPMIProfile {
return IPMIProfile{
LanChannel: []int{8, 1},
RootName: "root",
RootId: 2,
StrongPass: true,
}
}
var (
PROFILES map[string]IPMIProfile = map[string]IPMIProfile{
"inspur": InspurProfile(),
"lenovo": LenovoProfile(),
"hp": HpProfile(),
"huawei": HuaweiProfile(),
"foxconn": FoxconnProfile(),
"qemu": QemuProfile(),
types.OEM_NAME_INSPUR: InspurProfile(),
types.OEM_NAME_LENOVO: LenovoProfile(),
types.OEM_NAME_HP: HpProfile(),
types.OEM_NAME_HUAWEI: HuaweiProfile(),
types.OEM_NAME_FOXCONN: FoxconnProfile(),
types.OEM_NAME_QEMU: QemuProfile(),
types.OEM_NAME_H3C: H3CProfile(),
}
)

View File

@@ -459,17 +459,17 @@ func (manager *SMetadataManager) SetValue(ctx context.Context, obj IModel, key s
}
func (manager *SMetadataManager) SetValuesWithLog(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) error {
changes, err := manager.SetValues(ctx, obj, store, userCred)
changes, err := manager.setValues(ctx, obj, store, userCred)
if err != nil {
return err
}
if len(changes) > 0 {
OpsLog.LogEvent(obj, ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
OpsLog.LogEvent(obj.GetIModel(), ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
}
return nil
}
func (manager *SMetadataManager) SetValues(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) ([]sMetadataChange, error) {
func (manager *SMetadataManager) setValues(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) ([]sMetadataChange, error) {
idStr := GetObjectIdstr(obj)
// no need to lock
@@ -546,9 +546,9 @@ func (manager *SMetadataManager) SetValues(ctx context.Context, obj IModel, stor
}
func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential, delRange string) error {
changes, err := manager.SetValues(ctx, obj, store, userCred)
changes, err := manager.setValues(ctx, obj, store, userCred)
if err != nil {
return err
return errors.Wrap(err, "setValues")
}
idStr := GetObjectIdstr(obj)
@@ -565,9 +565,9 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
q := manager.Query().Equals("id", idStr).NotLike("key", `\_\_%`) //避免删除系统内置的metadata, _ 在mysql里面有特殊含义,需要转义
switch delRange {
case USER_TAG_PREFIX:
q = q.Like("key", USER_TAG_PREFIX+"%")
q = q.Startswith("key", USER_TAG_PREFIX)
case CLOUD_TAG_PREFIX:
q = q.Like("key", CLOUD_TAG_PREFIX+"%")
q = q.Startswith("key", CLOUD_TAG_PREFIX)
}
q = q.Filter(sqlchemy.NOT(sqlchemy.In(q.Field("key"), keys)))
if err := FetchModelObjects(manager, q, &records); err != nil {
@@ -581,7 +581,7 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
changes = append(changes, sMetadataChange{Key: rec.Key, OValue: rec.Value})
}
if len(changes) > 0 {
OpsLog.LogEvent(obj, ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
OpsLog.LogEvent(obj.GetIModel(), ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
}
return nil
}
@@ -603,7 +603,7 @@ func (manager *SMetadataManager) GetAll(obj IModel, keys []string, keyPrefix str
ret := make(map[string]string)
for _, rec := range records {
if len(rec.Value) > 0 || strings.HasPrefix(rec.Key, USER_TAG_PREFIX) {
ret[rec.Key] = rec.Value
ret[strings.ToLower(rec.Key)] = rec.Value
}
}
return ret, nil

View File

@@ -126,7 +126,8 @@ func (manager *SOpsLogManager) LogEvent(model IModel, action string, notes inter
if !consts.OpsLogEnabled() {
return
}
if len(model.GetId()) == 0 || len(model.GetName()) == 0 {
if len(model.GetId()) == 0 {
log.Errorf("logevent for an object without ID???")
return
}
if action == ACT_UPDATE {

View File

@@ -47,8 +47,9 @@ const (
ACT_BACKUP_START = "backup_start"
ACT_BACKUP_START_FAILED = "backup_start_fail"
ACT_FREEZE = "freeze"
ACT_UNFREEZE = "unfreeze"
ACT_FREEZE = "freeze"
ACT_FREEZE_FAIL = "freeze_fail"
ACT_UNFREEZE = "unfreeze"
ACT_RESTARING = "restarting"
ACT_RESTART_FAIL = "restart_fail"

View File

@@ -51,6 +51,8 @@ func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action
case rbacutils.ScopeUser:
if ownerId != nil && objOwnerId != nil && (ownerId.GetUserId() == objOwnerId.GetUserId() || objOwnerId.GetUserId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
requireScope = rbacutils.ScopeUser
} else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}
@@ -103,6 +105,8 @@ func isClassRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential
case rbacutils.ScopeUser:
if ownerId != nil && ownerId.GetUserId() == objOwnerId.GetUserId() {
requireScope = rbacutils.ScopeUser
} else if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}

View File

@@ -433,14 +433,9 @@ func notifyWithChannel(ctx context.Context, p sNotifyParams, channels ...npk.TNo
p.recipientId = []string{}
p.contacts = []string{}
p.channel = c
if c == npk.NotifyByWebConsole {
p.contacts = reps
} else {
p.recipientId = reps
}
p.recipientId = reps
rawNotify(ctx, p)
}
}
func NotifyImportant(recipientId []string, isGroup bool, event string, data jsonutils.JSONObject) {
@@ -519,7 +514,7 @@ func notifyRobot(ctx context.Context, robot string, recipientId []string, isGrou
s := auth.GetAdminSession(ctx, consts.GetRegion(), "")
params := jsonutils.NewDict()
params.Set("robot", jsonutils.NewString(robot))
result, err := modules.NotifyConfig.PerformClassAction(s, "get-types", params)
result, err := modules.NotifyReceiver.PerformClassAction(s, "get-types", params)
if err != nil {
return err
}

View File

@@ -35,6 +35,7 @@ const (
OEM_NAME_FOXCONN = "foxconn"
OEM_NAME_QEMU = "qemu"
OEM_NAME_SUPERMICRO = "supermicro"
OEM_NAME_H3C = "h3c"
)
var (
@@ -48,6 +49,7 @@ var (
OEM_NAME_FOXCONN,
OEM_NAME_QEMU,
OEM_NAME_SUPERMICRO,
OEM_NAME_H3C,
}
)

View File

@@ -829,6 +829,9 @@ var ValidateModel = func(userCred mcclient.TokenCredential, manager db.IStandalo
if errors.Cause(err) == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError2(manager.Keyword(), *id)
}
if errors.Cause(err) == sqlchemy.ErrDuplicateEntry {
return nil, httperrors.NewDuplicateResourceError(manager.Keyword(), *id)
}
return nil, httperrors.NewGeneralError(err)
}
*id = model.GetId()

View File

@@ -34,7 +34,7 @@ import (
type SCloudeventManager struct {
db.SModelBaseManager
db.SProjectizedResourceBaseManager
db.SDomainizedResourceBaseManager
}
var CloudeventManager *SCloudeventManager
@@ -57,7 +57,7 @@ func init() {
type SCloudevent struct {
db.SModelBase
db.SProjectizedResourceBase
db.SDomainizedResourceBase
EventId int64 `primary:"true" auto_increment:"true" list:"user"`
Name string `width:"128" charset:"utf8" nullable:"false" index:"true" list:"user"`
@@ -76,6 +76,10 @@ type SCloudevent struct {
Brand string `width:"64" charset:"ascii" list:"domain"`
}
func (self *SCloudeventManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsDomainAllowList(userCred, self)
}
func (self *SCloudeventManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return false
}
@@ -88,6 +92,10 @@ func (self *SCloudevent) AllowUpdateItem(ctx context.Context, userCred mcclient.
return false
}
func (self *SCloudevent) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsDomainAllowGet(userCred, self)
}
// 云平台操作日志列表
func (manager *SCloudeventManager) ListItemFilter(
ctx context.Context,
@@ -97,7 +105,11 @@ func (manager *SCloudeventManager) ListItemFilter(
) (*sqlchemy.SQuery, error) {
q, err := manager.SModelBaseManager.ListItemFilter(ctx, q, userCred, input.ModelBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
return nil, errors.Wrap(err, "SModelBaseManager.ListItemFilter")
}
q, err = manager.SDomainizedResourceBaseManager.ListItemFilter(ctx, q, userCred, input.DomainizedResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SDomainizedResourceBaseManager.ListItemFilter")
}
if len(input.Providers) > 0 {
@@ -153,37 +165,45 @@ func (manager *SCloudeventManager) FetchCustomizeColumns(
) []api.CloudeventDetails {
rows := make([]api.CloudeventDetails, len(objs))
base := manager.SModelBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
projRows := manager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
domainRows := manager.SDomainizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
for i := range rows {
rows[i].ModelBaseDetails = base[i]
rows[i].ProjectizedResourceInfo = projRows[i]
rows[i].DomainizedResourceInfo = domainRows[i]
}
return rows
}
func (self *SCloudevent) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
return self.SModelBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
}
func (manager *SCloudeventManager) NamespaceScope() rbacutils.TRbacScope {
return rbacutils.ScopeDomain
}
func (manager *SCloudeventManager) ResourceScope() rbacutils.TRbacScope {
return rbacutils.ScopeProject
return rbacutils.ScopeDomain
}
func (self *SCloudevent) GetOwnerId() mcclient.IIdentityProvider {
owner := db.SOwnerId{DomainId: self.DomainId, ProjectId: self.ProjectId}
owner := db.SOwnerId{DomainId: self.DomainId}
return &owner
}
func (manager *SCloudeventManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
return manager.SProjectizedResourceBaseManager.FilterByOwner(q, owner, scope)
return manager.SDomainizedResourceBaseManager.FilterByOwner(q, owner, scope)
}
func (manager *SCloudeventManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
return manager.SProjectizedResourceBaseManager.FetchOwnerId(ctx, data)
return manager.SDomainizedResourceBaseManager.FetchOwnerId(ctx, data)
}
func (manager *SCloudeventManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
return manager.SProjectizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
return manager.SDomainizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
}
func (manager *SCloudeventManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
return manager.SProjectizedResourceBaseManager.QueryDistinctExtraField(q, field)
return manager.SDomainizedResourceBaseManager.QueryDistinctExtraField(q, field)
}
func (manager *SCloudeventManager) OrderByExtraFields(
@@ -192,7 +212,7 @@ func (manager *SCloudeventManager) OrderByExtraFields(
userCred mcclient.TokenCredential,
query api.CloudeventListInput,
) (*sqlchemy.SQuery, error) {
return manager.SProjectizedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ProjectizedResourceListInput)
return manager.SDomainizedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.DomainizedResourceListInput)
}
func (manager *SCloudeventManager) SyncCloudevent(ctx context.Context, userCred mcclient.TokenCredential, cloudprovider *SCloudprovider, iEvents []cloudprovider.ICloudEvent) int {
@@ -213,7 +233,6 @@ func (manager *SCloudeventManager) SyncCloudevent(ctx context.Context, userCred
CloudproviderId: cloudprovider.Id,
}
event.DomainId = cloudprovider.DomainId
event.ProjectId = cloudprovider.ProjectId
if len(event.Brand) == 0 {
event.Brand = event.Provider
}

View File

@@ -279,23 +279,12 @@ func (self *SCloudprovider) GetNextTimeRange() (time.Time, time.Time, error) {
if err != nil {
return start, end, errors.Wrap(err, "self.GetProviderFactory")
}
q := CloudeventManager.Query().Equals("cloudprovider_id", self.Id).Desc("created_at")
count, err := q.CountWithError()
if err != nil {
return start, end, errors.Wrap(err, "q.CountWithError")
}
if !self.LastSyncTimeAt.IsZero() {
start = self.LastSyncTimeAt
} else if count == 0 {
start = time.Now().AddDate(0, 0, -1*factory.GetMaxCloudEventKeepDays())
} else {
event := &SCloudevent{}
err = q.First(event)
if err != nil {
return start, end, errors.Wrap(err, "q.First")
}
start = event.CreatedAt
start = time.Now().AddDate(0, 0, -1*factory.GetMaxCloudEventKeepDays())
}
// 避免cloudevent过长时间未运行再次运行时记录的最后一条时间距离现在间隔太长
if start.Before(time.Now().AddDate(0, 0, factory.GetMaxCloudEventKeepDays()*-1)) {
start = time.Now().AddDate(0, 0, factory.GetMaxCloudEventKeepDays()*-1)

View File

@@ -21,8 +21,10 @@ import (
var (
cloudeventSystemResources = []string{}
cloudeventDomainResources = []string{}
cloudeventUserResources = []string{}
cloudeventDomainResources = []string{
"cloudevents",
}
cloudeventUserResources = []string{}
)
func init() {

View File

@@ -383,6 +383,10 @@ func (manager *SCloudaccountManager) SyncCloudaccounts(ctx context.Context, user
}
func (self *SCloudaccount) StartSyncSamlProvidersTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
if self.SAMLAuth.IsFalse() {
log.Debugf("cloudaccount %s(%s) not enable saml auth, skip sycing saml provider", self.Name, self.Provider)
return nil
}
params := jsonutils.NewDict()
task, err := taskman.TaskManager.NewTask(ctx, "SyncSAMLProvidersTask", self, userCred, params, parentTaskId, "", nil)
if err != nil {
@@ -1635,9 +1639,14 @@ func (self *SCloudaccount) SyncSystemCloudpoliciesForCloud(ctx context.Context,
return nil
}
func (self *SCloudaccount) GetLocalUserCloudroles(userId, spId string) ([]SCloudrole, error) {
func (self *SCloudaccount) GetLocalCloudroles(userId, groupId string, spId string, grouped bool) ([]SCloudrole, error) {
roles := []SCloudrole{}
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id).Equals("owner_id", userId).Equals("saml_provider_id", spId)
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id).Equals("saml_provider_id", spId)
if grouped {
q = q.Equals("cloudgroup_id", groupId)
} else {
q = q.Equals("owner_id", userId)
}
err := db.FetchModelObjects(CloudroleManager, q, &roles)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
@@ -1645,55 +1654,90 @@ func (self *SCloudaccount) GetLocalUserCloudroles(userId, spId string) ([]SCloud
return roles, nil
}
func (self *SCloudaccount) RegisterCloudrole(userId, spId string) (*SCloudrole, error) {
roles, err := self.GetLocalUserCloudroles(userId, spId)
func (self *SCloudaccount) RegisterCloudroles(userId string, grouped bool, spId string) ([]SCloudrole, error) {
samlUsers, err := self.GetSamlusers()
if err != nil {
return nil, errors.Wrapf(err, "GetLocalUserCloudroles")
return nil, errors.Wrapf(err, "GetSamlusers")
}
if len(roles) > 0 {
return &roles[0], nil
ret := []SCloudrole{}
roleIds := []string{}
for i := range samlUsers {
if samlUsers[i].OwnerId == userId {
roles, err := self.GetLocalCloudroles(userId, samlUsers[i].CloudgroupId, spId, grouped)
if err != nil {
return nil, errors.Wrapf(err, "GetLocalUserCloudroles")
}
for i := range roles {
if !utils.IsInStringArray(roles[i].Id, roleIds) {
ret = append(ret, roles[i])
break
}
}
if len(roles) == 0 {
role := SCloudrole{}
role.SetModelManager(CloudroleManager, &role)
role.CloudaccountId = self.Id
role.SAMLProviderId = spId
if grouped {
group, err := CloudgroupManager.FetchById(samlUsers[i].CloudgroupId)
if err != nil {
return nil, errors.Wrapf(err, "CloudgroupManager.FetchById(%s)", samlUsers[i].CloudgroupId)
}
role.Name = stringutils2.GenerateRoleName(group.GetName())
role.CloudgroupId = group.GetId()
} else {
user, err := db.UserCacheManager.FetchById(userId)
if err != nil {
return nil, errors.Wrapf(err, "UserCacheManager.FetchById(%s)", userId)
}
role.Name = stringutils2.GenerateRoleName(user.GetName())
role.OwnerId = userId
}
role.Status = api.CLOUD_ROLE_STATUS_CREATING
role.DomainId = self.DomainId
err = CloudroleManager.TableSpec().Insert(context.TODO(), &role)
if err != nil {
return nil, errors.Wrapf(err, "Insert role")
}
ret = append(ret, role)
}
}
}
user, err := db.UserCacheManager.FetchById(userId)
if err != nil {
return nil, errors.Wrapf(err, "UserCacheManager.FetchById(%s)", userId)
}
role := &SCloudrole{}
role.SetModelManager(CloudroleManager, role)
role.CloudaccountId = self.Id
role.OwnerId = userId
role.SAMLProviderId = spId
role.Name = stringutils2.GenerateRoleName(user.GetName())
role.Status = api.CLOUD_ROLE_STATUS_CREATING
role.DomainId = self.DomainId
return role, CloudroleManager.TableSpec().Insert(context.TODO(), role)
return ret, nil
}
func (self *SCloudaccount) GetCloudrole(userId string) (*SCloudrole, error) {
func (self *SCloudaccount) getCloudrolesForSync(userId string, grouped bool) ([]SCloudrole, error) {
sp, valid := self.IsSAMLProviderValid()
if !valid {
return nil, fmt.Errorf("SAMLProvider for account %s not ready", self.Id)
}
return self.RegisterCloudrole(userId, sp.Id)
return self.RegisterCloudroles(userId, grouped, sp.Id)
}
func (self *SCloudaccount) SyncRole(userId string) (*SCloudrole, error) {
role, err := self.GetCloudrole(userId)
func (self *SCloudaccount) SyncRoles(userId string, grouped bool) ([]SCloudrole, error) {
roles, err := self.getCloudrolesForSync(userId, grouped)
if err != nil {
return nil, errors.Wrapf(err, "GetCloudrole")
}
err = role.SyncRoles()
if err != nil {
return nil, errors.Wrapf(err, "SyncRoles")
for i := range roles {
err = roles[i].SyncRoles()
if err != nil {
return nil, errors.Wrapf(err, "SyncRoles")
}
}
return role, nil
if len(roles) == 0 {
return nil, fmt.Errorf("not found any available roles")
}
return roles, nil
}
func (self *SCloudaccount) GetCloudroles() ([]SCloudrole, error) {
roles := []SCloudrole{}
q := CloudroleManager.Query()
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id)
err := db.FetchModelObjects(CloudroleManager, q, &roles)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")

View File

@@ -41,6 +41,7 @@ type SCloudroleManager struct {
db.SExternalizedResourceBaseManager
SCloudaccountResourceBaseManager
SAMLProviderResourceBaseManager
SCloudgroupResourceBaseManager
}
var CloudroleManager *SCloudroleManager
@@ -62,6 +63,7 @@ type SCloudrole struct {
db.SExternalizedResourceBase
SCloudaccountResourceBase
SAMLProviderResourceBase
SCloudgroupResourceBase
Document *jsonutils.JSONDict `length:"long" charset:"ascii" list:"domain" update:"domain" create:"domain_required"`
OwnerId string `width:"128" charset:"ascii" index:"true" list:"user" nullable:"false" create:"optional"`
@@ -80,6 +82,11 @@ func (manager *SCloudroleManager) ListItemFilter(ctx context.Context, q *sqlchem
return nil, err
}
q, err = manager.SCloudgroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudgroupResourceListInput)
if err != nil {
return nil, err
}
return q, nil
}
@@ -161,10 +168,13 @@ func (self *SCloudrole) GetICloudrole() (cloudprovider.ICloudrole, error) {
if err != nil {
return nil, errors.Wrapf(err, "GetSAMLProvider")
}
for i := 0; i < 10; i++ {
for {
_, err := provider.GetICloudroleByName(self.Name)
if err != nil && errors.Cause(err) == cloudprovider.ErrNotFound {
break
if err != nil {
if errors.Cause(err) == cloudprovider.ErrNotFound {
break
}
return nil, errors.Wrapf(err, "GetICloudroleByName(%s)", self.Name)
}
info := strings.Split(self.Name, "-")
num, err := strconv.Atoi(info[len(info)-1])
@@ -196,10 +206,16 @@ func (self *SCloudrole) GetICloudrole() (cloudprovider.ICloudrole, error) {
func (self *SCloudrole) GetCloudpolicies() ([]SCloudpolicy, error) {
q := CloudpolicyManager.Query()
samlUsers := SamluserManager.Query("cloudgroup_id").Equals("owner_id", self.OwnerId).Equals("cloudaccount_id", self.CloudaccountId).SubQuery()
groups := CloudgroupManager.Query("id").In("id", samlUsers)
gp := CloudgroupPolicyManager.Query("cloudpolicy_id").In("cloudgroup_id", groups).SubQuery()
q = q.In("id", gp)
var sq *sqlchemy.SSubQuery
if len(self.OwnerId) > 0 {
su := SamluserManager.Query("cloudgroup_id").Equals("owner_id", self.OwnerId).Equals("cloudaccount_id", self.CloudaccountId).SubQuery()
sq = CloudgroupPolicyManager.Query("cloudpolicy_id").In("cloudgroup_id", su).SubQuery()
} else if len(self.CloudgroupId) > 0 {
sq = CloudgroupPolicyManager.Query("cloudpolicy_id").Equals("cloudgroup_id", self.CloudgroupId).SubQuery()
} else {
return nil, fmt.Errorf("empty owner id or cloudgroup id")
}
q = q.In("id", sq)
policies := []SCloudpolicy{}
err := db.FetchModelObjects(CloudpolicyManager, q, &policies)
if err != nil {

View File

@@ -127,16 +127,6 @@ func (manager *SSamluserManager) ValidateCreateData(ctx context.Context, userCre
return input, err
}
group := _group.(*SCloudgroup)
sq := CloudgroupManager.Query("id").Equals("provider", group.Provider).SubQuery()
q := manager.Query().Equals("owner_id", input.OwnerId).In("cloudgroup_id", sq)
groups := []SCloudgroup{}
err = db.FetchModelObjects(CloudgroupManager, q, &groups)
if err != nil {
return input, httperrors.NewGeneralError(errors.Wrapf(err, "db.FetchModelObjects"))
}
if len(groups) > 0 {
return input, httperrors.NewConflictError("user %s has already in other %s group", input.Name, group.Provider)
}
_account, err := validators.ValidateModel(userCred, CloudaccountManager, &input.CloudaccountId)
if err != nil {
return input, err
@@ -148,6 +138,17 @@ func (manager *SSamluserManager) ValidateCreateData(ctx context.Context, userCre
if account.Provider != group.Provider {
return input, httperrors.NewConflictError("account %s and group %s not with same provider", account.Name, group.Name)
}
sq := CloudgroupManager.Query("id").Equals("provider", group.Provider).SubQuery()
q := manager.Query().Equals("owner_id", input.OwnerId).Equals("cloudaccount_id", account.Id).In("cloudgroup_id", sq)
groups := []SCloudgroup{}
err = db.FetchModelObjects(CloudgroupManager, q, &groups)
if err != nil {
return input, httperrors.NewGeneralError(errors.Wrapf(err, "db.FetchModelObjects"))
}
if len(groups) > 0 {
return input, httperrors.NewConflictError("user %s has already in other %s group", input.Name, group.Provider)
}
input.Status = api.SAML_USER_STATUS_AVAILABLE
return input, nil
}

View File

@@ -52,7 +52,7 @@ func (d *SAliyunSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
}
role, err := account.SyncRole(userCred.GetUserId())
roles, err := account.SyncRoles(userCred.GetUserId(), true)
if err != nil {
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
}
@@ -61,7 +61,7 @@ func (d *SAliyunSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
data.NameIdFormat = samlutils.NAME_ID_FORMAT_PERSISTENT
data.AudienceRestriction = sp.GetEntityId()
for k, v := range map[string]string{
"https://www.aliyun.com/SAML-Role/Attributes/Role": fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
"https://www.aliyun.com/SAML-Role/Attributes/Role": fmt.Sprintf("%s,%s", roles[0].ExternalId, SAMLProvider.ExternalId),
"https://www.aliyun.com/SAML-Role/Attributes/RoleSessionName": userCred.GetUserId(),
"https://www.aliyun.com/SAML-Role/Attributes/SessionDuration": "1800",
} {

View File

@@ -52,7 +52,7 @@ func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
}
role, err := account.SyncRole(userCred.GetUserId())
roles, err := account.SyncRoles(userCred.GetUserId(), true)
if err != nil {
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
}
@@ -68,7 +68,7 @@ func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred
{
name: "https://aws.amazon.com/SAML/Attributes/Role",
friendlyName: "RoleEntitlement",
value: fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
value: fmt.Sprintf("%s,%s", roles[0].ExternalId, SAMLProvider.ExternalId),
},
{
name: "https://aws.amazon.com/SAML/Attributes/RoleSessionName",

View File

@@ -51,7 +51,7 @@ func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCre
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
}
role, err := account.SyncRole(userCred.GetUserId())
roles, err := account.SyncRoles(userCred.GetUserId(), true)
if err != nil {
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
}
@@ -67,7 +67,7 @@ func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCre
{
name: "https://aws.amazon.com/SAML/Attributes/Role",
friendlyName: "RoleEntitlement",
value: fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
value: fmt.Sprintf("%s,%s", roles[0].ExternalId, SAMLProvider.ExternalId),
},
{
name: "https://aws.amazon.com/SAML/Attributes/RoleSessionName",

View File

@@ -52,14 +52,14 @@ func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
}
role, err := account.SyncRole(userCred.GetUserId())
roles, err := account.SyncRoles(userCred.GetUserId(), true)
if err != nil {
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
}
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, role.ExternalId, account.AccountId, SAMLProvider.ExternalId)
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, roles[0].ExternalId, account.AccountId, SAMLProvider.ExternalId)
data.NameId = role.Name
data.NameId = roles[0].Name
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
data.AudienceRestriction = "https://cloud.tencent.com"
for _, v := range []struct {
@@ -75,7 +75,7 @@ func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
{
name: "https://cloud.tencent.com/SAML/Attributes/RoleSessionName",
friendlyName: "RoleSessionName",
value: role.Name,
value: roles[0].Name,
},
} {
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
@@ -94,7 +94,7 @@ func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCre
_account, err := models.CloudaccountManager.FetchById(cloudAccountId)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return data, httperrors.NewResourceNotFoundError("cloudaccount", cloudAccountId)
return data, httperrors.NewResourceNotFoundError2("cloudaccount", cloudAccountId)
}
return data, httperrors.NewGeneralError(err)
}
@@ -111,14 +111,14 @@ func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCre
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
}
role, err := account.SyncRole(userCred.GetUserId())
roles, err := account.SyncRoles(userCred.GetUserId(), true)
if err != nil {
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
}
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, role.ExternalId, account.AccountId, SAMLProvider.ExternalId)
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, roles[0].ExternalId, account.AccountId, SAMLProvider.ExternalId)
data.NameId = role.Name
data.NameId = roles[0].Name
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
data.AudienceRestriction = "https://cloud.tencent.com"
for _, v := range []struct {
@@ -134,7 +134,7 @@ func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCre
{
name: "https://cloud.tencent.com/SAML/Attributes/RoleSessionName",
friendlyName: "RoleSessionName",
value: role.Name,
value: roles[0].Name,
},
} {
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{

View File

@@ -18,7 +18,6 @@ import (
"context"
"fmt"
"net/http"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
@@ -163,12 +162,6 @@ type ProviderConfig struct {
ProxyFunc httputils.TransportProxyFunc
}
func (cp *ProviderConfig) HttpClient() *http.Client {
client := httputils.GetClient(true, 15*time.Second)
httputils.SetClientProxyFunc(client, cp.ProxyFunc)
return client
}
func (cp *ProviderConfig) AdaptiveTimeoutHttpClient() *http.Client {
client := httputils.GetAdaptiveTimeoutClient()
httputils.SetClientProxyFunc(client, cp.ProxyFunc)

View File

@@ -15,15 +15,71 @@
package cloudprovider
import (
"fmt"
"sort"
"strings"
"gopkg.in/fatih/set.v0"
"yunion.io/x/log"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/utils"
)
const DEFAULT_CLOUD_RULE_ID = "default_cloud_rule_id"
const DEFAULT_LOCAL_RULE_ID = "default_local_rule_id"
type SecDriver interface {
GetDefaultSecurityGroupInRule() SecurityRule
GetDefaultSecurityGroupOutRule() SecurityRule
GetSecurityGroupRuleMaxPriority() int
GetSecurityGroupRuleMinPriority() int
IsOnlySupportAllowRules() bool
IsSupportPeerSecgroup() bool
}
func NewSecRuleInfo(driver SecDriver) SecRuleInfo {
return SecRuleInfo{
InDefaultRule: driver.GetDefaultSecurityGroupInRule(),
OutDefaultRule: driver.GetDefaultSecurityGroupOutRule(),
MinPriority: driver.GetSecurityGroupRuleMinPriority(),
MaxPriority: driver.GetSecurityGroupRuleMaxPriority(),
IsOnlySupportAllowRules: driver.IsOnlySupportAllowRules(),
IsSupportPeerSecgroup: driver.IsSupportPeerSecgroup(),
}
}
const DEFAULT_DEST_RULE_ID = "default_dest_rule_id"
const DEFAULT_SRC_RULE_ID = "default_src_rule_id"
type SecRuleInfo struct {
InDefaultRule SecurityRule
OutDefaultRule SecurityRule
Rules SecurityRuleSet
MinPriority int
MaxPriority int
IsOnlySupportAllowRules bool
IsSupportPeerSecgroup bool
}
func (r SecRuleInfo) AddDefaultRule(d SecRuleInfo, inRules, outRules []SecurityRule, isSrc bool) ([]SecurityRule, []SecurityRule) {
min, max := r.MinPriority, r.MaxPriority
r.InDefaultRule.Priority = min + 1
r.OutDefaultRule.Priority = min + 1
if max >= min {
r.InDefaultRule.Priority = min - 1
r.OutDefaultRule.Priority = min - 1
}
if isSrc {
r.InDefaultRule.Id = DEFAULT_SRC_RULE_ID
r.OutDefaultRule.Id = DEFAULT_SRC_RULE_ID
} else {
r.InDefaultRule.ExternalId = DEFAULT_DEST_RULE_ID
r.OutDefaultRule.ExternalId = DEFAULT_DEST_RULE_ID
}
inRules = append(inRules, r.InDefaultRule)
outRules = append(outRules, r.OutDefaultRule)
return inRules, outRules
}
type SecurityGroupFilterOptions struct {
VpcId string
@@ -43,57 +99,38 @@ type SecurityRule struct {
secrules.SecurityRule
Name string
ExternalId string
Id string
PeerSecgroupId string
}
type LocalSecurityRule struct {
secrules.SecurityRule
ExternalId string
}
func (r LocalSecurityRule) String() string {
return r.SecurityRule.String()
}
type LocalSecurityRuleSet []LocalSecurityRule
func (srs LocalSecurityRuleSet) Len() int {
return len(srs)
}
func (srs LocalSecurityRuleSet) Swap(i, j int) {
srs[i], srs[j] = srs[j], srs[i]
}
func (srs LocalSecurityRuleSet) Less(i, j int) bool {
if srs[i].Priority > srs[j].Priority {
return true
} else if srs[i].Priority == srs[j].Priority {
return srs[i].String() < srs[j].String()
}
return false
}
func (srs LocalSecurityRuleSet) AllowList() secrules.SecurityRuleSet {
rules := secrules.SecurityRuleSet{}
for _, r := range srs {
rules = append(rules, r.SecurityRule)
}
return rules.AllowList()
}
type TPriorityOrder int
var (
PriorityOrderByDesc = TPriorityOrder(1)
PriorityOrderByAsc = TPriorityOrder(-1)
)
func (r SecurityRule) String() string {
return r.SecurityRule.String()
if len(r.PeerSecgroupId) == 0 {
return r.SecurityRule.String()
}
return fmt.Sprintf("%s-%s", r.SecurityRule.String(), r.PeerSecgroupId)
}
type SecurityRuleSet []SecurityRule
func (rules SecurityRuleSet) Split(isSupportPeerSecgroup bool) (in, out SecurityRuleSet, isStandardRules bool) {
isStandardRules = true
for i := 0; i < len(rules); i++ {
if len(rules[i].PeerSecgroupId) > 0 {
isStandardRules = false
}
if !isSupportPeerSecgroup && len(rules[i].PeerSecgroupId) > 0 {
continue
}
if rules[i].Direction == secrules.DIR_IN {
in = append(in, rules[i])
} else {
out = append(out, rules[i])
}
}
return
}
func (srs SecurityRuleSet) Len() int {
return len(srs)
}
@@ -114,234 +151,193 @@ func (srs SecurityRuleSet) AllowList() secrules.SecurityRuleSet {
return rules.AllowList()
}
func AddDefaultRule(rules []SecurityRule, defaultRule SecurityRule, localRuleStr string, order TPriorityOrder, min, max int, onlyAllowRules bool) []SecurityRule {
if defaultRule.String() == localRuleStr {
return rules
func (srs SecurityRuleSet) Debug() {
for i := 0; i < len(srs); i++ {
log.Debugf("Name: %s id: %s external_id: %s priority: %d %s", srs[i].Name, srs[i].Id, srs[i].ExternalId, srs[i].Priority, srs[i].String())
}
defaultRule.ExternalId = DEFAULT_CLOUD_RULE_ID
if order == PriorityOrderByDesc {
defaultRule.Priority = min
} else {
defaultRule.Priority = max
}
defaultRule.Priority -= int(order)
return append(rules, defaultRule)
}
func SortSecurityRule(rules SecurityRuleSet, order TPriorityOrder, onlyAllowRules bool) {
if onlyAllowRules {
sort.Sort(rules)
return
}
if order == PriorityOrderByAsc {
func SortSecurityRule(rules SecurityRuleSet, max, min int, isAsc, onlyAllowRules bool) {
if (max >= min || onlyAllowRules) && !isAsc {
sort.Sort(sort.Reverse(rules))
return
}
sort.Sort(rules)
return
}
func CompareRules(
minPriority, maxPriority int, order TPriorityOrder,
localRules secrules.SecurityRuleSet, remoteRules []SecurityRule,
defaultInRule, defaultOutRule SecurityRule,
onlyAllowRules bool, debug bool,
) (common, inAdds, outAdds, inDels, outDels []SecurityRule) {
localInRules := LocalSecurityRuleSet{}
localOutRules := LocalSecurityRuleSet{}
for i := range localRules {
localRule := LocalSecurityRule{}
localRule.SecurityRule = localRules[i]
if localRules[i].Direction == secrules.DIR_IN {
localInRules = append(localInRules, localRule)
} else {
localOutRules = append(localOutRules, localRule)
func isAllowListEqual(src, dest secrules.SecurityRuleSet) bool {
if len(src) != len(dest) {
return false
}
s1, s2 := set.New(set.ThreadSafe), set.New(set.ThreadSafe)
for i := 0; i < len(src); i++ {
s1.Add(src[i].String())
s2.Add(dest[i].String())
}
return s1.IsEqual(s2)
}
func CompareRules(src, dest SecRuleInfo, debug bool) (common, inAdds, outAdds, inDels, outDels SecurityRuleSet) {
srcInRules, srcOutRules, isSrcStandardRules := src.Rules.Split(src.IsSupportPeerSecgroup)
destInRules, destOutRules, isDestStandardRules := dest.Rules.Split(dest.IsSupportPeerSecgroup)
srcInRules, srcOutRules = src.AddDefaultRule(dest, srcInRules, srcOutRules, true)
destInRules, destOutRules = dest.AddDefaultRule(src, destInRules, destOutRules, false)
if debug {
log.Debugf("src in rules: ")
srcInRules.Debug()
}
if (isSrcStandardRules && isDestStandardRules) || (!src.IsSupportPeerSecgroup && !dest.IsSupportPeerSecgroup) {
// AllowList 需要优先级从高到低排序
SortSecurityRule(srcInRules, src.MaxPriority, src.MinPriority, false, src.IsOnlySupportAllowRules)
SortSecurityRule(srcOutRules, src.MaxPriority, src.MinPriority, false, src.IsOnlySupportAllowRules)
SortSecurityRule(destInRules, dest.MaxPriority, dest.MinPriority, false, dest.IsOnlySupportAllowRules)
SortSecurityRule(destOutRules, dest.MaxPriority, dest.MinPriority, false, dest.IsOnlySupportAllowRules)
srcInAllowList := srcInRules.AllowList()
srcOutAllowList := srcOutRules.AllowList()
destInAllowList := destInRules.AllowList()
destOutAllowList := destOutRules.AllowList()
inEquals, outEquals := isAllowListEqual(srcInAllowList, destInAllowList), isAllowListEqual(srcOutAllowList, destOutAllowList)
if inEquals && outEquals {
return
}
}
inRules := SecurityRuleSet{}
outRules := SecurityRuleSet{}
for i := 0; i < len(remoteRules); i++ {
if remoteRules[i].Direction == secrules.DIR_IN {
inRules = append(inRules, remoteRules[i])
} else {
outRules = append(outRules, remoteRules[i])
if debug {
log.Debugf("In: src: %s dest: %s result: %v", srcInAllowList.String(), destInAllowList.String(), inEquals)
log.Debugf("Out: src: %s dest: %s result: %v", srcOutAllowList.String(), destOutAllowList.String(), outEquals)
}
}
var inCommon, outCommon = inRules, outRules
defaultLocalInRule := LocalSecurityRule{ExternalId: DEFAULT_LOCAL_RULE_ID}
defaultLocalInRule.SecurityRule = *secrules.MustParseSecurityRule("in:deny any")
defaultLocalOutRule := LocalSecurityRule{ExternalId: DEFAULT_LOCAL_RULE_ID}
defaultLocalOutRule.SecurityRule = *secrules.MustParseSecurityRule("out:allow any")
inRules = AddDefaultRule(inRules, defaultInRule, defaultLocalInRule.String(), order, minPriority, maxPriority, onlyAllowRules)
outRules = AddDefaultRule(outRules, defaultOutRule, defaultLocalOutRule.String(), order, minPriority, maxPriority, onlyAllowRules)
defaultInEquals, defaultOutEquals := true, true
if defaultLocalInRule.String() != defaultInRule.String() {
localInRules = append(localInRules, defaultLocalInRule)
defaultInEquals = false
}
if defaultLocalOutRule.String() != defaultOutRule.String() {
localOutRules = append(localOutRules, defaultLocalOutRule)
defaultOutEquals = false
}
sort.Sort(localInRules)
sort.Sort(localOutRules)
localInAllowList := localInRules.AllowList()
localOutAllowList := localOutRules.AllowList()
_localInRules := LocalSecurityRuleSet{}
for i := range localInAllowList {
rule := LocalSecurityRule{}
rule.SecurityRule = localInAllowList[i]
_localInRules = append(_localInRules, rule)
}
_localOutRules := LocalSecurityRuleSet{}
for i := range localOutAllowList {
rule := LocalSecurityRule{}
rule.SecurityRule = localOutAllowList[i]
_localOutRules = append(_localOutRules, rule)
}
if onlyAllowRules {
localOutRules, localInRules = _localOutRules, _localInRules
}
if len(_localInRules) < len(localInRules) {
localInRules = _localInRules
}
if len(_localOutRules) < len(localOutRules) {
localOutRules = _localOutRules
}
SortSecurityRule(inRules, order, onlyAllowRules)
SortSecurityRule(outRules, order, onlyAllowRules)
inAllowList := inRules.AllowList()
outAllowList := outRules.AllowList()
inEquals, outEquals := inAllowList.Equals(localInAllowList), outAllowList.Equals(localOutAllowList)
if inEquals && outEquals {
return
}
// priority从小到大排列(从默认规则开始对比)
sort.Sort(sort.Reverse(localInRules))
sort.Sort(sort.Reverse(localOutRules))
sort.Sort(sort.Reverse(inRules))
sort.Sort(sort.Reverse(outRules))
startPriority := minPriority - 1
if order == PriorityOrderByAsc {
startPriority = maxPriority + 1
}
var addPriority = func(priority int, order TPriorityOrder, inc int, min, max int, onlyAllowRules bool) int {
if onlyAllowRules {
return 0
}
inc = inc * int(order) //+ int(order)
priority += inc
if priority < min {
return min
}
if priority > max {
return max
}
return priority
}
var getInitPriority = func(init, min, max int) int {
if init < min || init > max {
return (min + max) / 2
}
return init
}
var compare = func(localRules LocalSecurityRuleSet, remoteRules SecurityRuleSet) (common, add, del []SecurityRule) {
i, j, inc, prePriority := 0, 0, 1, 0
for i < len(localRules) || j < len(remoteRules) {
if i < len(localRules) && j < len(remoteRules) {
ruleStr := remoteRules[j].String()
localRuleStr := localRules[i].String()
if debug {
log.Debugf("compare local priority(%d) %s -> remote name(%s) priority(%d) %s\n", localRules[i].Priority, localRules[i].String(), remoteRules[j].Name, remoteRules[j].Priority, remoteRules[j].String())
var tryUseAllowList = func(defaultRule SecurityRule, allowList secrules.SecurityRuleSet, rules SecurityRuleSet, isOnlyAllowList bool) SecurityRuleSet {
if len(allowList) < len(rules) || isOnlyAllowList {
rules = SecurityRuleSet{}
for i := range allowList {
rule := SecurityRule{}
rule.SecurityRule = allowList[i]
rules = append(rules, rule)
}
cmp := strings.Compare(ruleStr, localRuleStr)
if !utils.IsInStringArray(allowList.String(), []string{
"",
"in:allow any",
"out:allow any",
"in:deny any",
"out:deny any",
}) && strings.HasSuffix(defaultRule.SecurityRule.String(), "deny any") {
rules = append(rules, defaultRule)
}
}
return rules
}
srcInRules = tryUseAllowList(src.InDefaultRule, srcInAllowList, srcInRules, dest.IsOnlySupportAllowRules)
srcOutRules = tryUseAllowList(src.OutDefaultRule, srcOutAllowList, srcOutRules, dest.IsOnlySupportAllowRules)
if inEquals {
srcInRules, destInRules = []SecurityRule{}, []SecurityRule{}
}
if outEquals {
srcOutRules, destOutRules = []SecurityRule{}, []SecurityRule{}
}
}
if debug {
log.Debugf("src in rules: ")
srcInRules.Debug()
}
// 默认从优先级低到高比较
SortSecurityRule(srcInRules, src.MaxPriority, src.MinPriority, true, src.IsOnlySupportAllowRules)
SortSecurityRule(srcOutRules, src.MaxPriority, src.MinPriority, true, src.IsOnlySupportAllowRules)
SortSecurityRule(destInRules, dest.MaxPriority, dest.MinPriority, true, dest.IsOnlySupportAllowRules)
SortSecurityRule(destOutRules, dest.MaxPriority, dest.MinPriority, true, dest.IsOnlySupportAllowRules)
var addPriority = func(priority int, min, max int, onlyAllowRules bool) int {
if onlyAllowRules {
return priority
}
inc := 1
if max < min {
max, min, inc = min, max, -1
}
if priority >= max || priority <= min {
return priority
}
return priority + inc
}
var _compare = func(srcRules SecurityRuleSet, destRules SecurityRuleSet) (common, add, del SecurityRuleSet) {
i, j, priority := 0, 0, (dest.MinPriority-1+dest.MaxPriority)/2
for i < len(srcRules) || j < len(destRules) {
if i < len(srcRules) && j < len(destRules) {
destRuleStr := destRules[j].String()
srcRuleStr := srcRules[i].String()
if debug {
log.Debugf("compare src %s(%s) priority(%d) %s -> dest name(%s) %s(%s) priority(%d) %s\n",
srcRules[i].Id, srcRules[i].ExternalId, srcRules[i].Priority, srcRules[i].String(),
destRules[j].Name, destRules[j].ExternalId, destRules[j].Id, destRules[j].Priority, destRules[j].String())
}
cmp := strings.Compare(destRuleStr, srcRuleStr)
if cmp == 0 {
prePriority = remoteRules[j].Priority
if remoteRules[j].ExternalId == DEFAULT_CLOUD_RULE_ID {
remoteRules[j].Priority = addPriority(remoteRules[j].Priority, order, 1, minPriority, maxPriority, onlyAllowRules)
}
if localRules[i].ExternalId != DEFAULT_LOCAL_RULE_ID ||
(localRules[i].Direction == secrules.DIR_IN && !defaultInEquals) ||
(localRules[i].Direction == secrules.DIR_OUT && !defaultOutEquals) {
common = append(common, remoteRules[j])
destRules[j].Id = srcRules[i].Id
common = append(common, destRules[j])
if destRules[j].ExternalId != DEFAULT_DEST_RULE_ID {
priority = destRules[j].Priority
}
i++
j++
} else if cmp < 0 {
if remoteRules[j].ExternalId != DEFAULT_CLOUD_RULE_ID {
del = append(del, remoteRules[j])
}
del = append(del, destRules[j])
j++
} else {
initPriority := getInitPriority(prePriority, minPriority, maxPriority)
localRules[i].Priority = addPriority(initPriority, order, inc, minPriority, maxPriority, onlyAllowRules)
if localRules[i].ExternalId != DEFAULT_LOCAL_RULE_ID ||
(localRules[i].Direction == secrules.DIR_IN && !defaultInEquals) ||
(localRules[i].Direction == secrules.DIR_OUT && !defaultOutEquals) {
add = append(add, SecurityRule{SecurityRule: localRules[i].SecurityRule})
}
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority, dest.IsOnlySupportAllowRules)
srcRules[i].Priority = priority
add = append(add, srcRules[i])
i++
inc++
}
} else if i >= len(localRules) {
if remoteRules[j].ExternalId != DEFAULT_CLOUD_RULE_ID {
del = append(del, remoteRules[j])
}
} else if i >= len(srcRules) {
del = append(del, destRules[j])
j++
} else if j >= len(remoteRules) {
initPriority := startPriority
if len(remoteRules) > 0 {
initPriority = remoteRules[len(remoteRules)-1].Priority
}
initPriority = getInitPriority(initPriority, minPriority, maxPriority) // 若是初始添加规则,尽量以中间为节点,避免仅出现天地规则
localRules[i].Priority = addPriority(initPriority, order, inc, minPriority, maxPriority, onlyAllowRules)
if localRules[i].ExternalId != DEFAULT_LOCAL_RULE_ID ||
(localRules[i].Direction == secrules.DIR_IN && !defaultInEquals) ||
(localRules[i].Direction == secrules.DIR_OUT && !defaultOutEquals) {
add = append(add, SecurityRule{SecurityRule: localRules[i].SecurityRule})
}
} else if j >= len(destRules) {
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority, dest.IsOnlySupportAllowRules)
srcRules[i].Priority = priority
add = append(add, srcRules[i])
i++
inc++
}
}
return
}
type rulePair struct {
localRules LocalSecurityRuleSet
remoteRules []SecurityRule
protocol string
srcRules SecurityRuleSet
destRules SecurityRuleSet
protocol string
}
var splitRules = func(localRules LocalSecurityRuleSet, remoteRules []SecurityRule) []rulePair {
var splitRules = func(src, dest SecurityRuleSet) []rulePair {
rules := map[string]rulePair{}
for _, r := range localRules {
for _, r := range src {
pair, ok := rules[r.Protocol]
if !ok {
pair = rulePair{localRules: LocalSecurityRuleSet{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
pair = rulePair{srcRules: SecurityRuleSet{}, destRules: SecurityRuleSet{}, protocol: r.Protocol}
}
pair.localRules = append(pair.localRules, r)
pair.srcRules = append(pair.srcRules, r)
rules[r.Protocol] = pair
}
for _, r := range remoteRules {
for _, r := range dest {
pair, ok := rules[r.Protocol]
if !ok {
pair = rulePair{localRules: LocalSecurityRuleSet{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
pair = rulePair{srcRules: SecurityRuleSet{}, destRules: SecurityRuleSet{}, protocol: r.Protocol}
}
pair.remoteRules = append(pair.remoteRules, r)
pair.destRules = append(pair.destRules, r)
rules[r.Protocol] = pair
}
@@ -352,24 +348,62 @@ func CompareRules(
return ret
}
var compareRules = func(localRules LocalSecurityRuleSet, remoteRules []SecurityRule) (common, add, dels []SecurityRule) {
pairs := splitRules(localRules, remoteRules)
var compare = func(src, dest SecurityRuleSet) (common, added, dels SecurityRuleSet) {
pairs := splitRules(src, dest)
for _, r := range pairs {
_common, _add, _dels := compare(r.localRules, r.remoteRules)
_common, _add, _dels := _compare(r.srcRules, r.destRules)
common = append(common, _common...)
add = append(add, _add...)
added = append(added, _add...)
dels = append(dels, _dels...)
}
return
}
if !inEquals {
inCommon, inAdds, inDels = compareRules(localInRules, inRules)
var inCommon, outCommon SecurityRuleSet
inCommon, inAdds, inDels = compare(srcInRules, destInRules)
outCommon, outAdds, outDels = compare(srcOutRules, destOutRules)
var handleDefaultRules = func(removed, added []SecurityRule, isOnlyAllowList bool) ([]SecurityRule, []SecurityRule) {
ret := []SecurityRule{}
for _, rule := range removed {
if rule.ExternalId == DEFAULT_DEST_RULE_ID {
if debug {
log.Debugf("remove dest default rule: %s external id %s priority: %d", rule.String(), rule.ExternalId, rule.Priority)
}
if rule.Action == secrules.SecurityRuleDeny && isOnlyAllowList {
continue
}
switch rule.Action {
case secrules.SecurityRuleDeny:
rule.Action = secrules.SecurityRuleAllow
case secrules.SecurityRuleAllow:
rule.Action = secrules.SecurityRuleDeny
}
rule.Priority = dest.MinPriority
find := false
for i := range added {
if added[i].String() == rule.String() {
find = true
break
}
}
if !find {
if debug {
log.Debugf("add new default rule: %s external id %s priority: %d", rule.String(), rule.ExternalId, rule.Priority)
}
added = append(added, rule)
}
} else {
ret = append(ret, rule)
}
}
return ret, added
}
if !outEquals {
outCommon, outAdds, outDels = compareRules(localOutRules, outRules)
}
common = append(inCommon, outCommon...)
inDels, inAdds = handleDefaultRules(inDels, inAdds, dest.IsOnlySupportAllowRules)
outDels, outAdds = handleDefaultRules(outDels, outAdds, dest.IsOnlySupportAllowRules)
common, _ = handleDefaultRules(append(inCommon, outCommon...), []SecurityRule{}, dest.IsOnlySupportAllowRules)
return
}

View File

@@ -31,6 +31,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/compute/options"
@@ -291,7 +292,14 @@ func (self *SKVMHostDriver) RequestDeallocateDiskOnHost(ctx context.Context, hos
url := fmt.Sprintf("/disks/%s/delete/%s", storage.Id, disk.Id)
body := jsonutils.NewDict()
_, err := host.Request(ctx, task.GetUserCred(), "POST", url, header, body)
return err
if err != nil {
if errors.Cause(err) == cloudprovider.ErrNotFound {
task.ScheduleRun(nil)
return nil
}
return err
}
return nil
}
func (driver *SKVMHostDriver) RequestDeallocateBackupDiskOnHost(ctx context.Context, host *models.SHost, storage *models.SStorage, disk *models.SDisk, task taskman.ITask) error {

View File

@@ -1690,13 +1690,30 @@ type SBucketUsages struct {
func (manager *SBucketManager) TotalCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, rangeObjs []db.IStandaloneModel, providers []string, brands []string, cloudEnv string) SBucketUsages {
usage := SBucketUsages{}
buckets := manager.Query().SubQuery()
bucketsQ := buckets.Query(
sqlchemy.NewFunction(
sqlchemy.NewCase().When(
sqlchemy.GE(buckets.Field("object_cnt"), 0),
buckets.Field("object_cnt"),
).Else(sqlchemy.NewConstField(0)),
"object_cnt1",
),
sqlchemy.NewFunction(
sqlchemy.NewCase().When(
sqlchemy.GE(buckets.Field("size_bytes"), 0),
buckets.Field("size_bytes"),
).Else(sqlchemy.NewConstField(0)),
"size_bytes1",
),
)
bucketsQ = manager.usageQ(bucketsQ, rangeObjs, providers, brands, cloudEnv)
bucketsQ = scopeOwnerIdFilter(bucketsQ, scope, ownerId)
buckets = bucketsQ.SubQuery()
q := buckets.Query(
sqlchemy.COUNT("buckets"),
sqlchemy.SUM("objects", buckets.Field("object_cnt")),
sqlchemy.SUM("bytes", buckets.Field("size_bytes")),
sqlchemy.SUM("objects", buckets.Field("object_cnt1")),
sqlchemy.SUM("bytes", buckets.Field("size_bytes1")),
)
q = manager.usageQ(q, rangeObjs, providers, brands, cloudEnv)
q = scopeOwnerIdFilter(q, scope, ownerId)
err := q.First(&usage)
if err != nil {
log.Errorf("Query bucket usage error %s", err)

View File

@@ -359,7 +359,8 @@ func (scm *SCloudaccountManager) AllowPerformPrepareNets(_ context.Context, user
type sNetworkInfo struct {
esxi.SNetworkInfo
prefix string
prefix string
fakeVsId string
}
func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, client *esxi.SESXiClient,
@@ -376,9 +377,11 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
if err != nil {
return nil, errors.Wrap(err, "unable to fetch ips of hosts and vms")
}
nInfo.IPPool.FillVsId(caName)
ret = append(ret, sNetworkInfo{
SNetworkInfo: nInfo,
prefix: caName,
fakeVsId: caName,
})
case api.CLOUD_ACCOUNT_WIRE_LEVEL_DATACENTER:
dcs, err := client.GetDatacenters()
@@ -390,9 +393,12 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
if err != nil {
return ret, errors.Wrapf(err, "unable to fetch ips of hosts and vms for dc %q", dc.GetName())
}
prefix := fmt.Sprintf("%s/%s", caName, dc.GetName())
nInfo.IPPool.FillVsId(prefix)
ret = append(ret, sNetworkInfo{
SNetworkInfo: nInfo,
prefix: fmt.Sprintf("%s/%s", caName, dc.GetName()),
prefix: prefix,
fakeVsId: prefix,
})
}
case api.CLOUD_ACCOUNT_WIRE_LEVEL_CLUSTER:
@@ -410,9 +416,12 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
if err != nil {
return ret, errors.Wrapf(err, "unable to fetch ips of hosts and vms for dc %q cluster %q", dc.GetName(), cluster.GetName())
}
prefix := fmt.Sprintf("%s/%s/%s", caName, dc.GetName(), cluster.GetName())
nInfo.IPPool.FillVsId(prefix)
ret = append(ret, sNetworkInfo{
SNetworkInfo: nInfo,
prefix: fmt.Sprintf("%s/%s/%s", caName, dc.GetName(), cluster.GetName()),
prefix: prefix,
fakeVsId: prefix,
})
}
}
@@ -555,6 +564,33 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
wires = params.Wires
networks = params.Networks
)
// build global existedNetMap and IPPool
netNum := 0
for i := range networks {
netNum += len(networks[i])
}
existedNets := newIPPool(netNum)
for _, nets := range networks {
for i := range nets {
startIp, _ := netutils.NewIPV4Addr(nets[i].GuestIpStart)
endIp, _ := netutils.NewIPV4Addr(nets[i].GuestIpEnd)
existedNets.Insert(startIp, sSimpleNet{
Diff: endIp - startIp,
Vlan: int32(nets[i].VlanId),
Id: nets[i].Id,
WireId: nets[i].WireId,
})
}
}
ipPoolLen := 0
for i := range nInfos {
ipPoolLen += nInfos[i].IPPool.Len()
}
ipPool := esxi.NewIPPool(ipPoolLen)
for i := range nInfos {
ipPool.Merge(&nInfos[i].IPPool)
}
output.CAWireNets = make([]api.CAWireNet, 0, len(nInfos))
for _, ni := range nInfos {
var (
@@ -569,11 +605,10 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
}
// Find suitable wire and the network containing the Host IP in suitable wire.
var (
tmpSocre int
maxScore = len(ipHosts)
suitableWire *SWire
suitableWireIndex = -1
suitableNetworks map[netutils.IPV4Addr]*SNetwork
tmpSocre int
maxScore = len(ipHosts)
suitableWire *SWire
suitableNetworks map[netutils.IPV4Addr]*SNetwork
)
for i, nets := range networks {
score := 0
@@ -595,7 +630,6 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
if score > tmpSocre {
tmpSocre = score
suitableWire = &wires[i]
suitableWireIndex = i
suitableNetworks = tmpSNs
}
if tmpSocre == maxScore {
@@ -638,30 +672,12 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
}
// Find the suitable network containing the VM IP, and if not, give the corresponding suggested network configuration in this project.
var allNets []SNetwork
if suitableWire != nil {
allNets = networks[suitableWireIndex]
}
type simpleNet struct {
Id string
Vlan int32
}
existedNetMap := make(map[netutils.IPV4Addr]simpleNet, len(allNets))
for i := range allNets {
ipStart, _ := netutils.NewIPV4Addr(allNets[i].GuestIpStart)
ipEnd, _ := netutils.NewIPV4Addr(allNets[i].GuestIpEnd)
for ip := ipStart; ip <= ipEnd; ip++ {
existedNetMap[ip] = simpleNet{Id: allNets[i].Id, Vlan: int32(allNets[i].VlanId)}
}
}
for i := range wireNet.HostSuggestedNetworks {
ipStart, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpStart)
ipEnd, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpEnd)
existedNetMap[ipStart] = simpleNet{}
if ipEnd != ipStart {
existedNetMap[ipEnd] = simpleNet{}
}
existedNets.Insert(ipStart, sSimpleNet{
Diff: ipEnd - ipStart,
})
}
guests := make([]api.CAGuestNet, len(ni.VMs))
@@ -669,7 +685,7 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
guests[i].Name = ni.VMs[i].Name
for _, ipvlan := range ni.VMs[i].IPVlans {
var suitableNetId string
sn, ok := existedNetMap[ipvlan.IP]
sn, ok := existedNets.Get(ipvlan.IP)
if ok {
suitableNetId = sn.Id
}
@@ -685,7 +701,7 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
for vlan, ips := range ni.VlanIps {
for i := 0; i < len(ips); i++ {
ip := ips[i]
if _, ok := existedNetMap[ip]; ok {
if _, ok := existedNets.Get(ip); ok {
continue
}
net := ip.NetAddr(24)
@@ -694,20 +710,20 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
// find startip
startIp := ip - 1
for ; startIp >= netLimitLow; startIp-- {
if _, ok := existedNetMap[startIp]; ok {
if _, ok := existedNets.Get(startIp); ok {
break
}
if _, ok := ni.IPPool.Get(startIp); ok {
if _, ok := ipPool.Get(startIp); ok {
break
}
}
endIp := ip + 1
for ; endIp <= netLimitUp; endIp++ {
if _, ok := existedNetMap[endIp]; ok {
if _, ok := existedNets.Get(endIp); ok {
break
}
if proc, ok := ni.IPPool.Get(endIp); ok {
if proc.VlanId == vlan {
if proc, ok := ipPool.Get(endIp); ok {
if proc.VlanId == vlan && proc.VSId == ni.fakeVsId {
// find one in ips
i++
continue
@@ -729,8 +745,9 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
},
})
// Avoid assigning already assigned ip subnet
existedNetMap[startIp+1] = simpleNet{}
existedNetMap[endIp-1] = simpleNet{}
existedNets.Insert(startIp+1, sSimpleNet{
Diff: endIp - startIp - 2,
})
}
}
output.CAWireNets = append(output.CAWireNets, wireNet)
@@ -824,6 +841,64 @@ func (manager *SCloudaccountManager) suggestHostNetworks(ips []netutils.IPV4Addr
return ret
}
type sIPPool struct {
netranges []netutils.IPV4Addr
simpleNetMap map[netutils.IPV4Addr]sSimpleNet
}
func newIPPool(length ...int) *sIPPool {
initLen := 0
if len(length) > 0 {
initLen = length[0]
}
return &sIPPool{
netranges: make([]netutils.IPV4Addr, 0, initLen),
simpleNetMap: make(map[netutils.IPV4Addr]sSimpleNet, initLen),
}
}
type sSimpleNet struct {
Diff netutils.IPV4Addr
Id string
Vlan int32
WireId string
}
func (pl *sIPPool) Insert(startIp netutils.IPV4Addr, sNet sSimpleNet) {
// TODO:check
index := pl.getIndex(startIp)
pl.netranges = append(pl.netranges, 0)
pl.netranges = append(pl.netranges[:index+1], pl.netranges[index:len(pl.netranges)-1]...)
pl.netranges[index] = startIp
pl.simpleNetMap[startIp] = sNet
}
func (pl *sIPPool) getIndex(ip netutils.IPV4Addr) int {
index := sort.Search(len(pl.netranges), func(n int) bool {
return pl.netranges[n] >= ip
})
return index
}
func (pl *sIPPool) Get(ip netutils.IPV4Addr) (sSimpleNet, bool) {
index := pl.getIndex(ip)
if index > len(pl.netranges) || index < 0 {
return sSimpleNet{}, false
}
if index < len(pl.netranges) && pl.netranges[index] == ip {
return pl.simpleNetMap[ip], true
}
if index == 0 {
return sSimpleNet{}, false
}
startIp := pl.netranges[index-1]
simpleNet := pl.simpleNetMap[startIp]
if ip-startIp <= simpleNet.Diff {
return simpleNet, true
}
return sSimpleNet{}, false
}
// The suggestVMNetworks give the suggest config of network that contain the IP in 'ips' and does not intersect with the network segment described in 'excludes'.
// The suggested network mask is 24 and the gateway is x.x.x.1.
// The suggests network is the largest network segment that meets the above conditions.
@@ -2565,7 +2640,7 @@ func (account *SCloudaccount) SubmitSyncAccountTask(ctx context.Context, userCre
cloudaccountPendingSyncs[account.Id] = struct{}{}
RunSyncCloudAccountTask(ctx, func() {
func() {
defer func() {
cloudaccountPendingSyncsMutex.Lock()
defer cloudaccountPendingSyncsMutex.Unlock()
delete(cloudaccountPendingSyncs, account.Id)
@@ -3287,7 +3362,7 @@ func (self *SCloudaccount) SyncAccountResources(ctx context.Context, userCred mc
return errors.Wrapf(err, "GetProvider")
}
if cloudprovider.IsSupportProject(provider) {
return func() error {
err = func() error {
lockman.LockRawObject(ctx, "projects", self.Id)
defer lockman.ReleaseRawObject(ctx, "projects", self.Id)
@@ -3299,10 +3374,13 @@ func (self *SCloudaccount) SyncAccountResources(ctx context.Context, userCred mc
log.Infof("Sync project for cloudaccount %s result: %s", self.Name, result.Result())
return nil
}()
if err != nil {
log.Errorf("sync project for account %s error: %v", self.Name, err)
}
}
if cloudprovider.IsSupportDnsZone(provider) {
return func() error {
err = func() error {
lockman.LockRawObject(ctx, "dns_zones", self.Id)
defer lockman.ReleaseRawObject(ctx, "dns_zones", self.Id)
@@ -3327,6 +3405,9 @@ func (self *SCloudaccount) SyncAccountResources(ctx context.Context, userCred mc
}
return nil
}()
if err != nil {
log.Errorf("sync dns zone for account %s error: %v", self.Name, err)
}
}
return nil

View File

@@ -38,6 +38,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/options"
@@ -537,6 +538,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
manRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
rdsIds := make([]string, len(rows))
vpcIds := make([]string, len(rows))
zone1Ids := make([]string, len(rows))
zone2Ids := make([]string, len(rows))
@@ -548,6 +550,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
CloudregionResourceInfo: regRows[i],
}
instance := objs[i].(*SDBInstance)
rdsIds[i] = instance.Id
vpcIds[i] = instance.VpcId
zone1Ids[i] = instance.Zone1
zone2Ids[i] = instance.Zone2
@@ -569,6 +572,42 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
}
}
q := SecurityGroupManager.Query()
ownerId, queryScope, err := db.FetchCheckQueryOwnerScope(ctx, userCred, query, SecurityGroupManager, policy.PolicyActionList, true)
if err != nil {
log.Errorf("FetchCheckQueryOwnerScope error: %v", err)
return rows
}
secgroups := SecurityGroupManager.FilterByOwner(q, ownerId, queryScope).SubQuery()
rdssecgroups := DBInstanceSecgroupManager.Query().SubQuery()
secQ := rdssecgroups.Query(rdssecgroups.Field("dbinstance_id"), rdssecgroups.Field("secgroup_id"), secgroups.Field("name").Label("secgroup_name")).Join(secgroups, sqlchemy.Equals(rdssecgroups.Field("secgroup_id"), secgroups.Field("id"))).Filter(sqlchemy.In(rdssecgroups.Field("dbinstance_id"), rdsIds))
type sRdsSecgroupInfo struct {
DBInstanceId string `json:"dbinstance_id"`
SecgroupName string
SecgroupId string
}
rsgs := []sRdsSecgroupInfo{}
err = secQ.All(&rsgs)
if err != nil {
log.Errorf("secQ.All error: %v", err)
return rows
}
ret := make(map[string][]apis.StandaloneShortDesc)
for i := range rsgs {
rsg, ok := ret[rsgs[i].DBInstanceId]
if !ok {
rsg = make([]apis.StandaloneShortDesc, 0)
}
rsg = append(rsg, apis.StandaloneShortDesc{
Id: rsgs[i].SecgroupId,
Name: rsgs[i].SecgroupName,
})
ret[rsgs[i].DBInstanceId] = rsg
}
zone1, err := db.FetchIdNameMap2(ZoneManager, zone1Ids)
if err != nil {
return rows
@@ -588,6 +627,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
rows[i].Zone1Name = zone1[zone1Ids[i]]
rows[i].Zone2Name = zone2[zone2Ids[i]]
rows[i].Zone3Name = zone3[zone3Ids[i]]
rows[i].Secgroups, _ = ret[rdsIds[i]]
}
return rows

View File

@@ -432,18 +432,21 @@ func (self *SGuest) PerformLiveMigrate(ctx context.Context, userCred mcclient.To
host := iHost.(*SHost)
preferHostId = host.Id
}
err := self.StartGuestLiveMigrateTask(ctx, userCred, self.Status, preferHostId, "")
err := self.StartGuestLiveMigrateTask(ctx, userCred, self.Status, preferHostId, input.SkipCpuCheck, "")
return nil, err
}
return nil, httperrors.NewBadRequestError("Cannot live migrate in status %s", self.Status)
}
func (self *SGuest) StartGuestLiveMigrateTask(ctx context.Context, userCred mcclient.TokenCredential, guestStatus, preferHostId, parentTaskId string) error {
func (self *SGuest) StartGuestLiveMigrateTask(ctx context.Context, userCred mcclient.TokenCredential, guestStatus, preferHostId string, skipCpuCheck *bool, parentTaskId string) error {
self.SetStatus(userCred, api.VM_START_MIGRATE, "")
data := jsonutils.NewDict()
if len(preferHostId) > 0 {
data.Set("prefer_host_id", jsonutils.NewString(preferHostId))
}
if skipCpuCheck != nil {
data.Set("skip_cpu_check", jsonutils.NewBool(*skipCpuCheck))
}
data.Set("guest_status", jsonutils.NewString(guestStatus))
dedicateMigrateTask := "GuestLiveMigrateTask"
if self.GetHypervisor() != api.HYPERVISOR_KVM {
@@ -805,6 +808,16 @@ func (self *SGuest) AllowPerformStart(ctx context.Context,
func (self *SGuest) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_START_FAILED, api.VM_SAVE_DISK_FAILED, api.VM_SUSPEND}) {
if !self.guestDisksStorageTypeIsShared() {
host := self.GetHost()
guestsMem, err := host.GetNotReadyGuestsMemorySize()
if err != nil {
return nil, err
}
if float32(guestsMem+self.VmemSize) > host.GetVirtualMemorySize() {
return nil, httperrors.NewInsufficientResourceError("host virtual memory not enough")
}
}
if self.isAllDisksReady() {
var kwargs *jsonutils.JSONDict
if data != nil {
@@ -2726,7 +2739,7 @@ func (self *SGuest) PerformStatus(ctx context.Context, userCred mcclient.TokenCr
}
status := input.Status
if len(self.BackupHostId) > 0 && status == api.VM_RUNNING {
if len(self.BackupHostId) > 0 && status == api.VM_RUNNING && input.BlockJobsCount > 0 {
self.SetMetadata(ctx, api.MIRROR_JOB, api.MIRROR_JOB_READY, userCred)
} else if ispId := self.GetMetadata(api.BASE_INSTANCE_SNAPSHOT_ID, userCred); len(ispId) > 0 {
ispM, err := InstanceSnapshotManager.FetchById(ispId)
@@ -2763,6 +2776,27 @@ func (self *SGuest) PerformStop(ctx context.Context, userCred mcclient.TokenCred
return nil, httperrors.NewInvalidStatusError("Cannot stop server in status %s", self.Status)
}
func (self *SGuest) PerformFreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformFreezeInput) (jsonutils.JSONObject, error) {
if self.Freezed {
return nil, httperrors.NewBadRequestError("virtual resource already freezed")
}
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_STOP_FAILED}) {
return nil, self.StartGuestStopAndFreezeTask(ctx, userCred)
} else {
return self.SVirtualResourceBase.PerformFreeze(ctx, userCred, query, input)
}
}
func (self *SGuest) StartGuestStopAndFreezeTask(ctx context.Context, userCred mcclient.TokenCredential) error {
self.SetStatus(userCred, api.VM_START_STOP, "")
task, err := taskman.TaskManager.NewTask(ctx, "GuestStopAndFreezeTask", self, userCred, nil, "", "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SGuest) AllowPerformRestart(ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,

View File

@@ -32,7 +32,6 @@ import (
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/util/osprofile"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
@@ -365,11 +364,9 @@ func (manager *SGuestManager) ListItemFilter(
if len(query.IpAddr) > 0 {
gn := GuestnetworkManager.Query("guest_id").Contains("ip_addr", query.IpAddr).SubQuery()
guestEip := ElasticipManager.Query("associate_id").Equals("associate_type", api.EIP_ASSOCIATE_TYPE_SERVER).Contains("ip_addr", query.IpAddr).SubQuery()
q = q.LeftJoin(gn, sqlchemy.Equals(q.Field("id"), gn.Field("guest_id")))
q = q.LeftJoin(guestEip, sqlchemy.Equals(q.Field("id"), guestEip.Field("associate_id")))
q = q.Filter(sqlchemy.OR(
sqlchemy.IsNotNull(gn.Field("guest_id")),
sqlchemy.IsNotNull(guestEip.Field("associate_id")),
sqlchemy.In(q.Field("id"), gn),
sqlchemy.In(q.Field("id"), guestEip),
))
}
@@ -1324,6 +1321,13 @@ func (manager *SGuestManager) validateCreateData(
}
log.Debugf("ROOT DISK: %#v", rootDiskConfig)
input.Disks[0] = rootDiskConfig
if sku != nil {
if len(rootDiskConfig.OsArch) >= 0 && len(sku.CpuArch) >= 0 {
if strings.Contains(rootDiskConfig.OsArch, sku.CpuArch) {
return nil, httperrors.NewConflictError("root disk image(%s) and sku(%s) architecture mismatch", rootDiskConfig.OsArch, sku.CpuArch)
}
}
}
//data.Set("disk.0", jsonutils.Marshal(rootDiskConfig))
for i := 0; i < len(dataDiskDefs); i += 1 {
@@ -2334,31 +2338,6 @@ func (self *SGuest) getAdminSecgroupName() string {
return ""
}
func (self *SGuest) GetSecRules() []secrules.SecurityRule {
return self.getSecRules()
}
func (self *SGuest) getSecRules() []secrules.SecurityRule {
if secgrp := self.getSecgroup(); secgrp != nil {
return secgrp.GetSecRules("")
}
if rule, err := secrules.ParseSecurityRule(options.Options.DefaultSecurityRules); err == nil {
return []secrules.SecurityRule{*rule}
} else {
log.Errorf("Default SecurityRules error: %v", err)
}
return []secrules.SecurityRule{}
}
func (self *SGuest) getSecurityRules() string {
secgrp := self.getSecgroup()
if secgrp != nil {
return secgrp.getSecurityRuleString("")
} else {
return options.Options.DefaultSecurityRules
}
}
//获取多个安全组规则,优先级降序排序
func (self *SGuest) getSecurityGroupsRules() string {
secgroups, _ := self.GetSecgroups()
@@ -2383,7 +2362,8 @@ func (self *SGuest) getSecurityGroupsRules() string {
func (self *SGuest) getAdminSecurityRules() string {
secgrp := self.getAdminSecgroup()
if secgrp != nil {
return secgrp.getSecurityRuleString("")
ret, _ := secgrp.getSecurityRuleString()
return ret
} else {
return options.Options.DefaultAdminSecurityRules
}
@@ -4784,7 +4764,7 @@ func (self *SGuestManager) switchBackupGuests(ctx context.Context, userCred mccl
log.Errorf("ReconcileBackupGuests failed fetch guests %s", err)
return
}
log.Infof("Guests count %d need reconcile with switch bakcup", len(guests))
log.Debugf("Guests count %d need reconcile with switch backup", len(guests))
for i := 0; i < len(guests); i++ {
val := guests[i].GetMetadataJson("switch_backup", userCred)
t, err := val.GetTime()
@@ -5276,8 +5256,11 @@ func (self *SGuest) ToCreateInput(userCred mcclient.TokenCredential) *api.Server
userInput.KeypairId = genInput.KeypairId
userInput.EipBw = genInput.EipBw
userInput.EipChargeType = genInput.EipChargeType
userInput.PublicIpBw = genInput.PublicIpBw
userInput.PublicIpChargeType = genInput.PublicIpChargeType
provider := self.GetDriver()
if provider.IsSupportPublicIp() {
userInput.PublicIpBw = genInput.PublicIpBw
userInput.PublicIpChargeType = genInput.PublicIpChargeType
}
userInput.AutoRenew = genInput.AutoRenew
// cloned server should belongs to the project creating it
userInput.ProjectId = userCred.GetProjectId()
@@ -5347,8 +5330,10 @@ func (self *SGuest) toCreateInput() *api.ServerCreateInput {
r.EipBw = eip.Bandwidth
r.EipChargeType = eip.ChargeType
case api.EIP_MODE_INSTANCE_PUBLICIP:
r.PublicIpBw = eip.Bandwidth
r.PublicIpChargeType = eip.ChargeType
if driver := self.GetDriver(); driver.IsSupportPublicIp() {
r.PublicIpBw = eip.Bandwidth
r.PublicIpChargeType = eip.ChargeType
}
}
}
if zone := self.getZone(); zone != nil {

View File

@@ -251,6 +251,14 @@ func (manager *SHostManager) ListItemFilter(
q = q.Equals("access_mac", anyMac)
}
}
if len(query.AnyIp) > 0 {
hn := HostnetworkManager.Query("baremetal_id").Contains("ip_addr", query.AnyIp).SubQuery()
q = q.Filter(sqlchemy.OR(
sqlchemy.Contains(q.Field("access_ip"), query.AnyIp),
sqlchemy.Contains(q.Field("ipmi_ip"), query.AnyIp),
sqlchemy.In(q.Field("id"), hn),
))
}
// var scopeQuery *sqlchemy.SSubQuery
schedTagStr := query.SchedtagId
@@ -1497,6 +1505,23 @@ func (self *SHost) GetRunningGuestCount() (int, error) {
return q.CountWithError()
}
func (self *SHost) GetNotReadyGuestsMemorySize() (int, error) {
guests := GuestManager.Query().SubQuery()
q := guests.Query(sqlchemy.COUNT("guest_count"),
sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")),
sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")))
cond := sqlchemy.OR(sqlchemy.Equals(q.Field("host_id"), self.Id),
sqlchemy.Equals(q.Field("backup_host_id"), self.Id))
q = q.Filter(cond)
q = q.NotEquals("status", api.VM_READY)
stat := SHostGuestResourceUsage{}
err := q.First(&stat)
if err != nil {
return -1, err
}
return stat.GuestVmemSize, nil
}
func (self *SHost) GetRunningGuestMemorySize() int {
res := self.getGuestsResource(api.VM_RUNNING)
if res != nil {

View File

@@ -184,9 +184,9 @@ func (man *SAwsCachedLbbgManager) GetCachedBackendGroups(backendGroupId string)
return ret, nil
}
func (man *SAwsCachedLbbgManager) getLoadbalancerBackendgroupsByRegion(regionId string) ([]SAwsCachedLbbg, error) {
func (man *SAwsCachedLbbgManager) getLoadbalancerBackendgroupsByRegion(managerId string, regionId string) ([]SAwsCachedLbbg, error) {
lbbgs := []SAwsCachedLbbg{}
q := man.Query().Equals("cloudregion_id", regionId).IsFalse("pending_deleted")
q := man.Query().Equals("cloudregion_id", regionId).Equals("manager_id", managerId).IsFalse("pending_deleted")
if err := db.FetchModelObjects(man, q, &lbbgs); err != nil {
log.Errorf("failed to get lbbgs for region: %s error: %v", regionId, err)
return nil, err
@@ -204,7 +204,7 @@ func (man *SAwsCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.Cont
remoteLbbgs := []cloudprovider.ICloudLoadbalancerBackendGroup{}
syncResult := compare.SyncResult{}
dbLbbgs, err := man.getLoadbalancerBackendgroupsByRegion(region.GetId())
dbLbbgs, err := man.getLoadbalancerBackendgroupsByRegion(provider.GetId(), region.GetId())
if err != nil {
syncResult.Error(err)
return nil, nil, syncResult

View File

@@ -303,11 +303,11 @@ func (man *SLoadbalancerManager) ValidateCreateData(
var region *SCloudregion
if len(input.VpcId) > 0 {
var vpc *SVpc
vpc, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
_vpc, err := validators.ValidateModel(userCred, VpcManager, &input.VpcId)
if err != nil {
return nil, errors.Wrap(err, "ValidateVpcResourceInput")
return nil, err
}
vpc := _vpc.(*SVpc)
region, _ = vpc.GetRegion()
} else if len(input.ZoneId) > 0 {
var zone *SZone
@@ -716,6 +716,19 @@ func (lb *SLoadbalancer) getMoreDetails(out api.LoadbalancerDetails) (api.Loadba
}
func (lb *SLoadbalancer) ValidateDeleteCondition(ctx context.Context) error {
err := lb.validatePurgeCondition(ctx)
if err != nil {
return err
}
if lb.DisableDelete.IsTrue() {
return httperrors.NewInvalidStatusError("loadbalancer is locked, cannot delete")
}
return nil
}
func (lb *SLoadbalancer) validatePurgeCondition(ctx context.Context) error {
region := lb.GetRegion()
if region != nil {
if err := region.GetDriver().ValidateDeleteLoadbalancerCondition(ctx, lb); err != nil {
@@ -723,10 +736,6 @@ func (lb *SLoadbalancer) ValidateDeleteCondition(ctx context.Context) error {
}
}
if lb.DisableDelete.IsTrue() {
return httperrors.NewInvalidStatusError("loadbalancer is locked, cannot delete")
}
return lb.SModelBase.ValidateDeleteCondition(ctx)
}
@@ -790,11 +799,9 @@ func (lb *SLoadbalancer) Delete(ctx context.Context, userCred mcclient.TokenCred
func (man *SLoadbalancerManager) getLoadbalancersByRegion(region *SCloudregion, provider *SCloudprovider) ([]SLoadbalancer, error) {
lbs := []SLoadbalancer{}
vpcs := VpcManager.Query().SubQuery()
q := man.Query()
q = q.Join(vpcs, sqlchemy.Equals(q.Field("vpc_id"), vpcs.Field("id")))
q = q.Filter(sqlchemy.Equals(vpcs.Field("cloudregion_id"), region.Id))
q = q.Filter(sqlchemy.Equals(vpcs.Field("manager_id"), provider.Id))
q = q.Equals("manager_id", provider.Id)
q = q.Equals("cloudregion_id", region.Id)
q = q.IsFalse("pending_deleted")
if err := db.FetchModelObjects(man, q, &lbs); err != nil {
log.Errorf("failed to get lbs for region: %v provider: %v error: %v", region, provider, err)
@@ -816,6 +823,12 @@ func (man *SLoadbalancerManager) getLoadbalancersByExternalIds(externalIds []str
}
func (man *SLoadbalancerManager) getLocalLoadbalancers(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, lbs []cloudprovider.ICloudLoadbalancer) ([]SLoadbalancer, error) {
// current external ID
extIds := []string{}
for i := range lbs {
extIds = append(extIds, lbs[i].GetGlobalId())
}
part1, err := man.getLoadbalancersByRegion(region, provider)
if err != nil {
return nil, err
@@ -824,15 +837,13 @@ func (man *SLoadbalancerManager) getLocalLoadbalancers(ctx context.Context, user
localLbs := map[string]SLoadbalancer{}
for i := range part1 {
localLbs[part1[i].Id] = part1[i]
if len(part1[i].GetExternalId()) > 0 {
extIds = append(extIds, part1[i].GetExternalId())
}
}
externalIds := []string{}
for i := range lbs {
externalIds = append(externalIds, lbs[i].GetGlobalId())
}
if len(externalIds) > 0 {
part2, err := man.getLoadbalancersByExternalIds(externalIds)
if len(extIds) > 0 {
part2, err := man.getLoadbalancersByExternalIds(extIds)
if err != nil {
return nil, err
}
@@ -842,7 +853,7 @@ func (man *SLoadbalancerManager) getLocalLoadbalancers(ctx context.Context, user
}
}
ret := []SLoadbalancer{}
ret := make([]SLoadbalancer, 0)
for id, _ := range localLbs {
ret = append(ret, localLbs[id])
}
@@ -860,7 +871,7 @@ func (man *SLoadbalancerManager) SyncLoadbalancers(ctx context.Context, userCred
remoteLbs := []cloudprovider.ICloudLoadbalancer{}
syncResult := compare.SyncResult{}
dbLbs, err := man.getLocalLoadbalancers(ctx, userCred, provider, region, remoteLbs)
dbLbs, err := man.getLocalLoadbalancers(ctx, userCred, provider, region, lbs)
if err != nil {
syncResult.Error(err)
return nil, nil, syncResult
@@ -1007,7 +1018,7 @@ func (lb *SLoadbalancer) syncRemoveCloudLoadbalancer(ctx context.Context, userCr
lockman.LockObject(ctx, lb)
defer lockman.ReleaseObject(ctx, lb)
err := lb.ValidateDeleteCondition(ctx)
err := lb.validatePurgeCondition(ctx)
if err != nil { // cannot delete
return lb.SetStatus(userCred, api.LB_STATUS_UNKNOWN, "sync to delete")
} else {

View File

@@ -298,6 +298,16 @@ func (self *SNetwork) ValidateElbNetwork(ipAddr net.IP) (*SCloudregion, *SZone,
return region, zone, vpc, wire, nil
}
func (self *SNetwork) GetGuestnetworks() ([]SGuestnetwork, error) {
q := GuestnetworkManager.Query().Equals("network_id", self.Id)
gns := []SGuestnetwork{}
err := db.FetchModelObjects(GuestnetworkManager, q, &gns)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
return gns, nil
}
func (self *SNetwork) GetGuestnicsCount() (int, error) {
return GuestnetworkManager.Query().Equals("network_id", self.Id).IsFalse("virtual").CountWithError()
}
@@ -1791,6 +1801,16 @@ func (self *SNetwork) RealDelete(ctx context.Context, userCred mcclient.TokenCre
return errors.Wrapf(err, "reservedIps.Release %s(%d)", reservedIps[i].IpAddr, reservedIps[i].Id)
}
}
gns, err := self.GetGuestnetworks() // delete virtual nics
if err != nil {
return errors.Wrapf(err, "GetGuestnetworks")
}
for i := range gns {
err = gns[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrapf(err, "delete virtual nic %s(%d)", gns[i].Ifname, gns[i].RowId)
}
}
if err := self.SSharableVirtualResourceBase.Delete(ctx, userCred); err != nil {
return err
}

View File

@@ -630,9 +630,9 @@ func (snapshot *SSnapshot) purge(ctx context.Context, userCred mcclient.TokenCre
lockman.LockObject(ctx, snapshot)
defer lockman.ReleaseObject(ctx, snapshot)
err := snapshot.ValidateDeleteCondition(ctx)
err := snapshot.ValidatePurgeCondition(ctx)
if err != nil {
return err
return errors.Wrapf(err, "ValidatePurgeCondition for snapshot %s(%s)", snapshot.Name, snapshot.Id)
}
return snapshot.RealDelete(ctx, userCred)
}

View File

@@ -129,12 +129,13 @@ type IRegionDriver interface {
RequestCacheSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, vpc *SVpc, secgroup *SSecurityGroup, classic bool, removeProjectId string, task taskman.ITask) error
RequestSyncSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, vpcId string, vpc *SVpc, secgroup *SSecurityGroup, removeProjectId, service string) (string, error)
GetSecurityGroupRuleOrder() cloudprovider.TPriorityOrder // Desc(priority值越大,优先级越高) Asc(priority值越小,优先级越高)
GetDefaultSecurityGroupInRule() cloudprovider.SecurityRule
GetDefaultSecurityGroupOutRule() cloudprovider.SecurityRule
GetSecurityGroupRuleMaxPriority() int
GetSecurityGroupRuleMinPriority() int
IsOnlySupportAllowRules() bool
IsPeerSecgroupWithSameProject() bool
IsSupportPeerSecgroup() bool
IsSupportClassicSecurityGroup() bool
IsSecurityGroupBelongVpc() bool
IsVpcBelongGlobalVpc() bool

View File

@@ -155,9 +155,9 @@ func (man *SRouteTableManager) ValidateCreateData(
if err != nil {
return input, errors.Wrap(err, "validateRoutes")
}
_, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
_, err = validators.ValidateModel(userCred, VpcManager, &input.VpcId)
if err != nil {
return input, errors.Wrap(err, "ValidateVpcResourceInput")
return input, err
}
input.StatusInfrasResourceBaseCreateInput, err = man.SStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusInfrasResourceBaseCreateInput)
if err != nil {

View File

@@ -31,6 +31,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/logclient"
@@ -136,7 +137,7 @@ func (sgm *SScalingGroupManager) ValidateCreateData(ctx context.Context, userCre
input.CloudregionId = cloudregion.GetId()
// check vpc
_, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
_, err = validators.ValidateModel(userCred, VpcManager, &input.VpcId)
if err != nil {
return input, err
}

View File

@@ -18,8 +18,6 @@ import (
"context"
"database/sql"
"fmt"
"strconv"
"strings"
"time"
"yunion.io/x/jsonutils"
@@ -205,17 +203,7 @@ func (st *SScalingTimer) TriggerId() string {
var cstSh, _ = time.LoadLocation("Asia/Shanghai")
func (st *SScalingTimer) TriggerDescription() string {
var detail string
switch st.Type {
case api.TIMER_TYPE_ONCE:
detail = st.EndTime.In(cstSh).Format("2006-01-02 15:04:05")
case api.TIMER_TYPE_DAY:
detail = fmt.Sprintf("%d:%d every day", st.Hour, st.Minute)
case api.TIMER_TYPE_WEEK:
detail = st.WeekDaysDesc()
case api.TIMER_TYPE_MONTH:
detail = st.MonthDaysDesc()
}
detail := st.descEnglish()
name := st.ScalingPolicyId
sp, _ := st.ScalingPolicy()
if sp != nil {
@@ -336,11 +324,14 @@ var indicatorMap = map[string]sTableField{
api.INDICATOR_FLOW_OUT: {"vm_netio", "bps_sent"},
}
var alertConfigUsedBy = "scaling_group"
func (sa *SScalingAlarm) generateAlertConfig(sp *SScalingPolicy) (*monitor.AlertConfig, error) {
config, err := monitor.NewAlertConfig(fmt.Sprintf("sp-%s", sp.Id), fmt.Sprintf("%ds", sa.Cycle), true)
if err != nil {
return nil, err
}
config.UsedBy = alertConfigUsedBy
cond := config.Condition("telegraf", indicatorMap[sa.Indicator].Table).Avg()
log.Debugf("alarm: %#v", sa)
@@ -442,61 +433,3 @@ var units = map[string]string{
api.INDICATOR_FLOW_INTO: "KB/s",
api.INDICATOR_FLOW_OUT: "KB/s",
}
var weekDays = []string{"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
func (st *SScalingTimer) WeekDaysDesc() string {
if st.WeekDays == 0 {
return ""
}
var desc strings.Builder
wds := st.GetWeekDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d every %s", st.Hour, st.Minute, weekDays[wds[i]]))
for i++; i < len(wds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(weekDays[wds[i]])
}
if i == len(wds)-1 {
desc.WriteString(" and ")
desc.WriteString(weekDays[wds[i]])
}
return desc.String()
}
func (st *SScalingTimer) MonthDaysDesc() string {
if st.MonthDays == 0 {
return ""
}
var desc strings.Builder
mds := st.GetMonthDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d on the %d%s", st.Hour, st.Minute, mds[i], dateSuffix(mds[i])))
for i++; i < len(mds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(dateSuffix(mds[i]))
}
if i == len(mds)-1 {
desc.WriteString(" and ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(dateSuffix(mds[i]))
}
desc.WriteString(" of each month")
return desc.String()
}
func dateSuffix(date int) string {
var ret string
switch date {
case 1:
ret = "st"
case 2:
ret = "nd"
case 3:
ret = "rd"
default:
ret = "th"
}
return ret
}

View File

@@ -72,7 +72,6 @@ type SScheduledTask struct {
STimer
TimerDesc string `width:"128" charset:"utf8" list:"user" get:"user"`
ResourceType string `width:"32" charset:"ascii" create:"required" list:"user" get:"user"`
Operation string `width:"32" charset:"ascii" create:"required" list:"user" get:"user"`
LabelType string `width:"4" charset:"ascii" create:"required" list:"user" get:"user"`
@@ -139,6 +138,7 @@ func (st *SScheduledTask) getMoreDetails(ctx context.Context, userCred mcclient.
case api.ST_TYPE_CYCLE:
out.CycleTimer = st.STimer.CycleTimerDetails()
}
out.TimerDesc = st.Description(ctx)
// fill label
stLabels, err := st.STLabels()
if err != nil {
@@ -184,36 +184,6 @@ func (stm *SScheduledTaskManager) ValidateCreateData(ctx context.Context, userCr
return input, nil
}
var wdsCN = []string{"", "一", "二", "三", "四", "五", "六", "日"}
var zone = time.FixedZone("GMT", 8*3600)
func (st *SScheduledTask) TimerDescription() string {
format := "2006-01-02 15:04:05"
var prefix string
timer := st.STimer
switch timer.Type {
case api.TIMER_TYPE_ONCE:
return fmt.Sprintf("单次 %s触发", timer.StartTime.In(zone).Format(format))
case api.TIMER_TYPE_DAY:
prefix = "每天"
case api.TIMER_TYPE_WEEK:
wds := timer.GetWeekDays()
weekDays := make([]string, len(wds))
for i := range wds {
weekDays[i] = fmt.Sprintf("星期%s", wdsCN[wds[i]])
}
prefix = fmt.Sprintf("每周 【%s】", strings.Join(weekDays, ""))
case api.TIMER_TYPE_MONTH:
mns := timer.GetMonthDays()
monthDays := make([]string, len(mns))
for i := range mns {
monthDays[i] = fmt.Sprintf("%d号", mns[i])
}
prefix = fmt.Sprintf("每月 【%s】", strings.Join(monthDays, ""))
}
return fmt.Sprintf("%s %02d:%02d触发 有效时间为%s至%s", prefix, timer.Hour, timer.Minute, timer.StartTime.In(zone).Format(format), timer.EndTime.In(zone).Format(format))
}
func (st *SScheduledTask) AllowPerformEnable(ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, input apis.PerformEnableInput) bool {
return true
@@ -288,7 +258,7 @@ func (st *SScheduledTask) PostCreate(ctx context.Context, userCred mcclient.Toke
st.Update(time.Time{})
st.Status = api.ST_STATUS_READY
st.Enabled = tristate.True
st.TimerDesc = st.TimerDescription()
// st.TimerDesc = st.Description(ctx)
err = st.GetModelManager().TableSpec().InsertOrUpdate(ctx, st)
if err != nil {
createFailed("update itself")

View File

@@ -18,6 +18,7 @@ import (
"context"
"database/sql"
"fmt"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -33,6 +34,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rand"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
@@ -330,18 +332,22 @@ func (manager *SSecurityGroupCacheManager) NewCache(ctx context.Context, userCre
return nil, errors.Wrapf(err, "SecurityGroupManager.FetchById(%s)", secgroupId)
}
return manager.newCache(ctx, secgroupId, secgroup.GetName(), vpcId, regionId, providerId, projectId)
}
func (manager *SSecurityGroupCacheManager) newCache(ctx context.Context, secgroupId, secgroupName, vpcId, regionId string, providerId string, projectId string) (*SSecurityGroupCache, error) {
secgroupCache := &SSecurityGroupCache{}
secgroupCache.SecgroupId = secgroupId
secgroupCache.VpcId = vpcId
secgroupCache.ManagerId = providerId
secgroupCache.Status = api.SECGROUP_CACHE_STATUS_CACHING
secgroupCache.CloudregionId = regionId
secgroupCache.Name = secgroup.GetName()
secgroupCache.Name = secgroupName
secgroupCache.ExternalProjectId = projectId
secgroupCache.SetModelManager(manager, secgroupCache)
if err := manager.TableSpec().Insert(ctx, secgroupCache); err != nil {
log.Errorf("insert secgroupcache error: %v", err)
return nil, err
err := manager.TableSpec().Insert(ctx, secgroupCache)
if err != nil {
return nil, errors.Wrapf(err, "Insert")
}
return secgroupCache, nil
}
@@ -382,7 +388,7 @@ func (self *SSecurityGroupCache) GetSecgroup() (*SSecurityGroup, error) {
return model.(*SSecurityGroup), nil
}
func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudSecurityGroup) error {
func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudSecurityGroup) ([]SSecurityGroupRule, error) {
_, err := db.Update(self, func() error {
self.Status = api.SECGROUP_CACHE_STATUS_READY
self.Name = ext.GetName()
@@ -391,28 +397,26 @@ func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context,
return nil
})
if err != nil {
return errors.Wrapf(err, "db.Update")
return nil, errors.Wrapf(err, "db.Update")
}
secgroup, err := self.GetSecgroup()
if err != nil {
return errors.Wrapf(err, "GetSecurity")
return nil, errors.Wrapf(err, "GetSecurity")
}
cacheCount, err := secgroup.GetSecgroupCacheCount()
if err != nil {
return errors.Wrapf(err, "GetSecgroupCacheCount")
return nil, errors.Wrapf(err, "GetSecgroupCacheCount")
}
if cacheCount > 1 {
return nil
return nil, nil
}
info, err := SecurityGroupManager.getRuleInfo(provider, ext)
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(provider.Provider))
dest.Rules, err = ext.GetRules()
if err != nil {
return errors.Wrapf(err, "getRuleInfo")
return nil, errors.Wrapf(err, "GetRules")
}
err = secgroup.SyncSecurityGroupRules(ctx, userCred, info)
if err != nil {
return errors.Wrapf(err, "SyncSecurityGroupRules")
}
return nil
rules, _ := secgroup.SyncSecurityGroupRules(ctx, userCred, dest)
return rules, nil
}
func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, secgroups []cloudprovider.ICloudSecurityGroup, vpc *SVpc) ([]SSecurityGroup, []cloudprovider.ICloudSecurityGroup, compare.SyncResult) {
@@ -474,21 +478,25 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
}
}
rules := []SSecurityGroupRule{}
for i := 0; i < len(commondb); i++ {
err = commondb[i].syncWithCloudSecurityGroup(ctx, userCred, provider, commonext[i])
_rules, err := commondb[i].syncWithCloudSecurityGroup(ctx, userCred, provider, commonext[i])
if err != nil {
syncResult.UpdateError(errors.Wrapf(err, "syncWithCloudSecurityGroup"))
continue
}
rules = append(rules, _rules...)
syncResult.Update()
}
for i := 0; i < len(added); i++ {
secgroup, err := SecurityGroupManager.newFromCloudSecgroup(ctx, userCred, provider, added[i])
secgroup, _rules, err := SecurityGroupManager.newFromCloudSecgroup(ctx, userCred, provider, added[i])
if err != nil {
syncResult.AddError(errors.Wrapf(err, "newFromCloudSecgroup"))
continue
}
rules = append(rules, _rules...)
if secgroup.ProjectId != provider.ProjectId {
_, err = secgroup.PerformPublic(ctx, userCred, nil,
apis.PerformPublicProjectInput{
@@ -521,6 +529,17 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
remoteSecgroups = append(remoteSecgroups, added[i])
syncResult.Add()
}
for i := range rules {
if len(rules[i].PeerSecgroupId) > 0 {
cache, _ := db.FetchByExternalId(SecurityGroupCacheManager, rules[i].PeerSecgroupId)
if cache != nil {
db.Update(&rules[i], func() error {
rules[i].PeerSecgroupId = cache.(*SSecurityGroupCache).SecgroupId
return nil
})
}
}
}
return localSecgroups, remoteSecgroups, syncResult
}
@@ -616,7 +635,7 @@ func (manager *SSecurityGroupCacheManager) ListItemExportKeys(ctx context.Contex
func (self *SSecurityGroupCache) GetISecurityGroup() (cloudprovider.ICloudSecurityGroup, error) {
if len(self.ExternalId) == 0 {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty externalId")
return self.CreateISecurityGroup()
}
manager := self.GetCloudprovider()
@@ -628,5 +647,165 @@ func (self *SSecurityGroupCache) GetISecurityGroup() (cloudprovider.ICloudSecuri
if err != nil {
return nil, errors.Wrapf(err, "GetIRegion")
}
return iRegion.GetISecurityGroupById(self.ExternalId)
iSecgroup, err := iRegion.GetISecurityGroupById(self.ExternalId)
if err != nil {
if errors.Cause(err) != cloudprovider.ErrNotFound {
return nil, errors.Wrap(err, "iRegion.GetSecurityGroupById")
}
return self.CreateISecurityGroup()
}
return iSecgroup, nil
}
func (self *SSecurityGroupCache) CreateISecurityGroup() (cloudprovider.ICloudSecurityGroup, error) {
iRegion, err := self.GetIRegion()
if err != nil {
return nil, errors.Wrapf(err, "self.GetIRegion")
}
if strings.ToLower(self.Name) == "default" { //避免有些云不支持default关键字
self.Name = "DefaultGroup"
}
// 避免有的云不支持重名安全组
randomString := func(prefix string, length int) string {
return fmt.Sprintf("%s-%s", prefix, rand.String(length))
}
opts := &cloudprovider.SecurityGroupFilterOptions{
Name: randomString(self.Name, 1),
VpcId: self.VpcId,
ProjectId: self.ExternalProjectId,
}
for i := 2; i < 30; i++ {
_, err := iRegion.GetISecurityGroupByName(opts)
if err != nil {
if errors.Cause(err) == cloudprovider.ErrNotFound {
break
}
if errors.Cause(err) != cloudprovider.ErrDuplicateId {
return nil, errors.Wrapf(err, "GetISecurityGroupByName")
}
}
opts.Name = randomString(self.Name, i)
}
conf := &cloudprovider.SecurityGroupCreateInput{
Name: opts.Name,
Desc: self.Description,
VpcId: self.VpcId,
ProjectId: self.ExternalProjectId,
}
iSecgroup, err := iRegion.CreateISecurityGroup(conf)
if err != nil {
return nil, errors.Wrapf(err, "iRegion.CreateISecurityGroup")
}
_, err = db.Update(self, func() error {
self.ExternalId = iSecgroup.GetGlobalId()
self.Name = iSecgroup.GetName()
self.Status = api.SECGROUP_CACHE_STATUS_READY
return nil
})
return iSecgroup, nil
}
func (self *SSecurityGroupCache) GetSecuritRuleSet() (cloudprovider.SecurityRuleSet, []SSecurityGroupCache, error) {
ruleSet := cloudprovider.SecurityRuleSet{}
secgroup, err := self.GetSecgroup()
if err != nil {
return ruleSet, nil, errors.Wrapf(err, "GetSecgroup")
}
rules, err := secgroup.getSecurityRules()
if err != nil {
return ruleSet, nil, errors.Wrapf(err, "getSecurityRules")
}
caches := []SSecurityGroupCache{}
driver := GetRegionDriver(self.GetProviderName())
for i := range rules {
if !driver.IsSupportPeerSecgroup() && len(rules[i].PeerSecgroupId) > 0 {
continue
}
//这里没必要拆分为单个单个的端口,到公有云那边适配
rule, err := rules[i].toRule()
if err != nil {
return nil, nil, errors.Wrapf(err, "toRule")
}
peerId := ""
if len(rules[i].PeerSecgroupId) > 0 {
_peerSecgroup, err := SecurityGroupManager.FetchById(rules[i].PeerSecgroupId)
if err != nil {
return nil, nil, errors.Wrapf(err, "SecurityGroupManager.FetchById(%s)", rules[i].PeerSecgroupId)
}
peerSecgroup := _peerSecgroup.(*SSecurityGroup)
peerCaches, err := peerSecgroup.GetSecurityGroupCaches()
if err != nil {
return nil, nil, errors.Wrapf(err, "peerSecgroup.GetSecurityGroupCaches")
}
for _, cache := range peerCaches {
if cache.ManagerId == self.ManagerId && cache.VpcId == self.VpcId && len(cache.ExternalId) > 0 && (!driver.IsPeerSecgroupWithSameProject() || cache.ExternalProjectId == self.ExternalProjectId) {
peerId = cache.ExternalId
break
}
}
if len(peerId) == 0 {
cache, err := SecurityGroupCacheManager.newCache(context.TODO(), peerSecgroup.Id, peerSecgroup.Name, self.VpcId, self.CloudregionId, self.ManagerId, self.ExternalProjectId)
if err != nil {
return nil, nil, errors.Wrapf(err, "SecurityGroupCacheManager.newCache")
}
iSecgroup, err := cache.CreateISecurityGroup()
if err != nil {
return nil, nil, errors.Wrapf(err, "cache.CreateISecurityGroup")
}
peerId = iSecgroup.GetGlobalId()
caches = append(caches, *cache)
}
}
ruleSet = append(ruleSet, cloudprovider.SecurityRule{SecurityRule: *rule, ExternalId: rules[i].Id, PeerSecgroupId: peerId})
}
return ruleSet, caches, nil
}
func (self *SSecurityGroupCache) SyncRules() error {
region := self.GetRegion()
if region == nil {
return fmt.Errorf("failed to get region for secgroupcache %s(%s)", self.Name, self.Id)
}
iSecgroup, err := self.GetISecurityGroup()
if err != nil {
return errors.Wrapf(err, "GetISecurityGroup")
}
rules, err := iSecgroup.GetRules()
if err != nil {
return errors.Wrapf(err, "iSecgroup.GetRules")
}
localRules, caches, err := self.GetSecuritRuleSet()
if err != nil {
return errors.Wrapf(err, "GetSecuritRuleSet")
}
src := cloudprovider.NewSecRuleInfo(GetRegionDriver(api.CLOUD_PROVIDER_ONECLOUD))
src.Rules = localRules
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(region.Provider))
dest.Rules = rules
common, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(src, dest, false)
if len(inAdds) == 0 && len(inDels) == 0 && len(outAdds) == 0 && len(outDels) == 0 {
return nil
}
err = iSecgroup.SyncRules(common, inAdds, outAdds, inDels, outDels)
if err != nil {
return errors.Wrapf(err, "iSecgroup.SyncRules")
}
for i := range caches {
err = caches[i].SyncRules()
if err != nil {
return errors.Wrapf(err, "SyncRules for caches %s(%s)", caches[i].Name, caches[i].Id)
}
}
return nil
}

View File

@@ -17,7 +17,6 @@ package models
import (
"context"
"net"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -27,7 +26,6 @@ import (
"yunion.io/x/pkg/util/stringutils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -63,40 +61,21 @@ type SSecurityGroupRule struct {
db.SResourceBase
SSecurityGroupResourceBase `create:"required"`
Id string `width:"128" charset:"ascii" primary:"true" list:"user"`
Priority int64 `default:"1" list:"user" update:"user" list:"user"`
Protocol string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
Ports string `width:"256" charset:"ascii" list:"user" update:"user" create:"optional"`
Direction string `width:"3" charset:"ascii" list:"user" create:"required"`
CIDR string `width:"256" charset:"ascii" list:"user" update:"user" create:"required"`
Action string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
Description string `width:"256" charset:"utf8" list:"user" update:"user" create:"optional"`
// SecgroupID string `width:"128" charset:"ascii" create:"required"`
Id string `width:"128" charset:"ascii" primary:"true" list:"user"`
Priority int64 `default:"1" list:"user" update:"user" list:"user"`
Protocol string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
Ports string `width:"256" charset:"ascii" list:"user" update:"user" create:"optional"`
Direction string `width:"3" charset:"ascii" list:"user" create:"required"`
CIDR string `width:"256" charset:"ascii" list:"user" update:"user" create:"optional"`
Action string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
Description string `width:"256" charset:"utf8" list:"user" update:"user" create:"optional"`
PeerSecgroupId string `width:"128" charset:"ascii" create:"optional" list:"user" update:"user"`
}
func (self *SSecurityGroupRule) GetId() string {
return self.Id
}
type SecurityGroupRuleSet []SSecurityGroupRule
func (v SecurityGroupRuleSet) Len() int {
return len(v)
}
func (v SecurityGroupRuleSet) Swap(i, j int) {
v[i], v[j] = v[j], v[i]
}
func (v SecurityGroupRuleSet) Less(i, j int) bool {
if v[i].Priority < v[j].Priority {
return true
} else if v[i].Priority == v[j].Priority {
return strings.Compare(v[i].String(), v[j].String()) <= 0
}
return false
}
func (manager *SSecurityGroupRuleManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
secgroupId, _ := data.GetString("secgroup_id")
return jsonutils.Marshal(map[string]string{"secgroup_id": secgroupId})
@@ -150,13 +129,6 @@ func (self *SSecurityGroupRule) AllowDeleteItem(ctx context.Context, userCred mc
return false
}
/*func (self *SSecurityGroupRule) GetSecGroup() *SSecurityGroup {
if secgroup, _ := SecurityGroupManager.FetchById(self.SecgroupI); secgroup != nil {
return secgroup.(*SSecurityGroup)
}
return nil
}*/
func (manager *SSecurityGroupRuleManager) FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
return q.Equals("id", idStr)
}
@@ -226,6 +198,7 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
bRows := manager.SResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
secRows := manager.SSecurityGroupResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
secIds := make([]string, len(objs))
peerIds := make([]string, len(objs))
for i := range rows {
rows[i] = api.SecgroupRuleDetails{
ResourceBaseDetails: bRows[i],
@@ -233,6 +206,7 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
}
rule := objs[i].(*SSecurityGroupRule)
secIds[i] = rule.SecgroupId
peerIds[i] = rule.PeerSecgroupId
}
secgroups := make(map[string]SSecurityGroup)
@@ -242,6 +216,12 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
return rows
}
peerMaps, err := db.FetchIdNameMap2(SecurityGroupManager, peerIds)
if err != nil {
log.Errorf("db.FetchIdNameMap2 fail: %v", err)
return rows
}
virObjs := make([]interface{}, len(objs))
for i := range rows {
if secgroup, ok := secgroups[secIds[i]]; ok {
@@ -253,6 +233,7 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
projRows := SecurityGroupManager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, virObjs, fields, isList)
for i := range rows {
rows[i].ProjectizedResourceInfo = projRows[i]
rows[i].PeerSecgroup, _ = peerMaps[peerIds[i]]
}
return rows
@@ -304,30 +285,32 @@ func (self *SSecurityGroupRule) BeforeInsert() {
}
func (manager *SSecurityGroupRuleManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SSecgroupRuleCreateInput) (api.SSecgroupRuleCreateInput, error) {
data := jsonutils.Marshal(input).(*jsonutils.JSONDict)
if input.Priority == nil {
return input, httperrors.NewMissingParameterError("priority")
}
if *input.Priority < 1 || *input.Priority > 100 {
return input, httperrors.NewOutOfRangeError("Invalid priority %d, must be in range or 1 ~ 100", input.Priority)
}
priorityV := validators.NewRangeValidator("priority", 1, 100)
priorityV.Optional(true)
err := priorityV.Validate(data)
_secgroup, err := validators.ValidateModel(userCred, SecurityGroupManager, &input.SecgroupId)
if err != nil {
return input, err
}
secgroupV := validators.NewModelIdOrNameValidator("secgroup", "secgroup", ownerId)
err = secgroupV.Validate(data)
if err != nil {
return input, err
}
secgroup := secgroupV.Model.(*SSecurityGroup)
secgroup := _secgroup.(*SSecurityGroup)
if !secgroup.IsOwner(userCred) && !userCred.HasSystemAdminPrivilege() {
return input, httperrors.NewForbiddenError("not enough privilege")
}
err = data.Unmarshal(&input)
if err != nil {
return input, httperrors.NewInputParameterError("Failed to unmarshal input: %v", err)
if len(input.PeerSecgroupId) > 0 {
_, err = validators.ValidateModel(userCred, SecurityGroupManager, &input.PeerSecgroupId)
if err != nil {
return input, err
}
if input.PeerSecgroupId == input.SecgroupId {
return input, httperrors.NewInputParameterError("peer_secgroup_id can not point to secgroup self")
}
}
err = input.Check()
@@ -342,48 +325,47 @@ func (manager *SSecurityGroupRuleManager) ValidateCreateData(ctx context.Context
return input, nil
}
func (self *SSecurityGroupRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
priorityV := validators.NewRangeValidator("priority", 1, 100)
priorityV.Optional(true)
err := priorityV.Validate(data)
func (self *SSecurityGroupRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SSecgroupRuleUpdateInput) (api.SSecgroupRuleUpdateInput, error) {
priority := int(self.Priority)
output := api.SSecgroupRuleUpdateInput{
SSecgroupRuleResource: api.SSecgroupRuleResource{
Priority: &priority,
Protocol: self.Protocol,
Ports: self.Ports,
Direction: self.Direction,
CIDR: self.CIDR,
Action: self.Action,
Description: self.Description,
PeerSecgroupId: self.PeerSecgroupId,
},
}
jsonutils.Update(&output, input)
if *output.Priority < 1 || *output.Priority > 100 {
return output, httperrors.NewOutOfRangeError("Invalid priority %d, must be in range or 1 ~ 100", input.Priority)
}
if len(input.PeerSecgroupId) > 0 {
_, err := validators.ValidateModel(userCred, SecurityGroupManager, &input.PeerSecgroupId)
if err != nil {
return output, err
}
if input.PeerSecgroupId == self.Id {
return output, httperrors.NewInputParameterError("peer_secgroup_id can not point to secgroup self")
}
}
err := output.Check()
if err != nil {
return nil, err
return output, err
}
input := &api.SSecgroupRuleCreateInput{
Direction: self.Direction,
Action: self.Action,
CIDR: self.CIDR,
Protocol: self.Protocol,
Ports: self.Ports,
Priority: int(self.Priority),
}
err = jsonutils.Update(input, data)
output.ResourceBaseUpdateInput, err = self.SResourceBase.ValidateUpdateData(ctx, userCred, query, input.ResourceBaseUpdateInput)
if err != nil {
return nil, err
return output, errors.Wrap(err, "SResourceBase.ValidateUpdateData")
}
err = input.Check()
if err != nil {
return nil, err
}
// 更新操作日志: 对比可以知道改了原有规则哪些内容
data.Add(jsonutils.Marshal(self), "origin")
rinput := apis.ResourceBaseUpdateInput{}
err = data.Unmarshal(&rinput)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
rinput, err = self.SResourceBase.ValidateUpdateData(ctx, userCred, query, rinput)
if err != nil {
return nil, errors.Wrap(err, "SResourceBase.ValidateUpdateData")
}
data.Update(jsonutils.Marshal(rinput))
return data, nil
return output, nil
}
func (self *SSecurityGroupRule) String() string {
@@ -427,6 +409,13 @@ func (self *SSecurityGroupRule) toRule() (*secrules.SecurityRule, error) {
func (self *SSecurityGroupRule) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
if len(self.PeerSecgroupId) > 0 {
db.Update(self, func() error {
self.CIDR = ""
return nil
})
}
log.Debugf("POST Create %s", data)
if secgroup := self.GetSecGroup(); secgroup != nil {
logclient.AddSimpleActionLog(secgroup, logclient.ACT_ALLOCATE, data, userCred, true)
@@ -446,6 +435,13 @@ func (self *SSecurityGroupRule) PreDelete(ctx context.Context, userCred mcclient
func (self *SSecurityGroupRule) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SResourceBase.PostUpdate(ctx, userCred, query, data)
if len(self.PeerSecgroupId) > 0 {
db.Update(self, func() error {
self.CIDR = ""
return nil
})
}
log.Debugf("POST Update %s", data)
if secgroup := self.GetSecGroup(); secgroup != nil {
logclient.AddSimpleActionLog(secgroup, logclient.ACT_UPDATE, data, userCred, true)
@@ -462,27 +458,12 @@ func (manager *SSecurityGroupRuleManager) getRulesBySecurityGroup(secgroup *SSec
return rules, nil
}
func (self *SSecurityGroup) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, rules cloudprovider.SecurityRuleSet) error {
priority, prePriority := 10, 0
for i := 0; i < len(rules); i++ {
// 这里避免了Rule规则优先级在 1-100之外的问题,ext.GetRules()不需要进行优先级转换
if prePriority != 0 && rules[i].Priority != prePriority && priority < 100 {
priority++
}
prePriority = rules[i].Priority
rules[i].Priority = priority
_, err := self.newFromCloudSecurityGroupRule(ctx, userCred, rules[i])
if err != nil {
return errors.Wrapf(err, "newFromCloudSecurityGroupRule")
}
}
return nil
}
func (self *SSecurityGroup) newFromCloudSecurityGroupRule(ctx context.Context, userCred mcclient.TokenCredential, rule cloudprovider.SecurityRule) (*SSecurityGroupRule, error) {
func (self *SSecurityGroup) newFromCloudSecurityGroupRule(ctx context.Context, userCred mcclient.TokenCredential, rule cloudprovider.SecurityRule) (*SSecurityGroupRule, bool, error) {
lockman.LockObject(ctx, self)
defer lockman.ReleaseObject(ctx, self)
isNeedFix := false
protocol := rule.Protocol
if len(protocol) == 0 {
protocol = secrules.PROTO_ANY
@@ -493,23 +474,38 @@ func (self *SSecurityGroup) newFromCloudSecurityGroupRule(ctx context.Context, u
cidr = rule.IPNet.String()
}
if len(rule.PeerSecgroupId) > 0 {
cidr = ""
cache, _ := db.FetchByExternalId(SecurityGroupCacheManager, rule.PeerSecgroupId)
if cache != nil {
rule.PeerSecgroupId = cache.(*SSecurityGroupCache).SecgroupId
}
isNeedFix = true
}
err := rule.ValidateRule()
if err != nil {
return nil, isNeedFix, errors.Wrapf(err, "ValidateRule %s ", jsonutils.Marshal(rule).String())
}
secrule := &SSecurityGroupRule{
Priority: int64(rule.Priority),
Protocol: protocol,
Ports: rule.GetPortsString(),
Direction: string(rule.Direction),
CIDR: cidr,
Action: string(rule.Action),
Description: rule.Description,
Priority: int64(rule.Priority),
Protocol: protocol,
Ports: rule.GetPortsString(),
Direction: string(rule.Direction),
CIDR: cidr,
Action: string(rule.Action),
Description: rule.Description,
PeerSecgroupId: rule.PeerSecgroupId,
}
secrule.SetModelManager(SecurityGroupRuleManager, secrule)
secrule.SecgroupId = self.Id
err := SecurityGroupRuleManager.TableSpec().Insert(ctx, secrule)
err = SecurityGroupRuleManager.TableSpec().Insert(ctx, secrule)
if err != nil {
return nil, errors.Wrapf(err, "SecurityGroupRuleManager.Insert")
return nil, isNeedFix, errors.Wrapf(err, "SecurityGroupRuleManager.Insert")
}
return secrule, nil
return secrule, isNeedFix, nil
}
func (self *SSecurityGroupRule) GetOwnerId() mcclient.IIdentityProvider {

View File

@@ -23,6 +23,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/utils"
@@ -95,8 +96,10 @@ func (manager *SSecurityGroupManager) ListItemFilter(
return nil, httperrors.NewInputParameterError("Failed fetching secgroup %s", input.Equals)
}
secgroup := _secgroup.(*SSecurityGroup)
inAllowList := secgroup.GetInAllowList()
outAllowList := secgroup.GetOutAllowList()
inAllowList, outAllowList, err := secgroup.GetAllowList()
if err != nil {
return q, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
}
sq := manager.Query().NotEquals("id", secgroup.Id)
secgroups := []SSecurityGroup{}
err = db.FetchModelObjects(manager, sq, &secgroups)
@@ -105,12 +108,11 @@ func (manager *SSecurityGroupManager) ListItemFilter(
}
secgroupIds := []string{}
for i := 0; i < len(secgroups); i++ {
_inAllowList := secgroups[i].GetInAllowList()
if !inAllowList.Equals(_inAllowList) {
continue
_inAllowList, _outAllowList, err := secgroups[i].GetAllowList()
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
}
_outAllowList := secgroups[i].GetOutAllowList()
if !outAllowList.Equals(_outAllowList) {
if !inAllowList.Equals(_inAllowList) || !outAllowList.Equals(_outAllowList) {
continue
}
secgroupIds = append(secgroupIds, secgroups[i].Id)
@@ -515,7 +517,7 @@ func (self *SSecurityGroup) PostCreate(ctx context.Context, userCred mcclient.To
for _, r := range input.Rules {
rule := &SSecurityGroupRule{
Priority: int64(r.Priority),
Priority: int64(*r.Priority),
Protocol: r.Protocol,
Ports: r.Ports,
Direction: r.Direction,
@@ -539,40 +541,61 @@ func (manager *SSecurityGroupManager) FetchSecgroupById(secId string) *SSecurity
return nil
}
func (self *SSecurityGroup) getSecurityRules(direction string) (rules []SSecurityGroupRule) {
func (self *SSecurityGroup) getSecurityRules() ([]SSecurityGroupRule, error) {
secgrouprules := SecurityGroupRuleManager.Query().SubQuery()
sql := secgrouprules.Query().Filter(sqlchemy.Equals(secgrouprules.Field("secgroup_id"), self.Id)).Desc("priority")
if len(direction) > 0 && utils.IsInStringArray(direction, []string{"in", "out"}) {
sql = sql.Equals("direction", direction)
rules := []SSecurityGroupRule{}
err := db.FetchModelObjects(SecurityGroupRuleManager, sql, &rules)
if err != nil {
return nil, errors.Wrapf(err, "db.FetchModelObjects")
}
if err := db.FetchModelObjects(SecurityGroupRuleManager, sql, &rules); err != nil {
log.Errorf("GetGuests fail %s", err)
return
}
return
return rules, nil
}
func (self *SSecurityGroup) GetSecRules(direction string) []secrules.SecurityRule {
func (self *SSecurityGroup) GetSecuritRuleSet() (cloudprovider.SecurityRuleSet, error) {
ruleSet := cloudprovider.SecurityRuleSet{}
rules, err := self.getSecurityRules()
if err != nil {
return ruleSet, errors.Wrapf(err, "getSecurityRules")
}
for i := range rules {
//这里没必要拆分为单个单个的端口,到公有云那边适配
rule, err := rules[i].toRule()
if err != nil {
return nil, errors.Wrapf(err, "toRule")
}
ruleSet = append(ruleSet, cloudprovider.SecurityRule{SecurityRule: *rule, ExternalId: rules[i].Id})
}
return ruleSet, nil
}
func (self *SSecurityGroup) GetSecRules() ([]secrules.SecurityRule, error) {
rules := make([]secrules.SecurityRule, 0)
for _, _rule := range self.getSecurityRules(direction) {
_rules, err := self.getSecurityRules()
if err != nil {
return nil, errors.Wrapf(err, "getSecurityRules()")
}
for _, _rule := range _rules {
//这里没必要拆分为单个单个的端口,到公有云那边适配
rule, err := _rule.toRule()
if err != nil {
log.Errorln(err)
continue
return nil, errors.Wrapf(err, "toRule")
}
rules = append(rules, *rule)
}
return rules
return rules, nil
}
func (self *SSecurityGroup) getSecurityRuleString(direction string) string {
secgrouprules := self.getSecurityRules(direction)
func (self *SSecurityGroup) getSecurityRuleString() (string, error) {
secgrouprules, err := self.getSecurityRules()
if err != nil {
return "", errors.Wrapf(err, "getSecurityRules()")
}
var rules []string
for _, rule := range secgrouprules {
rules = append(rules, rule.String())
}
return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
return strings.Join(rules, SECURITY_GROUP_SEPARATOR), nil
}
func totalSecurityGroupCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) (int, error) {
@@ -735,7 +758,10 @@ func (self *SSecurityGroup) PerformClone(ctx context.Context, userCred mcclient.
return input, httperrors.NewGeneralError(errors.Wrapf(err, "Insert"))
}
secgrouprules := self.getSecurityRules("")
secgrouprules, err := self.getSecurityRules()
if err != nil {
return input, httperrors.NewGeneralError(errors.Wrapf(err, "getSecurityRules"))
}
for _, rule := range secgrouprules {
secgrouprule := &SSecurityGroupRule{}
secgrouprule.SetModelManager(SecurityGroupRuleManager, secgrouprule)
@@ -772,8 +798,10 @@ func (self *SSecurityGroup) PerformMerge(ctx context.Context, userCred mcclient.
if len(input.SecgroupIds) == 0 {
return nil, httperrors.NewMissingParameterError("secgroup_ids")
}
inAllowList := self.GetInAllowList()
outAllowList := self.GetOutAllowList()
inAllowList, outAllowList, err := self.GetAllowList()
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
}
secgroups := []*SSecurityGroup{}
for _, secgroupId := range input.SecgroupIds {
_secgroup, err := SecurityGroupManager.FetchByIdOrName(userCred, secgroupId)
@@ -785,11 +813,13 @@ func (self *SSecurityGroup) PerformMerge(ctx context.Context, userCred mcclient.
}
secgroup := _secgroup.(*SSecurityGroup)
secgroup.SetModelManager(SecurityGroupManager, secgroup)
_inAllowList := secgroup.GetInAllowList()
_inAllowList, _outAllowList, err := secgroup.GetAllowList()
if err != nil {
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
}
if !inAllowList.Equals(_inAllowList) {
return nil, httperrors.NewUnsupportOperationError("secgroup %s rules not equals %s rules", secgroup.Name, self.Name)
}
_outAllowList := secgroup.GetOutAllowList()
if !outAllowList.Equals(_outAllowList) {
return nil, httperrors.NewUnsupportOperationError("secgroup %s rules not equals %s rules", secgroup.Name, self.Name)
}
@@ -813,27 +843,20 @@ func (self *SSecurityGroup) PerformMerge(ctx context.Context, userCred mcclient.
return nil, nil
}
func (self *SSecurityGroup) GetOutAllowList() secrules.SecurityRuleSet {
rules := self.GetSecRules("out")
ruleSet := secrules.SecurityRuleSet(rules)
rules = append(rules, *secrules.MustParseSecurityRule("out:allow any"))
return ruleSet.AllowList()
}
func (self *SSecurityGroup) GetInAllowList() secrules.SecurityRuleSet {
rules := self.GetSecRules("in")
rules = append(rules, *secrules.MustParseSecurityRule("in:deny any"))
ruleSet := secrules.SecurityRuleSet(rules)
return ruleSet.AllowList()
}
func (self *SSecurityGroup) getSecurityGroupRuleSet() secrules.SecurityGroupRuleSet {
rules := self.GetSecRules("")
srs := secrules.SecurityGroupRuleSet{}
for i := 0; i < len(rules); i++ {
srs.AddRule(rules[i])
func (self *SSecurityGroup) GetAllowList() (secrules.SecurityRuleSet, secrules.SecurityRuleSet, error) {
in, out := secrules.SecurityRuleSet{*secrules.MustParseSecurityRule("in:deny any")}, secrules.SecurityRuleSet{*secrules.MustParseSecurityRule("out:allow any")}
rules, err := self.GetSecRules()
if err != nil {
return in, out, errors.Wrapf(err, "GetSecRules")
}
return srs
for i := range rules {
if rules[i].Direction == secrules.DIR_IN {
in = append(in, rules[i])
} else {
in = append(in, rules[i])
}
}
return in.AllowList(), out.AllowList(), nil
}
func (self *SSecurityGroup) mergeSecurityGroupCache(secgroup *SSecurityGroup) error {
@@ -892,94 +915,81 @@ func (manager *SSecurityGroupManager) getSecurityGroups() ([]SSecurityGroup, err
}
}
func (self *SSecurityGroup) cleanRules(ctx context.Context, userCred mcclient.TokenCredential) error {
func (self *SSecurityGroup) removeRules(ruleIds []string, result *compare.SyncResult) {
if len(ruleIds) == 0 {
return
}
rules := []SSecurityGroupRule{}
q := SecurityGroupRuleManager.Query().Equals("secgroup_id", self.Id)
q := SecurityGroupRuleManager.Query().In("id", ruleIds)
err := db.FetchModelObjects(SecurityGroupRuleManager, q, &rules)
if err != nil {
return errors.Wrapf(err, "db.FetchModelObjects")
result.DeleteError(errors.Wrapf(err, "db.FetchModelObjects"))
return
}
for i := range rules {
err = rules[i].Delete(ctx, userCred)
err = rules[i].Delete(context.TODO(), nil)
if err != nil {
return errors.Wrapf(err, "DeleteRule(%s)", rules[i].Id)
result.DeleteError(errors.Wrapf(err, "delte rule %s", rules[i].Id))
continue
}
result.Delete()
}
}
func (self *SSecurityGroup) SyncSecurityGroupRules(ctx context.Context, userCred mcclient.TokenCredential, src cloudprovider.SecRuleInfo) ([]SSecurityGroupRule, compare.SyncResult) {
result := compare.SyncResult{}
localRules, err := self.GetSecuritRuleSet()
if err != nil {
result.Error(errors.Wrapf(err, "GetSecuritRuleSet"))
return nil, result
}
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(api.CLOUD_PROVIDER_ONECLOUD))
dest.Rules = localRules
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(src, dest, false)
if len(inAdds)+len(inDels)+len(outAdds)+len(outDels) == 0 {
return nil, result
}
ruleIds := []string{}
for _, dels := range [][]cloudprovider.SecurityRule{inDels, outDels} {
for i := range dels {
if len(dels[i].ExternalId) > 0 {
ruleIds = append(ruleIds, dels[i].ExternalId)
}
}
}
return nil
}
func (self *SSecurityGroup) SyncSecurityGroupRules(ctx context.Context, userCred mcclient.TokenCredential, info *sRuleInfo) error {
inRules := cloudprovider.AddDefaultRule(info.inRules, info.defaultInRule, "in:deny any", info.order, info.minPriority, info.maxPriority, info.onlyAllowRules)
cloudprovider.SortSecurityRule(inRules, info.order, info.onlyAllowRules)
outRules := cloudprovider.AddDefaultRule(info.outRules, info.defaultOutRule, "out:allow any", info.order, info.minPriority, info.maxPriority, info.onlyAllowRules)
cloudprovider.SortSecurityRule(outRules, info.order, info.onlyAllowRules)
self.removeRules(ruleIds, &result)
err := self.cleanRules(ctx, userCred)
if err != nil {
return errors.Wrapf(err, "cleanRules")
}
err = self.SyncRules(ctx, userCred, inRules)
if err != nil {
return errors.Wrapf(err, "SyncInRules")
}
err = self.SyncRules(ctx, userCred, outRules)
if err != nil {
return errors.Wrapf(err, "SyncOutRules")
}
return nil
}
type sRuleInfo struct {
rules []cloudprovider.SecurityRule
inRules []cloudprovider.SecurityRule
outRules []cloudprovider.SecurityRule
defaultInRule cloudprovider.SecurityRule
defaultOutRule cloudprovider.SecurityRule
order cloudprovider.TPriorityOrder
onlyAllowRules bool
maxPriority int
minPriority int
}
func (manager *SSecurityGroupManager) getRuleInfo(provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*sRuleInfo, error) {
regionDriver, err := provider.GetRegionDriver()
if err != nil {
return nil, errors.Wrap(err, "provider.GetRegionDriver")
}
rules, err := extSec.GetRules()
if err != nil {
return nil, errors.Wrap(err, "extSec.GetRules")
}
info := &sRuleInfo{
rules: rules,
inRules: []cloudprovider.SecurityRule{},
outRules: []cloudprovider.SecurityRule{},
defaultInRule: regionDriver.GetDefaultSecurityGroupInRule(),
defaultOutRule: regionDriver.GetDefaultSecurityGroupOutRule(),
order: regionDriver.GetSecurityGroupRuleOrder(),
onlyAllowRules: regionDriver.IsOnlySupportAllowRules(),
maxPriority: regionDriver.GetSecurityGroupRuleMaxPriority(),
minPriority: regionDriver.GetSecurityGroupRuleMinPriority(),
}
for i := range rules {
if rules[i].Direction == secrules.DIR_IN {
info.inRules = append(info.inRules, rules[i])
} else {
info.outRules = append(info.outRules, rules[i])
rules := []SSecurityGroupRule{}
for _, adds := range [][]cloudprovider.SecurityRule{inAdds, outAdds} {
for i := range adds {
rule, isNeedFix, err := self.newFromCloudSecurityGroupRule(ctx, userCred, adds[i])
if err != nil {
result.AddError(errors.Wrapf(err, "newFromCloudSecurityGroupRule"))
continue
}
if isNeedFix && rule != nil {
rules = append(rules, *rule)
}
result.Add()
}
}
return info, nil
log.Infof("Sync Rules for Secgroup %s(%s) result: %s", self.Name, self.Id, result.Result())
return rules, result
}
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, error) {
info, err := manager.getRuleInfo(provider, extSec)
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, []SSecurityGroupRule, error) {
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(provider.Provider))
var err error
dest.Rules, err = extSec.GetRules()
if err != nil {
return nil, errors.Wrapf(err, "getRuleInfo")
return nil, nil, errors.Wrapf(err, "extSec.GetRules")
}
src := cloudprovider.NewSecRuleInfo(GetRegionDriver(api.CLOUD_PROVIDER_ONECLOUD))
if options.Options.EnableAutoMergeSecurityGroup {
// 查询与provider在同域的安全组比对寻找一个与云上安全组规则相同的安全组
@@ -987,13 +997,17 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
q := manager.Query().Equals("domain_id", provider.DomainId)
err = db.FetchModelObjects(manager, q, &secgroups)
if err != nil {
return nil, errors.Wrap(err, "db.FetchModelObjects")
return nil, nil, errors.Wrap(err, "db.FetchModelObjects")
}
for i := range secgroups {
localRules := secrules.SecurityRuleSet(secgroups[i].GetSecRules(""))
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(info.minPriority, info.maxPriority, info.order, localRules, info.rules, info.defaultInRule, info.defaultOutRule, info.onlyAllowRules, false)
src.Rules, err = secgroups[i].GetSecuritRuleSet()
if err != nil {
log.Warningf("GetSecuritRuleSet %s(%s) error: %v", secgroups[i].Name, secgroups[i].Id, err)
continue
}
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(src, dest, false)
if len(inAdds) == 0 && len(outAdds) == 0 && len(inDels) == 0 && len(outDels) == 0 {
return &secgroups[i], nil
return &secgroups[i], nil, nil
}
}
}
@@ -1005,7 +1019,7 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
secgroup.SetModelManager(manager, &secgroup)
secgroup.Name, err = db.GenerateName(manager, userCred, extSec.GetName())
if err != nil {
return nil, err
return nil, nil, err
}
secgroup.Status = api.SECGROUP_STATUS_READY
@@ -1015,16 +1029,13 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
err = manager.TableSpec().Insert(ctx, &secgroup)
if err != nil {
return nil, errors.Wrapf(err, "Insert")
return nil, nil, errors.Wrapf(err, "Insert")
}
err = secgroup.SyncSecurityGroupRules(ctx, userCred, info)
if err != nil {
return nil, errors.Wrapf(err, "SyncSecurityGroupRules")
}
rules, _ := secgroup.SyncSecurityGroupRules(ctx, userCred, dest)
db.OpsLog.LogEvent(&secgroup, db.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred)
return &secgroup, nil
return &secgroup, rules, nil
}
func (manager *SSecurityGroupManager) DelaySync(ctx context.Context, userCred mcclient.TokenCredential, idStr string) {
@@ -1223,6 +1234,9 @@ func (self *SSecurityGroup) AllowPerformImportRules(ctx context.Context, userCre
func (self *SSecurityGroup) PerformImportRules(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SecgroupImportRulesInput) (jsonutils.JSONObject, error) {
for i := range input.Rules {
if input.Rules[i].Priority == nil {
return nil, httperrors.NewMissingParameterError("priority")
}
err := input.Rules[i].Check()
if err != nil {
return nil, httperrors.NewInputParameterError("rule %d is invalid: %s", i+1, err)
@@ -1230,7 +1244,7 @@ func (self *SSecurityGroup) PerformImportRules(ctx context.Context, userCred mcc
}
for _, r := range input.Rules {
rule := &SSecurityGroupRule{
Priority: int64(r.Priority),
Priority: int64(*r.Priority),
Protocol: r.Protocol,
Ports: r.Ports,
Direction: r.Direction,

View File

@@ -88,8 +88,9 @@ type SServerSku struct {
PrepaidStatus string `width:"32" charset:"utf8" nullable:"true" list:"user" create:"admin_optional" default:"available"` // 预付费资源状态 available|soldout
PostpaidStatus string `width:"32" charset:"utf8" nullable:"true" list:"user" create:"admin_optional" default:"available"` // 按需付费资源状态 available|soldout
CpuCoreCount int `nullable:"false" list:"user" create:"admin_required"`
MemorySizeMB int `nullable:"false" list:"user" create:"admin_required"`
CpuArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"admin"` // CPU 架构 x86|xarm
CpuCoreCount int `nullable:"false" list:"user" create:"admin_required"`
MemorySizeMB int `nullable:"false" list:"user" create:"admin_required"`
OsName string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"admin" default:"Any"` // Windows|Linux|Any
@@ -834,7 +835,7 @@ func (manager *SServerSkuManager) ListItemFilter(
conditions = append(
conditions,
sqlchemy.AND(
sqlchemy.GE(q.Field("memory_size_mb"), s),
sqlchemy.GT(q.Field("memory_size_mb"), s),
sqlchemy.LE(q.Field("memory_size_mb"), e),
),
)
@@ -1171,6 +1172,7 @@ func (self *SServerSku) syncWithCloudSku(ctx context.Context, userCred mcclient.
self.InstanceTypeCategory = extSku.InstanceTypeCategory
self.PrepaidStatus = extSku.PrepaidStatus
self.PostpaidStatus = extSku.PostpaidStatus
self.CpuArch = extSku.CpuArch
self.SysDiskType = extSku.SysDiskType
self.DataDiskTypes = extSku.DataDiskTypes
return nil

View File

@@ -621,6 +621,10 @@ func (self *SSnapshot) ValidateDeleteCondition(ctx context.Context) error {
if self.Status == api.SNAPSHOT_DELETING {
return httperrors.NewBadRequestError("Cannot delete snapshot in status %s", self.Status)
}
return self.ValidatePurgeCondition(ctx)
}
func (self *SSnapshot) ValidatePurgeCondition(ctx context.Context) error {
count, err := InstanceSnapshotJointManager.Query().Equals("snapshot_id", self.Id).CountWithError()
if err != nil {
return httperrors.NewInternalServerError("Fetch instance snapshot error %s", err)

View File

@@ -28,10 +28,9 @@ import (
)
var (
syncSecgroupWorker *appsrv.SWorkerManager
syncAccountWorker *appsrv.SWorkerManager
syncWorkers []*appsrv.SWorkerManager
syncWorkerRing *hashring.HashRing
syncAccountWorker *appsrv.SWorkerManager
syncWorkers []*appsrv.SWorkerManager
syncWorkerRing *hashring.HashRing
)
func InitSyncWorkers(count int) {
@@ -53,12 +52,6 @@ func InitSyncWorkers(count int) {
2048,
true,
)
syncSecgroupWorker = appsrv.NewWorkerManager(
"syncSecgroupProbeWorkerManager",
1,
2048,
true,
)
}
func RunSyncCloudproviderRegionTask(ctx context.Context, key string, syncFunc func()) {
@@ -75,9 +68,3 @@ func RunSyncCloudAccountTask(ctx context.Context, probeFunc func()) {
panicutils.SendPanicMessage(ctx, err)
})
}
func RunSyncSecgroupTask(ctx context.Context, syncFunc func()) {
syncSecgroupWorker.Run(syncFunc, nil, func(err error) {
panicutils.SendPanicMessage(ctx, err)
})
}

View File

@@ -15,13 +15,17 @@
package models
import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"time"
"yunion.io/x/log"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/i18n"
"yunion.io/x/onecloud/pkg/util/bitmap"
)
@@ -159,6 +163,134 @@ func checkTimerCreateInput(in api.TimerCreateInput) (api.TimerCreateInput, error
return in, nil
}
var (
timerDescTable = i18n.Table{}
TIMERLANG = "timerLang"
)
func init() {
timerDescTable.Set("timerLang", i18n.NewTableEntry().EN("en").CN("cn"))
}
func (st *STimer) Description(ctx context.Context) string {
lang := timerDescTable.Lookup(ctx, TIMERLANG)
switch lang {
case "en":
return st.descEnglish()
case "cn":
return st.descChinese()
}
return ""
}
var (
wdsCN = []string{"", "一", "二", "三", "四", "五", "六", "日"}
wdsEN = []string{"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
zone = time.Now().Local().Location()
//zone = time.FixedZone("GMT", 8*3600)
)
func (st *STimer) descChinese() string {
format := "2006-01-02 15:04:05"
var prefix string
switch st.Type {
case api.TIMER_TYPE_ONCE:
return fmt.Sprintf("单次 %s触发", st.StartTime.In(zone).Format(format))
case api.TIMER_TYPE_DAY:
prefix = "每天"
case api.TIMER_TYPE_WEEK:
wds := st.GetWeekDays()
weekDays := make([]string, len(wds))
for i := range wds {
weekDays[i] = fmt.Sprintf("星期%s", wdsCN[wds[i]])
}
prefix = fmt.Sprintf("每周 【%s】", strings.Join(weekDays, ""))
case api.TIMER_TYPE_MONTH:
mns := st.GetMonthDays()
monthDays := make([]string, len(mns))
for i := range mns {
monthDays[i] = fmt.Sprintf("%d号", mns[i])
}
prefix = fmt.Sprintf("每月 【%s】", strings.Join(monthDays, ""))
}
return fmt.Sprintf("%s %02d:%02d触发 有效时间为%s至%s", prefix, st.Hour, st.Minute, st.StartTime.In(zone).Format(format), st.EndTime.In(zone).Format(format))
}
func (st *STimer) descEnglish() string {
var detail string
format := "2006-01-02 15:04:05"
switch st.Type {
case api.TIMER_TYPE_ONCE:
return st.EndTime.In(zone).Format(format)
case api.TIMER_TYPE_DAY:
detail = fmt.Sprintf("%d:%d every day", st.Hour, st.Minute)
case api.TIMER_TYPE_WEEK:
detail = st.weekDaysDesc()
case api.TIMER_TYPE_MONTH:
detail = st.monthDaysDesc()
}
if st.EndTime.IsZero() {
return detail
}
return fmt.Sprintf("%s, from %s to %s", detail, st.StartTime.In(zone).Format(format), st.EndTime.In(zone).Format(format))
}
func (st *STimer) weekDaysDesc() string {
if st.WeekDays == 0 {
return ""
}
var desc strings.Builder
wds := st.GetWeekDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d every %s", st.Hour, st.Minute, wdsEN[wds[i]]))
for i++; i < len(wds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(wdsEN[wds[i]])
}
if i == len(wds)-1 {
desc.WriteString(" and ")
desc.WriteString(wdsEN[wds[i]])
}
return desc.String()
}
func (st *STimer) monthDaysDesc() string {
if st.MonthDays == 0 {
return ""
}
var desc strings.Builder
mds := st.GetMonthDays()
i := 0
desc.WriteString(fmt.Sprintf("%d:%d on the %d%s", st.Hour, st.Minute, mds[i], st.dateSuffix(mds[i])))
for i++; i < len(mds)-1; i++ {
desc.WriteString(", ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(st.dateSuffix(mds[i]))
}
if i == len(mds)-1 {
desc.WriteString(" and ")
desc.WriteString(strconv.Itoa(mds[i]))
desc.WriteString(st.dateSuffix(mds[i]))
}
desc.WriteString(" of each month")
return desc.String()
}
func (st *STimer) dateSuffix(date int) string {
var ret string
switch date {
case 1:
ret = "st"
case 2:
ret = "nd"
case 3:
ret = "rd"
default:
ret = "th"
}
return ret
}
func checkCycleTimerCreateInput(in api.CycleTimerCreateInput) (api.CycleTimerCreateInput, error) {
now := time.Now()
if in.Minute < 0 || in.Minute > 59 {

View File

@@ -16,7 +16,6 @@ package models
import (
"context"
"database/sql"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -26,6 +25,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -46,19 +46,6 @@ type SVpcResourceBaseManager struct {
SManagedResourceBaseManager
}
func ValidateVpcResourceInput(userCred mcclient.TokenCredential, input api.VpcResourceInput) (*SVpc, api.VpcResourceInput, error) {
vpcObj, err := VpcManager.FetchByIdOrName(userCred, input.VpcId)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return nil, input, httperrors.NewResourceNotFoundError2(VpcManager.Keyword(), input.VpcId)
} else {
return nil, input, errors.Wrap(err, "VpcManager.FetchByIdOrName")
}
}
input.VpcId = vpcObj.GetId()
return vpcObj.(*SVpc), input, nil
}
func (self *SVpcResourceBase) GetVpc() *SVpc {
obj, _ := VpcManager.FetchById(self.VpcId)
if obj == nil {
@@ -180,11 +167,16 @@ func (manager *SVpcResourceBaseManager) ListItemFilter(
) (*sqlchemy.SQuery, error) {
var err error
if len(query.VpcId) > 0 {
vpcObj, _, err := ValidateVpcResourceInput(userCred, query.VpcResourceInput)
if err != nil {
return nil, errors.Wrap(err, "ValidateVpcResourceInput")
switch query.VpcId {
case api.CLASSIC_VPC_NAME:
q = q.Equals("name", api.CLASSIC_VPC_NAME)
default:
_, err := validators.ValidateModel(userCred, VpcManager, &query.VpcId)
if err != nil {
return nil, err
}
q = q.Equals("vpc_id", query.VpcId)
}
q = q.Equals("vpc_id", vpcObj.GetId())
}
subq := VpcManager.Query("id").Snapshot()
subq, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, subq, userCred, query.RegionalFilterListInput)

View File

@@ -287,7 +287,7 @@ func (manager *SVpcManager) GetOrCreateVpcForClassicNetwork(ctx context.Context,
vpc.IsDefault = false
vpc.CloudregionId = region.Id
vpc.SetModelManager(manager, vpc)
vpc.Name = "-"
vpc.Name = api.CLASSIC_VPC_NAME
vpc.IsEmulated = true
vpc.SetEnabled(false)
vpc.Status = api.VPC_STATUS_UNAVAILABLE
@@ -1417,7 +1417,7 @@ func (manager *SVpcManager) ListItemExportKeys(ctx context.Context,
if keys.Contains("wire_count") {
wires := WireManager.Query("vpc_id").SubQuery()
subq := wires.Query(sqlchemy.COUNT("wire_count"), wires.Field("vpc_id")).GroupBy(wires.Field("vpc_id")).SubQuery()
q = q.Join(subq, sqlchemy.Equals(q.Field("id"), subq.Field("vpc_id")))
q = q.LeftJoin(subq, sqlchemy.Equals(q.Field("id"), subq.Field("vpc_id")))
q = q.AppendField(subq.Field("wire_count"))
}
@@ -1425,10 +1425,10 @@ func (manager *SVpcManager) ListItemExportKeys(ctx context.Context,
wires := WireManager.Query("id", "vpc_id").SubQuery()
networks := NetworkManager.Query("wire_id").SubQuery()
subq := networks.Query(sqlchemy.COUNT("network_count"), wires.Field("vpc_id"))
subq = subq.Join(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
subq = subq.LeftJoin(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
subq = subq.GroupBy(wires.Field("vpc_id"))
subqQ := subq.SubQuery()
q = q.Join(subqQ, sqlchemy.Equals(q.Field("id"), subqQ.Field("vpc_id")))
q = q.LeftJoin(subqQ, sqlchemy.Equals(q.Field("id"), subqQ.Field("vpc_id")))
q = q.AppendField(subqQ.Field("network_count"))
}

View File

@@ -113,11 +113,11 @@ func (manager *SWireManager) ValidateCreateData(
input.VpcId = api.DEFAULT_VPC_ID
}
var vpc *SVpc
vpc, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
_vpc, err := validators.ValidateModel(userCred, VpcManager, &input.VpcId)
if err != nil {
return input, errors.Wrap(err, "ValidateVpcResourceInput")
return input, err
}
vpc := _vpc.(*SVpc)
if len(vpc.ManagerId) > 0 {
return input, httperrors.NewNotSupportedError("Currently only kvm platform supports creating wire")
@@ -1012,6 +1012,10 @@ func (manager *SWireManager) ListItemFilter(
q = q.Filter(sqlchemy.In(q.Field("id"), sq.SubQuery()))
}
if query.Bandwidth != nil {
q = q.Equals("bandwidth", *query.Bandwidth)
}
return q, nil
}

View File

@@ -149,7 +149,8 @@ type ComputeOptions struct {
SyncStorageCapacityUsedIntervalMinutes int `help:"interval sync storage capacity used" default:"20"`
LockStorageFromCachedimage bool `help:"must use storage in where selected cachedimage when creating vm"`
SyncExtDiskSnapshotIntervalMinutes int `help:"sync snapshot for external disk" default:"20"`
SyncExtDiskSnapshotIntervalMinutes int `help:"sync snapshot for external disk" default:"20"`
AutoReconcileBackupServers bool `help:"auto reconcile backup servers" default:"false"`
SCapabilityOptions
SASControllerOptions

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