mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-21 00:24:07 +08:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ec0c8e703 | ||
|
|
3347d6c1e1 | ||
|
|
dce9d5e4a1 | ||
|
|
ef9b64990e | ||
|
|
f19fe2178c | ||
|
|
2265c9422f | ||
|
|
cf3717557a | ||
|
|
0bbdcb9278 | ||
|
|
d72081770e | ||
|
|
0f874d8f07 | ||
|
|
dd5dd15a76 | ||
|
|
cb36572c1c | ||
|
|
2a210407a5 | ||
|
|
82c59154c5 | ||
|
|
041ee6f904 | ||
|
|
4317fac6da | ||
|
|
a022f99851 | ||
|
|
407251975e | ||
|
|
b7fd879e44 | ||
|
|
0a7ccbe958 | ||
|
|
7efb85ba04 | ||
|
|
84e8e4e6c8 | ||
|
|
3fe15d2675 | ||
|
|
d574a823ba | ||
|
|
a2c8ad13ab | ||
|
|
de8f57f625 | ||
|
|
658159b18e | ||
|
|
67cc7b8747 | ||
|
|
ce694ff638 | ||
|
|
98702c2470 | ||
|
|
9ac5265c07 | ||
|
|
896bec8f43 | ||
|
|
a8426482bf | ||
|
|
d7316b26aa | ||
|
|
d16affc9a6 | ||
|
|
2259fe1195 | ||
|
|
09e37de117 | ||
|
|
715db28e3e | ||
|
|
152ea54f36 | ||
|
|
865b433bb0 | ||
|
|
f04a37d0a3 | ||
|
|
7edcd151e3 | ||
|
|
df90d99bc5 | ||
|
|
552ce3b2ea | ||
|
|
91c852676a | ||
|
|
8528d79817 | ||
|
|
d2aacafa4c | ||
|
|
8714503087 | ||
|
|
d0d3d8e333 | ||
|
|
dee1aa26dc | ||
|
|
c973bf1632 | ||
|
|
1aa82ae950 | ||
|
|
488e7e56a6 | ||
|
|
6a2ebdc123 | ||
|
|
4105284718 | ||
|
|
ac5f29bc0c | ||
|
|
58d52d947c | ||
|
|
c5ef564d35 | ||
|
|
1cacf1068f | ||
|
|
63b0d0c071 | ||
|
|
39a45229af | ||
|
|
e82cf184f1 | ||
|
|
afa16944c0 | ||
|
|
8f953e41da | ||
|
|
6e0180656d | ||
|
|
718bf0d537 | ||
|
|
9fbd4f0599 | ||
|
|
078b1d635a | ||
|
|
b8e0599e3f | ||
|
|
27bd564d2d | ||
|
|
5b79ba5607 | ||
|
|
c9d20d13f1 | ||
|
|
779d4a9acf | ||
|
|
1bc4b3cb90 | ||
|
|
49887e540a | ||
|
|
7ce0d7b44b | ||
|
|
e8d737ff6c | ||
|
|
fd954efcf2 | ||
|
|
e9415ae49e | ||
|
|
5b0afbdc6b | ||
|
|
ec393a6e3c | ||
|
|
adccad3487 | ||
|
|
76f794d1a2 | ||
|
|
bba2cf23fd |
3
Makefile
3
Makefile
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## {{.title}}
|
||||
- 时间: {{.start_time}}
|
||||
- 级别: {{.level}}
|
||||
- 详情地址: {{.web_url}}/commonalerts
|
||||
|
||||
{{ range .matches}}
|
||||
- 指标: {{.metric}}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## {{.title}}
|
||||
- Time: {{.start_time}}
|
||||
- Level: {{.level}}
|
||||
- WebUrl: {{.web_url}}/commonalerts
|
||||
|
||||
{{ range .matches}}
|
||||
- Metric: {{.metric}}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
}
|
||||
|
||||
@@ -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
4
go.mod
@@ -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
8
go.sum
@@ -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=
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
// 获取资源标签(元数据)输出
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -228,4 +228,6 @@ type SVirtualResourceBase struct {
|
||||
PendingDeletedAt time.Time `json:"pending_deleted_at"`
|
||||
// 资源是否处于回收站中
|
||||
PendingDeleted bool `json:"pending_deleted"`
|
||||
// 资源是否被冻结
|
||||
Freezed bool `json:"freezed"`
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ const (
|
||||
CLOUD_CAPABILITY_EVENT = "event"
|
||||
CLOUD_CAPABILITY_CLOUDID = "cloudid"
|
||||
CLOUD_CAPABILITY_DNSZONE = "dnszone"
|
||||
CLOUD_CAPABILITY_PUBLIC_IP = "public_ip"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
|
||||
package cloudprovider
|
||||
|
||||
type TElasticipChargeType string
|
||||
|
||||
var (
|
||||
ElasticipChargeTypeByTraffic = TElasticipChargeType("traffic")
|
||||
ElasticipChargeTypeByBandwidth = TElasticipChargeType("bandwidth")
|
||||
)
|
||||
|
||||
type SEip struct {
|
||||
Name string
|
||||
BandwidthMbps int
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -153,40 +153,37 @@ 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
|
||||
@@ -203,7 +200,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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -728,6 +728,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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -52,6 +52,7 @@ func InitDB() error {
|
||||
LoadbalancerListenerRuleManager,
|
||||
LoadbalancerBackendGroupManager,
|
||||
LoadbalancerBackendManager,
|
||||
AwsCachedLbbgManager,
|
||||
LoadbalancerClusterManager,
|
||||
SchedtagManager,
|
||||
DynamicschedtagManager,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -1942,10 +1942,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 +2194,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 +2219,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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -387,6 +387,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"`
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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")
|
||||
|
||||
46
pkg/monitor/models/monitorscoperesource.go
Normal file
46
pkg/monitor/models/monitorscoperesource.go
Normal 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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,13 +17,46 @@ package esxi
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
)
|
||||
|
||||
type IPV4Range struct {
|
||||
iprange *netutils.IPV4AddrRange
|
||||
}
|
||||
|
||||
func (i IPV4Range) Contains(ip string) bool {
|
||||
ipaddr, err := netutils.NewIPV4Addr(ip)
|
||||
if err != nil {
|
||||
log.Errorf("unable to parse ip %q: %v", ip, err)
|
||||
return false
|
||||
}
|
||||
if i.iprange == nil {
|
||||
return true
|
||||
}
|
||||
return i.iprange.Contains(ipaddr)
|
||||
}
|
||||
|
||||
var vmIPV4Filter IPV4Range
|
||||
|
||||
func initVMIPV4Filter(cidr string) error {
|
||||
if len(cidr) == 0 {
|
||||
return nil
|
||||
}
|
||||
prefix, err := netutils.NewIPV4Prefix(cidr)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "parse cidr %q", cidr)
|
||||
}
|
||||
irange := prefix.ToIPRange()
|
||||
vmIPV4Filter.iprange = &irange
|
||||
return nil
|
||||
}
|
||||
|
||||
var HOST_PROPS = []string{"name", "config.network", "vm"}
|
||||
|
||||
var VM_PROPS = []string{"name", "guest.net", "config.template"}
|
||||
var VM_PROPS = []string{"name", "guest.net", "config.template", "summary.config.uuid", "summary.runtime.powerState"}
|
||||
|
||||
func (cli *SESXiClient) AllHostIP() (map[string]string, []mo.HostSystem, error) {
|
||||
var hosts []mo.HostSystem
|
||||
@@ -50,7 +83,10 @@ func (cli *SESXiClient) VMIP(host mo.HostSystem) (map[string][]string, error) {
|
||||
ret := make(map[string][]string, len(vms))
|
||||
for i := range vms {
|
||||
vm := vms[i]
|
||||
if vm.Config.Template {
|
||||
if vm.Config == nil || vm.Config.Template {
|
||||
continue
|
||||
}
|
||||
if vm.Guest == nil {
|
||||
continue
|
||||
}
|
||||
guestIps := make([]string, 0)
|
||||
@@ -66,27 +102,57 @@ func (cli *SESXiClient) VMIP(host mo.HostSystem) (map[string][]string, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) VMIP2() (map[string][]string, error) {
|
||||
type SVMIPInfo struct {
|
||||
Moid string
|
||||
PowerState string
|
||||
Name string
|
||||
Uuid string
|
||||
MacIps []SMacIps
|
||||
}
|
||||
|
||||
type SMacIps struct {
|
||||
Mac string
|
||||
IPs []string
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) VMIP2() ([]SVMIPInfo, error) {
|
||||
var vms []mo.VirtualMachine
|
||||
err := cli.scanAllMObjects(VM_PROPS, &vms)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
ret := make(map[string][]string, len(vms))
|
||||
ret := make([]SVMIPInfo, 0, len(vms))
|
||||
for i := range vms {
|
||||
vm := vms[i]
|
||||
if vm.Config.Template {
|
||||
if vm.Config == nil || vm.Config.Template {
|
||||
continue
|
||||
}
|
||||
guestIps := make([]string, 0)
|
||||
if vm.Guest == nil {
|
||||
continue
|
||||
}
|
||||
info := SVMIPInfo{
|
||||
Moid: vm.Reference().Value,
|
||||
PowerState: string(vm.Summary.Runtime.PowerState),
|
||||
Uuid: vm.Summary.Config.Uuid,
|
||||
Name: vm.Name,
|
||||
}
|
||||
macIps := make([]SMacIps, 0, len(vm.Guest.Net))
|
||||
for _, net := range vm.Guest.Net {
|
||||
if len(net.Network) == 0 {
|
||||
continue
|
||||
}
|
||||
macip := SMacIps{
|
||||
Mac: net.MacAddress,
|
||||
}
|
||||
for _, ip := range net.IpAddress {
|
||||
if regutils.MatchIP4Addr(ip) {
|
||||
guestIps = append(guestIps, ip)
|
||||
macip.IPs = append(macip.IPs, ip)
|
||||
}
|
||||
}
|
||||
macIps = append(macIps, macip)
|
||||
}
|
||||
ret[vm.Name] = guestIps
|
||||
info.MacIps = macIps
|
||||
ret = append(ret, info)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/object"
|
||||
@@ -36,6 +37,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
@@ -347,6 +349,54 @@ func (cli *SESXiClient) scanAllMObjects(props []string, dst interface{}) error {
|
||||
return cli.scanMObjects(cli.client.ServiceContent.RootFolder, props, dst)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) SearchTemplateVM(id string) (*SVirtualMachine, error) {
|
||||
filter := property.Filter{}
|
||||
filter["config.template"] = true
|
||||
filter["summary.config.uuid"] = id
|
||||
var movms []mo.VirtualMachine
|
||||
err := cli.scanMObjectsWithFilter(cli.client.ServiceContent.RootFolder, VIRTUAL_MACHINE_PROPS, &movms, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(movms) == 0 {
|
||||
return nil, errors.ErrNotFound
|
||||
}
|
||||
vm := NewVirtualMachine(cli, &movms[0], nil)
|
||||
dc, err := vm.fetchDatacenter()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetchDatacenter")
|
||||
}
|
||||
vm.datacenter = dc
|
||||
return vm, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanMObjectsWithFilter(folder types.ManagedObjectReference, props []string, dst interface{}, filter property.Filter) error {
|
||||
dstValue := reflect.Indirect(reflect.ValueOf(dst))
|
||||
dstType := dstValue.Type()
|
||||
dstEleType := dstType.Elem()
|
||||
|
||||
resType := dstEleType.Name()
|
||||
m := view.NewManager(cli.client.Client)
|
||||
|
||||
v, err := m.CreateContainerView(cli.context, folder, []string{resType}, true)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "m.CreateContainerView %s", resType)
|
||||
}
|
||||
|
||||
defer v.Destroy(cli.context)
|
||||
|
||||
err = v.RetrieveWithFilter(cli.context, []string{resType}, props, dst, filter)
|
||||
if err != nil {
|
||||
// hack
|
||||
if strings.Contains(err.Error(), "object references is empty") {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "v.RetrieveWithFilter %s", resType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanMObjects(folder types.ManagedObjectReference, props []string, dst interface{}) error {
|
||||
dstValue := reflect.Indirect(reflect.ValueOf(dst))
|
||||
dstType := dstValue.Type()
|
||||
@@ -552,7 +602,11 @@ func (cli *SESXiClient) FindVMByPrivateID(idstr string) (*SVirtualMachine, error
|
||||
return nil, errors.Wrap(err, "reference2Object fail")
|
||||
}
|
||||
|
||||
return NewVirtualMachine(cli, &vm, nil), nil
|
||||
ret := NewVirtualMachine(cli, &vm, nil)
|
||||
if ret == nil {
|
||||
return nil, errors.Error("invalid vm")
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) DoExtendDiskOnline(_vm *SVirtualMachine, _disk *SVirtualDisk, newSizeMb int64) error {
|
||||
@@ -602,17 +656,54 @@ func (cli *SESXiClient) MoveDisk(ctx context.Context, src, dst string, isForce b
|
||||
|
||||
var (
|
||||
SIMPLE_HOST_PROPS = []string{"name", "config.network", "vm"}
|
||||
SIMPLE_VM_PROPS = []string{"name", "guest.net", "config.template"}
|
||||
SIMPLE_VM_PROPS = []string{"name", "guest.net", "config.template", "config.hardware.device"}
|
||||
SIMPLE_DVPG_PROPS = []string{"key", "config.defaultPortConfig"}
|
||||
)
|
||||
|
||||
type SIPVlan struct {
|
||||
IP string
|
||||
VlanID int32
|
||||
}
|
||||
|
||||
type SSimpleVM struct {
|
||||
Name string
|
||||
IPs []string
|
||||
Name string
|
||||
IPVlans []SIPVlan
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanAllDvPortgroups() ([]*SDistributedVirtualPortgroup, error) {
|
||||
var modvpgs []mo.DistributedVirtualPortgroup
|
||||
err := cli.scanAllMObjects(SIMPLE_DVPG_PROPS, &modvpgs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
dvpgs := make([]*SDistributedVirtualPortgroup, 0, len(modvpgs))
|
||||
for i := range modvpgs {
|
||||
dvpgs = append(dvpgs, NewDistributedVirtualPortgroup(cli, &modvpgs[i], nil))
|
||||
}
|
||||
return dvpgs, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) dvpgKeyVlanMap() (*sync.Map, error) {
|
||||
dvpgs, err := cli.scanAllDvPortgroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := new(sync.Map)
|
||||
for i := range dvpgs {
|
||||
key := dvpgs[i].getMODVPortgroup().Key
|
||||
vlanid := dvpgs[i].GetVlanId()
|
||||
ret.Store(key, vlanid)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPs(ctx context.Context) (map[string]string, []SSimpleVM, error) {
|
||||
dvpgKeyVlanMap, err := cli.dvpgKeyVlanMap()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "unable to get dvpgKeyVlanMap")
|
||||
}
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanAllMObjects(SIMPLE_HOST_PROPS, &hosts)
|
||||
err = cli.scanAllMObjects(SIMPLE_HOST_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
@@ -621,7 +712,7 @@ func (cli *SESXiClient) HostVmIPs(ctx context.Context) (map[string]string, []SSi
|
||||
for i := range hosts {
|
||||
j := i
|
||||
group.Go(func() error {
|
||||
vmIps, err := cli.vmIPs(&hosts[j])
|
||||
vmIps, err := cli.vmIPs(&hosts[j], dvpgKeyVlanMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -655,27 +746,74 @@ func (cli *SESXiClient) HostVmIPs(ctx context.Context) (map[string]string, []SSi
|
||||
return hostIps, svms, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) vmIPs(host *mo.HostSystem) ([]SSimpleVM, error) {
|
||||
func (cli *SESXiClient) macVlanMap(movm mo.VirtualMachine, dvpgKeyVlanMap *sync.Map) map[string]int32 {
|
||||
ret := make(map[string]int32, 2)
|
||||
for _, device := range movm.Config.Hardware.Device {
|
||||
bcard, ok := device.(types.BaseVirtualEthernetCard)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
card := bcard.GetVirtualEthernetCard()
|
||||
mac := card.MacAddress
|
||||
dvpgBackInfo, ok := card.Backing.(*types.VirtualEthernetCardDistributedVirtualPortBackingInfo)
|
||||
if !ok {
|
||||
ret[mac] = 0
|
||||
continue
|
||||
}
|
||||
dvpgKey := dvpgBackInfo.Port.PortgroupKey
|
||||
value, ok := dvpgKeyVlanMap.Load(dvpgKey)
|
||||
if !ok {
|
||||
log.Errorf("dvpg %s not found in key-vlanid map", dvpgKey)
|
||||
ret[mac] = 0
|
||||
continue
|
||||
}
|
||||
vlanid := value.(int32)
|
||||
ret[mac] = vlanid
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) vmIPs(host *mo.HostSystem, dvpgKeyVlanMap *sync.Map) ([]SSimpleVM, error) {
|
||||
if len(host.Vm) == 0 {
|
||||
return []SSimpleVM{}, nil
|
||||
}
|
||||
var vms []mo.VirtualMachine
|
||||
err := cli.references2Objects(host.Vm, VM_PROPS, &vms)
|
||||
err := cli.references2Objects(host.Vm, SIMPLE_VM_PROPS, &vms)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "references2Objects")
|
||||
}
|
||||
ret := make([]SSimpleVM, 0, len(vms))
|
||||
for i := range vms {
|
||||
vm := vms[i]
|
||||
if vm.Config.Template {
|
||||
if vm.Config == nil || vm.Config.Template {
|
||||
continue
|
||||
}
|
||||
guestIps := make([]string, 0)
|
||||
if vm.Guest == nil {
|
||||
continue
|
||||
}
|
||||
macVlanMap := cli.macVlanMap(vm, dvpgKeyVlanMap)
|
||||
guestIps := make([]SIPVlan, 0)
|
||||
for _, net := range vm.Guest.Net {
|
||||
if len(net.Network) == 0 {
|
||||
continue
|
||||
}
|
||||
mac := net.MacAddress
|
||||
for _, ip := range net.IpAddress {
|
||||
if regutils.MatchIP4Addr(ip) {
|
||||
guestIps = append(guestIps, ip)
|
||||
if !regutils.MatchIP4Addr(ip) {
|
||||
continue
|
||||
}
|
||||
if !vmIPV4Filter.Contains(ip) {
|
||||
continue
|
||||
}
|
||||
ipaddr, _ := netutils.NewIPV4Addr(ip)
|
||||
if netutils.IsLinkLocal(ipaddr) {
|
||||
continue
|
||||
}
|
||||
guestIps = append(guestIps, SIPVlan{
|
||||
IP: ip,
|
||||
VlanID: macVlanMap[mac],
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
ret = append(ret, SSimpleVM{vm.Name, guestIps})
|
||||
|
||||
@@ -15,41 +15,140 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/esxi"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type IPOption struct {
|
||||
Host bool
|
||||
type IPListOption struct {
|
||||
Host bool `help:"List only host ips"`
|
||||
Vm bool `help:"List only vm ips"`
|
||||
Cidr string `help:"Filter ips in this cidr, such as 192.168.10.0/24"`
|
||||
}
|
||||
shellutils.R(&IPOption{}, "ip-all", "List all ip", func(cli *esxi.SESXiClient, args *IPOption) error {
|
||||
hostIps, _, err := cli.AllHostIP()
|
||||
if err != nil {
|
||||
return err
|
||||
shellutils.R(&IPListOption{}, "ip-list", "List all ip", func(cli *esxi.SESXiClient, args *IPListOption) error {
|
||||
host, vm := args.Host, args.Vm
|
||||
if !host && !vm {
|
||||
host, vm = true, true
|
||||
}
|
||||
for name, ip := range hostIps {
|
||||
fmt.Printf("name: %s, ip: %s\n", name, ip)
|
||||
var cidr netutils.IPV4Prefix
|
||||
var err error
|
||||
if len(args.Cidr) > 0 {
|
||||
cidr, err = netutils.NewIPV4Prefix(args.Cidr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to parse cidr")
|
||||
}
|
||||
}
|
||||
// for i := range hosts {
|
||||
// fmt.Printf("host %s: \n", hosts[i].Name)
|
||||
// vmips, err := cli.VMIP(hosts[i])
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// for name, ip := range vmips {
|
||||
// fmt.Printf("\tname: %s, ip: %s\n", name, ip)
|
||||
// }
|
||||
// }
|
||||
vmips, err := cli.VMIP2()
|
||||
if err != nil {
|
||||
return err
|
||||
list := make([]IPDetails, 0, 5)
|
||||
if host {
|
||||
hostIps, _, err := cli.AllHostIP()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "AllHostIP")
|
||||
}
|
||||
for n, ip := range hostIps {
|
||||
ipaddr, err := netutils.NewIPV4Addr(ip)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewIPV4Addr for ip %s", ip)
|
||||
}
|
||||
if len(args.Cidr) > 0 && !cidr.Contains(ipaddr) {
|
||||
continue
|
||||
}
|
||||
list = append(list, IPDetails{
|
||||
Name: n,
|
||||
Type: "host",
|
||||
Ip: ip,
|
||||
Ipaddr: ipaddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
for name, ip := range vmips {
|
||||
fmt.Printf("\tname: %s, ip: %s\n", name, ip)
|
||||
if vm {
|
||||
vmipinfos, err := cli.VMIP2()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "VMIP2")
|
||||
}
|
||||
//split
|
||||
for i := range vmipinfos {
|
||||
for _, macip := range vmipinfos[i].MacIps {
|
||||
mac := macip.Mac
|
||||
if len(macip.IPs) == 0 {
|
||||
list = append(list, IPDetails{
|
||||
Name: vmipinfos[i].Name,
|
||||
Mac: mac,
|
||||
Uuid: vmipinfos[i].Uuid,
|
||||
Moid: vmipinfos[i].Moid,
|
||||
PowerState: vmipinfos[i].PowerState,
|
||||
Type: "vm",
|
||||
Ip: "",
|
||||
Ipaddr: 0,
|
||||
})
|
||||
continue
|
||||
}
|
||||
ip := macip.IPs[0]
|
||||
ipaddr, err := netutils.NewIPV4Addr(ip)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewIPV4Addr for ip %s", ip)
|
||||
}
|
||||
if len(args.Cidr) > 0 && !cidr.Contains(ipaddr) {
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, IPDetails{
|
||||
Name: vmipinfos[i].Name,
|
||||
Mac: mac,
|
||||
Uuid: vmipinfos[i].Uuid,
|
||||
Moid: vmipinfos[i].Moid,
|
||||
PowerState: vmipinfos[i].PowerState,
|
||||
Type: "vm",
|
||||
Ip: ip,
|
||||
Ipaddr: ipaddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return list[i].Ipaddr < list[j].Ipaddr
|
||||
})
|
||||
printList(list, []string{"name", "type", "ip", "mac", "Power_State", "uuid", "moid"})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
type IPDetails struct {
|
||||
Moid string
|
||||
PowerState string
|
||||
Uuid string
|
||||
Name string
|
||||
Type string
|
||||
Ip string
|
||||
Mac string
|
||||
Ipaddr netutils.IPV4Addr
|
||||
}
|
||||
|
||||
func (i IPDetails) GetMoid() string {
|
||||
return i.Moid
|
||||
}
|
||||
func (i IPDetails) GetPowerState() string {
|
||||
return i.PowerState
|
||||
}
|
||||
func (i IPDetails) GetUuid() string {
|
||||
return i.Uuid
|
||||
}
|
||||
func (i IPDetails) GetMac() string {
|
||||
return i.Mac
|
||||
}
|
||||
func (i IPDetails) GetName() string {
|
||||
return i.Name
|
||||
}
|
||||
|
||||
func (i IPDetails) GetType() string {
|
||||
return i.Type
|
||||
}
|
||||
|
||||
func (i IPDetails) GetIp() string {
|
||||
return i.Ip
|
||||
}
|
||||
|
||||
@@ -29,9 +29,15 @@ func init() {
|
||||
type VirtualMachineListOptions struct {
|
||||
Datacenter string `help:"Datacenter"`
|
||||
HostIP string `help:"HostIP"`
|
||||
FakeRegex string `help:"regex for fake template' name"`
|
||||
Datastore string `help:"Datastore"`
|
||||
Template bool `help:"Whether it is tempalte virtual machine, default:false"`
|
||||
}
|
||||
shellutils.R(&VirtualMachineListOptions{}, "vm-list", "List vms of a host", func(cli *esxi.SESXiClient, args *VirtualMachineListOptions) error {
|
||||
var (
|
||||
vms []*esxi.SVirtualMachine
|
||||
err error
|
||||
)
|
||||
switch {
|
||||
case len(args.HostIP) > 0:
|
||||
host, err := cli.FindHostByIp(args.HostIP)
|
||||
@@ -53,27 +59,44 @@ func init() {
|
||||
printList(vms, []string{})
|
||||
return nil
|
||||
case len(args.Datacenter) > 0:
|
||||
dc, err := cli.FindDatacenterByMoId(args.Datacenter)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FindDatacenterByMoId")
|
||||
}
|
||||
var vms []*esxi.SVirtualMachine
|
||||
if args.Template {
|
||||
vms, err = dc.FetchTemplateVMs()
|
||||
var fetcher esxi.VMFetcher
|
||||
if len(args.Datastore) > 0 {
|
||||
ds, err := getDatastore(cli, args.Datacenter, args.Datastore)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FetchTemplateVMs")
|
||||
return err
|
||||
}
|
||||
fetcher = ds
|
||||
} else {
|
||||
dc, err := cli.FindDatacenterByMoId(args.Datacenter)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FindDatacenterByMoId")
|
||||
}
|
||||
fetcher = dc
|
||||
}
|
||||
if args.Template {
|
||||
if len(args.FakeRegex) > 0 {
|
||||
fmt.Printf("regex: %s\n", args.FakeRegex)
|
||||
vms, err = fetcher.FetchFakeTempateVMs(args.FakeRegex)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FetchFakeTempateVMs")
|
||||
}
|
||||
} else {
|
||||
vms, err = fetcher.FetchTemplateVMs()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FetchTemplateVMs")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vms, err = dc.FetchNoTemplateVMs()
|
||||
vms, err = fetcher.FetchNoTemplateVMs()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "FetchNoTemplateVMs")
|
||||
}
|
||||
}
|
||||
printList(vms, []string{})
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("Both Datacenter and HostIP cannot be empty")
|
||||
}
|
||||
printList(vms, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type VirtualMachineCloneOptions struct {
|
||||
|
||||
@@ -36,6 +36,7 @@ import (
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/progress"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
@@ -254,6 +255,33 @@ func (self *SDatastore) GetIZone() cloudprovider.ICloudZone {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDatastore) FetchNoTemplateVMs() ([]*SVirtualMachine, error) {
|
||||
mods := self.getDatastore()
|
||||
filter := property.Filter{}
|
||||
filter["datastore"] = mods.Reference()
|
||||
return self.datacenter.fetchVMsWithFilter(filter)
|
||||
}
|
||||
|
||||
func (self *SDatastore) FetchTemplateVMs() ([]*SVirtualMachine, error) {
|
||||
mods := self.getDatastore()
|
||||
filter := property.Filter{}
|
||||
filter["config.template"] = true
|
||||
filter["datastore"] = mods.Reference()
|
||||
return self.datacenter.fetchVMsWithFilter(filter)
|
||||
}
|
||||
|
||||
func (self *SDatastore) FetchFakeTempateVMs(regex string) ([]*SVirtualMachine, error) {
|
||||
mods := self.getDatastore()
|
||||
filter := property.Filter{}
|
||||
filter["datastore"] = mods.Reference()
|
||||
filter["summary.runtime.powerState"] = types.VirtualMachinePowerStatePoweredOff
|
||||
movms, err := self.datacenter.fetchMoVms(filter, []string{"name"})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch mo.VirtualMachines")
|
||||
}
|
||||
return self.datacenter.fetchFakeTemplateVMs(movms, regex)
|
||||
}
|
||||
|
||||
func (self *SDatastore) getVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
dc, err := self.GetDatacenter()
|
||||
if err != nil {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -36,6 +37,24 @@ type SDatastoreImageCache struct {
|
||||
host *SHost
|
||||
}
|
||||
|
||||
type EsxiOptions struct {
|
||||
ReasonableCIDREsxi string `help:"Reasonable CIDR in esxi, such as '10.0.0.0/8'" defautl:""`
|
||||
TemplateNameRegex string `help:"Regex of template name"`
|
||||
}
|
||||
|
||||
var tempalteNameRegex *regexp.Regexp
|
||||
|
||||
func InitEsxiConfig(opt EsxiOptions) error {
|
||||
var err error
|
||||
if len(opt.TemplateNameRegex) != 0 {
|
||||
tempalteNameRegex, err = regexp.Compile(opt.TemplateNameRegex)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "regexp.Compile")
|
||||
}
|
||||
}
|
||||
return initVMIPV4Filter(opt.ReasonableCIDREsxi)
|
||||
}
|
||||
|
||||
func (self *SDatastoreImageCache) GetId() string {
|
||||
if self.host != nil {
|
||||
return self.host.GetGlobalId()
|
||||
@@ -76,30 +95,38 @@ func (self *SDatastoreImageCache) GetPath() string {
|
||||
return path.Join(self.datastore.GetMountPoint(), IMAGE_CACHE_DIR_NAME)
|
||||
}
|
||||
|
||||
func (self *SDatastoreImageCache) getTempalteVMs() ([]*SVirtualMachine, error) {
|
||||
return self.datastore.FetchTemplateVMs()
|
||||
}
|
||||
|
||||
func (self *SDatastoreImageCache) getFakeTempateVMs() ([]*SVirtualMachine, error) {
|
||||
return self.datastore.FetchFakeTempateVMs("")
|
||||
}
|
||||
|
||||
func (self *SDatastoreImageCache) GetIImages() ([]cloudprovider.ICloudImage, error) {
|
||||
ctx := context.Background()
|
||||
ret := make([]cloudprovider.ICloudImage, 0, 2)
|
||||
log.Infof("start to GetIImages")
|
||||
|
||||
// get vm template with only one disk
|
||||
ihosts, err := self.datastore.GetAttachedHosts()
|
||||
realTemplates, err := self.getTempalteVMs()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SDatastore.GetAttachedHosts")
|
||||
return nil, errors.Wrap(err, "getTemplateVMs")
|
||||
}
|
||||
fakeTemplates, err := self.getFakeTempateVMs()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getFakeTempateVMs")
|
||||
}
|
||||
|
||||
for _, ihost := range ihosts {
|
||||
host := ihost.(*SHost)
|
||||
tems, err := host.GetTemplateVMs()
|
||||
if err != nil {
|
||||
log.Errorf("fail to get templateVMs of host '%s' in SDatastoreImageCache.GetIImages", self.host.GetName())
|
||||
return ret, nil
|
||||
}
|
||||
for _, tem := range tems {
|
||||
// for now, add vm template with only one disk as cachedimage
|
||||
if len(tem.vdisks) != 1 {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, NewVMTemplate(tem, self))
|
||||
}
|
||||
for i := range realTemplates {
|
||||
ret = append(ret, NewVMTemplate(realTemplates[i], self))
|
||||
}
|
||||
for i := range fakeTemplates {
|
||||
ret = append(ret, NewVMTemplate(fakeTemplates[i], self))
|
||||
}
|
||||
|
||||
log.Errorf("get templates successfully")
|
||||
for i := range fakeTemplates {
|
||||
log.Infof("fake template name: %s", fakeTemplates[i].GetName())
|
||||
}
|
||||
|
||||
files, err := self.datastore.ListDir(ctx, IMAGE_CACHE_DIR_NAME)
|
||||
@@ -108,7 +135,7 @@ func (self *SDatastoreImageCache) GetIImages() ([]cloudprovider.ICloudImage, err
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("GetIImages ListDir fail %s", err)
|
||||
return nil, err
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
validFilenames := make(map[string]bool)
|
||||
|
||||
@@ -63,6 +63,12 @@ type SVirtualMachine struct {
|
||||
guestIps map[string]string
|
||||
}
|
||||
|
||||
type VMFetcher interface {
|
||||
FetchNoTemplateVMs() ([]*SVirtualMachine, error)
|
||||
FetchTemplateVMs() ([]*SVirtualMachine, error)
|
||||
FetchFakeTempateVMs(string) ([]*SVirtualMachine, error)
|
||||
}
|
||||
|
||||
type byDiskType []SVirtualDisk
|
||||
|
||||
func (d byDiskType) Len() int { return len(d) }
|
||||
@@ -76,7 +82,11 @@ func (d byDiskType) Less(i, j int) bool {
|
||||
|
||||
func NewVirtualMachine(manager *SESXiClient, vm *mo.VirtualMachine, dc *SDatacenter) *SVirtualMachine {
|
||||
svm := &SVirtualMachine{SManagedObject: newManagedObject(manager, vm, dc)}
|
||||
svm.fetchHardwareInfo()
|
||||
err := svm.fetchHardwareInfo()
|
||||
if err != nil {
|
||||
log.Errorf("NewVirtualMachine: %v", err)
|
||||
return nil
|
||||
}
|
||||
return svm
|
||||
}
|
||||
|
||||
@@ -703,7 +713,7 @@ func (self *SVirtualMachine) UpdateUserData(userData string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) fetchHardwareInfo() {
|
||||
func (self *SVirtualMachine) fetchHardwareInfo() error {
|
||||
self.vnics = make([]SVirtualNIC, 0)
|
||||
self.vdisks = make([]SVirtualDisk, 0)
|
||||
self.cdroms = make([]SVirtualCdrom, 0)
|
||||
@@ -717,8 +727,7 @@ func (self *SVirtualMachine) fetchHardwareInfo() {
|
||||
}
|
||||
|
||||
if moVM == nil || moVM.Config == nil || moVM.Config.Hardware.Device == nil {
|
||||
log.Errorf("invalid vm config, moVM: %#v", moVM)
|
||||
return
|
||||
return fmt.Errorf("invalid vm")
|
||||
}
|
||||
|
||||
for i := 0; i < len(moVM.Config.Hardware.Device); i += 1 {
|
||||
@@ -746,6 +755,7 @@ func (self *SVirtualMachine) fetchHardwareInfo() {
|
||||
sort.Slice(self.vdisks, func(i, j int) bool {
|
||||
return self.vdisks[i].GetIndex() < self.vdisks[j].GetIndex()
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) getVdev(key int32) SVirtualDevice {
|
||||
@@ -759,6 +769,9 @@ func (self *SVirtualMachine) fetchGuestIps() map[string]string {
|
||||
mac := netutils.FormatMacAddr(net.MacAddress)
|
||||
for _, ip := range net.IpAddress {
|
||||
if regutils.MatchIP4Addr(ip) {
|
||||
if !vmIPV4Filter.Contains(ip) {
|
||||
continue
|
||||
}
|
||||
guestIps[mac] = ip
|
||||
break
|
||||
}
|
||||
@@ -1272,5 +1285,8 @@ func (self *SVirtualMachine) GetIHostId() string {
|
||||
|
||||
func (self *SVirtualMachine) IsTemplate() bool {
|
||||
movm := self.getVirtualMachine()
|
||||
if tempalteNameRegex != nil && tempalteNameRegex.MatchString(self.GetName()) && movm.Summary.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOff {
|
||||
return true
|
||||
}
|
||||
return movm.Config != nil && movm.Config.Template
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"asia-northeast3": {Latitude: 34.6937378, Longitude: 135.5021651, City: api.CITY_SEOUL, CountryCode: api.COUNTRY_CODE_KR},
|
||||
"asia-south1": {Latitude: 37.566535, Longitude: 126.9779692, City: api.CITY_MUMBAI, CountryCode: api.COUNTRY_CODE_IN},
|
||||
"asia-southeast1": {Latitude: 1.352083, Longitude: 103.819839, City: api.CITY_SINGAPORE, CountryCode: api.COUNTRY_CODE_SG},
|
||||
"asia-southeast2": {Latitude: -6.175110, Longitude: 106.865036, City: api.CITY_JAKARTA, CountryCode: api.COUNTRY_CODE_ID},
|
||||
"australia-southeast1": {Latitude: -33.8688197, Longitude: 151.2092955, City: api.CITY_SYDNEY, CountryCode: api.COUNTRY_CODE_AU},
|
||||
|
||||
"europe-north1": {Latitude: 39.904202, Longitude: 116.407394, City: api.CITY_FINLAND, CountryCode: api.COUNTRY_CODE_CN},
|
||||
@@ -55,6 +56,7 @@ var RegionNames = map[string]string{
|
||||
"asia-northeast3": "首尔",
|
||||
"asia-south1": "孟买",
|
||||
"asia-southeast1": "新加坡",
|
||||
"asia-southeast2": "雅加达",
|
||||
"australia-southeast1": "悉尼",
|
||||
|
||||
"europe-north1": "芬兰",
|
||||
|
||||
@@ -42,6 +42,14 @@ type SBucket struct {
|
||||
}
|
||||
|
||||
func (b *SBucket) GetProjectId() string {
|
||||
resp, err := b.region.HeadBucket(b.Name)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
epid, _ := resp.ResponseHeaders["epid"]
|
||||
if len(epid) > 0 {
|
||||
return epid[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
@@ -957,17 +957,20 @@ func (region *SRegion) DeleteIBucket(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
func (region *SRegion) HeadBucket(name string) (*obs.BaseModel, error) {
|
||||
obsClient, err := region.getOBSClient()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "region.getOBSClient")
|
||||
return nil, errors.Wrap(err, "region.getOBSClient")
|
||||
}
|
||||
_, err = obsClient.HeadBucket(name)
|
||||
return obsClient.HeadBucket(name)
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
_, err := region.HeadBucket(name)
|
||||
if err != nil {
|
||||
if obsHttpCode(err) == 404 {
|
||||
return false, nil
|
||||
} else {
|
||||
log.Debugf("%#v %s", err, err)
|
||||
return false, errors.Wrap(err, "HeadBucket")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,35 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/multicloud/huawei"
|
||||
"yunion.io/x/onecloud/pkg/multicloud/objectstore"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
objectstore.S3Shell()
|
||||
|
||||
type BucketNameOptions struct {
|
||||
NAME string
|
||||
}
|
||||
shellutils.R(&BucketNameOptions{}, "bucket-head", "Head bucket", func(cli *huawei.SRegion, args *BucketNameOptions) error {
|
||||
result, err := cli.HeadBucket(args.NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&BucketNameOptions{}, "bucket-project", "Show bucket project", func(cli *huawei.SRegion, args *BucketNameOptions) error {
|
||||
bucket, err := cli.GetIBucketByName(args.NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("project: ", bucket.GetProjectId())
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ type SEipAddress struct {
|
||||
IsEipDirectConnection bool // eip是否支持直通模式。true表示eip支持直通模式,false表示资源不支持直通模式
|
||||
AddressType string // eip资源类型,包括"CalcIP","WanIP","EIP","AnycastEIP"。其中"CalcIP"表示设备ip,“WanIP”表示普通公网ip,“EIP”表示弹性公网ip,“AnycastEip”表示加速EIP
|
||||
CascadeRelease bool // eip是否在解绑后自动释放。true表示eip将会在解绑后自动释放,false表示eip在解绑后不会自动释放
|
||||
Bandwidth int
|
||||
InternetChargeType string
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetId() string {
|
||||
@@ -163,6 +165,9 @@ func (self *SEipAddress) Delete() error {
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetBandwidth() int {
|
||||
if self.Bandwidth > 0 {
|
||||
return self.Bandwidth
|
||||
}
|
||||
if len(self.InstanceId) > 0 {
|
||||
if strings.HasPrefix(self.InstanceId, "ins-") {
|
||||
if instance, err := self.region.GetInstance(self.InstanceId); err == nil {
|
||||
@@ -190,6 +195,12 @@ func (self *SEipAddress) GetExpiredAt() time.Time {
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetInternetChargeType() string {
|
||||
switch self.InternetChargeType {
|
||||
case "TRAFFIC_POSTPAID_BY_HOUR":
|
||||
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
case "BANDWIDTH_PACKAGE", "BANDWIDTH_POSTPAID_BY_HOUR", "BANDWIDTH_PREPAID_BY_MONTH":
|
||||
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
|
||||
}
|
||||
if len(self.InstanceId) > 0 {
|
||||
if strings.HasPrefix(self.InstanceId, "ins-") {
|
||||
if instance, err := self.region.GetInstance(self.InstanceId); err == nil {
|
||||
@@ -210,7 +221,7 @@ func (self *SEipAddress) Associate(conf *cloudprovider.AssociateConfig) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if conf.Bandwidth > 0 {
|
||||
if conf.Bandwidth > 0 && self.Bandwidth == 0 {
|
||||
err = self.region.UpdateInstanceBandwidth(conf.InstanceId, conf.Bandwidth)
|
||||
if err != nil {
|
||||
log.Warningf("failed to change instance %s bandwidth -> %d error: %v", conf.InstanceId, conf.Bandwidth, err)
|
||||
@@ -284,7 +295,9 @@ func (region *SRegion) GetEip(eipId string) (*SEipAddress, error) {
|
||||
|
||||
func (region *SRegion) AllocateEIP(name string, bwMbps int, chargeType TInternetChargeType) (*SEipAddress, error) {
|
||||
params := make(map[string]string)
|
||||
params["Region"] = region.Region
|
||||
if bwMbps > 0 {
|
||||
params["InternetMaxBandwidthOut"] = fmt.Sprintf("%d", bwMbps)
|
||||
}
|
||||
addRessSet := []string{}
|
||||
body, err := region.vpcRequest("AllocateAddresses", params)
|
||||
if err != nil {
|
||||
@@ -298,6 +311,7 @@ func (region *SRegion) AllocateEIP(name string, bwMbps int, chargeType TInternet
|
||||
name = name[:20]
|
||||
}
|
||||
if len(addRessSet) > 0 {
|
||||
params = map[string]string{}
|
||||
params["AddressId"] = addRessSet[0]
|
||||
params["AddressName"] = name
|
||||
_, err = region.vpcRequest("ModifyAddressAttribute", params)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -63,7 +64,7 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr
|
||||
desc.InstanceType, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, desc.Password,
|
||||
desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId,
|
||||
desc.UserData, desc.BillingCycle, desc.ProjectId)
|
||||
desc.UserData, desc.BillingCycle, desc.ProjectId, desc.PublicIpBw, desc.PublicIpChargeType, desc.Tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -76,40 +77,17 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr
|
||||
|
||||
func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SDiskInfo, cpu int, memMB int, instanceType string,
|
||||
networkId string, ipAddr string, desc string, passwd string,
|
||||
diskSizes []cloudprovider.SDiskInfo, publicKey string, secgroupId string, userData string, bc *billing.SBillingCycle, projectId string) (string, error) {
|
||||
diskSizes []cloudprovider.SDiskInfo, publicKey string, secgroupId string, userData string, bc *billing.SBillingCycle, projectId string,
|
||||
publicIpBw int, publicIpChargeType cloudprovider.TElasticipChargeType,
|
||||
tags map[string]string,
|
||||
) (string, error) {
|
||||
net := self.zone.getNetworkById(networkId)
|
||||
if net == nil {
|
||||
return "", fmt.Errorf("invalid network ID %s", networkId)
|
||||
}
|
||||
if net.wire == nil {
|
||||
log.Errorf("network's wire is empty")
|
||||
return "", fmt.Errorf("network's wire is empty")
|
||||
}
|
||||
if net.wire.vpc == nil {
|
||||
log.Errorf("network's wire' vpc is empty")
|
||||
return "", fmt.Errorf("network's wire's vpc is empty")
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
// if len(secgroupId) == 0 {
|
||||
// secgroups, err := net.wire.vpc.GetISecurityGroups()
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("get security group error %s", err)
|
||||
// }
|
||||
|
||||
// if len(secgroups) == 0 {
|
||||
// secId, err := self.zone.region.createDefaultSecurityGroup(net.wire.vpc.VpcId)
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("no secgroup for vpc and failed to create a default One!!")
|
||||
// } else {
|
||||
// secgroupId = secId
|
||||
// }
|
||||
// } else {
|
||||
// secgroupId = secgroups[0].GetId()
|
||||
// }
|
||||
// }
|
||||
|
||||
keypair := ""
|
||||
if len(publicKey) > 0 {
|
||||
keypair, err = self.zone.region.syncKeypair(publicKey)
|
||||
@@ -120,12 +98,10 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
|
||||
img, err := self.zone.region.GetImage(imgId)
|
||||
if err != nil {
|
||||
log.Errorf("getiamge fail %s", err)
|
||||
return "", err
|
||||
return "", errors.Wrapf(err, "GetImage(%s)", imgId)
|
||||
}
|
||||
if img.ImageState != ImageStatusNormal && img.ImageState != ImageStatusUsing {
|
||||
log.Errorf("image %s status %s", imgId, img.ImageState)
|
||||
return "", fmt.Errorf("image not ready")
|
||||
return "", fmt.Errorf("image %s not ready status is %s", imgId, img.ImageState)
|
||||
}
|
||||
|
||||
err = self.zone.validateStorageType(sysDisk.StorageType)
|
||||
@@ -154,10 +130,9 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
|
||||
if len(instanceType) > 0 {
|
||||
log.Debugf("Try instancetype : %s", instanceType)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceType, err)
|
||||
return "", fmt.Errorf("Failed to create specification %s.%s", instanceType, err.Error())
|
||||
return "", errors.Wrapf(err, "Failed to create specification %s", instanceType)
|
||||
}
|
||||
return vmId, nil
|
||||
}
|
||||
@@ -174,7 +149,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD
|
||||
for _, instType := range instanceTypes {
|
||||
instanceTypeId := instType.InstanceType
|
||||
log.Debugf("Try instancetype : %s", instanceTypeId)
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId)
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.Zone, desc, passwd, disks, networkId, ipAddr, keypair, userData, bc, projectId, publicIpBw, publicIpChargeType, tags)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceTypeId, err)
|
||||
} else {
|
||||
|
||||
@@ -489,13 +489,15 @@ func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) {
|
||||
if instances[0].InstanceState == "LAUNCH_FAILED" {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
log.Debugf("%#v", instances)
|
||||
return &instances[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateInstance(name string, imageId string, instanceType string, securityGroupId string,
|
||||
zoneId string, desc string, passwd string, disks []SDisk, networkId string, ipAddr string,
|
||||
keypair string, userData string, bc *billing.SBillingCycle, projectId string) (string, error) {
|
||||
keypair string, userData string, bc *billing.SBillingCycle, projectId string,
|
||||
publicIpBw int, publicIpChargeType cloudprovider.TElasticipChargeType,
|
||||
tags map[string]string,
|
||||
) (string, error) {
|
||||
params := make(map[string]string)
|
||||
params["Region"] = self.Region
|
||||
params["ImageId"] = imageId
|
||||
@@ -506,10 +508,34 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
params["Placement.ProjectId"] = projectId
|
||||
}
|
||||
params["InstanceName"] = name
|
||||
params["HostName"] = name
|
||||
|
||||
params["InternetAccessible.InternetMaxBandwidthOut"] = "1"
|
||||
params["InternetAccessible.PublicIpAssigned"] = "FALSE"
|
||||
//params["HostName"] = name
|
||||
bandwidth := publicIpBw
|
||||
if publicIpBw == 0 {
|
||||
bandwidth = 100
|
||||
if bc != nil {
|
||||
bandwidth = 200
|
||||
}
|
||||
}
|
||||
|
||||
internetChargeType := "TRAFFIC_POSTPAID_BY_HOUR"
|
||||
if publicIpChargeType == cloudprovider.ElasticipChargeTypeByBandwidth {
|
||||
internetChargeType = "BANDWIDTH_PREPAID"
|
||||
}
|
||||
_, totalCount, err := self.GetBandwidthPackages([]string{}, 0, 50)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "GetBandwidthPackages")
|
||||
}
|
||||
if totalCount > 0 {
|
||||
bandwidth = 65535 // unlimited bandwidth
|
||||
internetChargeType = "BANDWIDTH_PACKAGE"
|
||||
}
|
||||
|
||||
params["InternetAccessible.InternetChargeType"] = internetChargeType
|
||||
params["InternetAccessible.InternetMaxBandwidthOut"] = fmt.Sprintf("%d", bandwidth)
|
||||
if publicIpBw == 0 {
|
||||
params["InternetAccessible.PublicIpAssigned"] = "FALSE"
|
||||
}
|
||||
if len(keypair) > 0 {
|
||||
params["LoginSettings.KeyIds.0"] = keypair
|
||||
} else if len(passwd) > 0 {
|
||||
@@ -533,6 +559,17 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
params["InstanceChargeType"] = "POSTPAID_BY_HOUR"
|
||||
}
|
||||
|
||||
// tags
|
||||
if len(tags) > 0 {
|
||||
params["TagSpecification.0.ResourceType"] = "instance"
|
||||
tagIdx := 0
|
||||
for k, v := range tags {
|
||||
params[fmt.Sprintf("TagSpecification.0.Tags.%d.Key", tagIdx)] = k
|
||||
params[fmt.Sprintf("TagSpecification.0.Tags.%d.Value", tagIdx)] = v
|
||||
tagIdx += 1
|
||||
}
|
||||
}
|
||||
|
||||
//params["IoOptimized"] = "optimized"
|
||||
for i, d := range disks {
|
||||
if i == 0 {
|
||||
@@ -545,7 +582,7 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
}
|
||||
network, err := self.GetNetwork(networkId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.Wrapf(err, "GetNetwork(%s)", networkId)
|
||||
}
|
||||
params["VirtualPrivateCloud.SubnetId"] = networkId
|
||||
params["VirtualPrivateCloud.VpcId"] = network.VpcId
|
||||
@@ -554,12 +591,10 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
}
|
||||
|
||||
params["ClientToken"] = utils.GenRequestId(20)
|
||||
// log.Errorf("create params: %s", jsonutils.Marshal(params).PrettyString())
|
||||
instanceIdSet := []string{}
|
||||
body, err := self.cvmRequest("RunInstances", params, true)
|
||||
if err != nil {
|
||||
log.Errorf("RunInstances fail %s", err)
|
||||
return "", err
|
||||
return "", errors.Wrapf(err, "RunInstances")
|
||||
}
|
||||
err = body.Unmarshal(&instanceIdSet, "InstanceIdSet")
|
||||
if err == nil && len(instanceIdSet) > 0 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user