Compare commits

...

103 Commits

Author SHA1 Message Date
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
138 changed files with 2042 additions and 948 deletions

View File

@@ -313,7 +313,8 @@ REGISTRY ?= "registry.cn-beijing.aliyuncs.com/yunionio"
VERSION ?= $(shell git describe --exact-match 2> /dev/null || \
git describe --match=$(git rev-parse --short=8 HEAD) --always --dirty --abbrev=8)
image:
image: clean
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

@@ -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

@@ -27,6 +27,8 @@ 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"`
}
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

@@ -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

@@ -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.Delete(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)
}
}

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-20201009235752-2ef1a29656b0
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-20201009235752-2ef1a29656b0 h1:ETDt3Xc3a6WnbHvhrMUemXVsnWY/RgHrsNRCVFWkCYo=
yunion.io/x/sqlchemy v0.0.0-20201009235752-2ef1a29656b0/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

@@ -58,6 +58,9 @@ type CachedimageListInput struct {
// 镜像类型,可能值为: system(公有云公共镜像), customized(自定义镜像)
// example: system
ImageType []string `json:"image_type"`
// filter by host schedtag
HostSchedtagId string `json:"host_schedtag_id"`
}
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

@@ -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,16 @@ 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"`
// 返回列表数据中包含资源的标签数据Metadata
WithMeta *bool `json:"with_meta"`
}

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

@@ -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

@@ -1368,7 +1368,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

@@ -585,13 +585,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.WithMeta != nil {
metadatas := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
sq := metadatas.Query(metadatas.Field("obj_id")).Distinct().SubQuery()
if *input.WithMeta {
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
} else {
q = q.Filter(sqlchemy.NotIn(q.Field("id"), sq))
}
}
return q

View File

@@ -87,6 +87,10 @@ func alterNameValidator(model IModel, name string) error {
return nil
}
func GenerateAlertName(model IModel, hint string) (string, error) {
return GenerateName2(model.GetModelManager(), nil, hint, model, 1)
}
func GenerateName(manager IModelManager, ownerId mcclient.IIdentityProvider, hint string) (string, error) {
return GenerateName2(manager, ownerId, hint, nil, 1)
}

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

@@ -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

@@ -295,7 +295,19 @@ func (model *SStandaloneResourceBase) RemoveAllMetadata(ctx context.Context, use
}
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 +316,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
}

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")
}

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

@@ -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

@@ -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")
}

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

@@ -153,47 +153,49 @@ 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)
return desc, errors.Errorf("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)
log.Errorf("unable to GetHost of storageCache %s: %v", storageCaches[0].Id, err)
hostIp = storageCaches[0].ExternalId
} else if storageCacheHost == nil {
log.Errorf("unable to GetHost of storageCache %s: result is nil", storageCaches[0].Id)
hostIp = storageCaches[0].ExternalId
} else {
hostIp = storageCacheHost.AccessIp
}
hostIp = storageCacheHost.AccessIp
imageInfo := SEsxiImageInfo{
@@ -203,7 +205,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

@@ -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

View File

@@ -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

@@ -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

@@ -472,7 +472,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.GenerateAlertName(self, image.GetName())
if err != nil {
return errors.Wrap(err, "GenerateAlertName")
}
self.Name = newName
self.Size = image.GetSizeByte()
self.ExternalId = image.GetGlobalId()
self.ImageType = image.GetImageType()
@@ -728,6 +732,25 @@ func (manager *SCachedimageManager) ListItemFilter(
q = q.In("image_type", query.ImageType)
}
if len(query.HostSchedtagId) > 0 {
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")
}
}
subq := StoragecachedimageManager.Query("cachedimage_id")
storages := StorageManager.Query("id", "storagecache_id").SubQuery()
hoststorages := HoststorageManager.Query("host_id", "storage_id").SubQuery()
hostschedtags := HostschedtagManager.Query().Equals("schedtag_id", schedTagObj.GetId()).SubQuery()
subq = subq.Join(storages, sqlchemy.Equals(storages.Field("storagecache_id"), subq.Field("storagecache_id")))
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")))
q = q.In("id", subq.SubQuery())
}
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)
}
}
}

View File

