Compare commits

..

243 Commits

Author SHA1 Message Date
yunion-ci-robot
a1760d7b86 Merge pull request #8537 from rainzm/automated-cherry-pick-of-#8535-upstream-release-3.4
Automated cherry pick of #8535: refactor(region): faster list for cachedimage
2020-10-28 17:58:42 +08:00
rainzm
c456586860 refactor(region): faster list for cachedimage
Pro version of #8440 with checking the necessity of id filtering
2020-10-28 15:36:03 +08:00
yunion-ci-robot
71e759a032 Merge pull request #8527 from rainzm/automated-cherry-pick-of-#8525-upstream-release-3.4
Automated cherry pick of #8525: fix(esxi): no callback in uploadHandler
2020-10-28 00:59:42 +08:00
yunion-ci-robot
96ce64d5f0 Merge pull request #8514 from ioito/automated-cherry-pick-of-#8512-upstream-release-3.4
Automated cherry pick of #8512: fix: avoid sync project panic
2020-10-28 00:48:42 +08:00
rainzm
d31802c87b fix(esxi): filter vmdk item in lease.info 2020-10-27 21:32:21 +08:00
rainzm
d3964bf0d1 fix(esxi): use correct device index
1. Sort devices via their Key.
2. There is no relationship between vdisk index and vnics length.
2020-10-27 21:32:21 +08:00
rainzm
57dad6281a fix(esxi): no callback in uploadHandler 2020-10-27 21:32:21 +08:00
Zexi Li
b74130903e Merge pull request #8519 from ioito/automated-cherry-pick-of-#8517-upstream-release-3.4
Automated cherry pick of #8517: fix: set secgroup status
2020-10-27 17:28:39 +08:00
Qu Xuan
44046f2861 fix: set secgroup status 2020-10-27 16:20:06 +08:00
Qu Xuan
95f7600b67 fix: avoid sync project panic 2020-10-27 16:13:48 +08:00
yunion-ci-robot
749b819a62 Merge pull request #8501 from yousong/automated-cherry-pick-of-#8499-upstream-release-3.4
Automated cherry pick of #8499: lockman: test: add prefix setting
2020-10-26 21:24:40 +08:00
Yousong Zhou
f7f7c7be81 lockman: test: add prefix setting 2020-10-26 20:36:32 +08:00
yunion-ci-robot
6a221dbc1e Merge pull request #8498 from zhaoxiangchun/automated-cherry-pick-of-#8496-upstream-release-3.4
Automated cherry pick of #8496: commalertUpdateInput increat param:
2020-10-26 19:55:47 +08:00
zhaoxiangchun
002a2af272 commalertUpdateInput increat param:
1.处理operator对alertType == system的报警策略的update请求
2020-10-26 18:21:11 +08:00
yunion-ci-robot
1757d3d6a9 Merge pull request #8494 from rainzm/automated-cherry-pick-of-#8493-upstream-release-3.4
Automated cherry pick of #8493: fix(region): roll back the optimization of cachedimage list
2020-10-26 18:17:39 +08:00
rainzm
be5a6a93cc fix(region): roll back the optimization of cachedimage list 2020-10-26 17:37:59 +08:00
yunion-ci-robot
bbbe78dbef Merge pull request #8489 from ioito/automated-cherry-pick-of-#8487-upstream-release-3.4
Automated cherry pick of #8487: fix: avoid delete public ip when sync eip list
2020-10-26 17:02:42 +08:00
Qu Xuan
a851e01330 fix: avoid delete public ip when sync eip list 2020-10-26 16:18:46 +08:00
yunion-ci-robot
29d06d52dd Merge pull request #8466 from wanyaoqi/automated-cherry-pick-of-#8464-upstream-release-3.4
Automated cherry pick of #8464: check disk is in reset before delete snapshot
2020-10-25 10:54:39 +08:00
yunion-ci-robot
1a6d4d1035 Merge pull request #8486 from swordqiu/automated-cherry-pick-of-#8484-upstream-release-3.4
Automated cherry pick of #8484: fix: server usage status not correct
2020-10-25 10:52:41 +08:00
Qiu Jian
90d649aef9 fix: server usage status not correct 2020-10-25 08:38:48 +08:00
Zexi Li
23b99a6232 Merge pull request #8472 from wanyaoqi/automated-cherry-pick-of-#8470-upstream-release-3.4
Automated cherry pick of #8470: fix on stream disk complete snapshots refcount not update
2020-10-24 13:09:42 +08:00
Zexi Li
16c38fe6be Merge pull request #8476 from zexi/automated-cherry-pick-of-#8474-upstream-release-3.4
Automated cherry pick of #8474: monitor: set default influxdb datasource by endpoint type
2020-10-24 13:07:07 +08:00
Zexi Li
b43f8b3fac monitor: set default influxdb datasource by endpoint type 2020-10-23 20:10:08 +08:00
wanyaoqi
8e5b74a3f6 fix on stream disk complete snapshots refcount not update 2020-10-23 19:11:32 +08:00
yunion-ci-robot
b0cd3bf999 Merge pull request #8414 from zhaoxiangchun/automated-cherry-pick-of-#8412-upstream-release-3.4
Automated cherry pick of #8412: bugfix:
2020-10-23 18:35:17 +08:00
yunion-ci-robot
4a15284684 Merge pull request #8463 from rainzm/automated-cherry-pick-of-#8461-upstream-release-3.4
Automated cherry pick of #8461: fix(glance): allow public and private operations of guestimage
2020-10-23 18:29:15 +08:00
wanyaoqi
d78068d43a check disk is in reset before delete snapshot 2020-10-23 18:26:22 +08:00
yunion-ci-robot
80dce5eafb Merge pull request #8452 from wanyaoqi/automated-cherry-pick-of-#8450-upstream-release-3.4
Automated cherry pick of #8450: host increase cpu mem max size
2020-10-23 18:18:20 +08:00
yunion-ci-robot
950696ddb9 Merge pull request #8458 from rainzm/automated-cherry-pick-of-#8456-upstream-release-3.4
Automated cherry pick of #8456: fix(esxi): resize root disk after cloning vm
2020-10-23 18:17:20 +08:00
zhaoxiangchun
e7674116e1 bugfix:
1.资源报警增加websocket 消息通知:admin用户
2.统一influxdb中查询到的tag展示
2020-10-23 17:58:20 +08:00
rainzm
3fae388db5 fix(glance): allow public and private operations of guestimage
The public and private operations of the guest image depends on these operations of the subimage.
2020-10-23 17:57:48 +08:00
rainzm
8f3b8c7ff1 fix(esxi): resize root disk after cloning vm
The root disk size set when the machine is cloned does not take effect,
so set the root disk size after the machine is cloned.
2020-10-23 17:03:52 +08:00
wanyaoqi
a4b1d3952d host increase cpu mem max size 2020-10-23 15:15:55 +08:00
yunion-ci-robot
a5ef16243d Merge pull request #8442 from rainzm/automated-cherry-pick-of-#8440-upstream-release-3.4
Automated cherry pick of #8440: refactor(region): faster list for cachedimage
2020-10-22 21:25:14 +08:00
rainzm
b0823a09bb refactor(region): faster list for cachedimage
修改之前:
诸如provider, zone, host_schedtag_id, valid
等过滤条件,是通过过滤出符合条件的 storagecachedimage 然后使用 cachedimage_id 来过滤 cachedimge,
问题是,每一个过滤条件都会独立的去执行上面的过程,这样同样的查询可能要经过很多次,并且如果遇到
弱的过滤条件,比如 valid ,过滤出来的 storagecachedimage
非常之多,然后在使用 cachedimage_id 去过滤 cachedimage,会非常慢。

