mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
Compare commits
110 Commits
v4.0.0-rc.
...
v3.11.12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd01cc9c95 | ||
|
|
6f5feb6a7f | ||
|
|
23a8fefbd0 | ||
|
|
e04fe21a5c | ||
|
|
272e32c0b9 | ||
|
|
bed77085c2 | ||
|
|
c9f3c9578d | ||
|
|
8deaead935 | ||
|
|
87e65dab12 | ||
|
|
671e24b01e | ||
|
|
3d8ea72139 | ||
|
|
70f29b481c | ||
|
|
35cb610755 | ||
|
|
62f44a77ff | ||
|
|
2ba9f0b887 | ||
|
|
1e676fb2e8 | ||
|
|
cfc6d56361 | ||
|
|
f50929bc60 | ||
|
|
2ebbfb4dd9 | ||
|
|
feb6a1981f | ||
|
|
ded669c7a2 | ||
|
|
2241f34b9b | ||
|
|
59ad7f73e8 | ||
|
|
2b08c946ff | ||
|
|
4f0ca33bf9 | ||
|
|
340d246ee5 | ||
|
|
ae0920476b | ||
|
|
2ffa2cf4ca | ||
|
|
cc4fdf189a | ||
|
|
5ab6e57d73 | ||
|
|
0ec0162857 | ||
|
|
f00099e29f | ||
|
|
0bbc92e46d | ||
|
|
4c3186f4a1 | ||
|
|
6722c43868 | ||
|
|
e4391b9cce | ||
|
|
70887c8d58 | ||
|
|
66840c2c16 | ||
|
|
34b417c60b | ||
|
|
b96abf5af6 | ||
|
|
433747ff99 | ||
|
|
614b13cd13 | ||
|
|
d7f0a6f065 | ||
|
|
160b6e3faf | ||
|
|
7a82d04f70 | ||
|
|
104c927e74 | ||
|
|
2d795063dd | ||
|
|
e0ed7e80df | ||
|
|
c880ee5940 | ||
|
|
88f61e6be2 | ||
|
|
0777418c63 | ||
|
|
3ddd2603f8 | ||
|
|
1a4a0fe647 | ||
|
|
0c090d08f2 | ||
|
|
c37b15a3d0 | ||
|
|
0eb0f9d99c | ||
|
|
620fd06d87 | ||
|
|
944267af35 | ||
|
|
f40095bd46 | ||
|
|
4781f552e2 | ||
|
|
8eb11e7865 | ||
|
|
523653e755 | ||
|
|
84dea5ace9 | ||
|
|
07912a9f8c | ||
|
|
bd72a48ecb | ||
|
|
4377da3aff | ||
|
|
140fda72e6 | ||
|
|
521bc94749 | ||
|
|
78850c6d03 | ||
|
|
32b85c1b28 | ||
|
|
ea65acf6ed | ||
|
|
f09e9f081d | ||
|
|
78eaa50af1 | ||
|
|
d9e8c89711 | ||
|
|
3b34ac8dba | ||
|
|
b93d913948 | ||
|
|
7d2bcd2828 | ||
|
|
76d798044e | ||
|
|
382d51e18c | ||
|
|
a316053a4f | ||
|
|
634058a832 | ||
|
|
4c2ba4a9c9 | ||
|
|
e244be79b1 | ||
|
|
6615224f93 | ||
|
|
555d77f9d0 | ||
|
|
c15d5ba838 | ||
|
|
5fce56f5e6 | ||
|
|
9a5b906d10 | ||
|
|
4d45708d11 | ||
|
|
1f39911996 | ||
|
|
d3154a0cde | ||
|
|
a5e4471e1f | ||
|
|
c00c81f23b | ||
|
|
061988edea | ||
|
|
7d453caff6 | ||
|
|
c231b0bc66 | ||
|
|
d83fd7490a | ||
|
|
1d7b27e5e3 | ||
|
|
1f083d2490 | ||
|
|
e7227612ea | ||
|
|
e304c99316 | ||
|
|
6c4c73c79e | ||
|
|
ba9457df30 | ||
|
|
5027e6bbde | ||
|
|
13060902a0 | ||
|
|
6c726c7211 | ||
|
|
1b6f13738a | ||
|
|
4455aa2f6d | ||
|
|
345de4a5c3 | ||
|
|
944953957e |
6
Makefile
6
Makefile
@@ -277,12 +277,12 @@ dep:
|
||||
@echo "$$depDeprecated"
|
||||
@$(MAKE) mod
|
||||
|
||||
RELEASE_BRANCH:=release/3.11
|
||||
RELEASE_BRANCH:=release/3.11.12
|
||||
GOPROXY ?= direct
|
||||
|
||||
mod:
|
||||
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get -d yunion.io/x/cloudmux@$(RELEASE_BRANCH)
|
||||
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get -d $(patsubst %,%@master,$(shell GO111MODULE=on go mod edit -print | sed -n -e 's|.*\(yunion.io/x/[a-z].*\) v.*|\1|p' | grep -v '/cloudmux$$'))
|
||||
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get yunion.io/x/cloudmux@$(RELEASE_BRANCH)
|
||||
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go get $(patsubst %,%@master,$(shell GO111MODULE=on go mod edit -print | sed -n -e 's|.*\(yunion.io/x/[a-z].*\) v.*|\1|p' | grep -v '/cloudmux$$'))
|
||||
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go mod tidy
|
||||
GOPROXY=$(GOPROXY) GONOSUMDB=yunion.io/x go mod vendor -v
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.9
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.11
|
||||
|
||||
MAINTAINER "Yaoqi Wan wanyaoqi@yunionyun.com"
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ func init() {
|
||||
cmd.Perform("rebuild", &options.ResourceIdOptions{})
|
||||
cmd.Perform("migrate", &compute_options.DiskMigrateOptions{})
|
||||
cmd.Perform("change-billing-type", new(compute_options.DiskChangeBillingTypeOptions))
|
||||
cmd.Perform("change-storage-type", &compute_options.DiskChangeStorageTypeOptions{})
|
||||
|
||||
type DiskDetailOptions struct {
|
||||
ID string `help:"ID or Name of disk"`
|
||||
|
||||
@@ -143,6 +143,8 @@ func init() {
|
||||
cmd.Get("sshport", new(options.ServerIdOptions))
|
||||
cmd.Get("qemu-info", new(options.ServerIdOptions))
|
||||
cmd.Get("hardware-info", new(options.ServerIdOptions))
|
||||
cmd.Get("screen-dump-show", new(options.ServerScreenDumpOptions))
|
||||
cmd.BatchPerform("screen-dump", new(options.ServerIdsOptions))
|
||||
|
||||
cmd.GetProperty(&options.ServerStatusStatisticsOptions{})
|
||||
cmd.GetProperty(&options.ServerProjectStatisticsOptions{})
|
||||
|
||||
23
cmd/climc/shell/compute/serverscreendumps.go
Normal file
23
cmd/climc/shell/compute/serverscreendumps.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type ServerScreenDumpListOptions struct {
|
||||
options.BaseListOptions
|
||||
Server string `help:"Id or name of server"`
|
||||
}
|
||||
|
||||
func (o *ServerScreenDumpListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.ServerScreenDumps)
|
||||
cmd.List(new(ServerScreenDumpListOptions))
|
||||
}
|
||||
@@ -28,5 +28,7 @@ func init() {
|
||||
cmd.Create(&compute.SnapshotPolicyCreateOptions{})
|
||||
cmd.Perform("bind-disks", &compute.SnapshotPolicyDisksOptions{})
|
||||
cmd.Perform("unbind-disks", &compute.SnapshotPolicyDisksOptions{})
|
||||
cmd.Perform("bind-resources", &compute.SnapshotPolicyResourcesOptions{})
|
||||
cmd.Perform("unbind-resources", &compute.SnapshotPolicyResourcesOptions{})
|
||||
cmd.Perform("syncstatus", &options.BaseIdOptions{})
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ func init() {
|
||||
DiskType string `help:"Filter by disk type" choices:"sys|data"`
|
||||
Server string `help:"Filter by server" json:"server_id"`
|
||||
Unused bool
|
||||
StorageId string `help:"Filter by storage id"`
|
||||
|
||||
OrderByGuest string
|
||||
OrderByDiskName string
|
||||
|
||||
@@ -23,5 +23,6 @@ func init() {
|
||||
cmd := NewResourceCmd(modules.AlertRecordManager)
|
||||
cmd.List(new(options.AlertRecordListOptions))
|
||||
cmd.Show(new(options.AlertRecordShowOptions))
|
||||
cmd.Get("", new(options.AlertRecordTotalOptions))
|
||||
cmd.GetProperty(new(options.AlertRecordTotalOptions))
|
||||
cmd.GetProperty(new(options.AlertRecordHistoryAlertOptions))
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/ldap.v3"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
|
||||
"yunion.io/x/pkg/util/shellutils"
|
||||
|
||||
|
||||
13
go.mod
13
go.mod
@@ -19,6 +19,7 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/go-ldap/ldap/v3 v3.1.5
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
github.com/golang-plus/uuid v1.0.0
|
||||
github.com/golang/mock v1.4.4
|
||||
@@ -65,6 +66,7 @@ require (
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible
|
||||
github.com/xuri/excelize/v2 v2.7.1
|
||||
github.com/zeebo/xxh3 v1.0.2
|
||||
github.com/zexi/influxql-to-metricsql v0.1.1
|
||||
go.etcd.io/etcd/api/v3 v3.5.0
|
||||
go.etcd.io/etcd/client/v3 v3.5.0
|
||||
@@ -79,7 +81,6 @@ require (
|
||||
google.golang.org/grpc v1.62.0
|
||||
google.golang.org/protobuf v1.32.0
|
||||
gopkg.in/fatih/set.v0 v0.2.1
|
||||
gopkg.in/ldap.v3 v3.0.3
|
||||
gopkg.in/mail.v2 v2.3.1
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.19.3
|
||||
@@ -87,14 +88,14 @@ require (
|
||||
k8s.io/client-go v0.19.3
|
||||
k8s.io/cluster-bootstrap v0.19.3
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250702132722-2420711ec647
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251015023252-07f4567eae95
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
|
||||
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
|
||||
yunion.io/x/pkg v1.10.4-0.20250618071935-840c253075b0
|
||||
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
|
||||
)
|
||||
|
||||
@@ -163,6 +164,7 @@ require (
|
||||
github.com/frankban/quicktest v1.14.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
@@ -196,7 +198,9 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/ks3sdklib/aws-sdk-go v1.8.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/lestrrat-go/iter v0.0.0-20200422075355-fc1769541911 // indirect
|
||||
github.com/lestrrat-go/pdebug v0.0.0-20200204225717-4d6bd78da58d // indirect
|
||||
@@ -276,7 +280,6 @@ require (
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
29
go.sum
29
go.sum
@@ -281,12 +281,17 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493 h1:OTanQnFt0bi5iLFSdbEVA/idR6Q2WhCm+deb7ir2CcM=
|
||||
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-ldap/ldap/v3 v3.1.5 h1:5o1ik2It7MJoXwoS7JXWUebf18L7E1VWBBgYV/iVsN0=
|
||||
github.com/go-ldap/ldap/v3 v3.1.5/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
|
||||
@@ -494,6 +499,8 @@ github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALr
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c h1:N7A4JCA2G+j5fuFxCsJqjFU/sZe0mj8H0sSoSwbaikw=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c/go.mod h1:Nn5wlyECw3iJrzi0AhIWg+AJUb4PlRQVW4/3XHH1LZA=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -510,6 +517,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/ks3sdklib/aws-sdk-go v1.8.1 h1:/3mYWujGfr4K/+mAdESbi9u3T4VDuHYMYFk1/OL0JWE=
|
||||
github.com/ks3sdklib/aws-sdk-go v1.8.1/go.mod h1:jGcsV0dJgMmStAyqjkKVUu6F167pAXYZAS3LqoZMmtM=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lestrrat-go/iter v0.0.0-20200422075355-fc1769541911 h1:FvnrqecqX4zT0wOIbYK1gNgTm0677INEWiFY8UEYggY=
|
||||
@@ -790,6 +799,10 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
github.com/zexi/influxql-to-metricsql v0.1.1 h1:dXnVzlxVLuo88zGkDca7erEnmvprGWjzsBcs8qIoQGQ=
|
||||
github.com/zexi/influxql-to-metricsql v0.1.1/go.mod h1:JlC5FY+6De9ZPxG47G5DOgva8P9X1VaKS4ExzCmhSCc=
|
||||
github.com/zexi/promql/v2 v2.12.1 h1:crHKpULdLLsBZ9b78Rg6qQkugzlk6BHeCj93tw/F5RU=
|
||||
@@ -1200,8 +1213,6 @@ google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -1216,8 +1227,6 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ldap.v3 v3.0.3 h1:YKRHW/2sIl05JsCtx/5ZuUueFuJyoj/6+DGXe3wp6ro=
|
||||
gopkg.in/ldap.v3 v3.0.3/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw=
|
||||
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
||||
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
@@ -1270,8 +1279,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250702132722-2420711ec647 h1:ozbBRR+0BaBxXMjUsjn9NRFFVedU6FCMNmk7E1J0A9k=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250702132722-2420711ec647/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251015023252-07f4567eae95 h1:RcTzopo22fQvKnJSJSBUvlP2jEqoVVJD9EGW3IeTJ3s=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251015023252-07f4567eae95/go.mod h1:S9o/TRZsnYWGaGe7o3PpeOv6CgMY8ZJwITYsEnGfOgQ=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
@@ -1285,11 +1294,11 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB
|
||||
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
|
||||
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v1.10.4-0.20250618071935-840c253075b0 h1:diTsDq4t6jntGdAKtHZYx9eRWkLg0KyMTp0WFdueT+0=
|
||||
yunion.io/x/pkg v1.10.4-0.20250618071935-840c253075b0/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
|
||||
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0 h1:/vHcYqzQInxqR1jjS+e7A0owRXj+/rvrIgES6uadUqs=
|
||||
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833 h1:XTFC1naKYkciCQDLm9izpzHXfTenmmtYsTpVKrsN5hE=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0 h1:L4zE6kTD1PEki1jQnLLBiYnEYFKWa/weoful0Sl4tKw=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250925091009-4ca0766fc8f0/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ=
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
|
||||
|
||||
@@ -36,7 +36,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apigateway/options"
|
||||
policytool "yunion.io/x/onecloud/pkg/apigateway/policy"
|
||||
agapi "yunion.io/x/onecloud/pkg/apis/apigateway"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -1107,25 +1106,6 @@ func getUserInfo2(s *mcclient.ClientSession, uid string, pid string, loginIp str
|
||||
menus.Add(item)
|
||||
}
|
||||
|
||||
log.Infof("getUserInfo modules.Hosts.Get")
|
||||
// s2 := auth.GetSession(ctx, token, FetchRegion(req), "v2")
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString("host_type"), "field")
|
||||
params.Add(jsonutils.NewString("system"), "scope")
|
||||
params.Add(jsonutils.JSONTrue, "usable")
|
||||
params.Add(jsonutils.JSONTrue, "show_emulated")
|
||||
cap, err := compute_modules.Hosts.Get(s, "distinct-field", params)
|
||||
if err != nil {
|
||||
log.Errorf("modules.Servers.Get distinct-field fail %s", err)
|
||||
} else {
|
||||
hostTypes, _ := jsonutils.GetStringArray(cap, "host_type")
|
||||
hypervisors := make([]string, len(hostTypes))
|
||||
for i, hostType := range hostTypes {
|
||||
hypervisors[i] = compute.HOSTTYPE_HYPERVISOR[hostType]
|
||||
}
|
||||
data.Add(jsonutils.NewStringArray(hypervisors), "hypervisors")
|
||||
}
|
||||
|
||||
data.Add(menus, "menus")
|
||||
data.Add(k8s, "k8sdashboard")
|
||||
data.Add(services, "services")
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
@@ -634,6 +636,8 @@ type ServerCreateInput struct {
|
||||
BillingType string `json:"billing_type"`
|
||||
// swagger:ignore
|
||||
BillingCycle string `json:"billing_cycle"`
|
||||
// 到期释放时间
|
||||
ReleaseAt time.Time `json:"release_at"`
|
||||
|
||||
// swagger:ignore
|
||||
// Deprecated
|
||||
|
||||
@@ -86,4 +86,7 @@ type CachedimageListInput struct {
|
||||
|
||||
// valid cachedimage
|
||||
Valid bool `json:"valid"`
|
||||
|
||||
// enum: [public, private]
|
||||
CloudEnv string `json:"cloud_env"`
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ type DBInstanceCreateInput struct {
|
||||
// default: false
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
|
||||
// swagger:ignore
|
||||
ExpiredAt time.Time `json:"expired_at"`
|
||||
// 到期释放时间
|
||||
ReleaseAt time.Time `json:"release_at"`
|
||||
|
||||
// 计费方式
|
||||
// enum: postpaid, prepaid
|
||||
|
||||
@@ -163,6 +163,9 @@ type DiskListInput struct {
|
||||
|
||||
// 根据虚拟机状态过滤
|
||||
GuestStatus string `json:"guest_status"`
|
||||
|
||||
// 根据是否绑定快照策略过滤
|
||||
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
|
||||
}
|
||||
|
||||
type DiskResourceInput struct {
|
||||
@@ -205,6 +208,8 @@ type SimpleGuest struct {
|
||||
Iops int `json:"iops"`
|
||||
// 磁盘吞吐
|
||||
Bps int `json:"bps"`
|
||||
// 计费类型
|
||||
BillingType string `json:"billing_type"`
|
||||
}
|
||||
|
||||
type SimpleSnapshotPolicy struct {
|
||||
@@ -229,6 +234,8 @@ type DiskDetails struct {
|
||||
GuestCount int `json:"guest_count"`
|
||||
// 所挂载虚拟机状态
|
||||
GuestStatus string `json:"guest_status"`
|
||||
// 所挂载虚拟机计费类型
|
||||
GuestBillingType string `json:"guest_billing_type"`
|
||||
|
||||
// 自动清理时间
|
||||
AutoDeleteAt time.Time `json:"auto_delete_at"`
|
||||
@@ -335,6 +342,11 @@ type DiskMigrateInput struct {
|
||||
TargetStorageId string `json:"target_storage_id"`
|
||||
}
|
||||
|
||||
type DiskChagneStorageTypeInput struct {
|
||||
// 目标存储类型
|
||||
StorageType string `json:"storage_type"`
|
||||
}
|
||||
|
||||
type DiskSnapshotpolicyInput struct {
|
||||
SnapshotpolicyId string `json:"snapshotpolicy_id"`
|
||||
}
|
||||
|
||||
@@ -246,13 +246,13 @@ type ElasticcacheCreateInput struct {
|
||||
// 包年包月时间周期
|
||||
Duration string `json:"duration"`
|
||||
|
||||
// 到期释放时间
|
||||
ReleaseAt time.Time `json:"release_at"`
|
||||
|
||||
// 是否自动续费(仅包年包月时生效)
|
||||
// default: false
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
|
||||
// swagger:ignore
|
||||
ExpiredAt time.Time `json:"expired_at"`
|
||||
|
||||
// 计费方式
|
||||
// enum: postpaid, prepaid
|
||||
BillingType string
|
||||
|
||||
@@ -87,8 +87,8 @@ type FileSystemCreateInput struct {
|
||||
// default: false
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
|
||||
// 到期释放时间,仅后付费支持
|
||||
ExpiredAt time.Time `json:"expired_at"`
|
||||
// 到期释放时间
|
||||
ReleaseAt time.Time `json:"release_at"`
|
||||
|
||||
// 计费方式
|
||||
// enum: postpaid, prepaid
|
||||
|
||||
@@ -27,3 +27,26 @@ type SImagesInGuest struct {
|
||||
RootImage SSubImage
|
||||
DataImages []SSubImage
|
||||
}
|
||||
|
||||
type SGuestScreenDump struct {
|
||||
S3AccessKey string
|
||||
S3SecretKey string
|
||||
S3Endpoint string
|
||||
S3BucketName string
|
||||
S3ObjectName string
|
||||
S3UseSSL bool
|
||||
}
|
||||
|
||||
type GuestScreenDumpListInput struct {
|
||||
Server string
|
||||
}
|
||||
|
||||
type GetDetailsGuestScreenDumpInput struct {
|
||||
ObjectName string
|
||||
}
|
||||
|
||||
type GetDetailsGuestScreenDumpOutput struct {
|
||||
GuestId string
|
||||
Name string
|
||||
ScreenDump string
|
||||
}
|
||||
|
||||
@@ -127,8 +127,13 @@ type ServerListInput struct {
|
||||
// 根据镜像发行版排序
|
||||
OrderByOsDist string `json:"order_by_os_dist"`
|
||||
|
||||
SnapshotpolicyId string `json:"snapshotpolicy_id"`
|
||||
|
||||
// 是否调度到宿主机上
|
||||
WithHost *bool `json:"with_host"`
|
||||
|
||||
// 根据是否绑定快照策略过滤
|
||||
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
|
||||
}
|
||||
|
||||
func (input *ServerListInput) AfterUnmarshal() {
|
||||
|
||||
@@ -163,6 +163,30 @@ type HostListInput struct {
|
||||
// 按内存分配大小排序
|
||||
// enmu: asc,desc
|
||||
OrderByMemCommit string `json:"order_by_mem_commit"`
|
||||
|
||||
// 按物理cpu使用率排序
|
||||
// enmu: asc,desc
|
||||
OrderByCpuUsage string `json:"order_by_cpu_usage"`
|
||||
|
||||
// 按物理内存使用率排序
|
||||
// enmu: asc,desc
|
||||
OrderByMemUsage string `json:"order_by_mem_usage"`
|
||||
|
||||
// 按物理存储使用率排序
|
||||
// enmu: asc,desc
|
||||
OrderByStorageUsage string `json:"order_by_storage_usage"`
|
||||
|
||||
// 按虚拟内存使用率排序
|
||||
// enmu: asc,desc
|
||||
OrderByVirtualMemUsage string `json:"order_by_virtual_mem_usage"`
|
||||
|
||||
// 按虚拟cpu使用率排序
|
||||
// enmu: asc,desc
|
||||
OrderByVirtualCpuUsage string `json:"order_by_virtual_cpu_usage"`
|
||||
|
||||
// 按虚拟存储使用率排序
|
||||
// enmu: asc,desc
|
||||
OrderByVirtualStorageUsage string `json:"order_by_virtual_storage_usage"`
|
||||
}
|
||||
|
||||
type HostDetails struct {
|
||||
|
||||
@@ -119,6 +119,11 @@ const (
|
||||
HostResourceTypeDedicated = "dedicated"
|
||||
)
|
||||
|
||||
const (
|
||||
HOST_METADATA_CPU_USAGE_PERCENT = "cpu_usage_percent"
|
||||
HOST_METADATA_MEMORY_USED_MB = "memory_used_mb"
|
||||
)
|
||||
|
||||
var HOST_TYPES = []string{
|
||||
HOST_TYPE_BAREMETAL,
|
||||
HOST_TYPE_HYPERVISOR,
|
||||
|
||||
@@ -147,6 +147,8 @@ type SnapshotPolicyListInput struct {
|
||||
// 按绑定的磁盘数量排序
|
||||
// pattern:asc|desc
|
||||
OrderByBindDiskCount string `json:"order_by_bind_disk_count"`
|
||||
// 按类型过滤
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type HostnameInput struct {
|
||||
|
||||
@@ -18,6 +18,10 @@ import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
var KEYPAIR_SCHEMAS = []string{
|
||||
KEYPAIRE_SCHEME_RSA,
|
||||
// OpenSSH deprecated DSA keys
|
||||
//KEYPAIRE_SCHEME_DSA,
|
||||
KEYPAIRE_SCHEME_ECDSA,
|
||||
KEYPAIRE_SCHEME_ED25519,
|
||||
}
|
||||
|
||||
type KeypairCreateInput struct {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
KEYPAIRE_SCHEME_RSA = "RSA"
|
||||
KEYPAIRE_SCHEME_DSA = "DSA"
|
||||
KEYPAIRE_SCHEME_RSA = "RSA"
|
||||
KEYPAIRE_SCHEME_DSA = "DSA"
|
||||
KEYPAIRE_SCHEME_ECDSA = "ECDSA"
|
||||
KEYPAIRE_SCHEME_ED25519 = "ED25519"
|
||||
)
|
||||
|
||||
@@ -117,8 +117,8 @@ type NatgatewayCreateInput struct {
|
||||
// default: false
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
|
||||
// 到期释放时间,仅后付费支持
|
||||
ExpiredAt time.Time `json:"expired_at"`
|
||||
// 到期释放时间
|
||||
ReleaseAt time.Time `json:"release_at"`
|
||||
|
||||
// 计费方式
|
||||
// enum: postpaid, prepaid
|
||||
|
||||
@@ -77,6 +77,9 @@ type SnapshotListInput struct {
|
||||
// 未关联任何磁盘
|
||||
Unused bool `json:"unused"`
|
||||
|
||||
// 按存储过滤
|
||||
StorageId string `json:"storage_id"`
|
||||
|
||||
// 按虚拟机名称排序
|
||||
// pattern:asc|desc
|
||||
OrderByGuest string `json:"order_by_guest"`
|
||||
|
||||
@@ -30,6 +30,9 @@ const (
|
||||
SNAPSHOT_POLICY_APPLY_FAILED = "apply_failed"
|
||||
SNAPSHOT_POLICY_CANCEL = "canceling"
|
||||
SNAPSHOT_POLICY_CANCEL_FAILED = "cancel_failed"
|
||||
|
||||
SNAPSHOT_POLICY_TYPE_DISK = "disk"
|
||||
SNAPSHOT_POLICY_TYPE_SERVER = "server"
|
||||
)
|
||||
|
||||
type SnapshotPolicyDetails struct {
|
||||
@@ -41,7 +44,8 @@ type SnapshotPolicyDetails struct {
|
||||
|
||||
RetentionDays int `json:"retention_days"`
|
||||
|
||||
BindingDiskCount int `json:"binding_disk_count"`
|
||||
BindingDiskCount int `json:"binding_disk_count"`
|
||||
BindingResourceCount int `json:"binding_resource_count"`
|
||||
}
|
||||
|
||||
type SSnapshotPolicyCreateInput struct {
|
||||
@@ -49,7 +53,10 @@ type SSnapshotPolicyCreateInput struct {
|
||||
CloudproviderResourceInput
|
||||
CloudregionResourceInput
|
||||
|
||||
RetentionDays int `json:"retention_days"`
|
||||
RetentionDays int `json:"retention_days"`
|
||||
RetentionCount int `json:"retention_count"`
|
||||
// 快照类型, 目前支持 disk, server
|
||||
Type string `json:"type"`
|
||||
|
||||
RepeatWeekdays []int `json:"repeat_weekdays"`
|
||||
|
||||
@@ -92,7 +99,8 @@ func (self *SSnapshotPolicyCreateInput) Validate() error {
|
||||
type SSnapshotPolicyUpdateInput struct {
|
||||
apis.VirtualResourceBaseUpdateInput
|
||||
|
||||
RetentionDays *int
|
||||
RetentionDays *int
|
||||
RegentionCount *int
|
||||
|
||||
RepeatWeekdays *[]int `json:"repeat_weekdays"`
|
||||
TimePoints *[]int `json:"time_points"`
|
||||
@@ -131,6 +139,13 @@ type SnapshotPolicyDisksInput struct {
|
||||
Disks []string `json:"disk"`
|
||||
}
|
||||
|
||||
type SnapshotPolicyResourcesInput struct {
|
||||
Resources []struct {
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
} `json:"resources"`
|
||||
}
|
||||
|
||||
type RepeatWeekdays []int
|
||||
|
||||
func (days RepeatWeekdays) String() string {
|
||||
|
||||
@@ -106,10 +106,15 @@ const (
|
||||
STORAGE_ZSTACK_SHARED_BLOCK = compute.STORAGE_ZSTACK_SHARED_BLOCK
|
||||
|
||||
// Google storage type
|
||||
STORAGE_GOOGLE_LOCAL_SSD = compute.STORAGE_GOOGLE_LOCAL_SSD //本地SSD暂存盘 (最多8个)
|
||||
STORAGE_GOOGLE_PD_STANDARD = compute.STORAGE_GOOGLE_PD_STANDARD //标准永久性磁盘
|
||||
STORAGE_GOOGLE_PD_SSD = compute.STORAGE_GOOGLE_PD_SSD //SSD永久性磁盘
|
||||
STORAGE_GOOGLE_PD_BALANCED = compute.STORAGE_GOOGLE_PD_BALANCED //平衡永久性磁盘
|
||||
STORAGE_GOOGLE_LOCAL_SSD = compute.STORAGE_GOOGLE_LOCAL_SSD //本地SSD暂存盘 (最多8个)
|
||||
STORAGE_GOOGLE_PD_STANDARD = compute.STORAGE_GOOGLE_PD_STANDARD //标准永久性磁盘
|
||||
STORAGE_GOOGLE_PD_SSD = compute.STORAGE_GOOGLE_PD_SSD //SSD永久性磁盘
|
||||
STORAGE_GOOGLE_PD_BALANCED = compute.STORAGE_GOOGLE_PD_BALANCED //平衡永久性磁盘
|
||||
STORAGE_GOOGLE_PD_EXTREME = compute.STORAGE_GOOGLE_PD_EXTREME //极端永久性磁盘
|
||||
STORAGE_GOOGLE_HYPERDISK_BALANCED = compute.STORAGE_GOOGLE_HYPERDISK_BALANCED //平衡 Hyperdisk
|
||||
STORAGE_GOOGLE_HYPERDISK_EXTREME = compute.STORAGE_GOOGLE_HYPERDISK_EXTREME //Hyperdisk Extreme
|
||||
STORAGE_GOOGLE_HYPERDISK_THROUGHPUT = compute.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT //Hyperdisk Throughput
|
||||
STORAGE_GOOGLE_HYPERDISK_ML = compute.STORAGE_GOOGLE_HYPERDISK_ML //Hyperdisk ML
|
||||
|
||||
// ctyun storage type
|
||||
STORAGE_CTYUN_SSD = compute.STORAGE_CTYUN_SSD // 超高IO云硬盘
|
||||
@@ -128,6 +133,21 @@ const (
|
||||
STORAGE_ECLOUD_SSD = compute.STORAGE_ECLOUD_SSD // 高性能盘
|
||||
STORAGE_ECLOUD_SSDEBS = compute.STORAGE_ECLOUD_SSDEBS // 性能优化盘
|
||||
STORAGE_ECLOUD_SYSTEM = compute.STORAGE_ECLOUD_SYSTEM // 系统盘
|
||||
|
||||
STORAGE_BAIDU_SSD = compute.STORAGE_BAIDU_SSD
|
||||
STORAGE_BAIDU_PREMIUM_SSD = compute.STORAGE_BAIDU_PREMIUM_SSD
|
||||
STORAGE_BAIDU_HDD = compute.STORAGE_BAIDU_HDD
|
||||
STORAGE_BAIDU_ENHANCED_SSD_PL1 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL1
|
||||
STORAGE_BAIDU_ENHANCED_SSD_PL2 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL2
|
||||
STORAGE_BAIDU_ENHANCED_SSD_PL3 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL3
|
||||
|
||||
// ksyun storage type
|
||||
STORAGE_KSYUN_ESSD_AUTO_PL = compute.STORAGE_KSYUN_ESSD_AUTO_PL
|
||||
STORAGE_KSYUN_SSD3_0 = compute.STORAGE_KSYUN_SSD3_0
|
||||
STORAGE_KSYUN_EHDD = compute.STORAGE_KSYUN_EHDD
|
||||
STORAGE_KSYUN_ESSD_PL1 = compute.STORAGE_KSYUN_ESSD_PL1
|
||||
STORAGE_KSYUN_ESSD_PL2 = compute.STORAGE_KSYUN_ESSD_PL2
|
||||
STORAGE_KSYUN_ESSD_PL3 = compute.STORAGE_KSYUN_ESSD_PL3
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -164,7 +184,7 @@ var (
|
||||
}
|
||||
STORAGE_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_SHEEPDOG,
|
||||
STORAGE_RBD, STORAGE_DOCKER, STORAGE_NAS, STORAGE_VSAN, STORAGE_NFS,
|
||||
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD, STORAGE_CLOUD_ESSD_PL2, STORAGE_CLOUD_ESSD_PL3,
|
||||
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD_PL0, STORAGE_CLOUD_ESSD, STORAGE_CLOUD_ESSD_PL2, STORAGE_CLOUD_ESSD_PL3,
|
||||
STORAGE_EPHEMERAL_SSD, STORAGE_CLOUD_EFFICIENCY,
|
||||
STORAGE_STANDARD_LRS, STORAGE_STANDARDSSD_LRS, STORAGE_PREMIUM_LRS,
|
||||
STORAGE_GP2_SSD, STORAGE_GP3_SSD, STORAGE_IO1_SSD, STORAGE_ST1_HDD, STORAGE_SC1_HDD, STORAGE_STANDARD_HDD,
|
||||
|
||||
@@ -149,6 +149,10 @@ func IsARM(osArch string) bool {
|
||||
return utils.IsInStringArray(osArch, ARCH_ARM)
|
||||
}
|
||||
|
||||
func IsX86(osArch string) bool {
|
||||
return utils.IsInStringArray(osArch, ARCH_X86)
|
||||
}
|
||||
|
||||
func IsIllegalSearchDomain(domain string) bool {
|
||||
switch domain {
|
||||
case "cloud.onecloud.io":
|
||||
@@ -156,3 +160,16 @@ func IsIllegalSearchDomain(domain string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsSameArch(arch1, arch2 string) bool {
|
||||
if arch1 == arch2 {
|
||||
return true
|
||||
}
|
||||
if IsARM(arch1) && IsARM(arch2) {
|
||||
return true
|
||||
}
|
||||
if IsX86(arch1) && IsX86(arch2) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ type IdentityProviderDetails struct {
|
||||
// 该认证源关联的所有域的组数量
|
||||
GroupCount int `json:"group_count,allowempty"`
|
||||
|
||||
// 该认证源的URL, 可以区分ladp是否使用TLS
|
||||
// example: ldaps://192.168.100.10, ldap://192.168.100.10
|
||||
URL string `json:"url,allowempty"`
|
||||
|
||||
SIdentityProvider
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ const (
|
||||
IMAGE_OS_VERSION = "os_version"
|
||||
IMAGE_DISK_FORMAT = "disk_format"
|
||||
IMAGE_UEFI_SUPPORT = "uefi_support"
|
||||
IMAGE_BIOS_SUPPORT = "bios_support"
|
||||
IMAGE_IS_LVM_PARTITION = "is_lvm_partition"
|
||||
IMAGE_IS_READONLY = "is_readonly"
|
||||
IMAGE_PARTITION_TYPE = "partition_type"
|
||||
|
||||
@@ -14,7 +14,13 @@
|
||||
|
||||
package apis
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
)
|
||||
|
||||
type DomainizedResourceInput struct {
|
||||
// 指定项目归属域名称或ID
|
||||
@@ -390,8 +396,25 @@ type DistinctFieldsInput struct {
|
||||
}
|
||||
|
||||
type PostpaidExpireInput struct {
|
||||
Duration string `json:"duration"`
|
||||
ExpireTime time.Time `json:"expire_time"`
|
||||
Duration string `json:"duration"`
|
||||
// swagger:ignore
|
||||
ExpireTime time.Time `json:"expire_time" yunion-deprecated-by:"release_at"`
|
||||
// 到期释放时间
|
||||
ReleaseAt time.Time `json:"release_at"`
|
||||
}
|
||||
|
||||
func (input *PostpaidExpireInput) GetReleaseAt() (time.Time, error) {
|
||||
if !input.ReleaseAt.IsZero() {
|
||||
return input.ReleaseAt, nil
|
||||
}
|
||||
if len(input.Duration) == 0 {
|
||||
return time.Time{}, httperrors.NewInputParameterError("missing duration/expire_time")
|
||||
}
|
||||
bc, err := billing.ParseBillingCycle(input.Duration)
|
||||
if err != nil {
|
||||
return time.Time{}, httperrors.NewInputParameterError("invalid duration: %s", input.Duration)
|
||||
}
|
||||
return bc.EndAt(time.Now()), nil
|
||||
}
|
||||
|
||||
type AutoRenewInput struct {
|
||||
|
||||
@@ -53,20 +53,6 @@ type AlertRecordDetails struct {
|
||||
TriggerTime time.Time
|
||||
}
|
||||
|
||||
func (self AlertRecordDetails) GetMetricTags() map[string]string {
|
||||
ret := map[string]string{
|
||||
"id": self.Id,
|
||||
"alert_id": self.AlertId,
|
||||
"alert_name": self.AlertName,
|
||||
"domain_id": self.DomainId,
|
||||
"project_domain": self.ProjectDomain,
|
||||
"res_type": self.ResType,
|
||||
"tenant": self.Tenant,
|
||||
"tenant_id": self.TenantId,
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type AlertRecordCreateInput struct {
|
||||
apis.StandaloneResourceCreateInput
|
||||
|
||||
@@ -99,3 +85,26 @@ type AlertRecordRule struct {
|
||||
SilentPeriod string `json:"silent_period"`
|
||||
Reducer string `json:"reducer"`
|
||||
}
|
||||
|
||||
type AlertRecordHistoryAlertData struct {
|
||||
ProjectId string `json:"project_id"`
|
||||
Project string `json:"project"`
|
||||
DomainId string `json:"domain_id"`
|
||||
Domain string `json:"domain"`
|
||||
ResType string `json:"res_type"`
|
||||
ResNum int64 `json:"res_num"`
|
||||
}
|
||||
|
||||
func (self AlertRecordHistoryAlertData) GetMetricTags() map[string]string {
|
||||
return map[string]string{
|
||||
"tenant_id": self.ProjectId,
|
||||
"domain_id": self.DomainId,
|
||||
"domain": self.Domain,
|
||||
"tenant": self.Project,
|
||||
"res_type": self.ResType,
|
||||
}
|
||||
}
|
||||
|
||||
type AlertRecordHistoryAlert struct {
|
||||
Data []AlertRecordHistoryAlertData `json:"data"`
|
||||
}
|
||||
|
||||
@@ -170,11 +170,35 @@ func (p TimePoint) IsValids() bool {
|
||||
}
|
||||
|
||||
func (p TimePoint) Value() float64 {
|
||||
return *(p[0].(*float64))
|
||||
v := p[0]
|
||||
if fval, ok := v.(*float64); ok {
|
||||
return *fval
|
||||
}
|
||||
if ival, ok := v.(*int64); ok {
|
||||
return float64(*ival)
|
||||
}
|
||||
if t, ok := v.(float64); ok {
|
||||
return t
|
||||
}
|
||||
if t, ok := v.(int64); ok {
|
||||
return float64(t)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p TimePoint) Timestamp() float64 {
|
||||
return p[len(p)-1].(float64)
|
||||
v := p[len(p)-1]
|
||||
if t, ok := v.(float64); ok {
|
||||
return t
|
||||
}
|
||||
if t, ok := v.(int64); ok {
|
||||
return float64(t)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p TimePoint) Time() time.Time {
|
||||
return time.UnixMilli(int64(p.Timestamp()))
|
||||
}
|
||||
|
||||
func (p TimePoint) Values() []float64 {
|
||||
|
||||
@@ -214,9 +214,10 @@ type SNotifyConfigContent struct {
|
||||
Username string
|
||||
SenderAddress string
|
||||
//Lark
|
||||
AppId string
|
||||
AppSecret string
|
||||
AccessToken string
|
||||
AppId string
|
||||
AppSecret string
|
||||
AccessToken string
|
||||
AccessTokenExpireTime time.Time
|
||||
// workwx
|
||||
AgentId string
|
||||
CorpId string
|
||||
|
||||
@@ -38,4 +38,8 @@ const (
|
||||
CLOUDPODS = "cloudpods"
|
||||
PROXMOX = "proxmox"
|
||||
VOLC_ENGINE = "volcengine"
|
||||
BAIDU = "baidu"
|
||||
SANGFOR = "sangfor"
|
||||
CNWARE = "cnware"
|
||||
KSYUN = "ksyun"
|
||||
)
|
||||
|
||||
@@ -188,6 +188,12 @@ func NewWorkerManager(name string, workerCount int, backlog int, dbWorker bool)
|
||||
}
|
||||
|
||||
func NewWorkerManagerIgnoreOverflow(name string, workerCount int, backlog int, dbWorker bool, ignoreOverflow bool) *SWorkerManager {
|
||||
if workerCount <= 0 {
|
||||
workerCount = 1
|
||||
}
|
||||
if backlog <= 0 {
|
||||
backlog = 128
|
||||
}
|
||||
manager := SWorkerManager{name: name,
|
||||
queue: NewRing(workerCount * backlog),
|
||||
workerCount: workerCount,
|
||||
|
||||
@@ -1311,10 +1311,17 @@ func (b *SBaremetalInstance) GetTask() tasks.ITask {
|
||||
}
|
||||
|
||||
func (b *SBaremetalInstance) SetTask(task tasks.ITask) {
|
||||
// hack: clear exist tasks if task is server destroy task
|
||||
if task.GetName() == tasks.BAREMETAL_SERVER_DESTROY_TASK {
|
||||
log.Infof("clear tasks of baremetal %s before executing %s", b.GetName(), task.GetName())
|
||||
b.taskQueue.ClearTasks()
|
||||
}
|
||||
b.taskQueue.AppendTask(task)
|
||||
if reflect.DeepEqual(task, b.taskQueue.GetTask()) {
|
||||
log.Infof("Set task equal, ExecuteTask %s", task.GetName())
|
||||
log.Infof("Execute task %s of baremetal %s", task.GetName(), b.GetName())
|
||||
tasks.ExecuteTask(task, nil)
|
||||
} else {
|
||||
log.Warningf("Append task %s of baremetal %s before executing %s", task.GetName(), b.GetName(), b.taskQueue.DebugString())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,6 +180,25 @@ func (q *TaskQueue) AppendTask(task ITask) *TaskQueue {
|
||||
return q
|
||||
}
|
||||
|
||||
func (q *TaskQueue) ClearTasks() {
|
||||
for {
|
||||
existTask := q.PopTask()
|
||||
if existTask != nil {
|
||||
log.Warningf("Clear task %s", existTask.GetName())
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (q *TaskQueue) DebugString() string {
|
||||
str := ""
|
||||
for e := q.objList.Front(); e != nil; e = e.Next() {
|
||||
str += fmt.Sprintf("%s, ", e.Value.(ITask).GetName())
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
type TaskFactory func(userCred mcclient.TokenCredential, bm IBaremetal, taskId string, data jsonutils.JSONObject) ITask
|
||||
|
||||
type SBaremetalTaskBase struct {
|
||||
|
||||
@@ -26,6 +26,10 @@ import (
|
||||
|
||||
var _ IServerBaseDeployTask = new(SBaremetalServerDestroyTask)
|
||||
|
||||
const (
|
||||
BAREMETAL_SERVER_DESTROY_TASK = "BaremetalServerDestroyTask"
|
||||
)
|
||||
|
||||
type SBaremetalServerDestroyTask struct {
|
||||
SBaremetalServerBaseDeployTask
|
||||
}
|
||||
@@ -45,7 +49,7 @@ func NewBaremetalServerDestroyTask(
|
||||
}
|
||||
|
||||
func (self *SBaremetalServerDestroyTask) GetName() string {
|
||||
return "BaremetalServerDestroyTask"
|
||||
return BAREMETAL_SERVER_DESTROY_TASK
|
||||
}
|
||||
|
||||
func (self *SBaremetalServerDestroyTask) RemoveEFIOSEntry() bool {
|
||||
|
||||
@@ -40,7 +40,13 @@ menuentry 'YunionOS for PXE' --class os {
|
||||
`, sleepTime, kernel, kernel, kernelArgs, initrd, initrd)
|
||||
}
|
||||
|
||||
// REF: https://github.com/bluebanquise/infrastructure/blob/master/packages/ipxe-bluebanquise/grub2-efi-autofind.cfg
|
||||
var (
|
||||
BOOT_EFI_MATCHER = "(hd*,gpt*)/EFI/BOOT/BOOTX64.EFI (hd*,msdos*)/EFI/BOOT/BOOTX64.EFI (hd*,gpt*)/EFI/BOOT/BOOTAA64.EFI (hd*,msdos*)/EFI/BOOT/BOOTAA64.EFI"
|
||||
GRUB_EFI_MATCHER = "(md*)/EFI/*/shimx64.efi (md*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimx64.efi (hd*,msdos*)/EFI/*/shimx64.efi (hd*,gpt*)/EFI/*/grubx64.efi (hd*,mosdos*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimaa64.efi (hd*,msdos*)/EFI/*/shimaa64.efi (hd*,gpt*)/EFI/*/grubaa64.efi (hd*,mosdos*)/EFI/*/grubaa64.efi"
|
||||
GRUB_CFG_MATCHER = "(md*)/boot/*/grub.cfg (md*)/*/grub.cfg (md*)/grub.cfg (md*)/EFI/*/grub.cfg (md*)/EFI/*/*/grub.cfg (hd*,gpt*)/boot/*/grub.cfg (hd*,gpt*)/*/grub.cfg (hd*,gpt*)/grub.cfg (hd*,gpt*)/EFI/*/grub.cfg (hd*,gpt*)/EFI/*/*/grub.cfg (hd*,mosdos*)/boot/*/grub.cfg (hd*,mosdos*)/*/grub.cfg (hd*,mosdos*)/grub.cfg (hd*,mosdos*)/EFI/*/grub.cfg (hd*,mosdos*)/EFI/*/*/grub.cfg"
|
||||
)
|
||||
|
||||
// REF: https://github.com/bluebanquise/infrastructure/blob/master/packages/bluebanquise-ipxe/grub2-efi-autofind.cfg
|
||||
const autoFindCfg = `
|
||||
echo "Loading modules..."
|
||||
insmod part_gpt
|
||||
@@ -48,34 +54,114 @@ insmod fat
|
||||
insmod chain
|
||||
insmod part_msdos
|
||||
insmod ext2
|
||||
insmod regexp
|
||||
insmod xfs
|
||||
insmod mdraid1x
|
||||
insmod mdraid09
|
||||
|
||||
echo
|
||||
echo "Scanning, first pass..."
|
||||
for cfg in (*,gpt*)/efi/*/grub.cfg (*,gpt*)/efi/*/*/grub.cfg (*,gpt*)/grub.cfg (*,gpt*)/*/grub.cfg (*,gpt*)/*/*/grub.cfg (*,msdos*)/grub.cfg (*,msdos*)/*/grub.cfg (*,mosdos*)/*/*/grub.cfg; do
|
||||
regexp --set=1:cfg_device '^\((.*)\)/' "${cfg}"
|
||||
echo "======================= lsmod ======================================="
|
||||
lsmod
|
||||
|
||||
echo
|
||||
echo "======================= devices ====================================="
|
||||
ls
|
||||
|
||||
echo
|
||||
echo "======================= Searching for the BOOT EFI executable ======="
|
||||
echo "Scanning, 1st pass"
|
||||
for efi in %s; do
|
||||
regexp --set=1:root '^\(([^)]+)\)/' "${efi}"
|
||||
echo "- Scanning: $efi"
|
||||
if [ -e "$efi" ] ; then
|
||||
echo " Found: $efi"
|
||||
else
|
||||
echo " $efi does not exist"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Scanning, second pass..."
|
||||
for cfg in (*,gpt*)/efi/*/grub.cfg (*,gpt*)/efi/*/*/grub.cfg (*,gpt*)/grub.cfg (*,gpt*)/*/grub.cfg (*,gpt*)/*/*/grub.cfg (*,msdos*)/grub.cfg (*,msdos*)/*/grub.cfg (*,mosdos*)/*/*/grub.cfg; do
|
||||
regexp --set=1:cfg_device '^\((.*)\)/' "${cfg}"
|
||||
echo "Try configfile ${cfg}"
|
||||
if [ -e "${cfg}" ]; then
|
||||
cfg_found=true
|
||||
echo " >> Found operating system grub config! <<"
|
||||
echo " Path: ${cfg}"
|
||||
echo " Booting in 5s..."
|
||||
sleep --interruptible --verbose 5
|
||||
configfile "${cfg}"
|
||||
echo
|
||||
echo "Scanning, 2nd pass..."
|
||||
for efi in %s; do
|
||||
echo "- Scanning: $efi"
|
||||
if [ -e "$efi" ] ; then
|
||||
regexp --set 1:root '^\(([^)]+)\)/' "${efi}"
|
||||
echo " Found: $efi"
|
||||
echo " Root: $root"
|
||||
echo " Chainloading $efi"
|
||||
chainloader "$efi"
|
||||
boot
|
||||
fi
|
||||
done
|
||||
|
||||
echo "No grub.cfg known OS found. Fall back on shell after 5s."
|
||||
sleep 5s
|
||||
echo
|
||||
echo " Found no BOOT EFI executable. Falling back to shell..."
|
||||
|
||||
echo
|
||||
echo "======================= Searching for Grub EFI executables =========="
|
||||
echo "Scanning, 1st pass"
|
||||
for efi in %s ; do
|
||||
regexp --set=1:root '^\(([^)]+)\)/' "${efi}"
|
||||
echo "- Scanning: $efi"
|
||||
if [ -e "$efi" ] ; then
|
||||
echo " Found: $efi"
|
||||
else
|
||||
echo " $efi does not exist"
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Scanning, 2nd pass..."
|
||||
for efi in %s ; do
|
||||
echo "- Scanning: $efi"
|
||||
if [ -e "$efi" ] ; then
|
||||
regexp --set 1:root '^\(([^)]+)\)/' "${efi}"
|
||||
echo " Found: $efi"
|
||||
echo " Root: $root"
|
||||
echo " Chainloading $efi"
|
||||
chainloader "$efi"
|
||||
boot
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo " Found no Grub EFI executable to load an OS."
|
||||
|
||||
echo
|
||||
echo "======================= Searching for grub.cfg on local disks ======="
|
||||
echo "Scanning, 1st pass..."
|
||||
for grubcfg in %s ; do
|
||||
regexp --set=1:root '^\(([^)]+)\)/' "${grubcfg}"
|
||||
if [ -e "$grubcfg" ] ; then
|
||||
echo " Found: $grubcfg"
|
||||
else
|
||||
echo " $grubcfg does not exist"
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Scanning, 2nd pass..."
|
||||
for grubcfg in %s ; do
|
||||
echo "- Scanning: $grubcfg"
|
||||
if [ -e "${grubcfg}" ]; then
|
||||
regexp --set=1:root '^\(([^)]+)\)/' "${grubcfg}"
|
||||
echo " Found: $grubcfg"
|
||||
echo " Root: $root"
|
||||
# echo " Contents:"
|
||||
# cat "$grubcfg"
|
||||
configfile "${grubcfg}"
|
||||
boot
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo " Found no grub.cfg configuration file to load."
|
||||
|
||||
sleep 4s
|
||||
`
|
||||
|
||||
func GetAutoFindConfig() string {
|
||||
return autoFindCfg
|
||||
return fmt.Sprintf(autoFindCfg, BOOT_EFI_MATCHER, BOOT_EFI_MATCHER, GRUB_EFI_MATCHER, GRUB_EFI_MATCHER, GRUB_CFG_MATCHER, GRUB_CFG_MATCHER)
|
||||
}
|
||||
|
||||
// REF: https://archived.forum.manjaro.org/t/detecting-efi-files-and-booting-them-from-grub/38083
|
||||
|
||||
@@ -445,13 +445,13 @@ func (adapter *MegaRaidAdaptor) GetDevices() []*baremetal.BaremetalStorage {
|
||||
|
||||
func (adapter *MegaRaidAdaptor) GetLogicVolumes() ([]*raiddrivers.RaidLogicalVolume, error) {
|
||||
errs := make([]error, 0)
|
||||
megaLvs, err := adapter.getMegacliLogicVolumes()
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
megaLvs, megacliErr := adapter.getMegacliLogicVolumes()
|
||||
if megacliErr != nil {
|
||||
errs = append(errs, megacliErr)
|
||||
}
|
||||
storeLvs, err := adapter.getStorcliLogicVolums()
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
storeLvs, storcliErr := adapter.getStorcliLogicVolums()
|
||||
if storcliErr != nil {
|
||||
errs = append(errs, storcliErr)
|
||||
}
|
||||
if len(megaLvs) > 0 {
|
||||
return megaLvs, nil
|
||||
@@ -459,7 +459,7 @@ func (adapter *MegaRaidAdaptor) GetLogicVolumes() ([]*raiddrivers.RaidLogicalVol
|
||||
if len(storeLvs) > 0 {
|
||||
return storeLvs, nil
|
||||
}
|
||||
if len(errs) == 0 {
|
||||
if len(errs) == 0 || megacliErr == nil || storcliErr == nil {
|
||||
// no error, no volume
|
||||
return []*raiddrivers.RaidLogicalVolume{}, nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/workmanager"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
@@ -49,13 +48,12 @@ func performImageCache(
|
||||
) {
|
||||
_, _, body := appsrv.FetchEnv(ctx, w, r)
|
||||
|
||||
input := compute.CacheImageInput{}
|
||||
err := body.Unmarshal(&input, "disk")
|
||||
disk, err := body.Get("disk")
|
||||
if err != nil {
|
||||
httperrors.BadRequestError(ctx, w, "unmarshal disk %s", err)
|
||||
httperrors.MissingParameterError(ctx, w, "disk")
|
||||
return
|
||||
}
|
||||
|
||||
hostutils.DelayImageCacheTask(ctx, performTask, input)
|
||||
hostutils.DelayImageCacheTask(ctx, performTask, disk)
|
||||
hostutils.ResponseOk(ctx, w)
|
||||
}
|
||||
|
||||
@@ -1085,12 +1085,15 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
|
||||
|
||||
funcName := fmt.Sprintf("GetDetails%s", specCamel)
|
||||
funcValue := modelValue.MethodByName(funcName)
|
||||
log.Errorf("MethodByName %s", funcName)
|
||||
if !funcValue.IsValid() || funcValue.IsNil() {
|
||||
log.Errorf("MethodByName2 %s", funcName)
|
||||
return nil, httperrors.NewSpecNotFoundError("%s %s %s not found", dispatcher.Keyword(), idStr, spec)
|
||||
}
|
||||
|
||||
outs, err := callFunc(funcValue, funcName, params...)
|
||||
if err != nil {
|
||||
log.Errorf("MethodByName4 %s", funcName)
|
||||
return nil, err
|
||||
}
|
||||
if len(outs) != 2 {
|
||||
@@ -1100,6 +1103,7 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
|
||||
resVal := outs[0]
|
||||
errVal := outs[1].Interface()
|
||||
if !gotypes.IsNil(errVal) {
|
||||
log.Errorf("MethodByName3 %s", funcName)
|
||||
return nil, errVal.(error)
|
||||
} else {
|
||||
if gotypes.IsNil(resVal.Interface()) {
|
||||
@@ -1580,17 +1584,20 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
|
||||
|
||||
results := make([]printutils.SubmitResult, count)
|
||||
models := make([]IModel, 0)
|
||||
for i, res := range createResults {
|
||||
for i := range createResults {
|
||||
res := createResults[i]
|
||||
result := printutils.SubmitResult{}
|
||||
if res.err != nil {
|
||||
jsonErr := httperrors.NewGeneralError(res.err)
|
||||
result.Status = jsonErr.Code
|
||||
result.Data = jsonutils.Marshal(jsonErr)
|
||||
} else {
|
||||
lockman.LockObject(ctx, res.model)
|
||||
defer lockman.ReleaseObject(ctx, res.model)
|
||||
func() {
|
||||
lockman.LockObject(ctx, res.model)
|
||||
defer lockman.ReleaseObject(ctx, res.model)
|
||||
|
||||
res.model.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
res.model.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
}()
|
||||
|
||||
models = append(models, res.model)
|
||||
body, err := getItemDetails(manager, res.model, ctx, userCred, query)
|
||||
@@ -1605,10 +1612,12 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
|
||||
results[i] = result
|
||||
}
|
||||
if len(models) > 0 {
|
||||
lockman.LockClass(ctx, manager, GetLockClassKey(manager, ownerId))
|
||||
defer lockman.ReleaseClass(ctx, manager, GetLockClassKey(manager, ownerId))
|
||||
func() {
|
||||
lockman.LockClass(ctx, manager, GetLockClassKey(manager, ownerId))
|
||||
defer lockman.ReleaseClass(ctx, manager, GetLockClassKey(manager, ownerId))
|
||||
|
||||
manager.OnCreateComplete(ctx, models, userCred, ownerId, query, multiData)
|
||||
manager.OnCreateComplete(ctx, models, userCred, ownerId, query, multiData)
|
||||
}()
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ const (
|
||||
ACT_BACKUP_START = "backup_start"
|
||||
ACT_BACKUP_START_FAILED = "backup_start_fail"
|
||||
|
||||
ACT_SET_RELEASE_TIME = "set_release_time"
|
||||
|
||||
ACT_FREEZE = "freeze"
|
||||
ACT_FREEZE_FAIL = "freeze_fail"
|
||||
ACT_UNFREEZE = "unfreeze"
|
||||
@@ -265,6 +267,7 @@ const (
|
||||
ACT_GUEST_CREATE_FROM_IMPORT_SUCC = "guest_create_from_import_succ"
|
||||
ACT_GUEST_CREATE_FROM_IMPORT_FAIL = "guest_create_from_import_fail"
|
||||
ACT_GUEST_PANICKED = "guest_panicked"
|
||||
ACT_GUEST_SCREEN_DUMP = "guest_screen_dump"
|
||||
ACT_HOST_MAINTENANCE = "host_maintenance"
|
||||
ACT_HOST_DOWN = "host_down"
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -52,6 +54,9 @@ type SStandaloneAnonResourceBase struct {
|
||||
// 是否是模拟资源, 部分从公有云上同步的资源并不真实存在, 例如宿主机
|
||||
// list 接口默认不会返回这类资源,除非显示指定 is_emulate=true 过滤参数
|
||||
IsEmulated bool `nullable:"false" default:"false" list:"admin" create:"admin_optional" json:"is_emulated"`
|
||||
|
||||
// 用以组织架构变更通知其他服务权限变更
|
||||
OrgNodeMd5 string `width:"32" charset:"ascii" nullable:"true"`
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) BeforeInsert() {
|
||||
@@ -365,6 +370,11 @@ func (model *SStandaloneAnonResourceBase) SetOrganizationMetadataAll(ctx context
|
||||
return errors.Wrap(err, "SetAllOrganization")
|
||||
}
|
||||
}
|
||||
Update(model, func() error {
|
||||
model.OrgNodeMd5 = fmt.Sprintf("%x", md5.Sum([]byte(jsonutils.Marshal(meta).String())))
|
||||
return nil
|
||||
})
|
||||
|
||||
// 避免加入组织架构后,项目所在的层级会移除此项目
|
||||
//{
|
||||
// userTags := make(map[string]interface{})
|
||||
@@ -1013,7 +1023,7 @@ func GetTagValueCountMap(
|
||||
}
|
||||
objSubQ = objSubQ.AppendField(sumFieldQ)
|
||||
|
||||
objSubQ.DebugQuery2("GetTagValueCountMap objSubQ")
|
||||
// objSubQ.DebugQuery2("GetTagValueCountMap objSubQ")
|
||||
|
||||
q := objSubQ.SubQuery().Query()
|
||||
q = q.AppendField(sqlchemy.SUM(tagValueCountKey, q.Field("_sub_count_")))
|
||||
@@ -1036,7 +1046,7 @@ func GetTagValueCountMap(
|
||||
}
|
||||
q = q.GroupBy(groupBy...)
|
||||
|
||||
q.DebugQuery2("GetTagValueCountMap")
|
||||
// q.DebugQuery2("GetTagValueCountMap")
|
||||
|
||||
valueMap, err := q.AllStringMap()
|
||||
if err != nil {
|
||||
|
||||
@@ -150,6 +150,7 @@ type CommonOptions struct {
|
||||
|
||||
type HostCommonOptions struct {
|
||||
CommonOptions
|
||||
S3CommonOptions
|
||||
|
||||
ExecutorSocketPath string `help:"Executor socket path" default:"/var/run/onecloud/exec.sock"`
|
||||
DeployServerSocketPath string `help:"Deploy server listen socket path" default:"/var/run/onecloud/deploy.sock"`
|
||||
@@ -163,6 +164,15 @@ type HostCommonOptions struct {
|
||||
Qcow2Preallocation string `help:"Qcow2 image create preallocation" default:"metadata" choices:"disable|metadata|falloc|full"`
|
||||
}
|
||||
|
||||
type S3CommonOptions struct {
|
||||
S3AccessKey string `help:"s3 access key"`
|
||||
S3SecretKey string `help:"s3 secret key"`
|
||||
S3Endpoint string `help:"s3 endpoint"`
|
||||
S3UseSSL bool `help:"s3 access use ssl"`
|
||||
S3BucketName string `help:"s3 bucket name" default:"onecloud-screendump"`
|
||||
S3BucketLifecycleKeepDay int `help:"s3 bucket lifecycle keep day" default:"180"`
|
||||
}
|
||||
|
||||
type DBOptions struct {
|
||||
SqlConnection string `help:"SQL connection string" alias:"connection"`
|
||||
|
||||
|
||||
@@ -19,13 +19,12 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/monitor"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/tsdb"
|
||||
"yunion.io/x/onecloud/pkg/cloutpost/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudmon/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
|
||||
@@ -40,67 +39,35 @@ const (
|
||||
func AlertHistoryReport(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
err := func() error {
|
||||
s := auth.GetAdminSession(ctx, options.Options.Region)
|
||||
params := map[string]interface{}{
|
||||
"field": "res_type",
|
||||
"scope": "system",
|
||||
"filter.0": fmt.Sprintf("created_at.ge('%s')", time.Now().Add(time.Hour*-24)),
|
||||
}
|
||||
ret, err := monitor.AlertRecordManager.Get(s, "distinct-field", jsonutils.Marshal(params))
|
||||
resp, err := monitor.AlertRecordManager.Get(s, "history-alert", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "distinct-filed")
|
||||
return errors.Wrapf(err, "history-alert")
|
||||
}
|
||||
alerts := api.AlertRecordHistoryAlert{}
|
||||
err = resp.Unmarshal(&alerts)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Unmarshal AlertRecordHistoryAlert")
|
||||
}
|
||||
resTypes := []string{}
|
||||
ret.Unmarshal(&resTypes, "res_type")
|
||||
metrics := []influxdb.SMetricData{}
|
||||
for _, resType := range resTypes {
|
||||
records := []api.AlertRecordDetails{}
|
||||
for {
|
||||
query := map[string]interface{}{
|
||||
"limit": 40,
|
||||
"offset": len(records),
|
||||
"@state": "alerting",
|
||||
"scope": "system",
|
||||
"filter.0": fmt.Sprintf(`res_type.equals('%s')`, resType),
|
||||
"filter.1": fmt.Sprintf("created_at.ge('%s')", time.Now().Add(time.Hour*-24)),
|
||||
}
|
||||
ret, err := monitor.AlertRecordManager.List(s, jsonutils.Marshal(query))
|
||||
if err != nil {
|
||||
log.Errorf("AlertRecordManager.List error: %v", err)
|
||||
break
|
||||
}
|
||||
part := []api.AlertRecordDetails{}
|
||||
err = jsonutils.Update(&part, ret.Data)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
records = append(records, part...)
|
||||
if len(records) >= ret.Total {
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, alert := range alerts.Data {
|
||||
metric := influxdb.SMetricData{}
|
||||
metric.Name = ALERT_RECORD_HISTORY_MEASUREMENT
|
||||
cnt := 0
|
||||
for i, record := range records {
|
||||
cnt += int(record.ResNum)
|
||||
if i == 0 {
|
||||
for k, v := range record.GetMetricTags() {
|
||||
metric.Tags = append(metric.Tags, influxdb.SKeyValue{
|
||||
Key: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
metric.Timestamp = time.Now()
|
||||
metric.Metrics = []influxdb.SKeyValue{
|
||||
{
|
||||
Key: "res_num",
|
||||
Value: fmt.Sprintf("%d", cnt),
|
||||
Value: fmt.Sprintf("%d", alert.ResNum),
|
||||
},
|
||||
}
|
||||
for k, v := range alert.GetMetricTags() {
|
||||
metric.Tags = append(metric.Tags, influxdb.SKeyValue{
|
||||
Key: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
metrics = append(metrics, metric)
|
||||
}
|
||||
|
||||
urls, err := tsdb.GetDefaultServiceSourceURLs(s, options.Options.SessionEndpointType)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetServiceURLs")
|
||||
|
||||
@@ -76,8 +76,8 @@ func (self *CtyunCollect) CollectServerMetrics(ctx context.Context, manager api.
|
||||
if last > len(servers) {
|
||||
last = len(servers)
|
||||
}
|
||||
for i := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i].ExternalId)
|
||||
for j := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i*10+j].ExternalId)
|
||||
}
|
||||
part, err := provider.GetMetrics(opts)
|
||||
if err != nil {
|
||||
|
||||
35
pkg/cloudmon/providerdriver/ksyun.go
Normal file
35
pkg/cloudmon/providerdriver/ksyun.go
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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 providerdriver
|
||||
|
||||
import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type KsyunCollect struct {
|
||||
SCollectByResourceIdDriver
|
||||
}
|
||||
|
||||
func (kc *KsyunCollect) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_KSYUN
|
||||
}
|
||||
|
||||
func (kc *KsyunCollect) IsSupportMetrics() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register(&KsyunCollect{})
|
||||
}
|
||||
@@ -102,8 +102,8 @@ func (self *QcloudCollect) CollectServerMetrics(ctx context.Context, manager api
|
||||
if last > len(servers) {
|
||||
last = len(servers)
|
||||
}
|
||||
for i := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i].ExternalId)
|
||||
for j := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i*10+j].ExternalId)
|
||||
}
|
||||
part, err := provider.GetMetrics(opts)
|
||||
if err != nil {
|
||||
@@ -197,8 +197,8 @@ func (self *QcloudCollect) CollectDBInstanceMetrics(ctx context.Context, manager
|
||||
if last > len(servers) {
|
||||
last = len(servers)
|
||||
}
|
||||
for i := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i].ExternalId)
|
||||
for j := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i*10+j].ExternalId)
|
||||
}
|
||||
|
||||
part, err := provider.GetMetrics(opts)
|
||||
@@ -293,8 +293,8 @@ func (self *QcloudCollect) CollectRedisMetrics(ctx context.Context, manager api.
|
||||
if last > len(servers) {
|
||||
last = len(servers)
|
||||
}
|
||||
for i := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i].ExternalId)
|
||||
for j := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i*10+j].ExternalId)
|
||||
}
|
||||
|
||||
part, err := provider.GetMetrics(opts)
|
||||
|
||||
@@ -104,8 +104,8 @@ func (self *VolcEngineCollect) CollectServerMetrics(ctx context.Context, manager
|
||||
if last > len(servers) {
|
||||
last = len(servers)
|
||||
}
|
||||
for i := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i].ExternalId)
|
||||
for j := range servers[i*10 : last] {
|
||||
opts.ResourceIds = append(opts.ResourceIds, servers[i*10+j].ExternalId)
|
||||
}
|
||||
part, err := provider.GetMetrics(opts)
|
||||
if err != nil {
|
||||
|
||||
@@ -34,8 +34,6 @@ func init() {
|
||||
models.RegisterGuestDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SBaiduGuestDriver) DoScheduleSKUFilter() bool { return false }
|
||||
|
||||
func (self *SBaiduGuestDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_BAIDU
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func (drv *SBaseGuestDriver) OnGuestCreateTaskComplete(ctx context.Context, gues
|
||||
if len(duration) > 0 {
|
||||
bc, err := billing.ParseBillingCycle(duration)
|
||||
if err == nil && guest.ExpiredAt.IsZero() {
|
||||
guest.SaveRenewInfo(ctx, task.GetUserCred(), &bc, nil, "")
|
||||
models.SaveRenewInfo(ctx, task.GetUserCred(), guest, &bc, nil, "")
|
||||
}
|
||||
if jsonutils.QueryBoolean(task.GetParams(), "auto_prepaid_recycle", false) {
|
||||
err := guest.CanPerformPrepaidRecycle()
|
||||
@@ -395,11 +395,6 @@ func (drv *SBaseGuestDriver) RequestSyncSecgroupsOnHost(ctx context.Context, gue
|
||||
return nil // do nothing
|
||||
}
|
||||
|
||||
func (drv *SBaseGuestDriver) CancelExpireTime(
|
||||
ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest) error {
|
||||
return guest.CancelExpireTime(ctx, userCred)
|
||||
}
|
||||
|
||||
func (drv *SBaseGuestDriver) IsSupportPublicipToEip() bool {
|
||||
return false
|
||||
}
|
||||
@@ -527,6 +522,10 @@ func (drv *SBaseGuestDriver) RequestQgaCommand(ctx context.Context, userCred mcc
|
||||
return nil, httperrors.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestGuestScreenDump(ctx context.Context, userCred mcclient.TokenCredential, body jsonutils.JSONObject, host *models.SHost, guest *models.SGuest) (jsonutils.JSONObject, error) {
|
||||
return nil, httperrors.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (drv *SBaseGuestDriver) FetchMonitorUrl(ctx context.Context, guest *models.SGuest) string {
|
||||
s := auth.GetAdminSessionWithPublic(ctx, consts.GetRegion())
|
||||
tsdbURL, err := tsdb.GetDefaultServiceSourceURL(s, options.Options.MonitorEndpointType)
|
||||
|
||||
@@ -34,8 +34,6 @@ func init() {
|
||||
models.RegisterGuestDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SCucloudGuestDriver) DoScheduleSKUFilter() bool { return false }
|
||||
|
||||
func (self *SCucloudGuestDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_CUCLOUD
|
||||
}
|
||||
|
||||
@@ -79,14 +79,25 @@ func (self *SGoogleGuestDriver) GetInstanceCapability() cloudprovider.SInstanceC
|
||||
},
|
||||
Storages: cloudprovider.Storage{
|
||||
DataDisk: []cloudprovider.StorageInfo{
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_EXTREME, MaxSizeGb: 65536, MinSizeGb: 500, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_LOCAL_SSD, MaxSizeGb: 375, MinSizeGb: 375, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_BALANCED, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_EXTREME, MaxSizeGb: 65536, MinSizeGb: 64, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT, MaxSizeGb: 32768, MinSizeGb: 2048, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_ML, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
},
|
||||
SysDisk: []cloudprovider.StorageInfo{
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_EXTREME, MaxSizeGb: 65536, MinSizeGb: 500, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_BALANCED, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_EXTREME, MaxSizeGb: 65536, MinSizeGb: 64, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT, MaxSizeGb: 32768, MinSizeGb: 2048, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_ML, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -105,7 +116,12 @@ func (self *SGoogleGuestDriver) GetStorageTypes() []string {
|
||||
api.STORAGE_GOOGLE_PD_SSD,
|
||||
api.STORAGE_GOOGLE_PD_STANDARD,
|
||||
api.STORAGE_GOOGLE_PD_BALANCED,
|
||||
api.STORAGE_GOOGLE_PD_EXTREME,
|
||||
api.STORAGE_GOOGLE_LOCAL_SSD,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_BALANCED,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_EXTREME,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_ML,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +157,12 @@ func (self *SGoogleGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *m
|
||||
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
}
|
||||
if !utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED}) {
|
||||
if !utils.IsInStringArray(storage.StorageType, []string{
|
||||
api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD,
|
||||
api.STORAGE_GOOGLE_PD_BALANCED, api.STORAGE_GOOGLE_PD_EXTREME,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_BALANCED, api.STORAGE_GOOGLE_HYPERDISK_EXTREME,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT, api.STORAGE_GOOGLE_HYPERDISK_ML,
|
||||
}) {
|
||||
return fmt.Errorf("Cannot resize %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
@@ -163,10 +184,22 @@ func (self *SGoogleGuestDriver) ValidateCreateData(ctx context.Context, userCred
|
||||
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED:
|
||||
minGB = 10
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_PD_EXTREME:
|
||||
minGB = 500
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_LOCAL_SSD:
|
||||
minGB = 375
|
||||
maxGB = 375
|
||||
localDisk++
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_BALANCED, api.STORAGE_GOOGLE_HYPERDISK_ML:
|
||||
minGB = 4
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT:
|
||||
minGB = 2048
|
||||
maxGB = 32768
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_EXTREME:
|
||||
minGB = 64
|
||||
maxGB = 65536
|
||||
default:
|
||||
return nil, httperrors.NewInputParameterError("Unknown google storage type %s", disk.Backend)
|
||||
}
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
package guestdrivers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
"yunion.io/x/pkg/util/rbacscope"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
@@ -34,8 +37,6 @@ func init() {
|
||||
models.RegisterGuestDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) DoScheduleSKUFilter() bool { return false }
|
||||
|
||||
func (self *SKsyunGuestDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_KSYUN
|
||||
}
|
||||
@@ -52,6 +53,56 @@ func (self *SKsyunGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return 20
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetStorageTypes() []string {
|
||||
return []string{
|
||||
api.STORAGE_KSYUN_ESSD_AUTO_PL,
|
||||
api.STORAGE_KSYUN_SSD3_0,
|
||||
api.STORAGE_KSYUN_EHDD,
|
||||
api.STORAGE_KSYUN_ESSD_PL1,
|
||||
api.STORAGE_KSYUN_ESSD_PL2,
|
||||
api.STORAGE_KSYUN_ESSD_PL3,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) ChooseHostStorage(host *models.SHost, guest *models.SGuest, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
|
||||
return chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetRebuildRootStatus() ([]string, error) {
|
||||
return []string{api.VM_READY}, nil
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) IsAllowSaveImageOnRunning() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetChangeInstanceTypeStatus() ([]string, error) {
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_RUNNING
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
|
||||
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetComputeQuotaKeys(scope rbacscope.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
|
||||
keys := models.SComputeResourceKeys{}
|
||||
keys.SBaseProjectQuotaKeys = quotas.OwnerIdProjectQuotaKeys(scope, ownerId)
|
||||
@@ -76,15 +127,27 @@ func (self *SKsyunGuestDriver) GetInstanceCapability() cloudprovider.SInstanceCa
|
||||
Changeable: false,
|
||||
},
|
||||
},
|
||||
Storages: cloudprovider.Storage{
|
||||
DataDisk: []cloudprovider.StorageInfo{
|
||||
{StorageType: api.STORAGE_KSYUN_SSD3_0, MaxSizeGb: 65535, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_EHDD, MaxSizeGb: 65535, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_ESSD_PL1, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_ESSD_PL2, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_ESSD_PL3, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
},
|
||||
SysDisk: []cloudprovider.StorageInfo{
|
||||
{StorageType: api.STORAGE_KSYUN_SSD3_0, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_EHDD, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_ESSD_PL1, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_ESSD_PL2, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
{StorageType: api.STORAGE_KSYUN_ESSD_PL3, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetGuestInitialStateAfterCreate() string {
|
||||
return api.VM_READY
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_READY
|
||||
return api.VM_RUNNING
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) AllowReconfigGuest() bool {
|
||||
@@ -92,6 +155,9 @@ func (self *SKsyunGuestDriver) AllowReconfigGuest() bool {
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
if bc.GetMonths() >= 1 && bc.GetMonths() <= 36 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -102,3 +168,11 @@ func (self *SKsyunGuestDriver) IsSupportPublicipToEip() bool {
|
||||
func (self *SKsyunGuestDriver) IsSupportSetAutoRenew() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) IsSupportShutdownMode() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SKsyunGuestDriver) IsNeedRestartForResetLoginInfo() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1164,6 +1164,17 @@ func (self *SKVMGuestDriver) RequestQgaCommand(ctx context.Context, userCred mcc
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestGuestScreenDump(ctx context.Context, userCred mcclient.TokenCredential, body jsonutils.JSONObject, host *models.SHost, guest *models.SGuest) (jsonutils.JSONObject, error) {
|
||||
url := fmt.Sprintf("%s/servers/%s/guest-screen-dump", host.ManagerUri, guest.Id)
|
||||
httpClient := httputils.GetDefaultClient()
|
||||
header := mcclient.GetTokenHeaders(userCred)
|
||||
_, res, err := httputils.JSONRequest(httpClient, ctx, "POST", url, header, nil, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "host request")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) FetchMonitorUrl(ctx context.Context, guest *models.SGuest) string {
|
||||
if options.Options.KvmMonitorAgentUseMetadataService && !guest.IsSriov() {
|
||||
return apis.MetaServiceMonitorAgentUrl
|
||||
|
||||
@@ -84,7 +84,11 @@ func (drv *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Context
|
||||
config.InstanceType = guest.InstanceType
|
||||
|
||||
if len(guest.KeypairId) > 0 {
|
||||
config.PublicKey = guest.GetKeypairPublicKey()
|
||||
keypair := guest.GetKeypair()
|
||||
if keypair != nil {
|
||||
config.PublicKey = keypair.PublicKey
|
||||
config.KeypairName = keypair.Name
|
||||
}
|
||||
}
|
||||
|
||||
nics, _ := guest.GetNetworks("")
|
||||
@@ -755,9 +759,11 @@ func (drv *SManagedVirtualizedGuestDriver) RemoteDeployGuestForDeploy(ctx contex
|
||||
log.Debugf("Deploy VM params %s", params.String())
|
||||
|
||||
opts := &cloudprovider.SInstanceDeployOptions{
|
||||
Username: desc.Account,
|
||||
PublicKey: desc.PublicKey,
|
||||
Password: desc.Password,
|
||||
Username: desc.Account,
|
||||
PublicKey: desc.PublicKey,
|
||||
KeypairName: desc.KeypairName,
|
||||
Password: desc.Password,
|
||||
UserData: desc.UserData,
|
||||
}
|
||||
opts.DeleteKeypair = jsonutils.QueryBoolean(params, "__delete_keypair__", false)
|
||||
|
||||
@@ -820,12 +826,14 @@ func (drv *SManagedVirtualizedGuestDriver) RemoteDeployGuestForRebuildRoot(ctx c
|
||||
defer lockman.ReleaseObject(ctx, guest)
|
||||
|
||||
conf := cloudprovider.SManagedVMRebuildRootConfig{
|
||||
Account: desc.Account,
|
||||
ImageId: desc.ExternalImageId,
|
||||
Password: desc.Password,
|
||||
PublicKey: desc.PublicKey,
|
||||
SysSizeGB: desc.SysDisk.SizeGB,
|
||||
OsType: desc.OsType,
|
||||
Account: desc.Account,
|
||||
ImageId: desc.ExternalImageId,
|
||||
Password: desc.Password,
|
||||
PublicKey: desc.PublicKey,
|
||||
KeypairName: desc.KeypairName,
|
||||
SysSizeGB: desc.SysDisk.SizeGB,
|
||||
OsType: desc.OsType,
|
||||
UserData: desc.UserData,
|
||||
}
|
||||
return iVM.RebuildRoot(ctx, &conf)
|
||||
}()
|
||||
@@ -911,9 +919,10 @@ func (drv *SManagedVirtualizedGuestDriver) RequestUndeployGuestOnHost(ctx contex
|
||||
return nil, errors.Wrapf(err, "GetDisks")
|
||||
}
|
||||
|
||||
for _, disk := range disks {
|
||||
for i := range disks {
|
||||
disk := disks[i]
|
||||
storage, _ := disk.GetStorage()
|
||||
if !disk.AutoDelete && !utils.IsInStringArray(storage.StorageType, api.STORAGE_LOCAL_TYPES) && disk.DiskType != api.DISK_TYPE_SYS {
|
||||
if !utils.IsInStringArray(storage.StorageType, api.STORAGE_LOCAL_TYPES) && disk.DiskType != api.DISK_TYPE_SYS {
|
||||
idisk, err := disk.GetIDisk(ctx)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
@@ -1003,6 +1012,7 @@ func (drv *SManagedVirtualizedGuestDriver) RequestChangeBillingType(ctx context.
|
||||
guest.BillingType = ivm.GetBillingType()
|
||||
guest.Status = ivm.GetStatus()
|
||||
guest.ExpiredAt = time.Time{}
|
||||
guest.AutoRenew = false
|
||||
if guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
guest.AutoRenew = ivm.IsAutoRenew()
|
||||
guest.ExpiredAt = ivm.GetExpiredAt()
|
||||
@@ -1108,7 +1118,7 @@ func (drv *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Con
|
||||
}
|
||||
err := iVM.ChangeConfig(ctx, config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GuestDriver.RequestChangeVmConfig.ChangeConfig")
|
||||
return nil, errors.Wrap(err, "ChangeConfig")
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitCreated(time.Second*5, time.Minute*5, func() bool {
|
||||
@@ -1131,7 +1141,7 @@ func (drv *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Con
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GuestDriver.RequestChangeVmConfig.WaitCreated")
|
||||
return nil, errors.Wrap(err, "wait config change")
|
||||
}
|
||||
|
||||
instanceType = iVM.GetInstanceType()
|
||||
@@ -1141,7 +1151,7 @@ func (drv *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Con
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GuestDriver.RequestChangeVmConfig.Update")
|
||||
return nil, errors.Wrap(err, "Update")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1256,7 +1266,7 @@ func (drv *SManagedVirtualizedGuestDriver) OnGuestDeployTaskDataReceived(ctx con
|
||||
|
||||
exp, err := data.GetTime("expired_at")
|
||||
if err == nil && !guest.IsPrepaidRecycle() {
|
||||
guest.SaveRenewInfo(ctx, task.GetUserCred(), nil, &exp, "")
|
||||
models.SaveRenewInfo(ctx, task.GetUserCred(), guest, nil, &exp, "")
|
||||
}
|
||||
if guest.GetDriver().IsSupportSetAutoRenew() {
|
||||
autoRenew, _ := data.Bool("auto_renew")
|
||||
|
||||
@@ -34,8 +34,6 @@ func init() {
|
||||
models.RegisterGuestDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SQingCloudGuestDriver) DoScheduleSKUFilter() bool { return false }
|
||||
|
||||
func (self *SQingCloudGuestDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_QINGCLOUD
|
||||
}
|
||||
|
||||
@@ -50,12 +50,15 @@ func (self *SAliyunHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb
|
||||
case api.STORAGE_CLOUD_EFFICIENCY, api.STORAGE_CLOUD_SSD, api.STORAGE_CLOUD_ESSD:
|
||||
minGB = 20
|
||||
maxGB = 32768
|
||||
case api.STORAGE_CLOUD_ESSD_PL0:
|
||||
minGB = 1
|
||||
maxGB = 65536
|
||||
case api.STORAGE_CLOUD_ESSD_PL2:
|
||||
minGB = 461
|
||||
maxGB = 32768
|
||||
maxGB = 65536
|
||||
case api.STORAGE_CLOUD_ESSD_PL3:
|
||||
minGB = 1261
|
||||
maxGB = 32768
|
||||
maxGB = 65536
|
||||
case api.STORAGE_PUBLIC_CLOUD:
|
||||
minGB = 5
|
||||
maxGB = 2000
|
||||
@@ -66,7 +69,8 @@ func (self *SAliyunHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb
|
||||
minGB = 10
|
||||
maxGB = 32768
|
||||
default:
|
||||
return fmt.Errorf("Not support resize %s disk", storage.StorageType)
|
||||
minGB = 1
|
||||
maxGB = 65536
|
||||
}
|
||||
if sizeGb < minGB || sizeGb > maxGB {
|
||||
return fmt.Errorf("The %s disk size must be in the range of %dG ~ %dGB", storage.StorageType, minGB, maxGB)
|
||||
|
||||
@@ -39,6 +39,10 @@ func (self *SBaseHostDriver) ValidateUpdateDisk(ctx context.Context, userCred mc
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) RequestRemoteUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, disk *models.SDisk, replaceTags bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) ValidateResetDisk(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, guests []models.SGuest, input *api.DiskResetInput) (*api.DiskResetInput, error) {
|
||||
return nil, httperrors.NewNotImplementedError("Not Implement ValidateResetDisk")
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@ func (self *SESXiHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb i
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SESXiHostDriver) RequestRemoteUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, disk *models.SDisk, replaceTags bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SESXiHostDriver) CheckAndSetCacheImage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
|
||||
params := task.GetParams()
|
||||
imageId, err := params.GetString("image_id")
|
||||
|
||||
@@ -49,6 +49,18 @@ func (self *SGoogleHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb
|
||||
switch storage.StorageType {
|
||||
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED:
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_PD_EXTREME:
|
||||
minGB = 500
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_BALANCED, api.STORAGE_GOOGLE_HYPERDISK_ML:
|
||||
minGB = 4
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT:
|
||||
minGB = 2048
|
||||
maxGB = 32768
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_EXTREME:
|
||||
minGB = 64
|
||||
maxGB = 65536
|
||||
default:
|
||||
return fmt.Errorf("Not support resize %s disk", storage.StorageType)
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ func (self *SManagedVirtualizationHostDriver) RequestAllocateDiskOnStorage(ctx c
|
||||
if err != nil {
|
||||
logclient.AddSimpleActionLog(disk, logclient.ACT_SYNC_CLOUD_PROJECT, err, userCred, false)
|
||||
}
|
||||
conf := cloudprovider.DiskCreateConfig{
|
||||
opts := cloudprovider.DiskCreateConfig{
|
||||
Name: disk.GetName(),
|
||||
SizeGb: input.DiskSizeMb >> 10,
|
||||
ProjectId: projectId,
|
||||
@@ -261,7 +261,9 @@ func (self *SManagedVirtualizationHostDriver) RequestAllocateDiskOnStorage(ctx c
|
||||
Throughput: disk.Throughput,
|
||||
Desc: disk.Description,
|
||||
}
|
||||
iDisk, err := iCloudStorage.CreateIDisk(&conf)
|
||||
opts.Tags, _ = disk.GetAllUserMetadata()
|
||||
|
||||
iDisk, err := iCloudStorage.CreateIDisk(&opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -14,6 +14,55 @@
|
||||
|
||||
package hostdrivers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type SVirtualizationHostDriver struct {
|
||||
SBaseHostDriver
|
||||
}
|
||||
|
||||
func (self *SVirtualizationHostDriver) RequestRemoteUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, disk *models.SDisk, replaceTags bool) error {
|
||||
iDisk, err := disk.GetIDisk(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetIDisk")
|
||||
}
|
||||
|
||||
err = func() error {
|
||||
oldTags, err := iDisk.GetTags()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "iVM.GetTags()")
|
||||
}
|
||||
tags, err := disk.GetAllUserMetadata()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAllUserMetadata")
|
||||
}
|
||||
tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags}
|
||||
|
||||
err = cloudprovider.SetTags(ctx, iDisk, storage.ManagerId, tags, replaceTags)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented {
|
||||
return nil
|
||||
}
|
||||
logclient.AddSimpleActionLog(disk, logclient.ACT_UPDATE_TAGS, err, userCred, false)
|
||||
return errors.Wrap(err, "iVM.SetTags")
|
||||
}
|
||||
logclient.AddSimpleActionLog(disk, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true)
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -26,17 +26,16 @@ import (
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
notifyapi "yunion.io/x/onecloud/pkg/apis/notify"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/notify"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
@@ -44,8 +43,10 @@ type SBillingResourceBase struct {
|
||||
// 计费类型, 按量、包年包月
|
||||
// example: postpaid
|
||||
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"optional" json:"billing_type"`
|
||||
// 过期时间
|
||||
ExpiredAt time.Time `nullable:"true" list:"user" create:"optional" json:"expired_at"`
|
||||
// 包年包月到期时间
|
||||
ExpiredAt time.Time `nullable:"true" list:"user" json:"expired_at"`
|
||||
// 到期释放时间
|
||||
ReleaseAt time.Time `nullable:"true" list:"user" create:"optional" json:"release_at"`
|
||||
// 计费周期
|
||||
BillingCycle string `width:"10" charset:"ascii" nullable:"true" list:"user" create:"optional" json:"billing_cycle"`
|
||||
// 是否自动续费
|
||||
@@ -62,10 +63,35 @@ func (self *SBillingResourceBase) GetChargeType() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) SetReleaseAt(releaseAt time.Time) {
|
||||
self.ReleaseAt = releaseAt
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) GetExpiredAt() time.Time {
|
||||
return self.ExpiredAt
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) SetExpiredAt(expireAt time.Time) {
|
||||
self.ExpiredAt = expireAt
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) SetBillingCycle(billingCycle string) {
|
||||
self.BillingCycle = billingCycle
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) SetBillingType(billingType string) {
|
||||
self.BillingType = billingType
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) GetBillingType() string {
|
||||
return self.BillingType
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) getBillingBaseInfo() SBillingBaseInfo {
|
||||
info := SBillingBaseInfo{}
|
||||
info.ChargeType = self.GetChargeType()
|
||||
info.ExpiredAt = self.ExpiredAt
|
||||
info.ReleaseAt = self.ReleaseAt
|
||||
if self.GetChargeType() == api.BILLING_TYPE_PREPAID {
|
||||
info.BillingCycle = self.BillingCycle
|
||||
}
|
||||
@@ -93,7 +119,7 @@ func (self *SBillingResourceBase) IsValidPrePaid() bool {
|
||||
func (self *SBillingResourceBase) IsValidPostPaid() bool {
|
||||
if self.BillingType == api.BILLING_TYPE_POSTPAID {
|
||||
now := time.Now().UTC()
|
||||
if self.ExpiredAt.After(now) {
|
||||
if self.ReleaseAt.After(now) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -103,6 +129,7 @@ func (self *SBillingResourceBase) IsValidPostPaid() bool {
|
||||
type SBillingBaseInfo struct {
|
||||
ChargeType string `json:",omitempty"`
|
||||
ExpiredAt time.Time `json:",omitempty"`
|
||||
ReleaseAt time.Time `json:",omitempty"`
|
||||
BillingCycle string `json:",omitempty"`
|
||||
}
|
||||
|
||||
@@ -170,43 +197,14 @@ func (manager *SBillingResourceBaseManager) OrderByExtraFields(
|
||||
func ListExpiredPostpaidResources(
|
||||
q *sqlchemy.SQuery, limit int) *sqlchemy.SQuery {
|
||||
q = q.Equals("billing_type", api.BILLING_TYPE_POSTPAID)
|
||||
q = q.IsNotNull("expired_at")
|
||||
q = q.LT("expired_at", time.Now())
|
||||
q = q.IsNotNull("release_at")
|
||||
q = q.LT("release_at", time.Now())
|
||||
if limit > 0 {
|
||||
q = q.Limit(limit)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func ParseBillingCycleInput(billingBase *SBillingResourceBase, input apis.PostpaidExpireInput) (*billing.SBillingCycle, error) {
|
||||
var (
|
||||
bc billing.SBillingCycle
|
||||
err error
|
||||
durationStr string
|
||||
)
|
||||
if len(input.Duration) == 0 {
|
||||
if input.ExpireTime.IsZero() {
|
||||
return nil, httperrors.NewInputParameterError("missing duration/expire_time")
|
||||
}
|
||||
timeC := billingBase.ExpiredAt
|
||||
if timeC.IsZero() {
|
||||
timeC = time.Now()
|
||||
}
|
||||
dur := input.ExpireTime.Sub(timeC)
|
||||
if dur <= 0 {
|
||||
return nil, httperrors.NewInputParameterError("expire time is before current expire at")
|
||||
}
|
||||
bc = billing.DurationToBillingCycle(dur)
|
||||
} else {
|
||||
bc, err = billing.ParseBillingCycle(durationStr)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid duration %s: %s", durationStr, err)
|
||||
}
|
||||
}
|
||||
|
||||
return &bc, nil
|
||||
}
|
||||
|
||||
type SBillingResourceCheckManager struct {
|
||||
db.SResourceBaseManager
|
||||
}
|
||||
@@ -242,6 +240,55 @@ type IBillingModelManager interface {
|
||||
type IBillingModel interface {
|
||||
db.IModel
|
||||
GetExpiredAt() time.Time
|
||||
SetReleaseAt(releaseAt time.Time)
|
||||
SetExpiredAt(expireAt time.Time)
|
||||
SetBillingCycle(billingCycle string)
|
||||
SetBillingType(billingType string)
|
||||
GetBillingType() string
|
||||
}
|
||||
|
||||
func SaveReleaseAt(ctx context.Context, model IBillingModel, userCred mcclient.TokenCredential, releaseAt time.Time) error {
|
||||
diff, err := db.Update(model, func() error {
|
||||
model.SetReleaseAt(releaseAt)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Update")
|
||||
}
|
||||
if len(diff) > 0 {
|
||||
db.OpsLog.LogEvent(model, db.ACT_SET_RELEASE_TIME, fmt.Sprintf("release at: %s", releaseAt), userCred)
|
||||
}
|
||||
if len(diff) > 0 && userCred != nil {
|
||||
logclient.AddActionLogWithContext(ctx, model, logclient.ACT_SET_RELEASE_TIME, diff, userCred, true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
model IBillingModel, bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(model, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if model.GetBillingType() == "" {
|
||||
model.SetBillingType(billingType)
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
model.SetExpiredAt(*expireAt)
|
||||
} else if bc != nil {
|
||||
model.SetBillingCycle(bc.String())
|
||||
model.SetExpiredAt(bc.EndAt(model.GetExpiredAt()))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("UpdateItem error %s", err)
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogEvent(model, db.ACT_RENEW, model.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchExpiredModels(manager db.IModelManager, advanceDay int) ([]IBillingModel, error) {
|
||||
|
||||
@@ -882,47 +882,65 @@ func (manager *SCachedimageManager) ListItemFilter(
|
||||
}
|
||||
|
||||
{
|
||||
var idFilter bool
|
||||
storagecachedImages := StoragecachedimageManager.Query("cachedimage_id").Equals("status", api.CACHED_IMAGE_STATUS_ACTIVE).SubQuery()
|
||||
storageCaches := StoragecacheManager.Query().SubQuery()
|
||||
storagecachedImages := StoragecachedimageManager.Query("cachedimage_id").Equals("status", api.CACHED_IMAGE_STATUS_ACTIVE) // .SubQuery()
|
||||
storagecachedImages = storagecachedImages.Snapshot()
|
||||
|
||||
storagesQ := StorageManager.Query()
|
||||
storagesQ := StorageManager.Query("storagecache_id")
|
||||
storagesQ = storagesQ.Snapshot()
|
||||
if query.Valid {
|
||||
idFilter = true
|
||||
storagesQ = storagesQ.In("status", []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}).IsTrue("enabled")
|
||||
}
|
||||
if len(query.CloudproviderId) > 0 {
|
||||
idFilter = true
|
||||
storagesQ = storagesQ.In("manager_id", query.CloudproviderId)
|
||||
}
|
||||
storages := storagesQ.SubQuery()
|
||||
zonesQ := ZoneManager.Query()
|
||||
if len(query.CloudEnv) > 0 {
|
||||
switch query.CloudEnv {
|
||||
case api.CLOUD_ENV_PUBLIC_CLOUD:
|
||||
pubQ := CloudproviderManager.GetPublicProviderIdsQuery()
|
||||
storagesQ = storagesQ.In("manager_id", pubQ)
|
||||
case api.CLOUD_ENV_PRIVATE_CLOUD:
|
||||
privQ := CloudproviderManager.GetPrivateProviderIdsQuery()
|
||||
storagesQ = storagesQ.In("manager_id", privQ)
|
||||
case api.CLOUD_ENV_ON_PREMISE:
|
||||
storagesQ = storagesQ.IsNullOrEmpty("manager_id")
|
||||
case api.CLOUD_ENV_PRIVATE_ON_PREMISE:
|
||||
privQ := CloudproviderManager.GetPrivateProviderIdsQuery()
|
||||
storagesQ = storagesQ.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.In(storagesQ.Field("manager_id"), privQ),
|
||||
sqlchemy.IsNullOrEmpty(storagesQ.Field("manager_id")),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
if len(query.HostSchedtagId) > 0 {
|
||||
hostschedtags := HostschedtagManager.Query("host_id").Equals("schedtag_id", query.HostSchedtagId)
|
||||
hoststorages := HoststorageManager.Query("storage_id").In("host_id", hostschedtags.Distinct().SubQuery())
|
||||
storagesQ = storagesQ.In("id", hoststorages.Distinct().SubQuery())
|
||||
}
|
||||
|
||||
zonesQ := ZoneManager.Query("id")
|
||||
zonesQ = zonesQ.Snapshot()
|
||||
if len(query.ZoneId) > 0 {
|
||||
idFilter = true
|
||||
zonesQ = zonesQ.Equals("id", query.ZoneId)
|
||||
}
|
||||
if len(query.CloudregionId) > 0 {
|
||||
idFilter = true
|
||||
zonesQ = zonesQ.In("cloudregion_id", query.CloudregionId)
|
||||
}
|
||||
zones := zonesQ.SubQuery()
|
||||
|
||||
subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id"))
|
||||
subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id")))
|
||||
subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id")))
|
||||
subq = subq.Join(zones, sqlchemy.Equals(storages.Field("zone_id"), zones.Field("id")))
|
||||
|
||||
if len(query.HostSchedtagId) > 0 {
|
||||
idFilter = true
|
||||
hoststorages := HoststorageManager.Query("host_id", "storage_id").SubQuery()
|
||||
hostschedtags := HostschedtagManager.Query().Equals("schedtag_id", query.HostSchedtagId).SubQuery()
|
||||
subq = subq.Join(hoststorages, sqlchemy.Equals(hoststorages.Field("storage_id"), storages.Field("id")))
|
||||
subq = subq.Join(hostschedtags, sqlchemy.Equals(hostschedtags.Field("host_id"), hoststorages.Field("host_id")))
|
||||
if zonesQ.IsAltered() {
|
||||
storagesQ = storagesQ.Filter(
|
||||
sqlchemy.In(storagesQ.Field("zone_id"), zonesQ.Distinct().SubQuery()),
|
||||
)
|
||||
}
|
||||
|
||||
if idFilter {
|
||||
subQ := subq.Distinct().SubQuery()
|
||||
q = q.Join(subQ, sqlchemy.Equals(q.Field("id"), subQ.Field("cachedimage_id")))
|
||||
if storagesQ.IsAltered() {
|
||||
storagecachedImages = storagecachedImages.Filter(
|
||||
sqlchemy.In(storagecachedImages.Field("storagecache_id"), storagesQ.Distinct().SubQuery()),
|
||||
)
|
||||
}
|
||||
|
||||
if storagecachedImages.IsAltered() {
|
||||
q = q.In("id", storagecachedImages.Distinct().SubQuery())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,10 @@ type SCapabilities struct {
|
||||
DisabledObjectStorageBrands []string `json:",allowempty"`
|
||||
DisabledModelartsPoolsBrands []string `json:",allowempty"`
|
||||
ModelartsPoolsBrands []string `json:",allowempty"`
|
||||
MongoDBBrands []string `json:"mongodb_brands,allowempty"`
|
||||
DisabledMongoDBBrands []string `json:"disabled_mongodb_brands,allowempty"`
|
||||
KafkaBrands []string `json:"kafka_brands,allowempty"`
|
||||
DisabledKafkaBrands []string `json:"disabled_kafka_brands,allowempty"`
|
||||
|
||||
ContainerBrands []string `json:",allowempty"`
|
||||
DisabledContainerBrands []string `json:",allowempty"`
|
||||
@@ -117,6 +121,10 @@ type SCapabilities struct {
|
||||
ReadOnlyDisabledObjectStorageBrands []string `json:",allowempty"`
|
||||
ReadOnlyModelartsPoolsBrands []string `json:",allowempty"`
|
||||
ReadOnlyDisabledModelartsPoolsBrands []string `json:",allowempty"`
|
||||
ReadOnlyMongoDBBrands []string `json:"readonly_mongodb_brands,allowempty"`
|
||||
ReadOnlyDisabledMongoDBBrands []string `json:"readonly_disabled_mongodb_brands,allowempty"`
|
||||
ReadOnlyKafkaBrands []string `json:"readonly_kafka_brands,allowempty"`
|
||||
ReadOnlyDisabledKafkaBrands []string `json:"readonly_disabled_kafka_brands,allowempty"`
|
||||
|
||||
ReadOnlyContainerBrands []string `json:",allowempty"`
|
||||
ReadOnlyDisabledContainerBrands []string `json:",allowempty"`
|
||||
@@ -479,6 +487,10 @@ func getBrands(region *SCloudregion, zone *SZone, domainId string, capa *SCapabi
|
||||
appendBrand(&capa.SnapshotPolicyBrands, &capa.DisabledSnapshotPolicyBrands, &capa.ReadOnlySnapshotPolicyBrands, &capa.ReadOnlyDisabledSnapshotPolicyBrands, brand, capability, enabled, readOnly)
|
||||
case cloudprovider.CLOUD_CAPABILITY_MODELARTES:
|
||||
appendBrand(&capa.ModelartsPoolsBrands, &capa.DisabledModelartsPoolsBrands, &capa.ReadOnlyModelartsPoolsBrands, &capa.ReadOnlyDisabledModelartsPoolsBrands, brand, capability, enabled, readOnly)
|
||||
case cloudprovider.CLOUD_CAPABILITY_MONGO_DB:
|
||||
appendBrand(&capa.MongoDBBrands, &capa.DisabledMongoDBBrands, &capa.ReadOnlyMongoDBBrands, &capa.ReadOnlyDisabledMongoDBBrands, brand, capability, enabled, readOnly)
|
||||
case cloudprovider.CLOUD_CAPABILITY_KAFKA:
|
||||
appendBrand(&capa.KafkaBrands, &capa.DisabledKafkaBrands, &capa.ReadOnlyKafkaBrands, &capa.ReadOnlyDisabledKafkaBrands, brand, capability, enabled, readOnly)
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1189,7 +1189,7 @@ func (acnt *SCloudaccount) importSubAccount(ctx context.Context, userCred mcclie
|
||||
}
|
||||
provider.markProviderConnected(ctx, userCred, subAccount.HealthStatus)
|
||||
provider.updateName(ctx, userCred, subAccount.Name, subAccount.Desc)
|
||||
if provider.ExternalId != subAccount.Id {
|
||||
if len(provider.ExternalId) == 0 || provider.ExternalId != subAccount.Id {
|
||||
_, err := db.Update(provider, func() error {
|
||||
provider.ExternalId = subAccount.Id
|
||||
return nil
|
||||
|
||||
@@ -23,7 +23,9 @@ import (
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/util/yunionmeta"
|
||||
)
|
||||
|
||||
@@ -151,6 +153,7 @@ func (self *SCloudimage) syncWithImage(ctx context.Context, userCred mcclient.To
|
||||
|
||||
skuUrl := region.getMetaUrl(meta.ImageBase, image.GetGlobalId())
|
||||
|
||||
s := auth.GetAdminSession(ctx, options.Options.Region)
|
||||
obj, err := db.FetchByExternalId(CachedimageManager, image.GetGlobalId())
|
||||
if err != nil {
|
||||
if errors.Cause(err) != sql.ErrNoRows {
|
||||
@@ -166,7 +169,7 @@ func (self *SCloudimage) syncWithImage(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
|
||||
cachedImage.IsPublic = true
|
||||
cachedImage.ProjectId = "system"
|
||||
cachedImage.ProjectId = s.GetProjectId()
|
||||
err = CachedimageManager.TableSpec().Insert(ctx, cachedImage)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Insert cachedimage")
|
||||
@@ -174,18 +177,23 @@ func (self *SCloudimage) syncWithImage(ctx context.Context, userCred mcclient.To
|
||||
return nil
|
||||
}
|
||||
cachedImage := obj.(*SCachedimage)
|
||||
if gotypes.IsNil(cachedImage.Info) {
|
||||
err = meta.Get(skuUrl, &image)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Get")
|
||||
}
|
||||
_, err := db.Update(cachedImage, func() error {
|
||||
_, err = db.Update(cachedImage, func() error {
|
||||
if gotypes.IsNil(cachedImage.Info) {
|
||||
err = meta.Get(skuUrl, &image)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Get")
|
||||
}
|
||||
cachedImage.Info = image.Info
|
||||
cachedImage.Size = image.Size
|
||||
cachedImage.UEFI = image.UEFI
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
if cachedImage.ProjectId == "system" {
|
||||
cachedImage.ProjectId = s.GetProjectId()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Update cachedimage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/yunionmeta"
|
||||
)
|
||||
@@ -709,6 +710,7 @@ func (manager *SCloudregionManager) InitializeData() error {
|
||||
defRegion.Description = "Default Region"
|
||||
defRegion.Status = api.CLOUD_REGION_STATUS_INSERVER
|
||||
defRegion.Provider = api.CLOUD_PROVIDER_ONECLOUD
|
||||
defRegion.SetModelManager(manager, &defRegion)
|
||||
err := manager.TableSpec().Insert(context.TODO(), &defRegion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "insert default region")
|
||||
@@ -1264,7 +1266,8 @@ func (self *SCloudregion) newCloudimage(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
|
||||
image.IsPublic = true
|
||||
image.ProjectId = "system"
|
||||
s := auth.GetAdminSession(ctx, options.Options.Region)
|
||||
image.ProjectId = s.GetProjectId()
|
||||
err = CachedimageManager.TableSpec().Insert(ctx, image)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Insert cachedimage")
|
||||
|
||||
@@ -1100,6 +1100,12 @@ func syncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, syncRes
|
||||
return
|
||||
}
|
||||
|
||||
// 快速同步可能会导致guest被删除,所以需要重新获取
|
||||
guest := GuestManager.FetchGuestById(syncVMPairs[i].Local.Id)
|
||||
if guest == nil || guest.Deleted || guest.PendingDeleted {
|
||||
return
|
||||
}
|
||||
|
||||
SyncVMPeripherals(ctx, userCred, syncVMPairs[i].Local, syncVMPairs[i].Remote, localHost, provider, driver)
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
@@ -465,6 +466,9 @@ func (self *SDBInstanceBackup) SyncWithCloudDBInstanceBackup(
|
||||
if dbinstanceId := extBackup.GetDBInstanceId(); len(dbinstanceId) > 0 {
|
||||
//有可能云上删除了实例,未删除备份
|
||||
_instance, err := db.FetchByExternalIdAndManagerId(DBInstanceManager, dbinstanceId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
if len(self.CloudregionId) > 0 {
|
||||
q = q.Equals("cloudregion_id", self.CloudregionId)
|
||||
}
|
||||
return q.Equals("manager_id", provider.Id)
|
||||
})
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -515,6 +519,9 @@ func (manager *SDBInstanceBackupManager) newFromCloudDBInstanceBackup(
|
||||
|
||||
if dbinstanceId := extBackup.GetDBInstanceId(); len(dbinstanceId) > 0 {
|
||||
_dbinstance, err := db.FetchByExternalIdAndManagerId(DBInstanceManager, dbinstanceId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
if !gotypes.IsNil(region) {
|
||||
q = q.Equals("cloudregion_id", region.Id)
|
||||
}
|
||||
return q.Equals("manager_id", provider.Id)
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -403,9 +403,10 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred
|
||||
}
|
||||
}
|
||||
|
||||
tm := time.Time{}
|
||||
input.BillingCycle = billingCycle.String()
|
||||
input.ExpiredAt = billingCycle.EndAt(tm)
|
||||
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
|
||||
input.ReleaseAt = billingCycle.EndAt(time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range map[string]string{
|
||||
@@ -1131,33 +1132,6 @@ func (self *SDBInstance) StartDBInstanceRenewTask(ctx context.Context, userCred
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDBInstance) SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if self.BillingType == "" {
|
||||
self.BillingType = billingType
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
self.ExpiredAt = *expireAt
|
||||
} else {
|
||||
self.BillingCycle = bc.String()
|
||||
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Update error %s", err)
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDBInstance) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
|
||||
desc := self.SVirtualResourceBase.GetShortDesc(ctx)
|
||||
region, _ := self.GetRegion()
|
||||
@@ -1720,10 +1694,6 @@ func (self *SDBInstance) SyncWithCloudDBInstance(ctx context.Context, userCred m
|
||||
self.CreatedAt = createdAt
|
||||
}
|
||||
|
||||
if expiredAt := ext.GetExpiredAt(); !expiredAt.IsZero() {
|
||||
self.ExpiredAt = expiredAt
|
||||
}
|
||||
|
||||
if len(self.VpcId) == 0 {
|
||||
if vpcId := ext.GetIVpcId(); len(vpcId) > 0 {
|
||||
vpc, err := db.FetchByExternalIdAndManagerId(VpcManager, vpcId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
@@ -1749,19 +1719,13 @@ func (self *SDBInstance) SyncWithCloudDBInstance(ctx context.Context, userCred m
|
||||
}
|
||||
}
|
||||
|
||||
factory, err := provider.GetProviderFactory()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SyncWithCloudDBInstance.GetProviderFactory")
|
||||
}
|
||||
|
||||
if factory.IsSupportPrepaidResources() && !ext.GetExpiredAt().IsZero() {
|
||||
self.BillingType = ext.GetBillingType()
|
||||
if expired := ext.GetExpiredAt(); !expired.IsZero() {
|
||||
self.ExpiredAt = expired
|
||||
}
|
||||
self.BillingType = ext.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
self.AutoRenew = ext.IsAutoRenew()
|
||||
self.ExpiredAt = ext.GetExpiredAt()
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1839,23 +1803,19 @@ func (manager *SDBInstanceManager) newFromCloudDBInstance(ctx context.Context, u
|
||||
instance.CreatedAt = createdAt
|
||||
}
|
||||
|
||||
factory, err := provider.GetProviderFactory()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newFromCloudDBInstance.GetProviderFactory")
|
||||
}
|
||||
|
||||
if factory.IsSupportPrepaidResources() {
|
||||
instance.BillingType = extInstance.GetBillingType()
|
||||
if expired := extInstance.GetExpiredAt(); !expired.IsZero() {
|
||||
instance.ExpiredAt = expired
|
||||
}
|
||||
instance.BillingType = extInstance.GetBillingType()
|
||||
instance.AutoRenew = false
|
||||
instance.ExpiredAt = time.Time{}
|
||||
if instance.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
instance.AutoRenew = extInstance.IsAutoRenew()
|
||||
instance.ExpiredAt = extInstance.GetExpiredAt()
|
||||
}
|
||||
|
||||
err = func() error {
|
||||
err := func() error {
|
||||
lockman.LockRawObject(ctx, manager.Keyword(), "name")
|
||||
defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "name")
|
||||
|
||||
var err error
|
||||
instance.Name, err = db.GenerateName(ctx, manager, ownerId, extInstance.GetName())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.GenerateName")
|
||||
@@ -2061,41 +2021,27 @@ func (self *SDBInstance) PerformPostpaidExpire(ctx context.Context, userCred mcc
|
||||
return nil, httperrors.NewBadRequestError("dbinstance billing type is %s", self.BillingType)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
releaseAt, err := input.GetReleaseAt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SDBInstance) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if err := self.CancelExpireTime(ctx, userCred); err != nil {
|
||||
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SDBInstance) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return httperrors.NewBadRequestError("dbinstance billing type %s not support cancel expire", self.BillingType)
|
||||
}
|
||||
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
|
||||
DBInstanceManager.TableSpec().Name(),
|
||||
), self.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "dbinstance cancel expire time")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, "dbinstance cancel expire time", userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDBInstance) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DBInstanceRemoteUpdateInput) (jsonutils.JSONObject, error) {
|
||||
err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "")
|
||||
if err != nil {
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/pinyinutils"
|
||||
"yunion.io/x/pkg/util/rbacscope"
|
||||
@@ -207,6 +206,15 @@ func (manager *SDiskManager) ListItemFilter(
|
||||
}
|
||||
}
|
||||
|
||||
if query.BindingSnapshotpolicy != nil {
|
||||
spjsq := SnapshotPolicyDiskManager.Query("disk_id").SubQuery()
|
||||
if *query.BindingSnapshotpolicy {
|
||||
q = q.In("id", spjsq)
|
||||
} else {
|
||||
q = q.NotIn("id", spjsq)
|
||||
}
|
||||
}
|
||||
|
||||
guestId := query.ServerId
|
||||
if len(guestId) > 0 {
|
||||
server, err := validators.ValidateModel(ctx, userCred, GuestManager, &guestId)
|
||||
@@ -719,12 +727,28 @@ func getDiskResourceRequirements(ctx context.Context, userCred mcclient.TokenCre
|
||||
return req
|
||||
}
|
||||
|
||||
/*func (manager *SDiskManager) convertToBatchCreateData(data jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
diskConfig, _ := data.Get("disk")
|
||||
newData := data.(*jsonutils.JSONDict).CopyExcludes("disk")
|
||||
newData.Add(diskConfig, "disk.0")
|
||||
return newData
|
||||
}*/
|
||||
func (disk *SDisk) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
if len(disk.ExternalId) == 0 || options.Options.KeepTagLocalization {
|
||||
return
|
||||
}
|
||||
err := disk.StartRemoteUpdateTask(ctx, userCred, true, "")
|
||||
if err != nil {
|
||||
log.Errorf("StartRemoteUpdateTask fail: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (disk *SDisk) StartRemoteUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, replaceTags bool, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
if replaceTags {
|
||||
data.Add(jsonutils.JSONTrue, "replace_tags")
|
||||
}
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DiskRemoteUpdateTask", disk, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Start DiskRemoteUpdateTask")
|
||||
}
|
||||
disk.SetStatus(ctx, userCred, apis.STATUS_UPDATE_TAGS, "StartRemoteUpdateTask")
|
||||
return task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (disk *SDisk) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
disk.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
@@ -975,6 +999,40 @@ func (self *SDisk) PerformMigrate(ctx context.Context, userCred mcclient.TokenCr
|
||||
return nil, task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SDisk) PerformChangeStorageType(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.DiskChagneStorageTypeInput) (jsonutils.JSONObject, error) {
|
||||
if len(input.StorageType) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("storage_type")
|
||||
}
|
||||
storage, err := self.GetStorage()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetStorage")
|
||||
}
|
||||
if storage.StorageType == input.StorageType {
|
||||
return nil, httperrors.NewInputParameterError("Storage type is already %s", input.StorageType)
|
||||
}
|
||||
storages := []SStorage{}
|
||||
q := StorageManager.Query().Equals("zone_id", storage.ZoneId).Equals("storage_type", input.StorageType).IsTrue("enabled").Equals("status", api.STORAGE_ONLINE).Equals("manager_id", storage.ManagerId)
|
||||
err = q.All(&storages)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CountWithError")
|
||||
}
|
||||
if len(storages) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("no available storage type %s to change", input.StorageType)
|
||||
}
|
||||
if len(storages) > 1 {
|
||||
return nil, httperrors.NewInputParameterError("duplicate storage type %s found", input.StorageType)
|
||||
}
|
||||
|
||||
self.SetStatus(ctx, userCred, api.DISK_MIGRATING, "")
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("storage_id", jsonutils.NewString(storages[0].Id))
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "DiskChangeStorageTypeTask", self, userCred, params, "", "", nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return nil, task.ScheduleRun(nil)
|
||||
}
|
||||
|
||||
func (self *SDisk) GetSchedMigrateParams(targetStorageId string) (*schedapi.ScheduleInput, error) {
|
||||
diskConfig := self.ToDiskConfig()
|
||||
diskConfig.Medium = ""
|
||||
@@ -1757,13 +1815,13 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
|
||||
if provider.GetFactory().IsSupportPrepaidResources() && !recycle {
|
||||
if billintType := extDisk.GetBillingType(); len(billintType) > 0 {
|
||||
self.BillingType = extDisk.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
self.ExpiredAt = extDisk.GetExpiredAt()
|
||||
self.AutoRenew = extDisk.IsAutoRenew()
|
||||
}
|
||||
}
|
||||
if expiredAt := extDisk.GetExpiredAt(); !expiredAt.IsZero() {
|
||||
self.ExpiredAt = extDisk.GetExpiredAt()
|
||||
}
|
||||
}
|
||||
|
||||
if createdAt := extDisk.GetCreatedAt(); !createdAt.IsZero() {
|
||||
@@ -2324,7 +2382,11 @@ func (self *SDisk) PerformSyncstatus(ctx context.Context, userCred mcclient.Toke
|
||||
return nil, httperrors.NewBadRequestError("Disk has %d task active, can't sync status", count)
|
||||
}
|
||||
|
||||
return nil, StartResourceSyncStatusTask(ctx, userCred, self, "DiskSyncstatusTask", "")
|
||||
return nil, self.StartSyncstatus(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (disk *SDisk) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
return StartResourceSyncStatusTask(ctx, userCred, disk, "DiskSyncstatusTask", parentTaskId)
|
||||
}
|
||||
|
||||
func (self *SDisk) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
@@ -2408,6 +2470,7 @@ func (manager *SDiskManager) FetchCustomizeColumns(
|
||||
guestSQ.Field("id"),
|
||||
guestSQ.Field("name"),
|
||||
guestSQ.Field("status"),
|
||||
guestSQ.Field("billing_type"),
|
||||
gds.Field("disk_id"),
|
||||
gds.Field("index"),
|
||||
gds.Field("driver"),
|
||||
@@ -2424,11 +2487,12 @@ func (manager *SDiskManager) FetchCustomizeColumns(
|
||||
Status string
|
||||
DiskId string
|
||||
|
||||
Index int
|
||||
Driver string
|
||||
CacheMode string
|
||||
Iops int
|
||||
Bps int
|
||||
Index int
|
||||
Driver string
|
||||
CacheMode string
|
||||
Iops int
|
||||
Bps int
|
||||
BillingType string
|
||||
}{}
|
||||
err := q.All(&guestInfo)
|
||||
if err != nil {
|
||||
@@ -2447,11 +2511,12 @@ func (manager *SDiskManager) FetchCustomizeColumns(
|
||||
Name: guest.Name,
|
||||
Status: guest.Status,
|
||||
|
||||
Index: guest.Index,
|
||||
Driver: guest.Driver,
|
||||
CacheMode: guest.CacheMode,
|
||||
Iops: guest.Iops,
|
||||
Bps: guest.Bps,
|
||||
Index: guest.Index,
|
||||
Driver: guest.Driver,
|
||||
CacheMode: guest.CacheMode,
|
||||
Iops: guest.Iops,
|
||||
Bps: guest.Bps,
|
||||
BillingType: guest.BillingType,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2497,17 +2562,19 @@ func (manager *SDiskManager) FetchCustomizeColumns(
|
||||
|
||||
for i := range rows {
|
||||
rows[i].Guests, _ = guests[diskIds[i]]
|
||||
names, status := []string{}, []string{}
|
||||
names, status, billingTypes := []string{}, []string{}, []string{}
|
||||
var iops, bps int
|
||||
for _, guest := range rows[i].Guests {
|
||||
names = append(names, guest.Name)
|
||||
status = append(status, guest.Status)
|
||||
iops = guest.Iops
|
||||
bps = guest.Bps
|
||||
billingTypes = append(billingTypes, guest.BillingType)
|
||||
}
|
||||
rows[i].GuestCount = len(rows[i].Guests)
|
||||
rows[i].Guest = strings.Join(names, ",")
|
||||
rows[i].GuestStatus = strings.Join(status, ",")
|
||||
rows[i].GuestBillingType = strings.Join(billingTypes, ",")
|
||||
|
||||
rows[i].Snapshotpolicies, _ = policies[diskIds[i]]
|
||||
|
||||
@@ -2728,7 +2795,7 @@ func (manager *SDiskManager) GetNeedAutoSnapshotDisks() ([]SSnapshotPolicyDisk,
|
||||
}
|
||||
timePoint := t.Hour()
|
||||
|
||||
policy := SnapshotPolicyManager.Query().Equals("cloudregion_id", api.DEFAULT_REGION_ID)
|
||||
policy := SnapshotPolicyManager.Query().Equals("type", api.SNAPSHOT_POLICY_TYPE_DISK).Equals("cloudregion_id", api.DEFAULT_REGION_ID)
|
||||
policy = policy.Filter(sqlchemy.Contains(policy.Field("repeat_weekdays"), fmt.Sprintf("%d", week)))
|
||||
sq := policy.Filter(
|
||||
sqlchemy.OR(
|
||||
@@ -2921,49 +2988,6 @@ func (self *SDisk) DeleteSnapshots(ctx context.Context, userCred mcclient.TokenC
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if self.BillingType == "" {
|
||||
self.BillingType = billingType
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
self.ExpiredAt = *expireAt
|
||||
} else if bc != nil {
|
||||
self.BillingCycle = bc.String()
|
||||
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SaveRenewInfo.Update")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return fmt.Errorf("billing type %s not support cancel expire", self.BillingType)
|
||||
}
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
|
||||
DiskManager.TableSpec().Name(),
|
||||
), self.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "disk cancel expire time")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, "disk cancel expire time", userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) IsDetachable() bool {
|
||||
storage, _ := self.GetStorage()
|
||||
if storage == nil {
|
||||
|
||||
@@ -241,18 +241,22 @@ func (self *SDnsRecord) RealDelete(ctx context.Context, userCred mcclient.TokenC
|
||||
}
|
||||
|
||||
type sRecordUniqValues struct {
|
||||
DnsZoneId string
|
||||
DnsType string
|
||||
DnsName string
|
||||
DnsValue string
|
||||
DnsZoneId string
|
||||
DnsType string
|
||||
DnsName string
|
||||
DnsValue string
|
||||
PolicyType string
|
||||
PolicyValue string
|
||||
}
|
||||
|
||||
func (self *SDnsRecord) GetUniqValues() jsonutils.JSONObject {
|
||||
return jsonutils.Marshal(sRecordUniqValues{
|
||||
DnsZoneId: self.DnsZoneId,
|
||||
DnsName: self.Name,
|
||||
DnsType: self.DnsType,
|
||||
DnsValue: self.DnsValue,
|
||||
DnsZoneId: self.DnsZoneId,
|
||||
DnsName: self.Name,
|
||||
DnsType: self.DnsType,
|
||||
DnsValue: self.DnsValue,
|
||||
PolicyType: self.PolicyType,
|
||||
PolicyValue: self.PolicyValue,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -277,6 +281,12 @@ func (manager *SDnsRecordManager) FilterByUniqValues(q *sqlchemy.SQuery, values
|
||||
if len(uniq.DnsValue) > 0 {
|
||||
q = q.Equals("dns_value", uniq.DnsValue)
|
||||
}
|
||||
if len(uniq.PolicyType) > 0 {
|
||||
q = q.Equals("policy_type", uniq.PolicyType)
|
||||
}
|
||||
if len(uniq.PolicyValue) > 0 {
|
||||
q = q.Equals("policy_value", uniq.PolicyValue)
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
@@ -440,10 +440,10 @@ func (self *SElasticSearch) SyncWithCloudElasticSearch(ctx context.Context, user
|
||||
self.IsMultiAz = ext.IsMultiAz()
|
||||
|
||||
self.BillingType = ext.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
if expiredAt := ext.GetExpiredAt(); !expiredAt.IsZero() {
|
||||
self.ExpiredAt = expiredAt
|
||||
}
|
||||
self.ExpiredAt = ext.GetExpiredAt()
|
||||
self.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
@@ -586,10 +586,10 @@ func (self *SCloudregion) newFromCloudElasticSearch(ctx context.Context, userCre
|
||||
}
|
||||
|
||||
es.BillingType = ext.GetBillingType()
|
||||
es.ExpiredAt = time.Time{}
|
||||
es.AutoRenew = false
|
||||
if es.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
if expired := ext.GetExpiredAt(); !expired.IsZero() {
|
||||
es.ExpiredAt = expired
|
||||
}
|
||||
es.ExpiredAt = ext.GetExpiredAt()
|
||||
es.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
bc "yunion.io/x/pkg/util/billing"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
@@ -641,16 +640,11 @@ func (self *SElasticcache) SyncWithCloudElasticcache(ctx context.Context, userCr
|
||||
self.Connections = cnns
|
||||
}
|
||||
|
||||
factory, err := provider.GetProviderFactory()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SyncWithCloudElasticcache.GetProviderFactory")
|
||||
}
|
||||
|
||||
if factory.IsSupportPrepaidResources() {
|
||||
self.BillingType = extInstance.GetBillingType()
|
||||
if expired := extInstance.GetExpiredAt(); !expired.IsZero() {
|
||||
self.ExpiredAt = expired
|
||||
}
|
||||
self.BillingType = extInstance.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
self.ExpiredAt = extInstance.GetExpiredAt()
|
||||
self.AutoRenew = extInstance.IsAutoRenew()
|
||||
}
|
||||
|
||||
@@ -760,23 +754,19 @@ func (self *SCloudregion) newFromCloudElasticcache(ctx context.Context, userCred
|
||||
instance.CreatedAt = createdAt
|
||||
}
|
||||
|
||||
factory, err := provider.GetProviderFactory()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newFromCloudElasticcache.GetProviderFactory")
|
||||
}
|
||||
|
||||
if factory.IsSupportPrepaidResources() {
|
||||
instance.BillingType = extInstance.GetBillingType()
|
||||
if expired := extInstance.GetExpiredAt(); !expired.IsZero() {
|
||||
instance.ExpiredAt = expired
|
||||
}
|
||||
instance.BillingType = extInstance.GetBillingType()
|
||||
instance.ExpiredAt = time.Time{}
|
||||
instance.AutoRenew = false
|
||||
if instance.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
instance.ExpiredAt = extInstance.GetExpiredAt()
|
||||
instance.AutoRenew = extInstance.IsAutoRenew()
|
||||
}
|
||||
|
||||
err = func() error {
|
||||
err := func() error {
|
||||
lockman.LockRawObject(ctx, ElasticcacheManager.Keyword(), "name")
|
||||
defer lockman.ReleaseRawObject(ctx, ElasticcacheManager.Keyword(), "name")
|
||||
|
||||
var err error
|
||||
instance.Name, err = db.GenerateName(ctx, ElasticcacheManager, ownerId, extInstance.GetName())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -883,25 +873,15 @@ func (manager *SElasticcacheManager) validateCreateData(ctx context.Context, use
|
||||
}
|
||||
}
|
||||
|
||||
// postpiad billing cycle
|
||||
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
|
||||
if len(input.Duration) > 0 {
|
||||
cycle, err := bc.ParseBillingCycle(input.Duration)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid duration %s", input.Duration)
|
||||
}
|
||||
|
||||
tm := time.Time{}
|
||||
input.BillingCycle = cycle.String()
|
||||
// .Format("2006-01-02 15:04:05")
|
||||
input.ExpiredAt = cycle.EndAt(tm)
|
||||
}
|
||||
} else if input.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
cycle, err := billing.ParseBillingCycle(input.BillingCycle)
|
||||
if len(input.Duration) > 0 {
|
||||
cycle, err := bc.ParseBillingCycle(input.Duration)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid billing_cycle %s", input.BillingCycle)
|
||||
return nil, httperrors.NewInputParameterError("invalid duration %s", input.Duration)
|
||||
}
|
||||
input.BillingCycle = cycle.String()
|
||||
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
|
||||
input.ReleaseAt = cycle.EndAt(time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
// validate password
|
||||
@@ -1569,33 +1549,6 @@ func (manager *SElasticcacheManager) getExpiredPostpaids() []SElasticcache {
|
||||
return ecs
|
||||
}
|
||||
|
||||
func (cache *SElasticcache) SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bcycle *bc.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(cache, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if cache.BillingType == "" {
|
||||
cache.BillingType = billingType
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
cache.ExpiredAt = *expireAt
|
||||
} else if bcycle != nil {
|
||||
cache.BillingCycle = bcycle.String()
|
||||
cache.ExpiredAt = bcycle.EndAt(cache.ExpiredAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Update error %s", err)
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogEvent(cache, db.ACT_RENEW, cache.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cache *SElasticcache) SetDisableDelete(userCred mcclient.TokenCredential, val bool) error {
|
||||
diff, err := db.Update(cache, func() error {
|
||||
if val {
|
||||
@@ -1677,41 +1630,23 @@ func (self *SElasticcache) PerformPostpaidExpire(ctx context.Context, userCred m
|
||||
return nil, httperrors.NewBadRequestError("elasticcache billing type is %s", self.BillingType)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
releaseAt, err := input.GetReleaseAt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
|
||||
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SElasticcache) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if err := self.CancelExpireTime(ctx, userCred); err != nil {
|
||||
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SElasticcache) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return httperrors.NewBadRequestError("elasticcache billing type %s not support cancel expire", self.BillingType)
|
||||
}
|
||||
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
|
||||
ElasticcacheManager.TableSpec().Name(),
|
||||
), self.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "elasticcache cancel expire time")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, "elasticcache cancel expire time", userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SElasticcache) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticcacheRemoteUpdateInput) (jsonutils.JSONObject, error) {
|
||||
err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "")
|
||||
if err != nil {
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -33,6 +34,7 @@ import (
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -593,12 +595,11 @@ func (self *SElasticip) SyncWithCloudEip(ctx context.Context, userCred mcclient.
|
||||
self.ChargeType = chargeType
|
||||
}
|
||||
|
||||
factory, _ := provider.GetProviderFactory()
|
||||
if factory != nil && factory.IsSupportPrepaidResources() {
|
||||
self.BillingType = ext.GetBillingType()
|
||||
if expired := ext.GetExpiredAt(); !expired.IsZero() {
|
||||
self.ExpiredAt = expired
|
||||
}
|
||||
self.BillingType = ext.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
self.ExpiredAt = ext.GetExpiredAt()
|
||||
self.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
@@ -654,6 +655,13 @@ func (manager *SElasticipManager) newFromCloudEip(ctx context.Context, userCred
|
||||
if !extEip.GetCreatedAt().IsZero() {
|
||||
eip.CreatedAt = extEip.GetCreatedAt()
|
||||
}
|
||||
eip.BillingType = extEip.GetBillingType()
|
||||
eip.ExpiredAt = time.Time{}
|
||||
eip.AutoRenew = false
|
||||
if eip.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
eip.ExpiredAt = extEip.GetExpiredAt()
|
||||
eip.AutoRenew = extEip.IsAutoRenew()
|
||||
}
|
||||
if len(eip.ChargeType) == 0 {
|
||||
eip.ChargeType = api.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
}
|
||||
@@ -895,8 +903,9 @@ func (self *SElasticip) AssociateLoadbalancer(ctx context.Context, userCred mccl
|
||||
if len(self.AssociateType) > 0 && len(self.AssociateId) > 0 {
|
||||
if self.AssociateType == api.EIP_ASSOCIATE_TYPE_LOADBALANCER && self.AssociateId == lb.Id {
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("EIP has been associated!!")
|
||||
}
|
||||
if self.GetAssociateResource() != nil {
|
||||
return fmt.Errorf("eip has been associated!!")
|
||||
}
|
||||
}
|
||||
_, err := db.Update(self, func() error {
|
||||
@@ -927,7 +936,9 @@ func (self *SElasticip) AssociateInstance(ctx context.Context, userCred mcclient
|
||||
if self.AssociateType == insType && self.AssociateId == ins.GetId() {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("EIP has been associated!!")
|
||||
if self.GetAssociateResource() != nil {
|
||||
return fmt.Errorf("eip has been associated!!")
|
||||
}
|
||||
}
|
||||
_, err := db.Update(self, func() error {
|
||||
self.AssociateType = insType
|
||||
@@ -957,7 +968,9 @@ func (self *SElasticip) AssociateInstanceGroup(ctx context.Context, userCred mcc
|
||||
if self.AssociateType == insType && self.AssociateId == ins.GetId() {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("EIP has been associated!!")
|
||||
if self.GetAssociateResource() != nil {
|
||||
return fmt.Errorf("eip has been associated!!")
|
||||
}
|
||||
}
|
||||
_, err := db.Update(self, func() error {
|
||||
self.AssociateType = insType
|
||||
|
||||
@@ -175,9 +175,10 @@ func (man *SFileSystemManager) ValidateCreateData(ctx context.Context, userCred
|
||||
return input, httperrors.NewInputParameterError("unsupported duration %s", input.Duration)
|
||||
}
|
||||
}
|
||||
tm := time.Time{}
|
||||
input.BillingCycle = billingCycle.String()
|
||||
input.ExpiredAt = billingCycle.EndAt(tm)
|
||||
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
|
||||
input.ReleaseAt = billingCycle.EndAt(time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
input.StatusInfrasResourceBaseCreateInput, err = man.SStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusInfrasResourceBaseCreateInput)
|
||||
|
||||
@@ -141,15 +141,27 @@ func (self *SGuest) PerformEvent(ctx context.Context, userCred mcclient.TokenCre
|
||||
}
|
||||
if event == "GUEST_PANICKED" {
|
||||
kwargs := jsonutils.NewDict()
|
||||
kwargs.Set("reason", data)
|
||||
kwargs.Set("reason", jsonutils.NewString(event))
|
||||
if data.Contains("screen_dump_info") {
|
||||
screenDumpInfo := api.SGuestScreenDump{}
|
||||
if err := data.Unmarshal(&screenDumpInfo, "screen_dump_info"); err != nil {
|
||||
log.Errorf("failed unmarshal screen_dump_info %s", err)
|
||||
} else {
|
||||
kwargs.Set("screen_dump_name", jsonutils.NewString(screenDumpInfo.S3ObjectName))
|
||||
if _, err := self.SaveGuestScreenDump(ctx, userCred, &screenDumpInfo); err != nil {
|
||||
log.Errorf("SaveGuestScreenDump failed %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db.OpsLog.LogEvent(self, db.ACT_GUEST_PANICKED, data.String(), userCred)
|
||||
logclient.AddSimpleActionLog(self, logclient.ACT_GUEST_PANICKED, data.String(), userCred, true)
|
||||
db.OpsLog.LogEvent(self, db.ACT_GUEST_PANICKED, kwargs.String(), userCred)
|
||||
logclient.AddSimpleActionLog(self, logclient.ACT_GUEST_PANICKED, kwargs.String(), userCred, true)
|
||||
notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
|
||||
Obj: self,
|
||||
Action: notifyclient.ActionServerPanicked,
|
||||
IsFail: true,
|
||||
})
|
||||
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -1660,10 +1672,12 @@ func (self *SGuest) PerformRebuildRoot(
|
||||
}
|
||||
|
||||
// compare os arch
|
||||
if len(self.InstanceType) > 0 {
|
||||
if len(img.Properties["os_arch"]) > 0 && len(self.OsArch) > 0 && !apis.IsSameArch(self.OsArch, img.Properties["os_arch"]) {
|
||||
return nil, httperrors.NewConflictError("root disk image(%s) and guest(%s) OsArch mismatch", img.Properties["os_arch"], self.OsArch)
|
||||
} else if len(self.InstanceType) > 0 {
|
||||
provider := GetDriver(self.Hypervisor).GetProvider()
|
||||
sku, _ := ServerSkuManager.FetchSkuByNameAndProvider(self.InstanceType, provider, true)
|
||||
if sku != nil && len(sku.CpuArch) > 0 && len(img.Properties["os_arch"]) > 0 && !strings.Contains(img.Properties["os_arch"], sku.CpuArch) {
|
||||
if sku != nil && len(sku.CpuArch) > 0 && len(img.Properties["os_arch"]) > 0 && !apis.IsSameArch(img.Properties["os_arch"], sku.CpuArch) {
|
||||
return nil, httperrors.NewConflictError("root disk image(%s) and sku(%s) architecture mismatch", img.Properties["os_arch"], sku.CpuArch)
|
||||
}
|
||||
}
|
||||
@@ -1898,7 +1912,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
lockman.LockObject(ctx, host)
|
||||
defer lockman.ReleaseObject(ctx, host)
|
||||
|
||||
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage, false, false, nil, nil, false)
|
||||
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage, false, options.Options.UseServerTagsForDisk, nil, nil, false)
|
||||
if err != nil {
|
||||
quotas.CancelPendingUsage(ctx, userCred, pendingUsage, pendingUsage, false)
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, err.Error(), userCred, false)
|
||||
@@ -3113,7 +3127,8 @@ func (self *SGuest) DoCancelPendingDelete(ctx context.Context, userCred mcclient
|
||||
}
|
||||
|
||||
if self.BillingType == billing_api.BILLING_TYPE_POSTPAID && !self.ExpiredAt.IsZero() {
|
||||
if err := self.CancelExpireTime(ctx, userCred); err != nil {
|
||||
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -4125,16 +4140,22 @@ func (self *SGuest) PerformCancelExpire(ctx context.Context, userCred mcclient.T
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return nil, httperrors.NewBadRequestError("guest billing type %s not support cancel expire", self.BillingType)
|
||||
}
|
||||
if err := self.GetDriver().CancelExpireTime(ctx, userCred, self); err != nil {
|
||||
|
||||
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
disks, err := self.GetDisks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
if err := disks[i].CancelExpireTime(ctx, userCred); err != nil {
|
||||
return nil, err
|
||||
if disks[i].BillingType == billing_api.BILLING_TYPE_POSTPAID {
|
||||
err := SaveReleaseAt(ctx, &disks[i], userCred, time.Time{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
@@ -4149,16 +4170,15 @@ func (self *SGuest) PerformPostpaidExpire(ctx context.Context, userCred mcclient
|
||||
return nil, httperrors.NewBadRequestError("guest %s unsupport postpaid expire", self.Hypervisor)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
releaseAt, err := input.GetReleaseAt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
|
||||
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_SET_EXPIRED_TIME, input, userCred, true)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -4216,7 +4236,7 @@ func (self *SGuest) SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
err := self.doSaveRenewInfo(ctx, userCred, bc, expireAt, billingType)
|
||||
err := SaveRenewInfo(ctx, userCred, self, bc, expireAt, billingType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -4226,7 +4246,7 @@ func (self *SGuest) SaveRenewInfo(
|
||||
}
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
if disks[i].AutoDelete {
|
||||
err = disks[i].SaveRenewInfo(ctx, userCred, bc, expireAt, billingType)
|
||||
err = SaveRenewInfo(ctx, userCred, &disks[i], bc, expireAt, billingType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -4235,50 +4255,6 @@ func (self *SGuest) SaveRenewInfo(
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) doSaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if self.BillingType == "" {
|
||||
self.BillingType = billingType
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
self.ExpiredAt = *expireAt
|
||||
} else if bc != nil {
|
||||
self.BillingCycle = bc.String()
|
||||
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("UpdateItem error %s", err)
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return fmt.Errorf("billing type %s not support cancel expire", self.BillingType)
|
||||
}
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
|
||||
GuestManager.TableSpec().Name(),
|
||||
), self.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "guest cancel expire time")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, "guest cancel expire time", userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformStreamDisksComplete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
disks, err := self.GetDisks()
|
||||
if err != nil {
|
||||
@@ -5063,6 +5039,7 @@ func (self *SGuest) validateCreateInstanceBackup(
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// 创建主机快照
|
||||
// 1. validate guest status, guest hypervisor
|
||||
// 2. validate every disk manual snapshot count
|
||||
// 3. validate snapshot quota with disk count
|
||||
|
||||
@@ -493,11 +493,12 @@ func fetchGuestIPs(guestIds []string, virtual tristate.TriState) map[string][]st
|
||||
func fetchGuestVips(guestIds []string) map[string][]string {
|
||||
groupguests := GroupguestManager.Query().SubQuery()
|
||||
groupnetworks := GroupnetworkManager.Query().SubQuery()
|
||||
q := groupnetworks.Query(groupnetworks.Field("ip_addr"), groupguests.Field("guest_id"))
|
||||
q := groupnetworks.Query(groupnetworks.Field("ip_addr"), groupnetworks.Field("ip6_addr"), groupguests.Field("guest_id"))
|
||||
q = q.Join(groupguests, sqlchemy.Equals(q.Field("group_id"), groupguests.Field("group_id")))
|
||||
q = q.In("guest_id", guestIds)
|
||||
type sGuestVip struct {
|
||||
IpAddr string
|
||||
Ip6Addr string
|
||||
GuestId string
|
||||
}
|
||||
gvips := make([]sGuestVip, 0)
|
||||
@@ -510,7 +511,12 @@ func fetchGuestVips(guestIds []string) map[string][]string {
|
||||
if _, ok := ret[gvips[i].GuestId]; !ok {
|
||||
ret[gvips[i].GuestId] = make([]string, 0)
|
||||
}
|
||||
ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].IpAddr)
|
||||
if len(gvips[i].IpAddr) > 0 {
|
||||
ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].IpAddr)
|
||||
}
|
||||
if len(gvips[i].Ip6Addr) > 0 {
|
||||
ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].Ip6Addr)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -136,7 +136,9 @@ func (self *SGuestcdrom) GetImage() (*SCachedimage, error) {
|
||||
func (self *SGuestcdrom) GetDetails() string {
|
||||
if len(self.ImageId) > 0 {
|
||||
if self.Size > 0 {
|
||||
return fmt.Sprintf("%s(%s/%dMB)", self.Name, self.ImageId, self.Size)
|
||||
// Size is stored in bytes, convert to MB for display
|
||||
sizeMB := self.Size / 1024 / 1024
|
||||
return fmt.Sprintf("%s(%s/%dMB)", self.Name, self.ImageId, sizeMB)
|
||||
} else {
|
||||
return fmt.Sprintf("%s(inserting)", self.ImageId)
|
||||
}
|
||||
|
||||
@@ -201,7 +201,6 @@ type IGuestDriver interface {
|
||||
GetUserDataType() string
|
||||
GetWindowsUserDataType() string
|
||||
IsWindowsUserDataTypeNeedEncode() bool
|
||||
CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error
|
||||
|
||||
IsSupportCdrom(guest *SGuest) (bool, error)
|
||||
IsSupportFloppy(guest *SGuest) (bool, error)
|
||||
@@ -252,6 +251,7 @@ type IGuestDriver interface {
|
||||
ValidateSetOSInfo(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, input *api.ServerSetOSInfoInput) error
|
||||
ValidateSyncOSInfo(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error
|
||||
RequestStartRescue(ctx context.Context, task taskman.ITask, body jsonutils.JSONObject, host *SHost, guest *SGuest) error
|
||||
RequestGuestScreenDump(ctx context.Context, userCred mcclient.TokenCredential, body jsonutils.JSONObject, host *SHost, guest *SGuest) (jsonutils.JSONObject, error)
|
||||
}
|
||||
|
||||
var guestDrivers map[string]IGuestDriver
|
||||
|
||||
@@ -188,6 +188,8 @@ type SGuest struct {
|
||||
QgaStatus string `width:"36" charset:"ascii" nullable:"false" default:"unknown" list:"user" create:"optional"`
|
||||
// power_states limit in [on, off, unknown]
|
||||
PowerStates string `width:"36" charset:"ascii" nullable:"false" default:"unknown" list:"user" create:"optional"`
|
||||
// 健康状态, 仅开机中火运行中有效, 目前只支持阿里云
|
||||
HealthStatus string `width:"36" charset:"ascii" nullable:"true" default:"ok" list:"user"`
|
||||
// Used for guest rescue
|
||||
RescueMode bool `nullable:"false" default:"false" list:"user" create:"optional"`
|
||||
}
|
||||
@@ -422,12 +424,20 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
}
|
||||
|
||||
if len(query.IpAddrs) > 0 {
|
||||
// 如果只有一个ip地址,则使用正则匹配,否则使用等于匹配
|
||||
cmpFunc := sqlchemy.Equals
|
||||
if len(query.IpAddrs) == 1 {
|
||||
cmpFunc = func(f sqlchemy.IQueryField, v interface{}) sqlchemy.ICondition {
|
||||
return sqlchemy.Regexp(f, v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
grpnets := GroupnetworkManager.Query().SubQuery()
|
||||
vipq := GroupguestManager.Query("guest_id")
|
||||
conditions := []sqlchemy.ICondition{}
|
||||
for _, ipAddr := range query.IpAddrs {
|
||||
conditions = append(conditions, sqlchemy.Regexp(grpnets.Field("ip_addr"), ipAddr))
|
||||
conditions = append(conditions, sqlchemy.Regexp(grpnets.Field("ip6_addr"), ipAddr))
|
||||
conditions = append(conditions, cmpFunc(grpnets.Field("ip_addr"), ipAddr))
|
||||
conditions = append(conditions, cmpFunc(grpnets.Field("ip6_addr"), ipAddr))
|
||||
}
|
||||
vipq = vipq.Join(grpnets, sqlchemy.Equals(grpnets.Field("group_id"), vipq.Field("group_id"))).Filter(
|
||||
sqlchemy.OR(conditions...),
|
||||
@@ -436,7 +446,7 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
grpeips := ElasticipManager.Query().Equals("associate_type", api.EIP_ASSOCIATE_TYPE_INSTANCE_GROUP).SubQuery()
|
||||
conditions = []sqlchemy.ICondition{}
|
||||
for _, ipAddr := range query.IpAddrs {
|
||||
conditions = append(conditions, sqlchemy.Regexp(grpeips.Field("ip_addr"), ipAddr))
|
||||
conditions = append(conditions, cmpFunc(grpeips.Field("ip_addr"), ipAddr))
|
||||
}
|
||||
vipeipq := GroupguestManager.Query("guest_id")
|
||||
vipeipq = vipeipq.Join(grpeips, sqlchemy.Equals(grpeips.Field("associate_id"), vipeipq.Field("group_id"))).Filter(
|
||||
@@ -446,15 +456,15 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
gnQ := GuestnetworkManager.Query("guest_id")
|
||||
conditions = []sqlchemy.ICondition{}
|
||||
for _, ipAddr := range query.IpAddrs {
|
||||
conditions = append(conditions, sqlchemy.Regexp(gnQ.Field("ip_addr"), ipAddr))
|
||||
conditions = append(conditions, sqlchemy.Regexp(gnQ.Field("ip6_addr"), ipAddr))
|
||||
conditions = append(conditions, cmpFunc(gnQ.Field("ip_addr"), ipAddr))
|
||||
conditions = append(conditions, cmpFunc(gnQ.Field("ip6_addr"), ipAddr))
|
||||
}
|
||||
gn := gnQ.Filter(sqlchemy.OR(conditions...))
|
||||
|
||||
guestEipQ := ElasticipManager.Query("associate_id").Equals("associate_type", api.EIP_ASSOCIATE_TYPE_SERVER)
|
||||
conditions = []sqlchemy.ICondition{}
|
||||
for _, ipAddr := range query.IpAddrs {
|
||||
conditions = append(conditions, sqlchemy.Regexp(guestEipQ.Field("ip_addr"), ipAddr))
|
||||
conditions = append(conditions, cmpFunc(guestEipQ.Field("ip_addr"), ipAddr))
|
||||
}
|
||||
guestEip := guestEipQ.Filter(sqlchemy.OR(conditions...))
|
||||
|
||||
@@ -462,7 +472,7 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
conditions = []sqlchemy.ICondition{}
|
||||
for _, ipAddr := range query.IpAddrs {
|
||||
conditions = append(conditions, sqlchemy.AND(
|
||||
sqlchemy.Regexp(metadataQ.Field("value"), ipAddr),
|
||||
cmpFunc(metadataQ.Field("value"), ipAddr),
|
||||
sqlchemy.Equals(metadataQ.Field("key"), "sync_ips"),
|
||||
sqlchemy.Equals(metadataQ.Field("obj_type"), "server"),
|
||||
))
|
||||
@@ -708,6 +718,23 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
q = q.IsNullOrEmpty("host_id")
|
||||
}
|
||||
}
|
||||
if len(query.SnapshotpolicyId) > 0 {
|
||||
sp := SnapshotPolicyResourceManager.Query("resource_id").
|
||||
Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER).
|
||||
Equals("snapshotpolicy_id", query.SnapshotpolicyId).SubQuery()
|
||||
q = q.In("id", sp)
|
||||
}
|
||||
|
||||
if query.BindingSnapshotpolicy != nil {
|
||||
spjsq := SnapshotPolicyResourceManager.Query("resource_id").
|
||||
Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER).
|
||||
SubQuery()
|
||||
if *query.BindingSnapshotpolicy {
|
||||
q = q.In("id", spjsq)
|
||||
} else {
|
||||
q = q.NotIn("id", spjsq)
|
||||
}
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
@@ -1386,9 +1413,13 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
|
||||
var err error
|
||||
input, err = self.GetDriver().ValidateUpdateData(ctx, self, userCred, input)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "GetDriver().ValidateUpdateData")
|
||||
// 避免调度失败的机器修改删除保护时报no rows in result set 错误,导致前端删不掉机器
|
||||
if len(self.HostId) > 0 {
|
||||
drv := self.GetDriver()
|
||||
input, err = drv.ValidateUpdateData(ctx, self, userCred, input)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "GetDriver().ValidateUpdateData")
|
||||
}
|
||||
}
|
||||
|
||||
input.VirtualResourceBaseUpdateInput, err = self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualResourceBaseUpdateInput)
|
||||
@@ -1617,6 +1648,7 @@ func (manager *SGuestManager) validateCreateData(
|
||||
}
|
||||
var imgProperties map[string]string
|
||||
var imgEncryptKeyId string
|
||||
var imageDiskFormat string
|
||||
|
||||
if len(input.Disks) > 0 {
|
||||
diskConfig := input.Disks[0]
|
||||
@@ -1627,6 +1659,7 @@ func (manager *SGuestManager) validateCreateData(
|
||||
input.Disks[0] = diskConfig
|
||||
imgEncryptKeyId = diskConfig.ImageEncryptKeyId
|
||||
imgProperties = diskConfig.ImageProperties
|
||||
imageDiskFormat = imgProperties[imageapi.IMAGE_DISK_FORMAT]
|
||||
if imgProperties[imageapi.IMAGE_DISK_FORMAT] == "iso" {
|
||||
return nil, httperrors.NewInputParameterError("System disk does not support iso image, please consider using cdrom parameter")
|
||||
}
|
||||
@@ -1638,6 +1671,7 @@ func (manager *SGuestManager) validateCreateData(
|
||||
return nil, httperrors.NewInputParameterError("parse cdrom device info error %s", err)
|
||||
}
|
||||
input.Cdrom = image.Id
|
||||
imageDiskFormat = image.DiskFormat
|
||||
if len(imgProperties) == 0 {
|
||||
imgProperties = image.Properties
|
||||
}
|
||||
@@ -1661,28 +1695,43 @@ func (manager *SGuestManager) validateCreateData(
|
||||
input.OsArch = apis.OS_ARCH_AARCH64
|
||||
}
|
||||
|
||||
var imgSupportUEFI *bool
|
||||
if desc, ok := imgProperties[imageapi.IMAGE_UEFI_SUPPORT]; ok {
|
||||
support := desc == "true"
|
||||
imgSupportUEFI = &support
|
||||
}
|
||||
if input.OsArch == apis.OS_ARCH_AARCH64 {
|
||||
// arm image supports UEFI by default
|
||||
support := true
|
||||
imgSupportUEFI = &support
|
||||
}
|
||||
|
||||
switch {
|
||||
case imgSupportUEFI != nil && *imgSupportUEFI:
|
||||
if len(input.Bios) == 0 {
|
||||
input.Bios = "UEFI"
|
||||
} else if input.Bios != "UEFI" {
|
||||
return nil, httperrors.NewInputParameterError("UEFI image requires UEFI boot mode")
|
||||
if imageDiskFormat != "iso" {
|
||||
var imgSupportUEFI *bool
|
||||
var imgSupportBIOS *bool
|
||||
if desc, ok := imgProperties[imageapi.IMAGE_UEFI_SUPPORT]; ok {
|
||||
support := desc == "true"
|
||||
imgSupportUEFI = &support
|
||||
}
|
||||
default:
|
||||
// not UEFI image
|
||||
if input.Bios == "UEFI" && len(imgProperties) != 0 {
|
||||
return nil, httperrors.NewInputParameterError("UEFI boot mode requires UEFI image")
|
||||
if biosDesc, ok := imgProperties[imageapi.IMAGE_BIOS_SUPPORT]; ok {
|
||||
supportBIOS := biosDesc == "true"
|
||||
imgSupportBIOS = &supportBIOS
|
||||
}
|
||||
// uefi is not support set default support bios
|
||||
if imgSupportUEFI == nil || !*imgSupportUEFI {
|
||||
supportBIOS := true
|
||||
imgSupportBIOS = &supportBIOS
|
||||
}
|
||||
|
||||
if input.OsArch == apis.OS_ARCH_AARCH64 {
|
||||
// arm image supports UEFI by default
|
||||
support := true
|
||||
imgSupportUEFI = &support
|
||||
}
|
||||
switch input.Bios {
|
||||
case "UEFI":
|
||||
if imgSupportUEFI == nil || !*imgSupportUEFI {
|
||||
return nil, httperrors.NewInputParameterError("UEFI boot mode requires UEFI image")
|
||||
}
|
||||
case "BIOS":
|
||||
if imgSupportBIOS == nil || !*imgSupportBIOS {
|
||||
return nil, httperrors.NewInputParameterError("BIOS boot mode requires BIOS image")
|
||||
}
|
||||
default:
|
||||
if imgSupportUEFI != nil && *imgSupportUEFI {
|
||||
input.Bios = "UEFI"
|
||||
} else {
|
||||
input.Bios = "BIOS"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1885,10 +1934,6 @@ func (manager *SGuestManager) validateCreateData(
|
||||
}
|
||||
|
||||
if len(input.Duration) > 0 {
|
||||
/*if !userCred.IsAllow(rbacutils.ScopeSystem, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionPerform, "renew") {
|
||||
return nil, httperrors.NewForbiddenError("only admin can create prepaid resource")
|
||||
}*/
|
||||
|
||||
if input.ResourceType == api.HostResourceTypePrepaidRecycle {
|
||||
return nil, httperrors.NewConflictError("cannot create prepaid server on prepaid resource type")
|
||||
}
|
||||
@@ -1912,10 +1957,10 @@ func (manager *SGuestManager) validateCreateData(
|
||||
input.BillingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
input.BillingCycle = billingCycle.String()
|
||||
// expired_at will be set later by callback
|
||||
// data.Add(jsonutils.NewTimeString(billingCycle.EndAt(time.Time{})), "expired_at")
|
||||
|
||||
input.Duration = billingCycle.String()
|
||||
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
|
||||
input.ReleaseAt = billingCycle.EndAt(time.Now())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2780,9 +2825,11 @@ func (self *SGuest) GetRealIPs() []string {
|
||||
|
||||
func (self *SGuest) IsExitOnly() bool {
|
||||
for _, ip := range self.GetRealIPs() {
|
||||
addr, _ := netutils.NewIPV4Addr(ip)
|
||||
if !netutils.IsExitAddress(addr) {
|
||||
return false
|
||||
if regutils.MatchIP4Addr(ip) {
|
||||
addr, _ := netutils.NewIPV4Addr(ip)
|
||||
if !netutils.IsExitAddress(addr) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -2797,7 +2844,12 @@ func (self *SGuest) getVirtualIPs() []string {
|
||||
continue
|
||||
}
|
||||
for _, groupnetwork := range groupnets {
|
||||
ips = append(ips, groupnetwork.IpAddr)
|
||||
if len(groupnetwork.IpAddr) > 0 {
|
||||
ips = append(ips, groupnetwork.IpAddr)
|
||||
}
|
||||
if len(groupnetwork.Ip6Addr) > 0 {
|
||||
ips = append(ips, groupnetwork.Ip6Addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips
|
||||
@@ -2806,13 +2858,15 @@ func (self *SGuest) getVirtualIPs() []string {
|
||||
func (self *SGuest) GetPrivateIPs() []string {
|
||||
ips := self.GetRealIPs()
|
||||
for i := len(ips) - 1; i >= 0; i-- {
|
||||
ipAddr, err := netutils.NewIPV4Addr(ips[i])
|
||||
if err != nil {
|
||||
log.Errorf("guest %s(%s) has bad ipv4 address (%s): %v", self.Name, self.Id, ips[i], err)
|
||||
continue
|
||||
}
|
||||
if !netutils.IsPrivate(ipAddr) {
|
||||
ips = append(ips[:i], ips[i+1:]...)
|
||||
if regutils.MatchIP4Addr(ips[i]) {
|
||||
ipAddr, err := netutils.NewIPV4Addr(ips[i])
|
||||
if err != nil {
|
||||
log.Errorf("guest %s(%s) has bad ipv4 address (%s): %v", self.Name, self.Id, ips[i], err)
|
||||
continue
|
||||
}
|
||||
if !netutils.IsPrivate(ipAddr) {
|
||||
ips = append(ips[:i], ips[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips
|
||||
@@ -3106,6 +3160,9 @@ func (g *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.TokenCre
|
||||
|
||||
if !g.IsFailureStatus() && syncStatus {
|
||||
g.Status = extVM.GetStatus()
|
||||
if g.Status == api.VM_RUNNING || g.Status == api.VM_STARTING {
|
||||
g.HealthStatus = extVM.GetHealthStatus()
|
||||
}
|
||||
g.PowerStates = extVM.GetPowerStates()
|
||||
g.InferPowerStates()
|
||||
}
|
||||
@@ -3154,15 +3211,15 @@ func (g *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.TokenCre
|
||||
if len(extVM.GetDescription()) > 0 {
|
||||
g.Description = extVM.GetDescription()
|
||||
}
|
||||
g.IsEmulated = extVM.IsEmulated()
|
||||
|
||||
if provider.GetFactory().IsSupportPrepaidResources() && !recycle {
|
||||
g.BillingType = extVM.GetBillingType()
|
||||
g.BillingType = extVM.GetBillingType()
|
||||
g.ExpiredAt = time.Time{}
|
||||
g.AutoRenew = false
|
||||
if g.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
g.ExpiredAt = extVM.GetExpiredAt()
|
||||
if g.GetDriver().IsSupportSetAutoRenew() {
|
||||
g.AutoRenew = extVM.IsAutoRenew()
|
||||
}
|
||||
g.AutoRenew = extVM.IsAutoRenew()
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -3229,14 +3286,12 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
|
||||
|
||||
guest.IsEmulated = extVM.IsEmulated()
|
||||
|
||||
if provider.GetFactory().IsSupportPrepaidResources() {
|
||||
guest.BillingType = extVM.GetBillingType()
|
||||
if expired := extVM.GetExpiredAt(); !expired.IsZero() {
|
||||
guest.ExpiredAt = expired
|
||||
}
|
||||
if guest.GetDriver().IsSupportSetAutoRenew() {
|
||||
guest.AutoRenew = extVM.IsAutoRenew()
|
||||
}
|
||||
guest.BillingType = extVM.GetBillingType()
|
||||
guest.ExpiredAt = time.Time{}
|
||||
guest.AutoRenew = false
|
||||
if guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
guest.ExpiredAt = extVM.GetExpiredAt()
|
||||
guest.AutoRenew = extVM.IsAutoRenew()
|
||||
}
|
||||
|
||||
if createdAt := extVM.GetCreatedAt(); !createdAt.IsZero() {
|
||||
@@ -3247,18 +3302,6 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
|
||||
|
||||
instanceType := extVM.GetInstanceType()
|
||||
|
||||
/*zoneExtId, err := metaData.GetString("zone_ext_id")
|
||||
if err != nil {
|
||||
log.Errorf("get zone external id fail %s", err)
|
||||
}
|
||||
|
||||
isku, err := ServerSkuManager.FetchByZoneExtId(zoneExtId, instanceType)
|
||||
if err != nil {
|
||||
log.Errorf("get sku zone %s instance type %s fail %s", zoneExtId, instanceType, err)
|
||||
} else {
|
||||
guest.SkuId = isku.GetId()
|
||||
}*/
|
||||
|
||||
if len(instanceType) > 0 {
|
||||
guest.InstanceType = instanceType
|
||||
}
|
||||
@@ -3956,6 +3999,22 @@ func (self *SGuest) SyncVMDisks(
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *SGuest) setSystemDisk() error {
|
||||
sq := GuestdiskManager.Query("disk_id").Equals("guest_id", self.Id).Equals("index", 0).SubQuery()
|
||||
disks := DiskManager.Query().In("id", sq)
|
||||
disk := &SDisk{}
|
||||
disk.SetModelManager(DiskManager, disk)
|
||||
err := disks.First(disk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = db.Update(disk, func() error {
|
||||
disk.DiskType = api.DISK_TYPE_SYS
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SGuest) fixSysDiskIndex() error {
|
||||
disks := DiskManager.Query().SubQuery()
|
||||
sysQ := GuestdiskManager.Query().Equals("guest_id", self.Id)
|
||||
@@ -3965,7 +4024,7 @@ func (self *SGuest) fixSysDiskIndex() error {
|
||||
err := sysQ.First(sysDisk)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil
|
||||
return self.setSystemDisk()
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -4878,6 +4937,7 @@ func (self *SGuest) GetDeployConfigOnHost(ctx context.Context, userCred mcclient
|
||||
keypair := self.getKeypair()
|
||||
if keypair != nil {
|
||||
config.Add(jsonutils.NewString(keypair.PublicKey), "public_key")
|
||||
config.Add(jsonutils.NewString(keypair.Name), "keypair_name")
|
||||
}
|
||||
deletePubKey, _ := params.GetString("delete_public_key")
|
||||
if len(deletePubKey) > 0 {
|
||||
@@ -5614,6 +5674,10 @@ func (self *SGuest) GetKeypairPublicKey() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SGuest) GetKeypair() *SKeypair {
|
||||
return self.getKeypair()
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) GetIpsInProjectWithName(projectId, name string, isExitOnly bool, addrType api.TAddressType) []string {
|
||||
name = strings.TrimSuffix(name, ".")
|
||||
|
||||
|
||||
182
pkg/compute/models/guestscreendump.go
Normal file
182
pkg/compute/models/guestscreendump.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/multicloud/objectstore"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type SGuestScreenDumpManager struct {
|
||||
db.SResourceBaseManager
|
||||
}
|
||||
|
||||
var GuestScreenDumpManager *SGuestScreenDumpManager
|
||||
|
||||
func init() {
|
||||
db.InitManager(func() {
|
||||
GuestScreenDumpManager = &SGuestScreenDumpManager{
|
||||
SResourceBaseManager: db.NewResourceBaseManager(
|
||||
SGuestScreenDump{},
|
||||
"guest_screen_dumps_tbl",
|
||||
"guest_screen_dump",
|
||||
"guest_screen_dumps",
|
||||
),
|
||||
}
|
||||
GuestScreenDumpManager.SetVirtualObject(GuestScreenDumpManager)
|
||||
GuestScreenDumpManager.TableSpec().AddIndex(true, "guest_id")
|
||||
})
|
||||
}
|
||||
|
||||
type SGuestScreenDump struct {
|
||||
db.SResourceBase
|
||||
|
||||
RowId int64 `primary:"true" auto_increment:"true" list:"user"`
|
||||
GuestId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
Name string `width:"64" charset:"ascii" nullable:"true" list:"user"`
|
||||
|
||||
// s3 config
|
||||
S3AccessKey string `width:"64" charset:"ascii" nullable:"true"`
|
||||
S3SecretKey string `width:"64" charset:"ascii" nullable:"true"`
|
||||
S3Endpoint string `width:"64" charset:"ascii" nullable:"true" list:"user"`
|
||||
S3BucketName string `width:"64" charset:"ascii" nullable:"true" list:"user"`
|
||||
S3UseSsl bool `default:"false" list:"user" create:"optional"`
|
||||
}
|
||||
|
||||
func (manager *SGuestScreenDumpManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GuestScreenDumpListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if query.Server != "" {
|
||||
iGuest, err := GuestManager.FetchByIdOrName(ctx, userCred, query.Server)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "fetch guest")
|
||||
}
|
||||
q = q.Equals("guest_id", iGuest.GetId())
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SGuestScreenDump) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, self)
|
||||
}
|
||||
|
||||
func (self *SGuest) SaveGuestScreenDump(ctx context.Context, userCred mcclient.TokenCredential, screenDumpInfo *api.SGuestScreenDump) (*SGuestScreenDump, error) {
|
||||
sd := new(SGuestScreenDump)
|
||||
sd.SetModelManager(GuestScreenDumpManager, sd)
|
||||
sd.GuestId = self.GetId()
|
||||
sd.S3SecretKey = base64.StdEncoding.EncodeToString([]byte(screenDumpInfo.S3SecretKey))
|
||||
sd.S3Endpoint = screenDumpInfo.S3Endpoint
|
||||
sd.S3BucketName = screenDumpInfo.S3BucketName
|
||||
sd.S3AccessKey = base64.StdEncoding.EncodeToString([]byte(screenDumpInfo.S3AccessKey))
|
||||
sd.Name = screenDumpInfo.S3ObjectName
|
||||
|
||||
lockman.LockClass(ctx, GuestScreenDumpManager, self.ProjectId)
|
||||
defer lockman.ReleaseClass(ctx, GuestScreenDumpManager, self.ProjectId)
|
||||
|
||||
err := GuestScreenDumpManager.TableSpec().Insert(ctx, sd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "save guest screen_dump")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_GUEST_SCREEN_DUMP, sd.Name, userCred)
|
||||
logclient.AddSimpleActionLog(self, logclient.ACT_GUEST_SCREEN_DUMP, sd.Name, userCred, true)
|
||||
return sd, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) GetDetailsScreenDumpShow(ctx context.Context, userCred mcclient.TokenCredential, input *api.GetDetailsGuestScreenDumpInput) (*api.GetDetailsGuestScreenDumpOutput, error) {
|
||||
if input.ObjectName == "" {
|
||||
return nil, httperrors.NewMissingParameterError("object_name")
|
||||
}
|
||||
q := GuestScreenDumpManager.Query()
|
||||
q = q.Equals("guest_id", self.Id)
|
||||
q = q.Equals("name", input.ObjectName)
|
||||
|
||||
screenDump := new(SGuestScreenDump)
|
||||
err := q.First(screenDump)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "query screenDump")
|
||||
}
|
||||
|
||||
ak, _ := base64.StdEncoding.DecodeString(screenDump.S3AccessKey)
|
||||
sk, _ := base64.StdEncoding.DecodeString(screenDump.S3SecretKey)
|
||||
|
||||
url := screenDump.S3Endpoint
|
||||
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
||||
prefix := "http://"
|
||||
if screenDump.S3UseSsl {
|
||||
prefix = "https://"
|
||||
}
|
||||
url = prefix + url
|
||||
}
|
||||
cfg := objectstore.NewObjectStoreClientConfig(url, string(ak), string(sk))
|
||||
s3Client, err := objectstore.NewObjectStoreClient(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new minio client")
|
||||
}
|
||||
bucket, err := s3Client.GetIBucketByName(screenDump.S3BucketName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get bucket %s", screenDump.S3BucketName)
|
||||
}
|
||||
irc, err := bucket.GetObject(ctx, screenDump.Name, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get object %s", screenDump.Name)
|
||||
}
|
||||
defer irc.Close()
|
||||
obj, err := io.ReadAll(irc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "read object %s", screenDump.Name)
|
||||
}
|
||||
ret := new(api.GetDetailsGuestScreenDumpOutput)
|
||||
|
||||
contentType := http.DetectContentType(obj)
|
||||
base64Encoded := base64.StdEncoding.EncodeToString(obj)
|
||||
ret.ScreenDump = fmt.Sprintf("data:%s;base64,%s", contentType, base64Encoded)
|
||||
ret.ScreenDump = base64.StdEncoding.EncodeToString(obj)
|
||||
ret.GuestId = self.Id
|
||||
ret.Name = screenDump.Name
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformScreenDump(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if self.PowerStates != api.VM_POWER_STATES_ON {
|
||||
return nil, httperrors.NewBadRequestError("can't use qga in vm status: %s", self.Status)
|
||||
}
|
||||
|
||||
host, _ := self.GetHost()
|
||||
res, err := self.GetDriver().RequestGuestScreenDump(ctx, userCred, nil, host, self)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
screenDumpInfo := api.SGuestScreenDump{}
|
||||
if err := res.Unmarshal(&screenDumpInfo); err != nil {
|
||||
return nil, errors.Wrap(err, "unmarshal screen dump info")
|
||||
}
|
||||
if _, err := self.SaveGuestScreenDump(ctx, userCred, &screenDumpInfo); err != nil {
|
||||
return nil, errors.Wrap(err, "failed save ")
|
||||
}
|
||||
input := &api.GetDetailsGuestScreenDumpInput{
|
||||
ObjectName: screenDumpInfo.S3ObjectName,
|
||||
}
|
||||
ret, err := self.GetDetailsScreenDumpShow(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonutils.Marshal(ret), err
|
||||
}
|
||||
@@ -41,7 +41,7 @@ type IHostDriver interface {
|
||||
// create disk
|
||||
RequestAllocateDiskOnStorage(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, storage *SStorage, disk *SDisk, task taskman.ITask, input api.DiskAllocateInput) error
|
||||
RequestRebuildDiskOnStorage(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, task taskman.ITask, input api.DiskAllocateInput) error
|
||||
|
||||
RequestRemoteUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, disk *SDisk, replaceTags bool) error
|
||||
// delete disk
|
||||
RequestDeallocateDiskOnHost(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, cleanSnapshots bool, task taskman.ITask) error
|
||||
RequestDeallocateBackupDiskOnHost(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, task taskman.ITask) error
|
||||
|
||||
@@ -280,18 +280,24 @@ func (manager *SHostManager) ListItemFilter(
|
||||
}
|
||||
}
|
||||
if len(query.AnyIp) > 0 {
|
||||
cmpFunc := sqlchemy.Equals
|
||||
if len(query.AnyIp) == 1 {
|
||||
cmpFunc = func(f sqlchemy.IQueryField, v interface{}) sqlchemy.ICondition {
|
||||
return sqlchemy.Regexp(f, v.(string))
|
||||
}
|
||||
}
|
||||
hnQ := HostnetworkManager.Query("baremetal_id") //.Contains("ip_addr", query.AnyIp).SubQuery()
|
||||
conditions := []sqlchemy.ICondition{}
|
||||
for _, ip := range query.AnyIp {
|
||||
conditions = append(conditions, sqlchemy.Contains(hnQ.Field("ip_addr"), ip))
|
||||
conditions = append(conditions, cmpFunc(hnQ.Field("ip_addr"), ip))
|
||||
}
|
||||
hn := hnQ.Filter(
|
||||
sqlchemy.OR(conditions...),
|
||||
)
|
||||
conditions = []sqlchemy.ICondition{}
|
||||
for _, ip := range query.AnyIp {
|
||||
conditions = append(conditions, sqlchemy.Contains(q.Field("access_ip"), ip))
|
||||
conditions = append(conditions, sqlchemy.Contains(q.Field("ipmi_ip"), ip))
|
||||
conditions = append(conditions, cmpFunc(q.Field("access_ip"), ip))
|
||||
conditions = append(conditions, cmpFunc(q.Field("ipmi_ip"), ip))
|
||||
}
|
||||
conditions = append(conditions, sqlchemy.In(q.Field("id"), hn))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
@@ -452,8 +458,10 @@ func (manager *SHostManager) ListItemFilter(
|
||||
|
||||
for f, vars := range fieldQueryMap {
|
||||
vars = stringutils2.FilterEmpty(vars)
|
||||
if len(vars) > 0 {
|
||||
if len(vars) > 1 {
|
||||
q = q.In(f, vars)
|
||||
} else if len(vars) == 1 {
|
||||
q = q.Regexp(f, vars[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,6 +739,191 @@ func (manager *SHostManager) OrderByExtraFields(
|
||||
db.OrderByFields(q, []string{query.OrderByStorageUsed}, []sqlchemy.IQueryField{q.Field("storage_used")})
|
||||
}
|
||||
|
||||
if db.NeedOrderQuery([]string{query.OrderByCpuUsage}) {
|
||||
meta := db.Metadata.Query().
|
||||
Equals("obj_type", HostManager.Keyword()).
|
||||
Equals("key", api.HOST_METADATA_CPU_USAGE_PERCENT).SubQuery()
|
||||
metaQ := meta.Query(
|
||||
meta.Field("obj_id"),
|
||||
sqlchemy.CASTFloat(meta.Field("value"), "cpu_usage"),
|
||||
)
|
||||
metaSQ := metaQ.GroupBy(metaQ.Field("obj_id")).SubQuery()
|
||||
|
||||
q = q.LeftJoin(metaSQ, sqlchemy.Equals(q.Field("id"), metaSQ.Field("obj_id")))
|
||||
|
||||
db.OrderByFields(q, []string{query.OrderByCpuUsage}, []sqlchemy.IQueryField{metaSQ.Field("cpu_usage")})
|
||||
}
|
||||
|
||||
if db.NeedOrderQuery([]string{query.OrderByMemUsage}) {
|
||||
meta := db.Metadata.Query().
|
||||
Equals("obj_type", HostManager.Keyword()).
|
||||
Equals("key", api.HOST_METADATA_MEMORY_USED_MB).SubQuery()
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
metaQ := meta.Query(
|
||||
meta.Field("obj_id"),
|
||||
sqlchemy.DIV("mem_usage", sqlchemy.CASTFloat(meta.Field("value"), api.HOST_METADATA_MEMORY_USED_MB), hosts.Field("mem_size")),
|
||||
).LeftJoin(hosts, sqlchemy.Equals(meta.Field("obj_id"), hosts.Field("id")))
|
||||
|
||||
metaSQ := metaQ.GroupBy(metaQ.Field("obj_id")).SubQuery()
|
||||
|
||||
q = q.LeftJoin(metaSQ, sqlchemy.Equals(q.Field("id"), metaSQ.Field("obj_id")))
|
||||
|
||||
db.OrderByFields(q, []string{query.OrderByMemUsage}, []sqlchemy.IQueryField{metaSQ.Field("mem_usage")})
|
||||
}
|
||||
|
||||
if db.NeedOrderQuery([]string{query.OrderByStorageUsage}) {
|
||||
hs := HoststorageManager.Query().SubQuery()
|
||||
storages := StorageManager.Query().IsTrue("enabled").NotEquals("storage_type", api.STORAGE_BAREMETAL).In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
|
||||
host := HostManager.Query().SubQuery()
|
||||
hsSQ := hs.Query(
|
||||
hs.Field("host_id"),
|
||||
sqlchemy.SUM("actual_storage_used", storages.Field("actual_capacity_used")),
|
||||
).LeftJoin(storages, sqlchemy.Equals(hs.Field("storage_id"), storages.Field("id"))).GroupBy(hs.Field("host_id")).SubQuery()
|
||||
|
||||
hsQ := hsSQ.Query(
|
||||
hsSQ.Field("host_id"),
|
||||
sqlchemy.DIV("storage_usage", hsSQ.Field("actual_storage_used"), host.Field("storage_size")),
|
||||
).LeftJoin(host, sqlchemy.Equals(hsSQ.Field("host_id"), host.Field("id")))
|
||||
|
||||
hsSSQ := hsQ.GroupBy(hsQ.Field("host_id")).SubQuery()
|
||||
|
||||
q = q.LeftJoin(hsSSQ, sqlchemy.Equals(q.Field("id"), hsSSQ.Field("host_id")))
|
||||
|
||||
db.OrderByFields(q, []string{query.OrderByStorageUsage}, []sqlchemy.IQueryField{hsSSQ.Field("storage_usage")})
|
||||
}
|
||||
|
||||
if db.NeedOrderQuery([]string{query.OrderByVirtualMemUsage}) {
|
||||
guests := GuestManager.Query()
|
||||
if options.Options.IgnoreNonrunningGuests {
|
||||
guests = guests.Equals("status", api.VM_RUNNING)
|
||||
}
|
||||
|
||||
sq := guests.SubQuery()
|
||||
guestSQ := sq.Query(
|
||||
sq.Field("host_id"),
|
||||
sqlchemy.SUM("mem_commit", sq.Field("vmem_size")),
|
||||
).GroupBy(sq.Field("host_id")).SubQuery()
|
||||
|
||||
host := HostManager.Query().SubQuery()
|
||||
|
||||
vq := guestSQ.Query(
|
||||
guestSQ.Field("host_id"),
|
||||
guestSQ.Field("mem_commit"),
|
||||
sqlchemy.NewFunction(
|
||||
sqlchemy.NewCase().When(
|
||||
sqlchemy.GT(host.Field("mem_cmtbound"), 0),
|
||||
host.Field("mem_cmtbound"),
|
||||
).Else(sqlchemy.NewConstField(options.Options.DefaultMemoryOvercommitBound)),
|
||||
"mem_cmtbound",
|
||||
true,
|
||||
),
|
||||
sqlchemy.SUB("host_mem_size", host.Field("mem_size"), host.Field("mem_reserved")),
|
||||
).LeftJoin(host, sqlchemy.Equals(guestSQ.Field("host_id"), host.Field("id"))).GroupBy(guestSQ.Field("host_id")).SubQuery()
|
||||
|
||||
vsq := vq.Query(
|
||||
vq.Field("host_id"),
|
||||
sqlchemy.DIV("virtual_mem_usage", vq.Field("mem_commit"), sqlchemy.DIV("cmt_mem_size", vq.Field("mem_cmtbound"), vq.Field("host_mem_size"))),
|
||||
)
|
||||
|
||||
vqq := vsq.GroupBy(vsq.Field("host_id")).SubQuery()
|
||||
|
||||
q = q.LeftJoin(vqq, sqlchemy.Equals(q.Field("id"), vqq.Field("host_id")))
|
||||
|
||||
db.OrderByFields(q, []string{query.OrderByVirtualMemUsage}, []sqlchemy.IQueryField{vqq.Field("virtual_mem_usage")})
|
||||
}
|
||||
|
||||
if db.NeedOrderQuery([]string{query.OrderByVirtualCpuUsage}) {
|
||||
guests := GuestManager.Query()
|
||||
if options.Options.IgnoreNonrunningGuests {
|
||||
guests = guests.Equals("status", api.VM_RUNNING)
|
||||
}
|
||||
|
||||
sq := guests.SubQuery()
|
||||
guestSQ := sq.Query(
|
||||
sq.Field("host_id"),
|
||||
sqlchemy.SUM("cpu_commit", sq.Field("vcpu_count")),
|
||||
).GroupBy(sq.Field("host_id")).SubQuery()
|
||||
|
||||
host := HostManager.Query().SubQuery()
|
||||
|
||||
vq := guestSQ.Query(
|
||||
guestSQ.Field("host_id"),
|
||||
guestSQ.Field("cpu_commit"),
|
||||
sqlchemy.NewFunction(
|
||||
sqlchemy.NewCase().When(
|
||||
sqlchemy.GT(host.Field("cpu_cmtbound"), 0),
|
||||
host.Field("cpu_cmtbound"),
|
||||
).Else(sqlchemy.NewConstField(options.Options.DefaultCPUOvercommitBound)),
|
||||
"cpu_cmtbound",
|
||||
true,
|
||||
),
|
||||
sqlchemy.SUB("host_cpu_size", host.Field("cpu_count"), host.Field("cpu_reserved")),
|
||||
).LeftJoin(host, sqlchemy.Equals(guestSQ.Field("host_id"), host.Field("id"))).GroupBy(guestSQ.Field("host_id")).SubQuery()
|
||||
|
||||
vsq := vq.Query(
|
||||
vq.Field("host_id"),
|
||||
sqlchemy.DIV("virtual_cpu_usage", vq.Field("cpu_commit"), sqlchemy.DIV("cmt_cpu_size", vq.Field("cpu_cmtbound"), vq.Field("host_cpu_size"))),
|
||||
)
|
||||
|
||||
vqq := vsq.GroupBy(vsq.Field("host_id")).SubQuery()
|
||||
|
||||
q = q.LeftJoin(vqq, sqlchemy.Equals(q.Field("id"), vqq.Field("host_id")))
|
||||
|
||||
db.OrderByFields(q, []string{query.OrderByVirtualCpuUsage}, []sqlchemy.IQueryField{vqq.Field("virtual_cpu_usage")})
|
||||
}
|
||||
|
||||
if db.NeedOrderQuery([]string{query.OrderByVirtualStorageUsage}) {
|
||||
hoststorages := HoststorageManager.Query().SubQuery()
|
||||
storageQ := StorageManager.Query().IsTrue("enabled").NotEquals("storage_type", api.STORAGE_BAREMETAL).In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
|
||||
|
||||
diskReadySQ := DiskManager.Query().Equals("status", api.DISK_READY).SubQuery()
|
||||
diskReadyQ := diskReadySQ.Query(sqlchemy.SUM("sum", diskReadySQ.Field("disk_size")).Label("used")).GroupBy(diskReadySQ.Field("storage_id"))
|
||||
readySQ := diskReadyQ.SubQuery()
|
||||
|
||||
storageSQ := storageQ.Query(
|
||||
storageQ.Field("id"),
|
||||
sqlchemy.SUB("storage_capacity", storageQ.Field("capacity"), storageQ.Field("reserved")),
|
||||
hoststorages.Field("host_id"),
|
||||
sqlchemy.NewFunction(
|
||||
sqlchemy.NewCase().When(
|
||||
sqlchemy.GT(storageQ.Field("cmtbound"), 0),
|
||||
storageQ.Field("cmtbound"),
|
||||
).Else(sqlchemy.NewConstField(1)),
|
||||
"cmtbound",
|
||||
true,
|
||||
),
|
||||
readySQ.Field("used"),
|
||||
)
|
||||
|
||||
storageSQ = storageSQ.Join(hoststorages, sqlchemy.Equals(storageSQ.Field("id"), hoststorages.Field("storage_id")))
|
||||
storageSQ = storageSQ.LeftJoin(readySQ, sqlchemy.Equals(readySQ.Field("storage_id"), storageSQ.Field("id")))
|
||||
|
||||
sq := storageSQ.SubQuery()
|
||||
sqMul := sq.Query(
|
||||
sq.Field("host_id"),
|
||||
sq.Field("id"),
|
||||
sq.Field("used"),
|
||||
sqlchemy.MUL("virtual_storage_size", sq.Field("storage_capacity"), sq.Field("cmtbound")),
|
||||
).SubQuery()
|
||||
|
||||
sqSum := sqMul.Query(
|
||||
sqMul.Field("host_id"),
|
||||
sqMul.Field("id"),
|
||||
sqlchemy.SUM("total_used", sqMul.Field("used")),
|
||||
sqlchemy.SUM("total_virtual_storage_szie", sqMul.Field("virtual_storage_size")),
|
||||
).GroupBy(sqMul.Field("host_id")).SubQuery()
|
||||
|
||||
sqDiv := sqSum.Query(
|
||||
sqSum.Field("host_id"),
|
||||
sqlchemy.DIV("virtual_storage_usage", sqSum.Field("total_used"), sqSum.Field("total_virtual_storage_szie")),
|
||||
)
|
||||
|
||||
usageSQ := sqDiv.GroupBy(sqDiv.Field("host_id")).SubQuery()
|
||||
q = q.LeftJoin(usageSQ, sqlchemy.Equals(q.Field("id"), usageSQ.Field("host_id")))
|
||||
|
||||
db.OrderByFields(q, []string{query.OrderByVirtualStorageUsage}, []sqlchemy.IQueryField{usageSQ.Field("virtual_storage_usage")})
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
@@ -4805,7 +4998,7 @@ func (hh *SHost) PerformPing(ctx context.Context, userCred mcclient.TokenCredent
|
||||
}
|
||||
hh.SetMetadata(ctx, "root_partition_used_capacity_mb", input.RootPartitionUsedCapacityMb, userCred)
|
||||
hh.SetMetadata(ctx, "memory_used_mb", input.MemoryUsedMb, userCred)
|
||||
hh.SetMetadata(ctx, "cpu_usage_percent", input.CpuUsagePercent, userCred)
|
||||
hh.SetMetadata(ctx, api.HOST_METADATA_CPU_USAGE_PERCENT, input.CpuUsagePercent, userCred)
|
||||
|
||||
guests, _ := hh.GetGuests()
|
||||
for _, guest := range guests {
|
||||
|
||||
@@ -17,6 +17,8 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -32,6 +34,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
@@ -803,3 +806,189 @@ func (self *SInstanceSnapshot) CustomizeCreate(
|
||||
ownerId = guestObj.(*SGuest).GetOwnerId()
|
||||
return self.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (manager *SInstanceSnapshotManager) GetNeedAutoSnapshotServers() ([]SSnapshotPolicyResource, error) {
|
||||
tz, _ := time.LoadLocation(options.Options.TimeZone)
|
||||
t := time.Now().In(tz)
|
||||
week := t.Weekday()
|
||||
if week == 0 { // sunday is zero
|
||||
week += 7
|
||||
}
|
||||
timePoint := t.Hour()
|
||||
|
||||
policy := SnapshotPolicyManager.Query().Equals("type", api.SNAPSHOT_POLICY_TYPE_SERVER).Equals("cloudregion_id", api.DEFAULT_REGION_ID)
|
||||
policy = policy.Filter(sqlchemy.Contains(policy.Field("repeat_weekdays"), fmt.Sprintf("%d", week)))
|
||||
sq := policy.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.Contains(policy.Field("time_points"), fmt.Sprintf(",%d,", timePoint)),
|
||||
sqlchemy.Startswith(policy.Field("time_points"), fmt.Sprintf("[%d,", timePoint)),
|
||||
sqlchemy.Endswith(policy.Field("time_points"), fmt.Sprintf(",%d]", timePoint)),
|
||||
sqlchemy.Equals(policy.Field("time_points"), fmt.Sprintf("[%d]", timePoint)),
|
||||
),
|
||||
).SubQuery()
|
||||
servers := GuestManager.Query().SubQuery()
|
||||
q := SnapshotPolicyResourceManager.Query().Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER)
|
||||
q = q.Join(sq, sqlchemy.Equals(q.Field("snapshotpolicy_id"), sq.Field("id")))
|
||||
q = q.Join(servers, sqlchemy.Equals(q.Field("resource_id"), servers.Field("id")))
|
||||
ret := []SSnapshotPolicyResource{}
|
||||
err := db.FetchModelObjects(SnapshotPolicyResourceManager, q, &ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (manager *SInstanceSnapshotManager) AutoServerSnapshot(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
servers, err := manager.GetNeedAutoSnapshotServers()
|
||||
if err != nil {
|
||||
log.Errorf("Get auto snapshot servers id failed: %s", err)
|
||||
return
|
||||
}
|
||||
log.Infof("auto snapshot %d servers", len(servers))
|
||||
|
||||
serverMap := map[string]*SGuest{}
|
||||
for i := range servers {
|
||||
server, err := servers[i].GetServer()
|
||||
if err != nil {
|
||||
log.Errorf("get server error: %v", err)
|
||||
continue
|
||||
}
|
||||
serverMap[server.Id] = server
|
||||
}
|
||||
for i := range serverMap {
|
||||
input := api.ServerInstanceSnapshot{}
|
||||
input.GenerateName = fmt.Sprintf("auto-%s-%d", serverMap[i].Name, time.Now().Unix())
|
||||
serverMap[i].PerformInstanceSnapshot(ctx, userCred, jsonutils.NewDict(), input)
|
||||
}
|
||||
}
|
||||
|
||||
var instanceSnapshotCleanupTaskRunning int32 = 0
|
||||
|
||||
func (manager *SInstanceSnapshotManager) CleanupInstanceSnapshots(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
if instanceSnapshotCleanupTaskRunning > 0 {
|
||||
log.Errorf("Previous CleanupInstanceSnapshots tasks still running !!!")
|
||||
return
|
||||
}
|
||||
instanceSnapshotCleanupTaskRunning = 1
|
||||
defer func() {
|
||||
instanceSnapshotCleanupTaskRunning = 0
|
||||
}()
|
||||
sq := manager.Query().Equals("status", api.INSTANCE_SNAPSHOT_READY).Startswith("name", "auto-").SubQuery()
|
||||
|
||||
iss := []struct {
|
||||
GuestCnt int
|
||||
GuestId string
|
||||
}{}
|
||||
q := sq.Query(
|
||||
sqlchemy.COUNT("guest_cnt", sq.Field("guest_id")),
|
||||
sq.Field("guest_id"),
|
||||
).GroupBy(sq.Field("guest_id"))
|
||||
err := q.All(&iss)
|
||||
if err != nil {
|
||||
log.Errorf("Cleanup instance snapshots job fetch instance snapshot failed %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
guestCount := map[string]int{}
|
||||
for i := range iss {
|
||||
guestCount[iss[i].GuestId] = iss[i].GuestCnt
|
||||
}
|
||||
|
||||
// cleanup retention count instance snapshots
|
||||
{
|
||||
sq = SnapshotPolicyManager.Query().Equals("type", api.SNAPSHOT_POLICY_TYPE_SERVER).GT("retention_count", 0).SubQuery()
|
||||
spr := SnapshotPolicyResourceManager.Query().Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER).SubQuery()
|
||||
q = sq.Query(
|
||||
sq.Field("retention_count"),
|
||||
spr.Field("resource_id").Label("guest_id"),
|
||||
)
|
||||
q = q.Join(spr, sqlchemy.Equals(q.Field("id"), spr.Field("snapshotpolicy_id")))
|
||||
|
||||
guestRetentions := []struct {
|
||||
GuestId string
|
||||
RetentionCount int
|
||||
}{}
|
||||
err = q.All(&guestRetentions)
|
||||
if err != nil {
|
||||
log.Errorf("Cleanup instance snapshots job fetch guest retentions failed %s", err)
|
||||
return
|
||||
}
|
||||
guestRetentionMap := map[string]int{}
|
||||
for i := range guestRetentions {
|
||||
if _, ok := guestRetentionMap[guestRetentions[i].GuestId]; !ok {
|
||||
guestRetentionMap[guestRetentions[i].GuestId] = guestRetentions[i].RetentionCount
|
||||
}
|
||||
// 取最小保留个数
|
||||
if guestRetentionMap[guestRetentions[i].GuestId] > guestRetentions[i].RetentionCount {
|
||||
guestRetentionMap[guestRetentions[i].GuestId] = guestRetentions[i].RetentionCount
|
||||
}
|
||||
}
|
||||
|
||||
for guestId, retentionCnt := range guestRetentionMap {
|
||||
if cnt, ok := guestCount[guestId]; ok && cnt > retentionCnt {
|
||||
manager.startCleanupRetentionCount(ctx, userCred, guestId, cnt-retentionCnt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup retention days instance snapshots
|
||||
{
|
||||
sq = SnapshotPolicyManager.Query().Equals("type", api.SNAPSHOT_POLICY_TYPE_SERVER).GT("retention_days", 0).SubQuery()
|
||||
spr := SnapshotPolicyResourceManager.Query().Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER).SubQuery()
|
||||
q = sq.Query(
|
||||
sq.Field("retention_days"),
|
||||
spr.Field("resource_id").Label("guest_id"),
|
||||
)
|
||||
q = q.Join(spr, sqlchemy.Equals(q.Field("id"), spr.Field("snapshotpolicy_id")))
|
||||
|
||||
guestRetentions := []struct {
|
||||
GuestId string
|
||||
RetentionDays int
|
||||
}{}
|
||||
err = q.All(&guestRetentions)
|
||||
if err != nil {
|
||||
log.Errorf("Cleanup instance snapshots job fetch guest retentions failed %s", err)
|
||||
return
|
||||
}
|
||||
guestRetentionMap := map[string]int{}
|
||||
for i := range guestRetentions {
|
||||
if _, ok := guestRetentionMap[guestRetentions[i].GuestId]; !ok {
|
||||
guestRetentionMap[guestRetentions[i].GuestId] = guestRetentions[i].RetentionDays
|
||||
}
|
||||
// 取最小保留天数
|
||||
if guestRetentionMap[guestRetentions[i].GuestId] > guestRetentions[i].RetentionDays {
|
||||
guestRetentionMap[guestRetentions[i].GuestId] = guestRetentions[i].RetentionDays
|
||||
}
|
||||
}
|
||||
for guestId, retentionDays := range guestRetentionMap {
|
||||
manager.startCleanupRetentionDays(ctx, userCred, guestId, retentionDays)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SInstanceSnapshotManager) startCleanupRetentionCount(ctx context.Context, userCred mcclient.TokenCredential, guestId string, cnt int) error {
|
||||
q := manager.Query().Equals("guest_id", guestId).Equals("status", api.INSTANCE_SNAPSHOT_READY).Startswith("name", "auto-").Asc("created_at").Limit(cnt)
|
||||
vms := []SInstanceSnapshot{}
|
||||
err := db.FetchModelObjects(manager, q, &vms)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchModelObjects")
|
||||
}
|
||||
for i := range vms {
|
||||
vms[i].StartInstanceSnapshotDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SInstanceSnapshotManager) startCleanupRetentionDays(ctx context.Context, userCred mcclient.TokenCredential, guestId string, day int) error {
|
||||
expiredTime := time.Now().AddDate(0, 0, -day)
|
||||
q := manager.Query().Equals("guest_id", guestId).Equals("status", api.INSTANCE_SNAPSHOT_READY).Startswith("name", "auto-").LE("created_at", expiredTime)
|
||||
vms := []SInstanceSnapshot{}
|
||||
err := db.FetchModelObjects(manager, q, &vms)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchModelObjects")
|
||||
}
|
||||
for i := range vms {
|
||||
vms[i].StartInstanceSnapshotDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -437,10 +437,10 @@ func (self *SKafka) SyncWithCloudKafka(ctx context.Context, userCred mcclient.To
|
||||
self.IsMultiAz = ext.IsMultiAz()
|
||||
|
||||
self.BillingType = ext.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
if expiredAt := ext.GetExpiredAt(); !expiredAt.IsZero() {
|
||||
self.ExpiredAt = expiredAt
|
||||
}
|
||||
self.ExpiredAt = ext.GetExpiredAt()
|
||||
self.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
@@ -538,10 +538,10 @@ func (self *SCloudregion) newFromCloudKafka(ctx context.Context, userCred mcclie
|
||||
}
|
||||
|
||||
kafka.BillingType = ext.GetBillingType()
|
||||
kafka.ExpiredAt = time.Time{}
|
||||
kafka.AutoRenew = false
|
||||
if kafka.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
if expired := ext.GetExpiredAt(); !expired.IsZero() {
|
||||
kafka.ExpiredAt = expired
|
||||
}
|
||||
kafka.ExpiredAt = ext.GetExpiredAt()
|
||||
kafka.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/util/rbacscope"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
@@ -230,24 +229,34 @@ func (self *SKeypair) GetLinkedGuestsCount() (int, error) {
|
||||
return GuestManager.Query().Equals("keypair_id", self.Id).CountWithError()
|
||||
}
|
||||
|
||||
func (manager *SKeypairManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.KeypairCreateInput) (api.KeypairCreateInput, error) {
|
||||
func (manager *SKeypairManager) ValidateCreateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
input *api.KeypairCreateInput,
|
||||
) (*api.KeypairCreateInput, error) {
|
||||
input.PublicKey = strings.TrimSpace(input.PublicKey)
|
||||
if len(input.PublicKey) == 0 {
|
||||
if len(input.Scheme) == 0 {
|
||||
input.Scheme = api.KEYPAIRE_SCHEME_RSA
|
||||
}
|
||||
if !utils.IsInStringArray(input.Scheme, api.KEYPAIR_SCHEMAS) {
|
||||
return input, httperrors.NewInputParameterError("Unsupported scheme %s", input.Scheme)
|
||||
}
|
||||
|
||||
var err error
|
||||
if input.Scheme == api.KEYPAIRE_SCHEME_RSA {
|
||||
switch input.Scheme {
|
||||
case api.KEYPAIRE_SCHEME_RSA:
|
||||
input.PrivateKey, input.PublicKey, err = seclib2.GenerateRSASSHKeypair()
|
||||
} else {
|
||||
case api.KEYPAIRE_SCHEME_DSA:
|
||||
input.PrivateKey, input.PublicKey, err = seclib2.GenerateDSASSHKeypair()
|
||||
case api.KEYPAIRE_SCHEME_ECDSA:
|
||||
input.PrivateKey, input.PublicKey, err = seclib2.GenerateECDSASHAP521SSHKeypair()
|
||||
case api.KEYPAIRE_SCHEME_ED25519:
|
||||
input.PrivateKey, input.PublicKey, err = seclib2.GenerateED25519SSHKeypair()
|
||||
default:
|
||||
return nil, httperrors.NewInputParameterError("Unsupported scheme %s", input.Scheme)
|
||||
}
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "Generate%sSSHKeypair", input.Scheme))
|
||||
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "Generate%sSSHKeypair", input.Scheme))
|
||||
}
|
||||
}
|
||||
pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(input.PublicKey))
|
||||
@@ -255,11 +264,7 @@ func (manager *SKeypairManager) ValidateCreateData(ctx context.Context, userCred
|
||||
return input, httperrors.NewInputParameterError("invalid public error: %v", err)
|
||||
}
|
||||
|
||||
// 只允许上传RSA格式密钥。PS: AWS只支持RSA格式。
|
||||
input.Scheme = seclib2.GetPublicKeyScheme(pubKey)
|
||||
if input.Scheme != api.KEYPAIRE_SCHEME_RSA {
|
||||
return input, httperrors.NewInputParameterError("Unsupported scheme %s", input.Scheme)
|
||||
}
|
||||
|
||||
input.Fingerprint = ssh.FingerprintLegacyMD5(pubKey)
|
||||
input.UserResourceCreateInput, err = manager.SUserResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.UserResourceCreateInput)
|
||||
|
||||
@@ -491,10 +491,10 @@ func (self *SCloudregion) newFromCloudModelartsPool(ctx context.Context, userCre
|
||||
pool.CpuArch = sku.CpuArch
|
||||
|
||||
pool.BillingType = ext.GetBillingType()
|
||||
pool.ExpiredAt = time.Time{}
|
||||
pool.AutoRenew = false
|
||||
if pool.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
if expired := ext.GetExpiredAt(); !expired.IsZero() {
|
||||
pool.ExpiredAt = expired
|
||||
}
|
||||
pool.ExpiredAt = ext.GetExpiredAt()
|
||||
pool.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/rbacscope"
|
||||
"yunion.io/x/sqlchemy"
|
||||
@@ -338,32 +337,6 @@ func (self *SMongoDB) SetAutoRenew(autoRenew bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SMongoDB) SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if self.BillingType == "" {
|
||||
self.BillingType = billingType
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
self.ExpiredAt = *expireAt
|
||||
} else {
|
||||
self.BillingCycle = bc.String()
|
||||
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SMongoDB) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
log.Infof("mongodb delete do nothing")
|
||||
return nil
|
||||
@@ -524,6 +497,14 @@ func (self *SMongoDB) SyncWithCloudMongoDB(ctx context.Context, userCred mcclien
|
||||
self.MaxConnections = ext.GetMaxConnections()
|
||||
self.NetworkAddress = ext.GetNetworkAddress()
|
||||
|
||||
self.BillingType = ext.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
self.ExpiredAt = ext.GetExpiredAt()
|
||||
self.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
if vpcId := ext.GetVpcId(); len(vpcId) > 0 {
|
||||
vpc, err := db.FetchByExternalIdAndManagerId(VpcManager, vpcId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
return q.Equals("manager_id", self.ManagerId)
|
||||
@@ -614,11 +595,10 @@ func (self *SCloudregion) newFromCloudMongoDB(ctx context.Context, userCred mccl
|
||||
}
|
||||
|
||||
ins.BillingType = ext.GetBillingType()
|
||||
ins.ExpiredAt = time.Time{}
|
||||
ins.AutoRenew = false
|
||||
if ins.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
expiredAt := ext.GetExpiredAt()
|
||||
if !expiredAt.IsZero() {
|
||||
ins.ExpiredAt = expiredAt
|
||||
}
|
||||
ins.ExpiredAt = ext.GetExpiredAt()
|
||||
ins.AutoRenew = ext.IsAutoRenew()
|
||||
}
|
||||
|
||||
@@ -780,41 +760,23 @@ func (self *SMongoDB) PerformPostpaidExpire(ctx context.Context, userCred mcclie
|
||||
return nil, httperrors.NewBadRequestError("self billing type is %s", self.BillingType)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
releaseAt, err := input.GetReleaseAt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
|
||||
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SMongoDB) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if err := self.CancelExpireTime(ctx, userCred); err != nil {
|
||||
err := SaveReleaseAt(ctx, self, userCred, time.Time{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SMongoDB) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return httperrors.NewBadRequestError("self billing type %s not support cancel expire", self.BillingType)
|
||||
}
|
||||
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
|
||||
MongoDBManager.TableSpec().Name(),
|
||||
), self.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "self cancel expire time")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, "self cancel expire time", userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SMongoDB) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.MongoDBRemoteUpdateInput) (jsonutils.JSONObject, error) {
|
||||
err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "")
|
||||
if err != nil {
|
||||
|
||||
@@ -184,9 +184,10 @@ func (man *SNatGatewayManager) ValidateCreateData(
|
||||
return input, httperrors.NewInputParameterError("unsupported duration %s", input.Duration)
|
||||
}
|
||||
}
|
||||
tm := time.Time{}
|
||||
input.BillingCycle = billingCycle.String()
|
||||
input.ExpiredAt = billingCycle.EndAt(tm)
|
||||
if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
|
||||
input.ReleaseAt = billingCycle.EndAt(time.Now())
|
||||
}
|
||||
}
|
||||
if len(input.Eip) > 0 || input.EipBw > 0 {
|
||||
if len(input.Eip) > 0 {
|
||||
@@ -519,12 +520,11 @@ func (self *SNatGateway) SyncWithCloudNatGateway(ctx context.Context, userCred m
|
||||
}
|
||||
}
|
||||
|
||||
factory, _ := provider.GetProviderFactory()
|
||||
if factory.IsSupportPrepaidResources() {
|
||||
self.BillingType = extNat.GetBillingType()
|
||||
if expired := extNat.GetExpiredAt(); !expired.IsZero() {
|
||||
self.ExpiredAt = expired
|
||||
}
|
||||
self.BillingType = extNat.GetBillingType()
|
||||
self.ExpiredAt = time.Time{}
|
||||
self.AutoRenew = false
|
||||
if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
self.ExpiredAt = extNat.GetExpiredAt()
|
||||
self.AutoRenew = extNat.IsAutoRenew()
|
||||
}
|
||||
|
||||
@@ -564,14 +564,14 @@ func (manager *SNatGatewayManager) newFromCloudNatGateway(ctx context.Context, u
|
||||
nat.ExternalId = extNat.GetGlobalId()
|
||||
nat.IsEmulated = extNat.IsEmulated()
|
||||
|
||||
factory, _ := provider.GetProviderFactory()
|
||||
if factory.IsSupportPrepaidResources() {
|
||||
nat.BillingType = extNat.GetBillingType()
|
||||
if expired := extNat.GetExpiredAt(); !expired.IsZero() {
|
||||
nat.ExpiredAt = expired
|
||||
}
|
||||
nat.BillingType = extNat.GetBillingType()
|
||||
nat.ExpiredAt = time.Time{}
|
||||
nat.AutoRenew = false
|
||||
if nat.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
nat.ExpiredAt = extNat.GetExpiredAt()
|
||||
nat.AutoRenew = extNat.IsAutoRenew()
|
||||
}
|
||||
|
||||
if networId := extNat.GetINetworkId(); len(networId) > 0 {
|
||||
_network, err := db.FetchByExternalIdAndManagerId(NetworkManager, networId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
sq := WireManager.Query("id").Equals("vpc_id", vpc.Id).SubQuery()
|
||||
@@ -890,25 +890,7 @@ func (manager *SNatEntryManager) FetchCustomizeColumns(
|
||||
}
|
||||
|
||||
func (self *SNatGateway) PerformCancelExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
return nil, self.CancelExpireTime(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SNatGateway) CancelExpireTime(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if self.BillingType != billing_api.BILLING_TYPE_POSTPAID {
|
||||
return httperrors.NewBadRequestError("nat billing type %s not support cancel expire", self.BillingType)
|
||||
}
|
||||
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"update %s set expired_at = NULL and billing_cycle = NULL where id = ?",
|
||||
NatGatewayManager.TableSpec().Name(),
|
||||
), self.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "nat cancel expire time")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, "nat cancel expire time", userCred)
|
||||
return nil
|
||||
return nil, SaveReleaseAt(ctx, self, userCred, time.Time{})
|
||||
}
|
||||
|
||||
func (self *SNatGateway) PerformPostpaidExpire(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PostpaidExpireInput) (jsonutils.JSONObject, error) {
|
||||
@@ -916,41 +898,15 @@ func (self *SNatGateway) PerformPostpaidExpire(ctx context.Context, userCred mcc
|
||||
return nil, httperrors.NewBadRequestError("nat gateway billing type is %s", self.BillingType)
|
||||
}
|
||||
|
||||
bc, err := ParseBillingCycleInput(&self.SBillingResourceBase, input)
|
||||
releaseAt, err := input.GetReleaseAt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.SaveRenewInfo(ctx, userCred, bc, nil, billing_api.BILLING_TYPE_POSTPAID)
|
||||
err = SaveReleaseAt(ctx, self, userCred, releaseAt)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SNatGateway) SaveRenewInfo(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
bc *billing.SBillingCycle, expireAt *time.Time, billingType string,
|
||||
) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
if billingType == "" {
|
||||
billingType = billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
if self.BillingType == "" {
|
||||
self.BillingType = billingType
|
||||
}
|
||||
if expireAt != nil && !expireAt.IsZero() {
|
||||
self.ExpiredAt = *expireAt
|
||||
} else {
|
||||
self.BillingCycle = bc.String()
|
||||
self.ExpiredAt = bc.EndAt(self.ExpiredAt)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SNatGateway) PerformRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.RenewInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(self.Status, []string{api.NAT_STAUTS_AVAILABLE}) {
|
||||
return nil, httperrors.NewInvalidStatusError("Cannot do renew nat gateway in status %s required status %s", self.Status, api.NAT_SKU_AVAILABLE)
|
||||
|
||||
@@ -2664,9 +2664,15 @@ func (manager *SNetworkManager) ListItemFilter(
|
||||
ipStart := sqlchemy.INET_ATON(q.Field("guest_ip_start"))
|
||||
ipEnd := sqlchemy.INET_ATON(q.Field("guest_ip_end"))
|
||||
|
||||
ipConst := sqlchemy.INET_ATON(q.StringField(ip4Addr.String()))
|
||||
|
||||
ipCondtion = sqlchemy.AND(
|
||||
sqlchemy.GE(ipEnd, uint32(ip4Addr)),
|
||||
sqlchemy.LE(ipStart, uint32(ip4Addr)),
|
||||
sqlchemy.IsNotNull(q.Field("guest_ip_start")),
|
||||
sqlchemy.IsNotNull(q.Field("guest_ip_end")),
|
||||
sqlchemy.IsNotEmpty(q.Field("guest_ip_start")),
|
||||
sqlchemy.IsNotEmpty(q.Field("guest_ip_end")),
|
||||
sqlchemy.GE(ipEnd, ipConst),
|
||||
sqlchemy.LE(ipStart, ipConst),
|
||||
)
|
||||
if !exactIpMatch {
|
||||
ipCondtion = sqlchemy.OR(
|
||||
@@ -2677,18 +2683,24 @@ func (manager *SNetworkManager) ListItemFilter(
|
||||
}
|
||||
} else if ip6Addr, err := netutils.NewIPV6Addr(ipstr); err == nil {
|
||||
// ipv6 address, exactly
|
||||
ipStart := q.Field("guest_ip6_start")
|
||||
ipEnd := q.Field("guest_ip6_end")
|
||||
ipStart := sqlchemy.INET6_ATON(q.Field("guest_ip6_start"))
|
||||
ipEnd := sqlchemy.INET6_ATON(q.Field("guest_ip6_end"))
|
||||
|
||||
ipConst := sqlchemy.INET6_ATON(q.StringField(ip6Addr.String()))
|
||||
|
||||
ipCondtion = sqlchemy.AND(
|
||||
sqlchemy.GE(ipEnd, ip6Addr.String()),
|
||||
sqlchemy.LE(ipStart, ip6Addr.String()),
|
||||
sqlchemy.IsNotNull(q.Field("guest_ip6_start")),
|
||||
sqlchemy.IsNotNull(q.Field("guest_ip6_end")),
|
||||
sqlchemy.IsNotEmpty(q.Field("guest_ip6_start")),
|
||||
sqlchemy.IsNotEmpty(q.Field("guest_ip6_end")),
|
||||
sqlchemy.GE(ipEnd, ipConst),
|
||||
sqlchemy.LE(ipStart, ipConst),
|
||||
)
|
||||
if !exactIpMatch {
|
||||
ipCondtion = sqlchemy.OR(
|
||||
ipCondtion,
|
||||
sqlchemy.Contains(q.Field("guest_ip6_start"), ipstr),
|
||||
sqlchemy.Contains(q.Field("guest_ip6_end"), ipstr),
|
||||
sqlchemy.Contains(q.Field("guest_ip6_start"), ip6Addr.String()),
|
||||
sqlchemy.Contains(q.Field("guest_ip6_end"), ip6Addr.String()),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -16,7 +16,6 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -236,7 +235,7 @@ type IElasticcacheDriver interface {
|
||||
RequestCreateElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheAccount *SElasticcacheAccount, task taskman.ITask) error
|
||||
RequestCreateElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheAcl *SElasticcacheAcl, task taskman.ITask) error
|
||||
RequestCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheBackup *SElasticcacheBackup, task taskman.ITask) error
|
||||
RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, bc billing.SBillingCycle) (time.Time, error)
|
||||
RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, bc billing.SBillingCycle) error
|
||||
RequestElasticcacheSetAutoRenew(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, autoRenew bool, task taskman.ITask) error
|
||||
RequestRestartElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
|
||||
RequestSyncElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error
|
||||
|
||||
@@ -352,6 +352,7 @@ func (self *SServerSkuManager) ValidateCreateData(ctx context.Context, userCred
|
||||
input.Provider = region.Provider
|
||||
}
|
||||
if input.Provider == api.CLOUD_PROVIDER_ONECLOUD {
|
||||
input.CloudregionId = api.DEFAULT_REGION_ID
|
||||
} else if utils.IsInStringArray(input.Provider, api.PRIVATE_CLOUD_PROVIDERS) {
|
||||
input.Status = api.SkuStatusCreating
|
||||
}
|
||||
|
||||
77
pkg/compute/models/snapshot_policy_resources.go
Normal file
77
pkg/compute/models/snapshot_policy_resources.go
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
)
|
||||
|
||||
type SSnapshotPolicyResourceManager struct {
|
||||
db.SResourceBaseManager
|
||||
}
|
||||
|
||||
var SnapshotPolicyResourceManager *SSnapshotPolicyResourceManager
|
||||
|
||||
func init() {
|
||||
SnapshotPolicyResourceManager = &SSnapshotPolicyResourceManager{
|
||||
SResourceBaseManager: db.NewResourceBaseManager(
|
||||
SSnapshotPolicyResource{},
|
||||
"snapshot_policy_resources_tbl",
|
||||
"snapshot_policy_resource",
|
||||
"snapshot_policy_resources",
|
||||
),
|
||||
}
|
||||
SnapshotPolicyResourceManager.SetVirtualObject(SnapshotPolicyResourceManager)
|
||||
}
|
||||
|
||||
type SSnapshotPolicyResource struct {
|
||||
db.SResourceBase
|
||||
|
||||
SnapshotpolicyId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
ResourceId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
ResourceType string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
}
|
||||
|
||||
func (man *SSnapshotPolicyResourceManager) RemoveByResource(id, typ string) error {
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"delete from %s where resource_id = ? and resource_type = ?",
|
||||
man.TableSpec().Name(),
|
||||
), id, typ,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyResource) GetServer() (*SGuest, error) {
|
||||
guest, err := GuestManager.FetchById(self.ResourceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return guest.(*SGuest), nil
|
||||
}
|
||||
|
||||
func (man *SSnapshotPolicyResourceManager) RemoveBySnapshotpolicy(id string) error {
|
||||
_, err := sqlchemy.GetDB().Exec(
|
||||
fmt.Sprintf(
|
||||
"delete from %s where snapshotpolicy_id = ?",
|
||||
man.TableSpec().Name(),
|
||||
), id,
|
||||
)
|
||||
return err
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user