@@ -164,6 +164,9 @@ func (manager *SDBInstanceSkuManager) ListItemFilter(
if len(query.EngineVersion) > 0 {
q = q.In("engine_version", query.EngineVersion)
}
if len(query.Providers) > 0 {
q = q.In("provider", query.Providers)
}
for k, zoneIds := range map[string][]string{"zone1": query.Zone1, "zone2": query.Zone2, "zone3": query.Zone3} {
ids := []string{}

View File

@@ -149,6 +149,18 @@ func (manager *SDnsZoneManager) ValidateCreateData(ctx context.Context, userCred
}
func (self *SDnsZone) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
quota := &SDomainQuota{
SBaseDomainQuotaKeys: quotas.SBaseDomainQuotaKeys{
DomainId: ownerId.GetProjectDomainId(),
},
DnsZone: 1,
}
err := quotas.CancelPendingUsage(ctx, userCred, quota, quota, true)
if err != nil {
log.Errorf("SDnsZone CancelPendingUsage fail %s", err)
}
self.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
input := &api.DnsZoneCreateInput{}
data.Unmarshal(input)
switch cloudprovider.TDnsZoneType(input.ZoneType) {
@@ -873,3 +885,14 @@ func (manager *SDnsZoneManager) totalCount(scope rbacutils.TRbacScope, ownerId m
cnt, _ := q.CountWithError()
return cnt
}
func (dzone *SDnsZone) GetUsages() []db.IUsage {
if dzone.Deleted {
return nil
}
usage := SDomainQuota{DnsZone: 1}
usage.SetKeys(quotas.SBaseDomainQuotaKeys{DomainId: dzone.DomainId})
return []db.IUsage{
&usage,
}
}

View File

@@ -1234,8 +1234,8 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
chargeType = api.EIP_CHARGE_TYPE_BY_TRAFFIC
}
eip := SElasticip{}
eip.SetModelManager(manager, &eip)
eip := &SElasticip{}
eip.SetModelManager(manager, eip)
eip.Mode = api.EIP_MODE_STANDALONE_EIP
// do not implicitly auto dellocate EIP, should be set by user explicitly
@@ -1288,11 +1288,12 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
return nil, errors.Wrap(err, "db.GenerateName")
}
err = manager.TableSpec().Insert(ctx, &eip)
err = manager.TableSpec().Insert(ctx, eip)
if err != nil {
log.Errorf("create EIP record fail %s", err)
return nil, err
}
db.OpsLog.LogEvent(eip, db.ACT_CREATE, eip.GetShortDesc(ctx), userCred)
eipPendingUsage := &SRegionQuota{Eip: 1}
keys := fetchRegionalQuotaKeys(
@@ -1304,7 +1305,7 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
eipPendingUsage.SetKeys(keys)
quotas.CancelPendingUsage(ctx, userCred, pendingUsage, eipPendingUsage, true)
return &eip, nil
return eip, nil
}
func (eip *SElasticip) AllocateAndAssociateVM(ctx context.Context, userCred mcclient.TokenCredential, vm *SGuest, parentTaskId string) error {

View File

@@ -89,6 +89,9 @@ func (self *SGuest) PreCheckPerformAction(
ctx context.Context, userCred mcclient.TokenCredential,
action string, query jsonutils.JSONObject, data jsonutils.JSONObject,
) error {
if err := self.SVirtualResourceBase.PreCheckPerformAction(ctx, userCred, action, query, data); err != nil {
return err
}
if self.Hypervisor == api.HYPERVISOR_KVM {
host := self.GetHost()
if host != nil && (host.HostStatus == api.HOST_OFFLINE || !host.Enabled.Bool()) &&
@@ -169,8 +172,7 @@ func (self *SGuest) GetDetailsDesc(ctx context.Context, userCred mcclient.TokenC
if host == nil {
return nil, httperrors.NewInvalidStatusError("No host for server")
}
desc := self.GetDriver().GetJsonDescAtHost(ctx, userCred, self, host)
return desc, nil
return self.GetDriver().GetJsonDescAtHost(ctx, userCred, self, host, nil)
}
func (self *SGuest) AllowPerformSaveImage(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {

View File

@@ -56,7 +56,7 @@ type IGuestDriver interface {
RequestRenewInstance(guest *SGuest, bc billing.SBillingCycle) (time.Time, error)
GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, host *SHost) jsonutils.JSONObject
GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, host *SHost, params *jsonutils.JSONDict) (jsonutils.JSONObject, error)
ValidateImage(ctx context.Context, image *cloudprovider.SImage) error
ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *api.ServerCreateInput) (*api.ServerCreateInput, error)
@@ -169,6 +169,7 @@ type IGuestDriver interface {
RequestSyncToBackup(ctx context.Context, guest *SGuest, task taskman.ITask) error
IsSupportEip() bool
IsSupportPublicIp() bool
ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error
RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, eip *SElasticip, task taskman.ITask) error

View File

@@ -1523,6 +1523,21 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
func (manager *SGuestManager) validateEip(userCred mcclient.TokenCredential, input *api.ServerCreateInput,
preferRegionId string, preferManagerId string) error {
if input.PublicIpBw > 0 {
if !GetDriver(input.Hypervisor).IsSupportPublicIp() {
return httperrors.NewNotImplementedError("public ip not supported for %s", input.Hypervisor)
}
if len(input.PublicIpChargeType) == 0 {
input.PublicIpChargeType = string(cloudprovider.ElasticipChargeTypeByTraffic)
}
if !utils.IsInStringArray(input.PublicIpChargeType, []string{
string(cloudprovider.ElasticipChargeTypeByTraffic),
string(cloudprovider.ElasticipChargeTypeByBandwidth),
}) {
return httperrors.NewInputParameterError("invalid public_ip_charge_type %s", input.PublicIpChargeType)
}
return nil
}
eipStr := input.Eip
eipBw := input.EipBw
if len(eipStr) > 0 || eipBw > 0 {
@@ -3676,7 +3691,10 @@ func (self *SGuest) isNeedDoResetPasswd() bool {
func (self *SGuest) GetDeployConfigOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, params *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
config := jsonutils.NewDict()
desc := self.GetDriver().GetJsonDescAtHost(ctx, userCred, self, host)
desc, err := self.GetDriver().GetJsonDescAtHost(ctx, userCred, self, host, params)
if err != nil {
return nil, errors.Wrapf(err, "GetJsonDescAtHost")
}
config.Add(desc, "desc")
deploys, err := cmdline.FetchDeployConfigsByJSON(params)

View File

@@ -52,6 +52,7 @@ func InitDB() error {
LoadbalancerListenerRuleManager,
LoadbalancerBackendGroupManager,
LoadbalancerBackendManager,
AwsCachedLbbgManager,
LoadbalancerClusterManager,
SchedtagManager,
DynamicschedtagManager,

View File

@@ -159,16 +159,14 @@ func (man *SAwsCachedLbManager) SyncLoadbalancerBackends(ctx context.Context, us
if err != nil {
syncResult.UpdateError(err)
} else {
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
syncResult.Update()
}
}
for i := 0; i < len(added); i++ {
local, err := man.newFromCloudLoadbalancerBackend(ctx, userCred, loadbalancerBackendgroup, added[i], syncOwnerId)
_, err := man.newFromCloudLoadbalancerBackend(ctx, userCred, loadbalancerBackendgroup, added[i], syncOwnerId)
if err != nil {
syncResult.AddError(err)
} else {
syncMetadata(ctx, userCred, local, added[i])
syncResult.Add()
}
}

View File

@@ -16,6 +16,7 @@ package models
import (
"context"
"database/sql"
"fmt"
"strconv"
"strings"
@@ -249,7 +250,6 @@ func (man *SAwsCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.Cont
if err != nil {
syncResult.UpdateError(err)
} else {
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
localLbgs = append(localLbgs, commondb[i])
remoteLbbgs = append(remoteLbbgs, commonext[i])
syncResult.Update()
@@ -277,7 +277,6 @@ func (man *SAwsCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.Cont
if err != nil {
syncResult.AddError(err)
} else {
syncMetadata(ctx, userCred, new, added[i])
localLbgs = append(localLbgs, *new)
remoteLbbgs = append(remoteLbbgs, added[i])
syncResult.Add()
@@ -434,3 +433,30 @@ func (man *SAwsCachedLbbgManager) newFromCloudLoadbalancerBackendgroup(ctx conte
db.OpsLog.LogEvent(lbbg, db.ACT_CREATE, lbbg.GetShortDesc(ctx), userCred)
return lbbg, nil
}
func (man *SAwsCachedLbbgManager) InitializeData() error {
ret := []db.SMetadata{}
q := db.Metadata.Query().Equals("obj_type", man.Keyword())
err := db.FetchModelObjects(db.Metadata, q, &ret)
if err != nil {
if errors.Cause(err) != sql.ErrNoRows {
log.Debugf("SAwsCachedLbbgManager.InitializeData %s", err)
}
return nil
}
for i := range ret {
item := ret[i]
_, err := db.Update(&item, func() error {
return item.MarkDelete()
})
if err != nil {
log.Debugf("SAwsCachedLbbgManager.MarkDelete %s", err)
return nil
}
}
log.Debugf("SAwsCachedLbbgManager cleaned %d dirty data.", len(ret))
return nil
}

View File

@@ -162,16 +162,14 @@ func (man *SHuaweiCachedLbManager) SyncLoadbalancerBackends(ctx context.Context,
if err != nil {
syncResult.UpdateError(err)
} else {
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
syncResult.Update()
}
}
for i := 0; i < len(added); i++ {
local, err := man.newFromCloudLoadbalancerBackend(ctx, userCred, loadbalancerBackendgroup, added[i], syncOwnerId)
_, err := man.newFromCloudLoadbalancerBackend(ctx, userCred, loadbalancerBackendgroup, added[i], syncOwnerId)
if err != nil {
syncResult.AddError(err)
} else {
syncMetadata(ctx, userCred, local, added[i])
syncResult.Add()
}
}
@@ -303,7 +301,9 @@ func newLocalBackendFromCloudLoadbalancerBackend(ctx context.Context, userCred m
sq := HostManager.Query().SubQuery()
return q.Join(sq, sqlchemy.Equals(sq.Field("id"), q.Field("host_id"))).Filter(sqlchemy.Equals(sq.Field("manager_id"), lbbgProvider.Id))
})
if err != nil {
return nil, err
}
guest := instance.(*SGuest)
//address, err := LoadbalancerBackendManager.GetGuestAddress(guest)
//if err != nil {

View File

@@ -222,7 +222,6 @@ func (man *SHuaweiCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.C
if err != nil {
syncResult.UpdateError(err)
} else {
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
localLbgs = append(localLbgs, commondb[i])
remoteLbbgs = append(remoteLbbgs, commonext[i])
syncResult.Update()
@@ -233,7 +232,6 @@ func (man *SHuaweiCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.C
if err != nil {
syncResult.AddError(err)
} else {
syncMetadata(ctx, userCred, new, added[i])
localLbgs = append(localLbgs, *new)
remoteLbbgs = append(remoteLbbgs, added[i])
syncResult.Add()

View File

@@ -246,7 +246,10 @@ func (man *SOpenstackCachedLbManager) newFromCloudLoadbalancerBackend(ctx contex
if err != nil {
return nil, err
}
// openstack lb后端是ip:port 不一定有server映射
if len(extLoadbalancerBackend.GetBackendId()) == 0 {
return nil, errors.Wrap(cloudprovider.ErrNotFound, "extLoadbalancerBackend.GetBackendId()")
}
locallbb, err := newLocalBackendFromCloudLoadbalancerBackend(ctx, userCred, localBackendGroup, extLoadbalancerBackend, syncOwnerId)
if err != nil {
return nil, err

View File

@@ -234,16 +234,14 @@ func (man *SQcloudCachedLbManager) SyncLoadbalancerBackends(ctx context.Context,
if err != nil {
syncResult.UpdateError(err)
} else {
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
syncResult.Update()
}
}
for i := 0; i < len(added); i++ {
local, err := man.newFromCloudLoadbalancerBackend(ctx, userCred, loadbalancerBackendgroup, added[i], syncOwnerId)
_, err := man.newFromCloudLoadbalancerBackend(ctx, userCred, loadbalancerBackendgroup, added[i], syncOwnerId)
if err != nil {
syncResult.AddError(err)
} else {
syncMetadata(ctx, userCred, local, added[i])
syncResult.Add()
}
}

View File

@@ -294,7 +294,6 @@ func (man *SQcloudCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.C
if err != nil {
syncResult.UpdateError(err)
} else {
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
localLbgs = append(localLbgs, commondb[i])
remoteLbbgs = append(remoteLbbgs, commonext[i])
syncResult.Update()
@@ -305,7 +304,6 @@ func (man *SQcloudCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.C
if err != nil {
syncResult.AddError(err)
} else {
syncMetadata(ctx, userCred, newlbbg, added[i])
localLbgs = append(localLbgs, *newlbbg)
remoteLbbgs = append(remoteLbbgs, added[i])
syncResult.Add()

View File

@@ -1333,6 +1333,20 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
return input, httperrors.NewInputParameterError("Invalid server_type: %s", input.ServerType)
}
{
defaultVlanId := 1
if input.VlanId == nil {
input.VlanId = &defaultVlanId
} else if *input.VlanId < 1 {
input.VlanId = &defaultVlanId
}
if *input.VlanId > 4095 {
return input, httperrors.NewInputParameterError("valid vlan id")
}
}
{
if len(input.IfnameHint) == 0 {
input.IfnameHint = input.Name
@@ -1942,10 +1956,10 @@ func (manager *SNetworkManager) ListItemFilter(
q = q.In("ifname_hint", input.IfnameHint)
}
if len(input.GuestIpStart) > 0 {
q = q.In("guest_ip_start", input.GuestIpStart)
q = q.Filter(sqlchemy.ContainsAny(q.Field("guest_ip_start"), input.GuestIpStart))
}
if len(input.GuestIpEnd) > 0 {
q = q.In("guest_ip_end", input.GuestIpEnd)
q = q.Filter(sqlchemy.ContainsAny(q.Field("guest_ip_end"), input.GuestIpEnd))
}
if len(input.GuestIpMask) > 0 {
q = q.In("guest_ip_mask", input.GuestIpMask)
@@ -2194,8 +2208,21 @@ func (self *SNetwork) PerformMerge(ctx context.Context, userCred mcclient.TokenC
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_MERGE, err.Error(), userCred, false)
return nil, err
}
if self.WireId != net.WireId || self.GuestGateway != net.GuestGateway {
err = httperrors.NewInputParameterError("Invalid Target Network: %s", input.Target)
failReason := make([]string, 0)
if self.WireId != net.WireId {
failReason = append(failReason, "wire_id")
}
if self.GuestGateway != net.GuestGateway {
failReason = append(failReason, "guest_gateway")
}
if self.VlanId != net.VlanId {
failReason = append(failReason, "vlan_id")
}
if len(failReason) > 0 {
err = httperrors.NewInputParameterError("Invalid Target Network %s: inconsist %s", input.Target, strings.Join(failReason, ","))
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_MERGE, err.Error(), userCred, false)
return nil, err
}
@@ -2206,9 +2233,17 @@ func (self *SNetwork) PerformMerge(ctx context.Context, userCred mcclient.TokenC
ipSS, _ := netutils.NewIPV4Addr(self.GuestIpStart)
ipSE, _ := netutils.NewIPV4Addr(self.GuestIpEnd)
if ipNE.StepUp() == ipSS {
wireNets := make([]SNetwork, 0)
q := NetworkManager.Query().Equals("wire_id", self.WireId).NotEquals("id", self.Id).NotEquals("id", net.Id)
err = db.FetchModelObjects(NetworkManager, q, &wireNets)
if err != nil && errors.Cause(err) != sql.ErrNoRows {
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_MERGE, err.Error(), userCred, false)
return nil, errors.Wrap(err, "Query nets of same wire")
}
if ipNE.StepUp() == ipSS || (ipNE.StepUp() < ipSS && !isOverlapNetworks(wireNets, ipNE.StepUp(), ipSS.StepDown())) {
startIp, endIp = net.GuestIpStart, self.GuestIpEnd
} else if ipSE.StepUp() == ipNS {
} else if ipSE.StepUp() == ipNS || (ipSE.StepUp() < ipNS && !isOverlapNetworks(wireNets, ipSE.StepUp(), ipNS.StepDown())) {
startIp, endIp = self.GuestIpStart, net.GuestIpEnd
} else {
note := "Incontinuity Network for %s and %s"

View File

@@ -140,6 +140,43 @@ func (manager *SSchedtagManager) AllowListItems(ctx context.Context, userCred mc
return true
}
func (m *SSchedtagManager) FilterByOwner(q *sqlchemy.SQuery, userCred mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
if userCred == nil {
return q
}
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()),
))
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()),
),
))
}
return q
}
// 调度标签列表
func (manager *SSchedtagManager) ListItemFilter(
ctx context.Context,

View File

@@ -545,6 +545,10 @@ func (self *SSecurityGroup) AllowPerformPurge(ctx context.Context, userCred mccl
}
func (self *SSecurityGroup) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
err := self.ValidateDeleteCondition(ctx)
if err != nil {
return nil, err
}
return nil, self.StartDeleteSecurityGroupTask(ctx, userCred, true, "")
}
@@ -1001,12 +1005,11 @@ func (self *SSecurityGroup) DoSync(ctx context.Context, userCred mcclient.TokenC
func (manager *SSecurityGroupManager) InitializeData() error {
_, err := manager.FetchById("default")
if err != nil && err != sql.ErrNoRows {
log.Errorf("find default secgroup fail %s", err)
return err
return errors.Wrapf(err, `manager.FetchById("default")`)
}
if err == sql.ErrNoRows {
var secGrp *SSecurityGroup
secGrp = &SSecurityGroup{}
if errors.Cause(err) == sql.ErrNoRows {
log.Debugf("Init default secgroup")
secGrp := &SSecurityGroup{}
secGrp.SetModelManager(manager, secGrp)
secGrp.Id = "default"
secGrp.Name = "Default"
@@ -1015,11 +1018,11 @@ func (manager *SSecurityGroupManager) InitializeData() error {
secGrp.DomainId = auth.AdminCredential().GetProjectDomainId()
// secGrp.IsEmulated = false
secGrp.IsPublic = true
secGrp.Deleted = false
secGrp.PublicScope = string(rbacutils.ScopeSystem)
err = manager.TableSpec().Insert(context.TODO(), secGrp)
err = manager.TableSpec().InsertOrUpdate(context.TODO(), secGrp)
if err != nil {
log.Errorf("Insert default secgroup failed!!! %s", err)
return err
return errors.Wrapf(err, "Insert default secgroup")
}
defRule := SSecurityGroupRule{}
@@ -1032,8 +1035,7 @@ func (manager *SSecurityGroupManager) InitializeData() error {
defRule.SecgroupId = "default"
err = SecurityGroupRuleManager.TableSpec().Insert(context.TODO(), &defRule)
if err != nil {
log.Errorf("Insert default secgroup rule fail %s", err)
return err
return errors.Wrapf(err, "Insert default secgroup rule")
}
}
guests := make([]SGuest, 0)

View File

@@ -17,6 +17,7 @@ package options
import (
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
"yunion.io/x/onecloud/pkg/cloudcommon/pending_delete"
"yunion.io/x/onecloud/pkg/multicloud/esxi"
)
type ComputeOptions struct {
@@ -151,6 +152,10 @@ type ComputeOptions struct {
common_options.DBOptions
EnableAutoMergeSecurityGroup bool `help:"Enable auto merge secgroup when sync security group from cloud, default False" default:"false"`
DefaultNetworkGatewayAddressEsxi uint32 `help:"Default address for network gateway" default:"1"`
esxi.EsxiOptions
}
type SCapabilityOptions struct {

View File

@@ -0,0 +1,68 @@
// 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 regiondrivers
import (
"sort"
"testing"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
func TestQcloudRuleSync(t *testing.T) {
driver := SQcloudRegionDriver{}
maxPriority := driver.GetSecurityGroupRuleMaxPriority()
minPriority := driver.GetSecurityGroupRuleMinPriority()
defaultInRule := driver.GetDefaultSecurityGroupInRule()
defaultOutRule := driver.GetDefaultSecurityGroupOutRule()
order := driver.GetSecurityGroupRuleOrder()
isOnlyAllowRules := driver.IsOnlySupportAllowRules()
data := []TestData{
{
Name: "Test out rules",
LocalRules: secrules.SecurityRuleSet{
localRuleWithPriority("out:allow any", 11),
localRuleWithPriority("out:deny any", 10),
},
RemoteRules: []cloudprovider.SecurityRule{},
Common: []cloudprovider.SecurityRule{},
InAdds: []cloudprovider.SecurityRule{},
OutAdds: []cloudprovider.SecurityRule{
remoteRuleWithName("", "out:allow any", 100),
},
InDels: []cloudprovider.SecurityRule{},
OutDels: []cloudprovider.SecurityRule{},
},
}
for _, d := range data {
t.Logf("check %s", d.Name)
common, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(minPriority, maxPriority, order, d.LocalRules, d.RemoteRules, defaultInRule, defaultOutRule, isOnlyAllowRules, true)
sort.Sort(cloudprovider.SecurityRuleSet(common))
sort.Sort(cloudprovider.SecurityRuleSet(inAdds))
sort.Sort(cloudprovider.SecurityRuleSet(outAdds))
sort.Sort(cloudprovider.SecurityRuleSet(inDels))
sort.Sort(cloudprovider.SecurityRuleSet(outDels))
check(t, "common", common, d.Common)
check(t, "inAdds", inAdds, d.InAdds)
check(t, "outAdds", outAdds, d.OutAdds)
check(t, "inDels", inDels, d.InDels)
check(t, "outDels", outDels, d.OutDels)
}
}

View File

@@ -44,6 +44,7 @@ import (
_ "yunion.io/x/onecloud/pkg/compute/tasks"
"yunion.io/x/onecloud/pkg/controller/autoscaling"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/multicloud/esxi"
_ "yunion.io/x/onecloud/pkg/multicloud/loader"
)
@@ -64,6 +65,11 @@ func StartService() {
})
common_options.StartOptionManager(opts, opts.ConfigSyncPeriodSeconds, api.SERVICE_TYPE, api.SERVICE_VERSION, options.OnOptionsChange)
err := esxi.InitEsxiConfig(opts.EsxiOptions)
if err != nil {
log.Fatalf("unable to init esxi configs: %v", err)
}
if opts.FetchEtcdServiceInfoAndUseEtcdLock {
err := initEtcdLockOpts(opts)
if err != nil {

View File

@@ -60,7 +60,7 @@ func (self *BaremetalDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneM
func (self *BaremetalDeleteTask) OnDeleteBaremetalComplete(ctx context.Context, baremetal *models.SHost, body jsonutils.JSONObject) {
err := baremetal.RealDelete(ctx, self.UserCred)
if err != nil {
log.Errorln("RealDelete fail %s", err)
log.Errorf("RealDelete fail %s", err)
self.OnFailure(ctx, baremetal, jsonutils.Marshal(err))
return
}

View File

@@ -176,6 +176,10 @@ func (self *GuestBatchCreateTask) allocateGuestOnHost(ctx context.Context, guest
return err
}
if input.PublicIpBw > 0 {
input.Eip, input.EipBw = "", 0
}
// allocate eips
if input.EipBw > 0 {
eip, err := models.ElasticipManager.NewEipForVMOnHost(ctx, self.UserCred, guest, host, input.EipBw, input.EipChargeType, input.EipAutoDellocate, &pendingRegionUsage)

View File

@@ -14,7 +14,10 @@
package options
import common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
import (
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
"yunion.io/x/onecloud/pkg/multicloud/esxi"
)
type EsxiOptions struct {
common_options.CommonOptions
@@ -32,6 +35,7 @@ type EsxiOptions struct {
Zone string `help:"Zone where the agent locates"`
DeployServerSocketPath string `help:"Deploy server listen socket path" default:"/var/run/deploy.sock"`
HostDelayTaskWorkerCount int `default:"8" help:"Host delay worker thread count, default is 8"`
esxi.EsxiOptions
}
var (

View File

@@ -31,6 +31,7 @@ import (
"yunion.io/x/onecloud/pkg/hostman/guestfs/fsdriver"
"yunion.io/x/onecloud/pkg/hostman/hostdeployer/deployclient"
"yunion.io/x/onecloud/pkg/hostman/hostutils"
mcesxi "yunion.io/x/onecloud/pkg/multicloud/esxi"
)
type SExsiAgentService struct {
@@ -75,6 +76,8 @@ func (s *SExsiAgentService) StartService() {
app := app_common.InitApp(&options.Options.BaseOptions, false)
handler.InitHandlers(app)
mcesxi.InitEsxiConfig(options.Options.EsxiOptions)
s.startAgent(app)
app_common.ServeForeverWithCleanup(app, &options.Options.BaseOptions, func() {

View File

@@ -1035,7 +1035,7 @@ func (s *SGuestSnapshotDeleteTask) onReloadBlkdevSucc(err string) {
func (s *SGuestSnapshotDeleteTask) onSnapshotBlkdevFail(res string) {
snapshotPath := path.Join(s.disk.GetSnapshotDir(), s.convertSnapshot)
if output, err := procutils.NewCommand("mv", "-f", s.tmpPath, snapshotPath).Output(); err != nil {
log.Errorln("mv %s to %s failed: %s, %s", s.tmpPath, snapshotPath, err, output)
log.Errorf("mv %s to %s failed: %s, %s", s.tmpPath, snapshotPath, err, output)
}
s.taskFailed("Reload blkdev failed")
}

View File

@@ -386,7 +386,7 @@ func (s *SGuestMonitorCollector) reportIo(curInfo, prevInfo jsonutils.JSONObject
prev, _ := prevInfo.GetString(field)
fcur, _ := strconv.ParseFloat(cur, 64)
fprev, _ := strconv.ParseFloat(prev, 64)
ioInfo.Set(s.GetIoFiledName(field), jsonutils.NewFloat((fcur-fprev)/float64(diffTime)))
ioInfo.Set(s.GetIoFiledName(field), jsonutils.NewFloat64((fcur-fprev)/float64(diffTime)))
}
}
return ioInfo
@@ -515,11 +515,11 @@ func (m *SGuestMonitor) Cpu() jsonutils.JSONObject {
cpuTimes, _ := m.Process.Times()
ret := jsonutils.NewDict()
percent, _ = strconv.ParseFloat(fmt.Sprintf("%0.4f", percent/float64(m.CpuCnt)), 64)
ret.Set("usage_active", jsonutils.NewFloat(percent))
ret.Set("cpu_usage_idle_pcore", jsonutils.NewFloat(100-percent/float64(m.CpuCnt)))
ret.Set("cpu_usage_pcore", jsonutils.NewFloat(percent/float64(m.CpuCnt)))
ret.Set("cpu_time_user", jsonutils.NewFloat(cpuTimes.User))
ret.Set("cpu_time_system", jsonutils.NewFloat(cpuTimes.System))
ret.Set("usage_active", jsonutils.NewFloat64(percent))
ret.Set("cpu_usage_idle_pcore", jsonutils.NewFloat64(100-percent/float64(m.CpuCnt)))
ret.Set("cpu_usage_pcore", jsonutils.NewFloat64(percent/float64(m.CpuCnt)))
ret.Set("cpu_time_user", jsonutils.NewFloat64(cpuTimes.User))
ret.Set("cpu_time_system", jsonutils.NewFloat64(cpuTimes.System))
ret.Set("cpu_count", jsonutils.NewInt(int64(m.CpuCnt)))
threadCnt, _ := m.Process.NumThreads()
@@ -558,6 +558,6 @@ func (m *SGuestMonitor) Mem() jsonutils.JSONObject {
ret := jsonutils.NewDict()
ret.Set("rss", jsonutils.NewInt(int64(mem.RSS)))
ret.Set("vms", jsonutils.NewInt(int64(mem.VMS)))
ret.Set("used_percent", jsonutils.NewFloat(float64(used_percent)))
ret.Set("used_percent", jsonutils.NewFloat64(float64(used_percent)))
return ret
}

View File

@@ -144,7 +144,7 @@ func (d *SLocalDisk) Resize(ctx context.Context, params interface{}) (jsonutils.
sizeMb, _ := diskInfo.Int("size")
disk, err := qemuimg.NewQemuImage(d.GetPath())
if err != nil {
log.Errorln(err)
log.Errorf("qemuimg.NewQemuImage %s fail: %s", d.GetPath(), err)
return nil, err
}
if err := disk.Resize(int(sizeMb)); err != nil {
@@ -163,15 +163,13 @@ func (d *SLocalDisk) Resize(ctx context.Context, params interface{}) (jsonutils.
func (d *SLocalDisk) CreateFromImageFuse(ctx context.Context, url string, size int64) error {
log.Infof("Create from image fuse %s", url)
var (
localPath = d.Storage.GetFuseTmpPath()
mntPath = path.Join(d.Storage.GetFuseMountPath(), d.Id)
contentPath = path.Join(mntPath, "content")
newImg, err = qemuimg.NewQemuImage(d.getPath())
)
localPath := d.Storage.GetFuseTmpPath()
mntPath := path.Join(d.Storage.GetFuseMountPath(), d.Id)
contentPath := path.Join(mntPath, "content")
newImg, err := qemuimg.NewQemuImage(d.getPath())
if err != nil {
log.Errorln(err)
log.Errorf("qemuimg.NewQemuImage %s fail: %s", d.getPath(), err)
return err
}
@@ -344,14 +342,14 @@ func (d *SLocalDisk) CreateSnapshot(snapshotId string) error {
if !fileutils2.Exists(snapshotDir) {
output, err := procutils.NewCommand("mkdir", "-p", snapshotDir).Output()
if err != nil {
log.Errorln("mkdir %s failed: %s", snapshotDir, output)
log.Errorf("mkdir %s failed: %s", snapshotDir, output)
return errors.Wrapf(err, "mkdir %s failed: %s", snapshotDir, output)
}
}
snapshotPath := path.Join(snapshotDir, snapshotId)
output, err := procutils.NewCommand("mv", "-f", d.getPath(), snapshotPath).Output()
if err != nil {
log.Errorln("mv %s to %s failed %s", d.getPath(), snapshotPath, output)
log.Errorf("mv %s to %s failed %s", d.getPath(), snapshotPath, output)
return errors.Wrapf(err, "mv %s to %s failed %s", d.getPath(), snapshotPath, output)
}
img, err := qemuimg.NewQemuImage(d.getPath())

View File

@@ -211,23 +211,13 @@ func (c *SAgentImageCacheManager) prefetchImageCacheByUpload(ctx context.Context
}
func (c *SAgentImageCacheManager) perfetchTemplateVMImageCache(ctx context.Context, data *sImageCacheData) (jsonutils.JSONObject, error) {
client, err := esxi.NewESXiClientFromAccessInfo(ctx, &data.Datastore)
if err != nil {
return nil, errors.Wrap(err, "esxi.NewESXiClientFromJson")
}
// data.StorageCacheExternalId is Host Ip associated with the StorageCache in where CachedImage stored
host, err := client.FindHostByIp(data.StorageCacheHostIp)
_, err = client.SearchTemplateVM(data.ImageExternalId)
if err != nil {
return nil, err
}
dc, err := host.GetDatacenter()
if err != nil {
return nil, errors.Wrap(err, "host.GetDatacenter")
}
_, err = dc.FetchTemplateVMById(data.ImageExternalId)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "SEsxiClient.SearchTemplateVM for image %q", data.ImageExternalId)
}
res := jsonutils.NewDict()
res.Add(jsonutils.NewString(data.ImageExternalId), "image_id")

View File

@@ -310,10 +310,9 @@ func (as *SAgentStorage) AgentDeployGuest(ctx context.Context, data interface{})
}
array := jsonutils.NewArray()
diskArray, _ := desc.GetArray("disks")
for idx, d := range disks {
for _, d := range disks {
disk := d.(*esxi.SVirtualDisk)
diskId, _ := diskArray[idx].GetString("disk_id")
diskId := disk.GetId()
diskDict := jsonutils.NewDict()
diskDict.Add(jsonutils.NewString(diskId), "disk_id")
diskDict.Add(jsonutils.NewString(disk.GetGlobalId()), "uuid")

View File

@@ -145,6 +145,8 @@ func syncScopeResourceCount(ctx context.Context, regionId string, serviceId stri
ownerList = append(ownerList, scopeRes.OwnerId)
}
scopeRes.SetModelManager(models.ScopeResourceManager, &scopeRes)
err := models.ScopeResourceManager.TableSpec().InsertOrUpdate(ctx, &scopeRes)
if err != nil {
log.Errorf("table insert error %s", err)

View File

@@ -181,7 +181,7 @@ func (self *SLDAPDriver) syncUsers(ctx context.Context, cli *ldaputils.SLDAPClie
if err != nil {
return nil, errors.Wrap(err, "searchLDAP")
}
log.Debugf("syncUsers: ldapSearch entries: %s", entries)
log.Debugf("syncUsers: ldapSearch entries: %#v", entries)
userIds := make([]string, 0)
userIdMap := make(map[string]string)
for i := range entries {
@@ -241,13 +241,13 @@ func (self *SLDAPDriver) syncUserDB(ctx context.Context, ui SUserInfo, domainId
// } else {
// user.Enabled = tristate.False
// }
if val, ok := ui.Extra["email"]; ok && len(val) > 0 && len(user.Email) > 0 {
if val, ok := ui.Extra["email"]; ok && len(val) > 0 && len(user.Email) == 0 {
user.Email = val
}
if val, ok := ui.Extra["displayname"]; ok && len(val) > 0 && len(user.Displayname) > 0 {
if val, ok := ui.Extra["displayname"]; ok && len(val) > 0 && len(user.Displayname) == 0 {
user.Displayname = val
}
if val, ok := ui.Extra["mobile"]; ok && len(val) > 0 && len(user.Mobile) > 0 {
if val, ok := ui.Extra["mobile"]; ok && len(val) > 0 && len(user.Mobile) == 0 {
user.Mobile = val
}
})

View File

@@ -463,6 +463,7 @@ func roleAssignmentHandler(ctx context.Context, w http.ResponseWriter, r *http.R
input.Roles,
input.Domains,
input.Projects,
input.ProjectDomains,
includeNames, effective, includeSub, includeSystem, includePolicies,
limit, offset)
@@ -481,7 +482,7 @@ func roleAssignmentHandler(ctx context.Context, w http.ResponseWriter, r *http.R
func (manager *SAssignmentManager) queryAll(
userId, groupId, roleId, domainId, projectId string,
users, groups, roles, domains, projects []string,
users, groups, roles, domains, projects, projectDomains []string,
) *sqlchemy.SQuery {
assigments := manager.Query().SubQuery()
q := assigments.Query(
@@ -562,6 +563,17 @@ func (manager *SAssignmentManager) queryAll(
))
q = q.In("project_id", subq.SubQuery()).In("type", []string{api.AssignmentUserProject, api.AssignmentGroupProject})
}
if len(projectDomains) > 0 {
subq := ProjectManager.Query("id")
domainQ := DomainManager.Query("id", "name").SubQuery()
subq = subq.Join(domainQ, sqlchemy.Equals(subq.Field("domain_id"), domainQ.Field("id")))
subq = subq.Filter(sqlchemy.OR(
sqlchemy.In(domainQ.Field("id"), projectDomains),
sqlchemy.ContainsAny(domainQ.Field("name"), projectDomains),
))
q = q.In("project_id", subq.SubQuery()).In("type", []string{api.AssignmentUserProject, api.AssignmentGroupProject})
}
if len(domainId) > 0 {
q = q.Equals("domain_id", domainId).In("type", []string{api.AssignmentUserDomain, api.AssignmentGroupDomain})
}
@@ -626,16 +638,16 @@ func (assign *sAssignmentInternal) getRoleAssignment(domains, projects, groups,
func (manager *SAssignmentManager) FetchAll(
userId, groupId, roleId, domainId, projectId string,
userStrs, groupStrs, roleStrs, domainStrs, projectStrs []string,
userStrs, groupStrs, roleStrs, domainStrs, projectStrs, projectDomainStrs []string,
includeNames, effective, includeSub, includeSystem, includePolicies bool,
limit, offset int) ([]api.SRoleAssignment, int64, error) {
var q *sqlchemy.SQuery
if effective {
usrq := manager.queryAll(userId, "", roleId, domainId, projectId, userStrs, nil, roleStrs, domainStrs, projectStrs).In("type", []string{api.AssignmentUserProject, api.AssignmentUserDomain})
usrq := manager.queryAll(userId, "", roleId, domainId, projectId, userStrs, nil, roleStrs, domainStrs, projectStrs, projectDomainStrs).In("type", []string{api.AssignmentUserProject, api.AssignmentUserDomain})
memberships := UsergroupManager.Query("user_id", "group_id").SubQuery()
grpproj := manager.queryAll("", groupId, roleId, domainId, projectId, nil, groupStrs, roleStrs, domainStrs, projectStrs).In("type", []string{api.AssignmentGroupProject, api.AssignmentGroupDomain}).SubQuery()
grpproj := manager.queryAll("", groupId, roleId, domainId, projectId, nil, groupStrs, roleStrs, domainStrs, projectStrs, projectDomainStrs).In("type", []string{api.AssignmentGroupProject, api.AssignmentGroupDomain}).SubQuery()
q2 := grpproj.Query(
grpproj.Field("type"),
memberships.Field("user_id"),
@@ -659,7 +671,7 @@ func (manager *SAssignmentManager) FetchAll(
q = sqlchemy.Union(usrq, q2).Query().Distinct()
} else {
q = manager.queryAll(userId, groupId, roleId, domainId, projectId, userStrs, groupStrs, roleStrs, domainStrs, projectStrs).Distinct()
q = manager.queryAll(userId, groupId, roleId, domainId, projectId, userStrs, groupStrs, roleStrs, domainStrs, projectStrs, projectDomainStrs).Distinct()
}
if !includeSystem {

View File

@@ -19,6 +19,7 @@ import (
"net/http"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
@@ -222,6 +223,7 @@ func verifyCommon(ctx context.Context, w http.ResponseWriter, tokenStr string) (
token := SAuthToken{}
err := token.ParseFernetToken(tokenStr)
if err != nil {
log.Errorf("ParseFernetToken %s fail: %s", tokenStr, err)
return nil, httperrors.NewInvalidCredentialError("invalid token")
}
return &token, nil

View File

@@ -292,7 +292,7 @@ func (t *SAuthToken) getTokenV3(
token.Token.Projects[i].Domain.Name = extProjs[i].DomainName
}*/
assigns, _, err := models.AssignmentManager.FetchAll(user.Id, "", "", "", "",
nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil,
true, true, true, true, true, 0, 0)
if err != nil {
return nil, errors.Wrap(err, "models.AssignmentManager.FetchAll")

View File

@@ -141,6 +141,10 @@ func (this *RoleAssignmentManagerV3) GetProjectUsers(s *mcclient.ClientSession,
query.Add(jsonutils.JSONNull, "effective")
}
if jsonutils.QueryBoolean(params, "system", false) {
query.Add(jsonutils.JSONNull, "include_system")
}
resource, e := params.GetString("resource")
if e != nil {
return jsonutils.JSONNull, e
@@ -224,6 +228,10 @@ func (this *RoleAssignmentManagerV3) GetProjectRole(s *mcclient.ClientSession, i
query.Add(jsonutils.JSONNull, "effective")
}
if jsonutils.QueryBoolean(params, "system", false) {
query.Add(jsonutils.JSONNull, "include_system")
}
resource, err := params.GetString("resource")
if err != nil {
return jsonutils.JSONNull, err

View File

@@ -51,7 +51,7 @@ type SInfluxdbShemaManager struct {
func NewSuggestSysRuleManager() *SSuggestSysRuleManager {
man := NewMonitorV2Manager("suggestsysrule", "suggestsysrules",
[]string{"id", "name", "type", "enabled", "setting"},
[]string{"id", "name", "type", "enabled", "period", "time_from", "setting"},
[]string{})
return &SSuggestSysRuleManager{
ResourceManager: &man,

View File

@@ -116,7 +116,7 @@ func optionsStructRvToParams(rv reflect.Value) (*jsonutils.JSONDict, error) {
rv64 := f.Convert(gotypes.Float64Type)
f64 := rv64.Interface().(float64)
if f64 != 0 || !jsonInfo.OmitZero {
p.Set(name, jsonutils.NewFloat(f64))
p.Set(name, jsonutils.NewFloat64(f64))
}
case reflect.String:
s := f.Interface().(string)

View File

@@ -27,10 +27,36 @@ type SuggestRuleListOptions struct {
options.BaseListOptions
}
func (o *SuggestRuleListOptions) Params() (jsonutils.JSONObject, error) {
return options.ListStructToParams(o)
}
type SuggestRuleShowOptions struct {
ID string `help:"ID or name of the alert" json:"-"`
}
func (o *SuggestRuleShowOptions) Params() (jsonutils.JSONObject, error) {
return options.StructToParams(o)
}
func (o *SuggestRuleShowOptions) GetId() string {
return o.ID
}
type SuggestRuleConfigOptions struct {
ID string `help:"ID or name of the alert" json:"-"`
Period string `help:"Period of suggest rule e.g. '5s', '1m'"`
TimeFrom string `help:"TimeFrom of suggest rule e.g. '24h'"`
}
func (o *SuggestRuleConfigOptions) Params() (jsonutils.JSONObject, error) {
return options.StructToParams(o)
}
func (o *SuggestRuleConfigOptions) GetId() string {
return o.ID
}
type SuggestSysRuleAlertSettingOptions struct {
Status string `help:"Status of eip_unused rule"`
}
@@ -43,7 +69,7 @@ type SuggestRuleCreateOptions struct {
Period string `help:"Period of suggest rule e.g. '5s', '1m'" default:"30s"`
}
func (opt SuggestRuleCreateOptions) Params() (jsonutils.JSONObject, error) {
func (opt *SuggestRuleCreateOptions) Params() (jsonutils.JSONObject, error) {
input := new(monitor.SuggestSysRuleCreateInput)
input.Name = opt.Name
input.Period = opt.Period
@@ -119,5 +145,13 @@ func newSuggestSysAlertSetting(tp string) *monitor.SSuggestSysAlertSetting {
}
type SuggestRuleDeleteOptions struct {
ID []string `help:"ID of alert to delete"`
ID string `help:"ID of alert to delete"`
}
func (o *SuggestRuleDeleteOptions) GetId() string {
return o.ID
}
func (o *SuggestRuleDeleteOptions) Params() (jsonutils.JSONObject, error) {
return options.StructToParams(o)
}

View File

@@ -40,6 +40,9 @@ type NetworkListOptions struct {
IsClassic *bool `help:"search classic on-premise network"`
Status string `help:"filter by network status"`
GuestIpStart []string `help:"search by guest_ip_start"`
GuestIpEnd []string `help:"search by guest_ip_end"`
}
func (opts *NetworkListOptions) GetContextId() string {

View File

@@ -67,6 +67,10 @@ type ServerListOptions struct {
BaseListOptions
VpcProvider string `help:"filter by vpc's provider" json:"vpc_provider"`
WithMeta *bool `help:"filter by metadata" negative:"without_meta"`
WithUserMeta *bool `help:"filter by user metadata" negative:"without_user_meta"`
}
func (o *ServerListOptions) Params() (jsonutils.JSONObject, error) {
@@ -387,6 +391,9 @@ type ServerCreateOptionalOptions struct {
EipChargeType string `help:"newly allocated EIP charge type" choices:"traffic|bandwidth" json:"eip_charge_type,omitempty"`
Eip string `help:"associate with an existing EIP when server is created" json:"eip,omitempty"`
PublicIpBw int `help:"associate public ip with bandwidth in MB where server is created" json:"public_ip_bw,omitzero"`
PublicIpChargeType string `help:"newly allocated public ip charge type" choices:"traffic|bandwidth" json:"public_ip_charge_type,omitempty"`
GuestImageID string `help:"create from guest image, need to specify the guest image id"`
}

View File

@@ -55,7 +55,7 @@ type SAlertManager struct {
//db.SVirtualResourceBaseManager
db.SEnabledResourceBaseManager
db.SStatusStandaloneResourceBaseManager
db.SScopedResourceBaseManager
SMonitorScopedResourceManager
//db.SStatusResourceBaseManager
tester AlertTestRunner
@@ -112,7 +112,7 @@ type SAlert struct {
//db.SVirtualResourceBase
db.SEnabledResourceBase
db.SStatusStandaloneResourceBase
db.SScopedResourceBase
SMonitorScopedResource
//db.SStatusResourceBase
// Frequency is evaluate period

View File

@@ -101,12 +101,12 @@ func (man *SAlertDashBoardManager) ValidateCreateData(
for _, query := range data.CommonMetricInputQuery.MetricQuery {
if len(query.Comparator) != 0 {
if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) {
return data, httperrors.NewInputParameterError("the Comparator is illegal:", query.Comparator)
return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator)
}
}
if len(query.Reduce) != 0 {
if _, ok := monitor.AlertReduceFunc[query.Reduce]; !ok {
return data, httperrors.NewInputParameterError("the reduce is illegal", query.Reduce)
return data, httperrors.NewInputParameterError("the reduce is illegal %s", query.Reduce)
}
}
}
@@ -249,12 +249,12 @@ func (dash *SAlertDashBoard) ValidateUpdateData(
}
if len(query.Comparator) != 0 {
if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) {
return data, httperrors.NewInputParameterError("the Comparator is illegal:", query.Comparator)
return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator)
}
}
if len(query.Reduce) != 0 {
if _, ok := monitor.AlertReduceFunc[query.Reduce]; !ok {
return data, httperrors.NewInputParameterError("the reduce is illegal", query.Reduce)
return data, httperrors.NewInputParameterError("the reduce is illegal: %s", query.Reduce)
}
}
}

View File

@@ -21,14 +21,14 @@ var (
type SAlertRecordManager struct {
db.SEnabledResourceBaseManager
db.SStatusStandaloneResourceBaseManager
db.SScopedResourceBaseManager
SMonitorScopedResourceManager
}
type SAlertRecord struct {
//db.SVirtualResourceBase
db.SEnabledResourceBase
db.SStatusStandaloneResourceBase
db.SScopedResourceBase
SMonitorScopedResource
AlertId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
Level string `charset:"ascii" width:"36" nullable:"false" default:"normal" list:"user" update:"user"`

View File

@@ -104,10 +104,10 @@ func (man *SCommonAlertManager) ValidateCreateData(
} else {
for _, query := range data.CommonMetricInputQuery.MetricQuery {
if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) {
return data, httperrors.NewInputParameterError("the Comparator is illegal:", query.Comparator)
return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator)
}
if _, ok := monitor.AlertReduceFunc[query.Reduce]; !ok {
return data, httperrors.NewInputParameterError("the reduce is illegal", query.Reduce)
return data, httperrors.NewInputParameterError("the reduce is illegal: %s", query.Reduce)
}
if query.Threshold == 0 {
return data, httperrors.NewInputParameterError("threshold is meaningless")
@@ -669,10 +669,10 @@ func (alert *SCommonAlert) ValidateUpdateData(
return data, errors.Wrap(err, "metric_query Unmarshal error")
}
if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) {
return data, httperrors.NewInputParameterError("the Comparator is illegal:", query.Comparator)
return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator)
}
if _, ok := monitor.AlertReduceFunc[query.Reduce]; !ok {
return data, httperrors.NewInputParameterError("the reduce is illegal", query.Reduce)
return data, httperrors.NewInputParameterError("the reduce is illegal: %s", query.Reduce)
}
if query.Threshold == 0 {
return data, httperrors.NewInputParameterError("threshold is meaningless")

View File

@@ -0,0 +1,46 @@
package models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SMonitorScopedResourceManager struct {
db.SScopedResourceBaseManager
}
type SMonitorScopedResource struct {
db.SScopedResourceBase
}
func (m *SMonitorScopedResourceManager) FilterByOwner(q *sqlchemy.SQuery, userCred mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
if userCred == nil {
return q
}
switch scope {
case rbacutils.ScopeDomain:
q = q.Equals("domain_id", userCred.GetProjectDomainId())
case rbacutils.ScopeProject:
q = q.Equals("tenant_id", userCred.GetProjectId())
}
return q
}
func (manager *SMonitorScopedResourceManager) ResourceScope() rbacutils.TRbacScope {
return manager.SScopedResourceBaseManager.ResourceScope()
}
func (manager *SMonitorScopedResourceManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
return manager.SScopedResourceBaseManager.FetchOwnerId(ctx, data)
}
func (model *SMonitorScopedResource) GetOwnerId() mcclient.IIdentityProvider {
return model.SScopedResourceBase.GetOwnerId()
}

View File

@@ -167,7 +167,7 @@ func (man *SSuggestSysRuleManager) ValidateCreateData(
return data, err
}
} else if rule != nil {
return data, httperrors.NewDuplicateResourceError("type %s rule already exists")
return data, httperrors.NewDuplicateResourceError("type %s rule already exists", data.Type)
}
drvType := monitor.SuggestDriverType(data.Type)
@@ -311,6 +311,42 @@ func (self *SSuggestSysRule) PerformDisable(ctx context.Context, userCred mcclie
return nil, nil
}
func (self *SSuggestSysRule) AllowPerformConfig(ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowPerform(userCred, self, "config")
}
func (self *SSuggestSysRule) PerformConfig(ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
period, _ := data.GetString("period")
timeFrom, _ := data.GetString("time_from")
if len(period) != 0 {
period = parseDuration(period)
if _, err := time.ParseDuration(period); err != nil {
return data, httperrors.NewInputParameterError("Invalid period format: %s", period)
}
}
if len(timeFrom) != 0 {
timeFrom = parseDuration(timeFrom)
if _, err := time.ParseDuration(timeFrom); err != nil {
return data, httperrors.NewInputParameterError("Invalid time_from format: %s", timeFrom)
}
}
db.Update(self, func() error {
if len(period) != 0 {
self.Period = period
}
if len(timeFrom) != 0 {
self.TimeFrom = timeFrom
}
return nil
})
db.OpsLog.LogEvent(self, "modifyconfig", "", userCred)
self.updateCronjob()
return nil, nil
}
func (self *SSuggestSysRuleManager) AllowGetPropertyRuleType(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return true
}

View File

@@ -52,12 +52,12 @@ func init() {
// +onecloud:swagger-gen-model-plural=suggestsysruleconfigs
type SSuggestSysRuleConfigManager struct {
db.SStandaloneResourceBaseManager
db.SScopedResourceBaseManager
SMonitorScopedResourceManager
}
type SSuggestSysRuleConfig struct {
db.SStandaloneResourceBase
db.SScopedResourceBase
SMonitorScopedResource
// RuleId is SSuggestSysRule model object id
// RuleId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
@@ -166,7 +166,7 @@ func (man *SSuggestSysRuleConfigManager) createFromDriver(ctx context.Context, s
}
config.SetModelManager(man, config)
ownerId := config.GetOwnerId()
ownerId := config.SMonitorScopedResource.GetOwnerId()
data := monitor.SuggestSysRuleConfigCreateInput{}
data.Scope = string(scope)
data.ProjectDomainId = ownerId.GetProjectDomainId()

View File

@@ -230,7 +230,7 @@ func describeEvalResultTojson(evalMatchsMap map[string][]*monitor.EvalMatch, map
idTag := getMetricIdTag(evalMatch.Tags)
if val, ok := idTag[mappingId]; ok {
if val == mappingVal {
problem.Add(jsonutils.NewFloat(*evalMatch.Value), evalMatch.Metric)
problem.Add(jsonutils.NewFloat64(*evalMatch.Value), evalMatch.Metric)
}
}
}

View File

@@ -136,6 +136,11 @@ func jsonRequest(client *sdk.Client, domain, apiVersion, apiName string, params
}
}
for _, code := range []string{
"EOF",
"i/o timeout",
"TLS handshake timeout",
"connection reset by peer",
"server misbehaving",
"SignatureNonceUsed",
"InvalidInstance.NotSupported",
"try later",

View File

@@ -15,6 +15,7 @@
package esxi
import (
"regexp"
"strings"
"github.com/vmware/govmomi/object"
@@ -243,6 +244,59 @@ func (dc *SDatacenter) getDcObj() *object.Datacenter {
return object.NewDatacenter(dc.manager.client.Client, dc.object.Reference())
}
func (dc *SDatacenter) fetchMoVms(filter property.Filter, props []string) ([]mo.VirtualMachine, error) {
odc := dc.getObjectDatacenter()
root := odc.Reference()
var movms []mo.VirtualMachine
err := dc.manager.scanMObjectsWithFilter(root, props, &movms, filter)
if err != nil {
return nil, errors.Wrap(err, "scanMObjectsWithFilter")
}
return movms, nil
}
func (dc *SDatacenter) moVms2Vm(movms []mo.VirtualMachine, all *bool) ([]*SVirtualMachine, error) {
// avoid applying new memory and copying
vms := make([]*SVirtualMachine, 0, len(movms))
for i := range movms {
if (all != nil && *all) || !strings.HasPrefix(movms[i].Name, api.ESXI_IMAGE_CACHE_TMP_PREFIX) {
vm := NewVirtualMachine(dc.manager, &movms[i], dc)
// must
if vm == nil {
continue
}
vms = append(vms, vm)
}
}
return vms, nil
}
func (dc *SDatacenter) fetchFakeTemplateVMs(movms []mo.VirtualMachine, regex string) ([]*SVirtualMachine, error) {
var (
tNameRegex *regexp.Regexp
err error
)
if len(regex) == 0 {
tNameRegex = tempalteNameRegex
} else {
tNameRegex, err = regexp.Compile(regex)
if err != nil {
return nil, errors.Wrap(err, "generate regexp")
}
}
objs := make([]types.ManagedObjectReference, 0)
for i := range movms {
name := movms[i].Name
if tNameRegex != nil && tNameRegex.MatchString(name) {
objs = append(objs, movms[i].Reference())
}
}
if len(objs) == 0 {
return nil, nil
}
return dc.fetchVms(objs, false)
}
func (dc *SDatacenter) fetchVms(vmRefs []types.ManagedObjectReference, all bool) ([]*SVirtualMachine, error) {
var movms []mo.VirtualMachine
if vmRefs != nil {
@@ -251,15 +305,7 @@ func (dc *SDatacenter) fetchVms(vmRefs []types.ManagedObjectReference, all bool)
return nil, errors.Wrap(err, "dc.manager.references2Objects")
}
}
// avoid applying new memory and copying
vms := make([]*SVirtualMachine, 0, len(movms))
for i := range movms {
if all || !strings.HasPrefix(movms[i].Entity().Name, api.ESXI_IMAGE_CACHE_TMP_PREFIX) {
vms = append(vms, NewVirtualMachine(dc.manager, &movms[i], dc))
}
}
return vms, nil
return dc.moVms2Vm(movms, &all)
}
func (dc *SDatacenter) fetchHosts_(vmRefs []types.ManagedObjectReference, all bool) ([]*SHost, error) {
@@ -282,32 +328,35 @@ func (dc *SDatacenter) fetchHosts_(vmRefs []types.ManagedObjectReference, all bo
}
func (dc *SDatacenter) FetchVMs() ([]*SVirtualMachine, error) {
return dc.fetchVMs(property.Filter{})
return dc.fetchVMsWithFilter(property.Filter{})
}
func (dc *SDatacenter) FetchNoTemplateVMs() ([]*SVirtualMachine, error) {
filter := property.Filter{}
filter["config.template"] = false
return dc.fetchVMs(filter)
return dc.fetchVMsWithFilter(filter)
}
func (dc *SDatacenter) fetchVMs(filter property.Filter) ([]*SVirtualMachine, error) {
odc := dc.getObjectDatacenter()
root := odc.Reference()
m := view.NewManager(dc.manager.client.Client)
v, err := m.CreateContainerView(dc.manager.context, root, []string{"VirtualMachine"}, true)
func (dc *SDatacenter) FetchFakeTempateVMs(regex string) ([]*SVirtualMachine, error) {
filter := property.Filter{}
filter["summary.runtime.powerState"] = types.VirtualMachinePowerStatePoweredOff
movms, err := dc.fetchMoVms(filter, []string{"name"})
if err != nil {
return nil, err
return nil, errors.Wrap(err, "unable to fetch mo.VirtualMachines")
}
defer func() {
_ = v.Destroy(dc.manager.context)
}()
objs, err := v.Find(dc.manager.context, []string{"VirtualMachine"}, filter)
return dc.fetchFakeTemplateVMs(movms, regex)
}
func (dc *SDatacenter) fetchVMsWithFilter(filter property.Filter) ([]*SVirtualMachine, error) {
movms, err := dc.fetchMoVms(filter, VIRTUAL_MACHINE_PROPS)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "unable to fetch mo.VirtualMachines")
}
vms, err := dc.fetchVms(objs, false)
return vms, err
ret, err := dc.moVms2Vm(movms, nil)
if err != nil {
return nil, errors.Wrap(err, "unable to convert mo.VirtualMachine to VirtualMachine")
}
return ret, err
}
func (dc *SDatacenter) FetchNoTemplateVMEntityReferens() ([]types.ManagedObjectReference, error) {
@@ -371,14 +420,14 @@ func (dc *SDatacenter) fetchHosts(filter property.Filter) ([]*SHost, error) {
func (dc *SDatacenter) FetchTemplateVMs() ([]*SVirtualMachine, error) {
filter := property.Filter{}
filter["config.template"] = true
return dc.fetchVMs(filter)
return dc.fetchVMsWithFilter(filter)
}
func (dc *SDatacenter) FetchTemplateVMById(id string) (*SVirtualMachine, error) {
filter := property.Filter{}
filter["config.template"] = true
filter["summary.config.uuid"] = id
vms, err := dc.fetchVMs(filter)
vms, err := dc.fetchVMsWithFilter(filter)
if err != nil {
return nil, err
}
@@ -391,7 +440,7 @@ func (dc *SDatacenter) FetchTemplateVMById(id string) (*SVirtualMachine, error)
func (dc *SDatacenter) FetchVMById(id string) (*SVirtualMachine, error) {
filter := property.Filter{}
filter["summary.config.uuid"] = id
vms, err := dc.fetchVMs(filter)
vms, err := dc.fetchVMsWithFilter(filter)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,6 @@ import (
"context"
"fmt"
"regexp"
"sort"
"strings"
"time"
@@ -728,18 +727,9 @@ func (self *SHost) CreateVM2(ctx context.Context, ds *SDatastore, params SCreate
if imageInfo.ImageType != cloudprovider.CachedImageTypeSystem {
return self.DoCreateVM(ctx, ds, params)
}
// get host
imgHost, err := self.manager.FindHostByIp(imageInfo.StorageCacheHostIp)
temvm, err := self.manager.SearchTemplateVM(imageInfo.ImageExternalId)
if err != nil {
return nil, errors.Wrap(err, "SEsxiClient.FindHostByIp")
}
dc, err := imgHost.GetDatacenter()
if err != nil {
return nil, errors.Wrap(err, "host.GetDatacenter")
}
temvm, err := dc.FetchTemplateVMById(imageInfo.ImageExternalId)
if err != nil {
return nil, errors.Wrapf(err, "datacenter.TemplateVMById for image %q and datacenter %q", imageInfo.ImageExternalId, dc.GetId())
return nil, errors.Wrapf(err, "SEsxiClient.SearchTemplateVM for image %q", imageInfo.ImageExternalId)
}
return self.CloneVM(ctx, temvm, ds, params)
}
@@ -922,7 +912,11 @@ func (self *SHost) DoCreateVM(ctx context.Context, ds *SDatastore, params SCreat
return nil, errors.Wrap(err, "fail to fetch virtual machine just created")
}
return NewVirtualMachine(self.manager, &moVM, self.datacenter), nil
evm := NewVirtualMachine(self.manager, &moVM, self.datacenter)
if evm == nil {
return nil, errors.Error("create successfully but unable to NewVirtualMachine")
}
return evm, nil
}
func (host *SHost) CloneVM(ctx context.Context, from *SVirtualMachine, ds *SDatastore, params SCreateVMParam) (*SVirtualMachine, error) {
@@ -972,69 +966,59 @@ func (host *SHost) CloneVM(ctx context.Context, from *SVirtualMachine, ds *SData
}
}
// check scsi controller
var ctlKey int32
scsiDevs, err := from.FindController(ctx, "scsi")
if err != nil {
return nil, errors.Wrap(err, "SVirtualMachine.FindController")
}
if len(scsiDevs) == 0 {
key := from.FindMinDiffKey(1000)
driver := "pvscsi"
if host.isVersion50() {
driver = "scsi"
}
deviceChange = append(deviceChange, addDevSpec(NewSCSIDev(key, 100, driver)))
ctlKey = key
} else {
ctlKey = minDevKey(scsiDevs)
}
// change disk if set
newSizes := make([]int64, 0, len(from.vdisks))
if params.Disks != nil && len(params.Disks) > 0 {
var (
i int
disk SDiskInfo
)
// resize existed disk
for i, disk = range params.Disks {
if i == len(from.vdisks) {
break
if len(params.Disks) > 0 {
driver := params.Disks[0].Driver
if driver == "scsi" || driver == "pvscsi" {
scsiDevs, err := from.FindController(ctx, "scsi")
if err != nil {
return nil, errors.Wrap(err, "SVirtualMachine.FindController")
}
size := disk.Size
if size == 0 {
size = 30 * 1024
}
newSizes = append(newSizes, size)
}
// create new disk
if i == len(from.vdisks) {
// find same disk
var index int32
var key int32 = 2000
sameDisk := from.FindDiskByDriver("scsi", "pvscsi")
index += int32(len(sameDisk))
if index >= 7 {
index++
}
if len(sameDisk) > 0 {
key = minDiskKey(sameDisk)
}
for ; i < len(params.Disks); i++ {
size := params.Disks[i].Size
if size == 0 {
size = 30 * 1024
if len(scsiDevs) == 0 {
key := from.FindMinDiffKey(1000)
driver := "pvscsi"
if host.isVersion50() {
driver = "scsi"
}
uuid := params.Disks[i].DiskId
spec := addDevSpec(NewDiskDev(size, "", uuid, index, key, ctlKey, 0))
spec.FileOperation = "create"
deviceChange = append(deviceChange, spec)
deviceChange = append(deviceChange, addDevSpec(NewSCSIDev(key, 100, driver)))
}
} else {
ideDevs, err := from.FindController(ctx, "ide")
if err != nil {
return nil, errors.Wrap(err, "SVirtualMachine.FindController")
}
if len(ideDevs) == 0 {
// add ide driver
deviceChange = append(deviceChange, addDevSpec(NewIDEDev(200, 0)))
deviceChange = append(deviceChange, addDevSpec(NewIDEDev(200, 1)))
}
}
// resize system disk
sysDiskSize := params.Disks[0].Size
if sysDiskSize == 0 {
sysDiskSize = 30 * 1024
}
if int64(from.vdisks[0].GetDiskSizeMB()) != sysDiskSize {
vdisk := from.vdisks[0].getVirtualDisk()
vdisk.CapacityInKB = sysDiskSize * 1024
spec := &types.VirtualDeviceConfigSpec{}
spec.Operation = types.VirtualDeviceConfigSpecOperationEdit
spec.Device = vdisk
deviceChange = append(deviceChange, spec)
log.Infof("resize system disk: %dGB => %dGB", from.vdisks[0].GetDiskSizeMB()/1024, vdisk.CapacityInKB/1024/1024)
}
// remove extra disk
// for i := 1; i < len(from.vdisks); i++ {
// dev := from.vdisks[i].dev
// spec := &types.VirtualDeviceConfigSpec{}
// spec.Operation = types.VirtualDeviceConfigSpecOperationRemove
// spec.Device = dev
// spec.FileOperation = types.VirtualDeviceConfigSpecFileOperationDestroy
// deviceChange = append(deviceChange, spec)
// log.Debugf("remove disk, index: %d", i)
// }
}
dc, err := host.GetDatacenter()
if err != nil {
return nil, errors.Wrapf(err, "SHost.GetDatacenter for host '%s'", host.GetId())
@@ -1093,13 +1077,22 @@ func (host *SHost) CloneVM(ctx context.Context, from *SVirtualMachine, ds *SData
return nil, errors.Wrap(err, "fail to fetch virtual machine just created")
}
// resize the disk
vm := NewVirtualMachine(host.manager, &moVM, host.datacenter)
sort.Sort(byDiskType(vm.vdisks))
for i, s := range newSizes {
err := vm.vdisks[i].Resize(ctx, s)
if vm == nil {
return nil, errors.Error("clone successfully but unable to NewVirtualMachine")
}
// add data disk
for i := 1; i < len(params.Disks); i++ {
size := params.Disks[i].Size
if size == 0 {
size = 30 * 1024
}
uuid := params.Disks[i].DiskId
driver := params.Disks[i].Driver
err := vm.CreateDisk(ctx, int(size), uuid, driver)
if err != nil {
log.Errorf("no.%d vdisk.Resize failed: %s", i, err.Error())
log.Errorf("unable to add No.%d disk for vm %s", i, vm.GetId())
return vm, nil
}
}
return vm, nil

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