修改之后:
过滤条件的相似的逻辑合并起来,只需要向 subQuery 中添加 filter,使用 subQuery 一次把 storagecachedimage
过滤出来,然后使用 cachedimage_id 过滤 cachedimage。
2020-10-22 20:18:40 +08:00
yunion-ci-robot
492920ac7c Merge pull request #8428 from ioito/automated-cherry-pick-of-#8426-upstream-release-3.4
Automated cherry pick of #8426: fix: 避免冲掉设置的到期释放时间
2020-10-22 20:13:22 +08:00
yunion-ci-robot
f96ac33175 Merge pull request #8433 from lvyangyang/automated-cherry-pick-of-#8416-upstream-release-3.4
Automated cherry pick of #8416: fix:get all project dns resource
2020-10-22 20:10:19 +08:00
yunion-ci-robot
1bc16d6f2e Merge pull request #8439 from rainzm/automated-cherry-pick-of-#8437-upstream-release-3.4
Automated cherry pick of #8437: fix(region): add suffix 'display' for time_points and repeat_weekdays
2020-10-22 20:07:17 +08:00
rainzm
0ba8cb7fbd fix: don't update NextSyncTime when snapshots that should be added has not 2020-10-22 19:42:26 +08:00
rainzm
93bb4022f2 fix(region): init NextSyncTimeiwhen create snapshotpolicydisks 2020-10-22 19:42:26 +08:00
rainzm
bbfb9db90a fix(region): add suffix 'display' for time_points and repeat_weekdays
TimePoints and RepeatWeekdays in SnapshotPolicyDetails is duplicated
with thess in SnapshotPolicy, which result in the fault of reponse for
request GET.
2020-10-22 19:42:26 +08:00
lvyangyang
66c81ee548 fix:get all project dns resource 2020-10-22 17:06:00 +08:00
Qu Xuan
8f3cb9cdbb fix: 避免冲掉设置的到期释放时间 2020-10-22 15:41:19 +08:00
yunion-ci-robot
1ac71d0016 Merge pull request #8409 from wanyaoqi/automated-cherry-pick-of-#8407-upstream-release-3.4
Automated cherry pick of #8407: fix informer backend
2020-10-22 15:04:16 +08:00
yunion-ci-robot
e8238a2cf5 Merge pull request #8425 from ioito/automated-cherry-pick-of-#8423-upstream-release-3.4
Automated cherry pick of #8423: fix: add aliyun new region
2020-10-22 14:31:17 +08:00
Qu Xuan
22349276d9 fix: add aliyun new region 2020-10-22 11:53:08 +08:00
wanyaoqi
d6a9b5dac2 fix informer backend 2020-10-21 10:54:14 +08:00
yunion-ci-robot
0e3aa96f77 Merge pull request #8406 from rainzm/automated-cherry-pick-of-#8404-upstream-release-3.4
Automated cherry pick of #8404: fix(notify): add AllOkContactTypes in where permanently enabled and verified ContactType
2020-10-21 10:51:16 +08:00
rainzm
5306add70a feat(notify): add IntelliNotify
IntelliNotify will try to create receiver nonexistent if createReceiver is set to true
2020-10-20 20:38:17 +08:00
rainzm
f367f1abef fix(notify): add AllOkContactTypes in where permanently enabled and verified ContactType 2020-10-20 20:38:17 +08:00
Zexi Li
93dc36134d Merge pull request #8402 from wanyaoqi/automated-cherry-pick-of-#8400-upstream-release-3.4
Automated cherry pick of #8400: fix fetch customize columns
2020-10-20 18:52:56 +08:00
wanyaoqi
f706d59ac5 fix fetch customize columns 2020-10-20 18:43:52 +08:00
Zexi Li
7438bcab23 Merge pull request #8339 from tb365/automated-cherry-pick-of-#8338-upstream-release-3.4
Automated cherry pick of #8338: add aliyun finance environment
2020-10-20 13:33:47 +08:00
yunion-ci-robot
e038eebeb7 Merge pull request #8263 from rainzm/automated-cherry-pick-of-#8258-upstream-release-3.4
Automated cherry pick of #8258: feat: add a retry mechanism to AutoSyncExtDiskSnapshot
2020-10-20 13:31:13 +08:00
Zexi Li
bd7d84aebd Merge pull request #8396 from tb365/automated-cherry-pick-of-#8395-upstream-release-3.4
Automated cherry pick of #8395: lbcert delete bugfix
2020-10-20 13:28:31 +08:00
Zexi Li
5f6f554464 Merge pull request #8398 from zexi/automated-cherry-pick-of-#8397-upstream-release-3.4
Automated cherry pick of #8397: fix: monitor commonalert not detach alert resource
2020-10-20 13:26:51 +08:00
Zexi Li
d99d93d046 fix: monitor commonalert not detach alert resource 2020-10-20 13:21:22 +08:00
Zexi Li
4a856ac688 Merge pull request #8393 from rainzm/automated-cherry-pick-of-#8392-upstream-release-3.4
Automated cherry pick of #8392: fix(region): compute binded disk count when deleting snapshotpolicy
2020-10-20 11:49:52 +08:00
TangBin
7da0a67af5 lbcert delete bugfix 2020-10-20 11:27:53 +08:00
rainzm
37c14d756d feat: use details data to cover obj data in FetchCustomizeColumns 2020-10-20 11:20:45 +08:00
rainzm
6f1417d268 fix(region): compute binded disk count when deleting snapshotpolicy 2020-10-20 11:20:45 +08:00
Zexi Li
b3105a05d3 Merge pull request #8322 from ioito/automated-cherry-pick-of-#8321-upstream-release-3.4
Automated cherry pick of #8321: fix: sync dns records after sync vpcs
2020-10-20 11:19:50 +08:00
rainzm
93ac3260a1 feat: add a retry mechanism to AutoSyncExtDiskSnapshot 2020-10-20 09:54:53 +08:00
yunion-ci-robot
3d39c20c91 Merge pull request #8391 from zhaoxiangchun/automated-cherry-pick-of-#8390-upstream-release-3.4
Automated cherry pick of #8390: bugfix: commonalert
2020-10-19 23:19:23 +08:00
zhaoxiangchun
8a0eeb7d67 bugfix: commonalert
1.报警消息中取消返回sql信息
2.commonalert 中支持top bottom 结构influxdb 查询
2020-10-19 23:06:29 +08:00
yunion-ci-robot
163be04dbb Merge pull request #8364 from zhaoxiangchun/automated-cherry-pick-of-#8357-upstream-release-3.4
Automated cherry pick of #8357: bugfix: qcloud pull metric
2020-10-19 22:34:14 +08:00
zhaoxiangchun
06db7339e4 bugfix: qcloud pull metric
get请求中增加region参数
2020-10-19 22:26:52 +08:00
yunion-ci-robot
e5b3f4673d Merge pull request #8387 from zexi/automated-cherry-pick-of-#8346-upstream-release-3.4
Automated cherry pick of #8346: monitor: add alert resource
2020-10-19 22:13:12 +08:00
yunion-ci-robot
3a6e910580 Merge pull request #8380 from yousong/automated-cherry-pick-of-#8379-upstream-release-3.4
Automated cherry pick of #8379: logger: actionlog: readability change
2020-10-19 22:07:12 +08:00
Zexi Li
0317fad04e Merge pull request #8389 from wanyaoqi/automated-cherry-pick-of-#8388-upstream-release-3.4
Automated cherry pick of #8388: remove try set informer backend
2020-10-19 22:02:39 +08:00
Zexi Li
af11737e79 monitor: add alert resource 2020-10-19 21:48:35 +08:00
wanyaoqi
15bd6bacd6 remove try set informer backend 2020-10-19 21:33:49 +08:00
Zexi Li
28ba60f630 Merge pull request #8386 from wanyaoqi/automated-cherry-pick-of-#8385-upstream-release-3.4
Automated cherry pick of #8385: telegraf-raid-plugin: update raid state to lower case
2020-10-19 21:00:06 +08:00
yunion-ci-robot
8799a0bcf9 Merge pull request #8384 from wanyaoqi/automated-cherry-pick-of-#8383-upstream-release-3.4
Automated cherry pick of #8383: keystone init etcd backend
2020-10-19 20:58:13 +08:00
wanyaoqi
6706c39f85 telegraf-raid-plugin: update raid state to lower case 2020-10-19 20:12:47 +08:00
wanyaoqi
8ce183eaf5 keystone init etcd backend 2020-10-19 20:04:42 +08:00
yunion-ci-robot
a5bec974f1 Merge pull request #8345 from rainzm/automated-cherry-pick-of-#8344-upstream-release-3.4
Automated cherry pick of #8344: feat(notify): support webhook contact type
2020-10-19 18:25:11 +08:00
Zexi Li
ac15981b5d Merge pull request #8377 from swordqiu/automated-cherry-pick-of-#8350-upstream-release-3.4
Automated cherry pick of #8350: fix: missing authenticate action log for user web login
2020-10-19 17:44:44 +08:00
Zexi Li
3c447a32f6 Merge pull request #8342 from swordqiu/automated-cherry-pick-of-#8337-upstream-release-3.4
Automated cherry pick of #8337: fix: cancel pending-delete should increase resource quota usages
2020-10-19 17:44:03 +08:00
yunion-ci-robot
3a8809e060 Merge pull request #8341 from rainzm/automated-cherry-pick-of-#8340-upstream-release-3.4
Automated cherry pick of #8340: feat: add valid filter for cachedimage list
2020-10-19 17:13:11 +08:00
Yousong Zhou
0964c6ad82 logger: actionlog: i18n for distinct-field 2020-10-19 16:42:24 +08:00
Yousong Zhou
5d0fd14cb3 cloudcommon: db: GET: i18n for result of get property calls 2020-10-19 16:42:24 +08:00
Yousong Zhou
cd123e007d cloudcommon: db: add man.GetI18N 2020-10-19 16:42:24 +08:00
Yousong Zhou
91736710ba cloudcommon: db: modelbase: distinct-field: readability change 2020-10-19 16:42:24 +08:00
Yousong Zhou
c2589e7352 logger: actionlog: readability change 2020-10-19 16:42:24 +08:00
rainzm
d454b0a792 feat: add valid filter for cachedimage list
Use the 'valid' switch to control whether to filter out
the cachedimage corresponding to invalid storage
2020-10-19 16:28:04 +08:00
Qiu Jian
2a1a640f6b fix: cancel pending-delete should increase resource quota usages 2020-10-19 16:03:26 +08:00
rainzm
9dee4c1b90 feat(region): call NotifyWebhook in the life cycle of guests 2020-10-19 16:02:55 +08:00
rainzm
0fd6481e4d feat: add NotifyWebhook in notifyclient 2020-10-19 16:02:55 +08:00
rainzm
d799a71fdb feat(notify): allow empty receivers for robot or webhook contact type 2020-10-19 16:02:55 +08:00
rainzm
436f1e5cb9 feat(notify): support webhook contact type 2020-10-19 16:02:55 +08:00
Qiu Jian
a92a0e2d05 fix: missing authenticate action log for user web login 2020-10-19 15:54:10 +08:00
yunion-ci-robot
0cafa996d7 Merge pull request #8362 from swordqiu/automated-cherry-pick-of-#8361-upstream-release-3.4
Automated cherry pick of #8361: fix: do not lock guest after lock eip, to prevent possible dead lock
2020-10-19 15:20:12 +08:00
yunion-ci-robot
2a10b72f98 Merge pull request #8348 from swordqiu/automated-cherry-pick-of-#8347-upstream-release-3.4
Automated cherry pick of #8347: fix: remote update metadata may cause metadata update loop
2020-10-19 15:19:16 +08:00
yunion-ci-robot
31c2b6270a Merge pull request #8354 from swordqiu/automated-cherry-pick-of-#8353-upstream-release-3.4
Automated cherry pick of #8353: fix: reduce change config logs
2020-10-19 15:18:18 +08:00
yunion-ci-robot
a6397d18c2 Merge pull request #8351 from swordqiu/automated-cherry-pick-of-#8350-upstream-release-3.4
Automated cherry pick of #8350: fix: missing authenticate action log for user web login
2020-10-19 15:17:12 +08:00
Zexi Li
203bf44639 Merge pull request #8367 from ioito/automated-cherry-pick-of-#8366-upstream-release-3.4
Automated cherry pick of #8366: fix: add rds cpu and memory usage
2020-10-19 15:11:56 +08:00
Zexi Li
d7a4e52b15 Merge pull request #8374 from ioito/automated-cherry-pick-of-#8373-upstream-release-3.4
Automated cherry pick of #8373: fix: 新增google存储类型
2020-10-19 15:11:08 +08:00
Zexi Li
7946dcef3f Merge pull request #8370 from ioito/automated-cherry-pick-of-#8369-upstream-release-3.4
Automated cherry pick of #8369: fix: use correct worker
2020-10-19 15:10:00 +08:00
Qu Xuan
f77bcd3bbf fix: 新增google存储类型 2020-10-19 14:16:51 +08:00
yunion-ci-robot
4841fbb843 Merge pull request #8356 from wanyaoqi/automated-cherry-pick-of-#8355-upstream-release-3.4
Automated cherry pick of #8355: host: fix sync storage info duration'
2020-10-19 11:57:12 +08:00
Qiu Jian
9b8758e191 fix: reduce change config logs 2020-10-19 11:51:38 +08:00
Qiu Jian
62f5355b11 fix: remote update metadata may cause metadata update loop 2020-10-19 11:46:20 +08:00
Qiu Jian
d774581a23 fix: do not lock guest after lock eip, to prevent possible dead lock 2020-10-19 11:43:22 +08:00
Qu Xuan
062301f54a fix: use correct worker 2020-10-19 11:42:25 +08:00
Qu Xuan
16d13941ce fix: add rds cpu and memory usage 2020-10-19 11:23:21 +08:00
yunion-ci-robot
a10b1945f6 Merge pull request #8359 from yousong/automated-cherry-pick-of-#8358-upstream-release-3.4
Automated cherry pick of #8358: .circleci: build: make with parallel level 2
2020-10-19 10:50:16 +08:00
Yousong Zhou
3aadaf15b7 .circleci: build: make with parallel level 2 2020-10-19 10:29:50 +08:00
wanyaoqi
7a9b491d13 host: fix sync storage info duration' 2020-10-18 01:02:12 +08:00
Qiu Jian
ecbe76e9ff fix: missing authenticate action log for user web login 2020-10-17 22:09:55 +08:00
yunion-ci-robot
41bdfffd57 Merge pull request #8333 from rainzm/automated-cherry-pick-of-#8332-upstream-release-3.4
Automated cherry pick of #8332: feat: support lock storage from selected cachedimage
2020-10-17 18:23:10 +08:00
TangBin
a9c44ed304 add aliyun finance environment 2020-10-17 17:41:57 +08:00
rainzm
7a2c2b8047 refactor: find the most suitable storage 2020-10-17 17:40:08 +08:00
rainzm
a35a6f3c11 feat(esxiagent): try to customize vm if deployfs failed 2020-10-17 17:40:08 +08:00
rainzm
5a7876ae47 feat: support lock storage from selected cachedimage 2020-10-17 17:40:08 +08:00
yunion-ci-robot
31de731cbd Merge pull request #8336 from wanyaoqi/automated-cherry-pick-of-#8325-upstream-release-3.4
Automated cherry pick of #8325: telegraf raid plugin
2020-10-17 11:23:11 +08:00
wanyaoqi
8b2680ed56 telegraf raid plugin 2020-10-17 11:11:30 +08:00
yunion-ci-robot
39c35359aa Merge pull request #8329 from swordqiu/automated-cherry-pick-of-#8304-upstream-release-3.4
Automated cherry pick of #8304: feature: qcloud create VM with tags
2020-10-16 22:19:05 +08:00
Qiu Jian
a764a64696 feature: remote update qcloud instance metadata and name 2020-10-16 21:41:33 +08:00
Qiu Jian
f05a56aadd feature: qcloud create VM with tags 2020-10-16 21:41:33 +08:00
yunion-ci-robot
6cd69d3587 Merge pull request #8335 from rainzm/automated-cherry-pick-of-#8334-upstream-release-3.4
Automated cherry pick of #8334: fix(compute): filter cachedimage with health storage
2020-10-16 19:41:45 +08:00
rainzm
2a1bbfd574 fix(compute): filter cachedimage with health storage 2020-10-16 18:38:44 +08:00
Zexi Li
301006e213 Merge pull request #8331 from ioito/automated-cherry-pick-of-#8330-upstream-release-3.4
Automated cherry pick of #8330: fix: hostname for instance
2020-10-16 17:43:22 +08:00
Qu Xuan
950a2c29fb fix: hostname for instance 2020-10-16 17:12:40 +08:00
yunion-ci-robot
558872db27 Merge pull request #8324 from zhasm/automated-cherry-pick-of-#8323-upstream-release-3.4
Automated cherry pick of #8323: remove alpine build cache before make image
2020-10-16 15:14:46 +08:00
yunion-ci-robot
6386391bf4 Merge pull request #8327 from zexi/automated-cherry-pick-of-#8326-upstream-release-3.4
Automated cherry pick of #8326: fix: get images distinct field
2020-10-16 14:35:40 +08:00
Zexi Li
d298c75448 fix: get images distinct field 2020-10-16 12:01:01 +08:00
Zhang Dongliang
28cb75f41b remove alpine build cache before make image 2020-10-16 12:00:10 +08:00
yunion-ci-robot
560a68d379 Merge pull request #8320 from swordqiu/automated-cherry-pick-of-#8319-upstream-release-3.4
Automated cherry pick of #8319: fix: resolve with_meta filter conflict
2020-10-16 11:39:33 +08:00
Qu Xuan
11f8e4f71f fix: sync dns records after sync vpcs 2020-10-16 11:14:44 +08:00
yunion-ci-robot
9e597db90a Merge pull request #8315 from rainzm/automated-cherry-pick-of-#8314-upstream-release-3.4
Automated cherry pick of #8314: feat(esxi): do not specify portkey in NewVNIC
2020-10-16 10:38:34 +08:00
Qiu Jian
9c9cb17d32 fix: resolve with_meta filter conflict 2020-10-16 10:34:04 +08:00
rainzm
cc96c01c00 feat(esxi): do not specify portkey in NewVNIC 2020-10-16 08:22:58 +08:00
yunion-ci-robot
cb22077722 Merge pull request #8313 from swordqiu/automated-cherry-pick-of-#8312-upstream-release-3.4
Automated cherry pick of #8312: feature: filter storages by image
2020-10-15 23:10:33 +08:00
yunion-ci-robot
8e3c173373 Merge pull request #8309 from ioito/automated-cherry-pick-of-#8308-upstream-release-3.4
Automated cherry pick of #8308: fix: 避免并发同步安全组导致规则混乱
2020-10-15 23:02:32 +08:00
Qiu Jian
45e092bd2d feature: filter storages by image 2020-10-15 22:57:13 +08:00
Qu Xuan
4b2d67de42 fix: 避免并发同步安全组导致规则混乱 2020-10-15 22:26:54 +08:00
yunion-ci-robot
6677c30a5d Merge pull request #8306 from zexi/automated-cherry-pick-of-#8305-upstream-release-3.4
Automated cherry pick of #8305: stringutils2: add RemoveUtf8Strings func
2020-10-15 21:46:36 +08:00
Zexi Li
64593fc882 stringutils2: add RemoveUtf8Strings func 2020-10-15 19:37:00 +08:00
Zexi Li
0d7e1a2517 Merge pull request #8303 from swordqiu/automated-cherry-pick-of-#8302-upstream-release-3.4
Automated cherry pick of #8302: fix: allwo filter resource by with-meta and with-user-meta filter
2020-10-15 15:17:18 +08:00
Zexi Li
6fc835abb9 Merge pull request #8300 from ioito/automated-cherry-pick-of-#8299-upstream-release-3.4
Automated cherry pick of #8299: fix: support filter rds sku by provider
2020-10-15 15:16:04 +08:00
Zexi Li
44a9cc5adb Merge pull request #8293 from lvyangyang/automated-cherry-pick-of-#8289-upstream-release-3.4
Automated cherry pick of #8289: fix:openstack lb 后端ip无法映射到主机的异常处理
2020-10-15 15:15:09 +08:00
Qiu Jian
ff2b7eb345 fix: allwo filter resource by with-meta and with-user-meta filter 2020-10-15 14:46:48 +08:00
Qu Xuan
7b5d822373 fix: support filter rds sku by provider 2020-10-15 14:29:59 +08:00
yunion-ci-robot
f5a45fc16e Merge pull request #8298 from swordqiu/automated-cherry-pick-of-#8297-upstream-release-3.4
Automated cherry pick of #8297: fix: filter role assignments by project domains id or name
2020-10-15 14:24:33 +08:00
yunion-ci-robot
a583bbc74b Merge pull request #8295 from ioito/automated-cherry-pick-of-#8294-upstream-release-3.4
Automated cherry pick of #8294: fix: use new api
2020-10-15 14:22:37 +08:00
yunion-ci-robot
ece82cce42 Merge pull request #8266 from rainzm/automated-cherry-pick-of-#8265-upstream-release-3.4
Automated cherry pick of #8265: feat(esxiagent): sync and use of ESXi template
2020-10-15 13:14:31 +08:00
Qiu Jian
8042b9430c fix: filter project role with system=true 2020-10-15 13:10:54 +08:00
Qiu Jian
d1cbaead09 fix: filter role assignments by project domains id or name 2020-10-15 13:10:54 +08:00
Qu Xuan
1768d1e7db fix: use new api 2020-10-15 11:32:56 +08:00
rainzm
ff34e93862 feat: add 'vlan_id' param when creating network 2020-10-15 10:50:25 +08:00
rainzm
a891d1d876 feat: change templateid as <providerId>/<uuid> in esxi 2020-10-15 10:50:25 +08:00
Rain
c7d6bb7811 fix: support fake tempalte when searching template vm 2020-10-15 10:50:25 +08:00
rainzm
2076a75113 fix(esxiagent): check whether regexp is nil 2020-10-15 10:50:25 +08:00
rainzm
5d0d6d960b feat(esxiagent): keep data disks when cloning vm 2020-10-15 10:50:25 +08:00
lvyangyang
cf89e8a23a fix:openstack lb 后端ip无法映射到主机的异常处理 2020-10-15 10:09:53 +08:00
yunion-ci-robot
45994b59d5 Merge pull request #8291 from ioito/automated-cherry-pick-of-#8290-upstream-release-3.4
Automated cherry pick of #8290: fix: 优化安全组规则同步
2020-10-15 09:10:33 +08:00
Qu Xuan
d2d2934e80 fix: 优化安全组规则同步 2020-10-14 21:19:15 +08:00
yunion-ci-robot
0ec0c8e703 Merge pull request #8286 from lvyangyang/automated-cherry-pick-of-#8275-upstream-release-3.4
Automated cherry pick of #8275: fix:aliyun jsonRequest 增加i/o timeout retry
2020-10-14 17:53:30 +08:00
yunion-ci-robot
3347d6c1e1 Merge pull request #8285 from swordqiu/automated-cherry-pick-of-#8284-upstream-release-3.4
Automated cherry pick of #8284: feature: qcloud create VM with tags
2020-10-14 17:52:29 +08:00
yunion-ci-robot
dce9d5e4a1 Merge pull request #8288 from wanyaoqi/automated-cherry-pick-of-#8287-upstream-release-3.4
Automated cherry pick of #8287: make mode
2020-10-14 16:52:33 +08:00
Qiu Jian
ef9b64990e feature: qcloud create VM with tags 2020-10-14 15:22:30 +08:00
wanyaoqi
f19fe2178c replace NewFloat by NewFloat64 and NewFloat32 2020-10-14 11:56:49 +08:00
wanyaoqi
2265c9422f make mode 2020-10-14 11:56:49 +08:00
yunion-ci-robot
cf3717557a Merge pull request #8282 from ioito/automated-cherry-pick-of-#8281-upstream-release-3.4
Automated cherry pick of #8281: fix: sync huawei bucket project info
2020-10-14 10:51:30 +08:00
yunion-ci-robot
0bbdcb9278 Merge pull request #8280 from ioito/automated-cherry-pick-of-#8264-upstream-release-3.4
Automated cherry pick of #8264: fix: support public ip create
2020-10-14 10:50:30 +08:00
lvyangyang
d72081770e fix:aliyun jsonRequest 增加i/o timeout retry 2020-10-14 10:48:50 +08:00
yunion-ci-robot
0f874d8f07 Merge pull request #8254 from ioito/automated-cherry-pick-of-#8253-upstream-release-3.4
Automated cherry pick of #8253: fix: qcloud eip with bandwidth attr
2020-10-14 10:44:30 +08:00
yunion-ci-robot
dd5dd15a76 Merge pull request #8241 from wanyaoqi/automated-cherry-pick-of-#8231-upstream-release-3.4
Automated cherry pick of #8231: add interface freeze virtual resource
2020-10-14 10:42:30 +08:00
Qu Xuan
cb36572c1c fix: sync huawei bucket project info 2020-10-13 20:55:39 +08:00
Qu Xuan
2a210407a5 fix: support public ip create 2020-10-13 20:01:01 +08:00
Zexi Li
82c59154c5 Merge pull request #8268 from ioito/automated-cherry-pick-of-#8267-upstream-release-3.4
Automated cherry pick of #8267: fix: trans google new region name
2020-10-13 17:34:44 +08:00
Zexi Li
041ee6f904 Merge pull request #8271 from ioito/automated-cherry-pick-of-#8270-upstream-release-3.4
Automated cherry pick of #8270: fix: 支持带宽包用户
2020-10-13 17:34:35 +08:00
yunion-ci-robot
4317fac6da Merge pull request #8279 from wanyaoqi/automated-cherry-pick-of-#8278-upstream-release-3.4
Automated cherry pick of #8278: fix host-deployer base image
2020-10-13 17:04:29 +08:00
yunion-ci-robot
a022f99851 Merge pull request #8277 from zhasm/automated-cherry-pick-of-#8276-upstream-release-3.4
Automated cherry pick of #8276: 在 docker push 脚本里创建_output 目录,以便容错
2020-10-13 17:01:30 +08:00
wanyaoqi
407251975e fix host-deployer base image 2020-10-13 16:59:24 +08:00
Zhang Dongliang
b7fd879e44 在 docker push 脚本里创建_output 目录,以便容错 2020-10-13 16:47:33 +08:00
yunion-ci-robot
0a7ccbe958 Merge pull request #8274 from zhasm/automated-cherry-pick-of-#8273-upstream-release-3.4
Automated cherry pick of #8273: 在 docker push 脚本里创建_output 目录,以便容错
2020-10-13 16:18:31 +08:00
Zhang Dongliang
7efb85ba04 在 docker push 脚本里创建_output 目录,以便容错 2020-10-13 15:37:25 +08:00
Qu Xuan
84e8e4e6c8 fix: 支持带宽包用户 2020-10-13 15:34:03 +08:00
Qu Xuan
3fe15d2675 fix: trans google new region name 2020-10-13 14:18:09 +08:00
Qu Xuan
d574a823ba fix: qcloud eip with bandwidth attr 2020-10-13 10:42:25 +08:00
yunion-ci-robot
a2c8ad13ab Merge pull request #8191 from ioito/automated-cherry-pick-of-#8188-upstream-release-3.4
Automated cherry pick of #8188: fix: avoid qcloud secgroup cache name not sync
2020-10-13 10:41:31 +08:00
yunion-ci-robot
de8f57f625 Merge pull request #8243 from zexi/automated-cherry-pick-of-#8242-upstream-release-3.4
Automated cherry pick of #8242: baremetal: fix pxe filter network by guest_dhcp
2020-10-13 10:32:29 +08:00
Zexi Li
658159b18e Merge pull request #8229 from yousong/automated-cherry-pick-of-#8228-upstream-release-3.4
Automated cherry pick of #8228: eip: construct a pointer type
2020-10-13 10:13:49 +08:00
Zexi Li
67cc7b8747 Merge pull request #8259 from rainzm/automated-cherry-pick-of-#8232-upstream-release-3.4
Automated cherry pick of #8232: fix(esxi): search template from whole vCenter
2020-10-13 10:06:22 +08:00
Zexi Li
ce694ff638 Merge pull request #8247 from swordqiu/automated-cherry-pick-of-#8246-upstream-release-3.4
Automated cherry pick of #8246: fix: project_id in resource details not correct
2020-10-13 10:00:34 +08:00
Zexi Li
98702c2470 Merge pull request #8249 from ioito/automated-cherry-pick-of-#8248-upstream-release-3.4
Automated cherry pick of #8248: fix: qcloud instance with max bandwidth
2020-10-13 09:58:37 +08:00
yunion-ci-robot
9ac5265c07 Merge pull request #8257 from zhasm/automated-cherry-pick-of-#8256-upstream-release-3.4
Automated cherry pick of #8256: 解决编译之后 output 的 owerner 问题
2020-10-12 19:24:28 +08:00
Yousong Zhou
896bec8f43 eip: NewEipForVMOnHost: add opslog 2020-10-12 18:39:17 +08:00
Yousong Zhou
a8426482bf eip: construct a pointer type 2020-10-12 18:39:17 +08:00
Zhang Dongliang
d7316b26aa resolve conflict 2020-10-12 18:12:41 +08:00
rainzm
d16affc9a6 fix(esxi): use system disk of template only when cloning vm
1. Create a driver if necessary.
2. After cloning the virtual machine, remove all data disks.
3. Create new data disks.
2020-10-12 17:46:38 +08:00
rainzm
2259fe1195 fix(esxi): search template from whole vCenter 2020-10-12 17:46:38 +08:00
yunion-ci-robot
09e37de117 Merge pull request #8251 from swordqiu/automated-cherry-pick-of-#8237-upstream-release-3.4
Automated cherry pick of #8237: fix: format errors that block make test
2020-10-12 16:09:22 +08:00
Qu Xuan
715db28e3e fix: qcloud instance with max bandwidth 2020-10-12 15:09:09 +08:00
Qiu Jian
152ea54f36 fix: format errors that block make test 2020-10-12 15:06:44 +08:00
yunion-ci-robot
865b433bb0 Merge pull request #8236 from swordqiu/automated-cherry-pick-of-#8235-upstream-release-3.4
Automated cherry pick of #8235: fix: not clean pending domain usage
2020-10-12 15:04:21 +08:00
yunion-ci-robot
f04a37d0a3 Merge pull request #8233 from rainzm/automated-cherry-pick-of-#8126-upstream-release-3.4
Automated cherry pick of #8126: Feats for ESXi Manage
2020-10-12 15:02:18 +08:00
rainzm
7edcd151e3 feat: add vlanId for suggested network 2020-10-12 14:25:05 +08:00
rainzm
df90d99bc5 feat(esxi): support fake template vm via regex filter 2020-10-12 14:25:05 +08:00
rainzm
552ce3b2ea feat: filter esxi ip by CIDR 2020-10-12 14:25:05 +08:00
rainzm
91c852676a feat(region): make address recommendations more precise
1. 虚拟机的网络推荐不再是一整个C段网络,而是存在的连续IP组成的网段,
这样更准确,用户可以根据自己的需要,合并或者扩充建议的网段
2. 使用 DefaultNetworkGatewayAddressEsxi 来配置子网默认的网关地址。
2020-10-12 14:25:05 +08:00
rainzm
8528d79817 feat: add 'ip-list' for esxicli 2020-10-12 14:25:05 +08:00
Qiu Jian
d2aacafa4c fix: project_id in resource details not correct 2020-10-12 14:20:22 +08:00
yunion-ci-robot
8714503087 Merge pull request #8239 from swordqiu/automated-cherry-pick-of-#8238-upstream-release-3.4
Automated cherry pick of #8238: fix: ldap sync not update user's phone and email
2020-10-12 11:54:19 +08:00
Zexi Li
d0d3d8e333 baremetal: fix pxe filter network by guest_dhcp 2020-10-12 11:36:56 +08:00
wanyaoqi
dee1aa26dc genreate api models 2020-10-12 10:45:50 +08:00
wanyaoqi
c973bf1632 add interface freeze virtual resource 2020-10-12 10:45:50 +08:00
Qiu Jian
1aa82ae950 fix: ldap sync not update user's phone and email 2020-10-11 05:44:53 +08:00
Qiu Jian
488e7e56a6 fix: not clean pending domain usage 2020-10-11 04:37:04 +08:00
yunion-ci-robot
6a2ebdc123 Merge pull request #8195 from rainzm/automated-cherry-pick-of-#8194-upstream-release-3.4
Automated cherry pick of #8194: fix(esxi): check nil value when NewVirtualMachine
2020-10-10 19:10:17 +08:00
yunion-ci-robot
4105284718 Merge pull request #8217 from tb365/automated-cherry-pick-of-#8214-upstream-release-3.4
Automated cherry pick of #8214: remove aws lbbg cache metedata
2020-10-10 18:55:20 +08:00
yunion-ci-robot
ac5f29bc0c Merge pull request #8226 from zhaoxiangchun/automated-cherry-pick-of-#8213-upstream-release-3.4
Automated cherry pick of #8213: bugfix:scoperesource FilterByOwner
2020-10-10 17:11:18 +08:00
zhaoxiangchun
58d52d947c Add web url to alarm template 2020-10-10 16:24:29 +08:00
zhaoxiangchun
c5ef564d35 bugfix:scoperesource FilterByOwner
1.调度标签 和 优化建议 FilterByOwner 逻辑调整
2020-10-10 16:24:29 +08:00
yunion-ci-robot
1cacf1068f Merge pull request #8219 from yousong/automated-cherry-pick-of-#8218-upstream-release-3.4
Automated cherry pick of #8218: webconsole: ssh: each argument on its own line
2020-10-10 15:34:49 +08:00
Yousong Zhou
63b0d0c071 webconsole: ssh: add keyboard-interactive as an option
For ESXi 6.0

  Authentications that can continue: publickey,keyboard-interactive
2020-10-10 14:43:39 +08:00
Yousong Zhou
39a45229af webconsole: ssh: each argument on its own line 2020-10-10 14:43:39 +08:00
TangBin
e82cf184f1 remove aws lbbg cache metedata 2020-10-10 14:28:27 +08:00
yunion-ci-robot
afa16944c0 Merge pull request #8211 from ioito/automated-cherry-pick-of-#8210-upstream-release-3.4
Automated cherry pick of #8210: fix: validate secgroup purge condition
2020-10-10 14:02:15 +08:00
yunion-ci-robot
8f953e41da Merge pull request #8200 from rainzm/automated-cherry-pick-of-#8199-upstream-release-3.4
Automated cherry pick of #8199: fix(esxi): check whether some fields of vm are nil
2020-10-10 12:53:09 +08:00
yunion-ci-robot
6e0180656d Merge pull request #8208 from ioito/automated-cherry-pick-of-#8207-upstream-release-3.4
Automated cherry pick of #8207: fix: qcloud set hostname for instance
2020-10-10 12:08:09 +08:00
yunion-ci-robot
718bf0d537 Merge pull request #8184 from yousong/automated-cherry-pick-of-#8183-upstream-release-3.4
Automated cherry pick of #8183: vpcagent: ovn: increase dhcp lease, renew, rebind time
2020-10-10 11:56:13 +08:00
Qu Xuan
9fbd4f0599 fix: validate secgroup purge condition 2020-10-10 11:54:38 +08:00
rainzm
078b1d635a fix: avoid slice out of bounds 2020-10-10 11:52:06 +08:00
rainzm
b8e0599e3f fix(esxi): filter linkLocalAddress 2020-10-10 11:52:06 +08:00
rainzm
27bd564d2d fix(esxi): check whether some fields of vm are nil 2020-10-10 11:52:06 +08:00
Qu Xuan
5b79ba5607 fix: qcloud set hostname for instance 2020-10-10 11:41:15 +08:00
yunion-ci-robot
c9d20d13f1 Merge pull request #8206 from swordqiu/automated-cherry-pick-of-#8205-upstream-release-3.4
Automated cherry pick of #8205: fix: filter cached images with host schedtag
2020-10-10 11:35:09 +08:00
yunion-ci-robot
779d4a9acf Merge pull request #8203 from swordqiu/automated-cherry-pick-of-#8202-upstream-release-3.4
Automated cherry pick of #8202: fix: server name auto index should start from 1
2020-10-10 11:35:04 +08:00
rainzm
1bc4b3cb90 fix(esxi): check nil value when NewVirtualMachine 2020-10-10 11:24:12 +08:00
Qiu Jian
49887e540a fix: filter cached images with host schedtag 2020-10-10 06:57:57 +08:00
Qiu Jian
7ce0d7b44b fix: server name auto index should start from 1 2020-10-10 06:26:31 +08:00
Qu Xuan
e8d737ff6c fix: avoid qcloud secgroup cache name not sync 2020-10-09 14:58:10 +08:00
yunion-ci-robot
fd954efcf2 Merge pull request #8177 from zhaoxiangchun/automated-cherry-pick-of-#8176-upstream-release-3.4
Automated cherry pick of #8176: modify suggest rule cli
2020-10-09 10:35:01 +08:00
Yousong Zhou
e9415ae49e vpcagent: ovn: increase dhcp lease, renew, rebind time 2020-10-09 10:24:55 +08:00
yunion-ci-robot
5b0afbdc6b Merge pull request #8179 from swordqiu/automated-cherry-pick-of-#8178-upstream-release-3.4
Automated cherry pick of #8178: fix: error code of external bucket not found error should be 404
2020-10-09 09:13:00 +08:00
yunion-ci-robot
ec393a6e3c Merge pull request #8182 from swordqiu/automated-cherry-pick-of-#8181-upstream-release-3.4
Automated cherry pick of #8181: hotfix: 1. allow merge networks without continuous addresses 2. filter guest_ip_start and guest_ip_end with contains operator
2020-10-09 09:09:00 +08:00
Qiu Jian
adccad3487 hotfix: 1. allow merge networks without continuous addresses 2. filter guest_ip_start and guest_ip_end with contains operator 2020-10-07 23:32:32 +08:00
Qiu Jian
76f794d1a2 fix: error code of external bucket not found error should be 404 2020-09-30 18:01:44 +08:00
zhaoxiangchun
bba2cf23fd modify suggest rule cli
1.增加perform config方法,方便修改默认规则:执行周期,扫描窗口的属性
2020-09-30 17:18:18 +08:00
290 changed files with 6085 additions and 1569 deletions

View File

@@ -38,7 +38,7 @@ jobs:
command: |
targets="$(circleci tests glob "cmd/*" | grep -v cmd/host-image | circleci tests split)"
echo $targets | tr ' ' '\n'
make -j3 $targets
make -j2 $targets
ls -lh _output/bin/
- save_cache:
key: onecloud-build-cache-{{ checksum "go.mod" }}-{{ checksum "Makefile" }}

View File

@@ -314,6 +314,7 @@ VERSION ?= $(shell git describe --exact-match 2> /dev/null || \
git describe --match=$(git rev-parse --short=8 HEAD) --always --dirty --abbrev=8)
image:
mkdir -p $(ROOT_DIR)/_output
DEBUG=$(DEBUG) ARCH=$(ARCH) TAG=$(VERSION) REGISTRY=$(REGISTRY) $(ROOT_DIR)/scripts/docker_push.sh $(filter-out $@,$(MAKECMDGOALS))
.PHONY: image

View File

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

View File

@@ -0,0 +1,3 @@
FROM registry.cn-beijing.aliyuncs.com/yunionio/yunion-rootfs:v1.0
ADD ./_output/bin/telegraf-raid-plugin /opt/yunion/bin/telegraf-raid-plugin

View File

@@ -1,6 +1,7 @@
## {{.title}}
- 时间: {{.start_time}}
- 级别: {{.level}}
- 详情地址: {{.web_url}}/commonalerts
{{ range .matches}}
- 指标: {{.metric}}

View File

@@ -1,6 +1,7 @@
## {{.title}}
- Time: {{.start_time}}
- Level: {{.level}}
- WebUrl: {{.web_url}}/commonalerts
{{ range .matches}}
- Metric: {{.metric}}

View File

@@ -28,6 +28,7 @@ import (
type BaseOptions struct {
Debug bool `help:"debug mode"`
Help bool `help:"Show help"`
CloudEnv string `help:"Cloud environment" default:"$ALIYUN_CLOUD_ENV" choices:"InternationalCloud|FinanceCloud" metavar:"ALIYUN_CLOUD_ENV"`
AccessKey string `help:"Access key" default:"$ALIYUN_ACCESS_KEY" metavar:"ALIYUN_ACCESS_KEY"`
Secret string `help:"Secret" default:"$ALIYUN_SECRET" metavar:"ALIYUN_SECRET"`
RegionId string `help:"RegionId" default:"$ALIYUN_REGION" metavar:"ALIYUN_REGION"`
@@ -86,7 +87,9 @@ func newClient(options *BaseOptions) (*aliyun.SRegion, error) {
cli, err := aliyun.NewAliyunClient(
aliyun.NewAliyunClientConfig(
options.AccessKey, options.Secret,
options.CloudEnv,
options.AccessKey,
options.Secret,
).Debug(options.Debug),
)
if err != nil {

View File

@@ -27,6 +27,9 @@ func init() {
Region string `help:"show images cached at cloud region"`
Zone string `help:"show images cached at zone"`
HostSchedtagId string `help:"filter cached image with host schedtag"`
Valid *bool `help:"valid cachedimage"`
}
R(&CachedImageListOptions{}, "cached-image-list", "List cached images", func(s *mcclient.ClientSession, args *CachedImageListOptions) error {
params, err := options.ListStructToParams(args)

View File

@@ -259,10 +259,10 @@ func init() {
params.Add(jsonutils.NewString(args.Desc), "description")
}
if args.CpuCommitBound > 0.0 {
params.Add(jsonutils.NewFloat(args.CpuCommitBound), "cpu_cmtbound")
params.Add(jsonutils.NewFloat64(args.CpuCommitBound), "cpu_cmtbound")
}
if args.MemoryCommitBound > 0.0 {
params.Add(jsonutils.NewFloat(args.MemoryCommitBound), "mem_cmtbound")
params.Add(jsonutils.NewFloat64(args.MemoryCommitBound), "mem_cmtbound")
}
if len(args.MemoryReserved) > 0 {
params.Add(jsonutils.NewString(args.MemoryReserved), "mem_reserved")

View File

@@ -83,6 +83,7 @@ func init() {
cmd.Perform("publicip-to-eip", new(options.ServerPublicipToEip))
cmd.Perform("set-auto-renew", new(options.ServerSetAutoRenew))
cmd.Perform("save-template", new(options.ServerSaveImageOptions))
cmd.Perform("remote-update", new(options.ServerRemoteUpdateOptions))
cmd.Get("vnc", new(options.ServerIdOptions))
cmd.Get("desc", new(options.ServerIdOptions))

View File

@@ -37,6 +37,7 @@ func init() {
Schedtag string `help:"filter storage by schedtag"`
HostSchedtagId string `help:"filter storage by host schedtag"`
ImageId string `help:"filter storage by image"`
}
R(&StorageListOptions{}, "storage-list", "List storages", func(s *mcclient.ClientSession, opts *StorageListOptions) error {
params, err := options.ListStructToParams(opts)

View File

@@ -284,10 +284,7 @@ type IPerformOpt interface {
func (cmd ResourceCmd) Perform(action string, args IPerformOpt) {
man := cmd.manager
callback := func(s *mcclient.ClientSession, args IPerformOpt) error {
params, err := args.Params()
if err != nil {
return err
}
params := jsonutils.Marshal(args) // .Params()
ret, err := man.(modulebase.Manager).PerformAction(s, args.GetId(), action, params)
if err != nil {
return err
@@ -488,7 +485,7 @@ func (cmd JointCmd) List(args IJointListOpt) {
if len(args.GetMasterOpt()) > 0 {
result, err = man.ListDescendent(s, args.GetMasterOpt(), params)
} else if len(args.GetSlaveOpt()) > 0 {
result, err = man.ListDescendent2(s, args.GetMasterOpt(), params)
result, err = man.ListDescendent2(s, args.GetSlaveOpt(), params)
} else {
result, err = man.List(s, params)
}

View File

@@ -37,11 +37,13 @@ func init() {
RoleDomain string `help:"Domain for role"`
Limit int64 `help:"maximal returned number of rows"`
Offset int64 `help:"offset index of returned results"`
Users []string `help:"fitler by users id or name"`
Groups []string `help:"fitler by users id or name"`
Roles []string `help:"fitler by users id or name"`
Projects []string `help:"fitler by users id or name"`
Domains []string `help:"fitler by users id or name"`
Users []string `help:"fitler by user id or name"`
Groups []string `help:"fitler by group id or name"`
Roles []string `help:"fitler by role id or name"`
Projects []string `help:"fitler by project id or name"`
Domains []string `help:"fitler by domain id or name"`
ProjectDomains []string `help:"filter by project's domain id or name"`
}
R(&RoleAssignmentsOptions{}, "role-assignments", "List all role assignments", func(s *mcclient.ClientSession, args *RoleAssignmentsOptions) error {
query := jsonutils.NewDict()
@@ -105,6 +107,9 @@ func init() {
if len(args.Domains) > 0 {
query.Add(jsonutils.NewStringArray(args.Domains), "domains")
}
if len(args.ProjectDomains) > 0 {
query.Add(jsonutils.NewStringArray(args.ProjectDomains), "project_domains")
}
if args.Limit > 0 {
query.Add(jsonutils.NewInt(args.Limit), "limit")
}

View File

@@ -15,7 +15,10 @@
package misc
import (
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
)
func init() {
@@ -25,4 +28,36 @@ func init() {
printObject(s.ToJson())
return nil
})
type FreezeResrouceOptions struct {
ID string `help:"ID of resource"`
Module string `help:"Resource module type, eg: servers, disks, networks"`
}
R(&FreezeResrouceOptions{}, "freeze-resource", "Freeze resource operation update and perform action except for unfreeze", func(s *mcclient.ClientSession, args *FreezeResrouceOptions) error {
mod, err := modulebase.GetModule(s, args.Module)
if err != nil {
return errors.Wrap(err, "failed get module")
}
obj, err := mod.PerformAction(s, args.ID, "freeze", nil)
if err != nil {
return err
}
printObject(obj)
return nil
})
type UnfreezeResrouceOptions struct {
ID string `help:"ID of resource"`
Module string `help:"Resource module type, eg: servers, disks, networks"`
}
R(&UnfreezeResrouceOptions{}, "unfreeze-resource", "Unfreeze resource", func(s *mcclient.ClientSession, args *UnfreezeResrouceOptions) error {
mod, err := modulebase.GetModule(s, args.Module)
if err != nil {
return errors.Wrap(err, "failed get module")
}
obj, err := mod.PerformAction(s, args.ID, "unfreeze", nil)
if err != nil {
return err
}
printObject(obj)
return nil
})
}

View File

@@ -0,0 +1,31 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package monitor
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.AlertResources)
cmd.List(new(options.AlertResourceListOptions))
cmd.Show(new(options.AlertResourceShowOptions))
cmd.BatchDelete(new(options.AlertResourceDeleteOptions))
jCmd := shell.NewJointCmd(monitor.AlertResourceAlert)
jCmd.List(new(options.AlertResourceAlertListOptions))
}

View File

@@ -12,5 +12,6 @@ func init() {
cmd.Show(new(options.CommonAlertShowOptions))
cmd.Perform("enable", &options.CommonAlertShowOptions{})
cmd.Perform("disable", &options.CommonAlertShowOptions{})
cmd.Delete(new(options.CommonAlertDeleteOptions))
cmd.BatchDelete(new(options.CommonAlertDeleteOptions))
cmd.Perform("config", &options.CommonAlertUpdateOptions{})
}

View File

@@ -15,70 +15,19 @@
package monitor
import (
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
"yunion.io/x/onecloud/cmd/climc/shell"
"yunion.io/x/onecloud/pkg/mcclient/modules"
options "yunion.io/x/onecloud/pkg/mcclient/options/monitor"
)
func init() {
aN := cmdN("suggestsysrule")
R(&options.SuggestRuleListOptions{}, aN("list"), "List all suggestsysrules",
func(s *mcclient.ClientSession, args *options.SuggestRuleListOptions) error {
params, err := args.Params()
if err != nil {
return err
}
ret, err := monitor.SuggestSysRuleManager.List(s, params)
if err != nil {
return err
}
printList(ret, monitor.SuggestSysRuleManager.GetColumns(s))
return nil
})
R(&options.SuggestRuleCreateOptions{}, aN("create"), "Create suggestsys rule",
func(s *mcclient.ClientSession, args *options.SuggestRuleCreateOptions) error {
params, err := args.Params()
if err != nil {
return err
}
ret, err := monitor.SuggestSysRuleManager.Create(s, params)
if err != nil {
return err
}
printObject(ret)
return nil
})
R(&options.SuggestRuleShowOptions{}, aN("show"), "Show details of a alert rule",
func(s *mcclient.ClientSession, args *options.SuggestRuleShowOptions) error {
ret, err := monitor.SuggestSysRuleManager.Get(s, args.ID, nil)
if err != nil {
return err
}
printObject(ret)
return nil
})
R(&options.SuggestRuleUpdateOptions{}, aN("update"), "Update a alert rule",
func(s *mcclient.ClientSession, args *options.SuggestRuleUpdateOptions) error {
params, err := args.Params()
if err != nil {
return err
}
ret, err := monitor.SuggestSysRuleManager.Update(s, args.ID, params)
if err != nil {
return err
}
printObject(ret)
return nil
})
R(&options.SuggestRuleDeleteOptions{}, aN("delete"), "Delete alerts",
func(s *mcclient.ClientSession, args *options.SuggestRuleDeleteOptions) error {
ret := monitor.SuggestSysRuleManager.BatchDelete(s, args.ID, nil)
printBatchResults(ret, monitor.SuggestSysRuleManager.GetColumns(s))
return nil
})
cmd := shell.NewResourceCmd(modules.SuggestSysRuleManager)
cmd.List(new(options.SuggestRuleListOptions))
cmd.Show(new(options.SuggestRuleShowOptions))
cmd.Perform("enable", new(options.SuggestRuleShowOptions))
cmd.Perform("disable", new(options.SuggestRuleShowOptions))
cmd.BatchDelete(new(options.CommonAlertDeleteOptions))
cmd.Perform("config", new(options.SuggestRuleConfigOptions))
}

View File

@@ -44,7 +44,7 @@ func main() {
err = fs.Serve(c, *fetcherFs)
if err != nil {
log.Errorln("serve failed %s", err)
log.Errorf("serve failed %s", err)
}
}

View File

@@ -33,7 +33,8 @@ type BaseOptions struct {
Host string `help:"SSH Host IP" default:"$RAID_HOST" metavar:"RAID_HOST"`
Username string `help:"Username, usually root" default:"$RAID_USERNAME" metavar:"RAID_USERNAME"`
Password string `help:"Password" default:"$RAID_PASSWORD" metavar:"RAID_PASSWORD"`
Driver string `help:"Password" default:"$RAID_DRIVER" metavar:"RAID_DRIVER" choices:"MegaRaid|HPSARaid|Mpt2SAS|MarvelRaid"`
Driver string `help:"Raid dirver" default:"$RAID_DRIVER" metavar:"RAID_DRIVER" choices:"MegaRaid|HPSARaid|Mpt2SAS|MarvelRaid"`
LocalHost bool `help:"Run raidcli in localhost"`
SUBCOMMAND string `help:"s3cli subcommand" subcommand:"true"`
}
@@ -83,43 +84,48 @@ func showErrorAndExit(e error) {
}
func newClient() (raid.IRaidDriver, error) {
if len(options.Host) == 0 {
return nil, fmt.Errorf("Missing host")
}
if len(options.Username) == 0 {
return nil, fmt.Errorf("Missing username")
}
if len(options.Password) == 0 {
return nil, fmt.Errorf("Missing password")
if options.Debug {
raid.Debug = true
}
if len(options.Driver) == 0 {
return nil, fmt.Errorf("Missing driver")
}
if options.Debug {
raid.Debug = true
var drv raid.IRaidDriver
if !options.LocalHost {
if len(options.Host) == 0 {
return nil, fmt.Errorf("Missing host")
}
if len(options.Username) == 0 {
return nil, fmt.Errorf("Missing username")
}
if len(options.Password) == 0 {
return nil, fmt.Errorf("Missing password")
}
sshClient, err := ssh.NewClient(
options.Host,
22,
options.Username,
options.Password,
"",
)
if err != nil {
return nil, fmt.Errorf("ssh client init fail: %s", err)
}
drv = drivers.GetDriver(options.Driver, sshClient)
if drv == nil {
return nil, fmt.Errorf("not supported driver %s", options.Driver)
}
} else {
drv = drivers.GetLocalDriver(options.Driver)
}
sshClient, err := ssh.NewClient(
options.Host,
22,
options.Username,
options.Password,
"",
)
if err != nil {
return nil, fmt.Errorf("ssh client init fail: %s", err)
}
drv := drivers.GetDriver(options.Driver, sshClient)
if drv == nil {
return nil, fmt.Errorf("not supported driver %s", options.Driver)
}
err = drv.ParsePhyDevs()
err := drv.ParsePhyDevs()
if err != nil {
return nil, fmt.Errorf("parse phyical devices error %s", err)
}

View File

@@ -0,0 +1,193 @@
package main
import (
"context"
"fmt"
"os"
"strings"
"time"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/baremetal/utils/detect_storages"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid/drivers"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/httputils"
)
const (
INTERVAL_SECOND = 300
TelegrafServer = "http://localhost:8087/write"
)
// Failed, Offline, Degraded, Rebuilding, Out of Sync (OSY)
func main() {
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
log.Fatalln(err)
}
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatalln(err)
}
nodeName := os.Getenv("NODENAME")
if len(nodeName) == 0 {
log.Fatalf("Missing env nodename")
}
node, err := clientset.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
if err != nil {
log.Fatalln(err)
}
var masterAddress string
if length := len(node.Status.Conditions); length > 0 {
if node.Status.Conditions[length-1].Type == v1.NodeReady &&
node.Status.Conditions[length-1].Status == v1.ConditionTrue {
for _, addr := range node.Status.Addresses {
if addr.Type == v1.NodeInternalIP {
masterAddress = addr.Address
break
}
}
}
}
log.Infof("Start Colloct Raid Info And Send To Telegraf ...")
c := NewRaidInfoCollector(nodeName, masterAddress, INTERVAL_SECOND)
c.Start()
}
type RaidInfoCollector struct {
waitingReportData []string
LastCollectTime time.Time
ReportInterval int // seconds
Hostname string
HostIp string
}
func NewRaidInfoCollector(hostname, hostIp string, interval int) *RaidInfoCollector {
return &RaidInfoCollector{
waitingReportData: make([]string, 0),
ReportInterval: interval,
Hostname: hostname,
HostIp: hostIp,
}
}
func (c *RaidInfoCollector) runMain() {
timeBegin := time.Now()
elapse := timeBegin.Sub(c.LastCollectTime)
if elapse < time.Second*time.Duration(c.ReportInterval) {
return
} else {
c.LastCollectTime = timeBegin
}
c.runMonitor()
}
func (c *RaidInfoCollector) runMonitor() {
reportData := c.collectReportData()
if len(reportData) > 0 {
c.reportRaidInfoToTelegraf(reportData)
}
}
func (c *RaidInfoCollector) collectReportData() string {
if len(c.waitingReportData) > 60 {
c.waitingReportData = c.waitingReportData[1:]
}
return c.CollectReportData()
}
func (c *RaidInfoCollector) CollectReportData() string {
raidDiskInfo := make([]*baremetal.BaremetalStorage, 0)
// raidDrivers := []string{}
for _, drv := range drivers.GetDrivers(drivers.NewExecutor()) {
if err := drv.ParsePhyDevs(); err != nil {
log.Warningf("Raid driver %s ParsePhyDevs failed: %s", drv.GetName(), err)
continue
}
raidDiskInfo = append(raidDiskInfo, detect_storages.GetRaidDevices(drv)...)
// raidDrivers = append(raidDrivers, drv.GetName())
}
if len(raidDiskInfo) > 0 {
ret := c.toTelegrafReportData(raidDiskInfo)
return ret
}
return ""
}
func (c *RaidInfoCollector) Start() {
for {
c.runMain()
time.Sleep(time.Second * 1)
}
}
const MEASUREMENT = "host_raid"
func (c *RaidInfoCollector) toTelegrafReportData(raidDiskInfo []*baremetal.BaremetalStorage) string {
tag := fmt.Sprintf("%s=%s,%s=%s", "hostname", c.Hostname, "host_ip", c.HostIp)
ret := []string{}
for i := 0; i < len(raidDiskInfo); i++ {
statArr := []string{}
raidDiskInfo[i].Status = strings.ToLower(raidDiskInfo[i].Status)
jStat := jsonutils.Marshal(raidDiskInfo[i])
jMap, _ := jStat.GetMap()
for k, v := range jMap {
statArr = append(statArr, fmt.Sprintf("%s=%s", k, v.String()))
}
stat := strings.Join(statArr, ",")
diskTag := fmt.Sprintf(
"%s,%s=%s,%s=%d,%s=%d", tag, "driver", raidDiskInfo[i].Driver,
"adapter", raidDiskInfo[i].Adapter, "slot", raidDiskInfo[i].Slot,
)
line := fmt.Sprintf("%s,%s %s", MEASUREMENT, diskTag, stat)
ret = append(ret, line)
}
return strings.Join(ret, "\n")
}
func (c *RaidInfoCollector) reportRaidInfoToTelegraf(data string) {
body := strings.NewReader(data)
res, err := httputils.Request(
httputils.GetDefaultClient(), context.Background(), "POST", TelegrafServer, nil, body, false)
if err != nil {
log.Errorf("Upload guest metric failed: %s", err)
return
}
defer res.Body.Close()
if res.StatusCode != 204 {
log.Errorf("upload guest metric failed %d", res.StatusCode)
timestamp := time.Now().UnixNano()
for _, line := range strings.Split(data, "\n") {
c.waitingReportData = append(c.waitingReportData,
fmt.Sprintf("%s %d", line, timestamp))
}
} else {
if len(c.waitingReportData) > 0 {
oldDatas := strings.Join(c.waitingReportData, "\n")
body = strings.NewReader(oldDatas)
res, err = httputils.Request(
httputils.GetDefaultClient(), context.Background(), "POST", TelegrafServer, nil, body, false)
if err == nil {
defer res.Body.Close()
}
if res.StatusCode == 204 {
c.waitingReportData = c.waitingReportData[len(c.waitingReportData):]
} else {
log.Errorf("upload guest metric failed code: %d", res.StatusCode)
}
}
}
}

4
go.mod
View File

@@ -141,12 +141,12 @@ require (
k8s.io/cluster-bootstrap v0.17.3
k8s.io/kubernetes v1.16.0
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74
yunion.io/x/jsonutils v0.0.0-20200814075449-927b118adbd8
yunion.io/x/jsonutils v0.0.0-20201014025429-7ce189228db6
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/sqlchemy v0.0.0-20200909073353-606d1fe76db5
yunion.io/x/sqlchemy v0.0.0-20201014101037-8fe75542e6d8
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce
)

8
go.sum
View File

@@ -1124,8 +1124,8 @@ vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74 h1:A15C6VdVRWvmQ9pAJHrUs9yan5qKlYH7uaRxHg1kRbk=
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
yunion.io/x/jsonutils v0.0.0-20200814075449-927b118adbd8 h1:KQVw5EmohJCqBDMdZ3fAcOQNNMIYgVuNCNWNwg4EM3A=
yunion.io/x/jsonutils v0.0.0-20200814075449-927b118adbd8/go.mod h1:p0nyMqGA/apTxxyLIU/o1k4V7Vujl2O6ey30L594sYE=
yunion.io/x/jsonutils v0.0.0-20201014025429-7ce189228db6 h1:RPpnTSCZwa9VQuWAf7S2dRjnZlYTIM0NH/j5vvUpk9g=
yunion.io/x/jsonutils v0.0.0-20201014025429-7ce189228db6/go.mod h1:p0nyMqGA/apTxxyLIU/o1k4V7Vujl2O6ey30L594sYE=
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d h1:59zrDL7Ft+hDukguJRmLr/Gdu/9V75x+yX99ovZwfaA=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
@@ -1139,7 +1139,7 @@ yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6 h1:UarEDTBGkgcgc+nc+PZ75uo9M9
yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6/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-20200909073353-606d1fe76db5 h1:Z1BoBr1LUEqQKJ5k+xTczj22OSiOvMxEN5BJrOQq7+g=
yunion.io/x/sqlchemy v0.0.0-20200909073353-606d1fe76db5/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/sqlchemy v0.0.0-20201014101037-8fe75542e6d8 h1:AkPrqO37Yi3aICys9qDjTlSdVVGh2pWQ8ET+dSJmhoI=
yunion.io/x/sqlchemy v0.0.0-20201014101037-8fe75542e6d8/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=

View File

@@ -447,6 +447,7 @@ type ServerCreateInput struct {
// 弹性公网IP带宽
// 指定此参数后会创建新的弹性公网IP并绑定到新建的虚拟机
// 此参数优先级低于public_ip
// 私有云不支持此参数
EipBw int `json:"eip_bw,omitzero"`
// 弹性公网IP计费类型
@@ -459,6 +460,25 @@ type ServerCreateInput struct {
// required: false
Eip string `json:"eip,omitempty"`
// 公网IP带宽(单位MB)
// 若指定此参数则忽略eip相关参数
// 私有云不支持此参数
//
//
// |平台 |支持范围 |
// |---- |------- |
// |腾讯云 |按量计费1-100, 包年包月1-200 |
PublicIpBw int `json:"public_ip_bw,omitzero"`
// 公网IP计费类型
// 默认按流量计费
//
//
// |类别 |说明 |
// |---- |------- |
// |traffic |按流量计费|
// |bandwidth |按带宽计费|
PublicIpChargeType string `json:"public_ip_charge_type,omitempty"`
// 使用主机快照创建虚拟机, 主机快照不会重置密码及秘钥信息
// 使用主机快照创建的虚拟机将沿用之前的密码秘钥及安全组信息
// required: false

View File

@@ -367,7 +367,8 @@ type CAGuestNet struct {
type CAIPNet struct {
// description: IP
IP string `json:"ip"`
IP string `json:"ip"`
VlanID int32 `json:"vlan_id"`
// description: 合适的已有网络
SuitableNetwork string `json:"suitable_network,allowempty"`
}
@@ -377,6 +378,7 @@ type CASimpleNetConf struct {
GuestIpEnd string `json:"guest_ip_end"`
GuestIpMask int8 `json:"guest_ip_mask"`
GuestGateway string `json:"guest_gateway"`
VlanID int32 `json:"vlan_id"`
}
type CANetConf struct {

View File

@@ -71,6 +71,8 @@ const (
CLOUD_ACCESS_ENV_AZURE_CHINA = CLOUD_PROVIDER_AZURE
CLOUD_ACCESS_ENV_HUAWEI_GLOBAL = CLOUD_PROVIDER_HUAWEI + "-int"
CLOUD_ACCESS_ENV_HUAWEI_CHINA = CLOUD_PROVIDER_HUAWEI
CLOUD_ACCESS_ENV_ALIYUN_GLOBAL = CLOUD_PROVIDER_ALIYUN
CLOUD_ACCESS_ENV_ALIYUN_FINANCE = CLOUD_PROVIDER_ALIYUN + "-fin"
CLOUD_ACCESS_ENV_CTYUN_CHINA = CLOUD_PROVIDER_CTYUN
)

View File

@@ -98,6 +98,9 @@ type ServerListInput struct {
SrcMacCheck *bool `json:"src_mac_check"`
InstanceType []string `json:"instance_type"`
// 是否调度到宿主机上
WithHost *bool `json:"with_host"`
}
func (input *ServerListInput) AfterUnmarshal() {
@@ -409,3 +412,8 @@ type GuestAddSecgroupInput struct {
// | 其他 | 5 |
SecgroupIds []string `json:"secgroup_ids"`
}
type ServerRemoteUpdateInput struct {
// 是否覆盖替换所有标签
ReplaceTags *bool `json:"replace_tags" help:"replace all remote tags"`
}

View File

@@ -58,6 +58,12 @@ type CachedimageListInput struct {
// 镜像类型,可能值为: system(公有云公共镜像), customized(自定义镜像)
// example: system
ImageType []string `json:"image_type"`
// filter by host schedtag
HostSchedtagId string `json:"host_schedtag_id"`
// valid cachedimage
Valid *bool `json:"valid"`
}
type ExternalProjectListInput struct {

View File

@@ -187,6 +187,12 @@ type NetworkCreateInput struct {
// 是否加入自动分配地址池
IsAutoAlloc *bool `json:"is_auto_alloc"`
// VlanId
VlanId *int `json:"vlan_id"`
// deprecated
Vlan *int `json:"vlan" yunion-deprecated-by:"vlan_id"`
}
type NetworkDetails struct {

View File

@@ -21,10 +21,10 @@ type SnapshotPolicyDetails struct {
SSnapshotPolicy
RetentionDays int `json:"retention_days"`
RepeatWeekdays []int `json:"repeat_weekdays"`
TimePoints []int `json:"time_points"`
IsActivated *bool `json:"is_activated,omitempty"`
RetentionDays int `json:"retention_days"`
RepeatWeekdaysDisplay []int `json:"repeat_weekdays_display"`
TimePointsDisplay []int `json:"time_points_display"`
IsActivated *bool `json:"is_activated,omitempty"`
BindingDiskCount int `json:"binding_disk_count"`
}

View File

@@ -81,6 +81,7 @@ const (
STORAGE_GOOGLE_LOCAL_SSD = "local-ssd" //本地SSD暂存盘 (最多8个)
STORAGE_GOOGLE_PD_STANDARD = "pd-standard" //标准永久性磁盘
STORAGE_GOOGLE_PD_SSD = "pd-ssd" //SSD永久性磁盘
STORAGE_GOOGLE_PD_BALANCED = "pd-balanced" //平衡永久性磁盘
// ctyun storage type
STORAGE_CTYUN_SSD = "SSD" // 超高IO云硬盘
@@ -186,4 +187,7 @@ type StorageListInput struct {
// filter by host schedtag
HostSchedtagId string `json:"host_schedtag_id"`
// filter by cachedimage
ImageId string `json:"image_id"`
}

View File

@@ -916,7 +916,8 @@ type SGuestTemplate struct {
// 计费方式
BillingType string `json:"billing_type"`
// 其他配置信息
Content interface{} `json:"content"`
Content interface{} `json:"content"`
LastCheckTime time.Time `json:"last_check_time"`
}
// SGuestTemplateResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestTemplateResourceBase.
@@ -925,20 +926,6 @@ type SGuestTemplateResourceBase struct {
GuestTemplateId string `json:"guest_template_id"`
}
// SGuestcdrom is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestcdrom.
type SGuestcdrom struct {
Id string `json:"id"`
// = Column(VARCHAR(36, charset='ascii'), primary_key=True)
ImageId string `json:"image_id"`
// Column(VARCHAR(36, charset='ascii'), nullable=True)
Name string `json:"name"`
// Column(VARCHAR(64, charset='ascii'), nullable=True)
Path string `json:"path"`
// Column(VARCHAR(256, charset='ascii'), nullable=True)
Size int64 `json:"size"`
UpdateVersion int `json:"update_version"`
}
// SGuestdisk is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestdisk.
type SGuestdisk struct {
SGuestJointsBase
@@ -1058,10 +1045,11 @@ type SHost struct {
OvnVersion string `json:"ovn_version"`
IsBaremetal bool `json:"is_baremetal"`
// 是否处于维护状态
IsMaintenance bool `json:"is_maintenance"`
EnableHealthCheck bool `json:"enable_health_check"`
ResourceType string `json:"resource_type"`
RealExternalId string `json:"real_external_id"`
IsMaintenance bool `json:"is_maintenance"`
LastPingAt time.Time `json:"last_ping_at"`
EnableHealthCheck bool `json:"enable_health_check"`
ResourceType string `json:"resource_type"`
RealExternalId string `json:"real_external_id"`
// 是否为导入的宿主机
IsImport bool `json:"is_import"`
// 是否允许PXE启动
@@ -1317,9 +1305,12 @@ type SLoadbalancerAgentDeployment struct {
// SLoadbalancerAgentParams is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerAgentParams.
type SLoadbalancerAgentParams struct {
KeepalivedConfTmpl string `json:"keepalived_conf_tmpl"`
HaproxyConfTmpl string `json:"haproxy_conf_tmpl"`
TelegrafConfTmpl string `json:"telegraf_conf_tmpl"`
KeepalivedConfTmpl string `json:"keepalived_conf_tmpl"`
HaproxyConfTmpl string `json:"haproxy_conf_tmpl"`
TelegrafConfTmpl string `json:"telegraf_conf_tmpl"`
Vrrp SLoadbalancerAgentParamsVrrp `json:"vrrp"`
Haproxy SLoadbalancerAgentParamsHaproxy `json:"haproxy"`
Telegraf SLoadbalancerAgentParamsTelegraf `json:"telegraf"`
}
// SLoadbalancerAgentParamsHaproxy is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerAgentParamsHaproxy.
@@ -1561,16 +1552,6 @@ type SManagedResourceBase struct {
ManagerId string `json:"manager_id"`
}
// SNatDEntry is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SNatDEntry.
type SNatDEntry struct {
SNatEntry
ExternalIP string `json:"external_ip"`
ExternalPort int `json:"external_port"`
InternalIP string `json:"internal_ip"`
InternalPort int `json:"internal_port"`
IpProtocol string `json:"ip_protocol"`
}
// SNatEntry is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SNatEntry.
type SNatEntry struct {
apis.SStatusInfrasResourceBase
@@ -1601,25 +1582,6 @@ type SNatgatewayResourceBase struct {
NatgatewayId string `json:"natgateway_id"`
}
// SNetInterface is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SNetInterface.
type SNetInterface struct {
Mac string `json:"mac"`
// Column(VARCHAR(36, charset='ascii'), primary_key=True)
BaremetalId string `json:"baremetal_id"`
// Column(VARCHAR(36, charset='ascii'), nullable=True)
WireId string `json:"wire_id"`
// Column(VARCHAR(36, charset='ascii'), nullable=True)
Rate int `json:"rate"`
// Column(Integer, nullable=True) # Mbps
NicType string `json:"nic_type"`
// Column(VARCHAR(36, charset='ascii'), nullable=True)
Index byte `json:"index"`
// Column(TINYINT, nullable=True)
LinkUp bool `json:"link_up"`
// Column(Boolean, nullable=True)
Mtu int16 `json:"mtu"`
}
// SNetwork is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SNetwork.
type SNetwork struct {
apis.SSharableVirtualResourceBase
@@ -1825,6 +1787,8 @@ type SScalingAlarm struct {
Value float64 `json:"value"`
// Real-time cumulate number
RealCumulate int `json:"real_cumulate"`
// Last trigger time
LastTriggerTime time.Time `json:"last_trigger_time"`
}
// SScalingGroup is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SScalingGroup.
@@ -1855,6 +1819,10 @@ type SScalingGroup struct {
HealthCheckGov int `json:"health_check_gov"`
LoadbalancerBackendPort int `json:"loadbalancer_backend_port"`
LoadbalancerBackendWeight int `json:"loadbalancer_backend_weight"`
// Time to allow scale
AllowScaleTime time.Time `json:"allow_scale_time"`
// NextCheckTime descripe the next time to check instance's health
NextCheckTime time.Time `json:"next_check_time"`
}
// SScalingGroupGuest is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SScalingGroupGuest.
@@ -2196,7 +2164,13 @@ type STimer struct {
WeekDays byte `json:"week_days"`
// 0-31 0 is unlimited
MonthDays uint32 `json:"month_days"`
IsExpired bool `json:"is_expired"`
// StartTime represent the start time of this timer
StartTime time.Time `json:"start_time"`
// EndTime represent deadline of this timer
EndTime time.Time `json:"end_time"`
// NextTime represent the time timer should bell
NextTime time.Time `json:"next_time"`
IsExpired bool `json:"is_expired"`
}
// SVCenter is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SVCenter.

View File

@@ -87,6 +87,8 @@ type RoleAssignmentsInput struct {
Projects []string `json:"projects"`
Domains []string `json:"domains"`
ProjectDomains []string `json:"project_domains"`
IncludeNames *bool `json:"include_names"`
Effective *bool `json:"effective"`
IncludeSubtree *bool `json:"include_subtree"`

View File

@@ -241,6 +241,12 @@ type PerformChangeProjectOwnerInput struct {
ProjectizedResourceInput
}
type PerformFreezeInput struct {
}
type PerformUnfreezeInput struct {
}
type PerformChangeDomainOwnerInput struct {
DomainizedResourceInput
}
@@ -326,6 +332,9 @@ type GetMetadataInput struct {
// | 外部标签 | key以ext:为前缀,为从其他平台同步过来的标签 |
//
Field []string `json:"field"`
// 按标签前缀过滤
Prefix string `json:"prefix"`
}
// 获取资源标签(元数据)输出

View File

@@ -195,8 +195,19 @@ type MetadataResourceListInput struct {
// 通过标签过滤
OrderByTag string `json:"order_by_tag"`
// 返回资源的标签不包含特定的用户标签
WithoutUserMeta bool `json:"without_user_meta"`
// deprecated
// 返回资源的标签不包含用户标签
WithoutUserMeta *bool `json:"without_user_meta"`
// 返回包含用户标签的资源
WithUserMeta *bool `json:"with_user_meta"`
// 返回包含外部标签的资源
WithCloudMeta *bool `json:"with_cloud_meta"`
// 返回包含任意标签的资源
WithAnyMeta *bool `json:"with_any_meta"`
// 返回列表数据中包含资源的标签数据Metadata
WithMeta *bool `json:"with_meta"`
}

View File

@@ -39,6 +39,6 @@ type AlertRecordRule struct {
// 比较运算符, 比如: >, <, >=, <=
Comparator string `json:"comparator"`
// 报警阀值
Threshold float64 `json:"threshold"`
Period string `json:"period"`
Threshold string `json:"threshold"`
Period string `json:"period"`
}

View File

@@ -0,0 +1,77 @@
// 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/onecloud/pkg/apis"
)
type AlertResourceType string
const (
// AlertResourceTypeNode means onecloud system infrastructure controller or host node
AlertResourceTypeNode AlertResourceType = "node"
// AlertResourceTypeCloudaccount means cloudaccount resource
AlertResourceTypeCloudaccount AlertResourceType = "cloudaccount"
// AlertResourceTypeVM means virtual machine guest resource
// AlertResourceTypeVM AlertResourceType = "vm"
)
type AlertResourceCreateInput struct {
apis.StandaloneResourceCreateInput
Type AlertResourceType `json:"type"`
}
type AlertResourceListInput struct {
apis.StandaloneResourceListInput
Type string `json:"type"`
}
type AlertResourceAttachInput struct {
apis.Meta
AlertResourceId string `json:"alert_resource_id"`
AlertId string `json:"alert_id"`
AlertRecordId string `json:"alert_record_id"`
Data EvalMatch `json:"data"`
}
type AlertResourceDetails struct {
apis.StandaloneResourceDetails
Count int `json:"count"`
Tags map[string]string `json:"tags"`
}
type AlertResourceAlertListInput struct {
apis.JointResourceBaseListInput
AlertResourceId string `json:"alert_resource_id"`
AlertId string `json:"alert_id"`
}
type AlertResourceJointBaseDetails struct {
apis.JointResourceBaseDetails
AlertResource string `json:"alert_resource"`
Type AlertResourceType `json:"type"`
}
type AlertResourceAlertDetails struct {
AlertResourceJointBaseDetails
Alert string `json:"alert"`
AlertType string `json:"alert_type"`
Level string `json:"level"`
CommonAlertMetricDetails []*CommonAlertMetricDetails `json:"common_alert_metric_details"`
}

View File

@@ -86,6 +86,8 @@ type CommonAlertUpdateInput struct {
Channel []string `json:"channel"`
// 通知接受者
Recipients []string `json:"recipients"`
// systemalert policy may need update through operator
ForceUpdate bool `json:"force_update"`
}
type CommonAlertDetails struct {
@@ -105,13 +107,14 @@ type CommonAlertMetricDetails struct {
Comparator string `json:"comparator"`
Threshold float64 `json:"threshold"`
// metric points'value的运算方式
Reduce string `json:"reduce"`
DB string `json:"db"`
Measurement string `json:"measurement"`
MeasurementDisplayName string `json:"measurement_display_name"`
ResType string `json:"res_type"`
Field string `json:"field"`
Groupby string `json:"groupby"`
Reduce string `json:"reduce"`
DB string `json:"db"`
Measurement string `json:"measurement"`
MeasurementDisplayName string `json:"measurement_display_name"`
ResType string `json:"res_type"`
Field string `json:"field"`
Groupby string `json:"groupby"`
Filters []MetricQueryTag `json:"filters"`
FieldDescription MetricFieldDetail
FieldOpt string `json:"field_opt"`
}

View File

@@ -41,8 +41,11 @@ type MetricFunc struct {
}
type MetricInputQuery struct {
From string `json:"from"`
To string `json:"to"`
From string `json:"from"`
To string `json:"to"`
Scope string `json:"scope"`
//default group by
Unit bool `json:"unit"`
Interval string `json:"interval"`
DomainId string `json:"domain_id"`
ProjectId string `json:"project_id"`

View File

@@ -70,10 +70,11 @@ type SAlertRecord struct {
apis.SEnabledResourceBase
apis.SStatusStandaloneResourceBase
apis.SScopedResourceBase
AlertId string `json:"alert_id"`
Level string `json:"level"`
State string `json:"state"`
EvalData interface{} `json:"eval_data"`
AlertId string `json:"alert_id"`
Level string `json:"level"`
State string `json:"state"`
EvalData interface{} `json:"eval_data"`
AlertRule interface{} `json:"alert_rule"`
}
// SAlertnotification is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertnotification.

View File

@@ -29,6 +29,7 @@ const (
FEISHU_ROBOT = "feishu-robot"
DINGTALK_ROBOT = "dingtalk-robot"
WORKWX_ROBOT = "workwx-robot"
WEBHOOK = "webhook"
ROBOT = "robot"
@@ -60,4 +61,7 @@ const (
TEMPLATE_TYPE_TITLE = "title"
TEMPLATE_TYPE_CONTENT = "content"
TEMPLATE_TYPE_REMOTE = "remote"
CTYPE_ROBOT_YES = "yes"
CTYPE_ROBOT_ONLY = "only"
)

View File

@@ -157,7 +157,7 @@ type ProjectizedResourceInfo struct {
// 资源归属项目的ID(向后兼容别名)
// Deprecated
TenantId string `json:"project_id" yunion-deprecated-by:"tenant"`
TenantId string `json:"project_id" yunion-deprecated-by:"tenant_id"`
// 资源归属项目的名称(向后兼容别名)
// Deprecated

View File

@@ -228,4 +228,6 @@ type SVirtualResourceBase struct {
PendingDeletedAt time.Time `json:"pending_deleted_at"`
// 资源是否处于回收站中
PendingDeleted bool `json:"pending_deleted"`
// 资源是否被冻结
Freezed bool `json:"freezed"`
}

View File

@@ -28,11 +28,11 @@ func doStatsHandler(stats *jsonutils.JSONArray, method, path string, hi, total *
s.Add(jsonutils.NewString(path), "path")
s.Add(jsonutils.NewString(hi.GetName(nil)), "name")
s.Add(jsonutils.NewInt(hi.counter2XX.hit), "hit.2XX")
s.Add(jsonutils.NewFloat(hi.counter2XX.duration), "duration.2XX")
s.Add(jsonutils.NewFloat64(hi.counter2XX.duration), "duration.2XX")
s.Add(jsonutils.NewInt(hi.counter4XX.hit), "hit.4XX")
s.Add(jsonutils.NewFloat(hi.counter4XX.duration), "duration.4XX")
s.Add(jsonutils.NewFloat64(hi.counter4XX.duration), "duration.4XX")
s.Add(jsonutils.NewInt(hi.counter5XX.hit), "hit.5XX")
s.Add(jsonutils.NewFloat(hi.counter5XX.duration), "duration.5XX")
s.Add(jsonutils.NewFloat64(hi.counter5XX.duration), "duration.5XX")
total.counter2XX.hit += hi.counter2XX.hit
total.counter2XX.duration += hi.counter2XX.duration
total.counter4XX.hit += hi.counter4XX.hit
@@ -56,10 +56,10 @@ func StatisticHandler(ctx context.Context, w http.ResponseWriter, r *http.Reques
result := jsonutils.NewDict()
result.Add(stats, "paths")
result.Add(jsonutils.NewInt(total.counter2XX.hit), "hit.2XX")
result.Add(jsonutils.NewFloat(total.counter2XX.duration), "duration.2XX")
result.Add(jsonutils.NewFloat64(total.counter2XX.duration), "duration.2XX")
result.Add(jsonutils.NewInt(total.counter4XX.hit), "hit.4XX")
result.Add(jsonutils.NewFloat(total.counter4XX.duration), "duration.4XX")
result.Add(jsonutils.NewFloat64(total.counter4XX.duration), "duration.4XX")
result.Add(jsonutils.NewInt(total.counter5XX.hit), "hit.5XX")
result.Add(jsonutils.NewFloat(total.counter5XX.duration), "duration.5XX")
result.Add(jsonutils.NewFloat64(total.counter5XX.duration), "duration.5XX")
fmt.Fprintf(w, result.String())
}

View File

@@ -269,6 +269,9 @@ func (req *dhcpRequest) findNetworkConf(session *mcclient.ClientSession, filterU
params.Add(jsonutils.NewString(
fmt.Sprintf("guest_dhcp.endswith(',%s')", req.RelayAddr)),
"filter.3")
params.Add(jsonutils.NewString(
fmt.Sprintf("guest_dhcp.equals(%s)", req.RelayAddr)),
"filter.4")
params.Add(jsonutils.JSONTrue, "filter_any")
}
params.Add(jsonutils.JSONTrue, "is_classic")

View File

@@ -24,7 +24,6 @@ import (
"yunion.io/x/onecloud/pkg/baremetal/utils/raid/drivers"
"yunion.io/x/onecloud/pkg/cloudcommon/types"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/ssh"
"yunion.io/x/onecloud/pkg/util/sysutils"
)
@@ -48,7 +47,7 @@ func GetRaidLogicVolumes(drv raid.IRaidDriver) ([]*raid.RaidLogicalVolume, error
return lvs, nil
}
func DetectStorageInfo(term *ssh.Client, wait bool) ([]*baremetal.BaremetalStorage, []*baremetal.BaremetalStorage, []*baremetal.BaremetalStorage, error) {
func DetectStorageInfo(term raid.IExecTerm, wait bool) ([]*baremetal.BaremetalStorage, []*baremetal.BaremetalStorage, []*baremetal.BaremetalStorage, error) {
raidDiskInfo := make([]*baremetal.BaremetalStorage, 0)
lvDiskInfo := make([]*raid.RaidLogicalVolume, 0)

View File

@@ -29,10 +29,9 @@ import (
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/mvcli"
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/sas2iru"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/ssh"
)
func GetDriver(name string, term *ssh.Client) raid.IRaidDriver {
func GetDriver(name string, term raid.IExecTerm) raid.IRaidDriver {
factory := raid.RaidDrivers[name]
if factory == nil {
return nil
@@ -40,7 +39,15 @@ func GetDriver(name string, term *ssh.Client) raid.IRaidDriver {
return factory(term)
}
func GetDriverWithInit(name string, term *ssh.Client) (raid.IRaidDriver, error) {
func GetLocalDriver(name string) raid.IRaidDriver {
factory := raid.RaidDrivers[name]
if factory == nil {
return nil
}
return factory(NewExecutor())
}
func GetDriverWithInit(name string, term raid.IExecTerm) (raid.IRaidDriver, error) {
drv := GetDriver(name, term)
if drv == nil {
return nil, errors.Errorf("Not found raid driver %q", name)
@@ -48,7 +55,7 @@ func GetDriverWithInit(name string, term *ssh.Client) (raid.IRaidDriver, error)
return drv, drv.ParsePhyDevs()
}
func GetDriverByKernelModule(module string, term *ssh.Client) (raid.IRaidDriver, error) {
func GetDriverByKernelModule(module string, term raid.IExecTerm) (raid.IRaidDriver, error) {
name := ""
switch module {
case raid.MODULE_MEGARAID:
@@ -64,7 +71,7 @@ func GetDriverByKernelModule(module string, term *ssh.Client) (raid.IRaidDriver,
return GetDriverWithInit(name, term)
}
func GetDrivers(term *ssh.Client) []raid.IRaidDriver {
func GetDrivers(term raid.IExecTerm) []raid.IRaidDriver {
ret := []raid.IRaidDriver{}
for _, factory := range raid.RaidDrivers {
ret = append(ret, factory(term))

View File

@@ -0,0 +1,56 @@
package drivers
import (
"bytes"
"fmt"
"io"
"os/exec"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/util/ssh"
)
type Executor struct{}
func (e *Executor) Run(cmds ...string) ([]string, error) {
return e.run(true, cmds, nil)
}
func (e *Executor) RunWithInput(input io.Reader, cmds ...string) ([]string, error) {
return e.run(true, cmds, input)
}
func (e *Executor) run(parseOutput bool, cmds []string, input io.Reader) ([]string, error) {
ret := []string{}
for _, cmd := range cmds {
log.Debugf("Run command: %s", cmd)
proc := exec.Command("sh", "-c", cmd)
var stdOut bytes.Buffer
var stdErr bytes.Buffer
proc.Stdout = &stdOut
proc.Stderr = &stdErr
proc.Stdin = input
if err := proc.Run(); err != nil {
var outputErr error
errMsg := stdErr.String()
if len(stdOut.String()) != 0 {
errMsg = fmt.Sprintf("%s %s", errMsg, stdOut.String())
}
outputErr = errors.Error(errMsg)
err = errors.Wrapf(outputErr, "%q error: %v, cmd error", cmd, err)
return nil, err
}
if parseOutput {
ret = append(ret, ssh.ParseOutput(stdOut.Bytes())...)
} else {
ret = append(ret, stdOut.String())
}
}
return ret, nil
}
func NewExecutor() *Executor {
return new(Executor)
}

View File

@@ -31,7 +31,6 @@ import (
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/regutils2"
"yunion.io/x/onecloud/pkg/util/ssh"
)
type HPSARaidPhyDev struct {
@@ -347,11 +346,11 @@ func (adapter *HPSARaidAdaptor) RemoveLogicVolumes() error {
}
type HPSARaid struct {
term *ssh.Client
term raid.IExecTerm
adapters []*HPSARaidAdaptor
}
func NewHPSARaid(term *ssh.Client) raid.IRaidDriver {
func NewHPSARaid(term raid.IExecTerm) raid.IRaidDriver {
return &HPSARaid{
term: term,
adapters: make([]*HPSARaidAdaptor, 0),

View File

@@ -15,6 +15,8 @@
package raid
import (
"io"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/baremetal"
)
@@ -41,3 +43,8 @@ type IRaidAdapter interface {
BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error
BuildNoneRaid(devs []*baremetal.BaremetalStorage) error
}
type IExecTerm interface {
Run(cmds ...string) ([]string, error)
RunWithInput(input io.Reader, cmds ...string) ([]string, error)
}

View File

@@ -27,10 +27,10 @@ import (
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
raiddrivers "yunion.io/x/onecloud/pkg/baremetal/utils/raid"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/regutils2"
"yunion.io/x/onecloud/pkg/util/ssh"
)
var (
@@ -320,7 +320,7 @@ func (adapter *MegaRaidAdaptor) GetIndex() int {
return adapter.index
}
func (adapter *MegaRaidAdaptor) getTerm() *ssh.Client {
func (adapter *MegaRaidAdaptor) getTerm() raid.IExecTerm {
return adapter.raid.term
}
@@ -376,7 +376,7 @@ func (adapter *MegaRaidAdaptor) parseLogicVolumes(lines []string) ([]*raiddriver
return lvs, nil
}
func getLogicVolumeDeviceById(hostNum, scsiId int, term *ssh.Client) (string, error) {
func getLogicVolumeDeviceById(hostNum, scsiId int, term raid.IExecTerm) (string, error) {
items, err := raiddrivers.SGMap(term)
if err != nil {
return "", err
@@ -892,13 +892,13 @@ func (adapter *MegaRaidAdaptor) clearJBODDisks() {
}
type MegaRaid struct {
term *ssh.Client
term raid.IExecTerm
adapters []*MegaRaidAdaptor
PhyDevsCnt int
Capacity int64
}
func NewMegaRaid(term *ssh.Client) raiddrivers.IRaidDriver {
func NewMegaRaid(term raid.IExecTerm) raiddrivers.IRaidDriver {
return &MegaRaid{
term: term,
adapters: make([]*MegaRaidAdaptor, 0),

View File

@@ -25,7 +25,6 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/ssh"
)
type MarvelRaidPhyDev struct {
@@ -243,11 +242,11 @@ func (adapter *MarvelRaidAdaptor) BuildNoneRaid(devs []*baremetal.BaremetalStora
}
type MarvelRaid struct {
term *ssh.Client
term raid.IExecTerm
adapters []*MarvelRaidAdaptor
}
func NewMarvelRaid(term *ssh.Client) raid.IRaidDriver {
func NewMarvelRaid(term raid.IExecTerm) raid.IRaidDriver {
return &MarvelRaid{
term: term,
adapters: make([]*MarvelRaidAdaptor, 0),

View File

@@ -24,7 +24,6 @@ import (
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/ssh"
"yunion.io/x/onecloud/pkg/util/sysutils"
)
@@ -45,7 +44,7 @@ const (
UnknownLogicalVolumeIndex = MaxInt
)
type RaidDriverFactory func(term *ssh.Client) IRaidDriver
type RaidDriverFactory func(term IExecTerm) IRaidDriver
type sRaidDrivers map[string]RaidDriverFactory
@@ -106,7 +105,7 @@ func (dev *RaidBasePhyDev) ToBaremetalStorage(index int) *baremetal.BaremetalSto
}
}
func GetModules(term *ssh.Client) []string {
func GetModules(term IExecTerm) []string {
ret := []string{}
lines, err := term.Run("/sbin/lsmod")
if err != nil {
@@ -142,7 +141,7 @@ type RaidLogicalVolume struct {
BlockDev string
}
func SGMap(term *ssh.Client) ([]compute.SGMapItem, error) {
func SGMap(term IExecTerm) ([]compute.SGMapItem, error) {
lines, err := term.Run("/usr/bin/sg_map -x")
if err != nil {
return nil, errors.Wrap(err, "run sg_map")

View File

@@ -26,7 +26,6 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
"yunion.io/x/onecloud/pkg/compute/baremetal"
"yunion.io/x/onecloud/pkg/util/ssh"
)
type Mpt2SASRaidPhyDev struct {
@@ -307,12 +306,12 @@ func (adapter *Mpt2SASRaidAdaptor) RemoveLogicVolumes() error {
}
type Mpt2SASRaid struct {
term *ssh.Client
term raid.IExecTerm
utility string
adapters []*Mpt2SASRaidAdaptor
}
func NewMpt2SASRaid(term *ssh.Client) raid.IRaidDriver {
func NewMpt2SASRaid(term raid.IExecTerm) raid.IRaidDriver {
return &Mpt2SASRaid{
term: term,
adapters: make([]*Mpt2SASRaidAdaptor, 0),

View File

@@ -30,6 +30,7 @@ type SEndpointChangeManager struct {
func newEndpointChangeManager() *SEndpointChangeManager {
man := &SEndpointChangeManager{}
man.InitSync(man)
man.FirstSync()
return man
}

View File

@@ -301,6 +301,7 @@ func FetchCustomizeColumns(
retVal := make([]*jsonutils.JSONDict, ret[0].Len())
for i := 0; i < ret[0].Len(); i += 1 {
jsonDict := ValueToJSONDict(ret[0].Index(i))
// NOTE: don't use obj update jsonDict as retval
jsonDict.Update(jsonutils.Marshal(objs[i]).(*jsonutils.JSONDict))
retVal[i] = jsonDict
}

View File

@@ -928,6 +928,12 @@ func (dispatcher *DBModelDispatcher) Get(ctx context.Context, idStr string, quer
if err != nil {
return nil, err
} else if data != nil {
if dataDict, ok := data.(*jsonutils.JSONDict); ok {
i18nDict := dispatcher.modelManager.GetI18N(ctx, idStr, data)
if i18nDict != nil {
dataDict.Set("_i18n", i18nDict)
}
}
return data, nil
}
@@ -1368,7 +1374,7 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
ret := make([]sCreateResult, len(multiData))
for i := range multiData {
var model IModel
model, err = batchCreateDoCreateItem(manager, ctx, userCred, ownerId, query, multiData[i], i)
model, err = batchCreateDoCreateItem(manager, ctx, userCred, ownerId, query, multiData[i], i+1)
if err == nil {
ret[i] = sCreateResult{model: model, err: nil}
} else {

View File

@@ -107,12 +107,7 @@ func (manager *SDomainizedResourceBaseManager) ListItemFilter(
) (*sqlchemy.SQuery, error) {
if len(query.ProjectDomainIds) > 0 {
// make sure ids are not utf8 string
idList := make([]string, 0)
for _, pid := range query.ProjectDomainIds {
if !stringutils2.IsUtf8(pid) {
idList = append(idList, pid)
}
}
idList := stringutils2.RemoveUtf8Strings(query.ProjectDomainIds)
tenants := TenantCacheManager.GetDomainQuery().SubQuery()
subq := tenants.Query(tenants.Field("id")).Filter(sqlchemy.OR(
sqlchemy.In(tenants.Field("id"), idList),

View File

@@ -127,6 +127,8 @@ type IModelManager interface {
QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error)
GetPagingConfig() *SPagingConfig
GetI18N(ctx context.Context, idstr string, resObj jsonutils.JSONObject) *jsonutils.JSONDict
}
type IModel interface {
@@ -246,6 +248,10 @@ type IMetadataBaseModelManager interface {
GetMetadataHiddenKeys() []string
}
type IMetadataBaseModel interface {
OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential)
}
type IStandaloneModelManager interface {
IResourceModelManager
@@ -282,6 +288,8 @@ type IStandaloneModel interface {
GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error)
IsShared() bool
IMetadataBaseModel
}
type IDomainLevelModelManager interface {

View File

@@ -26,7 +26,8 @@ func TestEctdLockManager(t *testing.T) {
shared := newSharedObject()
for i := 0; i < 4; i++ {
lockman, err := NewEtcdLockManager(&SEtcdLockManagerConfig{
Endpoints: []string{"localhost:2379"},
LockPrefix: "test-etcd-lock-manager",
Endpoints: []string{"localhost:2379"},
})
if err != nil {
t.Skipf("new etcd lockman: %v", err)

View File

@@ -492,6 +492,7 @@ func (manager *SMetadataManager) SetValues(ctx context.Context, obj IModel, stor
}
newRecord := SMetadata{}
newRecord.SetModelManager(manager, &newRecord)
newRecord.ObjId = obj.GetId()
newRecord.ObjType = obj.GetModelManager().Keyword()
@@ -585,13 +586,16 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
return nil
}
func (manager *SMetadataManager) GetAll(obj IModel, keys []string, userCred mcclient.TokenCredential) (map[string]string, error) {
func (manager *SMetadataManager) GetAll(obj IModel, keys []string, keyPrefix string, userCred mcclient.TokenCredential) (map[string]string, error) {
idStr := GetObjectIdstr(obj)
records := make([]SMetadata, 0)
q := manager.Query().Equals("id", idStr)
if keys != nil && len(keys) > 0 {
q = q.In("key", keys)
}
if len(keyPrefix) > 0 {
q = q.Startswith("key", keyPrefix)
}
err := FetchModelObjects(manager, q, &records)
if err != nil {
return nil, err

View File

@@ -70,10 +70,34 @@ func (meta *SMetadataResourceBaseModelManager) ListItemFilter(
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
}
if input.WithoutUserMeta {
if input.WithoutUserMeta != nil || input.WithUserMeta != nil {
metadatas := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
sq := metadatas.Query(metadatas.Field("obj_id")).Startswith("key", USER_TAG_PREFIX).Distinct().SubQuery()
q.Filter(sqlchemy.NotIn(q.Field("id"), sq))
if (input.WithoutUserMeta != nil && *input.WithoutUserMeta) || (input.WithUserMeta != nil && !*input.WithUserMeta) {
q = q.Filter(sqlchemy.NotIn(q.Field("id"), sq))
} else {
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
}
}
if input.WithCloudMeta != nil {
metadatas := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
sq := metadatas.Query(metadatas.Field("obj_id")).Startswith("key", CLOUD_TAG_PREFIX).Distinct().SubQuery()
if *input.WithCloudMeta {
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
} else {
q = q.Filter(sqlchemy.NotIn(q.Field("id"), sq))
}
}
if input.WithAnyMeta != nil {
metadatas := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
sq := metadatas.Query(metadatas.Field("obj_id")).Distinct().SubQuery()
if *input.WithAnyMeta {
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
} else {
q = q.Filter(sqlchemy.NotIn(q.Field("id"), sq))
}
}
return q

View File

@@ -359,14 +359,15 @@ func (manager *SModelBaseManager) GetPropertyDistinctField(ctx context.Context,
}
}
var res = jsonutils.NewDict()
q := im.Query()
q, err = ListItemQueryFilters(im, ctx, q, userCred, query, policy.PolicyActionList)
if err != nil {
return nil, err
}
var backupQuery = *q
var (
backupQuery = *q
res = jsonutils.NewDict()
)
// query field
for i := 0; i < len(fields); i++ {
var nq = backupQuery
@@ -424,6 +425,10 @@ func (manager *SModelBaseManager) OnCreateFailed(ctx context.Context, userCred m
return nil
}
func (manager *SModelBaseManager) GetI18N(ctx context.Context, idstr string, resObj jsonutils.JSONObject) *jsonutils.JSONDict {
return nil
}
func (model *SModelBase) GetId() string {
return ""
}

View File

@@ -91,6 +91,13 @@ func GenerateName(manager IModelManager, ownerId mcclient.IIdentityProvider, hin
return GenerateName2(manager, ownerId, hint, nil, 1)
}
func GenerateAlterName(model IModel, hint string) (string, error) {
if hint == model.GetName() {
return hint, nil
}
return GenerateName2(nil, nil, hint, model, 1)
}
func GenerateName2(manager IModelManager, ownerId mcclient.IIdentityProvider, hint string, model IModel, baseIndex int) (string, error) {
_, pattern, patternLen := stringutils.ParseNamePattern(hint)
var name string

View File

@@ -45,31 +45,29 @@ type SOpsLogManager struct {
type SOpsLog struct {
SModelBase
Id int64 `primary:"true" auto_increment:"true" list:"user"` // = Column(BigInteger, primary_key=True)
ObjType string `width:"40" charset:"ascii" nullable:"false" list:"user" create:"required"` // = Column(VARCHAR(40, charset='ascii'), nullable=False)
ObjId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'), nullable=False)
ObjName string `width:"128" charset:"utf8" nullable:"false" list:"user" create:"required"` //= Column(VARCHAR(128, charset='utf8'), nullable=False)
Action string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"required"` //= Column(VARCHAR(32, charset='ascii'), nullable=False)
Id int64 `primary:"true" auto_increment:"true" list:"user"`
ObjType string `width:"40" charset:"ascii" nullable:"false" list:"user" create:"required"`
ObjId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
ObjName string `width:"128" charset:"utf8" nullable:"false" list:"user" create:"required"`
Action string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"required"`
Notes string `charset:"utf8" list:"user" create:"required"`
ProjectId string `name:"tenant_id" width:"128" charset:"ascii" list:"user" create:"required" index:"true"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'))
Project string `name:"tenant" width:"128" charset:"utf8" list:"user" create:"required"` // tenant = Column(VARCHAR(128, charset='utf8'))
ProjectId string `name:"tenant_id" width:"128" charset:"ascii" list:"user" create:"optional" index:"true"`
Project string `name:"tenant" width:"128" charset:"utf8" list:"user" create:"optional"`
ProjectDomainId string `name:"project_domain_id" default:"default" width:"128" charset:"ascii" list:"user" create:"required"`
ProjectDomain string `name:"project_domain" default:"Default" width:"128" charset:"utf8" list:"user" create:"required"`
ProjectDomainId string `name:"project_domain_id" default:"default" width:"128" charset:"ascii" list:"user" create:"optional"`
ProjectDomain string `name:"project_domain" default:"Default" width:"128" charset:"utf8" list:"user" create:"optional"`
UserId string `width:"128" charset:"ascii" list:"user" create:"required"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'))
User string `width:"128" charset:"utf8" list:"user" create:"required"` // = Column(VARCHAR(128, charset='utf8'))
UserId string `width:"128" charset:"ascii" list:"user" create:"required"`
User string `width:"128" charset:"utf8" list:"user" create:"required"`
DomainId string `width:"128" charset:"ascii" list:"user" create:"optional"`
Domain string `width:"128" charset:"utf8" list:"user" create:"optional"`
Roles string `width:"64" charset:"ascii" list:"user" create:"optional"` // = Column(VARCHAR(64, charset='ascii'))
Roles string `width:"64" charset:"ascii" list:"user" create:"optional"`
// BillingType string `width:"64" charset:"ascii" default:"postpaid" list:"user" create:"user"` // billing_type = Column(VARCHAR(64, charset='ascii'), nullable=True)
OpsTime time.Time `nullable:"false" list:"user"` // = Column(DateTime, nullable=False)
OpsTime time.Time `nullable:"false" list:"user"`
OwnerDomainId string `name:"owner_domain_id" default:"default" width:"128" charset:"ascii" list:"user" create:"optional"`
OwnerProjectId string `name:"owner_tenant_id" width:"128" charset:"ascii" list:"user" create:"optional"` // = Column(VARCHAR(ID_LENGTH, charset='ascii'))
// owner_user_id = Column(VARCHAR(ID_LENGTH, charset='ascii'))
OwnerProjectId string `name:"owner_tenant_id" width:"128" charset:"ascii" list:"user" create:"optional"`
}
var OpsLog *SOpsLogManager
@@ -434,6 +432,7 @@ func (manager *SOpsLogManager) ValidateCreateData(ctx context.Context,
query jsonutils.JSONObject,
data apis.OpsLogCreateInput,
) (apis.OpsLogCreateInput, error) {
data.User = ownerId.GetUserName()
return data, nil
}

View File

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

View File

@@ -102,12 +102,7 @@ func (manager *SProjectizedResourceBaseManager) ListItemFilter(
}
if len(query.ProjectIds) > 0 {
// make sure ids are not utf8 string
idList := make([]string, 0)
for _, pid := range query.ProjectIds {
if !stringutils2.IsUtf8(pid) {
idList = append(idList, pid)
}
}
idList := stringutils2.RemoveUtf8Strings(query.ProjectIds)
tenants := TenantCacheManager.GetTenantQuery().SubQuery()
subq := tenants.Query(tenants.Field("id")).Filter(sqlchemy.OR(
sqlchemy.In(tenants.Field("id"), idList),

View File

@@ -33,6 +33,7 @@ var (
func init() {
quotaManagerTable = make(map[reflect.Type]IQuotaManager)
db.AddUsages = AddUsages
db.CancelUsages = CancelUsages
db.CancelPendingUsagesInContext = cancelPendingUsagesInContext
db.InitPendingUsagesInContext = initPendingUsagesInContext

View File

@@ -116,34 +116,8 @@ func (m *SScopedResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, userCred
}
switch scope {
case rbacutils.ScopeDomain:
/* q = q.Filter(sqlchemy.OR(
// share to system
sqlchemy.AND(
sqlchemy.IsNullOrEmpty(q.Field("domain_id")),
sqlchemy.IsNullOrEmpty(q.Field("tenant_id")),
),
// share to this domain or its sub-projects
sqlchemy.Equals(q.Field("domain_id"), userCred.GetProjectDomainId()),
)) */
q = q.Equals("domain_id", userCred.GetProjectDomainId())
case rbacutils.ScopeProject:
/* q = q.Filter(sqlchemy.OR(
// share to system
sqlchemy.AND(
sqlchemy.IsNullOrEmpty(q.Field("domain_id")),
sqlchemy.IsNullOrEmpty(q.Field("tenant_id")),
),
// share to project's parent domain
sqlchemy.AND(
sqlchemy.Equals(q.Field("domain_id"), userCred.GetProjectDomainId()),
sqlchemy.IsNullOrEmpty(q.Field("tenant_id")),
),
// share to this project
sqlchemy.AND(
sqlchemy.Equals(q.Field("domain_id"), userCred.GetProjectDomainId()),
sqlchemy.Equals(q.Field("tenant_id"), userCred.GetProjectId()),
),
)) */
q = q.Equals("tenant_id", userCred.GetProjectId())
}
return q

View File

@@ -266,36 +266,97 @@ func (model *SStandaloneResourceBase) GetMetadataJson(key string, userCred mccli
return Metadata.GetJsonValue(model, key, userCred)
}
func isUserMetadata(key string) bool {
return strings.HasPrefix(key, USER_TAG_PREFIX)
}
func containsUserMetadata(dict map[string]interface{}) bool {
for k := range dict {
if isUserMetadata(k) {
return true
}
}
return false
}
func (model *SStandaloneResourceBase) SetMetadata(ctx context.Context, key string, value interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetValue(ctx, model, key, value, userCred)
err := Metadata.SetValue(ctx, model, key, value, userCred)
if err != nil {
return errors.Wrap(err, "SetValue")
}
if isUserMetadata(key) {
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
}
return nil
}
func (model *SStandaloneResourceBase) SetAllMetadata(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
err := Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
if err != nil {
return errors.Wrap(err, "SetValuesWithLog")
}
if containsUserMetadata(dictstore) {
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
}
return nil
}
func (model *SStandaloneResourceBase) SetUserMetadataValues(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
err := Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
if err != nil {
return errors.Wrap(err, "SetValuesWithLog")
}
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
return nil
}
func (model *SStandaloneResourceBase) SetUserMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetAll(ctx, model, dictstore, userCred, USER_TAG_PREFIX)
err := Metadata.SetAll(ctx, model, dictstore, userCred, USER_TAG_PREFIX)
if err != nil {
return errors.Wrap(err, "SetAll")
}
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
return nil
}
func (model *SStandaloneResourceBase) SetCloudMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetAll(ctx, model, dictstore, userCred, CLOUD_TAG_PREFIX)
err := Metadata.SetAll(ctx, model, dictstore, userCred, CLOUD_TAG_PREFIX)
if err != nil {
return errors.Wrap(err, "SetAll")
}
return nil
}
func (model *SStandaloneResourceBase) RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error {
return Metadata.SetValue(ctx, model, key, "", userCred)
err := Metadata.SetValue(ctx, model, key, "", userCred)
if err != nil {
return errors.Wrap(err, "SetValue")
}
return nil
}
func (model *SStandaloneResourceBase) RemoveAllMetadata(ctx context.Context, userCred mcclient.TokenCredential) error {
return Metadata.RemoveAll(ctx, model, userCred)
err := Metadata.RemoveAll(ctx, model, userCred)
if err != nil {
return errors.Wrap(err, "RemoveAll")
}
return nil
}
func (model *SStandaloneResourceBase) GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error) {
return Metadata.GetAll(model, nil, userCred)
return Metadata.GetAll(model, nil, "", userCred)
}
func (model *SStandaloneResourceBase) GetAllUserMetadata() (map[string]string, error) {
meta, err := Metadata.GetAll(model, nil, USER_TAG_PREFIX, nil)
if err != nil {
return nil, errors.Wrap(err, "Metadata.GetAll")
}
ret := make(map[string]string)
for k, v := range meta {
ret[k[len(USER_TAG_PREFIX):]] = v
}
return ret, nil
}
func (model *SStandaloneResourceBase) AllowGetDetailsMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
@@ -304,10 +365,18 @@ func (model *SStandaloneResourceBase) AllowGetDetailsMetadata(ctx context.Contex
// 获取资源标签(元数据)
func (model *SStandaloneResourceBase) GetDetailsMetadata(ctx context.Context, userCred mcclient.TokenCredential, input apis.GetMetadataInput) (apis.GetMetadataOutput, error) {
val, err := Metadata.GetAll(model, input.Field, userCred)
val, err := Metadata.GetAll(model, input.Field, input.Prefix, userCred)
if err != nil {
return nil, errors.Wrap(err, "Metadata.GetAll")
}
if len(input.Prefix) > 0 {
// trim prefix from key
ret := make(map[string]string)
for k, v := range val {
ret[k[len(input.Prefix):]] = v
}
val = ret
}
return val, nil
}
@@ -510,3 +579,7 @@ func (model *SStandaloneResourceBase) ValidateUpdateData(ctx context.Context, us
func (model *SStandaloneResourceBase) IsShared() bool {
return false
}
func (model *SStandaloneResourceBase) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) {
// noop
}

View File

@@ -28,6 +28,8 @@ type IUsage interface {
var (
CancelUsages func(ctx context.Context, userCred mcclient.TokenCredential, usages []IUsage)
AddUsages func(ctx context.Context, userCred mcclient.TokenCredential, usages []IUsage)
CancelPendingUsagesInContext func(ctx context.Context, userCred mcclient.TokenCredential) error
InitPendingUsagesInContext func(ctx context.Context) context.Context

View File

@@ -64,6 +64,8 @@ type SVirtualResourceBase struct {
PendingDeletedAt time.Time `json:"pending_deleted_at" list:"user"`
// 资源是否处于回收站中
PendingDeleted bool `nullable:"false" default:"false" index:"true" get:"user" list:"user" json:"pending_deleted"`
// 资源是否被冻结
Freezed bool `nullable:"false" default:"false" get:"user" list:"user" json:"freezed"`
}
func (model *SVirtualResourceBase) IsOwner(userCred mcclient.TokenCredential) bool {
@@ -228,8 +230,21 @@ func (manager *SVirtualResourceBaseManager) FetchCustomizeColumns(
return ret
}
func (model *SVirtualResourceBase) PreCheckPerformAction(
ctx context.Context, userCred mcclient.TokenCredential,
action string, query jsonutils.JSONObject, data jsonutils.JSONObject,
) error {
if err := model.SStandaloneResourceBase.PreCheckPerformAction(ctx, userCred, action, query, data); err != nil {
return err
}
if model.Freezed && action != "unfreeze" {
return httperrors.NewBadRequestError("Virtual resource freezed, can't do %s", action)
}
return nil
}
func (model *SVirtualResourceBase) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return model.IsOwner(userCred) || IsAdminAllowUpdate(userCred, model)
return !model.Freezed && (model.IsOwner(userCred) || IsAdminAllowUpdate(userCred, model))
}
func (model *SVirtualResourceBase) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
@@ -253,6 +268,47 @@ func (model *SVirtualResourceBase) GetTenantCache(ctx context.Context) (*STenant
return TenantCacheManager.FetchTenantById(ctx, model.ProjectId)
}
func (model *SVirtualResourceBase) AllowPerformFreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformFreezeInput) bool {
return IsAdminAllowPerform(userCred, model, "freeze")
}
// freezed update and perform action operation except for unfreeze
func (model *SVirtualResourceBase) PerformFreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformFreezeInput) (jsonutils.JSONObject, error) {
if model.Freezed {
return nil, httperrors.NewBadRequestError("virtual resource already freezed")
}
_, err := Update(model, func() error {
model.Freezed = true
return nil
})
if err != nil {
return nil, err
}
OpsLog.LogEvent(model, ACT_FREEZE, "perform freeze", userCred)
logclient.AddActionLogWithContext(ctx, model, logclient.ACT_FREEZE, "perform freeze", userCred, true)
return nil, nil
}
func (model *SVirtualResourceBase) AllowPerformUnfreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformUnfreezeInput) bool {
return IsAdminAllowPerform(userCred, model, "unfreeze")
}
func (model *SVirtualResourceBase) PerformUnfreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformUnfreezeInput) (jsonutils.JSONObject, error) {
if !model.Freezed {
return nil, httperrors.NewBadRequestError("virtual resource not freezed")
}
_, err := Update(model, func() error {
model.Freezed = false
return nil
})
if err != nil {
return nil, err
}
OpsLog.LogEvent(model, ACT_UNFREEZE, "perform unfreeze", userCred)
logclient.AddActionLogWithContext(ctx, model, logclient.ACT_UNFREEZE, "perform unfreeze", userCred, true)
return nil, nil
}
func (model *SVirtualResourceBase) AllowPerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) bool {
return IsAdminAllowPerform(userCred, model, "change-owner")
}
@@ -393,11 +449,21 @@ func (model *SVirtualResourceBase) AllowPerformCancelDelete(ctx context.Context,
func (model *SVirtualResourceBase) PerformCancelDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if model.PendingDeleted && !model.Deleted {
err := model.DoCancelPendingDelete(ctx, userCred)
return nil, err
if err != nil {
return nil, errors.Wrap(err, "model.DoCancelPendingDelete")
}
model.RecoverUsages(ctx, userCred)
}
return nil, nil
}
func (model *SVirtualResourceBase) RecoverUsages(ctx context.Context, userCred mcclient.TokenCredential) {
usages := model.GetIModel().GetUsages()
if AddUsages != nil && len(usages) > 0 {
AddUsages(ctx, userCred, usages)
}
}
func (model *SVirtualResourceBase) DoCancelPendingDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
err := model.CancelPendingDelete(ctx, userCred)
if err == nil {
@@ -416,7 +482,10 @@ func (model *SVirtualResourceBase) GetIVirtualModel() IVirtualModel {
func (model *SVirtualResourceBase) CancelPendingDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
if model.PendingDeleted && !model.Deleted {
return model.MarkCancelPendingDelete(ctx, userCred)
err := model.MarkCancelPendingDelete(ctx, userCred)
if err != nil {
return errors.Wrap(err, "MarkCancelPendingDelete")
}
}
return nil
}

View File

@@ -14,6 +14,13 @@
package notifyclient
import (
"fmt"
"strings"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
)
const (
SYSTEM_ERROR = "SYSTEM_ERROR"
SYSTEM_WARNING = "SYSTEM_WARNING"
@@ -28,3 +35,42 @@ const (
IMAGE_ACTIVED = "IMAGE_ACTIVED"
)
type SAction string
var (
Event SEvent
ActionCreate SAction = "create"
ActionUpdate SAction = "update"
ActionDelete SAction = "delete"
ActionRebuildRoot SAction = "rebuild_root"
ActionChangeConfig SAction = "change_config"
)
type SEvent struct {
resourceType string
action SAction
}
func (se SEvent) WithResourceType(manager db.IModelManager) SEvent {
se.resourceType = manager.Keyword()
return se
}
func (se SEvent) WithAction(a SAction) SEvent {
se.action = a
return se
}
func (se SEvent) ResourceType() string {
return se.resourceType
}
func (se SEvent) Action() string {
return string(se.action)
}
func (se SEvent) String() string {
return strings.ToUpper(fmt.Sprintf("%s_%s", se.ResourceType(), se.Action()))
}

View File

@@ -20,6 +20,7 @@ import (
"html/template"
"io/ioutil"
"path/filepath"
"regexp"
"strings"
"sync"
"time"
@@ -29,12 +30,15 @@ import (
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/i18n"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
"yunion.io/x/onecloud/pkg/mcclient/modules"
npk "yunion.io/x/onecloud/pkg/mcclient/modules/notify"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
var (
@@ -97,6 +101,9 @@ func getTemplate(ctx context.Context, topic string, contType string, channel npk
}
func getContent(ctx context.Context, topic string, contType string, channel npk.TNotifyChannel, data jsonutils.JSONObject) (string, error) {
if channel == npk.NotifyByWebhook {
return "", nil
}
tmpl, err := getTemplate(ctx, topic, contType, channel)
if err != nil {
return "", err
@@ -110,6 +117,23 @@ func getContent(ctx context.Context, topic string, contType string, channel npk.
return buf.String(), nil
}
func NotifyWebhook(ctx context.Context, userCred mcclient.TokenCredential, obj db.IModel, action SAction) error {
ret, err := db.FetchCustomizeColumns(obj.GetModelManager(), ctx, userCred, jsonutils.NewDict(), []interface{}{obj}, stringutils2.SSortedStrings{}, false)
if err != nil {
return err
}
if len(ret) == 0 {
return fmt.Errorf("unable to get details for model %q", obj.GetId())
}
event := Event.WithAction(action).WithResourceType(obj.GetModelManager())
msg := jsonutils.NewDict()
msg.Set("resource_type", jsonutils.NewString(event.ResourceType()))
msg.Set("action", jsonutils.NewString(event.Action()))
msg.Set("resource_details", ret[0])
RawNotifyWithCtx(ctx, []string{}, false, npk.NotifyByWebhook, npk.NotifyPriorityNormal, event.String(), msg)
return nil
}
func NotifyWithCtx(ctx context.Context, recipientId []string, isGroup bool, priority npk.TNotifyPriority, event string, data jsonutils.JSONObject) {
notify(ctx, recipientId, isGroup, priority, event, data)
}
@@ -137,7 +161,16 @@ func RawNotify(recipientId []string, isGroup bool, channel npk.TNotifyChannel, p
rawNotify(context.Background(), recipientId, isGroup, channel, priority, event, data)
}
func rawNotify(ctx context.Context, recipientId []string, isGroup bool, channel npk.TNotifyChannel, priority npk.TNotifyPriority, event string, data jsonutils.JSONObject) {
// IntelliNotify try to create receiver nonexistent if createReceiver is set to true
func IntelliNotify(ctx context.Context, recipientId []string, isGroup bool, channel npk.TNotifyChannel, priority npk.TNotifyPriority, event string, data jsonutils.JSONObject, createReceiver bool) {
intelliNotify(ctx, recipientId, isGroup, channel, priority, event, data, createReceiver)
}
const noSuchReceiver = `no such receiver whose uid is '(.*)'`
var noSuchReceiverRegexp = regexp.MustCompile(noSuchReceiver)
func intelliNotify(ctx context.Context, recipientId []string, isGroup bool, channel npk.TNotifyChannel, priority npk.TNotifyPriority, event string, data jsonutils.JSONObject, createReceiver bool) {
log.Infof("notify %s event %s priority %s", recipientId, event, priority)
msg := npk.SNotifyMessage{}
if isGroup {
@@ -160,13 +193,46 @@ func rawNotify(ctx context.Context, recipientId []string, isGroup bool, channel
// log.Debugf("send notification %s %s", topic, body)
notifyClientWorkerMan.Run(func() {
s := auth.GetAdminSession(context.Background(), consts.GetRegion(), "")
err := npk.Notifications.Send(s, msg)
if err != nil {
log.Errorf("unable to send notification: %v", err)
for {
err := npk.Notifications.Send(s, msg)
if err == nil {
break
}
if !createReceiver {
log.Errorf("unable to send notification: %v", err)
break
}
jerr, ok := err.(*httputils.JSONClientError)
if !ok {
log.Errorf("unable to send notification: %v", err)
break
}
if jerr.Code > 500 {
log.Errorf("unable to send notification: %v", err)
break
}
match := noSuchReceiverRegexp.FindStringSubmatch(jerr.Details)
if match == nil || len(match) <= 1 {
log.Errorf("unable to send notification: %v", err)
break
}
receiverId := match[1]
createData := jsonutils.NewDict()
createData.Set("uid", jsonutils.NewString(receiverId))
_, err = modules.NotifyReceiver.Create(s, createData)
if err != nil {
log.Errorf("try to create receiver %q, but failed: %v", receiverId, err)
break
}
log.Infof("create receiver %q successfully", receiverId)
}
}, nil, nil)
}
func rawNotify(ctx context.Context, recipientId []string, isGroup bool, channel npk.TNotifyChannel, priority npk.TNotifyPriority, event string, data jsonutils.JSONObject) {
intelliNotify(ctx, recipientId, isGroup, channel, priority, event, data, false)
}
func NotifyNormal(recipientId []string, isGroup bool, event string, data jsonutils.JSONObject) {
notifyNormal(context.Background(), recipientId, isGroup, event, data)
}

View File

@@ -56,7 +56,7 @@ type SCloudaccountCredential struct {
// 秘钥key (Aliyun, Aws, huawei, ucloud, ctyun, zstack, s3)
AccessKeySecret string `json:"access_key_secret"`
// 环境 (Azure, Aws, huawei, ctyun)
// 环境 (Azure, Aws, huawei, ctyun, aliyun)
Environment string `json:"environment"`
// 目录ID (Azure)

View File

@@ -51,6 +51,7 @@ const (
CLOUD_CAPABILITY_EVENT = "event"
CLOUD_CAPABILITY_CLOUDID = "cloudid"
CLOUD_CAPABILITY_DNSZONE = "dnszone"
CLOUD_CAPABILITY_PUBLIC_IP = "public_ip"
)
const (

View File

@@ -14,6 +14,13 @@
package cloudprovider
type TElasticipChargeType string
var (
ElasticipChargeTypeByTraffic = TElasticipChargeType("traffic")
ElasticipChargeTypeByBandwidth = TElasticipChargeType("bandwidth")
)
type SEip struct {
Name string
BandwidthMbps int

View File

@@ -41,6 +41,11 @@ const (
CLOUD_EC2 = "ec2"
)
type SPublicIpInfo struct {
PublicIpBw int
PublicIpChargeType TElasticipChargeType
}
type SManagedVMCreateConfig struct {
Name string
ExternalImageId string
@@ -64,6 +69,10 @@ type SManagedVMCreateConfig struct {
UserData string
ProjectId string
SPublicIpInfo
Tags map[string]string
BillingCycle *billing.SBillingCycle
}

View File

@@ -317,6 +317,8 @@ type ICloudVM interface {
LiveMigrateVM(hostid string) error
GetError() error
SetMetadata(tags map[string]string, replace bool) error
}
type ICloudNic interface {

View File

@@ -23,6 +23,7 @@ import (
)
const DEFAULT_CLOUD_RULE_ID = "default_cloud_rule_id"
const DEFAULT_LOCAL_RULE_ID = "default_local_rule_id"
type SecurityGroupFilterOptions struct {
VpcId string
@@ -44,6 +45,42 @@ type SecurityRule struct {
ExternalId 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 (
@@ -112,13 +149,15 @@ func CompareRules(
defaultInRule, defaultOutRule SecurityRule,
onlyAllowRules bool, debug bool,
) (common, inAdds, outAdds, inDels, outDels []SecurityRule) {
localInRules := secrules.SecurityRuleSet{}
localOutRules := secrules.SecurityRuleSet{}
localInRules := LocalSecurityRuleSet{}
localOutRules := LocalSecurityRuleSet{}
for i := range localRules {
localRule := LocalSecurityRule{}
localRule.SecurityRule = localRules[i]
if localRules[i].Direction == secrules.DIR_IN {
localInRules = append(localInRules, localRules[i])
localInRules = append(localInRules, localRule)
} else {
localOutRules = append(localOutRules, localRules[i])
localOutRules = append(localOutRules, localRule)
}
}
inRules := SecurityRuleSet{}
@@ -132,17 +171,22 @@ func CompareRules(
}
var inCommon, outCommon = inRules, outRules
defaultLocalInRule := *secrules.MustParseSecurityRule("in:deny any")
defaultLocalOutRule := *secrules.MustParseSecurityRule("out:allow any")
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)
@@ -150,9 +194,26 @@ func CompareRules(
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 {
localInRules = localInAllowList
localOutRules = localOutAllowList
localOutRules, localInRules = _localOutRules, _localInRules
}
if len(_localInRules) < len(localInRules) {
localInRules = _localInRules
}
if len(_localOutRules) < len(localOutRules) {
localOutRules = _localOutRules
}
SortSecurityRule(inRules, order, onlyAllowRules)
@@ -199,7 +260,7 @@ func CompareRules(
return init
}
var compare = func(localRules secrules.SecurityRuleSet, remoteRules SecurityRuleSet) (common, add, del []SecurityRule) {
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) {
@@ -214,7 +275,11 @@ func CompareRules(
if remoteRules[j].ExternalId == DEFAULT_CLOUD_RULE_ID {
remoteRules[j].Priority = addPriority(remoteRules[j].Priority, order, 1, minPriority, maxPriority, onlyAllowRules)
}
common = append(common, remoteRules[j])
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])
}
i++
j++
} else if cmp < 0 {
@@ -225,7 +290,11 @@ func CompareRules(
} else {
initPriority := getInitPriority(prePriority, minPriority, maxPriority)
localRules[i].Priority = addPriority(initPriority, order, inc, minPriority, maxPriority, onlyAllowRules)
add = append(add, SecurityRule{SecurityRule: localRules[i]})
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})
}
i++
inc++
}
@@ -241,7 +310,11 @@ func CompareRules(
}
initPriority = getInitPriority(initPriority, minPriority, maxPriority) // 若是初始添加规则,尽量以中间为节点,避免仅出现天地规则
localRules[i].Priority = addPriority(initPriority, order, inc, minPriority, maxPriority, onlyAllowRules)
add = append(add, SecurityRule{SecurityRule: localRules[i]})
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})
}
i++
inc++
}
@@ -250,17 +323,17 @@ func CompareRules(
}
type rulePair struct {
localRules []secrules.SecurityRule
localRules LocalSecurityRuleSet
remoteRules []SecurityRule
protocol string
}
var splitRules = func(localRules []secrules.SecurityRule, remoteRules []SecurityRule) []rulePair {
var splitRules = func(localRules LocalSecurityRuleSet, remoteRules []SecurityRule) []rulePair {
rules := map[string]rulePair{}
for _, r := range localRules {
pair, ok := rules[r.Protocol]
if !ok {
pair = rulePair{localRules: []secrules.SecurityRule{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
pair = rulePair{localRules: LocalSecurityRuleSet{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
}
pair.localRules = append(pair.localRules, r)
rules[r.Protocol] = pair
@@ -269,7 +342,7 @@ func CompareRules(
for _, r := range remoteRules {
pair, ok := rules[r.Protocol]
if !ok {
pair = rulePair{localRules: []secrules.SecurityRule{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
pair = rulePair{localRules: LocalSecurityRuleSet{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
}
pair.remoteRules = append(pair.remoteRules, r)
rules[r.Protocol] = pair
@@ -282,7 +355,7 @@ func CompareRules(
return ret
}
var compareRules = func(localRules []secrules.SecurityRule, remoteRules []SecurityRule) (common, add, dels []SecurityRule) {
var compareRules = func(localRules LocalSecurityRuleSet, remoteRules []SecurityRule) (common, add, dels []SecurityRule) {
pairs := splitRules(localRules, remoteRules)
for _, r := range pairs {
_common, _add, _dels := compare(r.localRules, r.remoteRules)

View File

@@ -77,8 +77,8 @@ func (self *SAliyunGuestDriver) GetStorageTypes() []string {
}
}
func (self *SAliyunGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SAliyunGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SAliyunGuestDriver) GetDetachDiskStatus() ([]string, error) {

View File

@@ -131,8 +131,8 @@ func (self *SAwsGuestDriver) GetStorageTypes() []string {
}
}
func (self *SAwsGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SAwsGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SAwsGuestDriver) GetDetachDiskStatus() ([]string, error) {

View File

@@ -79,8 +79,8 @@ func (self *SAzureGuestDriver) GetStorageTypes() []string {
}
}
func (self *SAzureGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SAzureGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SAzureGuestDriver) GetMaxSecurityGroupCount() int {

View File

@@ -249,15 +249,15 @@ func (self *SBaremetalGuestDriver) GetStorageTypes() []string {
}
}
func (self *SBaremetalGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
func (self *SBaremetalGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
if len(storageIds) != 0 {
return models.StorageManager.FetchStorageById(storageIds[0])
return models.StorageManager.FetchStorageById(storageIds[0]), nil
}
bs := host.GetBaremetalstorage()
if bs == nil {
return nil
return nil, nil
}
return bs.GetStorage()
return bs.GetStorage(), nil
}
func (self *SBaremetalGuestDriver) RequestGuestCreateAllDisks(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
@@ -404,8 +404,8 @@ func (self *SBaremetalGuestDriver) ValidateCreateDataOnHost(ctx context.Context,
return input, nil
}
func (self *SBaremetalGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
return guest.GetJsonDescAtBaremetal(ctx, host)
func (self *SBaremetalGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, params *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
return guest.GetJsonDescAtBaremetal(ctx, host), nil
}
func (self *SBaremetalGuestDriver) GetGuestVncInfo(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) (*jsonutils.JSONDict, error) {

View File

@@ -270,6 +270,10 @@ func (self *SBaseGuestDriver) IsSupportEip() bool {
return false
}
func (self *SBaseGuestDriver) IsSupportPublicIp() bool {
return false
}
func (self *SBaseGuestDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, eip *models.SElasticip, task taskman.ITask) error {
return fmt.Errorf("SBaseGuestDriver: Not Implement RequestAssociateEip")
}
@@ -389,3 +393,8 @@ func (self *SBaseGuestDriver) RequestMigrate(ctx context.Context, guest *models.
func (self *SBaseGuestDriver) RequestLiveMigrate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, task taskman.ITask) error {
return fmt.Errorf("Not Implement RequestLiveMigrate")
}
func (self *SBaseGuestDriver) RequestRemoteUpdate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, replaceTags bool) error {
// nil ops
return nil
}

View File

@@ -148,8 +148,8 @@ func (self *SContainerDriver) RequestUndeployGuestOnHost(ctx context.Context, gu
return err
}
func (self *SContainerDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
return guest.GetJsonDescAtHypervisor(ctx, host)
func (self *SContainerDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, params *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
return guest.GetJsonDescAtHypervisor(ctx, host), nil
}
func (self *SContainerDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {

View File

@@ -79,6 +79,46 @@ func (self *SESXiGuestDriver) GetDefaultSysDiskBackend() string {
return api.STORAGE_LOCAL
}
func (self *SESXiGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
if !options.Options.LockStorageFromCachedimage || len(diskConfig.ImageId) == 0 {
return self.SVirtualizedGuestDriver.ChooseHostStorage(host, diskConfig, storageIds)
}
var (
image *cloudprovider.SImage
err error
)
obj, err := models.CachedimageManager.FetchById(diskConfig.ImageId)
if err != nil {
return nil, errors.Wrapf(err, "unable to fetch cachedimage %s", diskConfig.ImageId)
}
cachedimage := obj.(*models.SCachedimage)
if len(cachedimage.ExternalId) > 0 || cachedimage.ImageType != cloudprovider.CachedImageTypeSystem {
return self.SVirtualizedGuestDriver.ChooseHostStorage(host, diskConfig, storageIds)
}
storages, err := cachedimage.GetStorages()
if err != nil {
return nil, errors.Wrapf(err, "unable to GetStorages of cachedimage %s", diskConfig.ImageId)
}
if len(storages) == 0 {
log.Warningf("there no storage associated with cachedimage %q", image.Id)
return self.SVirtualizedGuestDriver.ChooseHostStorage(host, diskConfig, storageIds)
}
if len(storages) > 1 {
log.Warningf("there are multiple storageCache associated with caheimage %q", image.Id)
}
wantStorageIds := make([]string, len(storages))
for i := range wantStorageIds {
wantStorageIds[i] = storages[i].GetId()
}
for i := range wantStorageIds {
if utils.IsInStringArray(wantStorageIds[i], storageIds) {
log.Infof("use storage %q in where cachedimage %q", wantStorageIds[i], image.Id)
return &storages[i], nil
}
}
return self.SVirtualizedGuestDriver.ChooseHostStorage(host, diskConfig, storageIds)
}
func (self *SESXiGuestDriver) GetMinimalSysDiskSizeGb() int {
return options.Options.DefaultDiskSizeMB / 1024
}
@@ -153,49 +193,64 @@ type SEsxiImageInfo struct {
StorageCacheHostIp string
}
func (self *SESXiGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
func (self *SESXiGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, params *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
desc := guest.GetJsonDescAtHypervisor(ctx, host)
// add image_info
disks, _ := desc.GetArray("disks")
if len(disks) == 0 {
return desc
return desc, nil
}
templateId, _ := disks[0].GetString("template_id")
if len(templateId) == 0 {
return desc
return desc, nil
}
model, err := models.CachedimageManager.FetchById(templateId)
if err != nil {
log.Errorf("fail to Fetch cachedimage by '%s' in SESXiGuestDriver.GetJsonDescAtHost: %s", templateId, err)
return desc
return desc, errors.Wrapf(err, "CachedimageManager.FetchById(%s)", templateId)
}
img := model.(*models.SCachedimage)
if img.ImageType != cloudprovider.CachedImageTypeSystem {
return desc
return desc, nil
}
sciSubQ := models.StoragecachedimageManager.Query("storagecache_id").Equals("cachedimage_id", templateId).Equals("status", api.CACHED_IMAGE_STATUS_ACTIVE).SubQuery()
scQ := models.StoragecacheManager.Query().In("id", sciSubQ)
storageCaches := make([]models.SStoragecache, 0, 1)
err = db.FetchModelObjects(models.StoragecacheManager, scQ, &storageCaches)
if err != nil {
log.Errorf("fail to fetch storageCache associated with cacheimage '%s'", templateId)
return desc
return desc, errors.Wrapf(err, "fetch storageCache associated with cacheimage %s", templateId)
}
if len(storageCaches) == 0 {
log.Errorf("no such storage cache associated with cacheimage '%s'", templateId)
return desc
return desc, errors.Errorf("no such storage cache associated with cacheimage %s", templateId)
}
if len(storageCaches) > 1 {
log.Errorf("there are multiple storageCache associated with caheimage '%s' ??!!", templateId)
log.Warningf("there are multiple storageCache associated with caheimage '%s' ??!!", templateId)
}
var hostIp string
storageCacheHost, err := storageCaches[0].GetHost()
if err != nil {
log.Errorf("fail to GetHost of storageCache %s", storageCaches[0].Id)
hostIp = storageCaches[0].ExternalId
var storageCacheHost *models.SHost
// select storagecacheHost
for i := range storageCaches {
hosts, err := storageCaches[i].GetHosts()
if err != nil {
return desc, errors.Wrap(err, "storageCaches.GetHosts")
}
for i := range hosts {
if host.GetId() == hosts[i].GetId() {
storageCacheHost = &hosts[i]
}
}
}
hostIp = storageCacheHost.AccessIp
if storageCacheHost == nil {
storageCacheHost, err = storageCaches[0].GetHost()
if err != nil {
return desc, errors.Wrapf(err, "unable to GetHost of storageCache %s", storageCaches[0].Id)
}
if storageCacheHost == nil {
return desc, fmt.Errorf("unable to GetHost of storageCache %s: result is nil", storageCaches[0].Id)
}
}
hostIp := storageCacheHost.AccessIp
imageInfo := SEsxiImageInfo{
ImageType: img.ImageType,
ImageExternalId: img.ExternalId,
@@ -203,7 +258,7 @@ func (self *SESXiGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mc
}
dict := disks[0].(*jsonutils.JSONDict)
dict.Add(jsonutils.Marshal(imageInfo), "image_info")
return desc
return desc, nil
}
func (self *SESXiGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {

View File

@@ -77,12 +77,13 @@ func (self *SGoogleGuestDriver) GetStorageTypes() []string {
return []string{
api.STORAGE_GOOGLE_PD_SSD,
api.STORAGE_GOOGLE_PD_STANDARD,
api.STORAGE_GOOGLE_PD_BALANCED,
api.STORAGE_GOOGLE_LOCAL_SSD,
}
}
func (self *SGoogleGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SGoogleGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SGoogleGuestDriver) GetGuestInitialStateAfterCreate() string {
@@ -113,7 +114,7 @@ func (self *SGoogleGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *m
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
}
if !utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD}) {
if !utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED}) {
return fmt.Errorf("Cannot resize %s disk", storage.StorageType)
}
return nil
@@ -132,13 +133,15 @@ func (self *SGoogleGuestDriver) ValidateCreateData(ctx context.Context, userCred
minGB := -1
maxGB := -1
switch disk.Backend {
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD:
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED:
minGB = 10
maxGB = 65536
case api.STORAGE_GOOGLE_LOCAL_SSD:
minGB = 375
maxGB = 375
localDisk++
default:
return nil, httperrors.NewInputParameterError("Unknown google storage type %s", disk.Backend)
}
if i == 0 && disk.Backend == api.STORAGE_GOOGLE_LOCAL_SSD {
return nil, httperrors.NewInputParameterError("System disk does not support %s disk", disk.Backend)

View File

@@ -67,8 +67,8 @@ func (self *SHuaweiGuestDriver) GetStorageTypes() []string {
return []string{api.STORAGE_HUAWEI_SATA, api.STORAGE_HUAWEI_SAS, api.STORAGE_HUAWEI_SSD}
}
func (self *SHuaweiGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SHuaweiGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SHuaweiGuestDriver) GetDetachDiskStatus() ([]string, error) {

View File

@@ -234,8 +234,8 @@ func (self *SKVMGuestDriver) RequestUndeployGuestOnHost(ctx context.Context, gue
return nil
}
func (self *SKVMGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
return guest.GetJsonDescAtHypervisor(ctx, host)
func (self *SKVMGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, params *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
return guest.GetJsonDescAtHypervisor(ctx, host), nil
}
func (self *SKVMGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
@@ -267,7 +267,10 @@ func (self *SKVMGuestDriver) RequestStartOnHost(ctx context.Context, guest *mode
header := self.getTaskRequestHeader(task)
config := jsonutils.NewDict()
desc := guest.GetDriver().GetJsonDescAtHost(ctx, userCred, guest, host)
desc, err := guest.GetDriver().GetJsonDescAtHost(ctx, userCred, guest, host, nil)
if err != nil {
return nil, errors.Wrapf(err, "GetJsonDescAtHost")
}
config.Add(desc, "desc")
params := task.GetParams()
if params.Length() > 0 {
@@ -447,7 +450,10 @@ func (self *SKVMGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *mode
}
func (self *SKVMGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
desc := guest.GetDriver().GetJsonDescAtHost(ctx, task.GetUserCred(), guest, host)
desc, err := guest.GetDriver().GetJsonDescAtHost(ctx, task.GetUserCred(), guest, host, nil)
if err != nil {
return errors.Wrapf(err, "GetJsonDescAtHost")
}
body := jsonutils.NewDict()
body.Add(desc, "desc")
if fw_only, _ := task.GetParams().Bool("fw_only"); fw_only {
@@ -455,7 +461,7 @@ func (self *SKVMGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest
}
url := fmt.Sprintf("%s/servers/%s/sync", host.ManagerUri, guest.Id)
header := self.getTaskRequestHeader(task)
_, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
_, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
return err
}
@@ -496,13 +502,16 @@ func (self *SKVMGuestDriver) RequestRebuildRootDisk(ctx context.Context, guest *
func (self *SKVMGuestDriver) RequestSyncToBackup(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
host := guest.GetHost()
desc := guest.GetDriver().GetJsonDescAtHost(ctx, task.GetUserCred(), guest, host)
desc, err := guest.GetDriver().GetJsonDescAtHost(ctx, task.GetUserCred(), guest, host, nil)
if err != nil {
return errors.Wrapf(err, "GetJsonDescAtHost")
}
body := jsonutils.NewDict()
body.Add(desc, "desc")
body.Set("backup_nbd_server_uri", jsonutils.NewString(guest.GetMetadata("backup_nbd_server_uri", task.GetUserCred())))
url := fmt.Sprintf("%s/servers/%s/drive-mirror", host.ManagerUri, guest.Id)
header := self.getTaskRequestHeader(task)
_, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
_, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
if err != nil {
return err
}

View File

@@ -54,12 +54,15 @@ func (d SManagedVirtualizedGuestDriver) DoScheduleMemoryFilter() bool { return f
func (d SManagedVirtualizedGuestDriver) DoScheduleStorageFilter() bool { return false }
func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, params *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
config := cloudprovider.SManagedVMCreateConfig{}
config.Name = guest.Name
config.Cpu = int(guest.VcpuCount)
config.MemoryMB = guest.VmemSize
config.Description = guest.Description
if params != nil {
params.Unmarshal(&config.SPublicIpInfo)
}
config.InstanceType = guest.InstanceType
@@ -117,7 +120,7 @@ func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Contex
if guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
bc, err := billing.ParseBillingCycle(guest.BillingCycle)
if err != nil {
log.Errorf("fail to parse billing cycle %s: %s", guest.BillingCycle, err)
return nil, errors.Wrapf(err, "ParseBillingCycle(%s)", guest.BillingCycle)
}
if bc.IsValid() {
bc.AutoRenew = guest.AutoRenew
@@ -125,7 +128,7 @@ func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Contex
}
}
return jsonutils.Marshal(&config)
return jsonutils.Marshal(&config), nil
}
func (self *SManagedVirtualizedGuestDriver) RequestGuestCreateAllDisks(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
@@ -293,16 +296,18 @@ func (self *SManagedVirtualizedGuestDriver) RequestStartOnHost(ctx context.Conte
func (self *SManagedVirtualizedGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
config, err := guest.GetDeployConfigOnHost(ctx, task.GetUserCred(), host, task.GetParams())
if err != nil {
log.Errorf("GetDeployConfigOnHost error: %v", err)
return err
return errors.Wrapf(err, "GetDeployConfigOnHost")
}
log.Debugf("RequestDeployGuestOnHost: %s", config)
desc := cloudprovider.SManagedVMCreateConfig{}
if err := desc.GetConfig(config); err != nil {
return err
err = desc.GetConfig(config)
if err != nil {
return errors.Wrapf(err, "desc.GetConfig")
}
desc.Tags, _ = guest.GetAllUserMetadata()
//创建并同步安全组规则
{
vpc, err := guest.GetVpc()
@@ -447,10 +452,6 @@ func (self *SManagedVirtualizedGuestDriver) RemoteDeployGuestForCreate(ctx conte
}
db.SetExternalId(guest, userCred, iVM.GetGlobalId())
err = iVM.SetSecurityGroups(desc.ExternalSecgroupIds)
if err != nil {
log.Errorf("failed to set multi secgroup for instance %s error: %v", guest.Name, err)
}
if hostId := iVM.GetIHostId(); len(hostId) > 0 {
host, err := db.FetchByExternalIdAndManagerId(models.HostManager, hostId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
@@ -482,8 +483,12 @@ func (self *SManagedVirtualizedGuestDriver) RemoteDeployGuestForCreate(ctx conte
iVM, err = ihost.GetIVMById(iVM.GetGlobalId())
if err != nil {
log.Errorf("cannot find vm %s", err)
return nil, err
return nil, errors.Wrapf(err, "GetIVMById(%s)", iVM.GetGlobalId())
}
err = iVM.SetSecurityGroups(desc.ExternalSecgroupIds)
if err != nil {
return nil, errors.Wrapf(err, "SetSecurityGroups")
}
ret, expect := 0, len(desc.DataDisks)+1
@@ -1210,3 +1215,30 @@ func (self *SManagedVirtualizedGuestDriver) RequestSetAutoRenewInstance(ctx cont
})
return nil
}
func (self *SManagedVirtualizedGuestDriver) RequestRemoteUpdate(ctx context.Context, guest *models.SGuest, userCred mcclient.TokenCredential, replaceTags bool) error {
// nil ops
iVM, err := guest.GetIVM()
if err != nil {
return errors.Wrap(err, "guest.GetIVM")
}
tags, err := guest.GetAllUserMetadata()
if err != nil {
log.Errorf("GetAllUserMetadata fail %s", err)
} else {
err := iVM.SetMetadata(tags, replaceTags)
if err != nil {
return errors.Wrap(err, "iVM.SetMetadata")
}
// sync back cloud metadata
err = models.SyncVirtualResourceMetadata(ctx, userCred, guest, iVM)
if err != nil {
return errors.Wrap(err, "syncVirtualResourceMetadata")
}
}
err = iVM.UpdateVM(ctx, guest.Name)
if err != nil {
return errors.Wrap(err, "iVM.UpdateVM")
}
return nil
}

View File

@@ -91,8 +91,8 @@ func (self *SOpenStackGuestDriver) GetStorageTypes() []string {
return storages
}
func (self *SOpenStackGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SOpenStackGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SOpenStackGuestDriver) GetDetachDiskStatus() ([]string, error) {

View File

@@ -75,8 +75,8 @@ func (self *SQcloudGuestDriver) GetStorageTypes() []string {
}
}
func (self *SQcloudGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SQcloudGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SQcloudGuestDriver) GetDetachDiskStatus() ([]string, error) {
@@ -259,6 +259,10 @@ func (self *SQcloudGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle
return false
}
func (self *SQcloudGuestDriver) IsSupportPublicIp() bool {
return true
}
func (self *SQcloudGuestDriver) IsSupportPublicipToEip() bool {
return true
}

View File

@@ -174,11 +174,11 @@ func (self *SVirtualizedGuestDriver) GetStorageTypes() []string {
return nil
}
func (self *SVirtualizedGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
func (self *SVirtualizedGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
if len(storageIds) == 0 {
return host.GetLeastUsedStorage(backend)
return host.GetLeastUsedStorage(diskConfig.Backend), nil
}
return models.StorageManager.FetchStorageById(storageIds[0])
return models.StorageManager.FetchStorageById(storageIds[0]), nil
}
func (self *SVirtualizedGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, guest *models.SGuest, task taskman.ITask) error {

View File

@@ -85,8 +85,8 @@ func (self *SZStackGuestDriver) GetMaxSecurityGroupCount() int {
return 1
}
func (self *SZStackGuestDriver) ChooseHostStorage(host *models.SHost, backend string, storageIds []string) *models.SStorage {
return self.chooseHostStorage(self, host, backend, storageIds)
func (self *SZStackGuestDriver) ChooseHostStorage(host *models.SHost, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return self.chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SZStackGuestDriver) GetDetachDiskStatus() ([]string, error) {

View File

@@ -48,7 +48,7 @@ func (self *SGoogleHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb
minGB := 10
maxGB := -1
switch storage.StorageType {
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD:
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED:
maxGB = 65536
default:
return fmt.Errorf("Not support resize %s disk", storage.StorageType)

View File

@@ -716,11 +716,7 @@ func (bucket *SBucket) GetDetailsObjects(
}
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return output, httperrors.NewInvalidStatusError("%s", err)
} else {
return output, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return output, errors.Wrap(err, "GetIBucket")
}
prefix := input.Prefix
isRecursive := false
@@ -794,11 +790,7 @@ func (bucket *SBucket) PerformTempUrl(
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return output, httperrors.NewInvalidStatusError("%s", err)
} else {
return output, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return output, errors.Wrap(err, "GetIBucket")
}
tmpUrl, err := iBucket.GetTempUrl(method, key, time.Duration(expire)*time.Second)
if err != nil {
@@ -842,11 +834,7 @@ func (bucket *SBucket) PerformMakedir(
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return nil, httperrors.NewInvalidStatusError("%s", err)
} else {
return nil, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return nil, errors.Wrap(err, "GetIBucket")
}
_, err = cloudprovider.GetIObject(iBucket, key+"/")
@@ -913,11 +901,7 @@ func (bucket *SBucket) PerformDelete(
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return nil, httperrors.NewInvalidStatusError("%s", err)
} else {
return nil, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return nil, errors.Wrap(err, "GetIBucket")
}
ok := jsonutils.NewDict()
results := modulebase.BatchDo(keyStrs, func(key string) (jsonutils.JSONObject, error) {
@@ -977,11 +961,7 @@ func (bucket *SBucket) PerformUpload(
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return nil, httperrors.NewInvalidStatusError("%s", err)
} else {
return nil, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return nil, errors.Wrap(err, "GetIBucket")
}
meta := cloudprovider.FetchMetaFromHttpHeader(cloudprovider.META_HEADER_PREFIX, appParams.Request.Header)
@@ -1185,11 +1165,7 @@ func (bucket *SBucket) PerformSync(
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return nil, httperrors.NewInvalidStatusError("%s", err)
} else {
return nil, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return nil, errors.Wrap(err, "GetIBucket")
}
err = bucket.syncWithCloudBucket(ctx, userCred, iBucket, nil, statsOnly)
@@ -1233,11 +1209,7 @@ func (bucket *SBucket) GetDetailsAcl(
}
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return output, httperrors.NewInvalidStatusError("%s", err)
} else {
return output, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return output, errors.Wrap(err, "GetIBucket")
}
objKey := input.Key
var acl cloudprovider.TBucketACLType
@@ -1321,11 +1293,7 @@ func (bucket *SBucket) PerformLimit(
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return nil, httperrors.NewInvalidStatusError("%s", err)
} else {
return nil, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return nil, errors.Wrap(err, "GetIBucket")
}
err = iBucket.SetLimit(limit)
@@ -1438,11 +1406,7 @@ func (bucket *SBucket) processObjectsActionInput(input api.BucketObjectsActionIn
}
iBucket, err := bucket.GetIBucket()
if err != nil {
if errors.Cause(err) == httperrors.ErrInvalidStatus {
return nil, nil, httperrors.NewInvalidStatusError("%s", err)
} else {
return nil, nil, httperrors.NewInternalServerError("fail to find external bucket: %s", err)
}
return nil, nil, errors.Wrap(err, "GetIBucket")
}
objects := make([]cloudprovider.ICloudObject, 0)
for _, key := range input.Key {

View File

@@ -272,6 +272,18 @@ func (manager *SCachedimageManager) cacheGlanceImageInfo(ctx context.Context, us
}
}
func (image *SCachedimage) GetStorages() ([]SStorage, error) {
sq := StorageManager.Query()
storagecacheimageSubq := StoragecachedimageManager.Query("storagecache_id").Equals("cachedimage_id", image.GetId()).SubQuery()
sq.Join(storagecacheimageSubq, sqlchemy.Equals(sq.Field("storagecache_id"), storagecacheimageSubq.Field("storagecache_id")))
storages := make([]SStorage, 0, 1)
err := db.FetchModelObjects(StorageManager, sq, &storages)
if err != nil {
return nil, errors.Wrap(err, "FetchModelObjects")
}
return storages, nil
}
func (manager *SCachedimageManager) GetImageById(ctx context.Context, userCred mcclient.TokenCredential, imageId string, refresh bool) (*cloudprovider.SImage, error) {
imgObj, _ := manager.FetchById(imageId)
if imgObj != nil {
@@ -472,7 +484,11 @@ func (self *SCachedimage) canDeleteLastCache() bool {
func (self *SCachedimage) syncWithCloudImage(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, image cloudprovider.ICloudImage, managerId string) error {
diff, err := db.UpdateWithLock(ctx, self, func() error {
self.Name = image.GetName()
newName, err := db.GenerateAlterName(self, image.GetName())
if err != nil {
return errors.Wrap(err, "GenerateAlterName")
}
self.Name = newName
self.Size = image.GetSizeByte()
self.ExternalId = image.GetGlobalId()
self.ImageType = image.GetImageType()
@@ -668,20 +684,6 @@ func (manager *SCachedimageManager) ListItemFilter(
return nil, errors.Wrapf(err, "SSharableBaseResourceManager.ListItemFilter")
}
q, err = managedResourceFilterByAccount(q, query.ManagedResourceListInput, "id", func() *sqlchemy.SQuery {
cachedImages := CachedimageManager.Query().SubQuery()
storagecachedImages := StoragecachedimageManager.Query().SubQuery()
storageCaches := StoragecacheManager.Query().SubQuery()
subq := cachedImages.Query(cachedImages.Field("id"))
subq = subq.Join(storagecachedImages, sqlchemy.Equals(cachedImages.Field("id"), storagecachedImages.Field("cachedimage_id")))
subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id")))
return subq
})
if err != nil {
return nil, errors.Wrap(err, "managedResourceFilterByAccount")
}
q, err = manager.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query.SharableVirtualResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SSharableVirtualResourceBaseManager.ListItemFilter")
@@ -692,40 +694,74 @@ func (manager *SCachedimageManager) ListItemFilter(
return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
}
q, err = managedResourceFilterByRegion(q, query.RegionalFilterListInput, "id", func() *sqlchemy.SQuery {
{
var idFilter bool
storagecachedImages := StoragecachedimageManager.Query().SubQuery()
storageCaches := StoragecacheManager.Query().SubQuery()
storages := StorageManager.Query().SubQuery()
var storages *sqlchemy.SSubQuery
if query.Valid == nil {
storages = StorageManager.Query().SubQuery()
} else if *query.Valid {
idFilter = true
storages = StorageManager.Query().In("status", []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}).IsTrue("enabled").SubQuery()
} else {
idFilter = true
stroage := StorageManager.Query()
storages = stroage.Filter(sqlchemy.OR(sqlchemy.NotIn(stroage.Field("status"), []string{}), sqlchemy.IsFalse(stroage.Field("enabled")))).SubQuery()
}
zones := ZoneManager.Query().SubQuery()
subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id"))
subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id")))
subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id")))
subq = subq.Join(zones, sqlchemy.Equals(storages.Field("zone_id"), zones.Field("id")))
subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
return subq
})
if err != nil {
return nil, errors.Wrap(err, "managedResourceFilterByRegion")
}
q, err = managedResourceFilterByZone(q, query.ZonalFilterListInput, "id", func() *sqlchemy.SQuery {
storagecachedImages := StoragecachedimageManager.Query().SubQuery()
storageCaches := StoragecacheManager.Query().SubQuery()
storages := StorageManager.Query().SubQuery()
subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id"))
subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id")))
subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id")))
if len(query.HostSchedtagId) > 0 {
idFilter = true
schedTagObj, err := SchedtagManager.FetchByIdOrName(userCred, query.HostSchedtagId)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return nil, errors.Wrapf(httperrors.ErrResourceNotFound, "%s %s", SchedtagManager.Keyword(), query.HostSchedtagId)
} else {
return nil, errors.Wrap(err, "SchedtagManager.FetchByIdOrName")
}
}
hoststorages := HoststorageManager.Query("host_id", "storage_id").SubQuery()
hostschedtags := HostschedtagManager.Query().Equals("schedtag_id", schedTagObj.GetId()).SubQuery()
subq = subq.Join(hoststorages, sqlchemy.Equals(hoststorages.Field("storage_id"), storages.Field("id")))
subq = subq.Join(hostschedtags, sqlchemy.Equals(hostschedtags.Field("host_id"), hoststorages.Field("host_id")))
}
subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE))
return subq
})
if err != nil {
return nil, errors.Wrap(err, "managedResourceFilterByZone")
subq = subq.Snapshot()
subq, err = managedResourceFilterByAccount(subq, query.ManagedResourceListInput, "", nil)
if err != nil {
return nil, errors.Wrap(err, "managedResourceFilterByAccount")
}
subq, err = managedResourceFilterByRegion(subq, query.RegionalFilterListInput, "", nil)
if err != nil {
return nil, errors.Wrap(err, "_managedResourceFilterByRegion")
}
subq, err = managedResourceFilterByZone(subq, query.ZonalFilterListInput, "", nil)
if err != nil {
return nil, errors.Wrap(err, "_managedResourceFilterByZone")
}
if subq.IsAltered() {
idFilter = true
}
if idFilter {
q = q.In("id", subq)
}
}
if len(query.ImageType) > 0 {
q = q.In("image_type", query.ImageType)
q = q.Equals("image_type", query.ImageType)
}
return q, nil

View File

@@ -44,6 +44,7 @@ type SCapabilities struct {
DisabledComputeEngineBrands []string `json:",allowempty"`
CloudIdBrands []string `json:",allowempty"`
DisabledCloudIdBrands []string `json:",allowempty"`
PublicIpBrands []string `json:",allowempty"`
NetworkManageBrands []string `json:",allowempty"`
DisabledNetworkManageBrands []string `json:",allowempty"`
ObjectStorageBrands []string `json:",allowempty"`
@@ -262,6 +263,7 @@ func getBrands(region *SCloudregion, zone *SZone, domainId string, capa *SCapabi
capa.NetworkManageBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_NETWORK)
capa.ObjectStorageBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE)
capa.CloudIdBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_CLOUDID)
capa.PublicIpBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_PUBLIC_IP)
if utils.IsInStringArray(api.HYPERVISOR_KVM, capa.Hypervisors) || utils.IsInStringArray(api.HYPERVISOR_BAREMETAL, capa.Hypervisors) {
capa.Brands = append(capa.Brands, api.ONECLOUD_BRAND_ONECLOUD)

View File

@@ -364,7 +364,7 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
if ownerId == nil {
ownerId = userCred
}
input.CloudaccountCreateInput, err = scm.ValidateCreateData(ctx, userCred, ownerId, query, input.CloudaccountCreateInput)
input.CloudaccountCreateInput, err = scm.validateCreateData(ctx, userCred, ownerId, query, input.CloudaccountCreateInput)
if err != nil {
return output, err
}
@@ -539,13 +539,14 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
FakeID int
IP netutils.IPV4Addr
Name string
VlanID int32
}
vms := make([]vm, 0, len(simpleVms))
var nip netutils.IPV4Addr
guestMap := make(map[int]*api.CAGuestNet)
for i := range simpleVms {
id := i
if len(simpleVms[i].IPs) == 0 {
if len(simpleVms[i].IPVlans) == 0 {
if _, ok := guestMap[id]; !ok {
guestMap[id] = &api.CAGuestNet{
Name: simpleVms[i].Name,
@@ -553,8 +554,8 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
}
}
}
for _, ip := range simpleVms[i].IPs {
nip, err = netutils.NewIPV4Addr(ip)
for _, ipVlan := range simpleVms[i].IPVlans {
nip, err = netutils.NewIPV4Addr(ipVlan.IP)
if err != nil {
return output, err
}
@@ -562,6 +563,7 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
FakeID: i,
IP: nip,
Name: simpleVms[i].Name,
VlanID: ipVlan.VlanID,
})
}
}
@@ -584,17 +586,18 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
return excludeNets[i].GuestIpStart < excludeNets[j].GuestIpStart
})
svNets := make([]netutils.IPV4AddrRange, 0, 5)
svNets := make([]api.CASimpleNetConf, 0, 5)
var vmi, neti int
lastEndIp := netutils.IPV4Addr(0)
Loop:
for neti = 0; neti < len(excludeNets); {
if vmi >= len(vms) {
break
}
startIp, _ := netutils.NewIPV4Addr(excludeNets[neti].GuestIpStart)
endIp, _ := netutils.NewIPV4Addr(excludeNets[neti].GuestIpEnd)
switch {
case vms[vmi].IP > endIp:
lastEndIp = endIp
neti++
case vms[vmi].IP >= startIp:
for vms[vmi].IP <= endIp {
@@ -608,29 +611,21 @@ Loop:
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
IP: vms[vmi].IP.String(),
SuitableNetwork: excludeNets[neti].Id,
VlanID: vms[vmi].VlanID,
})
vmi += 1
if vmi == len(vms) {
break Loop
}
}
lastEndIp = endIp
neti++
default:
for vms[vmi].IP < startIp {
suggestStartIp := vms[vmi].IP.NetAddr(24) + 1
if suggestStartIp <= lastEndIp {
suggestStartIp = lastEndIp + 1
}
if suggestStartIp >= startIp {
break
}
suggestEndIp := suggestStartIp.NetAddr(24) + 255
if suggestEndIp >= startIp {
suggestEndIp = startIp - 1
}
svNets = append(svNets, netutils.NewIPV4AddrRange(suggestStartIp, suggestEndIp))
for vmi < len(vms) && vms[vmi].IP <= suggestEndIp {
suggestStartIp := vms[vmi].IP
suggestEndIp := vms[vmi].IP
endLimitIp := suggestStartIp.NetAddr(24) + 255
vlanId := vms[vmi].VlanID
for {
id := vms[vmi].FakeID
if _, ok := guestMap[id]; !ok {
guestMap[id] = &api.CAGuestNet{
@@ -639,10 +634,34 @@ Loop:
}
}
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
IP: vms[vmi].IP.String(),
IP: vms[vmi].IP.String(),
VlanID: vms[vmi].VlanID,
})
vmi++
if vmi == len(vms) {
break
}
if suggestEndIp == endLimitIp {
break
}
if vms[vmi].IP > suggestEndIp+1 {
break
}
if vms[vmi].IP >= startIp {
break
}
if vms[vmi].VlanID != vlanId {
break
}
suggestEndIp = vms[vmi].IP
}
svNets = append(svNets, api.CASimpleNetConf{
GuestIpStart: suggestStartIp.String(),
GuestIpEnd: suggestEndIp.String(),
VlanID: vlanId,
GuestIpMask: 24,
GuestGateway: (suggestStartIp.NetAddr(24) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)).String(),
})
if vmi == len(vms) {
break Loop
}
@@ -651,13 +670,11 @@ Loop:
}
for vmi < len(vms) {
suggestStartIp := vms[vmi].IP.NetAddr(24) + 1
if suggestStartIp <= lastEndIp {
suggestStartIp = lastEndIp + 1
}
suggestEndIp := suggestStartIp.NetAddr(24) + 255
svNets = append(svNets, netutils.NewIPV4AddrRange(suggestStartIp, suggestEndIp))
for vmi < len(vms) && vms[vmi].IP <= suggestEndIp {
suggestStartIp := vms[vmi].IP
endLimitIp := suggestStartIp.NetAddr(24) + 255
suggestEndIp := suggestStartIp
vlanId := vms[vmi].VlanID
for {
id := vms[vmi].FakeID
if _, ok := guestMap[id]; !ok {
guestMap[id] = &api.CAGuestNet{
@@ -669,7 +686,27 @@ Loop:
IP: vms[vmi].IP.String(),
})
vmi++
if vmi == len(vms) {
break
}
if suggestEndIp == endLimitIp {
break
}
if vms[vmi].IP > suggestEndIp+1 {
break
}
if vms[vmi].VlanID != vlanId {
break
}
suggestEndIp = vms[vmi].IP
}
svNets = append(svNets, api.CASimpleNetConf{
GuestIpStart: suggestStartIp.String(),
GuestIpEnd: suggestEndIp.String(),
VlanID: vlanId,
GuestIpMask: 24,
GuestGateway: (suggestStartIp.NetAddr(24) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)).String(),
})
}
for _, guest := range guestMap {
@@ -679,12 +716,7 @@ Loop:
if len(svNets) > 0 {
confs := make([]api.CANetConf, len(svNets))
for i := range confs {
confs[i].CASimpleNetConf = api.CASimpleNetConf{
GuestIpStart: svNets[i].StartIp().String(),
GuestIpEnd: svNets[i].EndIp().String(),
GuestIpMask: 24,
GuestGateway: (svNets[i].StartIp().NetAddr(24) + 1).String(),
}
confs[i].CASimpleNetConf = svNets[i]
confs[i].Name = fmt.Sprintf("%s-guest-network-%d", input.Name, i+1)
}
output.GuestSuggestedNetworks = confs
@@ -758,7 +790,7 @@ func (manager *SCloudaccountManager) suggestHostNetworks(ips []netutils.IPV4Addr
lastnetAddr = netAddr
}
gatewayIP := consequent[0].NetAddr(mask) + 1
gatewayIP := consequent[0].NetAddr(mask) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)
ret = append(ret, api.CASimpleNetConf{
GuestIpStart: consequent[0].String(),
GuestIpEnd: consequent[len(consequent)-1].String(),
@@ -767,7 +799,7 @@ func (manager *SCloudaccountManager) suggestHostNetworks(ips []netutils.IPV4Addr
})
consequent = []netutils.IPV4Addr{ip}
}
gatewayIp := consequent[0].NetAddr(mask) + 1
gatewayIp := consequent[0].NetAddr(mask) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)
ret = append(ret, api.CASimpleNetConf{
GuestIpStart: consequent[0].String(),
GuestIpEnd: consequent[len(consequent)-1].String(),
@@ -888,11 +920,42 @@ func (manager *SCloudaccountManager) ValidateCreateData(
ownerId mcclient.IIdentityProvider,
query jsonutils.JSONObject,
input api.CloudaccountCreateInput,
) (api.CloudaccountCreateInput, error) {
input, err := manager.validateCreateData(ctx, userCred, ownerId, query, input)
if err != nil {
return input, errors.Wrap(err, "validateCreateData")
}
input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
if err != nil {
return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ValidateCreateData")
}
quota := &SDomainQuota{
SBaseDomainQuotaKeys: quotas.SBaseDomainQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
},
Cloudaccount: 1,
}
err = quotas.CheckSetPendingQuota(ctx, userCred, quota)
if err != nil {
return input, errors.Wrapf(err, "CheckSetPendingQuota")
}
return input, nil
}
func (manager *SCloudaccountManager) validateCreateData(
ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
query jsonutils.JSONObject,
input api.CloudaccountCreateInput,
) (api.CloudaccountCreateInput, error) {
// check domainId
err := db.ValidateCreateDomainId(ownerId.GetProjectDomainId())
if err != nil {
return input, err
return input, errors.Wrap(err, "db.ValidateCreateDomainId")
}
if !cloudprovider.IsSupported(input.Provider) {
@@ -1003,22 +1066,6 @@ func (manager *SCloudaccountManager) ValidateCreateData(
input.SyncIntervalSeconds = options.Options.MinimalSyncIntervalSeconds
}
input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
if err != nil {
return input, err
}
quota := &SDomainQuota{
SBaseDomainQuotaKeys: quotas.SBaseDomainQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
},
Cloudaccount: 1,
}
err = quotas.CheckSetPendingQuota(ctx, userCred, quota)
if err != nil {
return input, errors.Wrapf(err, "CheckSetPendingQuota")
}
return input, nil
}
@@ -1050,9 +1097,6 @@ func (self *SCloudaccount) CustomizeCreate(ctx context.Context, userCred mcclien
}
func (self *SCloudaccount) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
self.savePassword(self.Secret)
quota := &SDomainQuota{
SBaseDomainQuotaKeys: quotas.SBaseDomainQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
@@ -1063,6 +1107,10 @@ func (self *SCloudaccount) PostCreate(ctx context.Context, userCred mcclient.Tok
if err != nil {
log.Errorf("CancelPendingUsage fail %s", err)
}
self.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
self.savePassword(self.Secret)
if self.Enabled.IsTrue() {
self.StartSyncCloudProviderInfoTask(ctx, userCred, nil, "")
}
@@ -1922,7 +1970,7 @@ func (self *SCloudaccount) GetDetailsBalance(ctx context.Context, userCred mccli
return nil, httperrors.NewGeneralError(err)
}
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewFloat(balance), "balance")
ret.Add(jsonutils.NewFloat64(balance), "balance")
return ret, nil
}

View File

@@ -1,201 +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 models
import (
"reflect"
"sort"
"testing"
"yunion.io/x/pkg/util/netutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
)
func TestSCloudaccount_suggestHostNetworks(t *testing.T) {
cases := []struct {
in []string
want []api.CASimpleNetConf
}{
{
[]string{
"10.168.13.234",
"10.168.13.235",
"10.168.13.233",
"10.168.13.222",
},
[]api.CASimpleNetConf{
{
GuestIpStart: "10.168.13.222",
GuestIpEnd: "10.168.13.222",
GuestIpMask: 24,
GuestGateway: "10.168.13.1",
},
{
GuestIpStart: "10.168.13.233",
GuestIpEnd: "10.168.13.235",
GuestIpMask: 24,
GuestGateway: "10.168.13.1",
},
},
},
{
[]string{
"10.168.12.254",
"10.168.43.1",
},
[]api.CASimpleNetConf{
{
GuestIpStart: "10.168.12.254",
GuestIpEnd: "10.168.12.254",
GuestIpMask: 24,
GuestGateway: "10.168.12.1",
},
{
GuestIpStart: "10.168.43.1",
GuestIpEnd: "10.168.43.1",
GuestIpMask: 24,
GuestGateway: "10.168.43.1",
},
},
},
{
[]string{
"10.155.50.103",
"10.155.50.101",
"10.155.50.102",
},
[]api.CASimpleNetConf{
{
GuestIpStart: "10.155.50.101",
GuestIpEnd: "10.155.50.103",
GuestIpMask: 24,
GuestGateway: "10.155.50.1",
},
},
},
}
for _, c := range cases {
ins := make([]netutils.IPV4Addr, len(c.in))
for i := range ins {
ins[i], _ = netutils.NewIPV4Addr(c.in[i])
}
out := CloudaccountManager.suggestHostNetworks(ins)
sort.Slice(out, func(i, j int) bool {
if out[i].GuestIpStart == out[j].GuestIpStart {
return out[i].GuestIpEnd < out[j].GuestIpEnd
}
return out[i].GuestIpStart < out[j].GuestIpStart
})
if !reflect.DeepEqual(out, c.want) {
t.Fatalf("want: %#v\nreal: %#v", c.want, out)
}
}
}
func TestSCloudaccount_suggestVMNetwors(t *testing.T) {
cases := []struct {
in1 []string
in2 []struct {
startIp string
endIp string
}
want []api.CASimpleNetConf
}{
{
in1: []string{
"10.168.222.23",
"10.168.222.26",
"10.168.222.145",
"10.168.222.234",
},
in2: []struct {
startIp string
endIp string
}{
{"10.168.222.45", "10.168.222.120"},
{"10.168.222.200", "10.168.222.230"},
},
want: []api.CASimpleNetConf{
{
GuestIpStart: "10.168.222.1",
GuestIpEnd: "10.168.222.44",
GuestIpMask: 24,
GuestGateway: "10.168.222.1",
},
{
GuestIpStart: "10.168.222.121",
GuestIpEnd: "10.168.222.199",
GuestIpMask: 24,
GuestGateway: "10.168.222.1",
},
{
GuestIpStart: "10.168.222.231",
GuestIpEnd: "10.168.222.254",
GuestIpMask: 24,
GuestGateway: "10.168.222.1",
},
},
},
{
in1: []string{
"10.168.222.23",
"10.168.224.178",
},
in2: []struct {
startIp string
endIp string
}{
{"10.168.222.100", "10.168.224.100"},
},
want: []api.CASimpleNetConf{
{
GuestIpStart: "10.168.222.1",
GuestIpEnd: "10.168.222.99",
GuestIpMask: 24,
GuestGateway: "10.168.222.1",
},
{
GuestIpStart: "10.168.224.101",
GuestIpEnd: "10.168.224.254",
GuestIpMask: 24,
GuestGateway: "10.168.224.1",
},
},
},
}
for _, c := range cases {
ins1 := make([]netutils.IPV4Addr, len(c.in1))
ins2 := make([]netutils.IPV4AddrRange, len(c.in2))
for i := range ins1 {
ins1[i], _ = netutils.NewIPV4Addr(c.in1[i])
}
for i := range ins2 {
ip1, _ := netutils.NewIPV4Addr(c.in2[i].startIp)
ip2, _ := netutils.NewIPV4Addr(c.in2[i].endIp)
ins2[i] = netutils.NewIPV4AddrRange(ip1, ip2)
}
out := CloudaccountManager.suggestVMNetwors(ins1, ins2)
sort.Slice(out, func(i, j int) bool {
if out[i].GuestIpStart == out[j].GuestIpStart {
return out[i].GuestIpEnd < out[j].GuestIpEnd
}
return out[i].GuestIpStart < out[j].GuestIpStart
})
if !reflect.DeepEqual(out, c.want) {
t.Fatalf("want: %#v\nreal: %#v", c.want, out)
}
}
}

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